Statistics
| Revision:

root / org.gvsig.jcrs / libJCRS / src / org / gvsig / crs / ogr / CrsEPSG.java @ 38

History | View | Annotate | Download (18.8 KB)

1
/* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
2
 *
3
 * Copyright (C) 2006 Instituto de Desarrollo Regional and Generalitat Valenciana.
4
 *
5
 * This program is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU General Public License
7
 * as published by the Free Software Foundation; either version 2
8
 * of the License, or (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software
17
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
18
 *
19
 * For more information, contact:
20
 *
21
 *  Generalitat Valenciana
22
 *   Conselleria d'Infraestructures i Transport
23
 *   Av. Blasco Ib??ez, 50
24
 *   46010 VALENCIA
25
 *   SPAIN
26
 *
27
 *      +34 963862235
28
 *   gvsig@gva.es
29
 *      www.gvsig.gva.es
30
 *
31
 *    or
32
 *
33
 *   Instituto de Desarrollo Regional (Universidad de Castilla La-Mancha)
34
 *   Campus Universitario s/n
35
 *   02071 Alabacete
36
 *   Spain
37
 *
38
 *   +34 967 599 200
39
 */
40

    
41
package org.gvsig.crs.ogr;
42

    
43
import java.sql.ResultSet;
44
import java.sql.SQLException;
45

    
46

    
47
import es.idr.teledeteccion.connection.EpsgConnection;
48
import es.idr.teledeteccion.connection.Query;
49

    
50
/**
51
 * Clase que consigue los par?metros necesarios de la base de
52
 * datos de la EPSG una vez escogido un CRS, y que ser?n
53
 * los que se utilicen para la generaci?n de la cadena wkt
54
 * correcta para generar el CRS.
55
 * 
56
 * @author Jos? Luis G?mez Mart?nez (jolugomar@gmail.com)
57
 *
58
 */
