SAGA API  v9.7
projections.cpp
Go to the documentation of this file.
1 
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 // //
49 
50 //---------------------------------------------------------
51 #include "geo_tools.h"
52 
53 #include "table.h"
54 #include "shapes.h"
55 #include "data_manager.h"
56 #include "tool_library.h"
57 
58 
60 // //
61 // //
62 // //
64 
65 //---------------------------------------------------------
67 
68 //---------------------------------------------------------
70 {
71  return( gSG_Projections );
72 }
73 
74 
76 // //
77 // //
78 // //
80 
81 //---------------------------------------------------------
83 {
84  Destroy();
85 }
86 
88 {}
89 
90 //---------------------------------------------------------
92 {
93  Create(Projection);
94 }
95 
96 bool CSG_Projection::Create(const CSG_Projection &Projection)
97 {
98  m_Name = Projection.m_Name;
99  m_Type = Projection.m_Type;
100  m_Unit = Projection.m_Unit;
101 
102  m_WKT2 = Projection.m_WKT2;
103  m_PROJ = Projection.m_PROJ;
104  m_Authority = Projection.m_Authority;
105  m_Code = Projection.m_Code;
106 
107  return( true );
108 }
109 
110 //---------------------------------------------------------
111 CSG_Projection::CSG_Projection(const char *Definition)
112 {
113  Create(Definition);
114 }
115 
116 bool CSG_Projection::Create(const char *Definition)
117 {
118  if( Definition && *Definition)
119  {
120  return( Create(CSG_String(Definition)) );
121  }
122 
123  Destroy();
124 
125  return( false );
126 }
127 
128 //---------------------------------------------------------
129 CSG_Projection::CSG_Projection(const wchar_t *Definition)
130 {
131  Create(Definition);
132 }
133 
134 bool CSG_Projection::Create(const wchar_t *Definition)
135 {
136  if( Definition && *Definition )
137  {
138  return( Create(CSG_String(Definition)) );
139  }
140 
141  Destroy();
142 
143  return( false );
144 }
145 
146 //---------------------------------------------------------
148 {
149  Create(Definition);
150 }
151 
152 bool CSG_Projection::Create(const CSG_String &Definition)
153 {
154  Destroy();
155 
156  if( CSG_Projections::Parse(Definition, &m_PROJ, &m_WKT2) )
157  {
158  CSG_MetaData WKT(CSG_Projections::_WKT2_to_MetaData(m_WKT2, true));
159 
160  m_Type = CSG_Projections::Get_CRS_Type(WKT.Get_Name());
161 
162  if( m_Type != ESG_CRS_Type::Undefined )
163  {
164  m_Name = WKT.Get_Property("NAME"); if( m_Name.is_Empty() ) { m_Name = "unnamed"; }
165 
166  if( !WKT("ID") || !WKT["ID"].Get_Content("VAL1", m_Code) || !WKT["ID"].Get_Property("NAME", m_Authority) )
167  {
168  CSG_Strings Tokens = SG_String_Tokenize(Definition, ":");
169 
170  if( Tokens.Get_Count() == 2 && !Tokens[0].is_Empty() && Tokens[1].asInt(m_Code) )
171  {
172  m_Authority = Tokens[0]; m_Authority.Make_Upper();
173  }
174  else
175  {
176  m_Authority.Clear(); m_Code = -1;
177  }
178  }
179 
180  return( true );
181  }
182  }
183 
184  Destroy();
185 
186  return( false );
187 }
188 
189 //---------------------------------------------------------
190 CSG_Projection::CSG_Projection(int Code, const SG_Char *Authority)
191 {
192  Create(Code, Authority);
193 }
194 
195 bool CSG_Projection::Create(int Code, const SG_Char *Authority)
196 {
197  if( Create(CSG_String::Format("%s:%d", Authority && *Authority ? Authority : SG_T("EPSG"), Code)) )
198  {
199  return( true );
200  }
201 
202  return( Create(gSG_Projections.Get_Projection(Code, Authority)) ); // request SAGA's internal CRS database (might provide definitions not included in PROJ's default database)
203 }
204 
205 //---------------------------------------------------------
207 {
208  Create(WKT2, PROJ);
209 }
210 
211 bool CSG_Projection::Create(const CSG_String &WKT2, const CSG_String &PROJ)
212 {
213  if( PROJ.is_Empty() )
214  {
215  return( Create(WKT2) );
216  }
217 
218  m_PROJ = PROJ;
219  m_WKT2 = WKT2;
220 
221  CSG_MetaData WKT(CSG_Projections::_WKT2_to_MetaData(m_WKT2, true));
222 
223  m_Type = CSG_Projections::Get_CRS_Type(WKT.Get_Name());
224  m_Name = WKT.Get_Property("NAME"); if( m_Name.is_Empty() ) { m_Name = "unnamed"; }
225 
226  if( !WKT("ID") || !WKT["ID"].Get_Content("VAL1", m_Code) || !WKT["ID"].Get_Property("NAME", m_Authority) )
227  {
228  m_Authority.Clear(); m_Code = -1;
229  }
230 
231  return( true );
232 }
233 
234 //---------------------------------------------------------
236 {
237  m_Name = _TL("undefined");
238  m_Type = ESG_CRS_Type ::Undefined;
239  m_Unit = ESG_Projection_Unit::Undefined;
240 
241  m_WKT2 .Clear();
242  m_PROJ .Clear();
243  m_Authority .Clear();
244  m_Code = -1;
245 }
246 
247 
249 // //
251 
252 //---------------------------------------------------------
253 bool CSG_Projection::Load(const CSG_String &FileName)
254 {
255  CSG_File Stream(FileName, SG_FILE_R, false);
256 
257  return( Load(Stream) );
258 }
259 
260 //---------------------------------------------------------
261 bool CSG_Projection::Save(const CSG_String &FileName, ESG_CRS_Format Format) const
262 {
263  if( is_Okay() )
264  {
265  CSG_File Stream(FileName, SG_FILE_W, false);
266 
267  return( Save(Stream, Format) );
268  }
269 
270  if( SG_File_Exists(FileName) )
271  {
272  SG_File_Delete(FileName);
273  }
274 
275  return( false );
276 }
277 
278 //---------------------------------------------------------
280 {
281  if( Stream.is_Reading() )
282  {
283  CSG_String s; Stream.Read(s, (size_t)Stream.Length());
284 
285  return( Create(s) );
286  }
287 
288  return( false );
289 }
290 
291 //---------------------------------------------------------
292 bool CSG_Projection::Save(CSG_File &Stream, ESG_CRS_Format Format) const
293 {
294  if( is_Okay() && Stream.is_Writing() )
295  {
296  CSG_String Definition;
297 
298  switch( Format )
299  {
300  default:
301  case ESG_CRS_Format::WKT1: Definition = Get_WKT1(); break;
302  case ESG_CRS_Format::WKT2: Definition = Get_WKT2(); break;
303  case ESG_CRS_Format::PROJ: Definition = Get_PROJ(); break;
304  case ESG_CRS_Format::JSON: Definition = Get_JSON(); break;
305  case ESG_CRS_Format::ESRI: Definition = Get_ESRI(); break;
306  case ESG_CRS_Format::CODE: if( !m_Authority.is_Empty() && m_Code > 0 ) { Definition.Printf("%s:%d", m_Authority.c_str(), m_Code); } break;
307  }
308 
309  return( !Definition.is_Empty() && Stream.Write(Definition) == Definition.Length() );
310  }
311 
312  return( false );
313 }
314 
315 //---------------------------------------------------------
316 bool CSG_Projection::Load(const CSG_MetaData &Projection)
317 {
318  if( Projection("WKT2") && Projection("PROJ") && Create(Projection["WKT2"].Get_Content(), Projection["PROJ"].Get_Content()) ) { return( true ); }
319 
320  if( Projection("WKT2") && Create(Projection["WKT2"].Get_Content()) ) { return( true ); }
321  if( Projection("PROJ") && Create(Projection["PROJ"].Get_Content()) ) { return( true ); }
322 
323  //-----------------------------------------------------
324  // >>> backward compatibility
325 
326  if( Projection("WKT1" ) && Create(Projection["WKT1" ].Get_Content()) ) { return( true ); }
327  if( Projection("OGC_WKT") && Create(Projection["OGC_WKT"].Get_Content()) ) { return( true ); }
328  if( Projection("PROJ4" ) && Create(Projection["PROJ4" ].Get_Content()) ) { return( true ); }
329 
330  // <<< backward compatibility
331  //-----------------------------------------------------
332 
333  return( false );
334 }
335 
336 //---------------------------------------------------------
337 bool CSG_Projection::Save(CSG_MetaData &Projection) const
338 {
339  Projection.Del_Children();
340 
341  Projection.Add_Child("WKT2", m_WKT2);
342  Projection.Add_Child("PROJ", m_PROJ);
343  Projection.Add_Child("CODE", m_Code)->Add_Property("authority", m_Authority);
344 
345  return( true );
346 }
347 
348 
350 // //
352 
353 //---------------------------------------------------------
355 {
356  return( CSG_Projections::Parse(m_WKT2, ESG_CRS_Format::WKT1) );
357 }
358 
359 //---------------------------------------------------------
361 {
362  return( CSG_Projections::Parse(m_WKT2, ESG_CRS_Format::JSON) );
363 }
364 
365 //---------------------------------------------------------
367 {
368  return( CSG_Projections::Parse(m_WKT2, ESG_CRS_Format::ESRI) );
369 }
370 
371 //---------------------------------------------------------
373 {
374  return( CSG_Projections::_WKT2_to_MetaData(m_WKT2, false).asText(1) );
375 }
376 
377 
379 // //
381 
382 //---------------------------------------------------------
384 {
385  if( !is_Okay() )
386  {
387  return( _TL("Unknown Spatial Reference") );
388  }
389 
390  if( !bDetails )
391  {
393 
394  if( !m_Name.is_Empty() && m_Name.CmpNoCase("<custom>") )
395  {
396  s += "\n" + m_Name;
397  }
398 
399  if( m_Code > 0 && !m_Authority.is_Empty() )
400  {
401  s += CSG_String::Format(" [%s:%d]", m_Authority.c_str(), m_Code);
402  }
403 
404  return( s );
405  }
406 
407  //-----------------------------------------------------
408  #define ADD_HEAD(name, value) { CSG_String n(name), v(value); n.Replace("_", " "); v.Replace("_", " "); s += CSG_String::Format("<tr><th>%s</th><th>%s</th></tr>", n.c_str(), v.c_str()); }
409  #define ADD_INFO(name, value) { CSG_String n(name), v(value); n.Replace("_", " "); v.Replace("_", " "); s += CSG_String::Format("<tr><td>%s</td><td>%s</td></tr>", n.c_str(), v.c_str()); }
410  #define ADD_CONT(name, entry) if( entry ) { ADD_INFO(name, entry->Get_Content() ); }
411  #define ADD_PROP(name, entry, prop) if( entry && entry->Get_Property(prop) ) { ADD_INFO(name, entry->Get_Property(prop)); }
412 
413  CSG_MetaData WKT(CSG_Projections::_WKT2_to_MetaData(Get_WKT2(), false)), *pGCS = NULL;
414 
415  CSG_String s = "<table border=\"1\">";
416 
417  if( is_Projection() )
418  {
419  CSG_MetaData &PRJ = WKT.Cmp_Name("PROJCRS") ? WKT : WKT[0].Cmp_Name("PROJCRS") ? WKT[0] : WKT[0][0];
420 
421  ADD_HEAD(_TL("Projected Coordinate System" ), PRJ.Get_Property("NAME") && !PRJ.Cmp_Property("NAME", "unknown", true) ? PRJ.Get_Property("NAME") : SG_T(""));
422  ADD_PROP(_TL("Projection" ), PRJ("CONVERSION.METHOD"), "NAME");
423 
424  if( m_Code > 0 && !m_Authority.is_Empty() )
425  {
426  ADD_INFO(_TL("Authority Code" ), CSG_String::Format("%d", m_Code) );
427  ADD_INFO(_TL("Authority" ), m_Authority);
428  }
429 
430  ADD_PROP(_TL("Linear Unit" ), PRJ("UNIT"), "NAME");
431 
432  if( PRJ("CONVERSION") )
433  {
434  for(int i=0; i<PRJ["CONVERSION"].Get_Children_Count(); i++)
435  {
436  CSG_MetaData &Parameter = PRJ["CONVERSION"][i];
437 
438  if( Parameter.Cmp_Name("PARAMETER") && Parameter("VAL1") )
439  {
440  CSG_String Name(Parameter.Get_Property("NAME")); Name.Replace("_", " ");
441 
442  ADD_INFO(Name.c_str(), Parameter["VAL1"].Get_Content().c_str());
443  }
444  }
445  }
446 
447  pGCS = PRJ("BASEGEODCRS");
448  }
449  else if( is_Geographic() || is_Geodetic() )
450  {
451  pGCS = WKT .Cmp_Name("GEOGCRS") || WKT .Cmp_Name("GEODCRS") ? &WKT
452  : WKT[0].Cmp_Name("GEOGCRS") || WKT[0].Cmp_Name("GEODCRS") ? &WKT[0] : &WKT[0][0];
453  }
454 
455  if( pGCS )
456  {
457  CSG_MetaData &GCS = *pGCS;
458 
459  ADD_HEAD(_TL("Geographic Coordinate System"), GCS.Get_Property("NAME") && !GCS.Cmp_Property("NAME", "unknown", true) ? GCS.Get_Property("NAME") : _TL(""));
460  ADD_CONT(_TL("Authority Code" ), GCS("ID.VAL1"));
461  ADD_PROP(_TL("Authority" ), GCS("ID" ), "NAME");
462  ADD_PROP(_TL("Prime Meridian" ), GCS("PRIMEM" ), "NAME");
463  ADD_PROP(_TL("Angular Unit" ), GCS("PRIMEM.LENGTHUNIT"), "NAME");
464  ADD_PROP(_TL("Datum" ), GCS("DATUM" ), "NAME");
465  ADD_PROP(_TL("Spheroid" ), GCS("DATUM.ELLIPSOID" ), "NAME");
466  ADD_CONT(_TL("Semimajor Axis" ), GCS("DATUM.ELLIPSOID.VAL1"));
467  ADD_CONT(_TL("Inverse Flattening" ), GCS("DATUM.ELLIPSOID.VAL2"));
468  ADD_CONT(_TL("Extension" ), GCS("DATUM.EXTENSION" ));
469 
470  if( WKT("ABRIDGEDTRANSFORMATION") )
471  {
472  CSG_MetaData &Transformation = WKT["ABRIDGEDTRANSFORMATION"];
473 
474  ADD_HEAD(_TL("Transformation"), Transformation.Get_Property("NAME"));
475 
476  for(int i=0; i<Transformation.Get_Children_Count(); i++)
477  {
478  CSG_MetaData &Parameter = Transformation[i];
479 
480  if( Parameter.Cmp_Name("PARAMETER") && Parameter("VAL1") )
481  {
482  CSG_String Name(Parameter.Get_Property("NAME")); Name.Replace("_", " ");
483 
484  ADD_INFO(Name.c_str(), Parameter["VAL1"].Get_Content().c_str());
485  }
486  }
487  }
488  }
489 
490  s += "</table>";
491 
492  return( s );
493 }
494 
495 
497 // //
499 
500 //---------------------------------------------------------
501 bool CSG_Projection::is_Equal(const CSG_Projection &Projection) const
502 {
503  if( Get_Type() != Projection.Get_Type() )
504  {
505  return( false );
506  }
507 
508  if( !is_Okay() ) // both are not valid => ESG_CRS_Type::Undefined
509  {
510  return( true );
511  }
512 
513  if( !m_Authority.is_Empty() && !m_Authority.CmpNoCase(Projection.m_Authority) && m_Code == Projection.m_Code )
514  {
515  return( true );
516  }
517 
518  if( !m_PROJ.CmpNoCase(Projection.m_PROJ) ) // the simple case, identical PROJ strings...
519  {
520  return( true );
521  }
522 
523  //-----------------------------------------------------
524  // okay, let's perform a more detailed check...
525 
526  #define CMP_CONTENT(a, b ) (a && b && a->Cmp_Content(b->Get_Content()))
527  #define CMP_PROPERTY(a, b, p) (a && b && a->Get_Property(p) && b->Cmp_Property(p, a->Get_Property(p), true))
528  #define CMP_PARAMETER(a, b ) (a && b && ((!a->Cmp_Name("PARAMETER") && !b->Cmp_Name("PARAMETER")) || (CMP_PROPERTY(a, b, "name") && a->Cmp_Content(b->Get_Content()))))
529 
530  CSG_MetaData WKT[2] = {
531  CSG_Projections::_WKT1_to_MetaData( Get_WKT1()),
532  CSG_Projections::_WKT1_to_MetaData(Projection.Get_WKT1())
533  }, *pGCS[2] = { NULL, NULL };
534 
535  if( is_Projection() )
536  {
537 
538  if( !CMP_CONTENT (WKT[0]("PROJECTION"), WKT[1]("PROJECTION") ) ) { return( false ); }
539  if( !CMP_PROPERTY(WKT[0]("UNIT" ), WKT[1]("UNIT" ), "name") ) { return( false ); }
540 
541  for(int i=0; i<WKT[0].Get_Children_Count() && i<WKT[1].Get_Children_Count(); i++)
542  {
543  if( !CMP_PARAMETER(WKT[0](i), WKT[1](i)) ) { return( false ); }
544  }
545 
546  pGCS[0] = WKT[0]("GEOGCS");
547  pGCS[1] = WKT[1]("GEOGCS");
548  }
549  else if( is_Geographic() || is_Geodetic() )
550  {
551  pGCS[0] = &WKT[0];
552  pGCS[1] = &WKT[1];
553  }
554 
555  if( !pGCS[0] || !pGCS[1] )
556  {
557  return( false );
558  }
559 
560  if( !CMP_CONTENT((*pGCS[0])("PRIMEM" ), (*pGCS[1])("PRIMEM" )) ) { return( false ); }
561  if( !CMP_CONTENT((*pGCS[0])("UNIT" ), (*pGCS[1])("UNIT" )) ) { return( false ); }
562  if( !CMP_CONTENT((*pGCS[0])("DATUM.SPHEROID.a" ), (*pGCS[1])("DATUM.SPHEROID.a" )) ) { return( false ); }
563  if( !CMP_CONTENT((*pGCS[0])("DATUM.SPHEROID.rf"), (*pGCS[1])("DATUM.SPHEROID.rf")) ) { return( false ); }
564 
565  if( (*pGCS[0])("DATUM.TOWGS84") || (*pGCS[1])("DATUM.TOWGS84") )
566  {
567  #define CMP_TOWGS84(id) (\
568  ((*pGCS[0])("DATUM.TOWGS84." id) ? (*pGCS[0])["DATUM.TOWGS84." id].Get_Content().asDouble() : 0.)\
569  == ((*pGCS[1])("DATUM.TOWGS84." id) ? (*pGCS[1])["DATUM.TOWGS84." id].Get_Content().asDouble() : 0.) )
570 
571  if( !CMP_TOWGS84("dx") ) { return( false ); }
572  if( !CMP_TOWGS84("dy") ) { return( false ); }
573  if( !CMP_TOWGS84("dz") ) { return( false ); }
574  if( !CMP_TOWGS84("rx") ) { return( false ); }
575  if( !CMP_TOWGS84("ry") ) { return( false ); }
576  if( !CMP_TOWGS84("rz") ) { return( false ); }
577  if( !CMP_TOWGS84("sc") ) { return( false ); }
578  }
579 
580  if( (*pGCS[0])("DATUM.EXTENSION") || (*pGCS[1])("DATUM.EXTENSION") )
581  {
582  if( !CMP_CONTENT((*pGCS[0])("DATUM.EXTENSION"), (*pGCS[1])("DATUM.EXTENSION")) ) { return( false ); }
583  }
584 
585  return( true );
586 }
587 
588 
590 // //
592 
593 //---------------------------------------------------------
595 {
597 }
598 
599 //---------------------------------------------------------
601 {
602  return( CSG_Projections::Get_CRS_Type_Name(m_Type) );
603 }
604 
605 //---------------------------------------------------------
607 {
608  return( CSG_Projections::Get_Unit_Identifier(m_Unit) );
609 }
610 
611 //---------------------------------------------------------
613 {
614  return( CSG_Projections::Get_Unit_Name(m_Unit) );
615 }
616 
617 //---------------------------------------------------------
619 {
620  return( CSG_Projections::Get_Unit_To_Meter(m_Unit) );
621 }
622 
623 
625 // //
627 
628 //---------------------------------------------------------
630 {
631  static CSG_Projection GCS_WGS84;
632 
633  if( !GCS_WGS84.is_Okay() )
634  {
635  GCS_WGS84.Set_GCS_WGS84();
636  }
637 
638  return( GCS_WGS84 );
639 }
640 
641 //---------------------------------------------------------
643 {
644  m_Name = "WGS 84";
645  m_Type = ESG_CRS_Type::Geographic;
646  m_Unit = ESG_Projection_Unit::Undefined;
647  m_Authority = "EPSG";
648  m_Code = 4326;
649  m_PROJ = "+proj=longlat +datum=WGS84 +no_defs";
650  m_WKT2 =
651  "GEODCRS[\"WGS 84\","
652  " DATUM[\"World Geodetic System 1984\","
653  " ELLIPSOID[\"WGS 84\",6378137,298.257223563]],"
654  " CS[ellipsoidal,2],"
655  " AXIS[\"geodetic latitude (Lat)\",north],"
656  " AXIS[\"geodetic longitude (Lon)\",east],"
657  " UNIT[\"degree\",0.0174532925199433],"
658  " SCOPE[\"Horizontal component of 3D system.\"],"
659  " AREA[\"World.\"],"
660  " BBOX[-90,-180,90,180],"
661  " ID[\"EPSG\",4326]]";
662 
663 // m_WKT2 =
664 // "GEODCRS[\"WGS 84\","
665 // " DATUM[\"World Geodetic System 1984\","
666 // " ELLIPSOID[\"WGS 84\",6378137,298.257223563,"
667 // " LENGTHUNIT[\"metre\",1]]],"
668 // " PRIMEM[\"Greenwich\",0,"
669 // " ANGLEUNIT[\"degree\",0.0174532925199433]],"
670 // " CS[ellipsoidal,2],"
671 // " AXIS[\"geodetic latitude (Lat)\",north,"
672 // " ORDER[1],"
673 // " ANGLEUNIT[\"degree\",0.0174532925199433]],"
674 // " AXIS[\"geodetic longitude (Lon)\",east,"
675 // " ORDER[2],"
676 // " ANGLEUNIT[\"degree\",0.0174532925199433]],"
677 // " SCOPE[\"Horizontal component of 3D system.\"],"
678 // " AREA[\"World.\"],"
679 // " BBOX[-90,-180,90,180],"
680 // " ID[\"EPSG\",4326]]";
681 
682  return( true ); // return( Create(4326) );
683 }
684 
685 //---------------------------------------------------------
687 {
688  CSG_Projection Projection;
689 
690  Projection.Set_UTM_WGS84(Zone, bSouth);
691 
692  return( Projection );
693 }
694 
695 //---------------------------------------------------------
696 bool CSG_Projection::Set_UTM_WGS84(int Zone, bool bSouth)
697 {
698  if( Zone < 1 || Zone > 60 )
699  {
700  return( false );
701  }
702 
703  int EPSG_ID = (bSouth ? 32700 : 32600) + Zone;
704 
705  if( Create(EPSG_ID) )
706  {
707  return( true );
708  }
709 
710  //-----------------------------------------------------
711  CSG_String WKT; WKT.Printf(
712  "PROJCRS[\"WGS 84 / UTM zone %d%c\"," // Zone, N/S
713  " BASEGEODCRS[\"WGS 84\","
714  " DATUM[\"World Geodetic System 1984\","
715  " ELLIPSOID[\"WGS 84\",6378137,298.257223563,"
716  " LENGTHUNIT[\"metre\",1]]],"
717  " PRIMEM[\"Greenwich\",0,"
718  " ANGLEUNIT[\"degree\",0.0174532925199433]]],"
719  " CONVERSION[\"UTM zone 32N\","
720  " METHOD[\"Transverse Mercator\","
721  " ID[\"EPSG\",9807]],"
722  " PARAMETER[\"Latitude of natural origin\",0,"
723  " ANGLEUNIT[\"degree\",0.0174532925199433],"
724  " ID[\"EPSG\",8801]],"
725  " PARAMETER[\"Longitude of natural origin\",%d," // Central Meridian
726  " ANGLEUNIT[\"degree\",0.0174532925199433],"
727  " ID[\"EPSG\",8802]],"
728  " PARAMETER[\"Scale factor at natural origin\",0.9996,"
729  " SCALEUNIT[\"unity\",1],"
730  " ID[\"EPSG\",8805]],"
731  " PARAMETER[\"False easting\",500000,"
732  " LENGTHUNIT[\"metre\",1],"
733  " ID[\"EPSG\",8806]],"
734  " PARAMETER[\"False northing\",%d," // False Northing
735  " LENGTHUNIT[\"metre\",1],"
736  " ID[\"EPSG\",8807]]],"
737  " CS[Cartesian,2],"
738  " AXIS[\"(E)\",east,"
739  " ORDER[1],"
740  " LENGTHUNIT[\"metre\",1]],"
741  " AXIS[\"(N)\",north,"
742  " ORDER[2],"
743  " LENGTHUNIT[\"metre\",1]],"
744  " ID[\"EPSG\",32632]]", // EPSG ID
745  Zone, bSouth ? 'S' : 'N', 6 * (Zone - 1) - 177, bSouth ? 10000000 : 0, EPSG_ID
746  );
747 
748  return( Create(WKT) );
749 }
750 
751 
753 // //
754 // //
755 // //
757 
758 //---------------------------------------------------------
760 {
766 };
767 
768 
770 // //
772 
773 //---------------------------------------------------------
775 {
776  _On_Construction();
777 }
778 
779 //---------------------------------------------------------
781 {
782  _On_Construction();
783 
784  Create(LoadCodeList);
785 }
786 
787 bool CSG_Projections::Create(bool LoadCodeList)
788 {
789  Destroy();
790 
791  CSG_String Path_Shared;
792 
793  #if defined(__WXMAC__)
794  Path_Shared = SG_UI_Get_Application_Path(true);
795  #ifdef SHARE_PATH
796  if( !SG_File_Exists(SG_File_Make_Path(Path_Shared, "saga", "srs")) )
797  {
798  Path_Shared = SHARE_PATH;
799  }
800  #endif
801  #elif defined(_SAGA_LINUX)
802  #ifdef SHARE_PATH
803  Path_Shared = SHARE_PATH;
804  #endif
805  #else
806  Path_Shared = SG_UI_Get_API_Path();
807  #endif
808 
809  if( LoadCodeList ) // load spatial reference system database
810  {
811  _Load(m_pProjections, SG_File_Make_Path(Path_Shared, "saga", "srs"));
812  }
813 
814  if( _Load(m_pPreferences, SG_File_Make_Path(Path_Shared, "saga_preferences", "srs")) ) // always try to load preferences!
815  {
816  _Add_Preferences();
817  }
818 
819  return( true );
820 }
821 
822 //---------------------------------------------------------
823 void CSG_Projections::_On_Construction(void)
824 {
825  m_pProjections = new CSG_Table;
826 
827  m_pProjections->Add_Field("srid" , SG_DATATYPE_Int ); // PRJ_FIELD_SRID
828  m_pProjections->Add_Field("auth_name", SG_DATATYPE_String); // PRJ_FIELD_AUTH_NAME
829  m_pProjections->Add_Field("auth_srid", SG_DATATYPE_Int ); // PRJ_FIELD_AUTH_SRID
830  m_pProjections->Add_Field("srtext" , SG_DATATYPE_String); // PRJ_FIELD_SRTEXT
831  m_pProjections->Add_Field("proj4text", SG_DATATYPE_String); // PRJ_FIELD_PROJ4TEXT
832 
833  m_pPreferences = new CSG_Table(m_pProjections);
834 
835  _Set_Dictionary();
836 }
837 
838 //---------------------------------------------------------
840 {
841  Destroy();
842 
843  delete(m_pProjections);
844  delete(m_pPreferences);
845 }
846 
847 //---------------------------------------------------------
849 {
850  if( m_pProjections ) { m_pProjections->Del_Records(); }
851  if( m_pPreferences ) { m_pPreferences->Del_Records(); }
852 }
853 
854 
856 // //
858 
859 //---------------------------------------------------------
861 {
862  return( m_pProjections->Get_Count() );
863 }
864 
865 //---------------------------------------------------------
866 bool CSG_Projections::Add(const CSG_Projection &Projection)
867 {
868  return( false );
869 }
870 
871 //---------------------------------------------------------
872 bool CSG_Projections::Add(const SG_Char *WKT, const SG_Char *Proj4, const SG_Char *Authority, int Authority_ID)
873 {
874  CSG_Table_Record *pProjection = m_pProjections->Add_Record();
875 
876  pProjection->Set_Value(PRJ_FIELD_SRID , (int)m_pProjections->Get_Count());
877  pProjection->Set_Value(PRJ_FIELD_AUTH_NAME, Authority);
878  pProjection->Set_Value(PRJ_FIELD_AUTH_SRID, Authority_ID);
879  pProjection->Set_Value(PRJ_FIELD_SRTEXT , WKT);
880  pProjection->Set_Value(PRJ_FIELD_PROJ4TEXT, Proj4);
881 
882  return( true );
883 }
884 
885 //---------------------------------------------------------
886 CSG_Projection CSG_Projections::_Get_Projection(CSG_Table_Record *pProjection)
887 {
888  CSG_Projection Projection;
889 
890  if( pProjection )
891  {
892  Projection.m_Authority = pProjection->asString(PRJ_FIELD_AUTH_NAME);
893  Projection.m_Code = pProjection->asInt (PRJ_FIELD_AUTH_SRID);
894  Projection.m_PROJ = pProjection->asString(PRJ_FIELD_PROJ4TEXT);
895  Projection.m_WKT2 = pProjection->asString(PRJ_FIELD_SRTEXT );
896 
897  Projection.m_WKT2.Trim_Both();
898 
899  if( Projection.m_WKT2.Find("GEOGCS") == 0 // WKT-1 !
900  || Projection.m_WKT2.Find("GEOCCS") == 0
901  || Projection.m_WKT2.Find("GEODCS") == 0
902  || Projection.m_WKT2.Find("PROJCS") == 0 )
903  {
904  Projection.m_WKT2 = Parse(Projection.m_WKT2, ESG_CRS_Format::WKT2);
905  }
906 
907  //-------------------------------------------------
908  CSG_MetaData WKT = _WKT1_to_MetaData(Projection.Get_WKT1());
909 
910  Projection.m_Name = WKT.Get_Property("name");
911  Projection.m_Type = Get_CRS_Type(WKT.Get_Name());
912  Projection.m_Unit = WKT("UNIT") && WKT["UNIT"].Get_Property("name") ?
913  Get_Unit(WKT["UNIT"].Get_Property("name")) : ESG_Projection_Unit::Undefined;
914  }
915 
916  return( Projection );
917 }
918 
919 //---------------------------------------------------------
921 {
922  return( _Get_Projection(m_pProjections->Get_Record(Index)) );
923 }
924 
925 //---------------------------------------------------------
926 const SG_Char * CSG_Projections::Get_Projection(int Code, const SG_Char *_Authority) const
927 {
928  CSG_String Authority(_Authority && *_Authority ? _Authority : SG_T("EPSG"));
929 
930  for(sLong i=0; i<m_pProjections->Get_Count(); i++)
931  {
932  CSG_Table_Record *pProjection = m_pProjections->Get_Record(i);
933 
934  if( Code == pProjection->asInt(PRJ_FIELD_AUTH_SRID) && !Authority.CmpNoCase(pProjection->asString(PRJ_FIELD_AUTH_NAME)) )
935  {
936  return( pProjection->asString(PRJ_FIELD_SRTEXT) );
937  }
938  }
939 
940  return( SG_T("") );
941 }
942 
943 //---------------------------------------------------------
944 bool CSG_Projections::Get_Projection(CSG_Projection &Projection, int Code, const SG_Char *_Authority) const
945 {
946  CSG_String Authority(_Authority && *_Authority ? _Authority : SG_T("EPSG"));
947 
948  for(sLong i=0; i<m_pProjections->Get_Count(); i++)
949  {
950  CSG_Table_Record *pProjection = m_pProjections->Get_Record(i);
951 
952  if( Code == pProjection->asInt(PRJ_FIELD_AUTH_SRID) && !Authority.CmpNoCase(pProjection->asString(PRJ_FIELD_AUTH_NAME)) )
953  {
954  Projection = _Get_Projection(pProjection);
955 
956  return( Projection.is_Okay() );
957  }
958  }
959 
960  return( false );
961 }
962 
963 
965 // //
967 
968 //---------------------------------------------------------
969 bool CSG_Projections::_Add_Preferences(void)
970 {
971  if( !m_pProjections || !m_pPreferences || m_pPreferences->Get_Count() < 1 )
972  {
973  return( false );
974  }
975 
978 
979  for(sLong iPreference=0, iProjection=0; iPreference<m_pPreferences->Get_Count() && iProjection<m_pProjections->Get_Count(); )
980  {
981  CSG_Table_Record *pPreference = m_pPreferences->Get_Record_byIndex(iPreference);
982  CSG_Table_Record *pProjection = m_pProjections->Get_Record_byIndex(iProjection);
983 
984  CSG_String Authority = pProjection->asString(PRJ_FIELD_AUTH_NAME);
985 
986  int Comparison = Authority.CmpNoCase(pPreference->asString(PRJ_FIELD_AUTH_NAME));
987 
988  if( Comparison < 0 ) { iProjection++; } else if( Comparison > 0 ) { iPreference++; } else
989  {
990  Comparison = pProjection->asInt(PRJ_FIELD_AUTH_SRID) - pPreference->asInt(PRJ_FIELD_AUTH_SRID);
991 
992  if( Comparison < 0 ) { iProjection++; } else if( Comparison > 0 ) { iPreference++; } else
993  {
994  pProjection->Set_Value(PRJ_FIELD_SRTEXT , pPreference->asString(PRJ_FIELD_SRTEXT ));
995  pProjection->Set_Value(PRJ_FIELD_PROJ4TEXT, pPreference->asString(PRJ_FIELD_PROJ4TEXT));
996 
997  m_pPreferences->Select(pPreference, true);
998 
999  iProjection++; iPreference++;
1000  }
1001  }
1002  }
1003 
1004  m_pProjections->Del_Index();
1005  m_pPreferences->Del_Index();
1006 
1007  if( m_pPreferences->Get_Selection_Count() < m_pPreferences->Get_Count() )
1008  {
1009  for(sLong iPreference=0; iPreference<m_pPreferences->Get_Count(); iPreference++)
1010  {
1011  CSG_Table_Record *pPreference = m_pPreferences->Get_Record(iPreference);
1012 
1013  if( !pPreference->is_Selected() )
1014  {
1015  m_pProjections->Add_Record(pPreference);
1016  }
1017  }
1018  }
1019 
1020  m_pPreferences->Select(); // unselect all records
1021 
1022  return( true );
1023 }
1024 
1025 //---------------------------------------------------------
1026 bool CSG_Projections::Get_Preference(CSG_Projection &Projection, int Code, const CSG_String &Authority) const
1027 {
1028  for(sLong i=0; i<m_pPreferences->Get_Count(); i++)
1029  {
1030  CSG_Table_Record *pProjection = m_pPreferences->Get_Record(i);
1031 
1032  if( Code == pProjection->asInt(PRJ_FIELD_AUTH_SRID) && !Authority.CmpNoCase(pProjection->asString(PRJ_FIELD_AUTH_NAME)) )
1033  {
1034  Projection = _Get_Projection(pProjection);
1035 
1036  return( Projection.is_Okay() );
1037  }
1038  }
1039 
1040  return( false );
1041 }
1042 
1043 //---------------------------------------------------------
1044 bool CSG_Projections::Get_Preference(CSG_Projection &Projection, const CSG_String &Authority_Code) const
1045 {
1046  int i = Authority_Code.Find(':');
1047 
1048  if( i > 1 && i < (int)Authority_Code.Length() - 2 )
1049  {
1050  int Code; CSG_String Authority(Authority_Code.BeforeFirst(':'));
1051 
1052  if( !Authority.is_Empty() && Authority_Code.AfterFirst(':').asInt(Code) )
1053  {
1054  return( Get_Preference(Projection, Code, Authority) );
1055  }
1056  }
1057 
1058  return( false );
1059 }
1060 
1061 
1063 // //
1065 
1066 //---------------------------------------------------------
1067 bool CSG_Projections::_Load(CSG_Table *pTable, const CSG_String &File, bool bAppend) const
1068 {
1069  CSG_Table Table;
1070 
1071  SG_UI_Msg_Lock(true);
1072 
1073  if( pTable && Table.Create(File) && Table.Get_Count() > 0 && Table.Get_Field_Count() >= 5 )
1074  {
1075  if( bAppend )
1076  {
1077  for(sLong i=0; i<pTable->Get_Count(); i++)
1078  {
1079  Table.Add_Record(pTable->Get_Record(i));
1080  }
1081  }
1082 
1083  pTable->Del_Records();
1084 
1086 
1087  for(sLong i=0; i<Table.Get_Count(); i++)
1088  {
1089  pTable->Add_Record(Table.Get_Record_byIndex(i));
1090  }
1091 
1092  SG_UI_Msg_Lock(false);
1093 
1094  return( true );
1095  }
1096 
1097  SG_UI_Msg_Lock(false);
1098 
1099  return( false );
1100 }
1101 
1102 //---------------------------------------------------------
1103 bool CSG_Projections::Load(const CSG_String &File, bool bAppend)
1104 {
1105  return( _Load(m_pProjections, File, bAppend) );
1106 }
1107 
1108 //---------------------------------------------------------
1110 {
1111  return( m_pProjections->Save(File) );
1112 }
1113 
1114 
1116 // //
1118 
1119 //---------------------------------------------------------
1121 {
1122  CSG_String s; CSG_Tool *pTool = SG_Get_Tool_Library_Manager().Create_Tool("pj_proj4", 19); // Coordinate Reference System Format Conversion
1123 
1124  if( pTool ) // check proj.lib, ...will check white list first !
1125  {
1126  pTool->Set_Callback(false);
1127  pTool->Set_Parameter("DEFINITION", Definition);
1128  pTool->Set_Parameter("MULTILINE" , false);
1129  pTool->Set_Parameter("SIMPLIFIED", false);
1130 
1132 
1133  switch( Format )
1134  {
1135  case ESG_CRS_Format::PROJ: pTool->Set_Parameter("FORMAT", 0); if( pTool->Execute() ) { s = pTool->Get_Parameter("PROJ")->asString(); } break;
1136  case ESG_CRS_Format::WKT1: pTool->Set_Parameter("FORMAT", 1); if( pTool->Execute() ) { s = pTool->Get_Parameter("WKT1")->asString(); } break;
1137  case ESG_CRS_Format::WKT2: pTool->Set_Parameter("FORMAT", 2); if( pTool->Execute() ) { s = pTool->Get_Parameter("WKT2")->asString(); } break;
1138  case ESG_CRS_Format::JSON: pTool->Set_Parameter("FORMAT", 3); if( pTool->Execute() ) { s = pTool->Get_Parameter("JSON")->asString(); } break;
1139  case ESG_CRS_Format::ESRI: pTool->Set_Parameter("FORMAT", 4); if( pTool->Execute() ) { s = pTool->Get_Parameter("ESRI")->asString(); } break;
1140  default: break;
1141  }
1142 
1144 
1146  }
1147 
1148  return( s );
1149 }
1150 
1151 //---------------------------------------------------------
1152 bool CSG_Projections::Parse(const CSG_String &Definition, CSG_String *PROJ, CSG_String *WKT2, CSG_String *WKT1, CSG_String *JSON, CSG_String *ESRI)
1153 {
1154  if( Definition.is_Empty() )
1155  {
1156  return( false );
1157  }
1158 
1159  //-----------------------------------------------------
1160  CSG_Tool *pTool = SG_Get_Tool_Library_Manager().Create_Tool("pj_proj4", 19); // Coordinate Reference System Format Conversion
1161 
1162  if( pTool ) // check proj.lib, ...will check white list first !
1163  {
1164  pTool->Set_Callback(false);
1165  pTool->Set_Parameter("DEFINITION", Definition);
1166  pTool->Set_Parameter("MULTILINE" , false);
1167  pTool->Set_Parameter("SIMPLIFIED", false);
1168  pTool->Set_Parameter("FORMAT" , WKT1 || ESRI || JSON ? 5 : 6); // all : PROJ + WKT-2
1169 
1171 
1172  if( pTool->Execute() )
1173  {
1174  if( PROJ ) { *PROJ = pTool->Get_Parameter("PROJ")->asString(); }
1175  if( WKT1 ) { *WKT1 = pTool->Get_Parameter("WKT1")->asString(); }
1176  if( WKT2 ) { *WKT2 = pTool->Get_Parameter("WKT2")->asString(); }
1177  if( ESRI ) { *ESRI = pTool->Get_Parameter("ESRI")->asString(); }
1178  }
1179 
1181 
1183 
1184  return( !(PROJ && PROJ->is_Empty()) && !(WKT1 && WKT1->is_Empty()) && !(WKT2 && WKT2->is_Empty()) && !(ESRI && ESRI->is_Empty()) );
1185  }
1186 
1187  //-----------------------------------------------------
1188  else // proj.lib parser not available ...fallback!
1189  {
1190  int Code = -1; CSG_String Authority(Definition.BeforeFirst(':'));
1191 
1192  if( Authority.is_Empty() || Definition.AfterFirst(':').asInt(Code) == false )
1193  {
1194  CSG_MetaData WKT(CSG_Projections::_WKT1_to_MetaData(Definition));
1195 
1196  WKT.Get_Property("authority_name", Authority);
1197  WKT.Get_Property("authority_code", Code);
1198  }
1199 
1200  if( !Authority.is_Empty() && Code > 0 )
1201  {
1202  CSG_Projection Projection;
1203 
1204  if( gSG_Projections.Get_Projection(Projection, Code, Authority) )
1205  {
1206  if( WKT1 ) { *WKT1 = Projection.Get_WKT1(); }
1207  if( WKT2 ) { *WKT2 = Projection.Get_WKT2(); }
1208  if( PROJ ) { *PROJ = Projection.Get_PROJ(); }
1209  if( ESRI ) { *ESRI = Projection.Get_ESRI(); }
1210 
1211  return( true );
1212  }
1213  }
1214 
1215  //-------------------------------------------------
1216  CSG_String Proj4;
1217 
1218  if( gSG_Projections._WKT1_to_Proj4(Proj4, Definition) )
1219  {
1220  if( WKT1 ) { *WKT1 = Definition; }
1221  if( PROJ ) { *PROJ = Proj4 ; }
1222 
1223  return( !WKT2 || !ESRI );
1224  }
1225 
1226  //-------------------------------------------------
1227  CSG_String WKT;
1228 
1229  if( gSG_Projections._WKT1_from_Proj4(WKT, Definition) )
1230  {
1231  if( WKT1 ) { *WKT1 = WKT ; }
1232  if( PROJ ) { *PROJ = Definition; }
1233 
1234  return( !WKT2 || !ESRI );
1235  }
1236  }
1237 
1238  //-----------------------------------------------------
1239  return( false );
1240 }
1241 
1242 
1244 // //
1246 
1247 //---------------------------------------------------------
1249 {
1250  CSG_Table Projections;
1251 
1252  Projections.Add_Field("NAME", SG_DATATYPE_String);
1253  Projections.Add_Field("AUTH", SG_DATATYPE_String);
1254  Projections.Add_Field("CODE", SG_DATATYPE_Int );
1255  Projections.Add_Field("TYPE", SG_DATATYPE_String);
1256 
1257  for(int i=0; i<m_pProjections->Get_Count(); i++)
1258  {
1259  CSG_Table_Record *pProjection = m_pProjections->Get_Record(i);
1260 
1261  CSG_String WKT = pProjection->asString(PRJ_FIELD_SRTEXT);
1262 
1263  if( WKT.Length() == 0 )
1264  {
1265  continue;
1266  }
1267 
1268  ESG_CRS_Type _Type = Get_CRS_Type(WKT.BeforeFirst('['));
1269 
1270  for(int j=0; _Type == ESG_CRS_Type::Undefined && j<2; j++)
1271  {
1272  WKT = WKT.AfterFirst('['); // check nested keys like "COMPOUNDRDS[..., GEOGCRS[" or "BOUNDCRS[SOURCECRS[GEODCRS["...
1273 
1274  _Type = Get_CRS_Type(WKT.BeforeFirst('['));
1275  }
1276 
1277  if( _Type != ESG_CRS_Type::Undefined && (Type == ESG_CRS_Type::Undefined || Type == _Type) )
1278  {
1279  CSG_Table_Record &Projection = *Projections.Add_Record();
1280 
1281  Projection.Set_Value(0, WKT.AfterFirst('\"').BeforeFirst('\"'));
1282  Projection.Set_Value(1, pProjection->asString(PRJ_FIELD_AUTH_NAME));
1283  Projection.Set_Value(2, pProjection->asInt (PRJ_FIELD_AUTH_SRID));
1284  Projection.Set_Value(3, CSG_Projections::Get_CRS_Type_Name(_Type));
1285  }
1286  }
1287 
1288  CSG_String Names;
1289 
1290  if( bAddSelect )
1291  {
1292  Names.Printf("{}<%s>|", _TL("select"));
1293  }
1294 
1296 
1297  for(int i=0; i<Projections.Get_Count(); i++)
1298  {
1299  if( Type == ESG_CRS_Type::Undefined )
1300  {
1301  Names += CSG_String::Format("{%s:%d}%s: %s|",
1302  Projections[i].asString(1),
1303  Projections[i].asInt (2),
1304  Projections[i].asString(3),
1305  Projections[i].asString(0)
1306  );
1307  }
1308  else
1309  {
1310  Names += CSG_String::Format("{%s:%d}%s|",
1311  Projections[i].asString(1),
1312  Projections[i].asInt (2),
1313  Projections[i].asString(0)
1314  );
1315  }
1316  }
1317 
1318  return( Names );
1319 }
1320 
1321 
1323 // //
1325 
1326 //---------------------------------------------------------
1327 bool CSG_Projections::_WKT2_to_MetaData(CSG_MetaData &MetaData, const CSG_String &WKT)
1328 {
1329  if( WKT.is_Empty() )
1330  {
1331  return( false );
1332  }
1333 
1334  int Colon = -1, Bracket = -1;
1335 
1336  for(int i=0, bracket=0, quota=0; Colon<0 && i<(int)WKT.Length(); i++)
1337  {
1338  switch( WKT[i] )
1339  {
1340  case '[':
1341  bracket++; if( bracket == 1 ) { Bracket = i; }
1342  break;
1343 
1344  case ']':
1345  bracket--; if( bracket < 0 ) { return( false ); }
1346  break;
1347 
1348  case '\"':
1349  if( bracket == 0 )
1350  {
1351  quota = quota ? 0 : 1;
1352  }
1353  break;
1354 
1355  case ',':
1356  if( bracket == 0 && quota == 0 )
1357  {
1358  Colon = i;
1359  }
1360  break;
1361  }
1362  }
1363 
1364  CSG_String Value = Colon < 0 ? WKT : WKT.Left(Colon);
1365 
1366  if( Bracket < 0 )
1367  {
1368  Value.Trim_Both();
1369 
1370  if( Value.Find('\"') == 0 )
1371  {
1372  Value = Value.AfterFirst('\"').BeforeLast('\"'); Value.Trim_Both();
1373 
1374  MetaData.Add_Property("NAME" , Value);
1375  }
1376  else
1377  {
1378  MetaData.Add_Child(CSG_String::Format("VAL%d", 1 + MetaData.Get_Children_Count()), Value);
1379  }
1380  }
1381  else
1382  {
1383  CSG_String Key(Value.Left(Bracket)); Key.Trim_Both();
1384 
1385  CSG_String Content(Value.AfterFirst('[').BeforeLast(']')); Content.Trim_Both(); Content.Replace("\n", "");
1386 
1387  _WKT2_to_MetaData(*MetaData.Add_Child(Key), Content);
1388  }
1389 
1390  if( Colon > 0 )
1391  {
1392  _WKT2_to_MetaData(MetaData, WKT.Right(WKT.Length() - Colon - 1));
1393  }
1394 
1395  return( true );
1396 }
1397 
1398 //---------------------------------------------------------
1399 CSG_MetaData CSG_Projections::_WKT2_to_MetaData(const CSG_String &WKT, bool bTrim)
1400 {
1401  CSG_MetaData MetaData; _WKT2_to_MetaData(MetaData, WKT);
1402 
1403  if( MetaData.Get_Children_Count() == 1 )
1404  {
1405  CSG_MetaData *pMetaData = MetaData.Get_Child(0);
1406 
1407  if( bTrim ) // check nested keys like "COMPOUNDRDS[..., GEOGCRS[..." or "BOUNDCRS[SOURCECRS[GEODCRS[..."
1408  {
1410 
1411  for(int j=0; Type == ESG_CRS_Type::Undefined && pMetaData->Get_Child(0) && j<2; j++)
1412  {
1413  pMetaData = pMetaData->Get_Child(0);
1414 
1415  Type = CSG_Projections::Get_CRS_Type(pMetaData->Get_Name());
1416  }
1417  }
1418 
1419  return( *pMetaData );
1420  }
1421 
1422  MetaData.Destroy();
1423 
1424  return( MetaData );
1425 }
1426 
1427 //---------------------------------------------------------
1429 {
1430  CSG_String XML;
1431 
1432  if( !WKT.is_Empty() )
1433  {
1434  XML = _WKT2_to_MetaData(WKT, false).asText(1);
1435  }
1436 
1437  return( XML );
1438 }
1439 
1440 
1442 // //
1444 
1445 //---------------------------------------------------------
1446 bool CSG_Projections::_WKT1_to_MetaData(CSG_MetaData &MetaData, const CSG_String &WKT)
1447 {
1448  CSG_String Key; CSG_Strings Content; Content.Add("");
1449 
1450  for(int i=0, l=-1; l!=0 && i<(int)WKT.Length(); i++)
1451  {
1452  if( l < 0 ) // read key
1453  {
1454  switch( WKT[i] )
1455  {
1456  default : Key += WKT[i]; break;
1457  case ' ' : break;
1458  case '[': case '(': l = 1 ; break;
1459  case ')': case ']': return( false );
1460  }
1461  }
1462  else // read content
1463  {
1464  bool bAdd;
1465 
1466  switch( WKT[i] )
1467  {
1468  default : bAdd = true; break;
1469  case '\"' : bAdd = false; break;
1470  case '[' : case '(': bAdd = ++l > 1; break;
1471  case ']' : case ')': bAdd = l-- > 1; break;
1472  case ',' : if( !(bAdd = l > 1) ) Content.Add(""); break;
1473  }
1474 
1475  if( bAdd )
1476  {
1477  Content[Content.Get_Count() - 1] += WKT[i];
1478  }
1479  }
1480  }
1481 
1482  if( Key.is_Empty() || Content[0].is_Empty() )
1483  {
1484  return( false );
1485  }
1486 
1487  //-----------------------------------------------------
1488  if( !Key.Cmp("AUTHORITY") && Content.Get_Count() == 2 ) // AUTHORITY ["<name>", "<code>"]
1489  {
1490  MetaData.Add_Property("authority_name", Content[0]);
1491  MetaData.Add_Property("authority_code", Content[1]);
1492 
1493  return( true );
1494  }
1495 
1496  CSG_MetaData *pKey = MetaData.Add_Child(Key);
1497 
1498  if( (!Key.Cmp("GEOCCS" ) && Content.Get_Count() >= 4) // GEOCCS ["<name>", <datum>, <prime meridian>, <linear unit> {,<axis>, <axis>, <axis>} {,<authority>}]
1499  || (!Key.Cmp("GEOGCS" ) && Content.Get_Count() >= 4) // GEOGCS ["<name>", <datum>, <prime meridian>, <angular unit> {,<twin axes>} {,<authority>}]
1500  || (!Key.Cmp("PROJCS" ) && Content.Get_Count() >= 3) // PROJCS ["<name>", <geographic cs>, <projection>, {<parameter>,}* <linear unit> {,<twin axes>}{,<authority>}]
1501  || (!Key.Cmp("DATUM" ) && Content.Get_Count() >= 2) ) // DATUM ["<name>", <spheroid> {,<to wgs84>} {,<authority>}]
1502  {
1503  pKey->Add_Property("name", Content[0]);
1504  }
1505 
1506  if( (!Key.Cmp("PRIMEM" ) && Content.Get_Count() >= 2) // PRIMEM ["<name>", <longitude> {,<authority>}]
1507  || (!Key.Cmp("UNIT" ) && Content.Get_Count() >= 2) // UNIT ["<name>", <conversion factor> {,<authority>}]
1508  || (!Key.Cmp("AXIS" ) && Content.Get_Count() >= 2) // AXIS ["<name>", NORTH|SOUTH|EAST|WEST|UP|DOWN|OTHER]
1509  || (!Key.Cmp("PARAMETER" ) && Content.Get_Count() >= 2) ) // PARAMETER ["<name>", <value>]
1510  {
1511  pKey->Add_Property("name", Content[0]);
1512 
1513  pKey->Set_Content(Content[1]);
1514  }
1515 
1516  if( (!Key.Cmp("SPHEROID" ) && Content.Get_Count() >= 3) ) // SPHEROID ["<name>", <semi-major axis>, <inverse flattening> {,<authority>}]
1517  {
1518  pKey->Add_Property("name", Content[0]);
1519  pKey->Add_Child ("a" , Content[1]);
1520  pKey->Add_Child ("rf" , Content[2]);
1521  }
1522 
1523  if( (!Key.Cmp("TOWGS84" ) && Content.Get_Count() >= 7) ) // TOWGS84 [<dx>, <dy>, <dz>, <rx>, <ry>, <rz>, <sc>]
1524  {
1525  pKey->Add_Child("dx" , Content[0]);
1526  pKey->Add_Child("dy" , Content[1]);
1527  pKey->Add_Child("dz" , Content[2]);
1528  pKey->Add_Child("rx" , Content[3]);
1529  pKey->Add_Child("ry" , Content[4]);
1530  pKey->Add_Child("rz" , Content[5]);
1531  pKey->Add_Child("sc" , Content[6]);
1532  }
1533 
1534  if( (!Key.Cmp("EXTENSION" ) && Content.Get_Count() >= 2) ) // EXTENSION [<name>, <value>]
1535  {
1536  pKey->Add_Property("name", Content[0]);
1537  pKey->Set_Content( Content[1]);
1538  }
1539 
1540  if( (!Key.Cmp("PROJECTION") && Content.Get_Count() >= 1) ) // PROJECTION ["<name>" {,<authority>}]
1541  {
1542  pKey->Set_Content(Content[0]);
1543  }
1544 
1545  //-----------------------------------------------------
1546  for(int i=0; i<Content.Get_Count(); i++)
1547  {
1548  _WKT1_to_MetaData(*pKey, Content[i]);
1549  }
1550 
1551  return( true );
1552 }
1553 
1554 //---------------------------------------------------------
1555 CSG_MetaData CSG_Projections::_WKT1_to_MetaData(const CSG_String &WKT)
1556 {
1557  CSG_MetaData MetaData;
1558 
1559  _WKT1_to_MetaData(MetaData, WKT);
1560 
1561  if( MetaData.Get_Children_Count() == 1 )
1562  {
1563  return( *MetaData.Get_Child(0) );
1564  }
1565 
1566  MetaData.Destroy();
1567 
1568  return( MetaData );
1569 }
1570 
1571 
1573 // //
1575 
1576 //---------------------------------------------------------
1577 // DATUM ["<name>",
1578 // SPHEROID["<name>", <semi-major axis>, <inverse flattening>]
1579 // *TOWGS84 [<dx>, <dy>, <dz>, <rx>, <ry>, <rz>, <sc>]
1580 // ]
1581 //---------------------------------------------------------
1582 bool CSG_Projections::_WKT1_to_Proj4_Set_Datum(CSG_String &Proj4, const CSG_MetaData &WKT) const
1583 {
1584  if( WKT.Cmp_Property("name", "WGS84") )
1585  {
1586  Proj4 += " +datum=WGS84";
1587 
1588  return( true );
1589  }
1590 
1591  double a, b;
1592 
1593  if( !WKT("SPHEROID") || WKT["SPHEROID"].Get_Children_Count() != 2
1594  || !WKT["SPHEROID"][0].Get_Content().asDouble(a) || a <= 0.
1595  || !WKT["SPHEROID"][1].Get_Content().asDouble(b) || b < 0. )
1596  {
1597  return( false );
1598  }
1599 
1600  b = b > 0. ? a - a / b : a;
1601 
1602  Proj4 += CSG_String::Format(" +a=%f", a); // Semimajor radius of the ellipsoid axis
1603  Proj4 += CSG_String::Format(" +b=%f", b); // Semiminor radius of the ellipsoid axis
1604 
1605  if( WKT("TOWGS84") && WKT["TOWGS84"].Get_Children_Count() == 7 )
1606  {
1607  Proj4 += " +towgs84=";
1608 
1609  for(int i=0; i<7; i++)
1610  {
1611  if( i > 0 )
1612  {
1613  Proj4 += ",";
1614  }
1615 
1616  Proj4 += WKT["TOWGS84"][i].Get_Content();
1617  }
1618  }
1619 
1620  return( true );
1621 }
1622 
1623 //---------------------------------------------------------
1624 bool CSG_Projections::_WKT1_to_Proj4(CSG_String &Proj4, const CSG_String &WKT) const
1625 {
1626  Proj4.Clear();
1627 
1628  CSG_MetaData m = _WKT1_to_MetaData(WKT);
1629 
1630  if( m.Get_Children_Count() == 0 )
1631  {
1632  return( false );
1633  }
1634 
1635  //-----------------------------------------------------
1636  int Authority_Code; CSG_String Authority_Name;
1637 
1638  if( m.Get_Property("authority_name", Authority_Name)
1639  && m.Get_Property("authority_code", Authority_Code) )
1640  {
1641  CSG_Projection Projection;
1642 
1643  if( Get_Projection(Projection, Authority_Code, Authority_Name) )
1644  {
1645  Proj4 = Projection.Get_PROJ();
1646 
1647  return( true );
1648  }
1649  }
1650 
1651  //-----------------------------------------------------
1652  double d;
1653 
1654  //-----------------------------------------------------
1655  // GEOCCS["<name>",
1656  // DATUM ["<name>", ...],
1657  // PRIMEM ["<name>", <longitude>],
1658  // UNIT ["<name>", <conversion factor>],
1659  // *AXIS ["<name>", NORTH|SOUTH|EAST|WEST|UP|DOWN|OTHER], AXIS...
1660  // ]
1661  if( m.Cmp_Name("GEOCCS") )
1662  {
1663  Proj4 = CSG_String::Format("+proj=geocent");
1664 
1665  if( !m("DATUM") || !_WKT1_to_Proj4_Set_Datum(Proj4, m["DATUM"]) )
1666  {
1667  return( false );
1668  }
1669 
1670  if( m("PRIMEM") && m["PRIMEM"].Get_Content().asDouble(d) && d != 0. )
1671  {
1672  Proj4 += CSG_String::Format(" +pm=%f", d);
1673  }
1674 
1675  Proj4 += CSG_String::Format(" +no_defs"); // Don't use the /usr/share/proj/proj_def.dat defaults file
1676 
1677  return( true );
1678  }
1679 
1680  //-----------------------------------------------------
1681  // GEOGCS["<name>,
1682  // DATUM ["<name>", ...],
1683  // PRIMEM ["<name>", <longitude>],
1684  // UNIT ["<name>", <conversion factor>],
1685  // *AXIS ["<name>", NORTH|SOUTH|EAST|WEST|UP|DOWN|OTHER], AXIS...
1686  // ]
1687  if( m.Cmp_Name("GEOGCS") )
1688  {
1689  Proj4 = "+proj=longlat";
1690 
1691  if( !m("DATUM") || !_WKT1_to_Proj4_Set_Datum(Proj4, m["DATUM"]) )
1692  {
1693  return( false );
1694  }
1695 
1696  if( m("PRIMEM") && m["PRIMEM"].Get_Content().asDouble(d) && d != 0. )
1697  {
1698  Proj4 += CSG_String::Format(" +pm=%f", d);
1699  }
1700 
1701  Proj4 += CSG_String::Format(" +no_defs"); // Don't use the /usr/share/proj/proj_def.dat defaults file
1702 
1703  return( true );
1704  }
1705 
1706  //-----------------------------------------------------
1707  // PROJCS["<name>,
1708  // GEOGCS ["<name>, ...],
1709  // PROJECTION["<name>"],
1710  // *PARAMETER ["<name>", <value>], PARAMETER...
1711  // UNIT ["<name>", <conversion factor>],
1712  // *AXIS ["<name>", NORTH|SOUTH|EAST|WEST|UP|DOWN|OTHER], AXIS...
1713  // ]
1714  if( m.Cmp_Name("PROJCS") && m("GEOGCS") && m("PROJECTION") && m_WKT1_to_Proj4.Get_Translation(m["PROJECTION"].Get_Content(), Proj4) )
1715  {
1716  if( m["PROJECTION"].Cmp_Content("Transverse_Mercator") ) // UTM ???
1717  {
1718  double Scale = -1., Easting = -1., Northing = -1., Meridian = -1., Latitude = -1.;
1719 
1720  for(int i=0; i<m.Get_Children_Count(); i++)
1721  {
1722  if( m[i].Cmp_Name("PARAMETER") )
1723  {
1724  double v;
1725 
1726  if( m[i].Cmp_Property("name", "central_meridian" , true) && m[i].Get_Content().asDouble(v) ) Meridian = v;
1727  if( m[i].Cmp_Property("name", "latitude_of_origin", true) && m[i].Get_Content().asDouble(v) ) Latitude = v;
1728  if( m[i].Cmp_Property("name", "scale_factor" , true) && m[i].Get_Content().asDouble(v) ) Scale = v;
1729  if( m[i].Cmp_Property("name", "false_easting" , true) && m[i].Get_Content().asDouble(v) ) Easting = v;
1730  if( m[i].Cmp_Property("name", "false_northing" , true) && m[i].Get_Content().asDouble(v) ) Northing = v;
1731  }
1732  }
1733 
1734  if( Latitude == 0. && Scale == 0.9996 && Easting == 500000. && (Northing == 0. || Northing == 10000000.) )
1735  {
1736  Proj4 = "+proj=utm";
1737 
1738  if( !m["GEOGCS"]("DATUM") || !_WKT1_to_Proj4_Set_Datum(Proj4, m["GEOGCS"]["DATUM"]) )
1739  {
1740  return( false );
1741  }
1742 
1743  Proj4 += CSG_String::Format(" +zone=%d", (int)((183. + Meridian) / 6.));
1744 
1745  if( Northing == 10000000. )
1746  {
1747  Proj4 += " +south";
1748  }
1749 
1750  Proj4 += CSG_String::Format(" +no_defs"); // Don't use the /usr/share/proj/proj_def.dat defaults file
1751 
1752  return( true );
1753  }
1754  }
1755 
1756  //-------------------------------------------------
1757  Proj4 = "+proj=" + Proj4;
1758 
1759  if( !m["GEOGCS"]("DATUM") || !_WKT1_to_Proj4_Set_Datum(Proj4, m["GEOGCS"]["DATUM"]) )
1760  {
1761  return( false );
1762  }
1763 
1764  if( m("PRIMEM") && m["PRIMEM"].Get_Content().asDouble(d) && d != 0. )
1765  {
1766  Proj4 += CSG_String::Format(" +pm=%f", d);
1767  }
1768 
1769  for(int i=0; i<m.Get_Children_Count(); i++)
1770  {
1771  if( m[i].Cmp_Name("PARAMETER") )
1772  {
1773  CSG_String Parameter;
1774 
1775  if( m_WKT1_to_Proj4.Get_Translation(m[i].Get_Property("name"), Parameter) )
1776  {
1777  Proj4 += " +" + Parameter + "=" + m[i].Get_Content();
1778  }
1779  else
1780  {
1781  SG_UI_Msg_Add_Error(CSG_String::Format(">> WKT: %s [%s]", _TL("unknown parameter"), m[i].Get_Property("name")));
1782  }
1783  }
1784  }
1785 
1786  if( m("UNIT") && m["UNIT"].Get_Content().asDouble(d) && d != 0. && d != 1. )
1787  {
1788  Proj4 += CSG_String::Format(" +to_meter=%f", d);
1789  }
1790 
1791  Proj4 += CSG_String::Format(" +no_defs"); // Don't use the /usr/share/proj/proj_def.dat defaults file
1792 
1793  return( true );
1794  }
1795 
1796  //-----------------------------------------------------
1797  return( false );
1798 }
1799 
1800 
1802 // //
1804 
1805 //---------------------------------------------------------
1806 bool CSG_Projections::_Proj4_Find_Parameter(const CSG_String &Proj4, const CSG_String &Key)
1807 {
1808  return( Proj4.Find("+" + Key) >= 0 );
1809 }
1810 
1811 //---------------------------------------------------------
1812 bool CSG_Projections::_Proj4_Read_Parameter(CSG_String &Value, const CSG_String &Proj4, const CSG_String &Key)
1813 {
1814  Value.Clear();
1815 
1816  int l, i = Proj4.Find("+" + Key + "=");
1817 
1818  if( i >= 0 )
1819  {
1820  for(++i, l=0; l<2 && i<(int)Proj4.Length(); i++)
1821  {
1822  switch( Proj4[i] )
1823  {
1824  case '=': l++; break;
1825  case '+': l=2; break;
1826  case ' ': l=2; break;
1827  default :
1828  if( l == 1 )
1829  {
1830  Value += Proj4[i];
1831  }
1832  }
1833  }
1834  }
1835 
1836  return( Value.Length() > 0 );
1837 }
1838 
1839 //---------------------------------------------------------
1840 bool CSG_Projections::_Proj4_Get_Ellipsoid(CSG_String &Value, const CSG_String &Proj4)
1841 {
1842  const char ellipsoid[42][2][32] =
1843  { // ellipsoid a, b
1844  { "MERIT" , "6378137.0,298.257" }, // MERIT 1983
1845  { "SGS85" , "6378136.0,298.257" }, // Soviet Geodetic System 85
1846  { "GRS80" , "6378137.0,298.2572221" }, // GRS 1980 (IUGG, 1980)
1847  { "IAU76" , "6378140.0,298.257" }, // IAU 1976
1848  { "airy" , "6377563.396,299.3249753" }, // Airy 1830
1849  { "APL4.9" , "6378137.0,298.25" }, // Appl. Physics. 1965
1850  { "NWL9D" , "6378145.0,298.25" }, // Naval Weapons Lab., 1965
1851  { "mod_airy" , "6377340.189,299.3249374" }, // Modified Airy
1852  { "andrae" , "6377104.43,300" }, // Andrae 1876 (Den., Iclnd.)
1853  { "aust_SA" , "6378160.0,298.25" }, // Australian Natl & S. Amer. 1969
1854  { "GRS67" , "6378160.0,298.2471674" }, // GRS 67 (IUGG 1967)
1855  { "bessel" , "6377397.155,299.1528128" }, // Bessel 1841
1856  { "bess_nam" , "6377483.865,299.1528128" }, // Bessel 1841 (Namibia)
1857  { "clrk66" , "6378206.4,294.9786982" }, // Clarke 1866
1858  { "clrk80" , "6378249.145,293.4663" }, // Clarke 1880 mod.
1859  { "CPM" , "6375738.7,334.29" }, // Comm. des Poids et Mesures 1799
1860  { "delmbr" , "6376428.0,311.5" }, // Delambre 1810 (Belgium)
1861  { "engelis" , "6378136.05,298.2566" }, // Engelis 1985
1862  { "evrst30" , "6377276.345,300.8017" }, // Everest 1830
1863  { "evrst48" , "6377304.063,300.8017" }, // Everest 1948
1864  { "evrst56" , "6377301.243,300.8017" }, // Everest 1956
1865  { "evrst69" , "6377295.664,300.8017" }, // Everest 1969
1866  { "evrstSS" , "6377298.556,300.8017" }, // Everest (Sabah & Sarawak)
1867  { "fschr60" , "6378166.0,298.3" }, // Fischer (Mercury Datum) 1960
1868  { "fschr60m" , "6378155.0,298.3" }, // Modified Fischer 1960
1869  { "fschr68" , "6378150.0,298.3" }, // Fischer 1968
1870  { "helmert" , "6378200.0,298.3" }, // Helmert 1906
1871  { "hough" , "6378270.0,297" }, // Hough
1872  { "intl" , "6378388.0,297" }, // International 1909 (Hayford)
1873  { "krass" , "6378245.0,298.3" }, // Krassovsky, 1942
1874  { "kaula" , "6378163.0,298.24" }, // Kaula 1961
1875  { "lerch" , "6378139.0,298.257" }, // Lerch 1979
1876  { "mprts" , "6397300.0,191" }, // Maupertius 1738
1877  { "new_intl" , "6378157.5,298.2496154" }, // New International 1967
1878  { "plessis" , "6376523.0,308.6409971" }, // Plessis 1817 (France)
1879  { "SEasia" , "6378155.0,298.3000002" }, // Southeast Asia
1880  { "walbeck" , "6376896.0,302.7800002" }, // Walbeck
1881  { "WGS60" , "6378165.0,298.3" }, // WGS 60
1882  { "WGS66" , "6378145.0,298.25" }, // WGS 66
1883  { "WGS72" , "6378135.0,298.26" }, // WGS 72
1884  { "WGS84" , "6378137.0,298.2572236" }, // WGS 84
1885  { "sphere" , "6370997.0,-1" } // Normal Sphere (r=6370997)
1886  };
1887 
1888  //-----------------------------------------------------
1889  if( _Proj4_Read_Parameter(Value, Proj4, "ellps") )
1890  {
1891  for(int i=0; i<42; i++)
1892  {
1893  if( !Value.CmpNoCase(ellipsoid[i][0]) )
1894  {
1895  Value.Printf("SPHEROID[\"%s\",%s]", SG_STR_MBTOSG(ellipsoid[i][0]), SG_STR_MBTOSG(ellipsoid[i][1]));
1896 
1897  return( true );
1898  }
1899  }
1900  }
1901 
1902  //-----------------------------------------------------
1903  double a = _Proj4_Read_Parameter(Value, Proj4, "a" ) && Value.asDouble(a) ? a : 6378137.;
1904 
1905  double b = _Proj4_Read_Parameter(Value, Proj4, "b" ) && Value.asDouble(b) ? a / (a - b)
1906  : _Proj4_Read_Parameter(Value, Proj4, "rf") && Value.asDouble(b) ? b
1907  : _Proj4_Read_Parameter(Value, Proj4, "f" ) && Value.asDouble(b) ? 1. / b
1908  : _Proj4_Read_Parameter(Value, Proj4, "e" ) && Value.asDouble(b) ? a / (a - sqrt(b*b - a*a))
1909  : _Proj4_Read_Parameter(Value, Proj4, "es") && Value.asDouble(b) ? a / (a - sqrt( b - a*a))
1910  : 298.2572236;
1911 
1912  Value = CSG_String::Format("SPHEROID[\"Ellipsoid\",%f,%f]", a, b);
1913 
1914  return( true );
1915 }
1916 
1917 //---------------------------------------------------------
1918 bool CSG_Projections::_Proj4_Get_Datum(CSG_String &Value, const CSG_String &Proj4)
1919 {
1920  const char datum[9][3][64] =
1921  { // datum_id ellipse definition
1922  { "WGS84" , "WGS84" , "0,0,0,0,0,0,0" },
1923  { "GGRS87" , "GRS80" , "-199.87,74.79,246.62,0,0,0,0" }, // Greek_Geodetic_Reference_System_1987
1924  { "NAD83" , "GRS80" , "0,0,0,0,0,0,0" }, // North_American_Datum_1983
1925  // { "NAD27" , "clrk66" , "nadgrids=@conus,@alaska,@ntv2_0.gsb,@ntv1_can.dat" }, // North_American_Datum_1927
1926  { "potsdam" , "bessel" , "606.0,23.0,413.0,0,0,0,0" }, // Potsdam Rauenberg 1950 DHDN
1927  { "carthage" , "clark80" , "-263.0,6.0,431.0,0,0,0,0" }, // Carthage 1934 Tunisia
1928  { "hermannskogel" , "bessel" , "653.0,-212.0,449.0,0,0,0,0" }, // Hermannskogel
1929  { "ire65" , "mod_airy" , "482.530,-130.596,564.557,-1.042,-0.214,-0.631,8.15" }, // Ireland 1965
1930  { "nzgd49" , "intl" , "59.47,-5.04,187.44,0.47,-0.1,1.024,-4.5993" }, // New Zealand Geodetic Datum 1949
1931  { "OSGB36" , "airy" , "446.448,-125.157,542.060,0.1502,0.2470,0.8421,-20.4894" } // Airy 1830
1932  };
1933 
1934  CSG_String Spheroid, ToWGS84;
1935 
1936  //-----------------------------------------------------
1937  if( _Proj4_Read_Parameter(Value, Proj4, "datum") )
1938  {
1939  for(int i=0; i<9; i++)
1940  {
1941  if( !Value.CmpNoCase(datum[i][0]) && _Proj4_Get_Ellipsoid(Spheroid, CSG_String::Format("+ellps=%s", SG_STR_MBTOSG(datum[i][1]))) )
1942  {
1943  Value.Printf("DATUM[\"%s\",%s,TOWGS84[%s]]", SG_STR_MBTOSG(datum[i][0]), Spheroid.c_str(), SG_STR_MBTOSG(datum[i][2]));
1944 
1945  return( true );
1946  }
1947  }
1948  }
1949 
1950  //-----------------------------------------------------
1951  if( _Proj4_Get_Ellipsoid(Spheroid, Proj4) )
1952  {
1953  Value = "DATUM[\"Datum\","+ Spheroid;
1954 
1955  if( _Proj4_Read_Parameter(ToWGS84, Proj4, "towgs84") )
1956  {
1957  CSG_Strings s = SG_String_Tokenize(ToWGS84, ",");
1958 
1959  if( s.Get_Count() == 3 )
1960  {
1961  ToWGS84 += ",0,0,0,0";
1962  }
1963 
1964  Value += ",TOWGS84[" + ToWGS84 + "]";
1965  }
1966  else
1967  {
1968  Value += ",TOWGS84[0,0,0,0,0,0,0]";
1969  }
1970 
1971  Value += "]";
1972 
1973  return( true );
1974  }
1975 
1976  //-----------------------------------------------------
1977  Value = "DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563],TOWGS84[0,0,0,0,0,0,0]]";
1978 
1979  return( false );
1980 }
1981 
1982 //---------------------------------------------------------
1983 bool CSG_Projections::_Proj4_Get_Prime_Meridian(CSG_String &Value, const CSG_String &Proj4)
1984 {
1985  const char meridian[12][2][16] =
1986  {
1987  { "lisbon" , "-9.131906111" },
1988  { "paris" , "2.337229167" },
1989  { "bogota" , "74.08091667" },
1990  { "madrid" , "-3.687911111" },
1991  { "rome" , "12.45233333" },
1992  { "bern" , "7.439583333" },
1993  { "jakarta" , "106.8077194" },
1994  { "ferro" , "-17.66666667" },
1995  { "brussels" , "4.367975" },
1996  { "stockholm" , "18.05827778" },
1997  { "athens" , "23.7163375" },
1998  { "oslo" , "10.72291667" }
1999  };
2000 
2001  //-----------------------------------------------------
2002  if( _Proj4_Read_Parameter(Value, Proj4, "pm") )
2003  {
2004  for(int i=0; i<12; i++)
2005  {
2006  if( !Value.CmpNoCase(meridian[i][0]) )
2007  {
2008  Value.Printf("PRIMEM[\"%s\",%s]", SG_STR_MBTOSG(meridian[i][0]), SG_STR_MBTOSG(meridian[i][1]));
2009 
2010  return( true );
2011  }
2012  }
2013 
2014  double d;
2015 
2016  if( Value.asDouble(d) && d != 0. )
2017  {
2018  Value.Printf("PRIMEM[\"Prime_Meridian\",%f]", d);
2019 
2020  return( true );
2021  }
2022  }
2023 
2024  //-----------------------------------------------------
2025  Value = "PRIMEM[\"Greenwich\",0]";
2026 
2027  return( false );
2028 }
2029 
2030 //---------------------------------------------------------
2031 bool CSG_Projections::_Proj4_Get_Unit(CSG_String &Value, const CSG_String &Proj4)
2032 {
2033  ESG_Projection_Unit Unit = _Proj4_Read_Parameter(Value, Proj4, "units") ? CSG_Projections::Get_Unit(Value) : ESG_Projection_Unit::Undefined;
2034 
2035  if( Unit != ESG_Projection_Unit::Undefined )
2036  {
2037  Value = "UNIT[\"" + CSG_Projections::Get_Unit_Name(Unit) + "\"," + SG_Get_String(CSG_Projections::Get_Unit_To_Meter(Unit), -16) + "]";
2038 
2039  return( true );
2040  }
2041 
2042  //-----------------------------------------------------
2043  double d;
2044 
2045  if( _Proj4_Read_Parameter(Value, Proj4, "to_meter") && Value.asDouble(d) && d > 0. && d != 1. )
2046  {
2047  Value.Printf("UNIT[\"Unit\",%f]", d);
2048 
2049  return( true );
2050  }
2051 
2052  //-----------------------------------------------------
2053  Value = "UNIT[\"metre\",1]";
2054 // Value = "UNIT[\"degree\",0.01745329251994328]]";
2055 
2056  return( false );
2057 }
2058 
2059 //---------------------------------------------------------
2060 bool CSG_Projections::_WKT1_from_Proj4(CSG_String &WKT, const CSG_String &Proj4) const
2061 {
2062  CSG_String Value, ProjCS;
2063 
2064  //-----------------------------------------------------
2065  if( !_Proj4_Read_Parameter(ProjCS, Proj4, "proj") )
2066  {
2067  SG_UI_Msg_Add_Error(CSG_String::Format("Proj4 >> WKT: %s", _TL("no projection type defined")));
2068 
2069  return( false );
2070  }
2071 
2072  //-----------------------------------------------------
2073  // GEOCCS["<name>
2074  // DATUM ["<name>
2075  // SPHEROID["<name>", <semi-major axis>, <inverse flattening>],
2076  // *TOWGS84 [<dx>, <dy>, <dz>, <rx>, <ry>, <rz>, <sc>]
2077  // ],
2078  // PRIMEM ["<name>", <longitude>],
2079  // UNIT ["<name>", <conversion factor>],
2080  // *AXIS ["<name>", NORTH|SOUTH|EAST|WEST|UP|DOWN|OTHER],
2081  // *AXIS ["<name>", NORTH|SOUTH|EAST|WEST|UP|DOWN|OTHER]
2082  // ]
2083 
2084  if( !ProjCS.CmpNoCase("geocent") )
2085  {
2086  WKT = "GEOGCS[\"GCS\"";
2087 
2088  if( _Proj4_Get_Datum (Value, Proj4) ) { WKT += "," + Value; }
2089  if( _Proj4_Get_Prime_Meridian(Value, Proj4) ) { WKT += "," + Value; }
2090  if( _Proj4_Get_Unit (Value, Proj4) ) { WKT += "," + Value; }
2091 
2092  WKT += "]";
2093 
2094  return( true );
2095  }
2096 
2097  //-----------------------------------------------------
2098  // GEOGCS["<name>
2099  // DATUM ["<name>
2100  // SPHEROID["<name>", <semi-major axis>, <inverse flattening>],
2101  // *TOWGS84 [<dx>, <dy>, <dz>, <rx>, <ry>, <rz>, <sc>]
2102  // ],
2103  // PRIMEM ["<name>", <longitude>],
2104  // UNIT ["<name>", <conversion factor>],
2105  // *AXIS ["<name>", NORTH|SOUTH|EAST|WEST|UP|DOWN|OTHER],
2106  // *AXIS ["<name>", NORTH|SOUTH|EAST|WEST|UP|DOWN|OTHER]
2107  // ]
2108 
2109  CSG_String GeogCS = "GEOGCS[\"GCS\"";
2110 
2111  if( _Proj4_Get_Datum (Value, Proj4) ) { GeogCS += "," + Value; }
2112  if( _Proj4_Get_Prime_Meridian(Value, Proj4) ) { GeogCS += "," + Value; }
2113  if( _Proj4_Get_Unit (Value, Proj4) ) { GeogCS += "," + Value; } else { GeogCS += "UNIT[\"degree\",0.01745329251994328]"; }
2114 
2115  GeogCS += "]";
2116 
2117  if( !ProjCS.CmpNoCase("lonlat") || !ProjCS.CmpNoCase("longlat")
2118  || !ProjCS.CmpNoCase("latlon") || !ProjCS.CmpNoCase("latlong") )
2119  {
2120  WKT = GeogCS;
2121 
2122  return( true );
2123  }
2124 
2125  //-----------------------------------------------------
2126  // PROJCS["<name>
2127  // GEOGCS [ ...... ],
2128  // PROJECTION["<name>"],
2129  // *PARAMETER ["<name>", <value>], ...
2130  // UNIT ["<name>", <conversion factor>],
2131  // *AXIS ["<name>", NORTH|SOUTH|EAST|WEST|UP|DOWN|OTHER],
2132  // *AXIS ["<name>", NORTH|SOUTH|EAST|WEST|UP|DOWN|OTHER]
2133  // ]
2134 
2135  if( !m_Proj4_to_WKT1.Get_Translation(ProjCS, Value) )
2136  {
2137  SG_UI_Msg_Add_Error(CSG_String::Format("Proj4 >> WKT: %s [%s]", _TL("no translation available"), ProjCS.c_str()));
2138 
2139  // return( false );
2140  }
2141 
2142  //-----------------------------------------------------
2143  // UTM ...
2144 
2145  if( !ProjCS.CmpNoCase("utm") )
2146  {
2147  double Zone;
2148 
2149  if( !_Proj4_Read_Parameter(Value, Proj4, "zone") || !Value.asDouble(Zone) )
2150  {
2151  SG_UI_Msg_Add_Error(CSG_String::Format("Proj4 >> WKT: %s", _TL("invalid utm zone")));
2152 
2153  return( false );
2154  }
2155 
2156  bool South = _Proj4_Find_Parameter(Proj4, "south");
2157 
2158  WKT = CSG_String::Format("PROJCS[\"UTM zone %d%c\",%s,PROJECTION[Transverse_Mercator]", (int)Zone, South ? 'S' : 'N', GeogCS.c_str());
2159 
2160  WKT += CSG_String::Format(",PARAMETER[\"%s\",%d]", SG_T("latitude_of_origin"), 0);
2161  WKT += CSG_String::Format(",PARAMETER[\"%s\",%d]", SG_T("central_meridian" ), (int)(Zone * 6 - 183));
2162  WKT += CSG_String::Format(",PARAMETER[\"%s\",%f]", SG_T("scale_factor" ), 0.9996);
2163  WKT += CSG_String::Format(",PARAMETER[\"%s\",%d]", SG_T("false_easting" ), 500000);
2164  WKT += CSG_String::Format(",PARAMETER[\"%s\",%d]", SG_T("false_northing" ), South ? 10000000 : 0);
2165  WKT += ",UNIT[\"metre\",1]]";
2166 
2167  return( true );
2168  }
2169 
2170  //-----------------------------------------------------
2171  // Parameters ...
2172 
2173  WKT = CSG_String::Format("PROJCS[\"%s\",%s,PROJECTION[%s]", Value.c_str(), GeogCS.c_str(), Value.c_str());
2174 
2175  ProjCS = Proj4;
2176 
2177  while( ProjCS.Find('+') >= 0 )
2178  {
2179  CSG_String Key;
2180 
2181  ProjCS = ProjCS.AfterFirst ('+');
2182  Value = ProjCS.BeforeFirst('=');
2183 
2184  if( m_Proj4_to_WKT1.Get_Translation(Value, Key) )
2185  {
2186  Value = ProjCS.AfterFirst('=');
2187 
2188  if( Value.Find('+') >= 0 )
2189  {
2190  Value = Value.BeforeFirst('+');
2191  }
2192 
2193  WKT += ",PARAMETER[\"" + Key + "\"," + Value + "]";
2194  }
2195  }
2196 
2197  //-----------------------------------------------------
2198  // Unit ...
2199 
2200  if( _Proj4_Get_Unit(Value, Proj4) ) { WKT += "," + Value; }
2201 
2202  //-----------------------------------------------------
2203  WKT += "]";
2204 
2205  return( true );
2206 }
2207 
2208 
2210 // //
2211 // //
2212 // //
2214 
2215 //---------------------------------------------------------
2217 {
2218  if( !Identifier.CmpNoCase("PROJCS") || !Identifier.CmpNoCase("PROJCRS") ) { return( ESG_CRS_Type::Projection ); }
2219  if( !Identifier.CmpNoCase("GEOGCS") || !Identifier.CmpNoCase("GEOGCRS") ) { return( ESG_CRS_Type::Geographic ); }
2220  if( !Identifier.CmpNoCase("GEOCCS") || !Identifier.CmpNoCase("GEOCCRS") ) { return( ESG_CRS_Type::Geocentric ); }
2221  if( !Identifier.CmpNoCase("GEODCS") || !Identifier.CmpNoCase("GEODCRS") ) { return( ESG_CRS_Type::Geodetic ); }
2222 
2223  return( ESG_CRS_Type::Undefined );
2224 }
2225 
2226 //---------------------------------------------------------
2228 {
2229  switch( Type )
2230  {
2231  case ESG_CRS_Type::Projection: return( "PROJCRS" );
2232  case ESG_CRS_Type::Geographic: return( "GEOGCRS" );
2233  case ESG_CRS_Type::Geocentric: return( "GEOCCRS" );
2234  case ESG_CRS_Type::Geodetic : return( "GEODCRS" );
2235  default : return( "UNDEFINED" );
2236  }
2237 }
2238 
2239 //---------------------------------------------------------
2241 {
2242  switch( Type )
2243  {
2244  case ESG_CRS_Type::Projection: return( _TL("Projected Coordinate System" ) );
2245  case ESG_CRS_Type::Geographic: return( _TL("Geographic Coordinate System") );
2246  case ESG_CRS_Type::Geocentric: return( _TL("Geocentric Coordinate System") );
2247  case ESG_CRS_Type::Geodetic : return( _TL("Geodetic Coordinate System" ) );
2248  default : return( _TL("Unknown Coordinate System" ) );
2249  }
2250 }
2251 
2252 //---------------------------------------------------------
2254 {
2255  for(int i=0; i<(int)ESG_Projection_Unit::Undefined; i++)
2256  {
2258 
2259  if( !Identifier.CmpNoCase(Get_Unit_Identifier(Unit))
2260  || !Identifier.CmpNoCase(Get_Unit_Name (Unit)) )
2261  {
2262  return( Unit );
2263  }
2264  }
2265 
2266  return( !Identifier.CmpNoCase("metre") ? ESG_Projection_Unit::Meter : ESG_Projection_Unit::Undefined );
2267 }
2268 
2269 //---------------------------------------------------------
2271 {
2272  switch( Unit )
2273  {
2274  case ESG_Projection_Unit::Kilometer : return( "km" ); // Kilometers
2275  case ESG_Projection_Unit::Meter : return( "m" ); // Meters
2276  case ESG_Projection_Unit::Decimeter : return( "dm" ); // Decimeters
2277  case ESG_Projection_Unit::Centimeter : return( "cm" ); // Centimeters
2278  case ESG_Projection_Unit::Millimeter : return( "mm" ); // Millimeters
2279  case ESG_Projection_Unit::Int_Nautical_Mile: return( "kmi" ); // Miles
2280  case ESG_Projection_Unit::Int_Inch : return( "in" ); // Inches
2281  case ESG_Projection_Unit::Int_Foot : return( "ft" ); // Feet
2282  case ESG_Projection_Unit::Int_Yard : return( "yd" ); // Yards
2283  case ESG_Projection_Unit::Int_Statute_Mile : return( "mi" ); // Miles
2284  case ESG_Projection_Unit::Int_Fathom : return( "fath" ); // Fathoms
2285  case ESG_Projection_Unit::Int_Chain : return( "ch" ); // Chains
2286  case ESG_Projection_Unit::Int_Link : return( "link" ); // Links
2287  case ESG_Projection_Unit::US_Inch : return( "us-in" ); // Inches
2288  case ESG_Projection_Unit::US_Foot : return( "us-ft" ); // Feet
2289  case ESG_Projection_Unit::US_Yard : return( "us-yd" ); // Yards
2290  case ESG_Projection_Unit::US_Chain : return( "us-ch" ); // Chains
2291  case ESG_Projection_Unit::US_Statute_Mile : return( "us-mi" ); // Miles
2292  case ESG_Projection_Unit::Indian_Yard : return( "ind-yd" ); // Yards
2293  case ESG_Projection_Unit::Indian_Foot : return( "ind-ft" ); // Feet
2294  case ESG_Projection_Unit::Indian_Chain : return( "ind-ch" ); // Chains
2295  default: return( "" );
2296  };
2297 }
2298 
2299 //---------------------------------------------------------
2301 {
2302  switch( Unit )
2303  {
2304  case ESG_Projection_Unit::Kilometer : return( bSimple ? "Kilometers" : "Kilometer" );
2305  case ESG_Projection_Unit::Meter : return( bSimple ? "Meters" : "Meter" );
2306  case ESG_Projection_Unit::Decimeter : return( bSimple ? "Decimeters" : "Decimeter" );
2307  case ESG_Projection_Unit::Centimeter : return( bSimple ? "Centimeters" : "Centimeter" );
2308  case ESG_Projection_Unit::Millimeter : return( bSimple ? "Millimeters" : "Millimeter" );
2309  case ESG_Projection_Unit::Int_Nautical_Mile: return( bSimple ? "Miles" : "International Nautical Mile" );
2310  case ESG_Projection_Unit::Int_Inch : return( bSimple ? "Inches" : "International Inch" );
2311  case ESG_Projection_Unit::Int_Foot : return( bSimple ? "Feet" : "International Foot" );
2312  case ESG_Projection_Unit::Int_Yard : return( bSimple ? "Yards" : "International Yard" );
2313  case ESG_Projection_Unit::Int_Statute_Mile : return( bSimple ? "Miles" : "International Statute Mile" );
2314  case ESG_Projection_Unit::Int_Fathom : return( bSimple ? "Fathoms" : "International Fathom" );
2315  case ESG_Projection_Unit::Int_Chain : return( bSimple ? "Chains" : "International Chain" );
2316  case ESG_Projection_Unit::Int_Link : return( bSimple ? "Links" : "International Link" );
2317  case ESG_Projection_Unit::US_Inch : return( bSimple ? "Inches" : "U.S. Surveyor's Inch" );
2318  case ESG_Projection_Unit::US_Foot : return( bSimple ? "Feet" : "U.S. Surveyor's Foot" );
2319  case ESG_Projection_Unit::US_Yard : return( bSimple ? "Yards" : "U.S. Surveyor's Yard" );
2320  case ESG_Projection_Unit::US_Chain : return( bSimple ? "Chains" : "U.S. Surveyor's Chain" );
2321  case ESG_Projection_Unit::US_Statute_Mile : return( bSimple ? "Miles" : "U.S. Surveyor's Statute Mile" );
2322  case ESG_Projection_Unit::Indian_Yard : return( bSimple ? "Yards" : "Indian Yard" );
2323  case ESG_Projection_Unit::Indian_Foot : return( bSimple ? "Feet" : "Indian Foot" );
2324  case ESG_Projection_Unit::Indian_Chain : return( bSimple ? "Chains" : "Indian Chain" );
2325  default: return( "" );
2326  }
2327 }
2328 
2329 //---------------------------------------------------------
2331 {
2332  switch( Unit )
2333  {
2334  case ESG_Projection_Unit::Kilometer : return( 1000. );
2335  case ESG_Projection_Unit::Meter : return( 1. );
2336  case ESG_Projection_Unit::Decimeter : return( 0.1 );
2337  case ESG_Projection_Unit::Centimeter : return( 0.01 );
2338  case ESG_Projection_Unit::Millimeter : return( 0.001 );
2339  case ESG_Projection_Unit::Int_Nautical_Mile: return( 1852. );
2340  case ESG_Projection_Unit::Int_Inch : return( 0.0254 );
2341  case ESG_Projection_Unit::Int_Foot : return( 0.3048 );
2342  case ESG_Projection_Unit::Int_Yard : return( 0.9144 );
2343  case ESG_Projection_Unit::Int_Statute_Mile : return( 1609.344 );
2344  case ESG_Projection_Unit::Int_Fathom : return( 1.8288 );
2345  case ESG_Projection_Unit::Int_Chain : return( 20.1168 );
2346  case ESG_Projection_Unit::Int_Link : return( 0.201168 );
2347  case ESG_Projection_Unit::US_Inch : return( 1. / 39.37 );
2348  case ESG_Projection_Unit::US_Foot : return( 0.304800609601219 );
2349  case ESG_Projection_Unit::US_Yard : return( 0.914401828803658 );
2350  case ESG_Projection_Unit::US_Chain : return( 20.11684023368047 );
2351  case ESG_Projection_Unit::US_Statute_Mile : return( 1609.347218694437 );
2352  case ESG_Projection_Unit::Indian_Yard : return( 0.91439523 );
2353  case ESG_Projection_Unit::Indian_Foot : return( 0.30479841 );
2354  case ESG_Projection_Unit::Indian_Chain : return( 20.11669506 );
2355  default : return( 1. );
2356  }
2357 }
2358 
2359 
2361 // //
2362 // //
2363 // //
2365 
2366 //---------------------------------------------------------
2367 bool CSG_Projections::_Set_Dictionary(CSG_Table &Dictionary, int Direction)
2368 {
2369  const char Translation[][4][128] = {
2370 // { PROJ4 , DIR , WELL-KNOWN-TEXT , DESCRIPTION, *) projection type not verified
2371 
2372 // --- projection types ---
2373  { "aea" , " ", "Albers_Conic_Equal_Area" , "Albers Equal Area" },
2374  { "aea" , "<", "Albers" , "[ESRI] Albers Equal Area" },
2375  { "aeqd" , " ", "Azimuthal_Equidistant" , "Azimuthal Equidistant" },
2376  { "airy" , " ", "Airy 1830" , "Airy 1830" },
2377  { "aitoff" , " ", "Sphere_Aitoff" , "Aitoff" },
2378  { "alsk" , " ", "Mod_Stererographics_of_Alaska" , "*) Mod. Stererographics of Alaska" },
2379  { "Amersfoort" , "<", "D_Amersfoort" , "[ESRI] datum RD_NEW" },
2380  { "Amersfoort" , "<", "GCS_Amersfoort" , "[ESRI] GCS RD_NEW" },
2381  { "Amersfoort / RD New", "<", "Amersfoort_RD_New" , "[ESRI] RD_NEW" },
2382  { "apian" , " ", "Apian_Globular_I" , "*) Apian Globular I" },
2383  { "august" , " ", "August_Epicycloidal" , "*) August Epicycloidal" },
2384  { "bacon" , " ", "Bacon_Globular" , "*) Bacon Globular" },
2385  { "bipc" , " ", "Bipolar_conic_of_western_hemisphere" , "*) Bipolar conic of western hemisphere" },
2386  { "boggs" , " ", "Boggs_Eumorphic" , "*) Boggs Eumorphic" },
2387  { "bonne" , " ", "Bonne" , "Bonne (Werner lat_1=90)" },
2388  { "cass" , " ", "Cassini_Soldner" , "Cassini" },
2389  { "cass" , "<", "Cassini" , "[ESRI] Cassini" },
2390  { "cc" , " ", "Central_Cylindrical" , "*) Central Cylindrical" },
2391  { "cea" , " ", "Cylindrical_Equal_Area" , "Equal Area Cylindrical, alias: Lambert Cyl.Eq.A., Normal Authalic Cyl. (FME), Behrmann (SP=30), Gall Orthogr. (SP=45)" },
2392  { "cea" , "<", "Behrmann" , "[ESRI] Behrmann (standard parallel = 30)" },
2393  { "chamb" , " ", "Chamberlin_Trimetric" , "*) Chamberlin Trimetric" },
2394  { "collg" , " ", "Collignon" , "*) Collignon" },
2395  { "crast" , " ", "Craster_Parabolic" , "[ESRI] Craster Parabolic (Putnins P4)" },
2396  { "denoy" , " ", "Denoyer_Semi_Elliptical" , "*) Denoyer Semi-Elliptical" },
2397  { "eck1" , " ", "Eckert_I" , "*) Eckert I" },
2398  { "eck2" , " ", "Eckert_II" , "*) Eckert II" },
2399  { "eck3" , " ", "Eckert_III" , "*) Eckert III" },
2400  { "eck4" , " ", "Eckert_IV" , "Eckert IV" },
2401  { "eck5" , " ", "Eckert_V" , "*) Eckert V" },
2402  { "eck6" , " ", "Eckert_VI" , "Eckert VI" },
2403  { "eqearth" , " ", "Equal_Earth" , "*) Equal Earth" },
2404  { "eqc" , " ", "Equirectangular" , "Equidistant Cylindrical (Plate Caree)" },
2405  { "eqc" , "<", "Equidistant_Cylindrical" , "[ESRI] Equidistant Cylindrical (Plate Caree)" },
2406  { "eqc" , "<", "Plate_Carree" , "[ESRI] Equidistant Cylindrical (Plate Caree)" },
2407  { "eqdc" , " ", "Equidistant_Conic" , "*) Equidistant Conic" },
2408  { "euler" , " ", "Euler" , "*) Euler" },
2409  { "etmerc" , " ", "Extended_Transverse_Mercator" , "*) Extended Transverse Mercator" },
2410  { "fahey" , " ", "Fahey" , "*) Fahey" },
2411  { "fouc" , " ", "Foucault" , "*) Foucaut" },
2412  { "fouc_s" , " ", "Foucault_Sinusoidal" , "*) Foucaut Sinusoidal" },
2413  { "gall" , " ", "Gall_Stereographic" , "Gall (Gall Stereographic)" },
2414  { "geocent" , " ", "Geocentric" , "*) Geocentric" },
2415  { "geos" , " ", "GEOS" , "Geostationary Satellite View" },
2416  { "gins8" , " ", "Ginsburg_VIII" , "*) Ginsburg VIII (TsNIIGAiK)" },
2417  { "gn_sinu" , " ", "General_Sinusoidal_Series" , "*) General Sinusoidal Series" },
2418  { "gnom" , " ", "Gnomonic" , "Gnomonic" },
2419  { "goode" , " ", "Goode_Homolosine" , "*) Goode Homolosine" },
2420  { "gs48" , " ", "Mod_Stererographics_48" , "*) Mod. Stererographics of 48 U.S." },
2421  { "gs50" , " ", "Mod_Stererographics_50" , "*) Mod. Stererographics of 50 U.S." },
2422  { "hammer" , " ", "Hammer_Eckert_Greifendorff" , "*) Hammer & Eckert-Greifendorff" },
2423  { "hatano" , " ", "Hatano_Asymmetrical_Equal_Area" , "*) Hatano Asymmetrical Equal Area" },
2424  { "igh" , " ", "Interrupted_Goodes_Homolosine" , "*) Interrupted Goode's Homolosine" },
2425  { "igh_o" , " ", "Interrupted_Goodes_Homolosine_Ocean" , "*) Interrupted Goode's Homolosine (Ocean)" },
2426  { "imw_p" , " ", "International_Map_of_the_World_Polyconic" , "*) International Map of the World Polyconic" },
2427  { "kav5" , " ", "Kavraisky_V" , "*) Kavraisky V" },
2428  { "kav7" , " ", "Kavraisky_VII" , "*) Kavraisky VII" },
2429  { "krovak" , " ", "Krovak" , "Krovak" },
2430  { "labrd" , " ", "Laborde_Oblique_Mercator" , "*) Laborde" },
2431  { "laea" , " ", "Lambert_Azimuthal_Equal_Area" , "Lambert Azimuthal Equal Area" },
2432  { "lagrng" , " ", "Lagrange" , "*) Lagrange" },
2433  { "larr" , " ", "Larrivee" , "*) Larrivee" },
2434  { "lask" , " ", "Laskowski" , "*) Laskowski" },
2435  { "lcc" , "<", "Lambert_Conformal_Conic_1SP" , "Lambert Conformal Conic (1 standard parallel)" },
2436  { "lcc" , "<", "Lambert_Conformal_Conic_2SP" , "Lambert Conformal Conic (2 standard parallels)" },
2437  { "lcc" , " ", "Lambert_Conformal_Conic" , "Lambert Conformal Conic" },
2438  { "lcca" , " ", "Lambert_Conformal_Conic_Alternative" , "*) Lambert Conformal Conic Alternative" },
2439  { "leac" , " ", "Lambert_Equal_Area_Conic" , "*) Lambert Equal Area Conic" },
2440  { "lee_os" , " ", "Lee_Oblated_Stereographic" , "*) Lee Oblated Stereographic" },
2441  { "loxim" , " ", "Loximuthal" , "[ESRI] Loximuthal" },
2442  { "lsat" , " ", "Space_oblique_for_LANDSAT" , "*) Space oblique for LANDSAT" },
2443  { "mbt_s" , " ", "McBryde_Thomas_Flat_Polar_Sine" , "*) McBryde-Thomas Flat-Polar Sine" },
2444  { "mbt_fps" , " ", "McBryde_Thomas_Flat_Polar_Sine_2" , "*) McBryde-Thomas Flat-Pole Sine (No. 2)" },
2445  { "mbtfpp" , " ", "McBryde_Thomas_Flat_Polar_Parabolic" , "*) McBride-Thomas Flat-Polar Parabolic" },
2446  { "mbtfpq" , " ", "Flat_Polar_Quartic" , "[ESRI] McBryde-Thomas Flat-Polar Quartic" },
2447  { "mbtfps" , " ", "McBryde_Thomas_Flat_Polar_Sinusoidal" , "*) McBryde-Thomas Flat-Polar Sinusoidal" },
2448  { "merc" , " ", "Mercator" , "[ESRI] Mercator" },
2449  { "merc" , "<", "Mercator_1SP" , "Mercator (1 standard parallel)" },
2450  { "merc" , "<", "Mercator_2SP" , "Mercator (2 standard parallels)" },
2451  { "mil_os" , " ", "Miller_Oblated_Stereographic" , "*) Miller Oblated Stereographic" },
2452  { "mill" , " ", "Miller_Cylindrical" , "Miller Cylindrical" },
2453  { "moll" , " ", "Mollweide" , "Mollweide" },
2454  { "murd1" , " ", "Murdoch_I" , "*) Murdoch I" },
2455  { "murd2" , " ", "Murdoch_II" , "*) Murdoch II" },
2456  { "murd3" , " ", "Murdoch_III" , "*) Murdoch III" },
2457  { "nell" , " ", "Nell" , "*) Nell" },
2458  { "nell_h" , " ", "Nell_Hammer" , "*) Nell-Hammer" },
2459  { "nicol" , " ", "Nicolosi_Globular" , "*) Nicolosi Globular" },
2460  { "nsper" , " ", "Near_sided_perspective" , "*) Near-sided perspective" },
2461  { "nzmg" , " ", "New_Zealand_Map_Grid" , "New Zealand Map Grid" },
2462  { "ob_tran" , " ", "General_Oblique_Transformation" , "*) General Oblique Transformation" },
2463  { "ocea" , " ", "Oblique_Cylindrical_Equal_Area" , "*) Oblique Cylindrical Equal Area" },
2464  { "oea" , " ", "Oblated_Equal_Area" , "*) Oblated Equal Area" },
2465  { "omerc" , " ", "Hotine_Oblique_Mercator" , "Oblique Mercator" },
2466  { "omerc" , "<", "Oblique_Mercator" , "Oblique Mercator" },
2467  { "ortel" , " ", "Ortelius_Oval" , "*) Ortelius Oval" },
2468  { "ortho" , " ", "Orthographic" , "Orthographic (ESRI: World from Space)" },
2469  { "pconic" , " ", "Perspective_Conic" , "*) Perspective Conic" },
2470  { "poly" , " ", "Polyconic" , "*) Polyconic (American)" },
2471  { "putp1" , " ", "Putnins_P1" , "*) Putnins P1" },
2472  { "putp2" , " ", "Putnins_P2" , "*) Putnins P2" },
2473  { "putp3" , " ", "Putnins_P3" , "*) Putnins P3" },
2474  { "putp3p" , " ", "Putnins_P3'" , "*) Putnins P3'" },
2475  { "putp4p" , " ", "Putnins_P4'" , "*) Putnins P4'" },
2476  { "putp5" , " ", "Putnins_P5" , "*) Putnins P5" },
2477  { "putp5p" , " ", "Putnins_P5'" , "*) Putnins P5'" },
2478  { "putp6" , " ", "Putnins_P6" , "*) Putnins P6" },
2479  { "putp6p" , " ", "Putnins_P6'" , "*) Putnins P6'" },
2480  { "qua_aut" , " ", "Quartic_Authalic" , "[ESRI] Quart c Authalic" },
2481  { "robin" , " ", "Robinson" , "Robinson" },
2482  { "rouss" , " ", "Roussilhe_Stereographic" , "*) Roussilhe Stereographic" },
2483  { "rpoly" , " ", "Rectangular_Polyconic" , "*) Rectangular Polyconic" },
2484  { "sinu" , " ", "Sinusoidal" , "Sinusoidal (Sanson-Flamsteed)" },
2485  { "somerc" , " ", "Hotine_Oblique_Mercator" , "Swiss Oblique Mercator" },
2486  { "somerc" , "<", "Swiss_Oblique_Cylindrical" , "Swiss Oblique Cylindrical" },
2487  { "somerc" , "<", "Hotine_Oblique_Mercator_Azimuth_Center" , "[ESRI] Swiss Oblique Mercator/Cylindrical" },
2488  { "stere" , "<", "Polar_Stereographic" , "Stereographic" },
2489  { "stere" , " ", "Stereographic" , "[ESRI] Stereographic" },
2490  { "sterea" , " ", "Oblique_Stereographic" , "Oblique Stereographic Alternative" },
2491  { "sterea" , "<", "Double_Stereographic" , "[ESRI]" },
2492  { "gstmerc" , " ", "Gauss_Schreiber_Transverse_Mercator" , "*) Gauss-Schreiber Transverse Mercator (aka Gauss-Laborde Reunion)" },
2493  { "tcc" , " ", "Transverse_Central_Cylindrical" , "*) Transverse Central Cylindrical" },
2494  { "tcea" , " ", "Transverse_Cylindrical_Equal_Area" , "*) Transverse Cylindrical Equal Area" },
2495  { "tissot" , " ", "Tissot_Conic" , "*) Tissot Conic" },
2496  { "tmerc" , " ", "Transverse_Mercator" , "*) Transverse Mercator" },
2497  { "tmerc" , "<", "Gauss_Kruger" , "[ESRI] DHDN" },
2498  { "tpeqd" , " ", "Two_Point_Equidistant" , "*) Two Point Equidistant" },
2499  { "tpers" , " ", "Tilted_perspective" , "*) Tilted perspective" },
2500  { "ups" , " ", "Universal_Polar_Stereographic" , "*) Universal Polar Stereographic" },
2501  { "urm5" , " ", "Urmaev_V" , "*) Urmaev V" },
2502  { "urmfps" , " ", "Urmaev_Flat_Polar_Sinusoidal" , "*) Urmaev Flat-Polar Sinusoidal" },
2503  { "utm" , ">", "Transverse_Mercator" , "*) Universal Transverse Mercator (UTM)" },
2504  { "vandg" , "<", "Van_Der_Grinten_I" , "[ESRI] van der Grinten (I)" },
2505  { "vandg" , " ", "VanDerGrinten" , "van der Grinten (I)" },
2506  { "vandg2" , " ", "VanDerGrinten_II" , "*) van der Grinten II" },
2507  { "vandg3" , " ", "VanDerGrinten_III" , "*) van der Grinten III" },
2508  { "vandg4" , " ", "VanDerGrinten_IV" , "*) van der Grinten IV" },
2509  { "vitk1" , " ", "Vitkovsky_I" , "*) Vitkovsky I" },
2510  { "wag1" , " ", "Wagner_I" , "*) Wagner I (Kavraisky VI)" },
2511  { "wag2" , " ", "Wagner_II" , "*) Wagner II" },
2512  { "wag3" , " ", "Wagner_III" , "*) Wagner III" },
2513  { "wag4" , " ", "Wagner_IV" , "*) Wagner IV" },
2514  { "wag5" , " ", "Wagner_V" , "*) Wagner V" },
2515  { "wag6" , " ", "Wagner_VI" , "*) Wagner VI" },
2516  { "wag7" , " ", "Wagner_VII" , "*) Wagner VII" },
2517  { "webmerc" , " ", "Mercator_1SP" , "Web Mercator" },
2518  { "webmerc" , "<", "Mercator_Auxiliary_Sphere" , "[ESRI] Web Mercator" },
2519  { "weren" , " ", "Werenskiold_I" , "*) Werenskiold I" },
2520  { "wink1" , " ", "Winkel_I" , "[ESRI] Winkel I" },
2521  { "wink2" , " ", "Winkel_II" , "[ESRI] Winkel II" },
2522  { "wintri" , " ", "Winkel_Tripel" , "[ESRI] Winkel Tripel" },
2523 
2524 // --- general projection parameters ---
2525  { "alpha" , " ", "azimuth" , "? Used with Oblique Mercator and possibly a few others" },
2526  { "k" , ">", "scale_factor" , "Scaling factor (old name)" },
2527  { "K" , ">", "scale_factor" , "? Scaling factor (old name)" },
2528  { "k_0" , " ", "scale_factor" , "Scaling factor (new name)" },
2529  { "lat_0" , " ", "latitude_of_origin" , "Latitude of origin" },
2530  { "lat_0" , "<", "latitude_of_center" , "Latitude of center" },
2531  { "lat_0" , "<", "central_parallel" , "[ESRI] Latitude of center" },
2532  { "lat_1" , " ", "standard_parallel_1" , "Latitude of first standard parallel" },
2533  { "lat_2" , " ", "standard_parallel_2" , "Latitude of second standard parallel" },
2534  { "lat_ts" , ">", "latitude_of_origin" , "Latitude of true scale" },
2535  { "lon_0" , " ", "central_meridian" , "Central meridian" },
2536  { "lon_0" , "<", "longitude_of_center" , "Longitude of center" },
2537  { "lonc" , ">", "longitude_of_center" , "? Longitude used with Oblique Mercator and possibly a few others" },
2538  { "x_0" , " ", "false_easting" , "False easting" },
2539  { "y_0" , " ", "false_northing" , "False northing" },
2540 
2541 // --- special projection parameters ---
2542 // { "azi" , " ", "", "" },
2543 // { "belgium" , " ", "", "" },
2544 // { "beta" , " ", "", "" },
2545 // { "czech" , " ", "", "" },
2546 // { "gamma" , " ", "", "" },
2547 // { "geoc" , " ", "", "" },
2548 // { "guam" , " ", "", "" },
2549  { "h" , " ", "satellite_height", "Satellite height (geos - Geostationary Satellite View)" },
2550 // { "lat_b" , " ", "", "" },
2551 // { "lat_t" , " ", "", "" },
2552 // { "lon_1" , " ", "", "" },
2553 // { "lon_2" , " ", "", "" },
2554 // { "lsat" , " ", "", "" },
2555 // { "m" , " ", "", "" },
2556 // { "M" , " ", "", "" },
2557 // { "n" , " ", "", "" },
2558 // { "no_cut" , " ", "", "" },
2559 // { "no_off" , " ", "", "" },
2560 // { "no_rot" , " ", "", "" },
2561 // { "ns" , " ", "", "" },
2562 // { "o_alpha" , " ", "", "" },
2563 // { "o_lat_1" , " ", "", "" },
2564 // { "o_lat_2" , " ", "", "" },
2565 // { "o_lat_c" , " ", "", "" },
2566 // { "o_lat_p" , " ", "", "" },
2567 // { "o_lon_1" , " ", "", "" },
2568 // { "o_lon_2" , " ", "", "" },
2569 // { "o_lon_c" , " ", "", "" },
2570 // { "o_lon_p" , " ", "", "" },
2571 // { "o_proj" , " ", "", "" },
2572 // { "over" , " ", "", "" },
2573 // { "p" , " ", "", "" },
2574 // { "path" , " ", "", "" },
2575 // { "q" , " ", "", "" },
2576 // { "R" , " ", "", "" },
2577 // { "R_a" , " ", "", "" },
2578 // { "R_A" , " ", "", "" },
2579 // { "R_g" , " ", "", "" },
2580 // { "R_h" , " ", "", "" },
2581 // { "R_lat_a" , " ", "", "" },
2582 // { "R_lat_g" , " ", "", "" },
2583 // { "rot" , " ", "", "" },
2584 // { "R_V" , " ", "", "" },
2585 // { "s" , " ", "", "" },
2586 // { "sym" , " ", "", "" },
2587 // { "t" , " ", "", "" },
2588 // { "theta" , " ", "", "" },
2589 // { "tilt" , " ", "", "" },
2590 // { "vopt" , " ", "", "" },
2591 // { "W" , " ", "", "" },
2592 // { "westo" , " ", "", "" },
2593 
2594 // --- core projection types and parameters that don't require explicit translation ---
2595 // { "lonlat" , " ", "GEOGCS", "Lat/long (Geodetic)" },
2596 // { "latlon" , ">", "GEOGCS", "Lat/long (Geodetic alias)" },
2597 // { "latlong" , ">", "GEOGCS", "Lat/long (Geodetic alias)" },
2598 // { "longlat" , ">", "GEOGCS", "Lat/long (Geodetic alias)" },
2599 
2600 // { "a" , " ", "", "Semimajor radius of the ellipsoid axis" },
2601 // { "axis" , " ", "", "Axis orientation (new in 4.8.0)" },
2602 // { "b , " ", "", "Semiminor radius of the ellipsoid axis" },
2603 // { "datum , " ", "", "Datum name (see `proj -ld`)" },
2604 // { "ellps , " ", "", "Ellipsoid name (see `proj -le`)" },
2605 // { "nadgrids , " ", "", "Filename of NTv2 grid file to use for datum transforms (see below)" },
2606 // { "no_defs , " ", "", "Don't use the /usr/share/proj/proj_def.dat defaults file" },
2607 // { "pm , " ", "", "Alternate prime meridian (typically a city name, see below)" },
2608 // { "proj , " ", "", "Projection name (see `proj -l`)" },
2609 // { "to_meter , " ", "", "Multiplier to convert map units to 1.0m" },
2610 // { "towgs84 , " ", "", "3 or 7 term datum transform parameters (see below)" },
2611 // { "units , " ", "", "meters, US survey feet, etc." },
2612 // { "south , " ", "", "Denotes southern hemisphere UTM zone" },
2613 // { "zone , " ", "", "UTM zone" },
2614 // { "lon_wrap" , " ", "", "Center longitude to use for wrapping (see below)" },
2615 // { "over" , " ", "", "Allow longitude output outside -180 to 180 range, disables wrapping (see below)" },
2616  { "", "", "", "" } // end of records
2617 };
2618 
2619  //-----------------------------------------------------
2620  Dictionary.Destroy();
2621  Dictionary.Set_Name("Proj.4-WKT Dictionary");
2622 
2623  if( Direction == 0 )
2624  {
2625  Dictionary.Add_Field("PROJ4", SG_DATATYPE_String);
2626  Dictionary.Add_Field("DIR" , SG_DATATYPE_String);
2627  Dictionary.Add_Field("WKT" , SG_DATATYPE_String);
2628  Dictionary.Add_Field("DESC" , SG_DATATYPE_String);
2629 
2630  for(int i=0; *Translation[i][0]; i++)
2631  {
2632  CSG_Table_Record &Entry = *Dictionary.Add_Record();
2633 
2634  Entry.Set_Value(0, Translation[i][0]);
2635  Entry.Set_Value(1, Translation[i][1]);
2636  Entry.Set_Value(2, Translation[i][2]);
2637  Entry.Set_Value(3, Translation[i][3]);
2638  }
2639  }
2640  else if( Direction > 0 ) // Proj4 to WKT
2641  {
2642  Dictionary.Add_Field("PROJ4", SG_DATATYPE_String);
2643  Dictionary.Add_Field("WKT" , SG_DATATYPE_String);
2644 
2645  for(int i=0; *Translation[i][0]; i++)
2646  {
2647  if( Translation[i][1][0] != '<' ) // only WKT to Proj4
2648  {
2649  CSG_Table_Record &Entry = *Dictionary.Add_Record();
2650 
2651  Entry.Set_Value(0, Translation[i][0]);
2652  Entry.Set_Value(1, Translation[i][2]);
2653  }
2654  }
2655  }
2656  else if( Direction < 0 ) // WKT to Proj4
2657  {
2658  Dictionary.Add_Field("WKT" , SG_DATATYPE_String);
2659  Dictionary.Add_Field("PROJ4", SG_DATATYPE_String);
2660 
2661  for(int i=0; *Translation[i][0]; i++)
2662  {
2663  if( Translation[i][1][0] != '>' ) // only Proj4 to WKT
2664  {
2665  CSG_Table_Record &Entry = *Dictionary.Add_Record();
2666 
2667  Entry.Set_Value(0, Translation[i][2]);
2668  Entry.Set_Value(1, Translation[i][0]);
2669  }
2670  }
2671  }
2672 
2673  return( Dictionary.Get_Count() > 0 );
2674 }
2675 
2676 //---------------------------------------------------------
2677 bool CSG_Projections::_Set_Dictionary(void)
2678 {
2679  CSG_Table Table;
2680 
2681  return( _Set_Dictionary(Table, 1) && m_Proj4_to_WKT1.Create(&Table, 0, 1, true)
2682  && _Set_Dictionary(Table, -1) && m_WKT1_to_Proj4.Create(&Table, 0, 1, true)
2683  );
2684 }
2685 
2686 
2688 // //
2689 // //
2690 // //
2692 
2693 //---------------------------------------------------------
2694 bool SG_Get_Projected (CSG_Shapes *pSource, CSG_Shapes *pTarget, const CSG_Projection &Target)
2695 {
2696  if( pSource && pSource->is_Valid() && pSource->Get_Projection().is_Okay() && Target.is_Okay() )
2697  {
2698  if( pSource->Get_Projection() == Target )
2699  {
2700  return( pTarget ? pTarget->Create(*pSource) : true );
2701  }
2702 
2703  if( pTarget )
2704  {
2705  pTarget->Create(*pSource); pSource = pTarget;
2706  }
2707 
2708  CSG_Tool *pTool = SG_Get_Tool_Library_Manager().Create_Tool("pj_proj4", 2); // Coordinate Transformation (Shapes)
2709 
2710  if( pTool )
2711  {
2712  CSG_Data_Manager Data; Data.Add(pSource); pTool->Set_Manager(&Data);
2713 
2714  pTool->Set_Callback(false);
2715  pTool->Set_Parameter("CRS_WKT" , Target.Get_WKT2());
2716  pTool->Set_Parameter("CRS_PROJ", Target.Get_PROJ());
2717  pTool->Set_Parameter("SOURCE" , pSource);
2718  pTool->Set_Parameter("COPY" , false);
2719  pTool->Set_Parameter("PARALLEL", true);
2720 
2722  bool bResult = pTool->Execute();
2724 
2725  Data.Delete(pSource, true);
2727 
2728  return( bResult );
2729  }
2730  }
2731 
2732  return( false );
2733 }
2734 
2735 //---------------------------------------------------------
2736 bool SG_Get_Projected (const CSG_Projection &Source, const CSG_Projection &Target, TSG_Point &Point)
2737 {
2738  if( Source == Target )
2739  {
2740  return( true );
2741  }
2742 
2743  if( Source.is_Okay() && Target.is_Okay() )
2744  {
2745  CSG_Tool *pTool = SG_Get_Tool_Library_Manager().Create_Tool("pj_proj4", 29); // Single Coordinate Transformation
2746 
2747  if( pTool )
2748  {
2749  pTool->Set_Manager(NULL);
2750  pTool->Set_Callback(false);
2751  pTool->Set_Parameter("TARGET_CRS", Target.Get_WKT());
2752  pTool->Set_Parameter("SOURCE_CRS", Source.Get_WKT());
2753  pTool->Set_Parameter("SOURCE_X" , Point.x);
2754  pTool->Set_Parameter("SOURCE_Y" , Point.y);
2755 
2757  bool bResult = pTool->Execute();
2759 
2760  if( bResult )
2761  {
2762  Point.x = pTool->Get_Parameter("TARGET_X")->asDouble();
2763  Point.y = pTool->Get_Parameter("TARGET_Y")->asDouble();
2764  }
2765 
2767 
2768  return( bResult );
2769  }
2770  }
2771 
2772  return( false );
2773 }
2774 
2775 //---------------------------------------------------------
2776 bool SG_Get_Projected (const CSG_Projection &Source, const CSG_Projection &Target, TSG_Rect &Rectangle)
2777 {
2778  if( Source == Target )
2779  {
2780  return( true );
2781  }
2782 
2783  if( Source.is_Okay() && Target.is_Okay() )
2784  {
2785  CSG_Shapes Points(SHAPE_TYPE_Point); Points.Get_Projection().Create(Source);
2786 
2787  Points.Add_Shape()->Add_Point(Rectangle.xMin, Rectangle.yMin);
2788  Points.Add_Shape()->Add_Point(Rectangle.xMin, Rectangle.yMax);
2789  Points.Add_Shape()->Add_Point(Rectangle.xMax, Rectangle.yMax);
2790  Points.Add_Shape()->Add_Point(Rectangle.xMax, Rectangle.yMin);
2791 
2792  if( SG_Get_Projected(&Points, NULL, Target) )
2793  {
2794  Rectangle = Points.Get_Extent();
2795 
2796  return( true );
2797  }
2798  }
2799 
2800  return( false );
2801 }
2802 
2803 
2805 // //
2806 // //
2807 // //
2809 
2810 //---------------------------------------------------------
2812 {
2813  bool bResult = false;
2814 
2815  if( pGrid && pGrid->is_Valid() && pGrid->Get_Projection().is_Okay() && (pLon || pLat) )
2816  {
2817  CSG_Grid Lon; if( !pLon ) { pLon = &Lon; } pLon->Create(pGrid->Get_System());
2818  CSG_Grid Lat; if( !pLat ) { pLat = &Lat; } pLat->Create(pGrid->Get_System());
2819 
2820  SG_RUN_TOOL(bResult, "pj_proj4", 17, // geographic coordinate grids
2821  SG_TOOL_PARAMETER_SET("GRID", pGrid)
2822  && SG_TOOL_PARAMETER_SET("LON" , pLon )
2823  && SG_TOOL_PARAMETER_SET("LAT" , pLat )
2824  )
2825  }
2826 
2827  return( bResult );
2828 }
2829 
2830 
2832 // //
2833 // //
2834 // //
2836 
2837 //---------------------------------------------------------
CSG_String::BeforeFirst
CSG_String BeforeFirst(char Character) const
Definition: api_string.cpp:690
CSG_MetaData::Destroy
void Destroy(void)
Definition: metadata.cpp:140
SG_DATATYPE_Int
@ SG_DATATYPE_Int
Definition: api_core.h:1001
CSG_Projections::Create
bool Create(bool LoadCodeList=true)
Definition: projections.cpp:787
CSG_Projection::Save
bool Save(const CSG_String &File, ESG_CRS_Format Format=ESG_CRS_Format::WKT) const
Definition: projections.cpp:261
SG_T
#define SG_T(s)
Definition: api_core.h:537
CMP_PARAMETER
#define CMP_PARAMETER(a, b)
CSG_String::Printf
int Printf(const char *Format,...)
Definition: api_string.cpp:308
SG_DATATYPE_String
@ SG_DATATYPE_String
Definition: api_core.h:1006
_TL
#define _TL(s)
Definition: api_core.h:1507
CSG_Table::Del_Records
virtual bool Del_Records(void)
Definition: table.cpp:901
CSG_String::Length
size_t Length(void) const
Definition: api_string.cpp:172
CSG_MetaData::Get_Children_Count
int Get_Children_Count(void) const
Definition: metadata.h:147
CSG_Parameter::asString
const SG_Char * asString(void) const
Definition: parameters.h:285
CSG_MetaData::Get_Content
const CSG_String & Get_Content(void) const
Definition: metadata.h:132
CSG_Table_Record
Definition: table.h:130
CSG_MetaData::Set_Content
void Set_Content(const CSG_String &Content)
Definition: metadata.h:139
data_manager.h
CSG_Projection::Get_Unit_Name
CSG_String Get_Unit_Name(void) const
Definition: projections.cpp:612
SG_Get_String
SAGA_API_DLL_EXPORT CSG_String SG_Get_String(double Value, int Precision=-99)
Definition: api_string.cpp:1342
CSG_String::asInt
int asInt(void) const
Definition: api_string.cpp:746
CSG_Table::Get_Record
virtual CSG_Table_Record * Get_Record(sLong Index) const
Definition: table.h:399
CSG_Grid::Create
bool Create(const CSG_Grid &Grid)
Definition: grid.cpp:235
CSG_Shapes::Create
bool Create(const CSG_Shapes &Shapes)
Definition: shapes.cpp:209
CSG_Projection::~CSG_Projection
virtual ~CSG_Projection(void)
Definition: projections.cpp:87
CSG_Projection::Get_Description
CSG_String Get_Description(bool bDetails=false) const
Definition: projections.cpp:383
CSG_Projection::is_Okay
bool is_Okay(void) const
Definition: geo_tools.h:863
CSG_Tool
Definition: tool.h:151
CSG_Table::Destroy
virtual bool Destroy(void)
Definition: table.cpp:325
CSG_Projections::Get_Unit
static ESG_Projection_Unit Get_Unit(const CSG_String &Identifier)
Definition: projections.cpp:2253
CSG_String::Make_Upper
CSG_String & Make_Upper(void)
Definition: api_string.cpp:551
CSG_Tool::Execute
bool Execute(bool bAddHistory=false)
Definition: tool.cpp:258
ADD_PROP
#define ADD_PROP(name, entry, prop)
CSG_Projection::is_Geographic
bool is_Geographic(void) const
Definition: geo_tools.h:901
CSG_Table_Record::is_Selected
bool is_Selected(void) const
Definition: table.h:244
CSG_Projection::Set_UTM_WGS84
bool Set_UTM_WGS84(int Zone, bool bSouth=false)
Definition: projections.cpp:696
SSG_Rect::xMax
double xMax
Definition: geo_tools.h:468
CSG_Projections::Get_Unit_To_Meter
static double Get_Unit_To_Meter(ESG_Projection_Unit Unit)
Definition: projections.cpp:2330
ESG_CRS_Format::WKT1
@ WKT1
ESG_Projection_Unit
ESG_Projection_Unit
Definition: geo_tools.h:795
CSG_Projections::Parse
static bool Parse(const CSG_String &Definition, CSG_String *PROJ=NULL, CSG_String *WKT2=NULL, CSG_String *WKT1=NULL, CSG_String *JSON=NULL, CSG_String *ESRI=NULL)
Definition: projections.cpp:1152
PRJ_FIELD_AUTH_SRID
@ PRJ_FIELD_AUTH_SRID
Definition: projections.cpp:763
SG_RUN_TOOL
#define SG_RUN_TOOL(bRetVal, LIBRARY, TOOL, CONDITION)
Definition: tool_library.h:260
CSG_Table::Get_Field_Count
int Get_Field_Count(void) const
Definition: table.h:361
PRJ_FIELD_PROJ4TEXT
@ PRJ_FIELD_PROJ4TEXT
Definition: projections.cpp:765
SG_File_Delete
SAGA_API_DLL_EXPORT bool SG_File_Delete(const CSG_String &FileName)
Definition: api_file.cpp:995
CSG_MetaData::Get_Child
CSG_MetaData * Get_Child(int Index) const
Definition: metadata.h:148
CSG_MetaData::Get_Name
const CSG_String & Get_Name(void) const
Definition: metadata.h:131
SG_FILE_R
@ SG_FILE_R
Definition: api_core.h:1111
ESG_CRS_Type::Geographic
@ Geographic
CSG_Projections::Get_CRS_Type_Name
static CSG_String Get_CRS_Type_Name(ESG_CRS_Type Type)
Definition: projections.cpp:2240
CSG_Projection::Get_WKT
const CSG_String & Get_WKT(void) const
Definition: geo_tools.h:887
ADD_INFO
#define ADD_INFO(name, value)
SSG_Point
Definition: geo_tools.h:128
CSG_Shapes::is_Valid
virtual bool is_Valid(void) const
Definition: shapes.h:805
CSG_File::Read
size_t Read(void *Buffer, size_t Size, size_t Count=1) const
Definition: api_file.cpp:337
CSG_Projection::Destroy
void Destroy(void)
Definition: projections.cpp:235
CSG_Tool_Library_Manager::Delete_Tool
bool Delete_Tool(CSG_Tool *pTool) const
Definition: tool_library.cpp:865
CSG_Grid::Get_System
const CSG_Grid_System & Get_System(void) const
Definition: grid.h:533
CSG_File
Definition: api_core.h:1126
CSG_String::Cmp
int Cmp(const CSG_String &String) const
Definition: api_string.cpp:515
SSG_Rect::xMin
double xMin
Definition: geo_tools.h:468
CSG_Projection::Get_XML
CSG_String Get_XML(void) const
Definition: projections.cpp:372
ADD_HEAD
#define ADD_HEAD(name, value)
SSG_Rect
Definition: geo_tools.h:467
CSG_Shapes::Add_Shape
virtual CSG_Shape * Add_Shape(CSG_Table_Record *pCopy=NULL, TSG_ADD_Shape_Copy_Mode mCopy=SHAPE_COPY)
Definition: shapes.cpp:402
CSG_String::BeforeLast
CSG_String BeforeLast(char Character) const
Definition: api_string.cpp:701
CSG_Tool::Set_Parameter
bool Set_Parameter(const CSG_String &ID, CSG_Parameter *pValue)
Definition: tool.cpp:1140
SG_File_Exists
SAGA_API_DLL_EXPORT bool SG_File_Exists(const CSG_String &FileName)
Definition: api_file.cpp:989
SG_TOOL_PARAMETER_SET
#define SG_TOOL_PARAMETER_SET(IDENTIFIER, VALUE)
Definition: tool_library.h:354
CSG_MetaData::Cmp_Name
bool Cmp_Name(const CSG_String &String, bool bNoCase=true) const
Definition: metadata.cpp:461
CSG_Projection::Set_GCS_WGS84
bool Set_GCS_WGS84(void)
Definition: projections.cpp:642
SG_STR_MBTOSG
#define SG_STR_MBTOSG(s)
Definition: api_core.h:545
CSG_Table_Record::asString
const SG_Char * asString(int Field, int Decimals=-99) const
Definition: table_record.cpp:461
CMP_TOWGS84
#define CMP_TOWGS84(id)
CSG_Grid::is_Valid
virtual bool is_Valid(void) const
Definition: grid.cpp:441
CSG_Strings::Add
bool Add(const CSG_Strings &Strings)
Definition: api_string.cpp:1046
CSG_Table::Get_Selection_Count
sLong Get_Selection_Count(void) const
Definition: table.h:425
CSG_Projections::Convert_WKT2_to_XML
static CSG_String Convert_WKT2_to_XML(const CSG_String &WKT)
Definition: projections.cpp:1428
CSG_Projection::is_Equal
bool is_Equal(const CSG_Projection &Projection) const
Definition: projections.cpp:501
CSG_Projection::Get_Unit_Identifier
CSG_String Get_Unit_Identifier(void) const
Definition: projections.cpp:606
CSG_MetaData::Del_Children
bool Del_Children(int Depth=0, const SG_Char *Name=NULL)
Definition: metadata.cpp:381
CSG_Projections::Get_CRS_Type
static ESG_CRS_Type Get_CRS_Type(const CSG_String &Identifier)
Definition: projections.cpp:2216
CSG_Projection::Get_ESRI
CSG_String Get_ESRI(void) const
Definition: projections.cpp:366
ADD_CONT
#define ADD_CONT(name, entry)
CSG_File::is_Writing
bool is_Writing(void) const
Definition: api_core.h:1147
SG_UI_Msg_Lock
int SG_UI_Msg_Lock(bool bOn)
Definition: api_callback.cpp:471
sLong
signed long long sLong
Definition: api_core.h:158
CSG_Projections::Load
bool Load(const CSG_String &File, bool bAppend=false)
Definition: projections.cpp:1103
SG_Get_Tool_Library_Manager
CSG_Tool_Library_Manager & SG_Get_Tool_Library_Manager(void)
Definition: tool_library.cpp:286
CSG_MetaData::Add_Property
bool Add_Property(const CSG_String &Name, const CSG_String &Value)
Definition: metadata.cpp:559
ESG_PROJ_FIELD_ID
ESG_PROJ_FIELD_ID
Definition: projections.cpp:760
CSG_Tool::Set_Callback
void Set_Callback(bool bActive=true)
Definition: tool.cpp:559
CSG_Table::Get_Count
sLong Get_Count(void) const
Definition: table.h:397
CSG_String::Trim_Both
int Trim_Both(void)
Definition: api_string.cpp:624
CMP_PROPERTY
#define CMP_PROPERTY(a, b, p)
CSG_Projection::CSG_Projection
CSG_Projection(void)
Definition: projections.cpp:82
CSG_Projection::Get_Type
ESG_CRS_Type Get_Type(void) const
Definition: geo_tools.h:906
SG_String_Tokenize
SAGA_API_DLL_EXPORT CSG_Strings SG_String_Tokenize(const CSG_String &String, const CSG_String &Delimiters=SG_DEFAULT_DELIMITERS, TSG_String_Tokenizer_Mode Mode=SG_TOKEN_DEFAULT)
Definition: api_string.cpp:1564
CSG_Translator::Get_Translation
const SG_Char * Get_Translation(int i) const
Definition: api_core.h:1468
SG_Get_Projections
CSG_Projections & SG_Get_Projections(void)
Definition: projections.cpp:69
CSG_Table::Del_Index
bool Del_Index(void)
Definition: table.cpp:1368
CSG_Shape::Add_Point
virtual int Add_Point(double x, double y, int iPart=0)=0
CSG_Data_Manager::Delete
bool Delete(CSG_Data_Object *pObject, bool bDetach=false)
Definition: data_manager.cpp:623
CSG_Projections::Get_Projection
CSG_Projection Get_Projection(sLong Index) const
Definition: projections.cpp:920
SG_FILE_W
@ SG_FILE_W
Definition: api_core.h:1112
CSG_Projections::Get_Count
sLong Get_Count(void) const
Definition: projections.cpp:860
SSG_Rect::yMax
double yMax
Definition: geo_tools.h:468
CSG_Projection::Load
bool Load(const CSG_String &File)
Definition: projections.cpp:253
CSG_Strings
Definition: api_core.h:700
CSG_Table::Get_Record_byIndex
CSG_Table_Record * Get_Record_byIndex(sLong Index) const
Definition: table.h:404
CSG_String::Replace
size_t Replace(const CSG_String &Old, const CSG_String &New, bool bReplaceAll=true)
Definition: api_string.cpp:563
ESG_CRS_Format
ESG_CRS_Format
Definition: geo_tools.h:783
CSG_Shapes::Get_Extent
virtual const CSG_Rect & Get_Extent(void)
Definition: shapes.h:811
CSG_Data_Manager::Add
CSG_Data_Object * Add(CSG_Data_Object *pObject)
Definition: data_manager.cpp:310
CSG_Data_Object::Set_Name
void Set_Name(const CSG_String &Name)
Definition: dataobject.cpp:300
CSG_Projection::Get_PROJ
const CSG_String & Get_PROJ(void) const
Definition: geo_tools.h:890
CSG_String::Format
static CSG_String Format(const char *Format,...)
Definition: api_string.cpp:270
CSG_String::Find
int Find(char Character, bool fromEnd=false) const
Definition: api_string.cpp:640
CSG_Projection
Definition: geo_tools.h:827
SG_Get_Projected
bool SG_Get_Projected(CSG_Shapes *pSource, CSG_Shapes *pTarget, const CSG_Projection &Target)
Definition: projections.cpp:2694
CSG_Table::Add_Field
virtual bool Add_Field(const CSG_String &Name, TSG_Data_Type Type, int Position=-1)
Definition: table.cpp:474
CSG_Tool_Library_Manager::Create_Tool
CSG_Tool * Create_Tool(const CSG_String &Library, int Index, bool bWithGUI=false, bool bWithCMD=true) const
Definition: tool_library.cpp:836
CSG_Table
Definition: table.h:285
CSG_Translator::Create
bool Create(const CSG_String &File_Name, bool bSetExtension=true, int iText=0, int iTranslation=1, bool bCmpNoCase=false)
Definition: api_translator.cpp:157
CSG_Projection::Get_Type_Name
CSG_String Get_Type_Name(void) const
Definition: projections.cpp:600
CSG_MetaData::Cmp_Property
bool Cmp_Property(const CSG_String &Name, const CSG_String &String, bool bNoCase=false) const
Definition: metadata.cpp:671
PRJ_FIELD_AUTH_NAME
@ PRJ_FIELD_AUTH_NAME
Definition: projections.cpp:762
PRJ_FIELD_SRID
@ PRJ_FIELD_SRID
Definition: projections.cpp:761
CSG_File::Length
sLong Length(void) const
Definition: api_file.cpp:229
CSG_String::Left
CSG_String Left(size_t count) const
Definition: api_string.cpp:729
CSG_String::CmpNoCase
int CmpNoCase(const CSG_String &String) const
Definition: api_string.cpp:521
CSG_String::AfterFirst
CSG_String AfterFirst(char Character) const
Definition: api_string.cpp:668
CSG_String::Clear
void Clear(void)
Definition: api_string.cpp:259
CSG_Projection::Get_UTM_WGS84
static CSG_Projection Get_UTM_WGS84(int Zone, bool bSouth=false)
Definition: projections.cpp:686
CSG_Table_Record::asInt
int asInt(int Field) const
Definition: table_record.cpp:494
SG_Char
#define SG_Char
Definition: api_core.h:536
shapes.h
ESG_CRS_Type
ESG_CRS_Type
Definition: geo_tools.h:789
CSG_String
Definition: api_core.h:563
SG_UI_Get_Application_Path
CSG_String SG_UI_Get_Application_Path(bool bPathOnly)
Definition: api_core.cpp:356
CSG_Tool::Set_Manager
bool Set_Manager(class CSG_Data_Manager *pManager)
Definition: tool.cpp:570
SHAPE_TYPE_Point
@ SHAPE_TYPE_Point
Definition: shapes.h:102
CSG_Data_Manager
Definition: data_manager.h:129
CSG_Projection::Get_WKT2
const CSG_String & Get_WKT2(void) const
Definition: geo_tools.h:889
CSG_MetaData
Definition: metadata.h:88
CSG_Projection::Get_Type_Identifier
CSG_String Get_Type_Identifier(void) const
Definition: projections.cpp:594
PRJ_FIELD_SRTEXT
@ PRJ_FIELD_SRTEXT
Definition: projections.cpp:764
CSG_String::is_Empty
bool is_Empty(void) const
Definition: api_string.cpp:178
CSG_Parameter::asDouble
double asDouble(void) const
Definition: parameters.h:284
SSG_Point::x
double x
Definition: geo_tools.h:129
CSG_Projections::Get_Unit_Name
static const CSG_String Get_Unit_Name(ESG_Projection_Unit Unit, bool bSimple=true)
Definition: projections.cpp:2300
CSG_Table_Record::Set_Value
bool Set_Value(int Field, const CSG_String &Value)
Definition: table_record.cpp:270
CSG_Projection::Get_Unit_To_Meter
double Get_Unit_To_Meter(void) const
Definition: projections.cpp:618
CSG_Projection::is_Projection
bool is_Projection(void) const
Definition: geo_tools.h:904
CSG_Projections::~CSG_Projections
virtual ~CSG_Projections(void)
Definition: projections.cpp:839
SSG_Rect::yMin
double yMin
Definition: geo_tools.h:468
CSG_Tool::Get_Parameter
CSG_Parameter * Get_Parameter(const CSG_String &ID) const
Definition: tool.h:188
CSG_Projection::Get_GCS_WGS84
static const CSG_Projection & Get_GCS_WGS84(void)
Definition: projections.cpp:629
CSG_Projections::CSG_Projections
CSG_Projections(void)
Definition: projections.cpp:774
SSG_Point::y
double y
Definition: geo_tools.h:129
CSG_Grid
Definition: grid.h:475
SG_UI_Get_API_Path
CSG_String SG_UI_Get_API_Path(void)
Definition: api_core.cpp:345
CSG_Projections::Get_Unit_Identifier
static const CSG_String Get_Unit_Identifier(ESG_Projection_Unit Unit)
Definition: projections.cpp:2270
TABLE_INDEX_Ascending
@ TABLE_INDEX_Ascending
Definition: table.h:105
CSG_Projection::Get_WKT1
CSG_String Get_WKT1(void) const
Definition: projections.cpp:354
CSG_Projection::is_Geodetic
bool is_Geodetic(void) const
Definition: geo_tools.h:902
CSG_Table::Create
bool Create(void)
Definition: table.cpp:153
CSG_String::asDouble
double asDouble(void) const
Definition: api_string.cpp:784
SG_File_Make_Path
SAGA_API_DLL_EXPORT CSG_String SG_File_Make_Path(const CSG_String &Directory, const CSG_String &Name)
Definition: api_file.cpp:1058
CSG_Shapes
Definition: shapes.h:773
CSG_Table::Save
virtual bool Save(const CSG_String &File, int Format, SG_Char Separator, int Encoding=SG_FILE_ENCODING_UNDEFINED)
Definition: table_io.cpp:150
SG_UI_ProgressAndMsg_Lock
void SG_UI_ProgressAndMsg_Lock(bool bOn)
Definition: api_callback.cpp:589
CSG_String::c_str
const SG_Char * c_str(void) const
Definition: api_string.cpp:236
tool_library.h
CSG_Projections::Get_Names_List
CSG_String Get_Names_List(ESG_CRS_Type Type=ESG_CRS_Type::Undefined, bool bAddSelect=true) const
Definition: projections.cpp:1248
CSG_File::Write
size_t Write(void *Buffer, size_t Size, size_t Count=1) const
Definition: api_file.cpp:369
CSG_Projections::Destroy
void Destroy(void)
Definition: projections.cpp:848
CSG_Strings::Get_Count
int Get_Count(void) const
Definition: api_core.h:713
CSG_Table::Select
virtual bool Select(sLong Index, bool bInvert=false)
Definition: table_selection.cpp:136
CSG_Table::Set_Index
bool Set_Index(CSG_Index &Index, int Field, bool bAscending=true) const
Definition: table.cpp:1457
SG_UI_Msg_Add_Error
void SG_UI_Msg_Add_Error(const char *Message)
Definition: api_callback.cpp:556
CSG_MetaData::Add_Child
CSG_MetaData * Add_Child(void)
Definition: metadata.cpp:166
CSG_Projections::Save
bool Save(const CSG_String &File)
Definition: projections.cpp:1109
CSG_MetaData::asText
CSG_String asText(int Flags=0) const
Definition: metadata.cpp:698
CSG_Projection::Get_JSON
CSG_String Get_JSON(void) const
Definition: projections.cpp:360
CSG_Table::Add_Record
virtual CSG_Table_Record * Add_Record(CSG_Table_Record *pCopy=NULL)
Definition: table.cpp:788
CSG_Projection::Create
bool Create(const CSG_Projection &Projection)
Definition: projections.cpp:96
CSG_Projections::Add
bool Add(const CSG_Projection &Projection)
Definition: projections.cpp:866
CSG_Data_Object::Get_Projection
CSG_Projection & Get_Projection(void)
Definition: dataobject.cpp:637
table.h
SG_Grid_Get_Geographic_Coordinates
bool SG_Grid_Get_Geographic_Coordinates(CSG_Grid *pGrid, CSG_Grid *pLon, CSG_Grid *pLat)
Definition: projections.cpp:2811
CSG_MetaData::Get_Property
const SG_Char * Get_Property(int Index) const
Definition: metadata.h:180
CSG_File::is_Reading
bool is_Reading(void) const
Definition: api_core.h:1146
CSG_Projections
Definition: geo_tools.h:939
geo_tools.h
CSG_Projections::Get_CRS_Type_Identifier
static CSG_String Get_CRS_Type_Identifier(ESG_CRS_Type Type)
Definition: projections.cpp:2227
CMP_CONTENT
#define CMP_CONTENT(a, b)
CSG_Projections::Get_Preference
bool Get_Preference(CSG_Projection &Projection, int Code, const CSG_String &Authority) const
Definition: projections.cpp:1026
gSG_Projections
CSG_Projections gSG_Projections
Definition: projections.cpp:66