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