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