59
public class CrsEPSG {
60
        
61
        int epsg_code;
62
        boolean crs_source;
63
        int source_code;
64
        int projection_code;        
65
        int coord_op_code;        
66
        
67
                
68
        int datum_code;
69
        int ellipsoid_code, prime_meridian_code;
70
        
71
        String PROJCS = null;
72
        String GEOGCS = null;
73
        String DATUM = null;
74
        String[] SPHEROID = null;
75
        String[] PRIMEM = null;
76
        String UNIT_A = "degree";
77
        String UNIT_B = "Meter";
78
        double unit_BValue = 1.0;
79
        String PROJECTION = null;
80
        //ArrayList PARAMETER = null;
81
        String[] param_name = null;
82
        String[] param_value = null;
83
        String[] AUTHORITY = null;
84
        EpsgConnection connect;
85
        private int coordSysCode;
86
        
87
        public CrsEPSG(){                
88
        }        
89
        
90
        public CrsEPSG(int code, boolean source_yn, int source_cod, int coord_op_cod, EpsgConnection conn){
91
                epsg_code = code;
92
                crs_source = source_yn;
93
                source_code = source_cod;                
94
                coord_op_code = coord_op_cod;
95
                connect = conn;
96
                SPHEROID = new String[3];
97
                PRIMEM = new String[2];
98
                AUTHORITY = new String[2];
99
                initialize();
100
        }
101
        
102
        public void initialize(){
103
                ResultSet result;
104
                ResultSet result2;
105
                /*
106
                 * Si es base solamente realizamos una consulta, y ya tenemos el Datum
107
                 * (ver en caso de ser fuente que PROJCS no tiene que estar definido)
108
                 */
109
                if (crs_source){
110
                        String sentence = "SELECT coord_ref_sys_name, datum_code, coord_sys_code " +
111
                                                          "FROM epsg_coordinatereferencesystem " +                                      
112
                                                          "WHERE coord_ref_sys_code = " + epsg_code;
113
                        result = Query.select(sentence,connect.getConnection());
114
                        try {
115
                                while (result.next()){
116
                                        GEOGCS = result.getString("coord_ref_sys_name");
117
                                        datum_code = Integer.parseInt(result.getString("datum_code"));
118
                                        coordSysCode = result.getInt("coord_sys_code");
119
                                }
120
                        } catch (SQLException e) {
121
                                e.printStackTrace();
122
                        }                        
123
                }
124
                else{
125
                        String sentence = "SELECT coord_ref_sys_name, coord_sys_code " +
126
                                                          "FROM epsg_coordinatereferencesystem " +                                      
127
                                                          "WHERE coord_ref_sys_code = " + epsg_code;
128
                        result = Query.select(sentence,connect.getConnection());
129
                        
130
                        String sentence2 = "SELECT coord_ref_sys_name, datum_code " +
131
                                                          "FROM epsg_coordinatereferencesystem " +                                      
132
                                                          "WHERE coord_ref_sys_code = " + source_code;
133
                        result2 = Query.select(sentence2,connect.getConnection());
134
                        
135
                        try {
136
                                while (result.next()){
137
                                        PROJCS = result.getString("coord_ref_sys_name");
138
                                        coordSysCode = result.getInt("coord_sys_code");
139
                                }
140
                                while (result2.next()){
141
                                        datum_code = Integer.parseInt(result2.getString("datum_code"));
142
                                        GEOGCS = result2.getString("coord_ref_sys_name");
143
                                }
144
                        } catch (SQLException e) {
145
                                e.printStackTrace();
146
                        }
147
                }
148
                /*
149
                 * hasta aqui hemos rellenado projcs, geocs y tenemos el codigo de datum
150
                 * vamos a obtener los c?digos del elipsoide y el prime_meridian
151
                 */
152
                String sentence = "SELECT datum_name, ellipsoid_code, prime_meridian_code " +
153
                                                  "FROM epsg_datum " +                                      
154
                                                  "WHERE datum_code = " + datum_code;
155
                result = Query.select(sentence,connect.getConnection());
156
                try {
157
                        while (result.next()){
158
                                DATUM = result.getString("datum_name");
159
                                ellipsoid_code = Integer.parseInt(result.getString("ellipsoid_code"));        
160
                                prime_meridian_code = Integer.parseInt(result.getString("prime_meridian_code"));
161
                        }                        
162
                } catch (SQLException e) {
163
                        e.printStackTrace();
164
                }
165
                
166
                /*
167
                 * Ahora vamos a coger varios campos del elipsoide y operaremos con ellos, si la
168
                 * informaci?n de los mismos no esta en las unidades de medida que utilizaremos.
169
                 */
170
                sentence = "SELECT ellipsoid_name, semi_major_axis, inv_flattening, uom_code, " +
171
                                        "semi_minor_axis, ellipsoid_shape " +
172
                                          "FROM epsg_ellipsoid " +                                      
173
                                          "WHERE ellipsoid_code = " + ellipsoid_code;
174
                result = Query.select(sentence,connect.getConnection());
175
                
176
                SPHEROID = getEllipsoid(result);
177
                
178
                sentence = "SELECT prime_meridian_name, greenwich_longitude, uom_code " +
179
                                          "FROM epsg_primemeridian " +                                      
180
                                          "WHERE prime_meridian_code = " + prime_meridian_code;
181
                result = Query.select(sentence,connect.getConnection());
182
                
183
                PRIMEM = getPrimeMeridian(result);
184
                AUTHORITY = getAuthority(epsg_code);
185
                /*
186
                 * si tiene proyecci?n porque es proyectado, la buscamos
187
                 */
188
                if (!crs_source){                        
189
                        sentence = "SELECT coord_op_method_code " +
190
                                                "FROM epsg_coordoperation " +
191
                                                "WHERE coord_op_code = " + coord_op_code;
192
                        result = Query.select(sentence,connect.getConnection());
193
                        try {
194
                                while (result.next()){
195
                                        projection_code = result.getInt("coord_op_method_code");
196
                                }
197
                        } catch (SQLException e) {
198
                                e.printStackTrace();
199
                        }
200
                        
201
                        
202
                        sentence = "SELECT coord_op_method_name " +
203
                                                  "FROM epsg_coordoperationmethod " +                                      
204
                                                  "WHERE coord_op_method_code = " + projection_code;
205
                        result = Query.select(sentence,connect.getConnection());
206
                        try {
207
                                while (result.next()){
208
                                        PROJECTION = result.getString("coord_op_method_name");                                
209
                                }                        
210
                        } catch (SQLException e) {
211
                                e.printStackTrace();
212
                        }
213
                        
214
                        parameters(projection_code);
215
                        setUnit_B(coordSysCode);
216
                }
217
                /*
218
                 * Una vez que tengo todo, hago la llamada al constructor de Epsg2wkt para pasarle los
219
                 * parametros y realizar la cadena
220
                 * CAMBIARLO Y PONER METODOS getXXX para todos los parametros para hacerlo mas generico
221
                         
222
                if (crs_source){
223
                        cadwkt = new Epsg2wkt(0);
224
                }
225
                else{
226
                        cadwkt = new Epsg2wkt();
227
                }
228
                */
229
        }
230
        
231
        /**
232
         * Cuando recuperamos el elipsoide del CRS que hemos seleccionado,
233
         * buscamos sus par?metros, los pasamos a las unidades correctas
234
         * y devolvemos un array de string con el nombre y los valores
235
         * del esferoide.
236
         * @param result
237
         * @return
238
         */
239
        private String[] getEllipsoid(ResultSet result) {
240
                String[] spheroid = new String[3];                
241
                double semi_major_axis = 0;
242
                double semi_minor_axis = 0;
243
                double inv_flattening = 0;
244
                int uom_code = 0;
245
                int ellipsoid_shape = 0;
246
                
247
                try {
248
                        while (result.next()){
249
                                spheroid[0] = result.getString("ellipsoid_name");
250
                                semi_major_axis = result.getDouble("semi_major_axis");
251
                                semi_minor_axis = result.getDouble("semi_minor_axis");
252
                                inv_flattening = result.getDouble("inv_flattening");
253
                                uom_code = result.getInt("uom_code");
254
                                ellipsoid_shape = result.getInt("ellipsoid_shape");
255
                        }                        
256
                } catch (SQLException e) {
257
                        e.printStackTrace();
258
                }
259
                
260
                /*
261
                 * pasaremos a metros las unidades del semi_major_axis, semi_minor_axis
262
                 */
263
                String sentence = "SELECT factor_b, factor_c " +
264
                                                  "FROM epsg_unitofmeasure " +                                      
265
                                                  "WHERE uom_code = " + uom_code;
266
                ResultSet result2 = Query.select(sentence,connect.getConnection());
267
                
268
                double factor_b = 0;
269
                double factor_c = 0;
270
                try{                        
271
                        while (result2.next()){
272
                                factor_b = result2.getDouble("factor_b");
273
                                factor_c = result2.getDouble("factor_c");                                
274
                        }
275
                } catch (SQLException e) {
276
                        e.printStackTrace();
277
                }
278
                if (factor_b != 0 && factor_c != 0 ){
279
                        semi_major_axis = (semi_major_axis * factor_b)/ factor_c;
280
                        if (semi_minor_axis != 0){
281
                                semi_minor_axis = (semi_minor_axis * factor_b) / factor_c;
282
                        }
283
                }
284
                /*
285
                 * calculamos inv_flattening en caso de que sea nulo
286
                 */
287
                if (inv_flattening == 0){
288
                        if (ellipsoid_shape == 0){
289
                                inv_flattening = 0;
290
                        }
291
                        else{
292
                                inv_flattening = (semi_major_axis) / (semi_major_axis - semi_minor_axis);
293
                        }
294
                }                
295
                spheroid[1] = ""+semi_major_axis;
296
                spheroid[2] = ""+inv_flattening;
297
                
298
                return spheroid;
299
        }
300

    
301
        /**
302
         * Este m?todo acepta un result en el que tenemos los par?metros
303
         * del PrimeMeridian, se hace la conversi?n a las unidades correctas
304
         * y se devuelve un array de String con el nombre y los par?metros 
305
         * pertenecientes a PrimeMeridian.
306
         * @param result
307
         * @return
308
         */
309
        private String[] getPrimeMeridian(ResultSet result) {
310
                String[] primem = new String[2];
311
                double greenwich_longitude = 0;
312
                
313
                try {
314
                        while (result.next()){
315
                                primem[0] = result.getString("prime_meridian_name");
316
                                greenwich_longitude = result.getDouble("greenwich_longitude");
317
                                int co= Integer.parseInt((String)result.getString("uom_code"));
318
                                /*
319
                                 * Realizamos este cambio de meridiano origen de la unidad de la epsg
320
                                 * a degrees, para insertarlo en este formato en wkt
321
                                 */
322
                                ResultSet result2 = null;
323
                                if (co != 9110){
324
                                        String sentence = "SELECT factor_b, factor_c " +
325
                                          "FROM epsg_unitofmeasure " +                                      
326
                                          "WHERE uom_code = " + co;
327
                                        result2 = Query.select(sentence,connect.getConnection());
328
                                        
329
                                        while(result.next()){                                                
330
                                                greenwich_longitude = ((greenwich_longitude * result2.getDouble("factor_b") )/ result2.getDouble("factor_c")) * (180.0 / Math.PI);
331
                                        }                                        
332
                                } else {
333
                                        greenwich_longitude = Dms2Deg(greenwich_longitude);
334
                                }
335
                        }
336
                } catch (SQLException e) {
337
                        e.printStackTrace();
338
                }
339
                
340
                primem[1] = ""+greenwich_longitude;
341
                return primem;
342
        }
343
        
344
        /**
345
         * M?todo para bucar los par?metros de la proyecci?n que
346
         * se est? utilizando. Se rellenan las variables param_name y
347
         * param_value con los datos de la proyecci?n utilizada.
348
         * @param proj
349
         */
350
        private void parameters(int proj) {
351
                /*
352
                 * para la consecucion de los parametros se tiene que ir buscando dependiendo de la
353
                 * proyeccion que se utilice, hay que ver que parametros exactos tiene cada uno de ellos
354
                 * y si hay mas de 17, que son los que se utilizan en WKT, como vamos a tratarlos, mensaje
355
                 * de error, intentar no mostrarlos, o simplemente pasar de ellos
356
                 */                
357
                                        
358
                ResultSet result;
359
                ResultSet result2;
360
                ResultSet result3;
361
                
362
                /*
363
                 * Conseguimos la lista de parametros y valores, ordenados segun sort_order de manera
364
                 * ascendente por lo que coincidiram siempre param_name[i] y param_value[i]
365
                 */
366
                String sentence = "SELECT COUNT(*) " +
367
                                "FROM epsg_coordoperationparamusage " +
368
                                "WHERE coord_op_method_code = " + proj;
369
                result = Query.select(sentence,connect.getConnection());
370
                
371
                int count = 0;
372
                try {
373
                        result.next();
374
                        count = result.getInt(1);
375
                } catch (SQLException e1) {
376
                        e1.printStackTrace();
377
                }                
378
                param_name = new String[count];
379
                param_value = new String[count];
380
                
381
                sentence = "SELECT parameter_code " +
382
                "FROM epsg_coordoperationparamusage " +
383
                "WHERE coord_op_method_code = " + proj + " " +
384
                                "ORDER BY sort_order ASC";
385
                result = Query.select(sentence,connect.getConnection());
386
                
387
                int i = 0;
388
                try {
389
                        while (result.next()) {
390
                                
391
                                int cod = result.getInt("parameter_code");
392
                                /*
393
                                 * con el codigo del parametro, obtenemos tanto su nombre como su valor
394
                                 */
395
                                sentence = "SELECT parameter_name " +
396
                                                "FROM epsg_coordoperationparam " +
397
                                                "WHERE parameter_code = " + cod;
398
                                result2 = Query.select(sentence,connect.getConnection());
399
                                
400
                                result2.next();
401
                                param_name[i] = result2.getString("parameter_name");
402
                                
403
                                sentence = "SELECT parameter_value, uom_code " +
404
                                                "FROM epsg_coordoperationparamvalue " +
405
                                                "WHERE parameter_code = " + cod + " AND coord_op_code = " + coord_op_code;
406
                                result3 = Query.select(sentence,connect.getConnection());
407
                                
408
                                result3.next();
409
                                double param_val = result3.getDouble("parameter_value");
410
                                int uom_code = result3.getInt("uom_code");
411
                                
412
                                sentence = "SELECT factor_b, factor_c, unit_of_meas_type " +
413
                                                  "FROM epsg_unitofmeasure " +                                      
414
                                                  "WHERE uom_code = " + uom_code;
415
                                ResultSet result4 = Query.select(sentence,connect.getConnection());
416
                                
417
                                double factor_b = 0;
418
                                double factor_c = 0;                                
419
                                result4.next();
420
                                String type = result4.getString("unit_of_meas_type");
421
                                factor_b = result4.getDouble("factor_b");
422
                                factor_c = result4.getDouble("factor_c");                                
423
                                                                
424
                                if (factor_b != 0 && factor_c != 0 && !type.equals("angle")){
425
                                        param_val = (param_val * factor_b) / factor_c;
426
                                }
427
                                else if(factor_b != 0 && factor_c != 0 && type.equals("angle")){
428
                                        param_val = ((param_val * factor_b) / factor_c) * (180.0 / Math.PI);;
429
                                }else if (uom_code == 9110){
430
                                        param_val = especialDegree(param_val);
431
                                        param_val = Math.toDegrees(param_val);
432
                                }else {
433
                                        System.out.println("C?digo de medida no v?lido...");                                        
434
                                }                                
435
                                param_value[i] = ""+param_val;
436
                                
437
                                i++;
438
                        }
439
                } catch (SQLException e) {
440
                        e.printStackTrace();
441
                }
442
                        
443
        }        
444
        
445
        /**
446
         * M?todo para pasar a las unidades correctas el valor de los distintos
447
         * par?metros de la proyecci?n.
448
         * @param val
449
         * @return
450
         */
451
        private double especialDegree(double val){
452
                if(val==0)
453
                        return val;
454
                int signo = 1;
455
                if (val < 0){
456
                        signo = -1;
457
                        val = Math.abs(val);
458
                }                
459
                String strValue=String.valueOf(val);
460
                int posPto=strValue.indexOf('.');
461
                double grad=Double.parseDouble(strValue.substring(0,posPto));
462
                String strFraction=strValue.substring(posPto+1);
463
                double min=0;
464
                double sec=0;
465
                if(strFraction.length()==1)
466
                {
467
                        min=Double.parseDouble(strFraction);
468
                        min*=10;
469
                }
470
                if(strFraction.length()==2)
471
                {
472
                        min=Double.parseDouble(strFraction);
473
                }
474
                if(strFraction.length()>2)
475
                {
476
                        min=Double.parseDouble(strFraction.substring(0,2));
477
                        sec=Double.parseDouble(strFraction.substring(2));
478
                        if(strFraction.length()==3)
479
                                sec*=10;
480
                        if(strFraction.length()>4){
481
                                for(int i=0;i<strFraction.length()-4;i++)
482
                                        sec=sec/10.0;
483
                        }
484
                        
485
                }
486
                                
487
                val = ((grad + (min/60.0) + (sec/3600.0)) * (Math.PI/180.0)) * signo;
488
                
489
                return val;
490
        }        
491
        
492
        /**
493
         * M?todo para pasar a las unidades correctas el valor del prime meridian.
494
         * @param val
495
         * @return
496
         */
497
        private double Dms2Deg(double val){
498
                if(val==0)
499
                        return val;
500
                int signo = 1;
501
                if (val < 0){
502
                        signo = -1;
503
                        val = Math.abs(val);
504
                }                
505
                String strValue=String.valueOf(val);
506
                int posPto=strValue.indexOf('.');
507
                double grad=Double.parseDouble(strValue.substring(0,posPto));
508
                String strFraction=strValue.substring(posPto+1);
509
                double min=0;
510
                double sec=0;
511
                if(strFraction.length()==1)
512
                {
513
                        min=Double.parseDouble(strFraction);
514
                        min*=10;
515
                }
516
                if(strFraction.length()==2)
517
                {
518
                        min=Double.parseDouble(strFraction);
519
                }
520
                if(strFraction.length()>2)
521
                {
522
                        min=Double.parseDouble(strFraction.substring(0,2));
523
                        sec=Double.parseDouble(strFraction.substring(2));
524
                        if(strFraction.length()==3)
525
                                sec*=10;
526
                        if(strFraction.length()>4){
527
                                for(int i=0;i<strFraction.length()-4;i++)
528
                                        sec=sec/10.0;
529
                        }
530
                        
531
                }        
532
        
533
                val = ((grad + (min/60.0) + (sec/3600.0)) ) * signo;
534
                
535
                return val;
536
        }        
537
        
538
        /**
539
         * Genera el authority del CRS
540
         * @param epsg_cod
541
         * @return
542
         */        
543
        private String[] getAuthority(int epsg_cod) {
544
                String[] aut = new String[2];
545
                aut[0] = "EPSG";
546
                aut[1] = ""+epsg_cod;
547
                return aut;
548
        }
549
        
550
        public String getPROJCS(){
551
                return PROJCS;
552
        }
553
        
554
        public String getGEOGCS(){
555
                return GEOGCS;
556
        }
557
        
558
        public String getDATUM(){
559
                return DATUM;
560
        }
561
        
562
        public String[] getSPHEROID(){
563
                return SPHEROID;
564
        }
565
        
566
        public String[] getPRIMEM(){
567
                return PRIMEM;
568
        }
569
        
570
        public void setUnit_B(int code) {
571
                int uom = 0;
572
                String sentence = "SELECT uom_code " +
573
                                                "FROM epsg_coordinateaxis " +
574
                                                "WHERE coord_sys_code = " + code;
575
                
576
                ResultSet result = Query.select(sentence,connect.getConnection());
577
                /**
578
                 * Recuperar el nombre de la unidad para poder ponerlo en la cadena
579
                 * wkt
580
                 */
581
                try {
582
                        if (result.next()) {
583
                                uom = result.getInt("uom_code");
584
                        }
585
                } catch (SQLException e) {
586
                        // TODO Auto-generated catch block
587
                        e.printStackTrace();
588
                }
589
                
590
                sentence = "SELECT unit_of_meas_name " +
591
                "FROM epsg_unitofmeasure " +
592
                "WHERE uom_code = " + uom;
593
                
594
                result = Query.select(sentence,connect.getConnection());
595
                
596
                try {
597
                        if (result.next()) {
598
                                UNIT_B = result.getString("unit_of_meas_name");
599
                        }
600
                } catch (SQLException e) {
601
                        // TODO Auto-generated catch block
602
                        e.printStackTrace();
603
                }
604
                setUnit_BValue(uom);
605
        }
606
        
607
        private void setUnit_BValue(int uom) {
608
                if (uom != 9001) {
609
                        double factor_b =0.0;
610
                        double factor_c = 0.0;
611
                        String sentence = "SELECT factor_b, factor_c " +
612
                        "FROM epsg_unitofmeasure " +
613
                        "WHERE uom_code = " + uom;
614
                        
615
                        ResultSet result = Query.select(sentence,connect.getConnection());
616
                        try {
617
                                if (result.next()) {
618
                                        factor_b = result.getDouble("factor_b");
619
                                        factor_c = result.getDouble("factor_c");
620
                                }
621
                        } catch (SQLException e) {
622
                                // TODO Auto-generated catch block
623
                                e.printStackTrace();
624
                        }
625
                        unit_BValue = (unit_BValue * factor_b) / factor_c;
626
                        if (uom != 9002) {
627
                                UNIT_B = "[m*"+unit_BValue+"]";                                 
628
                        } else
629
                                UNIT_B = "ft";
630
                }
631
        }
632
                
633
        public String getUNIT_A(){
634
                return UNIT_A;
635
        }
636
        
637
        public String getPROJECTION(){
638
                return PROJECTION;
639
        }
640
        
641
        public String[] getParam_name(){
642
                return param_name;
643
        }
644
        
645
        public String[] getParam_value(){
646
                return param_value;
647
        }
648
        
649
        public String getUNIT_B(){
650
                return UNIT_B;
651
        }        
652
        
653
        public String getUnit_BValue() {
654
                return ""+unit_BValue;
655
        }
656
        
657
        public String[] getAUTHORITY(){
658
                return AUTHORITY;
659
        }
660
}