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