1
2 ///////////////////////////////////////////////////////////
3 // //
4 // SAGA //
5 // //
6 // System for Automated Geoscientific Analyses //
7 // //
8 // Application Programming Interface //
9 // //
10 // Library: SAGA_API //
11 // //
12 //-------------------------------------------------------//
13 // //
14 // projections.cpp //
15 // //
16 // Copyright (C) 2009 by Olaf Conrad //
17 // //
18 //-------------------------------------------------------//
19 // //
20 // This file is part of 'SAGA - System for Automated //
21 // Geoscientific Analyses'. //
22 // //
23 // This library is free software; you can redistribute //
24 // it and/or modify it under the terms of the GNU Lesser //
25 // General Public License as published by the Free //
26 // Software Foundation, either version 2.1 of the //
27 // License, or (at your option) any later version. //
28 // //
29 // This library is distributed in the hope that it will //
30 // be useful, but WITHOUT ANY WARRANTY; without even the //
31 // implied warranty of MERCHANTABILITY or FITNESS FOR A //
32 // PARTICULAR PURPOSE. See the GNU Lesser General Public //
33 // License for more details. //
34 // //
35 // You should have received a copy of the GNU Lesser //
36 // General Public License along with this program; if //
37 // not, see <http://www.gnu.org/licenses/>. //
38 // //
39 //-------------------------------------------------------//
40 // //
41 // contact: Olaf Conrad //
42 // Institute of Geography //
43 // University of Hamburg //
44 // Germany //
45 // //
46 // e-mail: oconrad@saga-gis.org //
47 // //
48 ///////////////////////////////////////////////////////////
49
50 //---------------------------------------------------------
51 #include "geo_tools.h"
52
53 #include "table.h"
54
55
56 ///////////////////////////////////////////////////////////
57 // //
58 // //
59 // //
60 ///////////////////////////////////////////////////////////
61
62 //---------------------------------------------------------
63 CSG_Projections gSG_Projections;
64
65 //---------------------------------------------------------
SG_Get_Projections(void)66 CSG_Projections & SG_Get_Projections(void)
67 {
68 return( gSG_Projections );
69 }
70
71
72 ///////////////////////////////////////////////////////////
73 // //
74 ///////////////////////////////////////////////////////////
75
76 //---------------------------------------------------------
SG_Get_Projection_Type(const CSG_String & Identifier)77 TSG_Projection_Type SG_Get_Projection_Type (const CSG_String &Identifier)
78 {
79 if( !Identifier.CmpNoCase("PROJCS") ) return( SG_PROJ_TYPE_CS_Projected );
80 if( !Identifier.CmpNoCase("GEOGCS") ) return( SG_PROJ_TYPE_CS_Geographic );
81 if( !Identifier.CmpNoCase("GEOCCS") ) return( SG_PROJ_TYPE_CS_Geocentric );
82
83 return( SG_PROJ_TYPE_CS_Undefined );
84 }
85
86 //---------------------------------------------------------
SG_Get_Projection_Type_Identifier(TSG_Projection_Type Type)87 CSG_String SG_Get_Projection_Type_Identifier (TSG_Projection_Type Type)
88 {
89 switch( Type )
90 {
91 case SG_PROJ_TYPE_CS_Projected : return( "PROJCS" );
92 case SG_PROJ_TYPE_CS_Geographic: return( "GEOGCS" );
93 case SG_PROJ_TYPE_CS_Geocentric: return( "GEOCCS" );
94 default : return( "UNDEFINED" );
95 }
96 }
97
98 //---------------------------------------------------------
SG_Get_Projection_Type_Name(TSG_Projection_Type Type)99 CSG_String SG_Get_Projection_Type_Name (TSG_Projection_Type Type)
100 {
101 switch( Type )
102 {
103 case SG_PROJ_TYPE_CS_Projected : return( _TL("Projected Coordinate System" ) );
104 case SG_PROJ_TYPE_CS_Geographic: return( _TL("Geographic Coordinate System") );
105 case SG_PROJ_TYPE_CS_Geocentric: return( _TL("Geocentric Coordinate System") );
106 default : return( _TL("Undefined Coordinate System" ) );
107 }
108 }
109
110
111 ///////////////////////////////////////////////////////////
112 // //
113 ///////////////////////////////////////////////////////////
114
115 //---------------------------------------------------------
116 const char SG_Projection_Units[SG_PROJ_UNIT_Undefined + 1][3][32] =
117 {
118 { "km" , "Kilometers" , "Kilometer" },
119 { "m" , "Meters" , "Meter" },
120 { "dm" , "Decimeters" , "Decimeter" },
121 { "cm" , "Centimeters", "Centimeter" },
122 { "mm" , "Millimeters", "Millimeter" },
123 { "kmi" , "Miles" , "International Nautical Mile" },
124 { "in" , "Inches" , "International Inch" },
125 { "ft" , "Feet" , "International Foot" },
126 { "yd" , "Yards" , "International Yard" },
127 { "mi" , "Miles" , "International Statute Mile" },
128 { "fath" , "Fathoms" , "International Fathom" },
129 { "ch" , "Chains" , "International Chain" },
130 { "link" , "Links" , "International Link" },
131 { "us-in" , "Inches" , "U.S. Surveyor's Inch" },
132 { "us-ft" , "Feet" , "U.S. Surveyor's Foot" },
133 { "us-yd" , "Yards" , "U.S. Surveyor's Yard" },
134 { "us-ch" , "Chains" , "U.S. Surveyor's Chain" },
135 { "us-mi" , "Miles" , "U.S. Surveyor's Statute Mile" },
136 { "ind-yd", "Yards" , "Indian Yard" },
137 { "ind-ft", "Feet" , "Indian Foot" },
138 { "ind-ch", "Chains" , "Indian Chain" },
139 { "" , "" , "" }
140 };
141
142 //---------------------------------------------------------
143 // same as proj4.
SG_Get_Projection_Unit(const CSG_String & Identifier)144 TSG_Projection_Unit SG_Get_Projection_Unit (const CSG_String &Identifier)
145 {
146 for(int i=0; i<SG_PROJ_UNIT_Undefined; i++)
147 {
148 if( !Identifier.CmpNoCase(SG_Projection_Units[i][0])
149 || !Identifier.CmpNoCase(SG_Projection_Units[i][2]) )
150 {
151 return( (TSG_Projection_Unit)i );
152 }
153 }
154
155 return( !Identifier.CmpNoCase("metre") ? SG_PROJ_UNIT_Meter : SG_PROJ_UNIT_Undefined );
156 }
157
158 //---------------------------------------------------------
159 // same as proj4.
SG_Get_Projection_Unit_Identifier(TSG_Projection_Unit Unit)160 CSG_String SG_Get_Projection_Unit_Identifier (TSG_Projection_Unit Unit)
161 {
162 if( Unit < 0 || Unit > SG_PROJ_UNIT_Undefined )
163 Unit = SG_PROJ_UNIT_Undefined;
164
165 return( SG_Projection_Units[Unit][0] );
166 }
167
168 //---------------------------------------------------------
SG_Get_Projection_Unit_Name(TSG_Projection_Unit Unit,bool bSimple)169 CSG_String SG_Get_Projection_Unit_Name (TSG_Projection_Unit Unit, bool bSimple)
170 {
171 if( Unit < 0 || Unit > SG_PROJ_UNIT_Undefined )
172 Unit = SG_PROJ_UNIT_Undefined;
173
174 return( SG_Projection_Units[Unit][bSimple ? 1 : 2] );
175 }
176
177 //---------------------------------------------------------
SG_Get_Projection_Unit_To_Meter(TSG_Projection_Unit Unit)178 double SG_Get_Projection_Unit_To_Meter (TSG_Projection_Unit Unit)
179 {
180 switch( Unit )
181 {
182 case SG_PROJ_UNIT_Kilometer : return( 1000. );
183 case SG_PROJ_UNIT_Meter : return( 1. );
184 case SG_PROJ_UNIT_Decimeter : return( 0.1 );
185 case SG_PROJ_UNIT_Centimeter : return( 0.01 );
186 case SG_PROJ_UNIT_Millimeter : return( 0.001 );
187 case SG_PROJ_UNIT_Int_Nautical_Mile: return( 1852. );
188 case SG_PROJ_UNIT_Int_Inch : return( 0.0254 );
189 case SG_PROJ_UNIT_Int_Foot : return( 0.3048 );
190 case SG_PROJ_UNIT_Int_Yard : return( 0.9144 );
191 case SG_PROJ_UNIT_Int_Statute_Mile : return( 1609.344 );
192 case SG_PROJ_UNIT_Int_Fathom : return( 1.8288 );
193 case SG_PROJ_UNIT_Int_Chain : return( 20.1168 );
194 case SG_PROJ_UNIT_Int_Link : return( 0.201168 );
195 case SG_PROJ_UNIT_US_Inch : return( 1. / 39.37 );
196 case SG_PROJ_UNIT_US_Foot : return( 0.304800609601219 );
197 case SG_PROJ_UNIT_US_Yard : return( 0.914401828803658 );
198 case SG_PROJ_UNIT_US_Chain : return( 20.11684023368047 );
199 case SG_PROJ_UNIT_US_Statute_Mile : return( 1609.347218694437 );
200 case SG_PROJ_UNIT_Indian_Yard : return( 0.91439523 );
201 case SG_PROJ_UNIT_Indian_Foot : return( 0.30479841 );
202 case SG_PROJ_UNIT_Indian_Chain : return( 20.11669506 );
203 default : return( 1. );
204 }
205 }
206
207 //---------------------------------------------------------
SG_Set_Projection_Unit(const CSG_MetaData & m,TSG_Projection_Unit & Unit,CSG_String & Name,double & To_Meter)208 bool SG_Set_Projection_Unit (const CSG_MetaData &m, TSG_Projection_Unit &Unit, CSG_String &Name, double &To_Meter)
209 {
210 if( m("UNIT") )
211 {
212 if( m["UNIT"].Get_Property("name", Name) && (Unit = SG_Get_Projection_Unit(Name)) != SG_PROJ_UNIT_Undefined )
213 {
214 Name = SG_Get_Projection_Unit_Name (Unit);
215 To_Meter = SG_Get_Projection_Unit_To_Meter(Unit);
216 }
217 else if( !m["UNIT"].Get_Content().asDouble(To_Meter) || To_Meter <= 0. )
218 {
219 To_Meter = 1.;
220 }
221
222 return( true );
223 }
224
225 return( false );
226 }
227
228
229 ///////////////////////////////////////////////////////////
230 // //
231 // //
232 // //
233 ///////////////////////////////////////////////////////////
234
235 //---------------------------------------------------------
CSG_Projection(void)236 CSG_Projection::CSG_Projection(void)
237 {
238 Destroy();
239 }
240
~CSG_Projection(void)241 CSG_Projection::~CSG_Projection(void)
242 {}
243
244 //---------------------------------------------------------
CSG_Projection(const CSG_Projection & Projection)245 CSG_Projection::CSG_Projection(const CSG_Projection &Projection)
246 {
247 Destroy();
248
249 Create(Projection);
250 }
251
Create(const CSG_Projection & Projection)252 bool CSG_Projection::Create(const CSG_Projection &Projection)
253 {
254 return( Assign(Projection) );
255 }
256
Assign(const CSG_Projection & Projection)257 bool CSG_Projection::Assign(const CSG_Projection &Projection)
258 {
259 m_Name = Projection.m_Name;
260 m_Type = Projection.m_Type;
261 m_Unit = Projection.m_Unit;
262 m_Unit_To_Meter = Projection.m_Unit_To_Meter;
263 m_Unit_Name = Projection.m_Unit_Name;
264 m_WKT = Projection.m_WKT;
265 m_Proj4 = Projection.m_Proj4;
266 m_Authority = Projection.m_Authority;
267 m_Authority_ID = Projection.m_Authority_ID;
268
269 return( true );
270 }
271
272 //---------------------------------------------------------
CSG_Projection(int Authority_ID,const SG_Char * Authority)273 CSG_Projection::CSG_Projection(int Authority_ID, const SG_Char *Authority)
274 {
275 Destroy();
276
277 Create(Authority_ID, Authority);
278 }
279
Create(int Authority_ID,const SG_Char * Authority)280 bool CSG_Projection::Create(int Authority_ID, const SG_Char *Authority)
281 {
282 return( Assign(Authority_ID, Authority) );
283 }
284
Assign(int Authority_ID,const SG_Char * Authority)285 bool CSG_Projection::Assign(int Authority_ID, const SG_Char *Authority)
286 {
287 return( Authority && *Authority
288 ? gSG_Projections.Get_Projection(*this, Authority, Authority_ID)
289 : gSG_Projections.Get_Projection(*this, Authority_ID)
290 );
291 }
292
293 //---------------------------------------------------------
CSG_Projection(const CSG_String & Projection,TSG_Projection_Format Format)294 CSG_Projection::CSG_Projection(const CSG_String &Projection, TSG_Projection_Format Format)
295 {
296 Create(Projection, Format);
297 }
298
Create(const CSG_String & Projection,TSG_Projection_Format Format)299 bool CSG_Projection::Create(const CSG_String &Projection, TSG_Projection_Format Format)
300 {
301 return( Assign(Projection, Format) );
302 }
303
Assign(const CSG_String & Projection,TSG_Projection_Format Format)304 bool CSG_Projection::Assign(const CSG_String &Projection, TSG_Projection_Format Format)
305 {
306 Destroy();
307
308 if( Projection.is_Empty() )
309 {
310 return( false );
311 }
312
313 //-----------------------------------------------------
314 int i;
315 CSG_String s;
316 CSG_MetaData m;
317
318 switch( Format )
319 {
320 default:
321 return( false );
322
323 //-----------------------------------------------------
324 case SG_PROJ_FMT_EPSG:
325 return( Projection.asInt(i) && Assign(i, SG_T("EPSG")) );
326
327 //-----------------------------------------------------
328 case SG_PROJ_FMT_Proj4:
329 if( !gSG_Projections.WKT_from_Proj4(s, Projection) )
330 {
331 return( false );
332 }
333
334 m_WKT = s;
335 m_Proj4 = Projection;
336
337 m = gSG_Projections.WKT_to_MetaData(m_WKT);
338
339 break;
340
341 //-----------------------------------------------------
342 case SG_PROJ_FMT_WKT:
343 m = gSG_Projections.WKT_to_MetaData(Projection);
344
345 if( m.Get_Property("authority_name", s) && s.CmpNoCase("EPSG") == 0
346 && m.Get_Property("authority_code", i) && gSG_Projections.Get_Projection(*this, i) )
347 {
348 return( true );
349 }
350
351 if( gSG_Projections.WKT_to_Proj4(s, Projection) )
352 {
353 m_Proj4 = s;
354 }
355
356 m_WKT = Projection;
357
358 break;
359 }
360
361 //-----------------------------------------------------
362 m_Name = m.Get_Property("name");
363 m_Type = SG_Get_Projection_Type(m.Get_Name());
364
365 SG_Set_Projection_Unit(m, m_Unit, m_Unit_Name, m_Unit_To_Meter);
366
367 return( true );
368 }
369
370 //---------------------------------------------------------
CSG_Projection(const CSG_String & WKT,const CSG_String & Proj4)371 CSG_Projection::CSG_Projection(const CSG_String &WKT, const CSG_String &Proj4)
372 {
373 Create(WKT, Proj4);
374 }
375
Create(const CSG_String & WKT,const CSG_String & Proj4)376 bool CSG_Projection::Create(const CSG_String &WKT, const CSG_String &Proj4)
377 {
378 return( Assign(WKT, Proj4) );
379 }
380
Assign(const CSG_String & WKT,const CSG_String & Proj4)381 bool CSG_Projection::Assign(const CSG_String &WKT, const CSG_String &Proj4)
382 {
383 if( Assign(WKT) )
384 {
385 m_Proj4 = Proj4;
386
387 return( true );
388 }
389
390 return( false );
391 }
392
393 //---------------------------------------------------------
Destroy(void)394 void CSG_Projection::Destroy(void)
395 {
396 m_Name = _TL("undefined");
397 m_Type = SG_PROJ_TYPE_CS_Undefined;
398 m_Unit = SG_PROJ_UNIT_Undefined;
399 m_Unit_To_Meter = 1.;
400 m_Unit_Name .Clear();
401 m_WKT .Clear();
402 m_Proj4 .Clear();
403 m_Authority .Clear();
404 m_Authority_ID = -1;
405 }
406
407
408 ///////////////////////////////////////////////////////////
409 // //
410 ///////////////////////////////////////////////////////////
411
412 //---------------------------------------------------------
Load(const CSG_String & FileName,TSG_Projection_Format Format)413 bool CSG_Projection::Load(const CSG_String &FileName, TSG_Projection_Format Format)
414 {
415 CSG_File Stream(FileName, SG_FILE_R, false);
416
417 return( Load(Stream, Format) );
418 }
419
420 //---------------------------------------------------------
Save(const CSG_String & FileName,TSG_Projection_Format Format) const421 bool CSG_Projection::Save(const CSG_String &FileName, TSG_Projection_Format Format) const
422 {
423 CSG_File Stream(FileName, SG_FILE_W, false);
424
425 return( is_Okay() && Save(Stream, Format) );
426 }
427
428 //---------------------------------------------------------
Load(CSG_File & Stream,TSG_Projection_Format Format)429 bool CSG_Projection::Load(CSG_File &Stream, TSG_Projection_Format Format)
430 {
431 if( Stream.is_Reading() )
432 {
433 CSG_String s;
434
435 Stream.Read(s, (size_t)Stream.Length());
436
437 return( Assign(s, Format) );
438 }
439
440 return( false );
441 }
442
443 //---------------------------------------------------------
Save(CSG_File & Stream,TSG_Projection_Format Format) const444 bool CSG_Projection::Save(CSG_File &Stream, TSG_Projection_Format Format) const
445 {
446 if( is_Okay() && Stream.is_Writing() )
447 {
448 switch( Format )
449 {
450 case SG_PROJ_FMT_WKT: default:
451 return( Stream.Write(m_WKT ) == m_WKT .Length() );
452
453 case SG_PROJ_FMT_Proj4:
454 return( Stream.Write(m_Proj4) == m_Proj4.Length() );
455 }
456 }
457
458 return( false );
459 }
460
461 //---------------------------------------------------------
Load(const CSG_MetaData & Projection)462 bool CSG_Projection::Load(const CSG_MetaData &Projection)
463 {
464 CSG_MetaData *pEntry;
465
466 if( (pEntry = Projection.Get_Child("OGC_WKT")) != NULL )
467 {
468 Assign(pEntry->Get_Content(), SG_PROJ_FMT_WKT);
469
470 if( (pEntry = Projection.Get_Child("PROJ4")) != NULL )
471 {
472 m_Proj4 = pEntry->Get_Content();
473 }
474
475 return( true );
476 }
477
478 return( false );
479 }
480
481 //---------------------------------------------------------
Save(CSG_MetaData & Projection) const482 bool CSG_Projection::Save(CSG_MetaData &Projection) const
483 {
484 Projection.Del_Children();
485
486 Projection.Add_Child("OGC_WKT", m_WKT );
487 Projection.Add_Child("PROJ4" , m_Proj4 );
488 Projection.Add_Child("EPSG" , Get_EPSG() );
489
490 return( true );
491 }
492
493
494 ///////////////////////////////////////////////////////////
495 // //
496 ///////////////////////////////////////////////////////////
497
498 //---------------------------------------------------------
499 #define WKT_GCS_WGS84 "GEOGCS[\"WGS 84\",AUTHORITY[\"EPSG\",\"4326\"]],"\
500 "DATUM[\"WGS_1984\",AUTHORITY[\"EPSG\",\"6326\"]],"\
501 "SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],"\
502 "PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],"\
503 "UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]]"
504
505 //---------------------------------------------------------
506 #define PROJ4_GCS_WGS84 "+proj=longlat +datum=WGS84 +no_defs"
507
508 //---------------------------------------------------------
Set_GCS_WGS84(void)509 bool CSG_Projection::Set_GCS_WGS84(void)
510 {
511 return( Create(WKT_GCS_WGS84, PROJ4_GCS_WGS84) );
512 }
513
514 //---------------------------------------------------------
Set_UTM_WGS84(int Zone,bool bSouth)515 bool CSG_Projection::Set_UTM_WGS84(int Zone, bool bSouth)
516 {
517 if( Zone < 1 || Zone > 60 )
518 {
519 return( false );
520 }
521
522 //-----------------------------------------------------
523 int EPSG_ID = (bSouth ? 32700 : 32600) + Zone;
524
525 if( Create(EPSG_ID) )
526 {
527 return( true );
528 }
529
530 //-----------------------------------------------------
531 CSG_String WKT, Proj4;
532
533 WKT.Printf("PROJCS[\"WGS 84 / UTM zone %d%c\",%s" // Zone, N/S, Datum
534 "PROJECTION[\"Transverse_Mercator\"],AUTHORITY[\"EPSG\",\"%d\"]]" // EPSG ID
535 "PARAMETER[\"latitude_of_origin\",0],"
536 "PARAMETER[\"central_meridian\",%d]," // Central Meridian
537 "PARAMETER[\"scale_factor\",0.9996],"
538 "PARAMETER[\"false_easting\",500000],"
539 "PARAMETER[\"false_northing\",%d]," // False Northing
540 "AXIS[\"Easting\",EAST],"
541 "AXIS[\"Northing\",NORTH],"
542 "UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]]",
543 Zone, bSouth ? 'S' : 'N', CSG_String(WKT_GCS_WGS84).c_str(), EPSG_ID, 6 * (Zone - 1) - 177, bSouth ? 10000000 : 0
544 );
545
546 Proj4.Printf("+proj=utm +zone=%d%s +datum=WGS84 +units=m +no_defs", Zone, bSouth ? SG_T(" +south") : SG_T(""));
547
548 return( Create(WKT, Proj4) );
549 }
550
551
552 ///////////////////////////////////////////////////////////
553 // //
554 ///////////////////////////////////////////////////////////
555
556 //---------------------------------------------------------
is_Equal(const CSG_Projection & Projection) const557 bool CSG_Projection::is_Equal(const CSG_Projection &Projection) const
558 {
559 if( is_Okay() != Projection.is_Okay() )
560 {
561 return( false );
562 }
563
564 if( !is_Okay() ) // both are not valid
565 {
566 return( true );
567 }
568
569 if( !m_Authority.is_Empty() && !Projection.m_Authority.is_Empty() )
570 {
571 return( m_Authority.CmpNoCase(Projection.m_Authority) == 0 && m_Authority_ID == Projection.m_Authority_ID );
572 }
573
574 if( m_Proj4.CmpNoCase(Projection.m_Proj4) == 0 ) // the simple case...
575 {
576 return( true );
577 }
578
579 //-----------------------------------------------------
580 CSG_Table parms[2]; // okay, let's perform a more detailed check...
581
582 for(int i=0; i<2; i++)
583 {
584 parms[i].Add_Field("key", SG_DATATYPE_String);
585 parms[i].Add_Field("val", SG_DATATYPE_String);
586
587 CSG_Strings s = SG_String_Tokenize(i == 0 ? m_Proj4 : Projection.m_Proj4, "+");
588
589 for(int j=0, k=0; j<s.Get_Count(); j++)
590 {
591 CSG_String key = s[j].BeforeFirst('='); key.Trim(false); key.Trim(true); key.Make_Lower();
592 CSG_String val = s[j].AfterFirst ('='); val.Trim(false); val.Trim(true); val.Make_Lower();
593
594 if( !key.is_Empty() && key.Cmp("no_defs") && parms[i].Add_Record() )
595 {
596 parms[i][k][0] = key;
597 parms[i][k][1] = val;
598
599 k++;
600 }
601 }
602 }
603
604 if( parms[0].Get_Count() != parms[1].Get_Count() ) // should be the same...
605 {
606 return( false );
607 }
608
609 parms[0].Set_Index(0, TABLE_INDEX_Ascending); // sort by key...
610 parms[1].Set_Index(0, TABLE_INDEX_Ascending);
611
612 for(int j=0; j<parms[0].Get_Count(); j++)
613 {
614 if( SG_STR_CMP(parms[0][j].asString(0), parms[1][j].asString(0)) ) // does the key match ?
615 {
616 return( false );
617 }
618
619 if( SG_STR_CMP(parms[0][j].asString(1), parms[1][j].asString(1)) ) // doe the value string match ?
620 {
621 double d[2];
622
623 if( !CSG_String(parms[0][j].asString(1)).asDouble(d[0]) // does the numerical value representation match ?
624 || !CSG_String(parms[1][j].asString(1)).asDouble(d[1]) || d[0] != d[1] )
625 {
626 return( false );
627 }
628 }
629 }
630
631 return( true );
632 }
633
634
635 ///////////////////////////////////////////////////////////
636 // //
637 ///////////////////////////////////////////////////////////
638
639 //---------------------------------------------------------
Get_Description(void) const640 CSG_String CSG_Projection::Get_Description(void) const
641 {
642 CSG_String s;
643
644 s = SG_Get_Projection_Type_Name(m_Type);
645
646 if( is_Okay() )
647 {
648 if( m_Authority.Length() > 0 && m_Authority_ID > 0 )
649 {
650 s += CSG_String::Format(" [%s %d]", m_Authority.c_str(), m_Authority_ID);
651 }
652
653 s += ":\n" + m_Name;
654
655 if( m_Proj4.Length() > 0 )
656 {
657 s += "\n[" + m_Proj4 + "]";
658 }
659 }
660
661 return( s );
662 }
663
664
665 ///////////////////////////////////////////////////////////
666 // //
667 // //
668 // //
669 ///////////////////////////////////////////////////////////
670
671 //---------------------------------------------------------
672 enum ESG_PROJ_FIELD_ID
673 {
674 PRJ_FIELD_SRID = 0,
675 PRJ_FIELD_AUTH_NAME,
676 PRJ_FIELD_AUTH_SRID,
677 PRJ_FIELD_SRTEXT,
678 PRJ_FIELD_PROJ4TEXT
679 };
680
681
682 ///////////////////////////////////////////////////////////
683 // //
684 ///////////////////////////////////////////////////////////
685
686 //---------------------------------------------------------
CSG_Projections(void)687 CSG_Projections::CSG_Projections(void)
688 {
689 _On_Construction();
690 }
691
692 //---------------------------------------------------------
CSG_Projections(bool bLoadDefaults)693 CSG_Projections::CSG_Projections(bool bLoadDefaults)
694 {
695 _On_Construction();
696
697 Create(bLoadDefaults);
698 }
699
Create(bool bLoadDefaults)700 bool CSG_Projections::Create(bool bLoadDefaults)
701 {
702 Destroy();
703
704 if( bLoadDefaults ) // load spatial reference system database and dictionary
705 {
706 #if defined(_SAGA_LINUX)
707 CSG_String Path_Shared = SHARE_PATH;
708 #else
709 CSG_String Path_Shared = SG_UI_Get_Application_Path(true);
710 #endif
711
712 SG_UI_Msg_Lock(true);
713
714 Load_Dictionary(SG_File_Make_Path(Path_Shared, "saga_prj", "dic"));
715 Load_DB (SG_File_Make_Path(Path_Shared, "saga_prj", "srs"));
716
717 SG_UI_Msg_Lock(false);
718 }
719
720 return( true );
721 }
722
723 //---------------------------------------------------------
CSG_Projections(const CSG_String & File_DB)724 CSG_Projections::CSG_Projections(const CSG_String &File_DB)
725 {
726 _On_Construction();
727
728 Create(File_DB);
729 }
730
Create(const CSG_String & File_DB)731 bool CSG_Projections::Create(const CSG_String &File_DB)
732 {
733 SG_UI_Msg_Lock(true);
734
735 bool bResult = Load_DB(File_DB);
736
737 SG_UI_Msg_Lock(false);
738
739 return( bResult );
740 }
741
742 //---------------------------------------------------------
_On_Construction(void)743 void CSG_Projections::_On_Construction(void)
744 {
745 m_pProjections = new CSG_Table;
746
747 m_pProjections->Add_Field("srid" , SG_DATATYPE_Int ); // PRJ_FIELD_SRID
748 m_pProjections->Add_Field("auth_name", SG_DATATYPE_String); // PRJ_FIELD_AUTH_NAME
749 m_pProjections->Add_Field("auth_srid", SG_DATATYPE_Int ); // PRJ_FIELD_AUTH_SRID
750 m_pProjections->Add_Field("srtext" , SG_DATATYPE_String); // PRJ_FIELD_SRTEXT
751 m_pProjections->Add_Field("proj4text", SG_DATATYPE_String); // PRJ_FIELD_PROJ4TEXT
752
753 Reset_Dictionary();
754 }
755
756 //---------------------------------------------------------
~CSG_Projections(void)757 CSG_Projections::~CSG_Projections(void)
758 {
759 Destroy();
760
761 delete(m_pProjections);
762 }
763
764 //---------------------------------------------------------
Destroy(void)765 void CSG_Projections::Destroy(void)
766 {
767 if( m_pProjections )
768 {
769 m_pProjections->Del_Records();
770 }
771
772 Reset_Dictionary();
773 }
774
775
776 ///////////////////////////////////////////////////////////
777 // //
778 ///////////////////////////////////////////////////////////
779
780 //---------------------------------------------------------
Reset_Dictionary(void)781 bool CSG_Projections::Reset_Dictionary(void)
782 {
783 _Set_Dictionary(m_Proj4_to_WKT, 1);
784 _Set_Dictionary(m_WKT_to_Proj4, -1);
785
786 return( true );
787 }
788
789 //---------------------------------------------------------
Load_Dictionary(const CSG_String & FileName)790 bool CSG_Projections::Load_Dictionary(const CSG_String &FileName)
791 {
792 CSG_Table Table;
793
794 if( SG_File_Exists(FileName) && Table.Create(FileName) && Table.Get_Field_Count() >= 3 )
795 {
796 CSG_Table Proj4_to_WKT(&Table), WKT_to_Proj4(&Table);
797
798 for(int i=0; i<Table.Get_Count(); i++)
799 {
800 switch( Table[i].asString(1)[0] )
801 {
802 case SG_T('<'): // ignore proj4 to wkt translation
803 WKT_to_Proj4.Add_Record(Table.Get_Record(i));
804 break;
805
806 case SG_T('>'): // ignore wkt to proj4 translation
807 Proj4_to_WKT.Add_Record(Table.Get_Record(i));
808 break;
809
810 default:
811 Proj4_to_WKT.Add_Record(Table.Get_Record(i));
812 WKT_to_Proj4.Add_Record(Table.Get_Record(i));
813 }
814 }
815
816 m_Proj4_to_WKT.Create(&Proj4_to_WKT, 0, 2, true);
817 m_WKT_to_Proj4.Create(&WKT_to_Proj4, 2, 0, true);
818
819 return( true );
820 }
821
822 return( false );
823 }
824
825 //---------------------------------------------------------
Save_Dictionary(const CSG_String & File)826 bool CSG_Projections::Save_Dictionary(const CSG_String &File)
827 {
828 CSG_Table Table;
829
830 return( _Set_Dictionary(Table, 0) && Table.Save(File) );
831 }
832
833
834 ///////////////////////////////////////////////////////////
835 // //
836 ///////////////////////////////////////////////////////////
837
838 //---------------------------------------------------------
Load_DB(const CSG_String & FileName,bool bAppend)839 bool CSG_Projections::Load_DB(const CSG_String &FileName, bool bAppend)
840 {
841 CSG_Table Table;
842
843 if( SG_File_Exists(FileName) && Table.Create(FileName) )
844 {
845 if( !bAppend )
846 {
847 Destroy();
848 }
849
850 Table.Set_Index(PRJ_FIELD_SRTEXT, TABLE_INDEX_Ascending);
851
852 for(int i=0; i<Table.Get_Count() && SG_UI_Process_Set_Progress(i, Table.Get_Count()); i++)
853 {
854 m_pProjections->Add_Record(Table.Get_Record_byIndex(i));
855 }
856
857 return( true );
858 }
859
860 return( false );
861 }
862
863 //---------------------------------------------------------
Save_DB(const CSG_String & File)864 bool CSG_Projections::Save_DB(const CSG_String &File)
865 {
866 return( m_pProjections->Save(File) );
867 }
868
869
870 ///////////////////////////////////////////////////////////
871 // //
872 ///////////////////////////////////////////////////////////
873
874 //---------------------------------------------------------
Get_GCS_WGS84(void)875 const CSG_Projection & CSG_Projections::Get_GCS_WGS84(void)
876 {
877 static CSG_Projection Projection(WKT_GCS_WGS84, PROJ4_GCS_WGS84);
878
879 return( Projection );
880 }
881
882
883 ///////////////////////////////////////////////////////////
884 // //
885 ///////////////////////////////////////////////////////////
886
887 //---------------------------------------------------------
Get_Count(void) const888 int CSG_Projections::Get_Count(void) const
889 {
890 return( m_pProjections->Get_Count() );
891 }
892
893 //---------------------------------------------------------
Add(const CSG_Projection & Projection)894 bool CSG_Projections::Add(const CSG_Projection &Projection)
895 {
896 return( false );
897 }
898
899 //---------------------------------------------------------
Add(const SG_Char * WKT,const SG_Char * Proj4,const SG_Char * Authority,int Authority_ID)900 bool CSG_Projections::Add(const SG_Char *WKT, const SG_Char *Proj4, const SG_Char *Authority, int Authority_ID)
901 {
902 CSG_Table_Record *pProjection = m_pProjections->Add_Record();
903
904 pProjection->Set_Value(PRJ_FIELD_SRID , m_pProjections->Get_Count());
905 pProjection->Set_Value(PRJ_FIELD_AUTH_NAME, Authority);
906 pProjection->Set_Value(PRJ_FIELD_AUTH_SRID, Authority_ID);
907 pProjection->Set_Value(PRJ_FIELD_SRTEXT , WKT);
908 pProjection->Set_Value(PRJ_FIELD_PROJ4TEXT, Proj4);
909
910 return( true );
911 }
912
913 //---------------------------------------------------------
Get_Projection(int Index) const914 CSG_Projection CSG_Projections::Get_Projection(int Index) const
915 {
916 CSG_Projection Projection;
917
918 if( Index >= 0 && Index < m_pProjections->Get_Count() )
919 {
920 CSG_Table_Record *pRecord = m_pProjections->Get_Record(Index);
921
922 Projection.m_Authority = pRecord->asString(PRJ_FIELD_AUTH_NAME);
923 Projection.m_Authority_ID = pRecord->asInt (PRJ_FIELD_AUTH_SRID);
924 Projection.m_WKT = pRecord->asString(PRJ_FIELD_SRTEXT );
925 Projection.m_Proj4 = pRecord->asString(PRJ_FIELD_PROJ4TEXT);
926
927 CSG_MetaData m = WKT_to_MetaData(Projection.m_WKT);
928
929 Projection.m_Name = m.Get_Property("name");
930 Projection.m_Type = !m.Get_Name().Cmp("GEOCCS") ? SG_PROJ_TYPE_CS_Geocentric
931 : !m.Get_Name().Cmp("GEOGCS") ? SG_PROJ_TYPE_CS_Geographic
932 : !m.Get_Name().Cmp("PROJCS") ? SG_PROJ_TYPE_CS_Projected
933 : SG_PROJ_TYPE_CS_Undefined;
934
935 SG_Set_Projection_Unit(m, Projection.m_Unit, Projection.m_Unit_Name, Projection.m_Unit_To_Meter);
936 }
937
938 return( Projection );
939 }
940
941 //---------------------------------------------------------
Get_Projection(CSG_Projection & Projection,int EPSG_ID) const942 bool CSG_Projections::Get_Projection(CSG_Projection &Projection, int EPSG_ID) const
943 {
944 return( Get_Projection(Projection, "", EPSG_ID) );
945 }
946
Get_Projection(CSG_Projection & Projection,const CSG_String & Authority,int Authority_ID) const947 bool CSG_Projections::Get_Projection(CSG_Projection &Projection, const CSG_String &Authority, int Authority_ID) const
948 {
949 for(int i=0; i<m_pProjections->Get_Count(); i++)
950 {
951 CSG_Table_Record *pProjection = m_pProjections->Get_Record(i);
952
953 if( Authority_ID == pProjection->asInt(PRJ_FIELD_AUTH_SRID)
954 && (Authority.is_Empty() || Authority.CmpNoCase(pProjection->asString(PRJ_FIELD_AUTH_NAME)) == 0) )
955 {
956 Projection = Get_Projection(i);
957
958 return( true );
959 }
960 }
961
962 return( false );
963 }
964
965
966 ///////////////////////////////////////////////////////////
967 // //
968 ///////////////////////////////////////////////////////////
969
970 //---------------------------------------------------------
EPSG_to_Proj4(CSG_String & Proj4,int EPSG_Code) const971 bool CSG_Projections::EPSG_to_Proj4(CSG_String &Proj4, int EPSG_Code) const
972 {
973 for(int i=0; i<m_pProjections->Get_Count(); i++)
974 {
975 if( m_pProjections->Get_Record(i)->asInt(PRJ_FIELD_AUTH_SRID) == EPSG_Code )
976 {
977 Proj4 = m_pProjections->Get_Record(i)->asString(PRJ_FIELD_PROJ4TEXT);
978
979 return( true );
980 }
981 }
982
983 Proj4.Printf("+init=epsg:%d ", EPSG_Code);
984
985 return( false );
986 }
987
988 //---------------------------------------------------------
EPSG_to_WKT(CSG_String & WKT,int EPSG_Code) const989 bool CSG_Projections::EPSG_to_WKT(CSG_String &WKT, int EPSG_Code) const
990 {
991 for(int i=0; i<m_pProjections->Get_Count(); i++)
992 {
993 if( m_pProjections->Get_Record(i)->asInt(PRJ_FIELD_AUTH_SRID) == EPSG_Code )
994 {
995 WKT = m_pProjections->Get_Record(i)->asString(PRJ_FIELD_SRTEXT);
996
997 return( true );
998 }
999 }
1000
1001 return( false );
1002 }
1003
1004
1005 ///////////////////////////////////////////////////////////
1006 // //
1007 ///////////////////////////////////////////////////////////
1008
1009 //---------------------------------------------------------
Get_Names_List(TSG_Projection_Type Type) const1010 CSG_String CSG_Projections::Get_Names_List(TSG_Projection_Type Type) const
1011 {
1012 CSG_String Names;
1013
1014 for(int i=0; i<Get_Count(); i++)
1015 {
1016 CSG_Table_Record *pProjection = m_pProjections->Get_Record(i);
1017
1018 CSG_String WKT = pProjection->asString(PRJ_FIELD_SRTEXT);
1019 int SRID = pProjection->asInt (PRJ_FIELD_SRID);
1020
1021 TSG_Projection_Type iType;
1022
1023 iType = !WKT.BeforeFirst('[').Cmp("PROJCS") ? SG_PROJ_TYPE_CS_Projected
1024 : !WKT.BeforeFirst('[').Cmp("GEOGCS") ? SG_PROJ_TYPE_CS_Geographic
1025 : !WKT.BeforeFirst('[').Cmp("GEOCCS") ? SG_PROJ_TYPE_CS_Geocentric
1026 : SG_PROJ_TYPE_CS_Undefined;
1027
1028 if( Type == SG_PROJ_TYPE_CS_Undefined )
1029 {
1030 Names += CSG_String::Format("{%d}%s: %s|", SRID,
1031 SG_Get_Projection_Type_Name(iType).c_str(),
1032 WKT.AfterFirst('\"').BeforeFirst('\"').c_str()
1033 );
1034 }
1035 else if( Type == iType )
1036 {
1037 Names += CSG_String::Format("{%d}%s|", SRID,
1038 WKT.AfterFirst('\"').BeforeFirst('\"').c_str()
1039 );
1040 }
1041 }
1042
1043 return( Names );
1044 }
1045
1046
1047 ///////////////////////////////////////////////////////////
1048 // //
1049 ///////////////////////////////////////////////////////////
1050
1051 //---------------------------------------------------------
_WKT_to_MetaData(CSG_MetaData & MetaData,const CSG_String & WKT)1052 bool CSG_Projections::_WKT_to_MetaData(CSG_MetaData &MetaData, const CSG_String &WKT)
1053 {
1054 int i, l;
1055 CSG_String Key;
1056 CSG_Strings Content;
1057
1058 //-----------------------------------------------------
1059 Content.Add("");
1060
1061 for(i=0, l=-1; l!=0 && i<(int)WKT.Length(); i++)
1062 {
1063 if( l < 0 ) // read key
1064 {
1065 switch( WKT[i] )
1066 {
1067 default : Key += WKT[i]; break;
1068 case ' ': break;
1069 case '[': case '(': l = 1; break;
1070 case ')': case ']': return( false );
1071 }
1072 }
1073 else // read content
1074 {
1075 bool bAdd;
1076
1077 switch( WKT[i] )
1078 {
1079 default: bAdd = true; break;
1080 case '\"': case ' ': bAdd = false; break;
1081 case '[' : case '(': bAdd = ++l > 1; break;
1082 case ']' : case ')': bAdd = l-- > 1; break;
1083 case ',' : if( !(bAdd = l > 1) ) Content.Add(""); break;
1084 }
1085
1086 if( bAdd )
1087 {
1088 Content[Content.Get_Count() - 1] += WKT[i];
1089 }
1090 }
1091 }
1092
1093 if( Key.Length() == 0 || Content[0].Length() == 0 )
1094 {
1095 return( false );
1096 }
1097
1098 //-----------------------------------------------------
1099 if( !Key.Cmp("AUTHORITY" ) && Content.Get_Count() == 2 ) // AUTHORITY ["<name>", "<code>"]
1100 {
1101 MetaData.Add_Property("authority_name", Content[0]);
1102 MetaData.Add_Property("authority_code", Content[1]);
1103
1104 return( true );
1105 }
1106
1107 CSG_MetaData *pKey = MetaData.Add_Child(Key);
1108
1109 if( (!Key.Cmp("GEOCCS" ) && Content.Get_Count() >= 4) // GEOCCS ["<name>", <datum>, <prime meridian>, <linear unit> {,<axis>, <axis>, <axis>} {,<authority>}]
1110 || (!Key.Cmp("GEOGCS" ) && Content.Get_Count() >= 4) // GEOGCS ["<name>", <datum>, <prime meridian>, <angular unit> {,<twin axes>} {,<authority>}]
1111 || (!Key.Cmp("PROJCS" ) && Content.Get_Count() >= 3) // PROJCS ["<name>", <geographic cs>, <projection>, {<parameter>,}* <linear unit> {,<twin axes>}{,<authority>}]
1112 || (!Key.Cmp("DATUM" ) && Content.Get_Count() >= 2) ) // DATUM ["<name>", <spheroid> {,<to wgs84>} {,<authority>}]
1113 {
1114 pKey->Add_Property("name", Content[0]);
1115 }
1116
1117 if( (!Key.Cmp("PRIMEM" ) && Content.Get_Count() >= 2) // PRIMEM ["<name>", <longitude> {,<authority>}]
1118 || (!Key.Cmp("UNIT" ) && Content.Get_Count() >= 2) // UNIT ["<name>", <conversion factor> {,<authority>}]
1119 || (!Key.Cmp("AXIS" ) && Content.Get_Count() >= 2) // AXIS ["<name>", NORTH|SOUTH|EAST|WEST|UP|DOWN|OTHER]
1120 || (!Key.Cmp("PARAMETER" ) && Content.Get_Count() >= 2) ) // PARAMETER ["<name>", <value>]
1121 {
1122 pKey->Add_Property("name", Content[0]);
1123
1124 pKey->Set_Content(Content[1]);
1125 }
1126
1127 if( (!Key.Cmp("SPHEROID" ) && Content.Get_Count() >= 3) ) // SPHEROID ["<name>", <semi-major axis>, <inverse flattening> {,<authority>}]
1128 {
1129 pKey->Add_Property("name", Content[0]);
1130 pKey->Add_Child ("a" , Content[1]);
1131 pKey->Add_Child ("rf" , Content[2]);
1132 }
1133
1134 if( (!Key.Cmp("TOWGS84" ) && Content.Get_Count() >= 7) ) // TOWGS84 [<dx>, <dy>, <dz>, <ex>, <ey>, <ez>, <ppm>]
1135 {
1136 pKey->Add_Child("dx" , Content[0]);
1137 pKey->Add_Child("dy" , Content[1]);
1138 pKey->Add_Child("dz" , Content[2]);
1139 pKey->Add_Child("ex" , Content[3]);
1140 pKey->Add_Child("ey" , Content[4]);
1141 pKey->Add_Child("ez" , Content[5]);
1142 pKey->Add_Child("ppm" , Content[6]);
1143 }
1144
1145 if( (!Key.Cmp("PROJECTION") && Content.Get_Count() >= 1) ) // PROJECTION ["<name>" {,<authority>}]
1146 {
1147 pKey->Set_Content(Content[0]);
1148 }
1149
1150 //-----------------------------------------------------
1151 for(i=0; i<Content.Get_Count(); i++)
1152 {
1153 _WKT_to_MetaData(*pKey, Content[i]);
1154 }
1155
1156 return( true );
1157 }
1158
1159 //---------------------------------------------------------
WKT_to_MetaData(const CSG_String & WKT)1160 CSG_MetaData CSG_Projections::WKT_to_MetaData(const CSG_String &WKT)
1161 {
1162 CSG_MetaData MetaData;
1163
1164 _WKT_to_MetaData(MetaData, WKT);
1165
1166 if( MetaData.Get_Children_Count() == 1 )
1167 {
1168 return( *MetaData.Get_Child(0) );
1169 }
1170
1171 MetaData.Destroy();
1172
1173 return( MetaData );
1174 }
1175
1176
1177 ///////////////////////////////////////////////////////////
1178 // //
1179 ///////////////////////////////////////////////////////////
1180
1181 //---------------------------------------------------------
1182 // DATUM ["<name>",
1183 // SPHEROID["<name>", <semi-major axis>, <inverse flattening>]
1184 // *TOWGS84 [<dx>, <dy>, <dz>, <ex>, <ey>, <ez>, <ppm>]
1185 // ]
1186 //---------------------------------------------------------
_WKT_to_Proj4_Set_Datum(CSG_String & Proj4,const CSG_MetaData & WKT) const1187 bool CSG_Projections::_WKT_to_Proj4_Set_Datum(CSG_String &Proj4, const CSG_MetaData &WKT) const
1188 {
1189 if( WKT.Cmp_Property("name", "WGS84") )
1190 {
1191 Proj4 += " +datum=WGS84";
1192
1193 return( true );
1194 }
1195
1196 double a, b;
1197
1198 if( !WKT("SPHEROID") || WKT["SPHEROID"].Get_Children_Count() != 2
1199 || !WKT["SPHEROID"][0].Get_Content().asDouble(a) || a <= 0.
1200 || !WKT["SPHEROID"][1].Get_Content().asDouble(b) || b < 0. )
1201 {
1202 return( false );
1203 }
1204
1205 b = b > 0. ? a - a / b : a;
1206
1207 Proj4 += CSG_String::Format(" +a=%f", a); // Semimajor radius of the ellipsoid axis
1208 Proj4 += CSG_String::Format(" +b=%f", b); // Semiminor radius of the ellipsoid axis
1209
1210 if( WKT("TOWGS84") && WKT["TOWGS84"].Get_Children_Count() == 7 )
1211 {
1212 Proj4 += " +towgs84=";
1213
1214 for(int i=0; i<7; i++)
1215 {
1216 if( i > 0 )
1217 {
1218 Proj4 += ",";
1219 }
1220
1221 Proj4 += WKT["TOWGS84"][i].Get_Content();
1222 }
1223 }
1224
1225 return( true );
1226 }
1227
1228 //---------------------------------------------------------
WKT_to_Proj4(CSG_String & Proj4,const CSG_String & WKT) const1229 bool CSG_Projections::WKT_to_Proj4(CSG_String &Proj4, const CSG_String &WKT) const
1230 {
1231 Proj4.Clear();
1232
1233 CSG_MetaData m = WKT_to_MetaData(WKT);
1234
1235 if( m.Get_Children_Count() == 0 )
1236 {
1237 return( false );
1238 }
1239
1240 //-----------------------------------------------------
1241 int Authority_Code;
1242 CSG_String Authority_Name;
1243
1244 if( m.Get_Property("authority_name", Authority_Name) && Authority_Name.CmpNoCase("EPSG") == 0
1245 && m.Get_Property("authority_code", Authority_Code) && EPSG_to_Proj4(Proj4, Authority_Code) )
1246 { // Proj4.Printf("+init=epsg:%d", Authority_Code);
1247 return( true );
1248 }
1249
1250 //-----------------------------------------------------
1251 double d;
1252
1253 //-----------------------------------------------------
1254 // GEOCCS["<name>",
1255 // DATUM ["<name>", ...],
1256 // PRIMEM ["<name>", <longitude>],
1257 // UNIT ["<name>", <conversion factor>],
1258 // *AXIS ["<name>", NORTH|SOUTH|EAST|WEST|UP|DOWN|OTHER], AXIS...
1259 // ]
1260 if( m.Cmp_Name("GEOCCS") )
1261 {
1262 Proj4 = CSG_String::Format("+proj=geocent");
1263
1264 if( !m("DATUM") || !_WKT_to_Proj4_Set_Datum(Proj4, m["DATUM"]) )
1265 {
1266 return( false );
1267 }
1268
1269 if( m("PRIMEM") && m["PRIMEM"].Get_Content().asDouble(d) && d != 0. )
1270 {
1271 Proj4 += CSG_String::Format(" +pm=%f", d);
1272 }
1273
1274 Proj4 += CSG_String::Format(" +no_defs"); // Don't use the /usr/share/proj/proj_def.dat defaults file
1275
1276 return( true );
1277 }
1278
1279 //-----------------------------------------------------
1280 // GEOGCS["<name>,
1281 // DATUM ["<name>", ...],
1282 // PRIMEM ["<name>", <longitude>],
1283 // UNIT ["<name>", <conversion factor>],
1284 // *AXIS ["<name>", NORTH|SOUTH|EAST|WEST|UP|DOWN|OTHER], AXIS...
1285 // ]
1286 if( m.Cmp_Name("GEOGCS") )
1287 {
1288 Proj4 = "+proj=longlat";
1289
1290 if( !m("DATUM") || !_WKT_to_Proj4_Set_Datum(Proj4, m["DATUM"]) )
1291 {
1292 return( false );
1293 }
1294
1295 if( m("PRIMEM") && m["PRIMEM"].Get_Content().asDouble(d) && d != 0. )
1296 {
1297 Proj4 += CSG_String::Format(" +pm=%f", d);
1298 }
1299
1300 Proj4 += CSG_String::Format(" +no_defs"); // Don't use the /usr/share/proj/proj_def.dat defaults file
1301
1302 return( true );
1303 }
1304
1305 //-----------------------------------------------------
1306 // PROJCS["<name>,
1307 // GEOGCS ["<name>, ...],
1308 // PROJECTION["<name>"],
1309 // *PARAMETER ["<name>", <value>], PARAMETER...
1310 // UNIT ["<name>", <conversion factor>],
1311 // *AXIS ["<name>", NORTH|SOUTH|EAST|WEST|UP|DOWN|OTHER], AXIS...
1312 // ]
1313 if( m.Cmp_Name("PROJCS") && m("GEOGCS") && m("PROJECTION") && m_WKT_to_Proj4.Get_Translation(m["PROJECTION"].Get_Content(), Proj4) )
1314 {
1315 if( m["PROJECTION"].Cmp_Content("Transverse_Mercator") ) // UTM ???
1316 {
1317 double Scale = -1., Easting = -1., Northing = -1., Meridian = -1., Latitude = -1.;
1318
1319 for(int i=0; i<m.Get_Children_Count(); i++)
1320 {
1321 if( m[i].Cmp_Name("PARAMETER") )
1322 {
1323 double v;
1324
1325 if( m[i].Cmp_Property("name", "central_meridian" , true) && m[i].Get_Content().asDouble(v) ) Meridian = v;
1326 if( m[i].Cmp_Property("name", "latitude_of_origin", true) && m[i].Get_Content().asDouble(v) ) Latitude = v;
1327 if( m[i].Cmp_Property("name", "scale_factor" , true) && m[i].Get_Content().asDouble(v) ) Scale = v;
1328 if( m[i].Cmp_Property("name", "false_easting" , true) && m[i].Get_Content().asDouble(v) ) Easting = v;
1329 if( m[i].Cmp_Property("name", "false_northing" , true) && m[i].Get_Content().asDouble(v) ) Northing = v;
1330 }
1331 }
1332
1333 if( Latitude == 0. && Scale == 0.9996 && Easting == 500000. && (Northing == 0. || Northing == 10000000.) )
1334 {
1335 Proj4 = "+proj=utm";
1336
1337 if( !m["GEOGCS"]("DATUM") || !_WKT_to_Proj4_Set_Datum(Proj4, m["GEOGCS"]["DATUM"]) )
1338 {
1339 return( false );
1340 }
1341
1342 Proj4 += CSG_String::Format(" +zone=%d", (int)((183. + Meridian) / 6.));
1343
1344 if( Northing == 10000000. )
1345 {
1346 Proj4 += " +south";
1347 }
1348
1349 Proj4 += CSG_String::Format(" +no_defs"); // Don't use the /usr/share/proj/proj_def.dat defaults file
1350
1351 return( true );
1352 }
1353 }
1354
1355 //-------------------------------------------------
1356 Proj4 = "+proj=" + Proj4;
1357
1358 if( !m["GEOGCS"]("DATUM") || !_WKT_to_Proj4_Set_Datum(Proj4, m["GEOGCS"]["DATUM"]) )
1359 {
1360 return( false );
1361 }
1362
1363 if( m("PRIMEM") && m["PRIMEM"].Get_Content().asDouble(d) && d != 0. )
1364 {
1365 Proj4 += CSG_String::Format(" +pm=%f", d);
1366 }
1367
1368 for(int i=0; i<m.Get_Children_Count(); i++)
1369 {
1370 if( m[i].Cmp_Name("PARAMETER") )
1371 {
1372 CSG_String Parameter;
1373
1374 if( m_WKT_to_Proj4.Get_Translation(m[i].Get_Property("name"), Parameter) )
1375 {
1376 Proj4 += " +" + Parameter + "=" + m[i].Get_Content();
1377 }
1378 else
1379 {
1380 SG_UI_Msg_Add_Error(CSG_String::Format(">> WKT: %s [%s]", _TL("unknown parameter"), m[i].Get_Property("name")));
1381 }
1382 }
1383 }
1384
1385 if( m("UNIT") && m["UNIT"].Get_Content().asDouble(d) && d != 0. && d != 1. )
1386 {
1387 Proj4 += CSG_String::Format(" +to_meter=%f", d);
1388 }
1389
1390 Proj4 += CSG_String::Format(" +no_defs"); // Don't use the /usr/share/proj/proj_def.dat defaults file
1391
1392 return( true );
1393 }
1394
1395 //-----------------------------------------------------
1396 return( false );
1397 }
1398
1399
1400 ///////////////////////////////////////////////////////////
1401 // //
1402 ///////////////////////////////////////////////////////////
1403
1404 //---------------------------------------------------------
_Proj4_Find_Parameter(const CSG_String & Proj4,const CSG_String & Key) const1405 bool CSG_Projections::_Proj4_Find_Parameter(const CSG_String &Proj4, const CSG_String &Key) const
1406 {
1407 return( Proj4.Find("+" + Key) >= 0 );
1408 }
1409
1410 //---------------------------------------------------------
_Proj4_Read_Parameter(CSG_String & Value,const CSG_String & Proj4,const CSG_String & Key) const1411 bool CSG_Projections::_Proj4_Read_Parameter(CSG_String &Value, const CSG_String &Proj4, const CSG_String &Key) const
1412 {
1413 Value.Clear();
1414
1415 int l, i = Proj4.Find("+" + Key + "=");
1416
1417 if( i >= 0 )
1418 {
1419 for(++i, l=0; l<2 && i<(int)Proj4.Length(); i++)
1420 {
1421 switch( Proj4[i] )
1422 {
1423 case '=': l++; break;
1424 case '+': l=2; break;
1425 case ' ': l=2; break;
1426 default:
1427 if( l == 1 )
1428 {
1429 Value += Proj4[i];
1430 }
1431 }
1432 }
1433 }
1434
1435 return( Value.Length() > 0 );
1436 }
1437
1438 //---------------------------------------------------------
1439 /* ellipsoids (a, b)
1440 { "MERIT" , "6378137.0" , "6356752.298" }, // MERIT 1983
1441 { "SGS85" , "6378136.0" , "6356751.302" }, // Soviet Geodetic System 85
1442 { "GRS80" , "6378137.0" , "6356752.314" }, // GRS 1980 (IUGG, 1980)
1443 { "IAU76" , "6378140.0" , "6356755.288" }, // IAU 1976
1444 { "airy" , "6377563.396" , "6356256.91" }, // Airy 1830
1445 { "APL4.9" , "6378137.0" , "6356751.796" }, // Appl. Physics. 1965
1446 { "NWL9D" , "6378145.0" , "6356759.769" }, // Naval Weapons Lab., 1965
1447 { "mod_airy" , "6377340.189" , "6356034.446" }, // Modified Airy
1448 { "andrae" , "6377104.43" , "6355847.415" }, // Andrae 1876 (Den., Iclnd.)
1449 { "aust_SA" , "6378160.0" , "6356774.719" }, // Australian Natl & S. Amer. 1969
1450 { "GRS67" , "6378160.0" , "6356774.516" }, // GRS 67 (IUGG 1967)
1451 { "bessel" , "6377397.155" , "6356078.963" }, // Bessel 1841
1452 { "bess_nam" , "6377483.865" , "6356165.383" }, // Bessel 1841 (Namibia)
1453 { "clrk66" , "6378206.4" , "6356583.8" }, // Clarke 1866
1454 { "clrk80" , "6378249.145" , "6356514.966" }, // Clarke 1880 mod.
1455 { "CPM" , "6375738.7" , "6356666.222" }, // Comm. des Poids et Mesures 1799
1456 { "delmbr" , "6376428.0" , "6355957.926" }, // Delambre 1810 (Belgium)
1457 { "engelis" , "6378136.05" , "6356751.323" }, // Engelis 1985
1458 { "evrst30" , "6377276.345" , "6356075.413" }, // Everest 1830
1459 { "evrst48" , "6377304.063" , "6356103.039" }, // Everest 1948
1460 { "evrst56" , "6377301.243" , "6356100.228" }, // Everest 1956
1461 { "evrst69" , "6377295.664" , "6356094.668" }, // Everest 1969
1462 { "evrstSS" , "6377298.556" , "6356097.55" }, // Everest (Sabah & Sarawak)
1463 { "fschr60" , "6378166.0" , "6356784.284" }, // Fischer (Mercury Datum) 1960
1464 { "fschr60m" , "6378155.0" , "6356773.32" }, // Modified Fischer 1960
1465 { "fschr68" , "6378150.0" , "6356768.337" }, // Fischer 1968
1466 { "helmert" , "6378200.0" , "6356818.17" }, // Helmert 1906
1467 { "hough" , "6378270.0" , "6356794.343" }, // Hough
1468 { "intl" , "6378388.0" , "6356911.946" }, // International 1909 (Hayford)
1469 { "krass" , "6378245.0" , "6356863.019" }, // Krassovsky, 1942
1470 { "kaula" , "6378163.0" , "6356776.992" }, // Kaula 1961
1471 { "lerch" , "6378139.0" , "6356754.292" }, // Lerch 1979
1472 { "mprts" , "6397300.0" , "6363806.283" }, // Maupertius 1738
1473 { "new_intl" , "6378157.5" , "6356772.2" }, // New International 1967
1474 { "plessis" , "6376523.0" , "6355863" }, // Plessis 1817 (France)
1475 { "SEasia" , "6378155.0" , "6356773.321" }, // Southeast Asia
1476 { "walbeck" , "6376896.0" , "6355834.847" }, // Walbeck
1477 { "WGS60" , "6378165.0" , "6356783.287" }, // WGS 60
1478 { "WGS66" , "6378145.0" , "6356759.769" }, // WGS 66
1479 { "WGS72" , "6378135.0" , "6356750.52" }, // WGS 72
1480 { "WGS84" , "6378137.0" , "6356752.314" }, // WGS 84
1481 { "sphere" , "6370997.0" , "6370997.0" } // Normal Sphere (r=6370997)
1482 */
1483
_Proj4_Get_Ellipsoid(CSG_String & Value,const CSG_String & Proj4) const1484 bool CSG_Projections::_Proj4_Get_Ellipsoid(CSG_String &Value, const CSG_String &Proj4) const
1485 {
1486 const char ellipsoid[42][2][32] =
1487 { // ellipsoid a b
1488 { "MERIT" , "6378137.0,298.257" }, // MERIT 1983
1489 { "SGS85" , "6378136.0,298.257" }, // Soviet Geodetic System 85
1490 { "GRS80" , "6378137.0,298.2572221" }, // GRS 1980 (IUGG, 1980)
1491 { "IAU76" , "6378140.0,298.257" }, // IAU 1976
1492 { "airy" , "6377563.396,299.3249753" }, // Airy 1830
1493 { "APL4.9" , "6378137.0,298.25" }, // Appl. Physics. 1965
1494 { "NWL9D" , "6378145.0,298.25" }, // Naval Weapons Lab., 1965
1495 { "mod_airy" , "6377340.189,299.3249374" }, // Modified Airy
1496 { "andrae" , "6377104.43,300" }, // Andrae 1876 (Den., Iclnd.)
1497 { "aust_SA" , "6378160.0,298.25" }, // Australian Natl & S. Amer. 1969
1498 { "GRS67" , "6378160.0,298.2471674" }, // GRS 67 (IUGG 1967)
1499 { "bessel" , "6377397.155,299.1528128" }, // Bessel 1841
1500 { "bess_nam" , "6377483.865,299.1528128" }, // Bessel 1841 (Namibia)
1501 { "clrk66" , "6378206.4,294.9786982" }, // Clarke 1866
1502 { "clrk80" , "6378249.145,293.4663" }, // Clarke 1880 mod.
1503 { "CPM" , "6375738.7,334.29" }, // Comm. des Poids et Mesures 1799
1504 { "delmbr" , "6376428.0,311.5" }, // Delambre 1810 (Belgium)
1505 { "engelis" , "6378136.05,298.2566" }, // Engelis 1985
1506 { "evrst30" , "6377276.345,300.8017" }, // Everest 1830
1507 { "evrst48" , "6377304.063,300.8017" }, // Everest 1948
1508 { "evrst56" , "6377301.243,300.8017" }, // Everest 1956
1509 { "evrst69" , "6377295.664,300.8017" }, // Everest 1969
1510 { "evrstSS" , "6377298.556,300.8017" }, // Everest (Sabah & Sarawak)
1511 { "fschr60" , "6378166.0,298.3" }, // Fischer (Mercury Datum) 1960
1512 { "fschr60m" , "6378155.0,298.3" }, // Modified Fischer 1960
1513 { "fschr68" , "6378150.0,298.3" }, // Fischer 1968
1514 { "helmert" , "6378200.0,298.3" }, // Helmert 1906
1515 { "hough" , "6378270.0,297" }, // Hough
1516 { "intl" , "6378388.0,297" }, // International 1909 (Hayford)
1517 { "krass" , "6378245.0,298.3" }, // Krassovsky, 1942
1518 { "kaula" , "6378163.0,298.24" }, // Kaula 1961
1519 { "lerch" , "6378139.0,298.257" }, // Lerch 1979
1520 { "mprts" , "6397300.0,191" }, // Maupertius 1738
1521 { "new_intl" , "6378157.5,298.2496154" }, // New International 1967
1522 { "plessis" , "6376523.0,308.6409971" }, // Plessis 1817 (France)
1523 { "SEasia" , "6378155.0,298.3000002" }, // Southeast Asia
1524 { "walbeck" , "6376896.0,302.7800002" }, // Walbeck
1525 { "WGS60" , "6378165.0,298.3" }, // WGS 60
1526 { "WGS66" , "6378145.0,298.25" }, // WGS 66
1527 { "WGS72" , "6378135.0,298.26" }, // WGS 72
1528 { "WGS84" , "6378137.0,298.2572236" }, // WGS 84
1529 { "sphere" , "6370997.0,-1" } // Normal Sphere (r=6370997)
1530 };
1531
1532 //-----------------------------------------------------
1533 if( _Proj4_Read_Parameter(Value, Proj4, "ellps") )
1534 {
1535 for(int i=0; i<42; i++)
1536 {
1537 if( !Value.CmpNoCase(ellipsoid[i][0]) )
1538 {
1539 Value.Printf("SPHEROID[\"%s\",%s]", SG_STR_MBTOSG(ellipsoid[i][0]), SG_STR_MBTOSG(ellipsoid[i][1]));
1540
1541 return( true );
1542 }
1543 }
1544 }
1545
1546 //-----------------------------------------------------
1547 double a, b;
1548
1549 a = _Proj4_Read_Parameter(Value, Proj4, "a" ) && Value.asDouble(a) ? a : 6378137.;
1550
1551 b = _Proj4_Read_Parameter(Value, Proj4, "b" ) && Value.asDouble(b) ? a / (a - b)
1552 : _Proj4_Read_Parameter(Value, Proj4, "rf") && Value.asDouble(b) ? b
1553 : _Proj4_Read_Parameter(Value, Proj4, "f" ) && Value.asDouble(b) ? 1. / b
1554 : _Proj4_Read_Parameter(Value, Proj4, "e" ) && Value.asDouble(b) ? a / (a - sqrt(b*b - a*a))
1555 : _Proj4_Read_Parameter(Value, Proj4, "es") && Value.asDouble(b) ? a / (a - sqrt( b - a*a))
1556 : 298.2572236;
1557
1558 Value = CSG_String::Format("SPHEROID[\"Ellipsoid\",%f,%f]", a, b);
1559
1560 return( true );
1561 }
1562
1563 //---------------------------------------------------------
_Proj4_Get_Datum(CSG_String & Value,const CSG_String & Proj4) const1564 bool CSG_Projections::_Proj4_Get_Datum(CSG_String &Value, const CSG_String &Proj4) const
1565 {
1566 const char datum[9][3][64] =
1567 { // datum_id ellipse definition
1568 { "WGS84" , "WGS84" , "0,0,0,0,0,0,0" },
1569 { "GGRS87" , "GRS80" , "-199.87,74.79,246.62,0,0,0,0" }, // Greek_Geodetic_Reference_System_1987
1570 { "NAD83" , "GRS80" , "0,0,0,0,0,0,0" }, // North_American_Datum_1983
1571 // { "NAD27" , "clrk66" , "nadgrids=@conus,@alaska,@ntv2_0.gsb,@ntv1_can.dat" }, // North_American_Datum_1927
1572 { "potsdam" , "bessel" , "606.0,23.0,413.0,0,0,0,0" }, // Potsdam Rauenberg 1950 DHDN
1573 { "carthage" , "clark80" , "-263.0,6.0,431.0,0,0,0,0" }, // Carthage 1934 Tunisia
1574 { "hermannskogel" , "bessel" , "653.0,-212.0,449.0,0,0,0,0" }, // Hermannskogel
1575 { "ire65" , "mod_airy" , "482.530,-130.596,564.557,-1.042,-0.214,-0.631,8.15" }, // Ireland 1965
1576 { "nzgd49" , "intl" , "59.47,-5.04,187.44,0.47,-0.1,1.024,-4.5993" }, // New Zealand Geodetic Datum 1949
1577 { "OSGB36" , "airy" , "446.448,-125.157,542.060,0.1502,0.2470,0.8421,-20.4894" } // Airy 1830
1578 };
1579
1580 CSG_String Spheroid, ToWGS84;
1581
1582 //-----------------------------------------------------
1583 if( _Proj4_Read_Parameter(Value, Proj4, "datum") )
1584 {
1585 for(int i=0; i<9; i++)
1586 {
1587 if( !Value.CmpNoCase(datum[i][0]) && _Proj4_Get_Ellipsoid(Spheroid, CSG_String::Format("+ellps=%s", SG_STR_MBTOSG(datum[i][1]))) )
1588 {
1589 Value.Printf("DATUM[\"%s\",%s,TOWGS84[%s]]", SG_STR_MBTOSG(datum[i][0]), Spheroid.c_str(), SG_STR_MBTOSG(datum[i][2]));
1590
1591 return( true );
1592 }
1593 }
1594 }
1595
1596 //-----------------------------------------------------
1597 if( _Proj4_Get_Ellipsoid(Spheroid, Proj4) )
1598 {
1599 Value = "DATUM[\"Datum\","+ Spheroid;
1600
1601 if( _Proj4_Read_Parameter(ToWGS84, Proj4, "towgs84") )
1602 {
1603 Value += ",TOWGS84[" + ToWGS84 + "]";
1604 }
1605 else
1606 {
1607 Value += ",TOWGS84[0,0,0,0,0,0,0]";
1608 }
1609
1610 Value += "]";
1611
1612 return( true );
1613 }
1614
1615 //-----------------------------------------------------
1616 Value = "DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563],TOWGS84[0,0,0,0,0,0,0]]";
1617
1618 return( false );
1619 }
1620
1621 //---------------------------------------------------------
_Proj4_Get_Prime_Meridian(CSG_String & Value,const CSG_String & Proj4) const1622 bool CSG_Projections::_Proj4_Get_Prime_Meridian(CSG_String &Value, const CSG_String &Proj4) const
1623 {
1624 const char meridian[12][2][16] =
1625 {
1626 { "lisbon" , "-9.131906111" },
1627 { "paris" , "2.337229167" },
1628 { "bogota" , "74.08091667" },
1629 { "madrid" , "-3.687911111" },
1630 { "rome" , "12.45233333" },
1631 { "bern" , "7.439583333" },
1632 { "jakarta" , "106.8077194" },
1633 { "ferro" , "-17.66666667" },
1634 { "brussels" , "4.367975" },
1635 { "stockholm" , "18.05827778" },
1636 { "athens" , "23.7163375" },
1637 { "oslo" , "10.72291667" }
1638 };
1639
1640 //-----------------------------------------------------
1641 if( _Proj4_Read_Parameter(Value, Proj4, "pm") )
1642 {
1643 for(int i=0; i<12; i++)
1644 {
1645 if( !Value.CmpNoCase(meridian[i][0]) )
1646 {
1647 Value.Printf("PRIMEM[\"%s\",%s]", SG_STR_MBTOSG(meridian[i][0]), SG_STR_MBTOSG(meridian[i][1]));
1648
1649 return( true );
1650 }
1651 }
1652
1653 double d;
1654
1655 if( Value.asDouble(d) && d != 0. )
1656 {
1657 Value.Printf("PRIMEM[\"Prime_Meridian\",%f]", d);
1658
1659 return( true );
1660 }
1661 }
1662
1663 //-----------------------------------------------------
1664 Value = "PRIMEM[\"Greenwich\",0]";
1665
1666 return( false );
1667 }
1668
1669 //---------------------------------------------------------
_Proj4_Get_Unit(CSG_String & Value,const CSG_String & Proj4) const1670 bool CSG_Projections::_Proj4_Get_Unit(CSG_String &Value, const CSG_String &Proj4) const
1671 {
1672 //-----------------------------------------------------
1673 TSG_Projection_Unit Unit = _Proj4_Read_Parameter(Value, Proj4, "units") ? SG_Get_Projection_Unit(Value) : SG_PROJ_UNIT_Undefined;
1674
1675 if( Unit != SG_PROJ_UNIT_Undefined )
1676 {
1677 Value = "UNIT[\"" + SG_Get_Projection_Unit_Name(Unit) + "\"," + SG_Get_String(SG_Get_Projection_Unit_To_Meter(Unit), -16) + "]";
1678
1679 return( true );
1680 }
1681
1682 //-----------------------------------------------------
1683 double d;
1684
1685 if( _Proj4_Read_Parameter(Value, Proj4, "to_meter") && Value.asDouble(d) && d > 0. && d != 1. )
1686 {
1687 Value.Printf("UNIT[\"Unit\",%f]", d);
1688
1689 return( true );
1690 }
1691
1692 //-----------------------------------------------------
1693 Value = "UNIT[\"metre\",1]";
1694
1695 return( false );
1696 }
1697
1698 //---------------------------------------------------------
WKT_from_Proj4(CSG_String & WKT,const CSG_String & Proj4) const1699 bool CSG_Projections::WKT_from_Proj4(CSG_String &WKT, const CSG_String &Proj4) const
1700 {
1701 CSG_String Value, GeogCS, ProjCS;
1702
1703 //-----------------------------------------------------
1704 if( !_Proj4_Read_Parameter(ProjCS, Proj4, "proj") )
1705 {
1706 SG_UI_Msg_Add_Error(CSG_String::Format("Proj4 >> WKT: %s", _TL("no projection type defined")));
1707
1708 return( false );
1709 }
1710
1711 //-----------------------------------------------------
1712 // GEOGCS["<name>
1713 // DATUM ["<name>
1714 // SPHEROID["<name>", <semi-major axis>, <inverse flattening>],
1715 // *TOWGS84 [<dx>, <dy>, <dz>, <ex>, <ey>, <ez>, <ppm>]
1716 // ],
1717 // PRIMEM ["<name>", <longitude>],
1718 // UNIT ["<name>", <conversion factor>],
1719 // *AXIS ["<name>", NORTH|SOUTH|EAST|WEST|UP|DOWN|OTHER],
1720 // *AXIS ["<name>", NORTH|SOUTH|EAST|WEST|UP|DOWN|OTHER]
1721 // ]
1722
1723 GeogCS = "GEOGCS[\"GCS\",";
1724
1725 _Proj4_Get_Datum (Value, Proj4); GeogCS += Value; GeogCS += ",";
1726 _Proj4_Get_Prime_Meridian (Value, Proj4); GeogCS += Value; GeogCS += ",";
1727
1728 GeogCS += "UNIT[\"degree\",0.01745329251994328]]";
1729
1730 //-----------------------------------------------------
1731 if( !ProjCS.CmpNoCase("lonlat") || !ProjCS.CmpNoCase("longlat")
1732 || !ProjCS.CmpNoCase("latlon") || !ProjCS.CmpNoCase("latlong") )
1733 {
1734 WKT = GeogCS;
1735
1736 return( true );
1737 }
1738
1739 //-----------------------------------------------------
1740 // PROJCS["<name>
1741 // GEOGCS [ ...... ],
1742 // PROJECTION["<name>"],
1743 // *PARAMETER ["<name>", <value>], ...
1744 // UNIT ["<name>", <conversion factor>],
1745 // *AXIS ["<name>", NORTH|SOUTH|EAST|WEST|UP|DOWN|OTHER],
1746 // *AXIS ["<name>", NORTH|SOUTH|EAST|WEST|UP|DOWN|OTHER]
1747 // ]
1748
1749 if( !m_Proj4_to_WKT.Get_Translation(ProjCS, Value) )
1750 {
1751 SG_UI_Msg_Add_Error(CSG_String::Format("Proj4 >> WKT: %s [%s]", _TL("no translation available"), ProjCS.c_str()));
1752
1753 return( false );
1754 }
1755
1756 //-----------------------------------------------------
1757 // UTM ...
1758
1759 if( !ProjCS.CmpNoCase("utm") )
1760 {
1761 double Zone;
1762
1763 if( !_Proj4_Read_Parameter(Value, Proj4, "zone") || !Value.asDouble(Zone) )
1764 {
1765 SG_UI_Msg_Add_Error(CSG_String::Format("Proj4 >> WKT: %s", _TL("invalid utm zone")));
1766
1767 return( false );
1768 }
1769
1770 bool South = _Proj4_Find_Parameter(Proj4, "south");
1771
1772 WKT = CSG_String::Format("PROJCS[\"UTM zone %d%c\",%s,PROJECTION[Transverse_Mercator]", (int)Zone, South ? 'S' : 'N', GeogCS.c_str());
1773
1774 WKT += CSG_String::Format(",PARAMETER[\"%s\",%d]", SG_T("latitude_of_origin"), 0);
1775 WKT += CSG_String::Format(",PARAMETER[\"%s\",%d]", SG_T("central_meridian" ), (int)(Zone * 6 - 183));
1776 WKT += CSG_String::Format(",PARAMETER[\"%s\",%f]", SG_T("scale_factor" ), 0.9996);
1777 WKT += CSG_String::Format(",PARAMETER[\"%s\",%d]", SG_T("false_easting" ), 500000);
1778 WKT += CSG_String::Format(",PARAMETER[\"%s\",%d]", SG_T("false_northing" ), South ? 10000000 : 0);
1779 WKT += ",UNIT[\"metre\",1]]";
1780
1781 return( true );
1782 }
1783
1784 //-----------------------------------------------------
1785 // Parameters ...
1786
1787 WKT = CSG_String::Format("PROJCS[\"%s\",%s,PROJECTION[%s]", Value.c_str(), GeogCS.c_str(), Value.c_str());
1788
1789 ProjCS = Proj4;
1790
1791 while( ProjCS.Find('+') >= 0 )
1792 {
1793 CSG_String Key;
1794
1795 ProjCS = ProjCS.AfterFirst ('+');
1796 Value = ProjCS.BeforeFirst('=');
1797
1798 if( m_Proj4_to_WKT.Get_Translation(Value, Key) )
1799 {
1800 Value = ProjCS.AfterFirst('=');
1801
1802 if( Value.Find('+') >= 0 )
1803 {
1804 Value = Value.BeforeFirst('+');
1805 }
1806
1807 WKT += ",PARAMETER[\"" + Key + "\"," + Value + "]";
1808 }
1809 }
1810
1811 //-----------------------------------------------------
1812 // Unit ...
1813
1814 _Proj4_Get_Unit(Value, Proj4);
1815
1816 WKT += "," + Value + "]";
1817
1818 //-----------------------------------------------------
1819 return( true );
1820 }
1821
1822
1823 ///////////////////////////////////////////////////////////
1824 // //
1825 // //
1826 // //
1827 ///////////////////////////////////////////////////////////
1828
1829 //---------------------------------------------------------
_Set_Dictionary(CSG_Table & Dictionary,int Direction)1830 bool CSG_Projections::_Set_Dictionary(CSG_Table &Dictionary, int Direction)
1831 {
1832 const int n = 209;
1833 const char Translation[n][4][128] = {
1834 // PROJ4 DIR WKT DESCRIPTION
1835
1836 // Projection Types, *) = not verified
1837 { "aea" , " ", "Albers_Conic_Equal_Area" , "Albers Equal Area" },
1838 { "aea" , "<", "Albers" , "[ESRI] Albers Equal Area" },
1839 { "aeqd" , " ", "Azimuthal_Equidistant" , "Azimuthal Equidistant" },
1840 { "airy" , " ", "Airy" , "*) Airy" },
1841 { "aitoff" , " ", "Aitoff" , "[ESRI] Aitoff" },
1842 { "alsk" , " ", "Mod_Stererographics_of_Alaska" , "*) Mod. Stererographics of Alaska" },
1843 { "apian" , " ", "Apian_Globular_I" , "*) Apian Globular I" },
1844 { "august" , " ", "August_Epicycloidal" , "*) August Epicycloidal" },
1845 { "bacon" , " ", "Bacon_Globular" , "*) Bacon Globular" },
1846 { "bipc" , " ", "Bipolar_conic_of_western_hemisphere" , "*) Bipolar conic of western hemisphere" },
1847 { "boggs" , " ", "Boggs_Eumorphic" , "*) Boggs Eumorphic" },
1848 { "bonne" , " ", "Bonne" , "Bonne (Werner lat_1=90)" },
1849 { "cass" , " ", "Cassini_Soldner" , "Cassini" },
1850 { "cass" , "<", "Cassini" , "[ESRI] Cassini" },
1851 { "cc" , " ", "Central_Cylindrical" , "*) Central Cylindrical" },
1852 { "cea" , " ", "Cylindrical_Equal_Area" , "Equal Area Cylindrical, alias: Lambert Cyl.Eq.A., Normal Authalic Cyl. (FME), Behrmann (SP=30), Gall Orthogr. (SP=45)" },
1853 { "cea" , "<", "Behrmann" , "[ESRI] Behrmann (standard parallel = 30)" },
1854 { "chamb" , " ", "Chamberlin_Trimetric" , "*) Chamberlin Trimetric" },
1855 { "collg" , " ", "Collignon" , "*) Collignon" },
1856 { "crast" , " ", "Craster_Parabolic" , "[ESRI] Craster Parabolic (Putnins P4)" },
1857 { "denoy" , " ", "Denoyer_Semi_Elliptical" , "*) Denoyer Semi-Elliptical" },
1858 { "eck1" , " ", "Eckert_I" , "*) Eckert I" },
1859 { "eck2" , " ", "Eckert_II" , "*) Eckert II" },
1860 { "eck3" , " ", "Eckert_III" , "*) Eckert III" },
1861 { "eck4" , " ", "Eckert_IV" , "Eckert IV" },
1862 { "eck5" , " ", "Eckert_V" , "*) Eckert V" },
1863 { "eck6" , " ", "Eckert_VI" , "Eckert VI" },
1864 { "eqc" , " ", "Equirectangular" , "Equidistant Cylindrical (Plate Caree)" },
1865 { "eqc" , "<", "Equidistant_Cylindrical" , "[ESRI] Equidistant Cylindrical (Plate Caree)" },
1866 { "eqc" , "<", "Plate_Carree" , "[ESRI] Equidistant Cylindrical (Plate Caree)" },
1867 { "eqdc" , " ", "Equidistant_Conic" , "*) Equidistant Conic" },
1868 { "euler" , " ", "Euler" , "*) Euler" },
1869 { "etmerc" , " ", "Extended_Transverse_Mercator" , "*) Extended Transverse Mercator" },
1870 { "fahey" , " ", "Fahey" , "*) Fahey" },
1871 { "fouc" , " ", "Foucault" , "*) Foucaut" },
1872 { "fouc_s" , " ", "Foucault_Sinusoidal" , "*) Foucaut Sinusoidal" },
1873 { "gall" , " ", "Gall_Stereographic" , "Gall (Gall Stereographic)" },
1874 { "geocent" , " ", "Geocentric" , "*) Geocentric" },
1875 { "geos" , " ", "GEOS" , "Geostationary Satellite View" },
1876 { "gins8" , " ", "Ginsburg_VIII" , "*) Ginsburg VIII (TsNIIGAiK)" },
1877 { "gn_sinu" , " ", "General_Sinusoidal_Series" , "*) General Sinusoidal Series" },
1878 { "gnom" , " ", "Gnomonic" , "Gnomonic" },
1879 { "goode" , " ", "Goode_Homolosine" , "*) Goode Homolosine" },
1880 { "gs48" , " ", "Mod_Stererographics_48" , "*) Mod. Stererographics of 48 U.S." },
1881 { "gs50" , " ", "Mod_Stererographics_50" , "*) Mod. Stererographics of 50 U.S." },
1882 { "hammer" , " ", "Hammer_Eckert_Greifendorff" , "*) Hammer & Eckert-Greifendorff" },
1883 { "hatano" , " ", "Hatano_Asymmetrical_Equal_Area" , "*) Hatano Asymmetrical Equal Area" },
1884 { "igh" , " ", "World_Goode_Homolosine_Land" , "*) Interrupted Goode Homolosine" },
1885 { "imw_p" , " ", "International_Map_of_the_World_Polyconic", "*) International Map of the World Polyconic" },
1886 { "kav5" , " ", "Kavraisky_V" , "*) Kavraisky V" },
1887 { "kav7" , " ", "Kavraisky_VII" , "*) Kavraisky VII" },
1888 { "krovak" , " ", "Krovak" , "Krovak" },
1889 { "labrd" , " ", "Laborde_Oblique_Mercator" , "*) Laborde" },
1890 { "laea" , " ", "Lambert_Azimuthal_Equal_Area" , "Lambert Azimuthal Equal Area" },
1891 { "lagrng" , " ", "Lagrange" , "*) Lagrange" },
1892 { "larr" , " ", "Larrivee" , "*) Larrivee" },
1893 { "lask" , " ", "Laskowski" , "*) Laskowski" },
1894 { "lcc" , "<", "Lambert_Conformal_Conic_1SP" , "Lambert Conformal Conic (1 standard parallel)" },
1895 { "lcc" , "<", "Lambert_Conformal_Conic_2SP" , "Lambert Conformal Conic (2 standard parallels)" },
1896 { "lcc" , " ", "Lambert_Conformal_Conic" , "Lambert Conformal Conic" },
1897 { "lcca" , " ", "Lambert_Conformal_Conic_Alternative" , "*) Lambert Conformal Conic Alternative" },
1898 { "leac" , " ", "Lambert_Equal_Area_Conic" , "*) Lambert Equal Area Conic" },
1899 { "lee_os" , " ", "Lee_Oblated_Stereographic" , "*) Lee Oblated Stereographic" },
1900 { "loxim" , " ", "Loximuthal" , "[ESRI] Loximuthal" },
1901 { "lsat" , " ", "Space_oblique_for_LANDSAT" , "*) Space oblique for LANDSAT" },
1902 { "mbt_s" , " ", "McBryde_Thomas_Flat_Polar_Sine" , "*) McBryde-Thomas Flat-Polar Sine" },
1903 { "mbt_fps" , " ", "McBryde_Thomas_Flat_Polar_Sine_2" , "*) McBryde-Thomas Flat-Pole Sine (No. 2)" },
1904 { "mbtfpp" , " ", "McBryde_Thomas_Flat_Polar_Parabolic" , "*) McBride-Thomas Flat-Polar Parabolic" },
1905 { "mbtfpq" , " ", "Flat_Polar_Quartic" , "[ESRI] McBryde-Thomas Flat-Polar Quartic" },
1906 { "mbtfps" , " ", "McBryde_Thomas_Flat_Polar_Sinusoidal" , "*) McBryde-Thomas Flat-Polar Sinusoidal" },
1907 { "merc" , " ", "Mercator" , "[ESRI] Mercator" },
1908 { "merc" , "<", "Mercator_1SP" , "Mercator (1 standard parallel)" },
1909 { "merc" , "<", "Mercator_2SP" , "Mercator (2 standard parallels)" },
1910 { "mil_os" , " ", "Miller_Oblated_Stereographic" , "*) Miller Oblated Stereographic" },
1911 { "mill" , " ", "Miller_Cylindrical" , "Miller Cylindrical" },
1912 { "moll" , " ", "Mollweide" , "Mollweide" },
1913 { "murd1" , " ", "Murdoch_I" , "*) Murdoch I" },
1914 { "murd2" , " ", "Murdoch_II" , "*) Murdoch II" },
1915 { "murd3" , " ", "Murdoch_III" , "*) Murdoch III" },
1916 { "nell" , " ", "Nell" , "*) Nell" },
1917 { "nell_h" , " ", "Nell_Hammer" , "*) Nell-Hammer" },
1918 { "nicol" , " ", "Nicolosi_Globular" , "*) Nicolosi Globular" },
1919 { "nsper" , " ", "Near_sided_perspective" , "*) Near-sided perspective" },
1920 { "nzmg" , " ", "New_Zealand_Map_Grid" , "New Zealand Map Grid" },
1921 { "ob_tran" , " ", "General_Oblique_Transformation" , "*) General Oblique Transformation" },
1922 { "ocea" , " ", "Oblique_Cylindrical_Equal_Area" , "*) Oblique Cylindrical Equal Area" },
1923 { "oea" , " ", "Oblated_Equal_Area" , "*) Oblated Equal Area" },
1924 { "omerc" , " ", "Hotine_Oblique_Mercator" , "Oblique Mercator" },
1925 { "omerc" , "<", "Oblique_Mercator" , "Oblique Mercator" },
1926 { "ortel" , " ", "Ortelius_Oval" , "*) Ortelius Oval" },
1927 { "ortho" , " ", "Orthographic" , "Orthographic (ESRI: World from Space)" },
1928 { "pconic" , " ", "Perspective_Conic" , "*) Perspective Conic" },
1929 { "poly" , " ", "Polyconic" , "*) Polyconic (American)" },
1930 { "putp1" , " ", "Putnins_P1" , "*) Putnins P1" },
1931 { "putp2" , " ", "Putnins_P2" , "*) Putnins P2" },
1932 { "putp3" , " ", "Putnins_P3" , "*) Putnins P3" },
1933 { "putp3p" , " ", "Putnins_P3'" , "*) Putnins P3'" },
1934 { "putp4p" , " ", "Putnins_P4'" , "*) Putnins P4'" },
1935 { "putp5" , " ", "Putnins_P5" , "*) Putnins P5" },
1936 { "putp5p" , " ", "Putnins_P5'" , "*) Putnins P5'" },
1937 { "putp6" , " ", "Putnins_P6" , "*) Putnins P6" },
1938 { "putp6p" , " ", "Putnins_P6'" , "*) Putnins P6'" },
1939 { "qua_aut" , " ", "Quartic_Authalic" , "[ESRI] Quartic Authalic" },
1940 { "robin" , " ", "Robinson" , "Robinson" },
1941 { "rouss" , " ", "Roussilhe_Stereographic" , "*) Roussilhe Stereographic" },
1942 { "rpoly" , " ", "Rectangular_Polyconic" , "*) Rectangular Polyconic" },
1943 { "sinu" , " ", "Sinusoidal" , "Sinusoidal (Sanson-Flamsteed)" },
1944 { "somerc" , " ", "Hotine_Oblique_Mercator" , "Swiss Oblique Mercator" },
1945 { "somerc" , "<", "Swiss_Oblique_Cylindrical" , "Swiss Oblique Cylindrical" },
1946 { "somerc" , "<", "Hotine_Oblique_Mercator_Azimuth_Center" , "[ESRI] Swiss Oblique Mercator/Cylindrical" },
1947 { "stere" , "<", "Polar_Stereographic" , "Stereographic" },
1948 { "stere" , " ", "Stereographic" , "[ESRI] Stereographic" },
1949 { "sterea" , " ", "Oblique_Stereographic" , "Oblique Stereographic Alternative" },
1950 { "gstmerc" , " ", "Gauss_Schreiber_Transverse_Mercator" , "*) Gauss-Schreiber Transverse Mercator (aka Gauss-Laborde Reunion)" },
1951 { "tcc" , " ", "Transverse_Central_Cylindrical" , "*) Transverse Central Cylindrical" },
1952 { "tcea" , " ", "Transverse_Cylindrical_Equal_Area" , "*) Transverse Cylindrical Equal Area" },
1953 { "tissot" , " ", "Tissot_Conic" , "*) Tissot Conic" },
1954 { "tmerc" , " ", "Transverse_Mercator" , "*) Transverse Mercator" },
1955 { "tmerc" , "<", "Gauss_Kruger" , "[ESRI] DHDN" },
1956 { "tpeqd" , " ", "Two_Point_Equidistant" , "*) Two Point Equidistant" },
1957 { "tpers" , " ", "Tilted_perspective" , "*) Tilted perspective" },
1958 { "ups" , " ", "Universal_Polar_Stereographic" , "*) Universal Polar Stereographic" },
1959 { "urm5" , " ", "Urmaev_V" , "*) Urmaev V" },
1960 { "urmfps" , " ", "Urmaev_Flat_Polar_Sinusoidal" , "*) Urmaev Flat-Polar Sinusoidal" },
1961 { "utm" , ">", "Transverse_Mercator" , "*) Universal Transverse Mercator (UTM)" },
1962 { "vandg" , "<", "Van_Der_Grinten_I" , "[ESRI] van der Grinten (I)" },
1963 { "vandg" , " ", "VanDerGrinten" , "van der Grinten (I)" },
1964 { "vandg2" , " ", "VanDerGrinten_II" , "*) van der Grinten II" },
1965 { "vandg3" , " ", "VanDerGrinten_III" , "*) van der Grinten III" },
1966 { "vandg4" , " ", "VanDerGrinten_IV" , "*) van der Grinten IV" },
1967 { "vitk1" , " ", "Vitkovsky_I" , "*) Vitkovsky I" },
1968 { "wag1" , " ", "Wagner_I" , "*) Wagner I (Kavraisky VI)" },
1969 { "wag2" , " ", "Wagner_II" , "*) Wagner II" },
1970 { "wag3" , " ", "Wagner_III" , "*) Wagner III" },
1971 { "wag4" , " ", "Wagner_IV" , "*) Wagner IV" },
1972 { "wag5" , " ", "Wagner_V" , "*) Wagner V" },
1973 { "wag6" , " ", "Wagner_VI" , "*) Wagner VI" },
1974 { "wag7" , " ", "Wagner_VII" , "*) Wagner VII" },
1975 { "weren" , " ", "Werenskiold_I" , "*) Werenskiold I" },
1976 { "wink1" , " ", "Winkel_I" , "[ESRI] Winkel I" },
1977 { "wink2" , " ", "Winkel_II" , "[ESRI] Winkel II" },
1978 { "wintri" , " ", "Winkel_Tripel" , "[ESRI] Winkel Tripel" },
1979
1980 // Core Projection Types and Parameters that don't require explicit translation" },
1981 // { "lonlat" , " ", "GEOGCS" , "Lat/long (Geodetic)" },
1982 // { "latlon" , ">", "GEOGCS" , "Lat/long (Geodetic alias)" },
1983 // { "latlong" , ">", "GEOGCS" , "Lat/long (Geodetic alias)" },
1984 // { "longlat" , ">", "GEOGCS" , "Lat/long (Geodetic alias)" },
1985
1986 // { "a" , " ", "" , "Semimajor radius of the ellipsoid axis" },
1987 // { "axis" , " ", "" , "Axis orientation (new in 4.8.0)" },
1988 // { "b , " ", "" , "Semiminor radius of the ellipsoid axis" },
1989 // { "datum , " ", "" , "Datum name (see `proj -ld`)" },
1990 // { "ellps , " ", "" , "Ellipsoid name (see `proj -le`)" },
1991 // { "nadgrids , " ", "" , "Filename of NTv2 grid file to use for datum transforms (see below)" },
1992 // { "no_defs , " ", "" , "Don't use the /usr/share/proj/proj_def.dat defaults file" },
1993 // { "pm , " ", "" , "Alternate prime meridian (typically a city name, see below)" },
1994 // { "proj , " ", "" , "Projection name (see `proj -l`)" },
1995 // { "to_meter , " ", "" , "Multiplier to convert map units to 1.0m" },
1996 // { "towgs84 , " ", "" , "3 or 7 term datum transform parameters (see below)" },
1997 // { "units , " ", "" , "meters, US survey feet, etc." },
1998
1999 // { "south , " ", "" , "Denotes southern hemisphere UTM zone" },
2000 // { "zone , " ", "" , "UTM zone" },
2001
2002 // { "lon_wrap" , " ", "" , "Center longitude to use for wrapping (see below)" },
2003 // { "over" , " ", "" , "Allow longitude output outside -180 to 180 range, disables wrapping (see below)" },
2004
2005 // General Projection Parameters" },
2006 { "alpha" , " ", "azimuth" , "? Used with Oblique Mercator and possibly a few others" },
2007 { "k" , ">", "scale_factor" , "Scaling factor (old name)" },
2008 { "K" , ">", "scale_factor" , "? Scaling factor (old name)" },
2009 { "k_0" , " ", "scale_factor" , "Scaling factor (new name)" },
2010 { "lat_0" , " ", "latitude_of_origin" , "Latitude of origin" },
2011 { "lat_0" , "<", "latitude_of_center" , "Latitude of center" },
2012 { "lat_0" , "<", "central_parallel" , "[ESRI] Latitude of center" },
2013 { "lat_1" , " ", "standard_parallel_1" , "Latitude of first standard parallel" },
2014 { "lat_2" , " ", "standard_parallel_2" , "Latitude of second standard parallel" },
2015 { "lat_ts" , ">", "latitude_of_origin" , "Latitude of true scale" },
2016 { "lon_0" , " ", "central_meridian" , "Central meridian" },
2017 { "lon_0" , "<", "longitude_of_center" , "Longitude of center" },
2018 { "lonc" , " ", "longitude_of_center" , "? Longitude used with Oblique Mercator and possibly a few others" },
2019 { "x_0" , " ", "false_easting" , "False easting" },
2020 { "y_0" , " ", "false_northing" , "False northing" },
2021
2022 // Additional Projection Parameters" },
2023 { "azi" , " ", "" , "" },
2024 { "belgium" , " ", "" , "" },
2025 { "beta" , " ", "" , "" },
2026 { "czech" , " ", "" , "" },
2027 { "gamma" , " ", "" , "" },
2028 { "geoc" , " ", "" , "" },
2029 { "guam" , " ", "" , "" },
2030 { "h" , " ", "satellite_height" , "Satellite height (geos - Geostationary Satellite View)" },
2031 { "lat_b" , " ", "" , "" },
2032 { "lat_t" , " ", "" , "" },
2033 { "lon_1" , " ", "" , "" },
2034 { "lon_2" , " ", "" , "" },
2035 { "lsat" , " ", "" , "" },
2036 { "m" , " ", "" , "" },
2037 { "M" , " ", "" , "" },
2038 { "n" , " ", "" , "" },
2039 { "no_cut" , " ", "" , "" },
2040 { "no_off" , " ", "" , "" },
2041 { "no_rot" , " ", "" , "" },
2042 { "ns" , " ", "" , "" },
2043 { "o_alpha" , " ", "" , "" },
2044 { "o_lat_1" , " ", "" , "" },
2045 { "o_lat_2" , " ", "" , "" },
2046 { "o_lat_c" , " ", "" , "" },
2047 { "o_lat_p" , " ", "" , "" },
2048 { "o_lon_1" , " ", "" , "" },
2049 { "o_lon_2" , " ", "" , "" },
2050 { "o_lon_c" , " ", "" , "" },
2051 { "o_lon_p" , " ", "" , "" },
2052 { "o_proj" , " ", "" , "" },
2053 { "over" , " ", "" , "" },
2054 { "p" , " ", "" , "" },
2055 { "path" , " ", "" , "" },
2056 { "q" , " ", "" , "" },
2057 { "R" , " ", "" , "" },
2058 { "R_a" , " ", "" , "" },
2059 { "R_A" , " ", "" , "" },
2060 { "R_g" , " ", "" , "" },
2061 { "R_h" , " ", "" , "" },
2062 { "R_lat_a" , " ", "" , "" },
2063 { "R_lat_g" , " ", "" , "" },
2064 { "rot" , " ", "" , "" },
2065 { "R_V" , " ", "" , "" },
2066 { "s" , " ", "" , "" },
2067 { "sym" , " ", "" , "" },
2068 { "t" , " ", "" , "" },
2069 { "theta" , " ", "" , "" },
2070 { "tilt" , " ", "" , "" },
2071 { "vopt" , " ", "" , "" },
2072 { "W" , " ", "" , "" },
2073 { "westo" , " ", "" , "" },
2074
2075 { "" , " ", "" , "" } // dummy
2076 };
2077
2078 //-----------------------------------------------------
2079 Dictionary.Destroy();
2080 Dictionary.Set_Name("Proj.4-WKT Dictionary");
2081
2082 if( Direction == 0 )
2083 {
2084 Dictionary.Add_Field("PROJ4", SG_DATATYPE_String);
2085 Dictionary.Add_Field("DIR" , SG_DATATYPE_String);
2086 Dictionary.Add_Field("WKT" , SG_DATATYPE_String);
2087 Dictionary.Add_Field("DESC" , SG_DATATYPE_String);
2088
2089 for(int i=0; i<n; i++)
2090 {
2091 CSG_Table_Record *pRecord = Dictionary.Add_Record();
2092
2093 pRecord->Set_Value(0, Translation[i][0]);
2094 pRecord->Set_Value(1, Translation[i][1]);
2095 pRecord->Set_Value(2, Translation[i][2]);
2096 pRecord->Set_Value(3, Translation[i][3]);
2097 }
2098 }
2099 else if( Direction > 0 ) // Proj4 to WKT
2100 {
2101 Dictionary.Add_Field("PROJ4", SG_DATATYPE_String);
2102 Dictionary.Add_Field("WKT" , SG_DATATYPE_String);
2103
2104 for(int i=0; i<n; i++)
2105 {
2106 if( Translation[i][1][0] != '<' ) // only WKT to Proj4
2107 {
2108 CSG_Table_Record *pRecord = Dictionary.Add_Record();
2109
2110 pRecord->Set_Value(0, Translation[i][0]);
2111 pRecord->Set_Value(1, Translation[i][2]);
2112 }
2113 }
2114 }
2115 else if( Direction < 0 ) // WKT to Proj4
2116 {
2117 Dictionary.Add_Field("WKT" , SG_DATATYPE_String);
2118 Dictionary.Add_Field("PROJ4", SG_DATATYPE_String);
2119
2120 for(int i=0; i<n; i++)
2121 {
2122 if( Translation[i][1][0] != '>' ) // only Proj4 to WKT
2123 {
2124 CSG_Table_Record *pRecord = Dictionary.Add_Record();
2125
2126 pRecord->Set_Value(0, Translation[i][2]);
2127 pRecord->Set_Value(1, Translation[i][0]);
2128 }
2129 }
2130 }
2131
2132 return( Dictionary.Get_Count() > 0 );
2133 }
2134
2135 //---------------------------------------------------------
_Set_Dictionary(CSG_Translator & Dictionary,int Direction)2136 bool CSG_Projections::_Set_Dictionary(CSG_Translator &Dictionary, int Direction)
2137 {
2138 CSG_Table Table;
2139
2140 return( _Set_Dictionary(Table, Direction) && Dictionary.Create(&Table, 0, 1, true) );
2141 }
2142
2143
2144 ///////////////////////////////////////////////////////////
2145 // //
2146 // //
2147 // //
2148 ///////////////////////////////////////////////////////////
2149
2150 //---------------------------------------------------------
2151 #include "shapes.h"
2152 #include "tool_library.h"
2153
2154 //---------------------------------------------------------
SG_Get_Projected(CSG_Shapes * pSource,CSG_Shapes * pTarget,const CSG_Projection & Target)2155 bool SG_Get_Projected (CSG_Shapes *pSource, CSG_Shapes *pTarget, const CSG_Projection &Target)
2156 {
2157 if( !pSource || !pSource->is_Valid() )
2158 {
2159 return( false );
2160 }
2161
2162 if( pSource->Get_Projection() == Target )
2163 {
2164 return( pTarget ? pTarget->Create(*pSource) : true );
2165 }
2166
2167 if( !pSource->Get_Projection().is_Okay() || !Target.is_Okay() )
2168 {
2169 return( false );
2170 }
2171
2172 CSG_Tool *pTool = SG_Get_Tool_Library_Manager().Create_Tool("pj_proj4", 2); // Coordinate Transformation (Shapes)
2173
2174 SG_UI_ProgressAndMsg_Lock(true);
2175
2176 bool bResult = pTool && pTool->Set_Manager(NULL);
2177
2178 if( bResult )
2179 {
2180 pTool->Set_Parameter("CRS_PROJ4", Target.Get_Proj4());
2181 pTool->Set_Parameter("SOURCE" , pSource);
2182 pTool->Set_Parameter("TARGET" , pTarget);
2183 pTool->Set_Parameter("COPY" , pTarget ? true : false);
2184 pTool->Set_Parameter("PARALLEL" , true);
2185
2186 bResult = pTool->Execute();
2187 }
2188
2189 SG_UI_ProgressAndMsg_Lock(false);
2190
2191 SG_Get_Tool_Library_Manager().Delete_Tool(pTool);
2192
2193 return( bResult );
2194 }
2195
2196 //---------------------------------------------------------
SG_Get_Projected(const CSG_Projection & Source,const CSG_Projection & Target,TSG_Point & Point)2197 bool SG_Get_Projected (const CSG_Projection &Source, const CSG_Projection &Target, TSG_Point &Point)
2198 {
2199 if( Source == Target )
2200 {
2201 return( true );
2202 }
2203
2204 if( Source.is_Okay() && Target.is_Okay() )
2205 {
2206 CSG_Tool *pTool = SG_Get_Tool_Library_Manager().Create_Tool("pj_proj4", 29); // Single Coordinate Transformation
2207
2208 SG_UI_ProgressAndMsg_Lock(true);
2209
2210 bool bResult = pTool && pTool->Set_Manager(NULL)
2211 && pTool->Set_Parameter("TARGET_CRS", Target.Get_Proj4())
2212 && pTool->Set_Parameter("SOURCE_CRS", Source.Get_Proj4())
2213 && pTool->Set_Parameter("SOURCE_X" , Point.x)
2214 && pTool->Set_Parameter("SOURCE_Y" , Point.y)
2215 && pTool->Execute();
2216
2217 if( bResult )
2218 {
2219 Point.x = pTool->Get_Parameter("TARGET_X")->asDouble();
2220 Point.y = pTool->Get_Parameter("TARGET_Y")->asDouble();
2221 }
2222
2223 SG_UI_ProgressAndMsg_Lock(false);
2224
2225 SG_Get_Tool_Library_Manager().Delete_Tool(pTool);
2226
2227 return( bResult );
2228 }
2229
2230 return( false );
2231 }
2232
2233 //---------------------------------------------------------
SG_Get_Projected(const CSG_Projection & Source,const CSG_Projection & Target,TSG_Rect & Rectangle)2234 bool SG_Get_Projected (const CSG_Projection &Source, const CSG_Projection &Target, TSG_Rect &Rectangle)
2235 {
2236 if( Source == Target )
2237 {
2238 return( true );
2239 }
2240
2241 if( Source.is_Okay() && Target.is_Okay() )
2242 {
2243 CSG_Shapes Points[2];
2244
2245 Points[0].Create(SHAPE_TYPE_Point);
2246 Points[0].Get_Projection().Create(Source);
2247 Points[0].Add_Shape()->Add_Point(Rectangle.xMin, Rectangle.yMin);
2248 Points[0].Add_Shape()->Add_Point(Rectangle.xMin, Rectangle.yMax);
2249 Points[0].Add_Shape()->Add_Point(Rectangle.xMax, Rectangle.yMax);
2250 Points[0].Add_Shape()->Add_Point(Rectangle.xMax, Rectangle.yMin);
2251
2252 if( SG_Get_Projected(&Points[0], &Points[1], Target) )
2253 {
2254 Rectangle = Points[1].Get_Extent();
2255
2256 return( true );
2257 }
2258 }
2259
2260 return( false );
2261 }
2262
2263
2264 ///////////////////////////////////////////////////////////
2265 // //
2266 // //
2267 // //
2268 ///////////////////////////////////////////////////////////
2269
2270 //---------------------------------------------------------
SG_Grid_Get_Geographic_Coordinates(CSG_Grid * pGrid,CSG_Grid * pLon,CSG_Grid * pLat)2271 bool SG_Grid_Get_Geographic_Coordinates (CSG_Grid *pGrid, CSG_Grid *pLon, CSG_Grid *pLat)
2272 {
2273 bool bResult = false;
2274
2275 if( pGrid && pGrid->is_Valid() && pGrid->Get_Projection().is_Okay() && (pLon || pLat) )
2276 {
2277 CSG_Grid Lon; if( !pLon ) { pLon = &Lon; } pLon->Create(pGrid->Get_System());
2278 CSG_Grid Lat; if( !pLat ) { pLat = &Lat; } pLat->Create(pGrid->Get_System());
2279
2280 SG_RUN_TOOL(bResult, "pj_proj4", 17, // geographic coordinate grids
2281 SG_TOOL_PARAMETER_SET("GRID", pGrid)
2282 && SG_TOOL_PARAMETER_SET("LON" , pLon )
2283 && SG_TOOL_PARAMETER_SET("LAT" , pLat )
2284 )
2285 }
2286
2287 return( bResult );
2288 }
2289
2290
2291 ///////////////////////////////////////////////////////////
2292 // //
2293 // //
2294 // //
2295 ///////////////////////////////////////////////////////////
2296
2297 //---------------------------------------------------------
2298