Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: OpenGIS Simple Features Reference Implementation
4 : * Purpose: OGRSpatialReference translation to/from "Panorama" GIS
5 : * georeferencing information (also know as GIS "Integration").
6 : * Author: Andrey Kiselev, dron@ak4719.spb.edu
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2005, Andrey Kiselev <dron@ak4719.spb.edu>
10 : * Copyright (c) 2008-2012, Even Rouault <even dot rouault at spatialys.com>
11 : * Copyright (c) 2020-2022, Dmitry Baryshnikov <polimax@mail.ru>
12 : *
13 : * SPDX-License-Identifier: MIT
14 : ****************************************************************************/
15 :
16 : #include "ogr_spatialref.h"
17 : #include "cpl_conv.h"
18 : #include "cpl_csv.h"
19 : #include "ogr_p.h"
20 :
21 : #include <cmath>
22 :
23 : constexpr double TO_DEGREES = 180.0 / M_PI;
24 : constexpr double TO_RADIANS = M_PI / 180.0;
25 : constexpr int NONE_VAL = -1L;
26 :
27 : // This function computes zone number from the central meridian parameter.
28 13 : static int GetZoneNumberGK(double dfCenterLong)
29 : {
30 13 : return static_cast<int>((dfCenterLong + 363.0) / 6.0 + 0.5) % 60;
31 : }
32 :
33 67 : static int GetZoneNumberUTM(double dfCenterLong)
34 : {
35 67 : return static_cast<int>((dfCenterLong + 186.0) / 6.0);
36 : }
37 :
38 236 : static bool IsNone(long val)
39 : {
40 236 : return val == -1L || val == 0L || val == 255L;
41 : }
42 :
43 : /************************************************************************/
44 : /* "Panorama" projection codes. */
45 : /************************************************************************/
46 :
47 : constexpr long PAN_PROJ_TM = 1L; // Gauss-Kruger (Transverse Mercator)
48 : constexpr long PAN_PROJ_LCC = 2L; // Lambert Conformal Conic 2SP
49 : constexpr long PAN_PROJ_STEREO = 5L; // Stereographic
50 : constexpr long PAN_PROJ_AE = 6L; // Azimuthal Equidistant (Postel)
51 : constexpr long PAN_PROJ_MERCAT = 8L; // Mercator
52 : constexpr long PAN_PROJ_POLYC = 10L; // Polyconic
53 : constexpr long PAN_PROJ_PS = 13L; // Polar Stereographic
54 : constexpr long PAN_PROJ_GNOMON = 15L; // Gnomonic
55 : constexpr long PAN_PROJ_UTM = 17L; // Universal Transverse Mercator (UTM)
56 : constexpr long PAN_PROJ_WAG1 = 18L; // Wagner I (Kavraisky VI)
57 : constexpr long PAN_PROJ_MOLL = 19L; // Mollweide
58 : constexpr long PAN_PROJ_EC = 20L; // Equidistant Conic
59 : constexpr long PAN_PROJ_LAEA = 24L; // Lambert Azimuthal Equal Area
60 : constexpr long PAN_PROJ_EQC = 27L; // Equirectangular
61 : constexpr long PAN_PROJ_CEA = 28L; // Cylindrical Equal Area (Lambert)
62 : constexpr long PAN_PROJ_IMWP = 29L; // International Map of the World Polyconic
63 : constexpr long PAN_PROJ_SPHERE = 33L; // Sphere
64 : constexpr long PAN_PROJ_MILLER = 34L; // Miller
65 : constexpr long PAN_PROJ_PSEUDO_MERCATOR =
66 : 35L; // Popular Visualisation Pseudo Mercator
67 : /************************************************************************/
68 : /* "Panorama" datum codes. */
69 : /************************************************************************/
70 :
71 : constexpr long PAN_DATUM_PULKOVO42 = 1L; // Pulkovo 1942
72 : constexpr long PAN_DATUM_UTM = 2L; // Universal Transverse Mercator
73 : constexpr long PAN_DATUM_RECTANGULAR = 6L; // WGS84
74 : // constexpr long PAN_DATUM_WGS84 = 8L; // WGS84
75 : constexpr long PAN_DATUM_PULKOVO95 = 9L; // Pulokovo 1995
76 : constexpr long PAN_DATUM_GSK2011 = 10L; // GSK 2011
77 :
78 : /************************************************************************/
79 : /* "Panorama" ellipsoid codes. */
80 : /************************************************************************/
81 :
82 : constexpr long PAN_ELLIPSOID_KRASSOVSKY = 1L; // Krassovsky, 1940
83 : // constexpr long PAN_ELLIPSOID_WGS72 = 2L; // WGS, 1972
84 : // constexpr long PAN_ELLIPSOID_INT1924 = 3L; // International, 1924
85 : // (Hayford, 1909) constexpr long PAN_ELLIPSOID_CLARCKE1880 = 4L; // Clarke,
86 : // 1880 constexpr long PAN_ELLIPSOID_CLARCKE1866 = 5L; // Clarke, 1866
87 : // (NAD1927) constexpr long PAN_ELLIPSOID_EVEREST1830 = 6L; // Everest, 1830
88 : // constexpr long PAN_ELLIPSOID_BESSEL1841 = 7L; // Bessel, 1841
89 : // constexpr long PAN_ELLIPSOID_AIRY1830 = 8L; // Airy, 1830
90 : constexpr long PAN_ELLIPSOID_WGS84 = 9L; // WGS, 1984 (GPS)
91 : constexpr long PAN_ELLIPSOID_WGS84_SPHERE = 45L; // WGS, 1984 (Sphere)
92 : constexpr long PAN_ELLIPSOID_GSK2011 = 46L; // GSK 2011
93 : constexpr long PAN_ELLIPSOID_PZ90 = 47L; // PZ-90
94 :
95 : /************************************************************************/
96 : /* Correspondence between "Panorama" datum and EPSG GeogCS codes. */
97 : /************************************************************************/
98 :
99 : constexpr int aoDatums[] = {
100 : 0, // 0. Undefined (also may be 255 or -1)
101 : 4284, // 1. Pulkovo, 1942
102 : 4326, // 2. WGS, 1984,
103 : 4277, // 3. OSGB 1936 (British National Grid)
104 : 0, // 4. Local spatial reference
105 : 0, // 5. SK 63
106 : 0, // 6. Rectangular conditional spatial reference
107 : 0, // 7. Geodesic coordinates in radians
108 : 0, // 8. Geodesic coordinates in degrees
109 : 4200, // 9. Pulkovo, 1995
110 : 7683 // 10. GSK 2011
111 : };
112 :
113 : constexpr int NUMBER_OF_DATUMS = static_cast<int>(CPL_ARRAYSIZE(aoDatums));
114 :
115 : /************************************************************************/
116 : /* Correspondence between "Panorama" and EPSG ellipsoid codes. */
117 : /************************************************************************/
118 :
119 : constexpr int aoPanoramaEllips[] = {
120 : 0, // 0. Undefined
121 : 7024, // 1. Krassovsky, 1940
122 : 7043, // 2. WGS, 1972
123 : 7022, // 3. International, 1924 (Hayford, 1909)
124 : 7034, // 4. Clarke, 1880
125 : 7008, // 5. Clarke, 1866 (NAD1927)
126 : 7015, // 6. Everest, 1830
127 : 7004, // 7. Bessel, 1841
128 : 7001, // 8. Airy, 1830
129 : 7030, // 9. WGS, 1984 (GPS)
130 : 7054, // 10. PZ-90.02 // http://epsg.io/7054-ellipsoid
131 : 7019, // 11. GRS, 1980 (NAD1983)
132 : 0, // 12. IERS 1996 (6378136.49 298.25645)
133 : 7022, // 13. International, 1924 (Hayford, 1909) XXX?
134 : 7036, // 14. South American, 1969
135 : 7021, // 15. Indonesian, 1974
136 : 7020, // 16. Helmert 1906
137 : 0, // 17. FIXME: Fisher 1960 - https://epsg.io/37002
138 : 0, // 18. FIXME: Fisher 1968 - https://epsg.io/37003
139 : 0, // 19. FIXME: Haff 1960 - (6378270.0 297.0)
140 : 7042, // 20. Everest, 1830
141 : 7003, // 21. Australian National, 1965
142 : 1024, // 22. CGCS2000 http://epsg.io/1024-ellipsoid
143 : 7002, // 23. Airy Modified 1849 http://epsg.io/7002-ellipsoid
144 : 7005, // 24. Bessel Modified
145 : 7046, // 25. Bessel Namibia
146 : 7046, // 26. Bessel Namibia (GLM)
147 : 7013, // 27. Clarke 1880 (Arc)
148 : 7014, // 28. Clarke 1880 (SGA 1922)
149 : 7042, // 29. Everest (1830 Definition)
150 : 7018, // 30. Everest 1830 Modified
151 : 7056, // 31. Everest 1830 (RSO 1969)
152 : 7045, // 32. Everest 1830 (1975 Definition)
153 : 7025, // 33. NWL 9D
154 : 7027, // 34. Plessis 1817
155 : 7028, // 35. Struve 1860
156 : 7029, // 36. War Office
157 : 7031, // 37. GEM 10C
158 : 7032, // 38. OSU86F
159 : 7033, // 39. OSU91A
160 : 7036, // 40. GRS 1967
161 : 7041, // 41. Average Terrestrial System 1977
162 : 7049, // 42. IAG 1975
163 : 7050, // 43. GRS 1967 Modified
164 : 7051, // 44. Danish 1876
165 : 7048, // 45. GRS 1980 Authalic Sphere
166 : 1025, // 46. GSK 2011
167 : 7054 // 47. PZ-90
168 : };
169 :
170 : constexpr int NUMBER_OF_PANORAM_ELLIPSOIDS =
171 : static_cast<int>(CPL_ARRAYSIZE(aoPanoramaEllips));
172 :
173 : /************************************************************************/
174 : /* Correspondence between "Panorama" and EPSG vertical CS. */
175 : /************************************************************************/
176 :
177 : constexpr int aoVCS[] = {
178 : 0, //0, 255, -1 - Undefined
179 : 8357, //1 Baltic 1957 height
180 : 5711, //2 AHD height
181 : 5195, //3 Trieste height
182 : 5710, //4 Ostend height - zero normal
183 : 5710, //5 Ostend height - null point de shosse
184 : 0, //6 Channel height (GB)
185 : 5732, //7 Belfast height
186 : 5731, //8 Malin Head height
187 : 0, //9 Dublib bay height
188 : 5716, //10 Piraeus height
189 : 5733, //11 DNN height
190 : 8089, //12 ISH2004 height
191 : 5782, //13 Alicante height
192 : 0, //14 Canary islands
193 : 5214, //15 Genoa height
194 : 5709, //16 NAP height
195 : 5776, //17 NN54 height
196 : 0, //18 North Norway
197 : 5780, //19 Cascais height
198 : 5717, //20 N60 height
199 : 5613, //21 RH2000 height
200 : 0, //22 France, Marseilles height
201 : 5775, //23 Antalya height
202 : 5702, //24 NGVD29 height (ftUS)
203 : 5705, //25 Baltic 1977 height
204 : 0, //26 Pacific Ocean (Ohotsk sea level)
205 : 5714 //27 MSL height
206 : };
207 :
208 : constexpr int NUMBER_OF_VERTICALCS = static_cast<int>(CPL_ARRAYSIZE(aoVCS));
209 :
210 : /************************************************************************/
211 : /* OSRImportFromPanorama() */
212 : /************************************************************************/
213 :
214 : /** Import coordinate system from "Panorama" GIS projection definition.
215 : *
216 : * See OGRSpatialReference::importFromPanorama()
217 : */
218 :
219 0 : OGRErr OSRImportFromPanorama(OGRSpatialReferenceH hSRS, long iProjSys,
220 : long iDatum, long iEllips, double *padfPrjParams)
221 :
222 : {
223 0 : VALIDATE_POINTER1(hSRS, "OSRImportFromPanorama", OGRERR_FAILURE);
224 :
225 0 : return reinterpret_cast<OGRSpatialReference *>(hSRS)->importFromPanorama(
226 0 : iProjSys, iDatum, iEllips, padfPrjParams);
227 : }
228 :
229 : /************************************************************************/
230 : /* importFromPanorama() */
231 : /************************************************************************/
232 :
233 : /**
234 : * Import coordinate system from "Panorama" GIS projection definition.
235 : *
236 : * This method will import projection definition in style, used by
237 : * "Panorama" GIS.
238 : *
239 : * This function is the equivalent of the C function OSRImportFromPanorama().
240 : *
241 : * @param iProjSys Input projection system code, used in GIS "Panorama".
242 : *
243 : * Supported Projections are:
244 : * <ul>
245 : * <li>1: Gauss-Kruger (Transverse Mercator)</li>
246 : * <li>2: Lambert Conformal Conic 2SP</li>
247 : * <li>5: Stereographic</li>
248 : * <li>6: Azimuthal Equidistant (Postel)</li>
249 : * <li>8: Mercator</li>
250 : * <li>10: Polyconic</li>
251 : * <li>13: Polar Stereographic</li>
252 : * <li>15: Gnomonic</li>
253 : * <li>17: Universal Transverse Mercator (UTM)</li>
254 : * <li>18: Wagner I (Kavraisky VI)</li>
255 : * <li>19: Mollweide</li>
256 : * <li>20: Equidistant Conic</li>
257 : * <li>24: Lambert Azimuthal Equal Area</li>
258 : * <li>27: Equirectangular</li>
259 : * <li>28: Cylindrical Equal Area (Lambert)</li>
260 : * <li>29: International Map of the World Polyconic</li>
261 : * </ul>
262 : *
263 : * @param iDatum Input coordinate system.
264 : *
265 : * Supported Datums are:
266 : * <ul>
267 : * <li>1: Pulkovo, 1942</li>
268 : * <li>2: WGS, 1984</li>
269 : * <li>3: OSGB 1936 (British National Grid)</li>
270 : * <li>9: Pulkovo, 1995</li>
271 : * <li>10: GSK 2011</li>
272 : * </ul>
273 : *
274 : * @param iEllips Input spheroid.
275 : *
276 : * Supported Spheroids are:
277 : * <ul>
278 : * <li>1: Krassovsky, 1940</li>
279 : * <li>2: WGS, 1972</li>
280 : * <li>3: International, 1924 (Hayford, 1909)</li>
281 : * <li>4: Clarke, 1880</li>
282 : * <li>5: Clarke, 1866 (NAD1927)</li>
283 : * <li>6: Everest, 1830</li>
284 : * <li>7: Bessel, 1841</li>
285 : * <li>8: Airy, 1830</li>
286 : * <li>9: WGS, 1984 (GPS)</li>
287 : * <li>10: PZ-90.02</li>
288 : * <li>11: GRS, 1980 (NAD1983)</li>
289 : * <li>12: IERS 1996 (6378136.49 298.25645)</li>
290 : * <li>13: International, 1924 (Hayford, 1909)</li>
291 : * <li>14: South American, 1969</li>
292 : * <li>15: Indonesian, 1974</li>
293 : * <li>16: Helmert 1906</li>
294 : * <li>17: Fisher 1960</li>
295 : * <li>18: Fisher 1968</li>
296 : * <li>19. Haff 1960 - (6378270.0 297.0)</li>
297 : * <li>20: Everest, 1830</li>
298 : * <li>21: Australian National, 1965</li>
299 : * <li>22: CGCS2000</li>
300 : * <li>23: Airy Modified 1849</li>
301 : * <li>24: Bessel Modified</li>
302 : * <li>25: Bessel Namibia</li>
303 : * <li>26: Bessel Namibia (GLM)</li>
304 : * <li>27: Clarke 1880 (Arc)</li>
305 : * <li>28: Clarke 1880 (SGA 1922)</li>
306 : * <li>29: Everest (1830 Definition)</li>
307 : * <li>30: Everest 1830 Modified</li>
308 : * <li>31: Everest 1830 (RSO 1969)</li>
309 : * <li>32: Everest 1830 (1975 Definition)</li>
310 : * <li>33: NWL 9D</li>
311 : * <li>34: Plessis 1817</li>
312 : * <li>35: Struve 1860</li>
313 : * <li>36: War Office</li>
314 : * <li>37: GEM 10C</li>
315 : * <li>38: OSU86F</li>
316 : * <li>39: OSU91A</li>
317 : * <li>40: GRS 1967</li>
318 : * <li>41: Average Terrestrial System 1977</li>
319 : * <li>42: IAG 1975</li>
320 : * <li>43: GRS 1967 Modified</li>
321 : * <li>44: Danish 1876</li>
322 : * <li>45: GRS 1980 Authalic Sphere</li>
323 : * <li>46: GSK 2011</li>
324 : * <li>47: PZ-90</li>
325 : * </ul>
326 : *
327 : * @param padfPrjParams Array of 8 coordinate system parameters:
328 : *
329 : * <ul>
330 : * <li>[0] Latitude of the first standard parallel (radians)</li>
331 : * <li>[1] Latitude of the second standard parallel (radians)</li>
332 : * <li>[2] Latitude of center of projection (radians)</li>
333 : * <li>[3] Longitude of center of projection (radians)</li>
334 : * <li>[4] Scaling factor</li>
335 : * <li>[5] False Easting</li>
336 : * <li>[6] False Northing</li>
337 : * <li>[7] Zone number</li>
338 : * </ul>
339 : *
340 : * @param bNorth If northern hemisphere true, else false. Defaults to true.
341 : *
342 : * Particular projection uses different parameters, unused ones may be set to
343 : * zero. If NULL supplied instead of array pointer default values will be used
344 : * (i.e., zeroes).
345 : *
346 : * @return OGRERR_NONE on success or an error code in case of failure.
347 : */
348 :
349 101 : OGRErr OGRSpatialReference::importFromPanorama(long iProjSys, long iDatum,
350 : long iEllips,
351 : double *padfPrjParams,
352 : bool bNorth)
353 :
354 : {
355 101 : Clear();
356 :
357 : /* -------------------------------------------------------------------- */
358 : /* Use safe defaults if projection parameters are not supplied. */
359 : /* -------------------------------------------------------------------- */
360 101 : double adfPrjParams[8] = {0.0};
361 101 : if (padfPrjParams != nullptr)
362 : {
363 99 : std::copy(padfPrjParams, padfPrjParams + 8, adfPrjParams);
364 : }
365 :
366 101 : CPLDebug("OSR_Panorama",
367 : "importFromPanorama: proj %ld, datum %ld, ellips %ld, params [%f, "
368 : "%f, %f, %f, %f, %f, %f, %f], north %d",
369 : iProjSys, iDatum, iEllips, adfPrjParams[0], adfPrjParams[1],
370 : adfPrjParams[2], adfPrjParams[3], adfPrjParams[4], adfPrjParams[5],
371 : adfPrjParams[6], adfPrjParams[7], bNorth);
372 :
373 : // Check some zonal projections
374 230 : if ((IsNone(iEllips) || iEllips == PAN_ELLIPSOID_KRASSOVSKY) &&
375 230 : (IsNone(iDatum) || iDatum == PAN_DATUM_PULKOVO42) &&
376 : iProjSys == PAN_PROJ_TM) // Pulkovo 1942 / Gauss-Kruger
377 : {
378 12 : int nZone = adfPrjParams[7] == 0.0
379 12 : ? GetZoneNumberGK(TO_DEGREES * adfPrjParams[3])
380 2 : : static_cast<int>(adfPrjParams[7]);
381 :
382 12 : if (nZone > 1 && nZone < 33)
383 : {
384 12 : return importFromEPSG(28400 + nZone);
385 : }
386 : }
387 178 : if ((IsNone(iEllips) || iEllips == PAN_ELLIPSOID_KRASSOVSKY) &&
388 178 : iDatum == PAN_DATUM_PULKOVO95 &&
389 : iProjSys == PAN_PROJ_TM) // Pulkovo 1995 / Gauss-Kruger
390 : {
391 0 : int nZone = adfPrjParams[7] == 0.0
392 0 : ? GetZoneNumberGK(TO_DEGREES * adfPrjParams[3])
393 0 : : static_cast<int>(adfPrjParams[7]);
394 :
395 0 : if (nZone > 3 && nZone < 33)
396 : {
397 0 : return importFromEPSG(20000 + nZone);
398 : }
399 : }
400 89 : if (iEllips == PAN_ELLIPSOID_WGS84 && iDatum == PAN_DATUM_UTM &&
401 : iProjSys == PAN_PROJ_UTM) // WGS84 / UTM
402 : {
403 4 : const int nZone = adfPrjParams[7] == 0.0
404 4 : ? GetZoneNumberUTM(TO_DEGREES * adfPrjParams[3])
405 0 : : static_cast<int>(adfPrjParams[7]);
406 : int nEPSG;
407 4 : if (bNorth)
408 : {
409 2 : nEPSG = 32600 + nZone;
410 : }
411 : else
412 : {
413 2 : nEPSG = 32700 + nZone;
414 : }
415 4 : return importFromEPSG(nEPSG);
416 : }
417 :
418 : /* -------------------------------------------------------------------- */
419 : /* Operate on the basis of the projection code. */
420 : /* -------------------------------------------------------------------- */
421 85 : switch (iProjSys)
422 : {
423 0 : case -1L:
424 : case 255L:
425 0 : break;
426 :
427 13 : case PAN_PROJ_SPHERE:
428 13 : if (iEllips == PAN_ELLIPSOID_WGS84)
429 : {
430 13 : return SetWellKnownGeogCS("EPSG:4326");
431 : }
432 0 : break;
433 :
434 63 : case PAN_PROJ_UTM:
435 : {
436 : const int nZone =
437 63 : adfPrjParams[7] == 0.0
438 63 : ? GetZoneNumberUTM(TO_DEGREES * adfPrjParams[3])
439 0 : : static_cast<int>(adfPrjParams[7]);
440 :
441 63 : SetUTM(nZone, bNorth);
442 : }
443 63 : break;
444 :
445 0 : case PAN_PROJ_WAG1:
446 0 : SetWagner(1, 0.0, adfPrjParams[5], adfPrjParams[6]);
447 0 : break;
448 :
449 0 : case PAN_PROJ_MERCAT:
450 0 : SetMercator(TO_DEGREES * adfPrjParams[0],
451 0 : TO_DEGREES * adfPrjParams[3], adfPrjParams[4],
452 : adfPrjParams[5], adfPrjParams[6]);
453 0 : break;
454 :
455 0 : case PAN_PROJ_PS:
456 0 : SetPS(TO_DEGREES * adfPrjParams[2], TO_DEGREES * adfPrjParams[3],
457 : adfPrjParams[4], adfPrjParams[5], adfPrjParams[6]);
458 0 : break;
459 :
460 0 : case PAN_PROJ_POLYC:
461 0 : SetPolyconic(TO_DEGREES * adfPrjParams[2],
462 0 : TO_DEGREES * adfPrjParams[3], adfPrjParams[5],
463 : adfPrjParams[6]);
464 0 : break;
465 :
466 0 : case PAN_PROJ_EC:
467 0 : SetEC(TO_DEGREES * adfPrjParams[0], TO_DEGREES * adfPrjParams[1],
468 0 : TO_DEGREES * adfPrjParams[2], TO_DEGREES * adfPrjParams[3],
469 : adfPrjParams[5], adfPrjParams[6]);
470 0 : break;
471 :
472 0 : case PAN_PROJ_LCC:
473 0 : SetLCC(TO_DEGREES * adfPrjParams[0], TO_DEGREES * adfPrjParams[1],
474 0 : TO_DEGREES * adfPrjParams[2], TO_DEGREES * adfPrjParams[3],
475 : adfPrjParams[5], adfPrjParams[6]);
476 0 : break;
477 :
478 6 : case PAN_PROJ_TM:
479 : {
480 : // XXX: we need zone number to compute false easting
481 : // parameter, because usually it is not contained in the
482 : // "Panorama" projection definition.
483 : // FIXME: what to do with negative values?
484 6 : int nZone = 0;
485 6 : double dfCenterLong = 0.0;
486 :
487 6 : if (adfPrjParams[7] == 0.0)
488 : {
489 0 : dfCenterLong = TO_DEGREES * adfPrjParams[3];
490 0 : nZone = GetZoneNumberGK(dfCenterLong);
491 : }
492 : else
493 : {
494 6 : nZone = static_cast<int>(adfPrjParams[7]);
495 6 : dfCenterLong = 6.0 * nZone - 3.0;
496 : }
497 :
498 6 : adfPrjParams[5] = nZone * 1000000.0 + 500000.0;
499 6 : adfPrjParams[4] = 1.0;
500 6 : SetTM(TO_DEGREES * adfPrjParams[2], dfCenterLong, adfPrjParams[4],
501 : adfPrjParams[5], adfPrjParams[6]);
502 : }
503 6 : break;
504 :
505 0 : case PAN_PROJ_STEREO:
506 0 : SetStereographic(TO_DEGREES * adfPrjParams[2],
507 0 : TO_DEGREES * adfPrjParams[3], adfPrjParams[4],
508 : adfPrjParams[5], adfPrjParams[6]);
509 0 : break;
510 :
511 0 : case PAN_PROJ_AE:
512 0 : SetAE(TO_DEGREES * adfPrjParams[0], TO_DEGREES * adfPrjParams[3],
513 : adfPrjParams[5], adfPrjParams[6]);
514 0 : break;
515 :
516 0 : case PAN_PROJ_GNOMON:
517 0 : SetGnomonic(TO_DEGREES * adfPrjParams[2],
518 0 : TO_DEGREES * adfPrjParams[3], adfPrjParams[5],
519 : adfPrjParams[6]);
520 0 : break;
521 :
522 0 : case PAN_PROJ_MOLL:
523 0 : SetMollweide(TO_DEGREES * adfPrjParams[3], adfPrjParams[5],
524 : adfPrjParams[6]);
525 0 : break;
526 :
527 0 : case PAN_PROJ_LAEA:
528 0 : SetLAEA(TO_DEGREES * adfPrjParams[0], TO_DEGREES * adfPrjParams[3],
529 : adfPrjParams[5], adfPrjParams[6]);
530 0 : break;
531 :
532 0 : case PAN_PROJ_EQC:
533 0 : SetEquirectangular(TO_DEGREES * adfPrjParams[0],
534 0 : TO_DEGREES * adfPrjParams[3], adfPrjParams[5],
535 : adfPrjParams[6]);
536 0 : break;
537 :
538 0 : case PAN_PROJ_CEA:
539 0 : SetCEA(TO_DEGREES * adfPrjParams[0], TO_DEGREES * adfPrjParams[3],
540 : adfPrjParams[5], adfPrjParams[6]);
541 0 : break;
542 :
543 0 : case PAN_PROJ_IMWP:
544 0 : SetIWMPolyconic(
545 0 : TO_DEGREES * adfPrjParams[0], TO_DEGREES * adfPrjParams[1],
546 0 : TO_DEGREES * adfPrjParams[3], adfPrjParams[5], adfPrjParams[6]);
547 0 : break;
548 :
549 0 : case PAN_PROJ_MILLER:
550 0 : SetMC(TO_DEGREES * adfPrjParams[5], TO_DEGREES * adfPrjParams[4],
551 : adfPrjParams[6], adfPrjParams[7]);
552 0 : break;
553 :
554 2 : case PAN_PROJ_PSEUDO_MERCATOR:
555 : {
556 2 : int nEPSG = 0;
557 2 : if (iEllips == PAN_ELLIPSOID_WGS84_SPHERE)
558 : {
559 1 : nEPSG = 3857;
560 : }
561 1 : else if (iEllips == PAN_ELLIPSOID_WGS84)
562 : {
563 1 : nEPSG = 3395;
564 : }
565 2 : if (nEPSG > 0)
566 : {
567 2 : return importFromEPSG(nEPSG);
568 : }
569 : }
570 0 : break;
571 :
572 1 : default:
573 1 : CPLDebug("OSR_Panorama", "Unsupported projection: %ld", iProjSys);
574 2 : SetLocalCS(CPLString().Printf("\"Panorama\" projection number %ld",
575 1 : iProjSys));
576 1 : break;
577 : }
578 :
579 : /* -------------------------------------------------------------------- */
580 : /* Try to translate the datum/spheroid. */
581 : /* -------------------------------------------------------------------- */
582 :
583 70 : if (!IsLocal())
584 : {
585 69 : if (iEllips == PAN_ELLIPSOID_GSK2011 || iDatum == PAN_DATUM_GSK2011)
586 : {
587 0 : OGRSpatialReference oGCS;
588 0 : oGCS.importFromEPSG(7683);
589 0 : CopyGeogCSFrom(&oGCS);
590 : }
591 69 : else if (iEllips == PAN_ELLIPSOID_PZ90)
592 : {
593 0 : OGRSpatialReference oGCS;
594 0 : oGCS.importFromEPSG(7679);
595 0 : CopyGeogCSFrom(&oGCS);
596 : }
597 69 : else if (iDatum == PAN_DATUM_PULKOVO95)
598 : {
599 0 : OGRSpatialReference oGCS;
600 0 : oGCS.importFromEPSG(4200);
601 0 : CopyGeogCSFrom(&oGCS);
602 : }
603 69 : else if (iDatum > 0 && iDatum < NUMBER_OF_DATUMS && aoDatums[iDatum])
604 : {
605 44 : OGRSpatialReference oGCS;
606 22 : oGCS.importFromEPSG(aoDatums[iDatum]);
607 44 : CopyGeogCSFrom(&oGCS);
608 : }
609 47 : else if (iEllips > 0 && iEllips < NUMBER_OF_PANORAM_ELLIPSOIDS &&
610 30 : aoPanoramaEllips[iEllips])
611 : {
612 30 : char *pszName = nullptr;
613 30 : double dfSemiMajor = 0.0;
614 30 : double dfInvFlattening = 0.0;
615 :
616 30 : if (OSRGetEllipsoidInfo(aoPanoramaEllips[iEllips], &pszName,
617 : &dfSemiMajor,
618 30 : &dfInvFlattening) == OGRERR_NONE)
619 : {
620 30 : SetGeogCS(
621 60 : CPLString().Printf(
622 30 : "Unknown datum based upon the %s ellipsoid", pszName),
623 60 : CPLString().Printf("Not specified (based on %s spheroid)",
624 30 : pszName),
625 : pszName, dfSemiMajor, dfInvFlattening, nullptr, 0.0,
626 : nullptr, 0.0);
627 30 : SetAuthority("SPHEROID", "EPSG", aoPanoramaEllips[iEllips]);
628 : }
629 : else
630 : {
631 0 : CPLError(CE_Warning, CPLE_AppDefined,
632 : "Failed to lookup ellipsoid code %ld. "
633 : "Falling back to use Pulkovo 42.",
634 : iEllips);
635 0 : SetWellKnownGeogCS("EPSG:4284");
636 : }
637 :
638 30 : CPLFree(pszName);
639 : }
640 : else
641 : {
642 17 : CPLError(CE_Warning, CPLE_AppDefined,
643 : "Wrong datum code %ld. Supported datums are 1 - %d "
644 : "only. Falling back to use Pulkovo 42.",
645 : iDatum, NUMBER_OF_DATUMS - 1);
646 17 : SetWellKnownGeogCS("EPSG:4284");
647 : }
648 : }
649 :
650 : /* -------------------------------------------------------------------- */
651 : /* Grid units translation */
652 : /* -------------------------------------------------------------------- */
653 70 : if (IsLocal() || IsProjected())
654 : {
655 70 : SetLinearUnits(SRS_UL_METER, 1.0);
656 : }
657 :
658 70 : return OGRERR_NONE;
659 : }
660 :
661 : /**
662 : * Import vertical coordinate system from "Panorama" GIS projection definition.
663 : *
664 : * @param iVCS Input vertical coordinate system ID.
665 : *
666 : * Supported VCS are:
667 : * <ul>
668 : * <li>1: Baltic 1977 height (EPSG:5705)</li>
669 : * <li>2: AHD height (EPSG:5711)</li>
670 : * <li>4: Ostend height (EPSG:5710)</li>
671 : * <li>5: Ostend height (EPSG:5710)</li>
672 : * <li>7: Belfast height (EPSG: 5732)</li>
673 : * <li>8: Malin Head height (EPSG: 5731)</li>
674 : * <li>10: Piraeus height (EPSG:5716)</li>
675 : * <li>11: DNN height (EPSG:5733)</li>
676 : * <li>12: ISH2004 height (EPSG:8089)</li>
677 : * <li>13: Alicante height (EPSG:5782)</li>
678 : * <li>15: Genoa height (EPSG:5214)</li>
679 : * <li>16: NAP height (EPSG:5709)</li>
680 : * <li>17: NN54 height (EPSG:5776)</li>
681 : * <li>19: Cascais height (EPSG:5780)</li>
682 : * <li>20: N60 height (EPSG:5717)</li>
683 : * <li>21: RH2000 height (EPSG:5613)</li>
684 : * <li>23: Antalya height (EPSG:5775)</li>
685 : * <li>24: NGVD29 height (ftUS) (EPSG:5702)</li>
686 : * <li>25: Baltic 1977 height (EPSG:5705)</li>
687 : * <li>27: MSL height (EPSG:5714)</li>
688 : * </ul>
689 : */
690 0 : OGRErr OGRSpatialReference::importVertCSFromPanorama(int iVCS)
691 : {
692 0 : if (iVCS < 0 || iVCS >= NUMBER_OF_VERTICALCS)
693 : {
694 0 : return OGRERR_CORRUPT_DATA;
695 : }
696 :
697 0 : const int nEPSG = aoVCS[iVCS];
698 :
699 0 : if (nEPSG == 0)
700 : {
701 0 : CPLError(CE_Warning, CPLE_NotSupported,
702 : "Vertical coordinate system (Panorama index %d) not supported",
703 : iVCS);
704 0 : return OGRERR_UNSUPPORTED_SRS;
705 : }
706 :
707 0 : OGRSpatialReference sr;
708 0 : sr.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
709 0 : OGRErr eImportFromEPSGErr = sr.importFromEPSG(nEPSG);
710 0 : if (eImportFromEPSGErr != OGRERR_NONE)
711 : {
712 0 : CPLError(CE_Warning, CPLE_None,
713 : "Vertical coordinate system (Panorama index %d, EPSG %d) "
714 : "import from EPSG error",
715 : iVCS, nEPSG);
716 0 : return OGRERR_UNSUPPORTED_SRS;
717 : }
718 :
719 0 : if (sr.IsVertical() != 1)
720 : {
721 0 : CPLError(CE_Warning, CPLE_None,
722 : "Coordinate system (Panorama index %d, EPSG %d) "
723 : "is not Vertical",
724 : iVCS, nEPSG);
725 0 : return OGRERR_UNSUPPORTED_SRS;
726 : }
727 :
728 : OGRErr eSetVertCSErr =
729 0 : SetVertCS(sr.GetAttrValue("VERT_CS"), sr.GetAttrValue("VERT_DATUM"));
730 0 : if (eSetVertCSErr != OGRERR_NONE)
731 : {
732 0 : CPLError(CE_Warning, CPLE_None,
733 : "Vertical coordinate system (Panorama index %d, EPSG %d) "
734 : "set error",
735 : iVCS, nEPSG);
736 0 : return eSetVertCSErr;
737 : }
738 0 : return OGRERR_NONE;
739 : }
740 :
741 : /**
742 : * Export vertical coordinate system to "Panorama" GIS projection definition.
743 : */
744 53 : OGRErr OGRSpatialReference::exportVertCSToPanorama(int *piVert) const
745 : {
746 53 : auto pszVertCSName = GetAttrValue("COMPD_CS|VERT_CS");
747 53 : if (pszVertCSName != nullptr)
748 : {
749 1 : auto pszValue = GetAuthorityCode("COMPD_CS|VERT_CS");
750 1 : if (pszValue != nullptr)
751 : {
752 0 : auto nEPSG = atoi(pszValue);
753 0 : if (nEPSG > 0)
754 : {
755 0 : for (int i = 0; i < NUMBER_OF_VERTICALCS; i++)
756 : {
757 0 : if (aoVCS[i] == nEPSG)
758 : {
759 0 : *piVert = i;
760 0 : return OGRERR_NONE;
761 : }
762 : }
763 : }
764 : }
765 : else // Try to get Panorama ID from pszVertCSName
766 : {
767 26 : for (int i = 0; i < NUMBER_OF_VERTICALCS; i++)
768 : {
769 26 : if (aoVCS[i] > 0)
770 : {
771 20 : OGRSpatialReference oTmpSRS;
772 20 : oTmpSRS.importFromEPSG(aoVCS[i]);
773 20 : if (EQUAL(pszVertCSName, oTmpSRS.GetAttrValue("VERT_CS")))
774 : {
775 :
776 1 : *piVert = i;
777 1 : return OGRERR_NONE;
778 : }
779 : }
780 : }
781 : }
782 : }
783 52 : CPLDebug("OSR_Panorama",
784 : "Vertical coordinate system not supported by Panorama");
785 52 : return OGRERR_UNSUPPORTED_SRS;
786 : }
787 :
788 : /************************************************************************/
789 : /* OSRExportToPanorama() */
790 : /************************************************************************/
791 :
792 : /** Export coordinate system in "Panorama" GIS projection definition.
793 : *
794 : * See OGRSpatialReference::exportToPanorama()
795 : */
796 :
797 0 : OGRErr OSRExportToPanorama(OGRSpatialReferenceH hSRS, long *piProjSys,
798 : long *piDatum, long *piEllips, long *piZone,
799 : double *padfPrjParams)
800 :
801 : {
802 0 : VALIDATE_POINTER1(hSRS, "OSRExportToPanorama", OGRERR_FAILURE);
803 0 : VALIDATE_POINTER1(piProjSys, "OSRExportToPanorama", OGRERR_FAILURE);
804 0 : VALIDATE_POINTER1(piDatum, "OSRExportToPanorama", OGRERR_FAILURE);
805 0 : VALIDATE_POINTER1(piEllips, "OSRExportToPanorama", OGRERR_FAILURE);
806 0 : VALIDATE_POINTER1(padfPrjParams, "OSRExportToPanorama", OGRERR_FAILURE);
807 :
808 0 : return reinterpret_cast<OGRSpatialReference *>(hSRS)->exportToPanorama(
809 0 : piProjSys, piDatum, piEllips, piZone, padfPrjParams);
810 : }
811 :
812 : /************************************************************************/
813 : /* exportToPanorama() */
814 : /************************************************************************/
815 :
816 : /**
817 : * Export coordinate system in "Panorama" GIS projection definition.
818 : *
819 : * This method is the equivalent of the C function OSRExportToPanorama().
820 : *
821 : * @param piProjSys Pointer to variable, where the projection system code will
822 : * be returned.
823 : *
824 : * @param piDatum Pointer to variable, where the coordinate system code will
825 : * be returned.
826 : *
827 : * @param piEllips Pointer to variable, where the spheroid code will be
828 : * returned.
829 : *
830 : * @param piZone Pointer to variable, where the zone for UTM projection
831 : * system will be returned.
832 : *
833 : * @param padfPrjParams an existing 7 double buffer into which the
834 : * projection parameters will be placed. See importFromPanorama()
835 : * for the list of parameters.
836 : *
837 : * @return OGRERR_NONE on success or an error code on failure.
838 : */
839 :
840 56 : OGRErr OGRSpatialReference::exportToPanorama(long *piProjSys, long *piDatum,
841 : long *piEllips, long *piZone,
842 : double *padfPrjParams) const
843 :
844 : {
845 56 : CPLAssert(padfPrjParams);
846 :
847 56 : const char *pszProjection = GetAttrValue("PROJECTION");
848 56 : int nEPSG = 0;
849 56 : auto pszEPSG = GetAuthorityCode("PROJCS");
850 56 : if (pszEPSG == nullptr)
851 : {
852 50 : pszEPSG = GetAuthorityCode("GEOGCS");
853 : }
854 56 : if (pszEPSG != nullptr)
855 : {
856 32 : nEPSG = atoi(pszEPSG);
857 : }
858 :
859 : /* -------------------------------------------------------------------- */
860 : /* Fill all projection parameters with zero. */
861 : /* -------------------------------------------------------------------- */
862 56 : *piDatum = 0L;
863 56 : *piEllips = 0L;
864 56 : *piZone = 0L;
865 448 : for (int i = 0; i < 7; i++)
866 392 : padfPrjParams[i] = 0.0;
867 :
868 : /* ==================================================================== */
869 : /* Handle the projection definition. */
870 : /* ==================================================================== */
871 56 : if (IsLocal())
872 : {
873 0 : *piProjSys = NONE_VAL;
874 : }
875 56 : else if (IsGeographic() || IsGeocentric())
876 : {
877 22 : *piProjSys = PAN_PROJ_SPHERE;
878 : }
879 : // Check well known EPSG codes
880 34 : else if (nEPSG == 3857)
881 : {
882 0 : *piProjSys = PAN_PROJ_PSEUDO_MERCATOR;
883 0 : *piDatum = PAN_DATUM_RECTANGULAR;
884 0 : *piEllips = PAN_ELLIPSOID_WGS84_SPHERE;
885 0 : return OGRERR_NONE;
886 : }
887 34 : else if (pszProjection == nullptr)
888 : {
889 : #ifdef DEBUG
890 0 : CPLDebug("OSR_Panorama",
891 : "Empty projection definition, considered as Geographic");
892 : #endif
893 0 : *piProjSys = NONE_VAL;
894 : }
895 34 : else if (EQUAL(pszProjection, SRS_PT_MERCATOR_1SP))
896 : {
897 0 : *piProjSys = PAN_PROJ_MERCAT;
898 0 : padfPrjParams[3] =
899 0 : TO_RADIANS * GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0);
900 0 : padfPrjParams[0] =
901 0 : TO_RADIANS * GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0);
902 0 : padfPrjParams[4] = GetNormProjParm(SRS_PP_SCALE_FACTOR, 1.0);
903 0 : padfPrjParams[5] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
904 0 : padfPrjParams[6] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
905 : }
906 34 : else if (EQUAL(pszProjection, SRS_PT_POLAR_STEREOGRAPHIC))
907 : {
908 0 : *piProjSys = PAN_PROJ_PS;
909 0 : padfPrjParams[3] =
910 0 : TO_RADIANS * GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0);
911 0 : padfPrjParams[2] =
912 0 : TO_RADIANS * GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0);
913 0 : padfPrjParams[4] = GetNormProjParm(SRS_PP_SCALE_FACTOR, 1.0);
914 0 : padfPrjParams[5] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
915 0 : padfPrjParams[6] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
916 : }
917 34 : else if (EQUAL(pszProjection, SRS_PT_POLYCONIC))
918 : {
919 0 : *piProjSys = PAN_PROJ_POLYC;
920 0 : padfPrjParams[3] =
921 0 : TO_RADIANS * GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0);
922 0 : padfPrjParams[2] =
923 0 : TO_RADIANS * GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0);
924 0 : padfPrjParams[5] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
925 0 : padfPrjParams[6] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
926 : }
927 34 : else if (EQUAL(pszProjection, SRS_PT_EQUIDISTANT_CONIC))
928 : {
929 0 : *piProjSys = PAN_PROJ_EC;
930 0 : padfPrjParams[0] =
931 0 : TO_RADIANS * GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1, 0.0);
932 0 : padfPrjParams[1] =
933 0 : TO_RADIANS * GetNormProjParm(SRS_PP_STANDARD_PARALLEL_2, 0.0);
934 0 : padfPrjParams[3] =
935 0 : TO_RADIANS * GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0);
936 0 : padfPrjParams[2] =
937 0 : TO_RADIANS * GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0);
938 0 : padfPrjParams[5] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
939 0 : padfPrjParams[6] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
940 : }
941 34 : else if (EQUAL(pszProjection, SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP))
942 : {
943 0 : *piProjSys = PAN_PROJ_LCC;
944 0 : padfPrjParams[0] =
945 0 : TO_RADIANS * GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1, 0.0);
946 0 : padfPrjParams[1] =
947 0 : TO_RADIANS * GetNormProjParm(SRS_PP_STANDARD_PARALLEL_2, 0.0);
948 0 : padfPrjParams[3] =
949 0 : TO_RADIANS * GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0);
950 0 : padfPrjParams[2] =
951 0 : TO_RADIANS * GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0);
952 0 : padfPrjParams[5] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
953 0 : padfPrjParams[6] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
954 : }
955 34 : else if (EQUAL(pszProjection, SRS_PT_TRANSVERSE_MERCATOR))
956 : {
957 33 : int bNorth = FALSE;
958 :
959 33 : *piZone = GetUTMZone(&bNorth);
960 :
961 33 : auto dfCenterLong = GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0);
962 33 : padfPrjParams[3] = TO_RADIANS * dfCenterLong;
963 33 : padfPrjParams[2] =
964 33 : TO_RADIANS * GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0);
965 33 : padfPrjParams[4] = GetNormProjParm(SRS_PP_SCALE_FACTOR, 1.0);
966 33 : padfPrjParams[5] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
967 33 : padfPrjParams[6] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
968 :
969 33 : if (*piZone != 0)
970 : {
971 30 : *piProjSys = PAN_PROJ_UTM;
972 30 : if (!bNorth)
973 0 : *piZone = -*piZone;
974 : }
975 : else
976 : {
977 3 : *piProjSys = PAN_PROJ_TM;
978 3 : auto nZone = GetZoneNumberGK(dfCenterLong);
979 3 : *piZone = nZone;
980 : }
981 : }
982 1 : else if (EQUAL(pszProjection, SRS_PT_WAGNER_I))
983 : {
984 0 : *piProjSys = PAN_PROJ_WAG1;
985 0 : padfPrjParams[5] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
986 0 : padfPrjParams[6] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
987 : }
988 1 : else if (EQUAL(pszProjection, SRS_PT_STEREOGRAPHIC))
989 : {
990 0 : *piProjSys = PAN_PROJ_STEREO;
991 0 : padfPrjParams[3] =
992 0 : TO_RADIANS * GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0);
993 0 : padfPrjParams[2] =
994 0 : TO_RADIANS * GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0);
995 0 : padfPrjParams[4] = GetNormProjParm(SRS_PP_SCALE_FACTOR, 1.0);
996 0 : padfPrjParams[5] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
997 0 : padfPrjParams[6] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
998 : }
999 1 : else if (EQUAL(pszProjection, SRS_PT_AZIMUTHAL_EQUIDISTANT))
1000 : {
1001 0 : *piProjSys = PAN_PROJ_AE;
1002 0 : padfPrjParams[3] =
1003 0 : TO_RADIANS * GetNormProjParm(SRS_PP_LONGITUDE_OF_CENTER, 0.0);
1004 0 : padfPrjParams[0] =
1005 0 : TO_RADIANS * GetNormProjParm(SRS_PP_LATITUDE_OF_CENTER, 0.0);
1006 0 : padfPrjParams[5] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
1007 0 : padfPrjParams[6] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
1008 : }
1009 1 : else if (EQUAL(pszProjection, SRS_PT_GNOMONIC))
1010 : {
1011 0 : *piProjSys = PAN_PROJ_GNOMON;
1012 0 : padfPrjParams[3] =
1013 0 : TO_RADIANS * GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0);
1014 0 : padfPrjParams[2] =
1015 0 : TO_RADIANS * GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0);
1016 0 : padfPrjParams[5] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
1017 0 : padfPrjParams[6] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
1018 : }
1019 1 : else if (EQUAL(pszProjection, SRS_PT_MOLLWEIDE))
1020 : {
1021 0 : *piProjSys = PAN_PROJ_MOLL;
1022 0 : padfPrjParams[3] =
1023 0 : TO_RADIANS * GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0);
1024 0 : padfPrjParams[5] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
1025 0 : padfPrjParams[6] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
1026 : }
1027 1 : else if (EQUAL(pszProjection, SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA))
1028 : {
1029 0 : *piProjSys = PAN_PROJ_LAEA;
1030 0 : padfPrjParams[3] =
1031 0 : TO_RADIANS * GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0);
1032 0 : padfPrjParams[0] =
1033 0 : TO_RADIANS * GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0);
1034 0 : padfPrjParams[5] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
1035 0 : padfPrjParams[6] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
1036 : }
1037 1 : else if (EQUAL(pszProjection, SRS_PT_EQUIRECTANGULAR))
1038 : {
1039 0 : *piProjSys = PAN_PROJ_EQC;
1040 0 : padfPrjParams[3] =
1041 0 : TO_RADIANS * GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0);
1042 0 : padfPrjParams[0] =
1043 0 : TO_RADIANS * GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0);
1044 0 : padfPrjParams[5] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
1045 0 : padfPrjParams[6] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
1046 : }
1047 1 : else if (EQUAL(pszProjection, SRS_PT_CYLINDRICAL_EQUAL_AREA))
1048 : {
1049 0 : *piProjSys = PAN_PROJ_CEA;
1050 0 : padfPrjParams[3] =
1051 0 : TO_RADIANS * GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0);
1052 0 : padfPrjParams[2] =
1053 0 : TO_RADIANS * GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1, 0.0);
1054 0 : padfPrjParams[5] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
1055 0 : padfPrjParams[6] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
1056 : }
1057 1 : else if (EQUAL(pszProjection, SRS_PT_IMW_POLYCONIC))
1058 : {
1059 0 : *piProjSys = PAN_PROJ_IMWP;
1060 0 : padfPrjParams[3] =
1061 0 : TO_RADIANS * GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0);
1062 0 : padfPrjParams[0] =
1063 0 : TO_RADIANS * GetNormProjParm(SRS_PP_LATITUDE_OF_1ST_POINT, 0.0);
1064 0 : padfPrjParams[1] =
1065 0 : TO_RADIANS * GetNormProjParm(SRS_PP_LATITUDE_OF_2ND_POINT, 0.0);
1066 0 : padfPrjParams[5] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
1067 0 : padfPrjParams[6] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
1068 : }
1069 : // Projection unsupported by "Panorama" GIS
1070 : else
1071 : {
1072 1 : CPLDebug("OSR_Panorama",
1073 : "Projection \"%s\" unsupported by \"Panorama\" GIS. "
1074 : "Geographic system will be used.",
1075 : pszProjection);
1076 1 : *piProjSys = NONE_VAL;
1077 : }
1078 :
1079 : /* -------------------------------------------------------------------- */
1080 : /* Translate the datum. */
1081 : /* -------------------------------------------------------------------- */
1082 56 : const char *pszDatum = GetAttrValue("DATUM");
1083 :
1084 56 : if (pszDatum == nullptr)
1085 : {
1086 0 : *piDatum = NONE_VAL;
1087 0 : *piEllips = NONE_VAL;
1088 : }
1089 56 : else if (EQUAL(pszDatum, "Pulkovo_1942"))
1090 : {
1091 22 : *piDatum = PAN_DATUM_PULKOVO42;
1092 22 : *piEllips = PAN_ELLIPSOID_KRASSOVSKY;
1093 : }
1094 34 : else if (EQUAL(pszDatum, "Pulkovo_1995"))
1095 : {
1096 0 : *piDatum = PAN_DATUM_PULKOVO95;
1097 0 : *piEllips = PAN_ELLIPSOID_KRASSOVSKY;
1098 : }
1099 34 : else if (EQUAL(pszDatum, SRS_DN_WGS84))
1100 : {
1101 24 : *piDatum = PAN_DATUM_RECTANGULAR; // PAN_DATUM_WGS84;
1102 24 : *piEllips = PAN_ELLIPSOID_WGS84;
1103 : }
1104 :
1105 : // If not found well known datum, translate ellipsoid.
1106 : else
1107 : {
1108 10 : const double dfSemiMajor = GetSemiMajor();
1109 10 : const double dfInvFlattening = GetInvFlattening();
1110 :
1111 : #ifdef DEBUG
1112 10 : CPLDebug("OSR_Panorama",
1113 : "Datum \"%s\" unsupported by \"Panorama\" GIS. "
1114 : "Trying to translate an ellipsoid definition.",
1115 : pszDatum);
1116 : #endif
1117 :
1118 10 : int i = 0; // Used after for.
1119 60 : for (; i < NUMBER_OF_PANORAM_ELLIPSOIDS; i++)
1120 : {
1121 60 : if (aoPanoramaEllips[i])
1122 : {
1123 50 : double dfSM = 0.0;
1124 50 : double dfIF = 1.0;
1125 :
1126 50 : if (OSRGetEllipsoidInfo(aoPanoramaEllips[i], nullptr, &dfSM,
1127 50 : &dfIF) == OGRERR_NONE &&
1128 60 : std::abs(dfSemiMajor - dfSM) < 1e-10 * dfSemiMajor &&
1129 10 : std::abs(dfInvFlattening - dfIF) < 1e-10 * dfInvFlattening)
1130 : {
1131 10 : *piEllips = i;
1132 10 : break;
1133 : }
1134 : }
1135 : }
1136 :
1137 10 : if (i == NUMBER_OF_PANORAM_ELLIPSOIDS) // Didn't found matches.
1138 : {
1139 : #ifdef DEBUG
1140 0 : CPLDebug("OSR_Panorama",
1141 : R"(Ellipsoid "%s" unsupported by "Panorama" GIS.)",
1142 : pszDatum);
1143 : #endif
1144 0 : *piDatum = NONE_VAL;
1145 0 : *piEllips = NONE_VAL;
1146 : }
1147 : }
1148 :
1149 56 : return OGRERR_NONE;
1150 : }
|