/src/gdal/ogr/ogrmitabspatialref.cpp
Line  | Count  | Source (jump to first uncovered line)  | 
1  |  | // SPDX-License-Identifier: MIT  | 
2  |  | // Copyright 1999-2003, Daniel Morissette  | 
3  |  | // Copyright (c) 1999-2001, Frank Warmerdam  | 
4  |  | // Implementation translation between MIF CoordSys format, and  | 
5  |  | // and OGRSpatialRef format.  | 
6  |  |  | 
7  |  | /*! @cond Doxygen_Suppress */  | 
8  |  |  | 
9  |  | #include "ogrmitabspatialref.h"  | 
10  |  |  | 
11  |  | #include "cpl_port.h"  | 
12  |  |  | 
13  |  | #include <algorithm>  | 
14  |  | #include <cmath>  | 
15  |  | #include <cstddef>  | 
16  |  | #include <cstdio>  | 
17  |  | #include <cstdlib>  | 
18  |  | #include <cstring>  | 
19  |  |  | 
20  |  | #include "cpl_conv.h"  | 
21  |  | #include "cpl_error.h"  | 
22  |  | #include "cpl_string.h"  | 
23  |  | #include "ogr_spatialref.h"  | 
24  |  | #include "ogr_srs_api.h"  | 
25  |  |  | 
26  |  | typedef struct  | 
27  |  | { | 
28  |  |     int nDatumEPSGCode;  | 
29  |  |     int nMapInfoDatumID;  | 
30  |  |     const char *pszOGCDatumName;  | 
31  |  |     int nEllipsoid;  | 
32  |  |     double dfShiftX;  | 
33  |  |     double dfShiftY;  | 
34  |  |     double dfShiftZ;  | 
35  |  |     double dfDatumParm0; /* RotX */  | 
36  |  |     double dfDatumParm1; /* RotY */  | 
37  |  |     double dfDatumParm2; /* RotZ */  | 
38  |  |     double dfDatumParm3; /* Scale Factor */  | 
39  |  |     double dfDatumParm4; /* Prime Meridian */  | 
40  |  | } MapInfoDatumInfo;  | 
41  |  |  | 
42  |  | typedef struct  | 
43  |  | { | 
44  |  |     int nMapInfoId;  | 
45  |  |     const char *pszMapinfoName;  | 
46  |  |     double dfA;             /* semi major axis in meters */  | 
47  |  |     double dfInvFlattening; /* Inverse flattening */  | 
48  |  | } MapInfoSpheroidInfo;  | 
49  |  |  | 
50  |  | /**********************************************************************  | 
51  |  |  * MapInfo Units string to numeric ID conversion  | 
52  |  |  **********************************************************************/  | 
53  |  | typedef struct  | 
54  |  | { | 
55  |  |     int nUnitId;  | 
56  |  |     const char *pszAbbrev;  | 
57  |  | } MapInfoUnitsInfo;  | 
58  |  |  | 
59  |  | static const MapInfoUnitsInfo gasUnitsList[] = { | 
60  |  |     {0, "mi"},        {1, "km"},          {2, "in"},  {3, "ft"}, | 
61  |  |     {4, "yd"},        {5, "mm"},          {6, "cm"},  {7, "m"}, | 
62  |  |     {8, "survey ft"}, {8, "survey foot"},  // alternate | 
63  |  |     {13, nullptr},    {9, "nmi"},         {30, "li"}, {31, "ch"}, | 
64  |  |     {32, "rd"},       {-1, nullptr}}; | 
65  |  |  | 
66  |  | /**********************************************************************  | 
67  |  |  *                       TABUnitIdToString()  | 
68  |  |  *  | 
69  |  |  * Return the MIF units name for specified units id.  | 
70  |  |  * Return "" if no match found.  | 
71  |  |  *  | 
72  |  |  * The returned string should not be freed by the caller.  | 
73  |  |  **********************************************************************/  | 
74  |  | static const char *TABUnitIdToString(int nId)  | 
75  | 0  | { | 
76  | 0  |     const MapInfoUnitsInfo *psList = gasUnitsList;  | 
77  |  | 
  | 
78  | 0  |     while (psList->nUnitId != -1)  | 
79  | 0  |     { | 
80  | 0  |         if (psList->nUnitId == nId)  | 
81  | 0  |             return psList->pszAbbrev;  | 
82  | 0  |         psList++;  | 
83  | 0  |     }  | 
84  |  |  | 
85  | 0  |     return "";  | 
86  | 0  | }  | 
87  |  |  | 
88  |  | /**********************************************************************  | 
89  |  |  *                       TABUnitIdFromString()  | 
90  |  |  *  | 
91  |  |  * Return the units ID for specified MIF units name  | 
92  |  |  *  | 
93  |  |  * Returns -1 if no match found.  | 
94  |  |  **********************************************************************/  | 
95  |  | static int TABUnitIdFromString(const char *pszName)  | 
96  | 0  | { | 
97  | 0  |     if (pszName == nullptr)  | 
98  | 0  |         return 13;  | 
99  |  |  | 
100  | 0  |     const MapInfoUnitsInfo *psList = gasUnitsList;  | 
101  |  | 
  | 
102  | 0  |     while (psList->nUnitId != -1)  | 
103  | 0  |     { | 
104  | 0  |         if (psList->pszAbbrev != nullptr && EQUAL(psList->pszAbbrev, pszName))  | 
105  | 0  |             return psList->nUnitId;  | 
106  | 0  |         psList++;  | 
107  | 0  |     }  | 
108  |  |  | 
109  | 0  |     return -1;  | 
110  | 0  | }  | 
111  |  |  | 
112  |  | /* -------------------------------------------------------------------- */  | 
113  |  | /*      This table was automatically generated by doing translations    */  | 
114  |  | /*      between mif and tab for each datum, and extracting the          */  | 
115  |  | /*      parameters from the tab file.  The EPSG codes and OGC names     */  | 
116  |  | /*      were added afterwards and may be incomplete or inaccurate.       */  | 
117  |  | /* -------------------------------------------------------------------- */  | 
118  |  |  | 
119  |  | extern const MapInfoDatumInfo asDatumInfoList[];  | 
120  |  | extern const MapInfoSpheroidInfo asSpheroidInfoList[];  | 
121  |  |  | 
122  |  | /* EPSG code, MapInfo datum ID (or 9999), OGC Name, datum parameters... */  | 
123  |  | const MapInfoDatumInfo asDatumInfoList[] = { | 
124  |  |  | 
125  |  |     {0, 104, "WGS_1984", 28, 0, 0, 0, 0, 0, 0, 0, 0}, | 
126  |  |     {6269, 74, "North_American_Datum_1983", 0, 0, 0, 0, 0, 0, 0, 0, 0}, | 
127  |  |  | 
128  |  |     {0, 0, "", 29, 0, 0, 0, 0, 0, 0, 0, 0},  // Datum ignore | 
129  |  |  | 
130  |  |     {6201, 1, "Adindan", 6, -162, -12, 206, 0, 0, 0, 0, 0}, | 
131  |  |     {6205, 2, "Afgooye", 3, -43, -163, 45, 0, 0, 0, 0, 0}, | 
132  |  |     {6204, 3, "Ain_el_Abd_1970", 4, -150, -251, -2, 0, 0, 0, 0, 0}, | 
133  |  |     {0, 4, "Anna_1_Astro_1965", 2, -491, -22, 435, 0, 0, 0, 0, 0}, | 
134  |  |     {6209, 5, "Arc_1950", 15, -143, -90, -294, 0, 0, 0, 0, 0}, | 
135  |  |     {6210, 6, "Arc_1960", 6, -160, -8, -300, 0, 0, 0, 0, 0}, | 
136  |  |     {0, 7, "Ascension_Islands", 4, -207, 107, 52, 0, 0, 0, 0, 0}, | 
137  |  |     {0, 8, "Astro_Beacon_E", 4, 145, 75, -272, 0, 0, 0, 0, 0}, | 
138  |  |     {0, 9, "Astro_B4_Sorol_Atoll", 4, 114, -116, -333, 0, 0, 0, 0, 0}, | 
139  |  |     {0, 10, "Astro_Dos_71_4", 4, -320, 550, -494, 0, 0, 0, 0, 0}, | 
140  |  |     {0, 11, "Astronomic_Station_1952", 4, 124, -234, -25, 0, 0, 0, 0, 0}, | 
141  |  |     {6202, 12, "Australian_Geodetic_Datum_66", 2, -133, -48, 148, 0, 0, 0, 0, | 
142  |  |      0},  | 
143  |  |     {6203, 13, "Australian_Geodetic_Datum_84", 2, -134, -48, 149, 0, 0, 0, 0, | 
144  |  |      0},  | 
145  |  |     {0, 14, "Bellevue_Ign", 4, -127, -769, 472, 0, 0, 0, 0, 0}, | 
146  |  |     {6216, 15, "Bermuda_1957", 7, -73, 213, 296, 0, 0, 0, 0, 0}, | 
147  |  |     {6218, 16, "Bogota", 4, 307, 304, -318, 0, 0, 0, 0, 0}, | 
148  |  |     {6221, 17, "Campo_Inchauspe", 4, -148, 136, 90, 0, 0, 0, 0, 0}, | 
149  |  |     {0, 18, "Canton_Astro_1966", 4, 298, -304, -375, 0, 0, 0, 0, 0}, | 
150  |  |     {6222, 19, "Cape", 6, -136, -108, -292, 0, 0, 0, 0, 0}, | 
151  |  |     {6717, 20, "Cape_Canaveral", 7, -2, 150, 181, 0, 0, 0, 0, 0}, | 
152  |  |     {6223, 21, "Carthage", 6, -263, 6, 431, 0, 0, 0, 0, 0}, | 
153  |  |     {6672, 22, "Chatham_1971", 4, 175, -38, 113, 0, 0, 0, 0, 0}, | 
154  |  |     {6224, 23, "Chua", 4, -134, 229, -29, 0, 0, 0, 0, 0}, | 
155  |  |     {6225, 24, "Corrego_Alegre", 4, -206, 172, -6, 0, 0, 0, 0, 0}, | 
156  |  |     {6211, 25, "Batavia", 10, -377, 681, -50, 0, 0, 0, 0, 0}, | 
157  |  |     {0, 26, "Dos_1968", 4, 230, -199, -752, 0, 0, 0, 0, 0}, | 
158  |  |     {6719, 27, "Easter_Island_1967", 4, 211, 147, 111, 0, 0, 0, 0, 0}, | 
159  |  |     {6230, 28, "European_Datum_1950", 4, -87, -98, -121, 0, 0, 0, 0, 0}, | 
160  |  |     {6668, 29, "European_Datum_1979", 4, -86, -98, -119, 0, 0, 0, 0, 0}, | 
161  |  |     {6233, 30, "Gandajika_1970", 4, -133, -321, 50, 0, 0, 0, 0, 0}, | 
162  |  |     {6272, 31, "New_Zealand_GD49", 4, 84, -22, 209, 0, 0, 0, 0, 0}, | 
163  |  |     {6272, 31, "New_Zealand_Geodetic_Datum_1949", 4, 84, -22, 209, 0, 0, 0, 0, | 
164  |  |      0},  | 
165  |  |     {0, 32, "GRS_67", 21, 0, 0, 0, 0, 0, 0, 0, 0}, | 
166  |  |     {0, 33, "GRS_80", 0, 0, 0, 0, 0, 0, 0, 0, 0}, | 
167  |  |     {6171, 33, "Reseau_Geodesique_Francais_1993", 0, 0, 0, 0, 0, 0, 0, 0, 0}, | 
168  |  |     {6619, 33, "SWEREF99", 0, 0, 0, 0, 0, 0, 0, 0, 0}, | 
169  |  |     {6675, 34, "Guam_1963", 7, -100, -248, 259, 0, 0, 0, 0, 0}, | 
170  |  |     {0, 35, "Gux_1_Astro", 4, 252, -209, -751, 0, 0, 0, 0, 0}, | 
171  |  |     {6254, 36, "Hito_XVIII_1963", 4, 16, 196, 93, 0, 0, 0, 0, 0}, | 
172  |  |     {6658, 37, "Hjorsey_1955", 4, -73, 46, -86, 0, 0, 0, 0, 0}, | 
173  |  |     {6738, 38, "Hong_Kong_1963", 4, -156, -271, -189, 0, 0, 0, 0, 0}, | 
174  |  |     {6236, 39, "Hu_Tzu_Shan", 4, -634, -549, -201, 0, 0, 0, 0, 0}, | 
175  |  |     {0, 40, "Indian_Thailand_Vietnam", 11, 214, 836, 303, 0, 0, 0, 0, 0}, | 
176  |  |     {0, 41, "Indian_Bangladesh", 11, 289, 734, 257, 0, 0, 0, 0, 0}, | 
177  |  |     {6299, 42, "Ireland_1965", 13, 506, -122, 611, 0, 0, 0, 0, 0}, | 
178  |  |     {0, 43, "ISTS_073_Astro_1969", 4, 208, -435, -229, 0, 0, 0, 0, 0}, | 
179  |  |     {6725, 44, "Johnston_Island_1961", 4, 191, -77, -204, 0, 0, 0, 0, 0}, | 
180  |  |     {6244, 45, "Kandawala", 11, -97, 787, 86, 0, 0, 0, 0, 0}, | 
181  |  |     {0, 46, "Kerguyelen_Island", 4, 145, -187, 103, 0, 0, 0, 0, 0}, | 
182  |  |     {6245, 47, "Kertau", 17, -11, 851, 5, 0, 0, 0, 0, 0}, | 
183  |  |     {0, 48, "L_C_5_Astro", 7, 42, 124, 147, 0, 0, 0, 0, 0}, | 
184  |  |     {6251, 49, "Liberia_1964", 6, -90, 40, 88, 0, 0, 0, 0, 0}, | 
185  |  |     {0, 50, "Luzon_Phillippines", 7, -133, -77, -51, 0, 0, 0, 0, 0}, | 
186  |  |     {0, 51, "Luzon_Mindanao_Island", 7, -133, -79, -72, 0, 0, 0, 0, 0}, | 
187  |  |     {6256, 52, "Mahe_1971", 6, 41, -220, -134, 0, 0, 0, 0, 0}, | 
188  |  |     {0, 53, "Marco_Astro", 4, -289, -124, 60, 0, 0, 0, 0, 0}, | 
189  |  |     {6262, 54, "Massawa", 10, 639, 405, 60, 0, 0, 0, 0, 0}, | 
190  |  |     {6261, 55, "Merchich", 16, 31, 146, 47, 0, 0, 0, 0, 0}, | 
191  |  |     {0, 56, "Midway_Astro_1961", 4, 912, -58, 1227, 0, 0, 0, 0, 0}, | 
192  |  |     {6263, 57, "Minna", 6, -92, -93, 122, 0, 0, 0, 0, 0}, | 
193  |  |     {0, 58, "Nahrwan_Masirah_Island", 6, -247, -148, 369, 0, 0, 0, 0, 0}, | 
194  |  |     {0, 59, "Nahrwan_Un_Arab_Emirates", 6, -249, -156, 381, 0, 0, 0, 0, 0}, | 
195  |  |     {0, 60, "Nahrwan_Saudi_Arabia", 6, -231, -196, 482, 0, 0, 0, 0, 0}, | 
196  |  |     {6271, 61, "Naparima_1972", 4, -2, 374, 172, 0, 0, 0, 0, 0}, | 
197  |  |     {6267, 62, "NAD_1927", 7, -8, 160, 176, 0, 0, 0, 0, 0}, | 
198  |  |     {6267, 62, "North_American_Datum_1927", 7, -8, 160, 176, 0, 0, 0, 0, 0}, | 
199  |  |     {0, 63, "NAD_27_Alaska", 7, -5, 135, 172, 0, 0, 0, 0, 0}, | 
200  |  |     {0, 64, "NAD_27_Bahamas", 7, -4, 154, 178, 0, 0, 0, 0, 0}, | 
201  |  |     {0, 65, "NAD_27_San_Salvador", 7, 1, 140, 165, 0, 0, 0, 0, 0}, | 
202  |  |     {0, 66, "NAD_27_Canada", 7, -10, 158, 187, 0, 0, 0, 0, 0}, | 
203  |  |     {0, 67, "NAD_27_Canal_Zone", 7, 0, 125, 201, 0, 0, 0, 0, 0}, | 
204  |  |     {0, 68, "NAD_27_Caribbean", 7, -7, 152, 178, 0, 0, 0, 0, 0}, | 
205  |  |     {0, 69, "NAD_27_Central_America", 7, 0, 125, 194, 0, 0, 0, 0, 0}, | 
206  |  |     {0, 70, "NAD_27_Cuba", 7, -9, 152, 178, 0, 0, 0, 0, 0}, | 
207  |  |     {0, 71, "NAD_27_Greenland", 7, 11, 114, 195, 0, 0, 0, 0, 0}, | 
208  |  |     {0, 72, "NAD_27_Mexico", 7, -12, 130, 190, 0, 0, 0, 0, 0}, | 
209  |  |     {0, 73, "NAD_27_Michigan", 8, -8, 160, 176, 0, 0, 0, 0, 0}, | 
210  |  |     {0, 75, "Observatorio_1966", 4, -425, -169, 81, 0, 0, 0, 0, 0}, | 
211  |  |     {0, 76, "Old_Egyptian", 22, -130, 110, -13, 0, 0, 0, 0, 0}, | 
212  |  |     {6135, 77, "Old_Hawaiian", 7, 61, -285, -181, 0, 0, 0, 0, 0}, | 
213  |  |     {0, 78, "Oman", 6, -346, -1, 224, 0, 0, 0, 0, 0}, | 
214  |  |     {6277, 79, "OSGB_1936", 9, 375, -111, 431, 0, 0, 0, 0, 0}, | 
215  |  |     {0, 80, "Pico_De_Las_Nieves", 4, -307, -92, 127, 0, 0, 0, 0, 0}, | 
216  |  |     {6729, 81, "Pitcairn_Astro_1967", 4, 185, 165, 42, 0, 0, 0, 0, 0}, | 
217  |  |     {6248, 82, "Provisional_South_American", 4, -288, 175, -376, 0, 0, 0, 0, 0}, | 
218  |  |     {6139, 83, "Puerto_Rico", 7, 11, 72, -101, 0, 0, 0, 0, 0}, | 
219  |  |     {6614, 84, "Qatar_National", 4, -128, -283, 22, 0, 0, 0, 0, 0}, | 
220  |  |     {6287, 85, "Qornoq", 4, 164, 138, -189, 0, 0, 0, 0, 0}, | 
221  |  |     {6627, 86, "Reunion", 4, 94, -948, -1262, 0, 0, 0, 0, 0}, | 
222  |  |     {6265, 87, "Monte_Mario", 4, -225, -65, 9, 0, 0, 0, 0, 0}, | 
223  |  |     {0, 88, "Santo_Dos", 4, 170, 42, 84, 0, 0, 0, 0, 0}, | 
224  |  |     {0, 89, "Sao_Braz", 4, -203, 141, 53, 0, 0, 0, 0, 0}, | 
225  |  |     {6292, 90, "Sapper_Hill_1943", 4, -355, 16, 74, 0, 0, 0, 0, 0}, | 
226  |  |     {6293, 91, "Schwarzeck", 14, 616, 97, -251, 0, 0, 0, 0, 0}, | 
227  |  |     {6618, 92, "South_American_Datum_1969", 24, -57, 1, -41, 0, 0, 0, 0, 0}, | 
228  |  |     {0, 93, "South_Asia", 19, 7, -10, -26, 0, 0, 0, 0, 0}, | 
229  |  |     {0, 94, "Southeast_Base", 4, -499, -249, 314, 0, 0, 0, 0, 0}, | 
230  |  |     {0, 95, "Southwest_Base", 4, -104, 167, -38, 0, 0, 0, 0, 0}, | 
231  |  |     {6298, 96, "Timbalai_1948", 11, -689, 691, -46, 0, 0, 0, 0, 0}, | 
232  |  |     {6301, 97, "Tokyo", 10, -128, 481, 664, 0, 0, 0, 0, 0}, | 
233  |  |     {0, 98, "Tristan_Astro_1968", 4, -632, 438, -609, 0, 0, 0, 0, 0}, | 
234  |  |     {6731, 99, "Viti_Levu_1916", 6, 51, 391, -36, 0, 0, 0, 0, 0}, | 
235  |  |     {0, 100, "Wake_Entiwetok_1960", 23, 101, 52, -39, 0, 0, 0, 0, 0}, | 
236  |  |     {0, 101, "WGS_60", 26, 0, 0, 0, 0, 0, 0, 0, 0}, | 
237  |  |     {6760, 102, "WGS_66", 27, 0, 0, 0, 0, 0, 0, 0, 0}, | 
238  |  |     {6322, 103, "WGS_1972", 1, 0, 8, 10, 0, 0, 0, 0, 0}, | 
239  |  |     {6322, 103, "World_Geodetic_System_1972", 1, 0, 8, 10, 0, 0, 0, 0, 0}, | 
240  |  |     {6326, 104, "WGS_1984", 28, 0, 0, 0, 0, 0, 0, 0, 0}, | 
241  |  |     {6309, 105, "Yacare", 4, -155, 171, 37, 0, 0, 0, 0, 0}, | 
242  |  |     {6311, 106, "Zanderij", 4, -265, 120, -358, 0, 0, 0, 0, 0}, | 
243  |  |     {0, 107, "NTF", 30, -168, -60, 320, 0, 0, 0, 0, 0}, | 
244  |  |     {6231, 108, "European_Datum_1987", 4, -83, -96, -113, 0, 0, 0, 0, 0}, | 
245  |  |     {0, 109, "Netherlands_Bessel", 10, 593, 26, 478, 0, 0, 0, 0, 0}, | 
246  |  |     {0, 110, "Belgium_Hayford", 4, 81, 120, 129, 0, 0, 0, 0, 0}, | 
247  |  |     {0, 111, "NWGL_10", 1, -1, 15, 1, 0, 0, 0, 0, 0}, | 
248  |  |     {6124, 112, "Rikets_koordinatsystem_1990", 10, 498, -36, 568, 0, 0, 0, 0, | 
249  |  |      0},  | 
250  |  |     {0, 113, "Lisboa_DLX", 4, -303, -62, 105, 0, 0, 0, 0, 0}, | 
251  |  |     {0, 114, "Melrica_1973_D73", 4, -223, 110, 37, 0, 0, 0, 0, 0}, | 
252  |  |     {6258, 115, "European_Terrestrial_Reference_System_1989", 0, 0, 0, 0, 0, 0, | 
253  |  |      0, 0, 0},  | 
254  |  |     {6258, 115, "Euref_89", 0, 0, 0, 0, 0, 0, 0, 0, 0}, | 
255  |  |     {6180, 115, "Estonia_1997", 0, 0, 0, 0, 0, 0, 0, 0, 0}, | 
256  |  |     {6283, 116, "GDA94", 0, 0, 0, 0, 0, 0, 0, 0, 0}, | 
257  |  |     {6283, 116, "Geocentric_Datum_of_Australia_1994", 0, 0, 0, 0, 0, 0, 0, 0, | 
258  |  |      0},  | 
259  |  |     {6167, 117, "NZGD2000", 0, 0, 0, 0, 0, 0, 0, 0, 0}, | 
260  |  |     {6167, 117, "New_Zealand_Geodetic_Datum_2000", 0, 0, 0, 0, 0, 0, 0, 0, 0}, | 
261  |  |     {6169, 118, "America_Samoa", 7, -115, 118, 426, 0, 0, 0, 0, 0}, | 
262  |  |     {0, 119, "Antigua_Astro_1965", 6, -270, 13, 62, 0, 0, 0, 0, 0}, | 
263  |  |     {6713, 120, "Ayabelle_Lighthouse", 6, -79, -129, 145, 0, 0, 0, 0, 0}, | 
264  |  |     {6219, 121, "Bukit_Rimpah", 10, -384, 664, -48, 0, 0, 0, 0, 0}, | 
265  |  |     {0, 122, "Estonia_1937", 10, 374, 150, 588, 0, 0, 0, 0, 0}, | 
266  |  |     {6155, 123, "Dabola", 6, -83, 37, 124, 0, 0, 0, 0, 0}, | 
267  |  |     {6736, 124, "Deception_Island", 6, 260, 12, -147, 0, 0, 0, 0, 0}, | 
268  |  |     {0, 125, "Fort_Thomas_1955", 6, -7, 215, 225, 0, 0, 0, 0, 0}, | 
269  |  |     {0, 126, "Graciosa_base_1948", 4, -104, 167, -38, 0, 0, 0, 0, 0}, | 
270  |  |     {6255, 127, "Herat_North", 4, -333, -222, 114, 0, 0, 0, 0, 0}, | 
271  |  |     {0, 128, "Hermanns_Kogel", 10, 682, -203, 480, 0, 0, 0, 0, 0}, | 
272  |  |     {6240, 129, "Indian", 50, 283, 682, 231, 0, 0, 0, 0, 0}, | 
273  |  |     {6239, 130, "Indian_1954", 11, 217, 823, 299, 0, 0, 0, 0, 0}, | 
274  |  |     {6131, 131, "Indian_1960", 11, 198, 881, 317, 0, 0, 0, 0, 0}, | 
275  |  |     {6240, 132, "Indian_1975", 11, 210, 814, 289, 0, 0, 0, 0, 0}, | 
276  |  |     {6238, 133, "Indonesian_Datum_1974", 4, -24, -15, 5, 0, 0, 0, 0, 0}, | 
277  |  |     {0, 134, "ISTS061_Astro_1968", 4, -794, 119, -298, 0, 0, 0, 0, 0}, | 
278  |  |     {0, 135, "Kusaie_Astro_1951", 4, 647, 1777, -1124, 0, 0, 0, 0, 0}, | 
279  |  |     {6250, 136, "Leigon", 6, -130, 29, 364, 0, 0, 0, 0, 0}, | 
280  |  |     {0, 137, "Montserrat_Astro_1958", 6, 174, 359, 365, 0, 0, 0, 0, 0}, | 
281  |  |     {6266, 138, "Mporaloko", 6, -74, -130, 42, 0, 0, 0, 0, 0}, | 
282  |  |     {0, 139, "North_Sahara_1959", 6, -186, -93, 310, 0, 0, 0, 0, 0}, | 
283  |  |     {0, 140, "Observatorio_Met_1939", 4, -425, -169, 81, 0, 0, 0, 0, 0}, | 
284  |  |     {6620, 141, "Point_58", 6, -106, -129, 165, 0, 0, 0, 0, 0}, | 
285  |  |     {6282, 142, "Pointe_Noire", 6, -148, 51, -291, 0, 0, 0, 0, 0}, | 
286  |  |     {6615, 143, "Porto_Santo_1936", 4, -499, -249, 314, 0, 0, 0, 0, 0}, | 
287  |  |     {6616, 144, "Selvagem_Grande_1938", 4, -289, -124, 60, 0, 0, 0, 0, 0}, | 
288  |  |     {0, 145, "Sierra_Leone_1960", 6, -88, 4, 101, 0, 0, 0, 0, 0}, | 
289  |  |     {6156, 146, "S_JTSK_Ferro", 10, 589, 76, 480, 0, 0, 0, 0, 0}, | 
290  |  |     {6297, 147, "Tananarive_1925", 4, -189, -242, -91, 0, 0, 0, 0, 0}, | 
291  |  |     {6811, 148, "Voirol_1874", 6, -73, -247, 227, 0, 0, 0, 0, 0}, | 
292  |  |     {0, 149, "Virol_1960", 6, -123, -206, 219, 0, 0, 0, 0, 0}, | 
293  |  |     {6148, 150, "Hartebeesthoek94", 28, 0, 0, 0, 0, 0, 0, 0, 0}, | 
294  |  |     {6122, 151, "ATS77", 51, 0, 0, 0, 0, 0, 0, 0, 0}, | 
295  |  |     {6612, 152, "JGD2000", 0, 0, 0, 0, 0, 0, 0, 0, 0}, | 
296  |  |     {0, 153, "HGRS87", 0, -199.87, 74.79, 246.62, 0, 0, 0, 0, 0}, | 
297  |  |     {6214, 154, "Beijing 1954", 3, -31.4, 144.3, 81.2, 0, 0, 0, 0, 0}, | 
298  |  |     {6754, 155, "Libya (LGD 2006)", 4, 208.4058, 109.8777, 2.5764, 0, 0, 0, 0, | 
299  |  |      0},  | 
300  |  |     {6317, 156, "Dealul Piscului 1970", 3, 28, -121, -77, 0, 0, 0, 0, 0}, | 
301  |  |     {0, 157, "WGS_1984", 54, 0, 0, 0, 0, 0, 0, 0, 0},  // Google merc | 
302  |  |     {6150, 158, "CH1903+ datum for Switzerland", 10, 674.374, 15.056, 405.346, | 
303  |  |      0, 0, 0, 0, 0},  | 
304  |  |     {0, 159, "Schwarzeck (updated) datum for Namibia", 14, 616.8, 103.3, -256.9, | 
305  |  |      0, 0, 0, 0, 0},  | 
306  |  |     {0, 161, "NOAA GCS_Sphere", 55, 0, 0, 0, 0, 0, 0, 0, 0}, | 
307  |  |     // Ellipsoid 40 got from https://docs.precisely.com/docs/sftw/mapinfo-pro/v2021/en-us/pdf/mapinfo-pro-v2021-user-guide.pdf  | 
308  |  |     // Ellipsoid 40 is "Everest (India 1956)", 6377301.243, 300.80174  | 
309  |  |     // but EPSG uses "Everest 1830 (RSO 1969)",6377295.664,300.8017  | 
310  |  |     {6751, 164, "Kertau (RSO)", 40, -11, 851, 5, 0, 0, 0, 0, 0}, | 
311  |  |     {0, 1000, "DHDN_Potsdam_Rauenberg", 10, 582, 105, 414, -1.04, -0.35, 3.08, | 
312  |  |      8.3, 0},  | 
313  |  |     {6284, 1001, "Pulkovo_1942", 3, 24, -123, -94, -0.02, 0.25, 0.13, 1.1, 0}, | 
314  |  |     {6807, 1002, "NTF_Paris_Meridian", 30, -168, -60, 320, 0, 0, 0, 0, | 
315  |  |      2.337229166667},  | 
316  |  |     {6149, 1003, "Switzerland_CH_1903", 10, 660.077, 13.551, 369.344, 0.804816, | 
317  |  |      0.577692, 0.952236, 5.66, 0},  | 
318  |  |     {6237, 1004, "Hungarian_Datum_1972", 21, -56, 75.77, 15.31, -0.37, -0.2, | 
319  |  |      -0.21, -1.01, 0},  | 
320  |  |     {0, 1005, "Cape_7_Parameter", 28, -134.73, -110.92, -292.66, 0, 0, 0, 1, 0}, | 
321  |  |     {6203, 1006, "AGD84_7_Param_Aust", 2, -117.763, -51.51, 139.061, -0.292, | 
322  |  |      -0.443, -0.277, -0.191, 0},  | 
323  |  |     {0, 1007, "AGD66_7_Param_ACT", 2, -129.193, -41.212, 130.73, -0.246, -0.374, | 
324  |  |      -0.329, -2.955, 0},  | 
325  |  |     {0, 1008, "AGD66_7_Param_TAS", 2, -120.271, -64.543, 161.632, -0.2175, | 
326  |  |      0.0672, 0.1291, 2.4985, 0},  | 
327  |  |     {0, 1009, "AGD66_7_Param_VIC_NSW", 2, -119.353, -48.301, 139.484, -0.415, | 
328  |  |      -0.26, -0.437, -0.613, 0},  | 
329  |  |     {6272, 1010, "NZGD_7_Param_49", 4, 59.47, -5.04, 187.44, -0.47, 0.1, -1.024, | 
330  |  |      -4.5993, 0},  | 
331  |  |     {0, 1011, "Rikets_Tri_7_Param_1990", 10, 419.3836, 99.3335, 591.3451, | 
332  |  |      -0.850389, -1.817277, 7.862238, -0.99496, 0},  | 
333  |  |     {0, 1012, "Russia_PZ90", 52, -1.08, -0.27, -0.9, 0, 0, -0.16, -0.12, 0}, | 
334  |  |     {0, 1013, "Russia_SK42", 52, 23.92, -141.27, -80.9, 0, -0.35, -0.82, -0.12, | 
335  |  |      0},  | 
336  |  |     {0, 1014, "Russia_SK95", 52, 24.82, -131.21, -82.66, 0, 0, -0.16, -0.12, 0}, | 
337  |  |     {6301, 1015, "Tokyo", 10, -146.414, 507.337, 680.507, 0, 0, 0, 0, 0}, | 
338  |  |     {6123, 1016, "Kartastokoordinaattijarjestelma_1966", 4, -96.062, -82.428, | 
339  |  |      -121.754, -4.801, -0.345, 1.376, 1.496, 0},  | 
340  |  |     {6610, 1017, "Xian 1980", 53, 24, -123, -94, -0.02, -0.25, 0.13, 1.1, 0}, | 
341  |  |     {0, 1018, "Lithuanian Pulkovo 1942", 4, -40.59527, -18.54979, -69.33956, | 
342  |  |      -2.508, -1.8319, 2.6114, -4.2991, 0},  | 
343  |  |     {6313, 1019, "Belgian 1972 7 Parameter", 4, -99.059, 53.322, -112.486, | 
344  |  |      -0.419, 0.83, -1.885, 0.999999, 0},  | 
345  |  |     {6818, 1020, "S-JTSK with Ferro prime meridian", 10, 589, 76, 480, 0, 0, 0, | 
346  |  |      0, -17.666666666667},  | 
347  |  |     {1031, 1021, "Serbia datum MGI 1901", 10, 574.027, 170.175, 401.545, | 
348  |  |      4.88786, -0.66524, -13.24673, 6.88933, 0},  | 
349  |  |     {0, 1022, "North Sahara 7-parameter", 6, -38.7086, -128.8054, 118.8837, | 
350  |  |      0.83822, 7.38459, -1.57989, 3.9904, 0},  | 
351  |  |     {0, 1023, "Hungarian Projection System (EOV) - updated", 21, 52.684, | 
352  |  |      -71.194, -13.975, 0.312, 0.1063, 0.3729, 1.0191, 0},  | 
353  |  |     {1052, 1024, "S-JTSK (Krovak) Coordinate system - updated", 10, 570.6934, | 
354  |  |      85.6936, 462.8393, -4.99825, -1.58663, -5.26114, 3.5430155, 0},  | 
355  |  |     {0, 1025, "JTSK03 (Slovak Republic)", 10, 485.014055, 169.473618, | 
356  |  |      483.842943, -7.78625453, -4.39770887, -4.10248899, 0, 0},  | 
357  |  |     {1168, 1028, "Geocentric Datum of Australia 2020", 0, -0.06155, 0.01087, | 
358  |  |      0.04019, 0.0394924, 0.0327221, 0.0328979, 0.009994, 0},  | 
359  |  |     // For some weird reason, MapInfo uses nEllipsoid=8 "Clarke 1866 (modified  | 
360  |  |     // for Michigan)" cf  | 
361  |  |     // https://docs.precisely.com/docs/sftw/mapinfo-pro/v2021.1/en-us/pdf/mapinfo-pro-v2021.1-release-notes.pdf  | 
362  |  |     // page 8 whereas EPSG uses the regular Clarke 1866 ellipsoid.  | 
363  |  |     {6683, 1031, "Philippine Reference System 1992", 8, -127.62, -67.24, -47.04, | 
364  |  |      -3.068, 4.903, 1.578, -1.06, 0},  | 
365  |  |     {0, 9999, "Bosnia-Herzegovina", 10, 472.8677, 187.8769, 544.7084, | 
366  |  |      -5.76198422, -5.3222842, 12.80666941, 1.54517287, 0},  | 
367  |  |     {6181, 9999, "Luxembourg 1930 / Gauss", 4, -192.986, 13.673, -39.309, | 
368  |  |      0.4099, 2.9332, -2.6881, 0.43, 0},  | 
369  |  |     {1168, 9999, "Geocentric Datum of Australia 2020", 0, -0.06155, 0.01087, | 
370  |  |      0.04019, 0.0394924, 0.0327221, 0.0328979, 0.009994, 0},  | 
371  |  |     {-1, -1, nullptr, 0, 0, 0, 0, 0, 0, 0, 0, 0}}; | 
372  |  |  | 
373  |  | /* -------------------------------------------------------------------- */  | 
374  |  | /*      This table was hand entered from Appendix I of the mapinfo 6    */  | 
375  |  | /*      manuals.                                                        */  | 
376  |  | /* -------------------------------------------------------------------- */  | 
377  |  |  | 
378  |  | const MapInfoSpheroidInfo asSpheroidInfoList[] = { | 
379  |  |     {9, "Airy 1930", 6377563.396, 299.3249646}, | 
380  |  |     {13, "Airy 1930 (modified for Ireland 1965", 6377340.189, 299.3249646}, | 
381  |  |     {51, "ATS77 (Average Terrestrial System 1977)", 6378135, 298.257}, | 
382  |  |     {2, "Australian", 6378160.0, 298.25}, | 
383  |  |     {10, "Bessel 1841", 6377397.155, 299.1528128}, | 
384  |  |     {35, "Bessel 1841 (modified for NGO 1948)", 6377492.0176, 299.15281}, | 
385  |  |     {14, "Bessel 1841 (modified for Schwarzeck)", 6377483.865, 299.1528128}, | 
386  |  |     {36, "Clarke 1858", 6378293.639, 294.26068}, | 
387  |  |     {7, "Clarke 1866", 6378206.4, 294.9786982}, | 
388  |  |     {8, "Clarke 1866 (modified for Michigan)", 6378450.047484481, 294.9786982}, | 
389  |  |     {6, "Clarke 1880", 6378249.145, 293.465}, | 
390  |  |     {15, "Clarke 1880 (modified for Arc 1950)", 6378249.145326, 293.4663076}, | 
391  |  |     {30, "Clarke 1880 (modified for IGN)", 6378249.2, 293.4660213}, | 
392  |  |     {37, "Clarke 1880 (modified for Jamaica)", 6378249.136, 293.46631}, | 
393  |  |     {16, "Clarke 1880 (modified for Merchich)", 6378249.2, 293.46598}, | 
394  |  |     {38, "Clarke 1880 (modified for Palestine)", 6378300.79, 293.46623}, | 
395  |  |     {39, "Everest (Brunei and East Malaysia)", 6377298.556, 300.8017}, | 
396  |  |     {11, "Everest (India 1830)", 6377276.345, 300.8017}, | 
397  |  |     {40, "Everest (India 1956)", 6377301.243, 300.80174}, | 
398  |  |     {50, "Everest (Pakistan)", 6377309.613, 300.8017}, | 
399  |  |     {17, "Everest (W. Malaysia and Singapore 1948)", 6377304.063, 300.8017}, | 
400  |  |     {48, "Everest (West Malaysia 1969)", 6377304.063, 300.8017}, | 
401  |  |     {18, "Fischer 1960", 6378166.0, 298.3}, | 
402  |  |     {19, "Fischer 1960 (modified for South Asia)", 6378155.0, 298.3}, | 
403  |  |     {20, "Fischer 1968", 6378150.0, 298.3}, | 
404  |  |     {21, "GRS 67", 6378160.0, 298.247167427}, | 
405  |  |     {0, "GRS 80", 6378137.0, 298.257222101}, | 
406  |  |     {56, "GSK2011", 6378136.5, 298.2564151}, | 
407  |  |     {5, "Hayford", 6378388.0, 297.0}, | 
408  |  |     {22, "Helmert 1906", 6378200.0, 298.3}, | 
409  |  |     {23, "Hough", 6378270.0, 297.0}, | 
410  |  |     {31, "IAG 75", 6378140.0, 298.257222}, | 
411  |  |     {41, "Indonesian", 6378160.0, 298.247}, | 
412  |  |     {4, "International 1924", 6378388.0, 297.0}, | 
413  |  |     {49, "Irish (WOFO)", 6377542.178, 299.325}, | 
414  |  |     {3, "Krassovsky", 6378245.0, 298.3}, | 
415  |  |     {32, "MERIT 83", 6378137.0, 298.257}, | 
416  |  |     {33, "New International 1967", 6378157.5, 298.25}, | 
417  |  |     {42, "NWL 9D", 6378145.0, 298.25}, | 
418  |  |     {43, "NWL 10D", 6378135.0, 298.26}, | 
419  |  |     {44, "OSU86F", 6378136.2, 298.25722}, | 
420  |  |     {45, "OSU91A", 6378136.3, 298.25722}, | 
421  |  |     {46, "Plessis 1817", 6376523.0, 308.64}, | 
422  |  |     {52, "PZ90", 6378136.0, 298.257839303}, | 
423  |  |     {57, "PZ90.11", 6378136.0, 298.25784}, | 
424  |  |     {24, "South American", 6378160.0, 298.25}, | 
425  |  |     {12, "Sphere", 6370997.0, 0.0}, | 
426  |  |     {47, "Struve 1860", 6378297.0, 294.73}, | 
427  |  |     {34, "Walbeck", 6376896.0, 302.78}, | 
428  |  |     {25, "War Office", 6378300.583, 296.0}, | 
429  |  |     {26, "WGS 60", 6378165.0, 298.3}, | 
430  |  |     {27, "WGS 66", 6378145.0, 298.25}, | 
431  |  |     {1, "WGS 72", 6378135.0, 298.26}, | 
432  |  |     {28, "WGS 84", 6378137.0, 298.257223563}, | 
433  |  |     {29, "WGS 84 (MAPINFO Datum 0)", 6378137.01, 298.257223563}, | 
434  |  |     {54, "WGS 84 (MAPINFO Datum 157)", 6378137.01, 298.257223563}, | 
435  |  |     {-1, nullptr, 0.0, 0.0}}; | 
436  |  |  | 
437  |  | /* For LCC, standard parallel 1 and 2 can be switched indifferently */  | 
438  |  | /* So the MapInfo order and the EPSG order are not generally identical */  | 
439  |  | /* which may cause recognition problems when reading in MapInfo */  | 
440  |  | /* This table contains the parameters in the order expected by MapInfo */  | 
441  |  | typedef struct  | 
442  |  | { | 
443  |  |     int nEPSGCode;  | 
444  |  |     int bReverseStdP;  | 
445  |  |     int nMapInfoDatumID;  | 
446  |  |     double dfCenterLong;  | 
447  |  |     double dfCenterLat;  | 
448  |  |     double dfStdP1;  | 
449  |  |     double dfStdP2;  | 
450  |  | } MapInfoLCCSRS;  | 
451  |  |  | 
452  |  | static const MapInfoLCCSRS asMapInfoLCCSRSList[] = { | 
453  |  |     {2154, 1, 33, 3, 46.5, 44, 49}, | 
454  |  |     {2154, 1, 33, 3, 46.5, 44, 49.00000000001}, | 
455  |  |     {2154, 1, 33, 3, 46.5, 44, 49.00000000002}, | 
456  |  |     {2225, 1, 74, -122, 39.3333333333, 40, 41.6666666667}, | 
457  |  |     {2226, 1, 74, -122, 37.6666666667, 38.3333333333, 39.8333333333}, | 
458  |  |     {2227, 1, 74, -120.5, 36.5, 37.0666666667, 38.4333333333}, | 
459  |  |     {2228, 1, 74, -119, 35.3333333333, 36, 37.25}, | 
460  |  |     {2229, 1, 74, -118, 33.5, 34.0333333333, 35.4666666667}, | 
461  |  |     {2230, 1, 74, -116.25, 32.1666666667, 32.7833333333, 33.8833333333}, | 
462  |  |     {2231, 1, 74, -105.5, 39.3333333333, 39.7166666667, 40.7833333333}, | 
463  |  |     {2232, 1, 74, -105.5, 37.8333333333, 38.45, 39.75}, | 
464  |  |     {2233, 1, 74, -105.5, 36.6666666667, 37.2333333333, 38.4333333333}, | 
465  |  |     {2234, 1, 74, -72.75, 40.8333333333, 41.2, 41.8666666667}, | 
466  |  |     {2238, 1, 74, -84.5, 29, 29.5833333333, 30.75}, | 
467  |  |     {2246, 0, 74, -84.25, 37.5, 37.9666666667, 38.9666666667}, | 
468  |  |     {2247, 1, 74, -85.75, 36.3333333333, 36.7333333333, 37.9333333333}, | 
469  |  |     {2248, 1, 74, -77, 37.6666666667, 38.3, 39.45}, | 
470  |  |     {2249, 1, 74, -71.5, 41, 41.7166666667, 42.6833333333}, | 
471  |  |     {2250, 1, 74, -70.5, 41, 41.2833333333, 41.4833333333}, | 
472  |  |     {2251, 1, 74, -87, 44.7833333333, 45.4833333333, 47.0833333333}, | 
473  |  |     {2252, 1, 74, -84.3666666667, 43.3166666667, 44.1833333333, 45.7}, | 
474  |  |     {2253, 1, 74, -84.3666666667, 41.5, 42.1, 43.6666666667}, | 
475  |  |     {2256, 1, 74, -109.5, 44.25, 45, 49}, | 
476  |  |     {2263, 1, 74, -74, 40.1666666667, 40.6666666667, 41.0333333333}, | 
477  |  |     {2264, 1, 74, -79, 33.75, 34.3333333333, 36.1666666667}, | 
478  |  |     {2265, 1, 74, -100.5, 47, 47.4333333333, 48.7333333333}, | 
479  |  |     {2266, 1, 74, -100.5, 45.6666666667, 46.1833333333, 47.4833333333}, | 
480  |  |     {2267, 1, 74, -98, 35, 35.5666666667, 36.7666666667}, | 
481  |  |     {2268, 1, 74, -98, 33.3333333333, 33.9333333333, 35.2333333333}, | 
482  |  |     {2269, 1, 74, -120.5, 43.6666666667, 44.3333333333, 46}, | 
483  |  |     {2270, 1, 74, -120.5, 41.6666666667, 42.3333333333, 44}, | 
484  |  |     {2271, 1, 74, -77.75, 40.1666666667, 40.8833333333, 41.95}, | 
485  |  |     {2272, 1, 74, -77.75, 39.3333333333, 39.9333333333, 40.9666666667}, | 
486  |  |     {2273, 1, 74, -81, 31.8333333333, 32.5, 34.8333333333}, | 
487  |  |     {2274, 1, 74, -86, 34.3333333333, 35.25, 36.4166666667}, | 
488  |  |     {2275, 1, 74, -101.5, 34, 34.65, 36.1833333333}, | 
489  |  |     {2276, 1, 74, -98.5, 31.6666666667, 32.1333333333, 33.9666666667}, | 
490  |  |     {2277, 1, 74, -100.3333333333, 29.6666666667, 30.1166666667, 31.8833333333}, | 
491  |  |     {2278, 1, 74, -99, 27.8333333333, 28.3833333333, 30.2833333333}, | 
492  |  |     {2279, 1, 74, -98.5, 25.6666666667, 26.1666666667, 27.8333333333}, | 
493  |  |     {2280, 1, 74, -111.5, 40.3333333333, 40.7166666667, 41.7833333333}, | 
494  |  |     {2281, 1, 74, -111.5, 38.3333333333, 39.0166666667, 40.65}, | 
495  |  |     {2282, 1, 74, -111.5, 36.6666666667, 37.2166666667, 38.35}, | 
496  |  |     {2283, 1, 74, -78.5, 37.6666666667, 38.0333333333, 39.2}, | 
497  |  |     {2284, 1, 74, -78.5, 36.3333333333, 36.7666666667, 37.9666666667}, | 
498  |  |     {2285, 1, 74, -120.8333333333, 47, 47.5, 48.7333333333}, | 
499  |  |     {2286, 1, 74, -120.5, 45.3333333333, 45.8333333333, 47.3333333333}, | 
500  |  |     {2287, 1, 74, -90, 45.1666666667, 45.5666666667, 46.7666666667}, | 
501  |  |     {2288, 1, 74, -90, 43.8333333333, 44.25, 45.5}, | 
502  |  |     {2289, 1, 74, -90, 42, 42.7333333333, 44.0666666667}, | 
503  |  |     {26740, 1, 63, -176, 51, 51.8333333333, 53.8333333333}, | 
504  |  |     {26741, 1, 62, -122, 39.3333333333, 40, 41.6666666667}, | 
505  |  |     {26742, 1, 62, -122, 37.6666666667, 38.3333333333, 39.8333333333}, | 
506  |  |     {26743, 1, 62, -120.5, 36.5, 37.0666666667, 38.4333333333}, | 
507  |  |     {26744, 1, 62, -119, 35.3333333333, 36, 37.25}, | 
508  |  |     {26745, 1, 62, -118, 33.5, 34.0333333333, 35.4666666667}, | 
509  |  |     {26746, 1, 62, -116.25, 32.1666666667, 32.7833333333, 33.8833333333}, | 
510  |  |     {26747, 1, 62, -118.3333333333, 34.1333333333, 33.8666666667, | 
511  |  |      34.4166666667},  | 
512  |  |     {26751, 1, 62, -92, 34.3333333333, 34.9333333333, 36.2333333333}, | 
513  |  |     {26752, 1, 62, -92, 32.6666666667, 33.3, 34.7666666667}, | 
514  |  |     {26753, 0, 62, -105.5, 39.3333333333, 39.7166666667, 40.7833333333}, | 
515  |  |     {26754, 1, 62, -105.5, 37.8333333333, 38.45, 39.75}, | 
516  |  |     {26755, 1, 62, -105.5, 36.6666666667, 37.2333333333, 38.4333333333}, | 
517  |  |     {26756, 1, 62, -72.75, 40.8333333333, 41.2, 41.8666666667}, | 
518  |  |     {26760, 1, 62, -84.5, 29, 29.5833333333, 30.75}, | 
519  |  |     {26775, 1, 62, -93.5, 41.5, 42.0666666667, 43.2666666667}, | 
520  |  |     {26776, 1, 62, -93.5, 40, 40.6166666667, 41.7833333333}, | 
521  |  |     {26777, 1, 62, -98, 38.3333333333, 38.7166666667, 39.7833333333}, | 
522  |  |     {26778, 0, 62, -98.5, 36.6666666667, 38.5666666667, 37.2666666667}, | 
523  |  |     {26779, 0, 62, -84.25, 37.5, 37.9666666667, 38.9666666667}, | 
524  |  |     {26780, 0, 62, -85.75, 36.3333333333, 36.7333333333, 37.9333333333}, | 
525  |  |     {26781, 0, 62, -92.5, 30.6666666667, 31.1666666667, 32.6666666667}, | 
526  |  |     {26785, 0, 62, -77, 37.8333333333, 38.3, 39.45}, | 
527  |  |     {26786, 0, 62, -71.5, 41, 41.7166666667, 42.6833333333}, | 
528  |  |     {26788, 0, 73, -87, 44.7833333333, 45.4833333333, 47.0833333333}, | 
529  |  |     {26789, 0, 73, -84.3333333333, 43.3166666667, 44.1833333333, 45.7}, | 
530  |  |     {26790, 0, 73, -84.3333333333, 41.5, 42.1, 43.6666666667}, | 
531  |  |     {26791, 0, 62, -93.1, 46.5, 47.0333333333, 48.6333333333}, | 
532  |  |     {26792, 0, 62, -94.25, 45, 45.6166666667, 47.05}, | 
533  |  |     {26793, 0, 62, -94, 43, 43.7833333333, 45.2166666667}, | 
534  |  |     {26940, 1, 74, -176, 51, 51.8333333333, 53.8333333333}, | 
535  |  |     {26941, 1, 74, -122, 39.3333333333, 40, 41.6666666667}, | 
536  |  |     {26942, 1, 74, -122, 37.6666666667, 38.3333333333, 39.8333333333}, | 
537  |  |     {26943, 1, 74, -120.5, 36.5, 37.0666666667, 38.4333333333}, | 
538  |  |     {26944, 1, 74, -119, 35.3333333333, 36, 37.25}, | 
539  |  |     {26945, 1, 74, -118, 33.5, 34.0333333333, 35.4666666667}, | 
540  |  |     {26946, 1, 74, -116.25, 32.1666666667, 32.7833333333, 33.8833333333}, | 
541  |  |     {26951, 1, 74, -92, 34.3333333333, 34.9333333333, 36.2333333333}, | 
542  |  |     {26952, 1, 74, -92, 32.6666666667, 33.3, 34.7666666667}, | 
543  |  |     {26953, 1, 74, -105.5, 39.3333333333, 39.7166666667, 40.7833333333}, | 
544  |  |     {26954, 1, 74, -105.5, 37.8333333333, 38.45, 39.75}, | 
545  |  |     {26955, 1, 74, -105.5, 36.6666666667, 37.2333333333, 38.4333333333}, | 
546  |  |     {26956, 1, 74, -72.75, 40.8333333333, 41.2, 41.8666666667}, | 
547  |  |     {26960, 1, 74, -84.5, 29, 29.5833333333, 30.75}, | 
548  |  |     {26975, 1, 74, -93.5, 41.5, 42.0666666667, 43.2666666667}, | 
549  |  |     {26976, 1, 74, -93.5, 40, 40.6166666667, 41.7833333333}, | 
550  |  |     {26977, 1, 74, -98, 38.3333333333, 38.7166666667, 39.7833333333}, | 
551  |  |     {26978, 0, 74, -98.5, 36.6666666667, 38.5666666667, 37.2666666667}, | 
552  |  |     {26980, 1, 74, -85.75, 36.3333333333, 36.7333333333, 37.9333333333}, | 
553  |  |     {26981, 1, 74, -92.5, 30.5, 31.1666666667, 32.6666666667}, | 
554  |  |     {26982, 1, 74, -91.3333333333, 28.5, 29.3, 30.7}, | 
555  |  |     {26985, 1, 74, -77, 37.6666666667, 38.3, 39.45}, | 
556  |  |     {26986, 1, 74, -71.5, 41, 41.7166666667, 42.6833333333}, | 
557  |  |     {26987, 1, 74, -70.5, 41, 41.2833333333, 41.4833333333}, | 
558  |  |     {26988, 1, 74, -87, 44.7833333333, 45.4833333333, 47.0833333333}, | 
559  |  |     {26989, 1, 74, -84.3666666667, 43.3166666667, 44.1833333333, 45.7}, | 
560  |  |     {26990, 1, 74, -84.3666666667, 41.5, 42.1, 43.6666666667}, | 
561  |  |     {26991, 1, 74, -93.1, 46.5, 47.0333333333, 48.6333333333}, | 
562  |  |     {26992, 1, 74, -94.25, 45, 45.6166666667, 47.05}, | 
563  |  |     {26993, 1, 74, -94, 43, 43.7833333333, 45.2166666667}, | 
564  |  |     {3111, 0, 116, 145, -37, -36, -38}, | 
565  |  |     {31370, 1, 1019, 4.3674866667, 90, 49.8333339000, 51.1666672333}, | 
566  |  |     {32001, 1, 62, -109.5, 47, 47.85, 48.7166666667}, | 
567  |  |     {32002, 1, 62, -109.5, 45.8333333333, 46.45, 47.8833333333}, | 
568  |  |     {32003, 1, 62, -109.5, 44, 44.8666666667, 46.4}, | 
569  |  |     {32005, 0, 62, -100, 41.3333333333, 41.85, 42.8166666667}, | 
570  |  |     {32006, 0, 62, -99.5, 39.6666666667, 40.2833333333, 41.7166666667}, | 
571  |  |     {32018, 1, 62, -74, 40.5, 40.6666666667, 41.0333333333}, | 
572  |  |     {32019, 0, 62, -79, 33.75, 34.3333333333, 36.1666666667}, | 
573  |  |     {32020, 0, 62, -100.5, 47, 47.4333333333, 48.7333333333}, | 
574  |  |     {32021, 0, 62, -100.5, 45.6666666667, 46.1833333333, 47.4833333333}, | 
575  |  |     {32022, 0, 62, -82.5, 39.6666666667, 40.4333333333, 41.7}, | 
576  |  |     {32023, 0, 62, -82.5, 38, 38.7333333333, 40.0333333333}, | 
577  |  |     {32024, 0, 62, -98, 35, 35.5666666667, 36.7666666667}, | 
578  |  |     {32025, 0, 62, -98, 33.3333333333, 33.9333333333, 35.2333333333}, | 
579  |  |     {32026, 0, 62, -120.5, 43.6666666667, 44.3333333333, 46}, | 
580  |  |     {32027, 0, 62, -120.5, 41.6666666667, 42.3333333333, 44}, | 
581  |  |     {32028, 0, 62, -77.75, 40.1666666667, 40.8833333333, 41.95}, | 
582  |  |     {32031, 0, 62, -81, 33, 33.7666666667, 34.9666666667}, | 
583  |  |     {32033, 0, 62, -81, 31.8333333333, 32.3333333333, 33.6666666667}, | 
584  |  |     {32034, 0, 62, -100, 43.8333333333, 44.4166666667, 45.6833333333}, | 
585  |  |     {32035, 0, 62, -100.3333333333, 42.3333333333, 42.8333333333, 44.4}, | 
586  |  |     {32036, 0, 62, -86, 34.6666666667, 35.25, 36.4166666667}, | 
587  |  |     {32037, 0, 62, -101.5, 34, 34.65, 36.1833333333}, | 
588  |  |     {32038, 0, 62, -97.5, 31.6666666667, 32.1333333333, 33.9666666667}, | 
589  |  |     {32039, 0, 62, -100.3333333333, 29.6666666667, 30.1166666667, | 
590  |  |      31.8833333333},  | 
591  |  |     {32040, 0, 62, -99, 27.8333333333, 28.3833333333, 30.2833333333}, | 
592  |  |     {32041, 0, 62, -98.5, 25.6666666667, 26.1666666667, 27.8333333333}, | 
593  |  |     {32042, 0, 62, -111.5, 40.3333333333, 40.7166666667, 41.7833333333}, | 
594  |  |     {32043, 0, 62, -111.5, 38.3333333333, 39.0166666667, 40.65}, | 
595  |  |     {32044, 0, 62, -111.5, 36.6666666667, 37.2166666667, 38.35}, | 
596  |  |     {32046, 0, 62, -78.5, 37.6666666667, 38.0333333333, 39.2}, | 
597  |  |     {32047, 0, 62, -78.5, 36.3333333333, 36.7666666667, 37.9666666667}, | 
598  |  |     {32048, 0, 62, -120.8333333333, 47, 47.5, 48.7333333333}, | 
599  |  |     {32049, 0, 62, -120.5, 45.3333333333, 45.8333333333, 47.3333333333}, | 
600  |  |     {32050, 0, 62, -79.5, 38.5, 39, 40.25}, | 
601  |  |     {32051, 0, 62, -81, 37, 37.4833333333, 38.8833333333}, | 
602  |  |     {32052, 0, 62, -90, 45.1666666667, 45.5666666667, 46.7666666667}, | 
603  |  |     {32053, 0, 62, -90, 43.8333333333, 44.25, 45.5}, | 
604  |  |     {32054, 0, 62, -90, 42, 42.7333333333, 44.0666666667}, | 
605  |  |     {32059, 0, 62, -66.4333333333, 18.4333333333, 18.0333333333, 18.4333333333}, | 
606  |  |     {32060, 0, 62, -66.4333333333, 18.4333333333, 18.0333333333, 18.4333333333}, | 
607  |  |     {32100, 1, 74, -109.5, 44.25, 45, 49}, | 
608  |  |     {32104, 1, 74, -100, 39.8333333333, 40, 43}, | 
609  |  |     {32118, 1, 74, -74, 40.1666666667, 40.6666666667, 41.0333333333}, | 
610  |  |     {32119, 1, 74, -79, 33.75, 34.3333333333, 36.1666666667}, | 
611  |  |     {32120, 1, 74, -100.5, 47, 47.4333333333, 48.7333333333}, | 
612  |  |     {32121, 1, 74, -100.5, 45.6666666667, 46.1833333333, 47.4833333333}, | 
613  |  |     {32122, 1, 74, -82.5, 39.6666666667, 40.4333333333, 41.7}, | 
614  |  |     {32123, 1, 74, -82.5, 38, 38.7333333333, 40.0333333333}, | 
615  |  |     {32124, 1, 74, -98, 35, 35.5666666667, 36.7666666667}, | 
616  |  |     {32125, 1, 74, -98, 33.3333333333, 33.9333333333, 35.2333333333}, | 
617  |  |     {32126, 1, 74, -120.5, 43.6666666667, 44.3333333333, 46}, | 
618  |  |     {32127, 1, 74, -120.5, 41.6666666667, 42.3333333333, 44}, | 
619  |  |     {32128, 1, 74, -77.75, 40.1666666667, 40.8833333333, 41.95}, | 
620  |  |     {32129, 1, 74, -77.75, 39.3333333333, 39.9333333333, 40.9666666667}, | 
621  |  |     {32133, 1, 74, -81, 31.8333333333, 32.5, 34.8333333333}, | 
622  |  |     {32134, 1, 74, -100, 43.8333333333, 44.4166666667, 45.6833333333}, | 
623  |  |     {32135, 1, 74, -100.3333333333, 42.3333333333, 42.8333333333, 44.4}, | 
624  |  |     {32136, 1, 74, -86, 34.3333333333, 35.25, 36.4166666667}, | 
625  |  |     {32137, 1, 74, -101.5, 34, 34.65, 36.1833333333}, | 
626  |  |     {32138, 1, 74, -98.5, 31.6666666667, 32.1333333333, 33.9666666667}, | 
627  |  |     {32139, 1, 74, -100.3333333333, 29.6666666667, 30.1166666667, | 
628  |  |      31.8833333333},  | 
629  |  |     {32140, 1, 74, -99, 27.8333333333, 28.3833333333, 30.2833333333}, | 
630  |  |     {32141, 1, 74, -98.5, 25.6666666667, 26.1666666667, 27.8333333333}, | 
631  |  |     {32142, 1, 74, -111.5, 40.3333333333, 40.7166666667, 41.7833333333}, | 
632  |  |     {32143, 1, 74, -111.5, 38.3333333333, 39.0166666667, 40.65}, | 
633  |  |     {32144, 1, 74, -111.5, 36.6666666667, 37.2166666667, 38.35}, | 
634  |  |     {32146, 1, 74, -78.5, 37.6666666667, 38.0333333333, 39.2}, | 
635  |  |     {32147, 1, 74, -78.5, 36.3333333333, 36.7666666667, 37.9666666667}, | 
636  |  |     {32148, 1, 74, -120.8333333333, 47, 47.5, 48.7333333333}, | 
637  |  |     {32149, 1, 74, -120.5, 45.3333333333, 45.8333333333, 47.3333333333}, | 
638  |  |     {32150, 1, 74, -79.5, 38.5, 39, 40.25}, | 
639  |  |     {32151, 1, 74, -81, 37, 37.4833333333, 38.8833333333}, | 
640  |  |     {32152, 1, 74, -90, 45.1666666667, 45.5666666667, 46.7666666667}, | 
641  |  |     {32153, 1, 74, -90, 43.8333333333, 44.25, 45.5}, | 
642  |  |     {32154, 1, 74, -90, 42, 42.7333333333, 44.0666666667}, | 
643  |  |     {32161, 1, 74, -66.4333333333, 17.8333333333, 18.0333333333, 18.4333333333}, | 
644  |  |     {3300, 1, 115, 24, 57.51755394, 58, 59.33333333}, | 
645  |  |     {3301, 1, 115, 24, 57.51755393056, 58, 59.33333333}, | 
646  |  |     {3797, 0, 66, -70, 44, 50, 46}, | 
647  |  |     {3798, 0, 74, -70, 44, 50, 46}, | 
648  |  |     {3799, 0, 74, -70, 44, 50, 46}, | 
649  |  |     {3942, 0, 33, 3, 42, 41.25, 42.75}, | 
650  |  |     {3943, 0, 33, 3, 43, 42.25, 43.75}, | 
651  |  |     {3944, 0, 33, 3, 44, 43.25, 44.75}, | 
652  |  |     {3945, 0, 33, 3, 45, 44.25, 45.75}, | 
653  |  |     {3946, 0, 33, 3, 46, 45.25, 46.75}, | 
654  |  |     {3947, 0, 33, 3, 47, 46.25, 47.75}, | 
655  |  |     {3948, 0, 33, 3, 48, 47.25, 48.75}, | 
656  |  |     {3949, 0, 33, 3, 49, 48.25, 49.75}, | 
657  |  |     {3950, 0, 33, 3, 50, 49.25, 50.75}, | 
658  |  |     {42101, 0, 104, -95, 0, 49, 77}, | 
659  |  |     {42103, 0, 104, -100, 0, 33, 45}, | 
660  |  |     {42304, 0, 74, -95, 49, 49, 77}, | 
661  |  |     {0, 0, 0, 110, 10, 25, 40}, | 
662  |  |     {0, 0, 0, 132.5, -10, -21.5, -33.5}, | 
663  |  |     {0, 0, 0, 25, 35, 40, 65}, | 
664  |  |     {0, 0, 0, 47.5, 25, 15, 35}, | 
665  |  |     {0, 0, 0, 95, 40, 20, 60}, | 
666  |  |     {0, 0, 1002, 0, 42.165, 41.5603877778, 42.76766333}, | 
667  |  |     {0, 0, 1002, 0, 42.165, 41.5603877778, 42.767663333}, | 
668  |  |     {0, 0, 1002, 0, 42.165, 41.560387778, 42.76766333}, | 
669  |  |     {0, 0, 1002, 0, 42.165, 41.560387778, 42.767663333}, | 
670  |  |     {0, 0, 1002, 0, 42.165, 41.56038778, 42.76766333}, | 
671  |  |     {0, 0, 1002, 0, 42.165, 41.560387840948, 42.76766346965}, | 
672  |  |     {0, 0, 1002, 0, 44.1, 43.199291275544, 44.996093814511}, | 
673  |  |     {0, 0, 1002, 0, 44.1, 43.1992913889, 44.99609389}, | 
674  |  |     {0, 0, 1002, 0, 44.1, 43.199291389, 44.99609389}, | 
675  |  |     {0, 0, 1002, 0, 44.1, 43.19929139, 44.99609389}, | 
676  |  |     {0, 0, 1002, 0, 46.8, 45.8989188889, 47.69601444}, | 
677  |  |     {0, 0, 1002, 0, 46.8, 45.898918889, 47.69601444}, | 
678  |  |     {0, 0, 1002, 0, 46.8, 45.89891889, 47.69601444}, | 
679  |  |     {0, 0, 1002, 0, 46.8, 45.898918964419, 47.696014502038}, | 
680  |  |     {0, 0, 1002, 0, 49.5, 48.5985227778, 50.39591167}, | 
681  |  |     {0, 0, 1002, 0, 49.5, 48.598522778, 50.39591167}, | 
682  |  |     {0, 0, 1002, 0, 49.5, 48.59852278, 50.39591167}, | 
683  |  |     {0, 0, 1002, 0, 49.5, 48.598522847174, 50.395911631678}, | 
684  |  |     {0, 0, 1005, 23, -23, -18, -32}, | 
685  |  |     {0, 0, 1022, 2.7, 36, 37.575, 34.425}, | 
686  |  |     {0, 0, 104, 13.33333333, 47.5, 46, 49}, | 
687  |  |     {0, 0, 104, 13.33333333, 48, 46, 49}, | 
688  |  |     {0, 0, 104, -19, 65, 64.25, 65.75}, | 
689  |  |     {0, 0, 104, 36.0, 25.0, 37.5, 40.5}, | 
690  |  |     {0, 0, 104, 36, 25, 37.5, 40.5}, | 
691  |  |     {0, 0, 104, 70, -50, -68.5, -74.5}, | 
692  |  |     {0, 0, 110, 4.367975, 90, 49.8333333333, 51.1666666667}, | 
693  |  |     {0, 0, 115, 10, 52, 35, 45}, | 
694  |  |     {0, 0, 116, 135, -24, -18, -36}, | 
695  |  |     {0, 0, 116, 135, -32, -28, -36}, | 
696  |  |     {0, 0, 12, 135, -24, -18, -36}, | 
697  |  |     {0, 0, 12, 145, -37, -36, -38}, | 
698  |  |     {0, 0, 13, 135, -24, -18, -36}, | 
699  |  |     {0, 0, 19, 23, -23, -18, -32}, | 
700  |  |     {0, 0, 28, 17, 29.77930555, 42, 56}, | 
701  |  |     {0, 0, 28, 19, 29.77930555, 42, 56}, | 
702  |  |     {0, 0, 28, 36.0, 25.0, 37.5, 40.5}, | 
703  |  |     {0, 0, 33, 13.5, 0, 52.6666666667, 55.3333333333}, | 
704  |  |     {0, 0, 33, 15, 0, 56.5, 60.5}, | 
705  |  |     {0, 0, 33, 15, 0, 58, 66}, | 
706  |  |     {0, 0, 33, 15, 0, 63.5, 67.5}, | 
707  |  |     {0, 0, 33, 15.5, 0, 56.6666666667, 59.3333333333}, | 
708  |  |     {0, 0, 33, 15.5, 0, 60.6666666667, 63.3333333333}, | 
709  |  |     {0, 0, 33, 16.5, 0, 60.6666666667, 63.3333333333}, | 
710  |  |     {0, 0, 33, 18.5, 0, 64.6666666667, 67.3333333333}, | 
711  |  |     {0, 0, 33, 19, 0, 64.6666666667, 67.3333333333}, | 
712  |  |     {0, 0, 55, -5.4, 22.5, 20.9075742561, 24.0921050540}, | 
713  |  |     {0, 0, 55, -5.4, 26.1, 24.5075340813, 27.6921073632}, | 
714  |  |     {0, 0, 55, -5.4, 29.7, 28.1063294800, 31.2932791054}, | 
715  |  |     {0, 0, 55, -5.4, 33.3, 31.72786641202, 34.8717272112}, | 
716  |  |     {0, 0, 62, -70.5, 41, 41.2833333333, 41.4833333333}, | 
717  |  |     {0, 0, 62, -77.75, 39.3333333333, 39.9333333333, 40.9666666667}, | 
718  |  |     {0, 0, 62, -91.3333333333, 25.6666666667, 26.1666666667, 27.8333333333}, | 
719  |  |     {0, 0, 62, -91.3333333333, 28.6666666667, 29.3, 30.67}, | 
720  |  |     {0, 0, 62, -96, 23, 20, 60}, | 
721  |  |     {0, 0, 62, -96, 23, 33, 45}, | 
722  |  |     {0, 0, 62, -96, 39, 33, 45}, | 
723  |  |     {0, 0, 66, -68.5, 44, 46, 60}, | 
724  |  |     {0, 0, 74, -100.3333333333, 42.3333333333, 42.8333333333, 44.4}, | 
725  |  |     {0, 0, 74, -100, 39.8333333333, 40, 43}, | 
726  |  |     {0, 0, 74, -100, 43.8333333333, 44.4166666667, 45.6833333333}, | 
727  |  |     {0, 0, 74, -109.5, 44.25, 45, 49}, | 
728  |  |     {0, 0, 74, -111.5, 36.6666666667, 37.2166666667, 38.35}, | 
729  |  |     {0, 0, 74, -111.5, 38.3333333333, 39.0166666667, 40.65}, | 
730  |  |     {0, 0, 74, -111.5, 40.3333333333, 40.7166666667, 41.7833333333}, | 
731  |  |     {0, 0, 74, -120.5, 41.6666666667, 42.3333333333, 44}, | 
732  |  |     {0, 0, 74, -120.5, 43.6666666667, 44.3333333333, 46}, | 
733  |  |     {0, 0, 74, -176, 51, 51.8333333333, 53.8333333333}, | 
734  |  |     {0, 0, 74, -66.4333333333, 17.8333333333, 18.0333333333, 18.4333333333}, | 
735  |  |     {0, 0, 74, -68.5, 44, 46, 60}, | 
736  |  |     {0, 0, 74, -79.5, 38.5, 39, 40.25}, | 
737  |  |     {0, 0, 74, -81, 31.8333333333, 32.5, 34.8333333333}, | 
738  |  |     {0, 0, 74, -81, 37, 37.4833333333, 38.8833333333}, | 
739  |  |     {0, 0, 74, -82.5, 38, 38.7333333333, 40.0333333333}, | 
740  |  |     {0, 0, 74, -82.5, 39.6666666667, 40.4333333333, 41.7}, | 
741  |  |     {0, 0, 74, -84.25, 37.5, 37.9666666667, 38.9666666667}, | 
742  |  |     {0, 0, 74, -84.3666666667, 41.5, 42.1, 43.6666666667}, | 
743  |  |     {0, 0, 74, -84.3666666667, 43.3166666667, 44.1833333333, 45.7}, | 
744  |  |     {0, 0, 74, -87, 44.7833333333, 45.4833333333, 47.0833333333}, | 
745  |  |     {0, 0, 74, -91.3333333333, 25.5, 26.1666666667, 27.8333333333}, | 
746  |  |     {0, 0, 74, -91.3333333333, 28.5, 29.3, 30.7}, | 
747  |  |     {0, 0, 74, -92, 32.6666666667, 33.3, 34.7666666667}, | 
748  |  |     {0, 0, 74, -92, 34.3333333333, 34.9333333333, 36.2333333333}, | 
749  |  |     {0, 0, 74, -92.5, 30.5, 31.1666666667, 32.6666666667}, | 
750  |  |     {0, 0, 74, -93.1, 46.5, 47.0333333333, 48.6333333333}, | 
751  |  |     {0, 0, 74, -93.5, 40, 40.6166666667, 41.7833333333}, | 
752  |  |     {0, 0, 74, -93.5, 41.5, 42.0666666667, 43.2666666667}, | 
753  |  |     {0, 0, 74, -94.25, 45, 45.6166666667, 47.05}, | 
754  |  |     {0, 0, 74, -94, 43, 43.7833333333, 45.2166666667}, | 
755  |  |     {0, 0, 74, -98, 38.3333333333, 38.7166666667, 39.7833333333}, | 
756  |  |     {0, 0, 74, -98.5, 36.6666666667, 38.5666666667, 37.2666666667}, | 
757  |  | };  | 
758  |  |  | 
759  |  | /**********************************************************************  | 
760  |  |  *                   TABFile::GetSpatialRefFromTABProj()  | 
761  |  |  **********************************************************************/  | 
762  |  |  | 
763  |  | static bool TAB_EQUAL(double a, double b)  | 
764  | 0  | { | 
765  | 0  |     return std::fabs(a - b) < 1.0e-10;  | 
766  | 0  | }  | 
767  |  |  | 
768  |  | OGRSpatialReference *  | 
769  |  | TABFileGetSpatialRefFromTABProj(const TABProjInfo &sTABProj)  | 
770  | 0  | { | 
771  |  |     /*-----------------------------------------------------------------  | 
772  |  |      * Get the units name, and translation factor.  | 
773  |  |      *----------------------------------------------------------------*/  | 
774  | 0  |     const char *pszUnitsName = nullptr;  | 
775  | 0  |     const char *pszUnitsConv = nullptr;  | 
776  |  |     /* double      dfConv = 1.0; */  | 
777  |  | 
  | 
778  | 0  |     switch (sTABProj.nUnitsId)  | 
779  | 0  |     { | 
780  | 0  |         case 0:  | 
781  | 0  |             pszUnitsName = "Mile";  | 
782  | 0  |             pszUnitsConv = "1609.344";  | 
783  | 0  |             break;  | 
784  |  |  | 
785  | 0  |         case 1:  | 
786  | 0  |             pszUnitsName = "Kilometer";  | 
787  | 0  |             pszUnitsConv = "1000.0";  | 
788  | 0  |             break;  | 
789  |  |  | 
790  | 0  |         case 2:  | 
791  | 0  |             pszUnitsName = "IINCH";  | 
792  | 0  |             pszUnitsConv = "0.0254";  | 
793  | 0  |             break;  | 
794  |  |  | 
795  | 0  |         case 3:  | 
796  | 0  |             pszUnitsName = SRS_UL_FOOT;  | 
797  | 0  |             pszUnitsConv = SRS_UL_FOOT_CONV;  | 
798  | 0  |             break;  | 
799  |  |  | 
800  | 0  |         case 4:  | 
801  | 0  |             pszUnitsName = "IYARD";  | 
802  | 0  |             pszUnitsConv = "0.9144";  | 
803  | 0  |             break;  | 
804  |  |  | 
805  | 0  |         case 5:  | 
806  | 0  |             pszUnitsName = "Millimeter";  | 
807  | 0  |             pszUnitsConv = "0.001";  | 
808  | 0  |             break;  | 
809  |  |  | 
810  | 0  |         case 6:  | 
811  | 0  |             pszUnitsName = "Centimeter";  | 
812  | 0  |             pszUnitsConv = "0.01";  | 
813  | 0  |             break;  | 
814  |  |  | 
815  | 0  |         case 7:  | 
816  | 0  |             pszUnitsName = SRS_UL_METER;  | 
817  | 0  |             pszUnitsConv = "1.0";  | 
818  | 0  |             break;  | 
819  |  |  | 
820  | 0  |         case 8:  | 
821  | 0  |             pszUnitsName = SRS_UL_US_FOOT;  | 
822  | 0  |             pszUnitsConv = SRS_UL_US_FOOT_CONV;  | 
823  | 0  |             break;  | 
824  |  |  | 
825  | 0  |         case 9:  | 
826  | 0  |             pszUnitsName = SRS_UL_NAUTICAL_MILE;  | 
827  | 0  |             pszUnitsConv = SRS_UL_NAUTICAL_MILE_CONV;  | 
828  | 0  |             break;  | 
829  |  |  | 
830  | 0  |         case 30:  | 
831  | 0  |             pszUnitsName = SRS_UL_LINK;  | 
832  | 0  |             pszUnitsConv = SRS_UL_LINK_CONV;  | 
833  | 0  |             break;  | 
834  |  |  | 
835  | 0  |         case 31:  | 
836  | 0  |             pszUnitsName = SRS_UL_CHAIN;  | 
837  | 0  |             pszUnitsConv = SRS_UL_CHAIN_CONV;  | 
838  | 0  |             break;  | 
839  |  |  | 
840  | 0  |         case 32:  | 
841  | 0  |             pszUnitsName = SRS_UL_ROD;  | 
842  | 0  |             pszUnitsConv = SRS_UL_ROD_CONV;  | 
843  | 0  |             break;  | 
844  |  |  | 
845  | 0  |         default:  | 
846  | 0  |             pszUnitsName = SRS_UL_METER;  | 
847  | 0  |             pszUnitsConv = "1.0";  | 
848  | 0  |             break;  | 
849  | 0  |     }  | 
850  |  |  | 
851  |  |     /* dfConv = CPLAtof(pszUnitsConv); */  | 
852  |  |  | 
853  |  |     /*-----------------------------------------------------------------  | 
854  |  |      * Transform them into an OGRSpatialReference.  | 
855  |  |      *----------------------------------------------------------------*/  | 
856  | 0  |     OGRSpatialReference *poSpatialRef = new OGRSpatialReference;  | 
857  | 0  |     poSpatialRef->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);  | 
858  |  |  | 
859  |  |     /*-----------------------------------------------------------------  | 
860  |  |      * Handle the PROJCS style projections, but add the datum later.  | 
861  |  |      *----------------------------------------------------------------*/  | 
862  | 0  |     switch (sTABProj.nProjId)  | 
863  | 0  |     { | 
864  | 0  |         case 0:  | 
865  | 0  |             poSpatialRef->SetLocalCS("Nonearth"); | 
866  | 0  |             poSpatialRef->SetLinearUnits(pszUnitsName, CPLAtof(pszUnitsConv));  | 
867  | 0  |             break;  | 
868  |  |  | 
869  |  |             /*--------------------------------------------------------------  | 
870  |  |              * lat/long .. just add the GEOGCS later.  | 
871  |  |              *-------------------------------------------------------------*/  | 
872  | 0  |         case 1:  | 
873  | 0  |             break;  | 
874  |  |  | 
875  |  |             /*--------------------------------------------------------------  | 
876  |  |              * Cylindrical Equal Area  | 
877  |  |              *-------------------------------------------------------------*/  | 
878  | 0  |         case 2:  | 
879  | 0  |             poSpatialRef->SetCEA(  | 
880  | 0  |                 sTABProj.adProjParams[1], sTABProj.adProjParams[0],  | 
881  | 0  |                 sTABProj.adProjParams[2], sTABProj.adProjParams[3]);  | 
882  | 0  |             break;  | 
883  |  |  | 
884  |  |             /*--------------------------------------------------------------  | 
885  |  |              * Lambert Conic Conformal  | 
886  |  |              *-------------------------------------------------------------*/  | 
887  | 0  |         case 3:  | 
888  | 0  |             poSpatialRef->SetLCC(  | 
889  | 0  |                 sTABProj.adProjParams[2], sTABProj.adProjParams[3],  | 
890  | 0  |                 sTABProj.adProjParams[1], sTABProj.adProjParams[0],  | 
891  | 0  |                 sTABProj.adProjParams[4], sTABProj.adProjParams[5]);  | 
892  | 0  |             break;  | 
893  |  |  | 
894  |  |             /*--------------------------------------------------------------  | 
895  |  |              * Lambert Azimuthal Equal Area  | 
896  |  |              *-------------------------------------------------------------*/  | 
897  | 0  |         case 4:  | 
898  | 0  |         case 29:  | 
899  | 0  |             poSpatialRef->SetLAEA(sTABProj.adProjParams[1],  | 
900  | 0  |                                   sTABProj.adProjParams[0], 0.0, 0.0);  | 
901  | 0  |             break;  | 
902  |  |  | 
903  |  |             /*--------------------------------------------------------------  | 
904  |  |              * Azimuthal Equidistant (Polar aspect only)  | 
905  |  |              *-------------------------------------------------------------*/  | 
906  | 0  |         case 5:  | 
907  | 0  |         case 28:  | 
908  | 0  |             poSpatialRef->SetAE(sTABProj.adProjParams[1],  | 
909  | 0  |                                 sTABProj.adProjParams[0], 0.0, 0.0);  | 
910  | 0  |             break;  | 
911  |  |  | 
912  |  |             /*--------------------------------------------------------------  | 
913  |  |              * Equidistant Conic  | 
914  |  |              *-------------------------------------------------------------*/  | 
915  | 0  |         case 6:  | 
916  | 0  |             poSpatialRef->SetEC(  | 
917  | 0  |                 sTABProj.adProjParams[2], sTABProj.adProjParams[3],  | 
918  | 0  |                 sTABProj.adProjParams[1], sTABProj.adProjParams[0],  | 
919  | 0  |                 sTABProj.adProjParams[4], sTABProj.adProjParams[5]);  | 
920  | 0  |             break;  | 
921  |  |  | 
922  |  |             /*--------------------------------------------------------------  | 
923  |  |              * Hotine Oblique Mercator  | 
924  |  |              *-------------------------------------------------------------*/  | 
925  | 0  |         case 7:  | 
926  | 0  |             poSpatialRef->SetHOM(  | 
927  | 0  |                 sTABProj.adProjParams[1], sTABProj.adProjParams[0],  | 
928  | 0  |                 sTABProj.adProjParams[2], 90.0, sTABProj.adProjParams[3],  | 
929  | 0  |                 sTABProj.adProjParams[4], sTABProj.adProjParams[5]);  | 
930  | 0  |             break;  | 
931  |  |  | 
932  |  |             /*--------------------------------------------------------------  | 
933  |  |              * Hotine Oblique Mercator with Angle from Rectified to Skew Grid  | 
934  |  |              *-------------------------------------------------------------*/  | 
935  | 0  |         case 35:  | 
936  | 0  |             poSpatialRef->SetHOM(  | 
937  | 0  |                 sTABProj.adProjParams[1], sTABProj.adProjParams[0],  | 
938  | 0  |                 sTABProj.adProjParams[2], sTABProj.adProjParams[3],  | 
939  | 0  |                 sTABProj.adProjParams[4], sTABProj.adProjParams[5],  | 
940  | 0  |                 sTABProj.adProjParams[6]);  | 
941  | 0  |             break;  | 
942  |  |  | 
943  |  |             /*--------------------------------------------------------------  | 
944  |  |              * Transverse Mercator  | 
945  |  |              *-------------------------------------------------------------*/  | 
946  | 0  |         case 8:  | 
947  | 0  |         case 34:  // Extended Transverse Mercator  | 
948  | 0  |             poSpatialRef->SetTM(  | 
949  | 0  |                 sTABProj.adProjParams[1], sTABProj.adProjParams[0],  | 
950  | 0  |                 sTABProj.adProjParams[2], sTABProj.adProjParams[3],  | 
951  | 0  |                 sTABProj.adProjParams[4]);  | 
952  | 0  |             break;  | 
953  |  |  | 
954  |  |             /*----------------------------------------------------------------  | 
955  |  |              * Transverse Mercator,(modified for Danish System 34 Jylland-Fyn)  | 
956  |  |              *---------------------------------------------------------------*/  | 
957  | 0  |         case 21:  | 
958  |  |             // poSpatialRef->SetTMVariant( SRS_PT_TRANSVERSE_MERCATOR_MI_21,  | 
959  | 0  |             poSpatialRef->SetTM(  | 
960  | 0  |                 sTABProj.adProjParams[1], sTABProj.adProjParams[0],  | 
961  | 0  |                 sTABProj.adProjParams[2], sTABProj.adProjParams[3],  | 
962  | 0  |                 sTABProj.adProjParams[4]);  | 
963  | 0  |             break;  | 
964  |  |  | 
965  |  |             /*--------------------------------------------------------------  | 
966  |  |              * Transverse Mercator,(modified for Danish System 34 Sjaelland)  | 
967  |  |              *-------------------------------------------------------------*/  | 
968  | 0  |         case 22:  | 
969  |  |             // poSpatialRef->SetTMVariant( SRS_PT_TRANSVERSE_MERCATOR_MI_22,  | 
970  | 0  |             poSpatialRef->SetTM(  | 
971  | 0  |                 sTABProj.adProjParams[1], sTABProj.adProjParams[0],  | 
972  | 0  |                 sTABProj.adProjParams[2], sTABProj.adProjParams[3],  | 
973  | 0  |                 sTABProj.adProjParams[4]);  | 
974  | 0  |             break;  | 
975  |  |  | 
976  |  |             /*----------------------------------------------------------------  | 
977  |  |              * Transverse Mercator,(modified for Danish System 34/45 Bornholm)  | 
978  |  |              *---------------------------------------------------------------*/  | 
979  | 0  |         case 23:  | 
980  |  |             // poSpatialRef->SetTMVariant( SRS_PT_TRANSVERSE_MERCATOR_MI_23,  | 
981  | 0  |             poSpatialRef->SetTM(  | 
982  | 0  |                 sTABProj.adProjParams[1], sTABProj.adProjParams[0],  | 
983  | 0  |                 sTABProj.adProjParams[2], sTABProj.adProjParams[3],  | 
984  | 0  |                 sTABProj.adProjParams[4]);  | 
985  | 0  |             break;  | 
986  |  |  | 
987  |  |             /*--------------------------------------------------------------  | 
988  |  |              * Transverse Mercator,(modified for Finnish KKJ)  | 
989  |  |              *-------------------------------------------------------------*/  | 
990  | 0  |         case 24:  | 
991  |  |             // poSpatialRef->SetTMVariant( SRS_PT_TRANSVERSE_MERCATOR_MI_24,  | 
992  | 0  |             poSpatialRef->SetTM(  | 
993  | 0  |                 sTABProj.adProjParams[1], sTABProj.adProjParams[0],  | 
994  | 0  |                 sTABProj.adProjParams[2], sTABProj.adProjParams[3],  | 
995  | 0  |                 sTABProj.adProjParams[4]);  | 
996  | 0  |             break;  | 
997  |  |  | 
998  |  |             /*--------------------------------------------------------------  | 
999  |  |              * Albers Conic Equal Area  | 
1000  |  |              *-------------------------------------------------------------*/  | 
1001  | 0  |         case 9:  | 
1002  | 0  |             poSpatialRef->SetACEA(  | 
1003  | 0  |                 sTABProj.adProjParams[2], sTABProj.adProjParams[3],  | 
1004  | 0  |                 sTABProj.adProjParams[1], sTABProj.adProjParams[0],  | 
1005  | 0  |                 sTABProj.adProjParams[4], sTABProj.adProjParams[5]);  | 
1006  | 0  |             break;  | 
1007  |  |  | 
1008  |  |             /*--------------------------------------------------------------  | 
1009  |  |              * Mercator  | 
1010  |  |              *-------------------------------------------------------------*/  | 
1011  | 0  |         case 10:  | 
1012  | 0  |             poSpatialRef->SetMercator(0.0, sTABProj.adProjParams[0], 1.0, 0.0,  | 
1013  | 0  |                                       0.0);  | 
1014  | 0  |             break;  | 
1015  |  |  | 
1016  |  |             /*--------------------------------------------------------------  | 
1017  |  |              * Miller Cylindrical  | 
1018  |  |              *-------------------------------------------------------------*/  | 
1019  | 0  |         case 11:  | 
1020  | 0  |             poSpatialRef->SetMC(0.0, sTABProj.adProjParams[0], 0.0, 0.0);  | 
1021  | 0  |             break;  | 
1022  |  |  | 
1023  |  |             /*--------------------------------------------------------------  | 
1024  |  |              * Robinson  | 
1025  |  |              *-------------------------------------------------------------*/  | 
1026  | 0  |         case 12:  | 
1027  | 0  |             poSpatialRef->SetRobinson(sTABProj.adProjParams[0], 0.0, 0.0);  | 
1028  | 0  |             break;  | 
1029  |  |  | 
1030  |  |             /*--------------------------------------------------------------  | 
1031  |  |              * Mollweide  | 
1032  |  |              *-------------------------------------------------------------*/  | 
1033  | 0  |         case 13:  | 
1034  | 0  |             poSpatialRef->SetMollweide(sTABProj.adProjParams[0], 0.0, 0.0);  | 
1035  | 0  |             break;  | 
1036  |  |  | 
1037  |  |             /*--------------------------------------------------------------  | 
1038  |  |              * Eckert IV  | 
1039  |  |              *-------------------------------------------------------------*/  | 
1040  | 0  |         case 14:  | 
1041  | 0  |             poSpatialRef->SetEckertIV(sTABProj.adProjParams[0], 0.0, 0.0);  | 
1042  | 0  |             break;  | 
1043  |  |  | 
1044  |  |             /*--------------------------------------------------------------  | 
1045  |  |              * Eckert VI  | 
1046  |  |              *-------------------------------------------------------------*/  | 
1047  | 0  |         case 15:  | 
1048  | 0  |             poSpatialRef->SetEckertVI(sTABProj.adProjParams[0], 0.0, 0.0);  | 
1049  | 0  |             break;  | 
1050  |  |  | 
1051  |  |             /*--------------------------------------------------------------  | 
1052  |  |              * Sinusoidal  | 
1053  |  |              *-------------------------------------------------------------*/  | 
1054  | 0  |         case 16:  | 
1055  | 0  |             poSpatialRef->SetSinusoidal(sTABProj.adProjParams[0], 0.0, 0.0);  | 
1056  | 0  |             break;  | 
1057  |  |  | 
1058  |  |             /*--------------------------------------------------------------  | 
1059  |  |              * Gall Stereographic  | 
1060  |  |              *-------------------------------------------------------------*/  | 
1061  | 0  |         case 17:  | 
1062  | 0  |             poSpatialRef->SetGS(sTABProj.adProjParams[0], 0.0, 0.0);  | 
1063  | 0  |             break;  | 
1064  |  |  | 
1065  |  |             /*--------------------------------------------------------------  | 
1066  |  |              * New Zealand Map Grid  | 
1067  |  |              *-------------------------------------------------------------*/  | 
1068  | 0  |         case 18:  | 
1069  | 0  |             poSpatialRef->SetNZMG(  | 
1070  | 0  |                 sTABProj.adProjParams[1], sTABProj.adProjParams[0],  | 
1071  | 0  |                 sTABProj.adProjParams[2], sTABProj.adProjParams[3]);  | 
1072  | 0  |             break;  | 
1073  |  |  | 
1074  |  |             /*--------------------------------------------------------------  | 
1075  |  |              * Lambert Conic Conformal (Belgium)  | 
1076  |  |              *-------------------------------------------------------------*/  | 
1077  | 0  |         case 19:  | 
1078  | 0  |             poSpatialRef->SetLCCB(  | 
1079  | 0  |                 sTABProj.adProjParams[2], sTABProj.adProjParams[3],  | 
1080  | 0  |                 sTABProj.adProjParams[1], sTABProj.adProjParams[0],  | 
1081  | 0  |                 sTABProj.adProjParams[4], sTABProj.adProjParams[5]);  | 
1082  | 0  |             break;  | 
1083  |  |  | 
1084  |  |             /*--------------------------------------------------------------  | 
1085  |  |              * Stereographic  | 
1086  |  |              *-------------------------------------------------------------*/  | 
1087  | 0  |         case 20:  | 
1088  | 0  |             poSpatialRef->SetStereographic(  | 
1089  | 0  |                 sTABProj.adProjParams[1], sTABProj.adProjParams[0],  | 
1090  | 0  |                 sTABProj.adProjParams[2], sTABProj.adProjParams[3],  | 
1091  | 0  |                 sTABProj.adProjParams[4]);  | 
1092  | 0  |             break;  | 
1093  |  |  | 
1094  |  |             /*--------------------------------------------------------------  | 
1095  |  |              * Swiss Oblique Mercator / Cylindrical  | 
1096  |  |              *-------------------------------------------------------------*/  | 
1097  | 0  |         case 25:  | 
1098  | 0  |             poSpatialRef->SetSOC(  | 
1099  | 0  |                 sTABProj.adProjParams[1], sTABProj.adProjParams[0],  | 
1100  | 0  |                 sTABProj.adProjParams[2], sTABProj.adProjParams[3]);  | 
1101  | 0  |             break;  | 
1102  |  |  | 
1103  |  |             /*--------------------------------------------------------------  | 
1104  |  |              * Regional Mercator (regular mercator with a latitude).  | 
1105  |  |              *-------------------------------------------------------------*/  | 
1106  | 0  |         case 26:  | 
1107  | 0  |             poSpatialRef->SetMercator2SP(sTABProj.adProjParams[1], 0.0,  | 
1108  | 0  |                                          sTABProj.adProjParams[0], 0.0, 0.0);  | 
1109  | 0  |             break;  | 
1110  |  |  | 
1111  |  |             /*--------------------------------------------------------------  | 
1112  |  |              * Polyconic  | 
1113  |  |              *-------------------------------------------------------------*/  | 
1114  | 0  |         case 27:  | 
1115  | 0  |             poSpatialRef->SetPolyconic(  | 
1116  | 0  |                 sTABProj.adProjParams[1], sTABProj.adProjParams[0],  | 
1117  | 0  |                 sTABProj.adProjParams[2], sTABProj.adProjParams[3]);  | 
1118  | 0  |             break;  | 
1119  |  |  | 
1120  |  |             /*--------------------------------------------------------------  | 
1121  |  |              * Cassini/Soldner  | 
1122  |  |              *-------------------------------------------------------------*/  | 
1123  | 0  |         case 30:  | 
1124  | 0  |             poSpatialRef->SetCS(  | 
1125  | 0  |                 sTABProj.adProjParams[1], sTABProj.adProjParams[0],  | 
1126  | 0  |                 sTABProj.adProjParams[2], sTABProj.adProjParams[3]);  | 
1127  | 0  |             break;  | 
1128  |  |  | 
1129  |  |             /*--------------------------------------------------------------  | 
1130  |  |              * Oblique Stereographic  | 
1131  |  |              *-------------------------------------------------------------*/  | 
1132  | 0  |         case 31:  | 
1133  | 0  |             poSpatialRef->SetOS(  | 
1134  | 0  |                 sTABProj.adProjParams[1], sTABProj.adProjParams[0],  | 
1135  | 0  |                 sTABProj.adProjParams[2], sTABProj.adProjParams[3],  | 
1136  | 0  |                 sTABProj.adProjParams[4]);  | 
1137  | 0  |             break;  | 
1138  |  |  | 
1139  |  |             /*--------------------------------------------------------------  | 
1140  |  |              * Krovak  | 
1141  |  |              *-------------------------------------------------------------*/  | 
1142  | 0  |         case 32:  | 
1143  | 0  |             poSpatialRef->SetKrovak(  | 
1144  | 0  |                 sTABProj.adProjParams[1],   // dfCenterLat  | 
1145  | 0  |                 sTABProj.adProjParams[0],   // dfCenterLong  | 
1146  | 0  |                 sTABProj.adProjParams[3],   // dfAzimuth  | 
1147  | 0  |                 sTABProj.adProjParams[2],   // dfPseudoStdParallelLat  | 
1148  | 0  |                 1.0,                        // dfScale  | 
1149  | 0  |                 sTABProj.adProjParams[4],   // dfFalseEasting  | 
1150  | 0  |                 sTABProj.adProjParams[5]);  // dfFalseNorthing  | 
1151  | 0  |             break;  | 
1152  |  |  | 
1153  |  |             /*--------------------------------------------------------------  | 
1154  |  |              * Equidistant Cylindrical / Equirectangular  | 
1155  |  |              *-------------------------------------------------------------*/  | 
1156  | 0  |         case 33:  | 
1157  | 0  |             poSpatialRef->SetEquirectangular(  | 
1158  | 0  |                 sTABProj.adProjParams[1], sTABProj.adProjParams[0],  | 
1159  | 0  |                 sTABProj.adProjParams[2], sTABProj.adProjParams[3]);  | 
1160  | 0  |             break;  | 
1161  |  |  | 
1162  | 0  |         default:  | 
1163  | 0  |             poSpatialRef->SetProjection(CPLSPrintf(  | 
1164  | 0  |                 "Unhandled MapInfo projection method %d", sTABProj.nProjId));  | 
1165  | 0  |             break;  | 
1166  | 0  |     }  | 
1167  |  |  | 
1168  |  |     /*-----------------------------------------------------------------  | 
1169  |  |      * Local (nonearth) coordinate systems have no Geographic relationship  | 
1170  |  |      * so we just return from here.  | 
1171  |  |      *----------------------------------------------------------------*/  | 
1172  | 0  |     if (sTABProj.nProjId == 0)  | 
1173  | 0  |         return poSpatialRef;  | 
1174  |  |  | 
1175  |  |     /*-----------------------------------------------------------------  | 
1176  |  |      * Set the datum.  We are only given the X, Y and Z shift for  | 
1177  |  |      * the datum, so for now we just synthesize a name from this.  | 
1178  |  |      * It would be better if we could lookup a name based on the shift.  | 
1179  |  |      *  | 
1180  |  |      * Since we have already encountered files in which adDatumParams[] values  | 
1181  |  |      * were in the order of 1e-150 when they should have actually been zeros,  | 
1182  |  |      * we will use an epsilon in our scan instead of looking for equality.  | 
1183  |  |      *----------------------------------------------------------------*/  | 
1184  | 0  |     const MapInfoDatumInfo *psDatumInfo = nullptr;  | 
1185  |  | 
  | 
1186  | 0  |     for (int iDatumInfo = 0; asDatumInfoList[iDatumInfo].nMapInfoDatumID != -1;  | 
1187  | 0  |          iDatumInfo++)  | 
1188  | 0  |     { | 
1189  | 0  |         psDatumInfo = asDatumInfoList + iDatumInfo;  | 
1190  |  | 
  | 
1191  | 0  |         if (TAB_EQUAL(psDatumInfo->nEllipsoid, sTABProj.nEllipsoidId) &&  | 
1192  | 0  |             ((sTABProj.nDatumId > 0 &&  | 
1193  | 0  |               sTABProj.nDatumId == psDatumInfo->nMapInfoDatumID) ||  | 
1194  | 0  |              (sTABProj.nDatumId <= 0 &&  | 
1195  | 0  |               TAB_EQUAL(psDatumInfo->dfShiftX, sTABProj.dDatumShiftX) &&  | 
1196  | 0  |               TAB_EQUAL(psDatumInfo->dfShiftY, sTABProj.dDatumShiftY) &&  | 
1197  | 0  |               TAB_EQUAL(psDatumInfo->dfShiftZ, sTABProj.dDatumShiftZ) &&  | 
1198  | 0  |               TAB_EQUAL(psDatumInfo->dfDatumParm0, sTABProj.adDatumParams[0]) &&  | 
1199  | 0  |               TAB_EQUAL(psDatumInfo->dfDatumParm1, sTABProj.adDatumParams[1]) &&  | 
1200  | 0  |               TAB_EQUAL(psDatumInfo->dfDatumParm2, sTABProj.adDatumParams[2]) &&  | 
1201  | 0  |               TAB_EQUAL(psDatumInfo->dfDatumParm3, sTABProj.adDatumParams[3]) &&  | 
1202  | 0  |               TAB_EQUAL(psDatumInfo->dfDatumParm4, sTABProj.adDatumParams[4]))))  | 
1203  | 0  |             break;  | 
1204  |  |  | 
1205  | 0  |         psDatumInfo = nullptr;  | 
1206  | 0  |     }  | 
1207  |  | 
  | 
1208  | 0  |     char szDatumName[200] = {}; | 
1209  | 0  |     if (psDatumInfo == nullptr)  | 
1210  | 0  |     { | 
1211  | 0  |         if (sTABProj.adDatumParams[0] == 0.0 &&  | 
1212  | 0  |             sTABProj.adDatumParams[1] == 0.0 &&  | 
1213  | 0  |             sTABProj.adDatumParams[2] == 0.0 &&  | 
1214  | 0  |             sTABProj.adDatumParams[3] == 0.0 &&  | 
1215  | 0  |             sTABProj.adDatumParams[4] == 0.0)  | 
1216  | 0  |         { | 
1217  | 0  |             snprintf(szDatumName, sizeof(szDatumName),  | 
1218  | 0  |                      "MIF 999,%u,%.15g,%.15g,%.15g", sTABProj.nEllipsoidId,  | 
1219  | 0  |                      sTABProj.dDatumShiftX, sTABProj.dDatumShiftY,  | 
1220  | 0  |                      sTABProj.dDatumShiftZ);  | 
1221  | 0  |         }  | 
1222  | 0  |         else  | 
1223  | 0  |         { | 
1224  | 0  |             snprintf(  | 
1225  | 0  |                 szDatumName, sizeof(szDatumName),  | 
1226  | 0  |                 "MIF 9999,%u,%.15g,%.15g,%.15g,%.15g,%.15g,%.15g,%.15g,%.15g",  | 
1227  | 0  |                 sTABProj.nEllipsoidId, sTABProj.dDatumShiftX,  | 
1228  | 0  |                 sTABProj.dDatumShiftY, sTABProj.dDatumShiftZ,  | 
1229  | 0  |                 sTABProj.adDatumParams[0], sTABProj.adDatumParams[1],  | 
1230  | 0  |                 sTABProj.adDatumParams[2], sTABProj.adDatumParams[3],  | 
1231  | 0  |                 sTABProj.adDatumParams[4]);  | 
1232  | 0  |         }  | 
1233  | 0  |     }  | 
1234  | 0  |     else if (strlen(psDatumInfo->pszOGCDatumName) > 0)  | 
1235  | 0  |     { | 
1236  | 0  |         CPLStrlcpy(szDatumName, psDatumInfo->pszOGCDatumName,  | 
1237  | 0  |                    sizeof(szDatumName));  | 
1238  | 0  |     }  | 
1239  | 0  |     else  | 
1240  | 0  |     { | 
1241  | 0  |         snprintf(szDatumName, sizeof(szDatumName), "MIF %d",  | 
1242  | 0  |                  psDatumInfo->nMapInfoDatumID);  | 
1243  | 0  |     }  | 
1244  |  |  | 
1245  |  |     /*-----------------------------------------------------------------  | 
1246  |  |      * Set the spheroid.  | 
1247  |  |      *----------------------------------------------------------------*/  | 
1248  | 0  |     double dfSemiMajor = 0.0;  | 
1249  | 0  |     double dfInvFlattening = 0.0;  | 
1250  | 0  |     const char *pszSpheroidName = nullptr;  | 
1251  |  | 
  | 
1252  | 0  |     for (int i = 0; asSpheroidInfoList[i].nMapInfoId != -1; i++)  | 
1253  | 0  |     { | 
1254  | 0  |         if (asSpheroidInfoList[i].nMapInfoId == sTABProj.nEllipsoidId)  | 
1255  | 0  |         { | 
1256  | 0  |             dfSemiMajor = asSpheroidInfoList[i].dfA;  | 
1257  | 0  |             dfInvFlattening = asSpheroidInfoList[i].dfInvFlattening;  | 
1258  | 0  |             pszSpheroidName = asSpheroidInfoList[i].pszMapinfoName;  | 
1259  | 0  |             break;  | 
1260  | 0  |         }  | 
1261  | 0  |     }  | 
1262  |  |  | 
1263  |  |     // use WGS 84 if nothing is known.  | 
1264  | 0  |     if (pszSpheroidName == nullptr)  | 
1265  | 0  |     { | 
1266  | 0  |         pszSpheroidName = "unknown";  | 
1267  | 0  |         dfSemiMajor = 6378137.0;  | 
1268  | 0  |         dfInvFlattening = 298.257223563;  | 
1269  | 0  |     }  | 
1270  |  |  | 
1271  |  |     /*-----------------------------------------------------------------  | 
1272  |  |      * Set the prime meridian.  | 
1273  |  |      *----------------------------------------------------------------*/  | 
1274  | 0  |     double dfPMOffset = 0.0;  | 
1275  | 0  |     const char *pszPMName = "Greenwich";  | 
1276  |  | 
  | 
1277  | 0  |     if (/*sTABProj.nDatumId == 9999 ||*/ sTABProj.adDatumParams[4] != 0.0)  | 
1278  | 0  |     { | 
1279  | 0  |         dfPMOffset = sTABProj.adDatumParams[4];  | 
1280  |  | 
  | 
1281  | 0  |         if (fabs(dfPMOffset - 2.337229166667) < 1e-10)  | 
1282  | 0  |             pszPMName = "Paris";  | 
1283  | 0  |         else  | 
1284  | 0  |             pszPMName = "non-Greenwich";  | 
1285  | 0  |     }  | 
1286  |  |  | 
1287  |  |     /*-----------------------------------------------------------------  | 
1288  |  |      * Create a GEOGCS definition.  | 
1289  |  |      *----------------------------------------------------------------*/  | 
1290  |  | 
  | 
1291  | 0  |     poSpatialRef->SetGeogCS("unnamed", szDatumName, pszSpheroidName, | 
1292  | 0  |                             dfSemiMajor, dfInvFlattening, pszPMName, dfPMOffset,  | 
1293  | 0  |                             SRS_UA_DEGREE, CPLAtof(SRS_UA_DEGREE_CONV));  | 
1294  |  | 
  | 
1295  | 0  |     if (psDatumInfo != nullptr)  | 
1296  | 0  |     { | 
1297  | 0  |         if (CPLTestBool(  | 
1298  | 0  |                 CPLGetConfigOption("MITAB_SET_TOWGS84_ON_KNOWN_DATUM", "NO"))) | 
1299  | 0  |         { | 
1300  | 0  |             poSpatialRef->SetTOWGS84(  | 
1301  | 0  |                 psDatumInfo->dfShiftX, psDatumInfo->dfShiftY,  | 
1302  | 0  |                 psDatumInfo->dfShiftZ,  | 
1303  | 0  |                 psDatumInfo->dfDatumParm0 == 0  | 
1304  | 0  |                     ? 0  | 
1305  | 0  |                     : -psDatumInfo->dfDatumParm0, /* avoids 0 to be transformed  | 
1306  |  |                                                      into -0 */  | 
1307  | 0  |                 psDatumInfo->dfDatumParm1 == 0 ? 0 : -psDatumInfo->dfDatumParm1,  | 
1308  | 0  |                 psDatumInfo->dfDatumParm2 == 0 ? 0 : -psDatumInfo->dfDatumParm2,  | 
1309  | 0  |                 psDatumInfo->dfDatumParm3);  | 
1310  | 0  |         }  | 
1311  | 0  |     }  | 
1312  | 0  |     else  | 
1313  | 0  |     { | 
1314  | 0  |         poSpatialRef->SetTOWGS84(  | 
1315  | 0  |             sTABProj.dDatumShiftX, sTABProj.dDatumShiftY, sTABProj.dDatumShiftZ,  | 
1316  | 0  |             sTABProj.adDatumParams[0] == 0 ? 0 : -sTABProj.adDatumParams[0],  | 
1317  | 0  |             sTABProj.adDatumParams[1] == 0 ? 0 : -sTABProj.adDatumParams[1],  | 
1318  | 0  |             sTABProj.adDatumParams[2] == 0 ? 0 : -sTABProj.adDatumParams[2],  | 
1319  | 0  |             sTABProj.adDatumParams[3]);  | 
1320  | 0  |     }  | 
1321  |  |  | 
1322  |  |     /*-----------------------------------------------------------------  | 
1323  |  |      * Special case for Google Mercator (datum=157, ellipse=54, gdal #4115)  | 
1324  |  |      *----------------------------------------------------------------*/  | 
1325  | 0  |     if (sTABProj.nProjId == 10 && sTABProj.nDatumId == 157 &&  | 
1326  | 0  |         sTABProj.nEllipsoidId == 54)  | 
1327  | 0  |     { | 
1328  | 0  |         poSpatialRef->SetNode("PROJCS", "WGS 84 / Pseudo-Mercator"); | 
1329  | 0  |         poSpatialRef->SetExtension(  | 
1330  | 0  |             "PROJCS", "PROJ4",  | 
1331  | 0  |             "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 "  | 
1332  | 0  |             "+y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext  +no_defs");  | 
1333  | 0  |     }  | 
1334  |  |  | 
1335  |  |     /*-----------------------------------------------------------------  | 
1336  |  |      * Special case for France Lambert-93  | 
1337  |  |      *----------------------------------------------------------------*/  | 
1338  | 0  |     if (sTABProj.nProjId == 3 && sTABProj.nDatumId == 33 &&  | 
1339  | 0  |         sTABProj.nEllipsoidId == 0 &&  | 
1340  | 0  |         TAB_EQUAL(poSpatialRef->GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0),  | 
1341  | 0  |                   3.0) &&  | 
1342  | 0  |         TAB_EQUAL(poSpatialRef->GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0),  | 
1343  | 0  |                   46.5))  | 
1344  | 0  |     { | 
1345  | 0  |         poSpatialRef->SetNode("PROJCS", "RGF93 / Lambert-93"); | 
1346  | 0  |         poSpatialRef->SetNode("PROJCS|GEOGCS", "RGF93"); | 
1347  | 0  |         poSpatialRef->SetNode("PROJCS|GEOGCS|DATUM", | 
1348  | 0  |                               "Reseau_Geodesique_Francais_1993");  | 
1349  | 0  |     }  | 
1350  |  | 
  | 
1351  | 0  |     if (sTABProj.nProjId == 3)  | 
1352  | 0  |     { | 
1353  |  |         // If the LCC_2SP can be turned into a LCC_1SP that has the same  | 
1354  |  |         // latitude of origin, then it is a better candidate  | 
1355  | 0  |         OGRSpatialReference *poLCC1SP = poSpatialRef->convertToOtherProjection(  | 
1356  | 0  |             SRS_PT_LAMBERT_CONFORMAL_CONIC_1SP);  | 
1357  | 0  |         if (poLCC1SP)  | 
1358  | 0  |         { | 
1359  | 0  |             if (TAB_EQUAL(  | 
1360  | 0  |                     poSpatialRef->GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,  | 
1361  | 0  |                                                   0.0),  | 
1362  | 0  |                     poLCC1SP->GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0)))  | 
1363  | 0  |             { | 
1364  | 0  |                 delete poSpatialRef;  | 
1365  | 0  |                 poSpatialRef = poLCC1SP;  | 
1366  | 0  |             }  | 
1367  | 0  |             else  | 
1368  | 0  |             { | 
1369  | 0  |                 delete poLCC1SP;  | 
1370  | 0  |             }  | 
1371  | 0  |         }  | 
1372  | 0  |     }  | 
1373  |  |  | 
1374  |  |     /* For LCC, standard parallel 1 and 2 can be switched indifferently */  | 
1375  |  |     /* So the MapInfo order and the EPSG order are not generally identical */  | 
1376  |  |     /* which may cause recognition problems when reading in MapInfo */  | 
1377  | 0  |     int nEPSGCandidateCode = 0;  | 
1378  | 0  |     if (sTABProj.nProjId == 3)  | 
1379  | 0  |     { | 
1380  | 0  |         double dfCenterLong = sTABProj.adProjParams[0];  | 
1381  | 0  |         double dfCenterLat = sTABProj.adProjParams[1];  | 
1382  | 0  |         double dfStdP1 = sTABProj.adProjParams[2];  | 
1383  | 0  |         double dfStdP2 = sTABProj.adProjParams[3];  | 
1384  |  | 
  | 
1385  | 0  |         for (size_t i = 0;  | 
1386  | 0  |              i < sizeof(asMapInfoLCCSRSList) / sizeof(asMapInfoLCCSRSList[0]);  | 
1387  | 0  |              i++)  | 
1388  | 0  |         { | 
1389  | 0  |             if (sTABProj.nDatumId == asMapInfoLCCSRSList[i].nMapInfoDatumID &&  | 
1390  | 0  |                 TAB_EQUAL(dfCenterLong, asMapInfoLCCSRSList[i].dfCenterLong) &&  | 
1391  | 0  |                 TAB_EQUAL(dfCenterLat, asMapInfoLCCSRSList[i].dfCenterLat))  | 
1392  | 0  |             { | 
1393  | 0  |                 if (TAB_EQUAL(dfStdP1, asMapInfoLCCSRSList[i].dfStdP1) &&  | 
1394  | 0  |                     (TAB_EQUAL(dfStdP2, asMapInfoLCCSRSList[i].dfStdP2) ||  | 
1395  |  |                      // EPSG:3301 "Estonian Coordinate System of 1997"  | 
1396  |  |                      // MapInfo uses a less accurate value of StdP2 than EPSG  | 
1397  | 0  |                      (TAB_EQUAL(asMapInfoLCCSRSList[i].dfStdP2, 59.33333333) &&  | 
1398  | 0  |                       TAB_EQUAL(dfStdP2, 59.3333333333333))))  | 
1399  | 0  |                 { | 
1400  | 0  |                     if (nEPSGCandidateCode)  | 
1401  | 0  |                     { | 
1402  | 0  |                         poSpatialRef->SetAuthority("PROJCS", "EPSG", | 
1403  | 0  |                                                    nEPSGCandidateCode);  | 
1404  | 0  |                         nEPSGCandidateCode = 0;  | 
1405  | 0  |                         break;  | 
1406  | 0  |                     }  | 
1407  | 0  |                     if (asMapInfoLCCSRSList[i].bReverseStdP)  | 
1408  | 0  |                     { | 
1409  | 0  |                         CPLDebug("MITAB", | 
1410  | 0  |                                  "Switching standard parallel 1 and 2");  | 
1411  | 0  |                         poSpatialRef->SetLCC(  | 
1412  | 0  |                             sTABProj.adProjParams[3], sTABProj.adProjParams[2],  | 
1413  | 0  |                             sTABProj.adProjParams[1], sTABProj.adProjParams[0],  | 
1414  | 0  |                             sTABProj.adProjParams[4], sTABProj.adProjParams[5]);  | 
1415  | 0  |                     }  | 
1416  | 0  |                     if (asMapInfoLCCSRSList[i].nEPSGCode > 0)  | 
1417  | 0  |                         nEPSGCandidateCode = asMapInfoLCCSRSList[i].nEPSGCode;  | 
1418  | 0  |                     else  | 
1419  | 0  |                         break;  | 
1420  | 0  |                 }  | 
1421  | 0  |             }  | 
1422  | 0  |         }  | 
1423  | 0  |     }  | 
1424  |  |  | 
1425  |  |     /*-----------------------------------------------------------------  | 
1426  |  |      * Apply linear units. Do that only after all above manipulations of  | 
1427  |  |      * projection parameters.  | 
1428  |  |      *----------------------------------------------------------------*/  | 
1429  | 0  |     if (sTABProj.nProjId != 0 && sTABProj.nProjId != 1 &&  | 
1430  | 0  |         CPLAtof(pszUnitsConv) != 1)  | 
1431  | 0  |     { | 
1432  | 0  |         poSpatialRef->SetTargetLinearUnits(nullptr, pszUnitsName,  | 
1433  | 0  |                                            CPLAtof(pszUnitsConv));  | 
1434  | 0  |     }  | 
1435  |  | 
  | 
1436  | 0  |     if (nEPSGCandidateCode)  | 
1437  | 0  |     { | 
1438  | 0  |         OGRSpatialReference oTmp;  | 
1439  | 0  |         oTmp.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);  | 
1440  | 0  |         if (oTmp.importFromEPSG(nEPSGCandidateCode) == OGRERR_NONE)  | 
1441  | 0  |         { | 
1442  | 0  |             *poSpatialRef = std::move(oTmp);  | 
1443  | 0  |         }  | 
1444  | 0  |     }  | 
1445  |  |  | 
1446  |  |     /*-----------------------------------------------------------------  | 
1447  |  |      * Special case for Philippine Reference System 1992, to override  | 
1448  |  |      * the MapInfo ellipsoid=8 "Clarke 1866 (modified for Michigan)"  | 
1449  |  |      * by the regular Clarke 1866 of EPSG  | 
1450  |  |      *----------------------------------------------------------------*/  | 
1451  | 0  |     if (sTABProj.nDatumId == 1031 && sTABProj.nEllipsoidId == 8)  | 
1452  | 0  |     { | 
1453  | 0  |         OGRSpatialReference oSRS_EPSG_4683;  | 
1454  | 0  |         if (oSRS_EPSG_4683.importFromEPSG(4683) == OGRERR_NONE)  | 
1455  | 0  |             poSpatialRef->CopyGeogCSFrom(&oSRS_EPSG_4683);  | 
1456  | 0  |     }  | 
1457  |  |  | 
1458  |  |     /*-----------------------------------------------------------------  | 
1459  |  |      * Special case for Kertau (RSO), to override  | 
1460  |  |      * the MapInfo ellipsoid=40 "Everest (India 1956)", 6377301.243, 300.80174  | 
1461  |  |      * with EPSG's "Everest 1830 (RSO 1969)",6377295.664,300.8017  | 
1462  |  |      *----------------------------------------------------------------*/  | 
1463  | 0  |     if (sTABProj.nDatumId == 164 && sTABProj.nEllipsoidId == 40)  | 
1464  | 0  |     { | 
1465  | 0  |         OGRSpatialReference oSRS_EPSG_4751;  | 
1466  | 0  |         if (oSRS_EPSG_4751.importFromEPSG(4751) == OGRERR_NONE)  | 
1467  | 0  |             poSpatialRef->CopyGeogCSFrom(&oSRS_EPSG_4751);  | 
1468  | 0  |     }  | 
1469  |  | 
  | 
1470  | 0  |     return poSpatialRef;  | 
1471  | 0  | }  | 
1472  |  |  | 
1473  |  | static int MITABGetCustomDatum(const OGRSpatialReference *poSpatialRef,  | 
1474  |  |                                TABProjInfo &sTABProj)  | 
1475  | 0  | { | 
1476  | 0  |     double adfTOWGS[7] = {0}; | 
1477  | 0  |     if (OGRERR_NONE != poSpatialRef->GetTOWGS84(  | 
1478  | 0  |                            adfTOWGS, sizeof(adfTOWGS) / sizeof(adfTOWGS[0])))  | 
1479  | 0  |     { | 
1480  | 0  |         return FALSE;  | 
1481  | 0  |     }  | 
1482  | 0  |     sTABProj.nDatumId = 9999;  | 
1483  | 0  |     sTABProj.dDatumShiftX = adfTOWGS[0];  | 
1484  | 0  |     sTABProj.dDatumShiftY = adfTOWGS[1];  | 
1485  | 0  |     sTABProj.dDatumShiftZ = adfTOWGS[2];  | 
1486  | 0  |     sTABProj.adDatumParams[0] = -adfTOWGS[3];  | 
1487  | 0  |     sTABProj.adDatumParams[1] = -adfTOWGS[4];  | 
1488  | 0  |     sTABProj.adDatumParams[2] = -adfTOWGS[5];  | 
1489  | 0  |     sTABProj.adDatumParams[3] = adfTOWGS[6];  | 
1490  |  | 
  | 
1491  | 0  |     int nSpheroidId = -1;  | 
1492  |  | 
  | 
1493  | 0  |     const char *pszWKTSpheroid = poSpatialRef->GetAttrValue("SPHEROID"); | 
1494  | 0  |     for (int i = 0; asSpheroidInfoList[i].nMapInfoId != -1; i++)  | 
1495  | 0  |     { | 
1496  | 0  |         if (EQUAL(pszWKTSpheroid, asSpheroidInfoList[i].pszMapinfoName))  | 
1497  | 0  |         { | 
1498  | 0  |             nSpheroidId = asSpheroidInfoList[i].nMapInfoId;  | 
1499  | 0  |             break;  | 
1500  | 0  |         }  | 
1501  | 0  |     }  | 
1502  |  | 
  | 
1503  | 0  |     if (nSpheroidId == -1)  | 
1504  | 0  |     { | 
1505  | 0  |         double adSemiMajor = poSpatialRef->GetSemiMajor();  | 
1506  | 0  |         double adInvFlattening = poSpatialRef->GetInvFlattening();  | 
1507  |  | 
  | 
1508  | 0  |         for (int i = 0; asSpheroidInfoList[i].nMapInfoId != -1; i++)  | 
1509  | 0  |         { | 
1510  | 0  |             if (CPLIsEqual(adSemiMajor, asSpheroidInfoList[i].dfA) &&  | 
1511  | 0  |                 CPLIsEqual(adInvFlattening,  | 
1512  | 0  |                            asSpheroidInfoList[i].dfInvFlattening))  | 
1513  | 0  |             { | 
1514  | 0  |                 nSpheroidId = asSpheroidInfoList[i].nMapInfoId;  | 
1515  | 0  |                 break;  | 
1516  | 0  |             }  | 
1517  | 0  |         }  | 
1518  | 0  |     }  | 
1519  | 0  |     if (nSpheroidId == -1)  | 
1520  | 0  |     { | 
1521  | 0  |         CPLDebug(  | 
1522  | 0  |             "MITAB",  | 
1523  | 0  |             "Cannot find MapInfo spheroid matching %s. Defaulting to WGS 84",  | 
1524  | 0  |             pszWKTSpheroid);  | 
1525  | 0  |         nSpheroidId = 28; /* WGS 84 */  | 
1526  | 0  |     }  | 
1527  | 0  |     sTABProj.nEllipsoidId = static_cast<GByte>(nSpheroidId);  | 
1528  | 0  |     return TRUE;  | 
1529  | 0  | }  | 
1530  |  |  | 
1531  |  | int TABFileGetTABProjFromSpatialRef(const OGRSpatialReference *poSpatialRef,  | 
1532  |  |                                     TABProjInfo &sTABProj, int &nParamCount)  | 
1533  | 0  | { | 
1534  |  |     /*-----------------------------------------------------------------  | 
1535  |  |      * Initialize TABProjInfo  | 
1536  |  |      *----------------------------------------------------------------*/  | 
1537  | 0  |     sTABProj.nProjId = 0;  | 
1538  | 0  |     sTABProj.nEllipsoidId = 0; /* how will we set this? */  | 
1539  | 0  |     sTABProj.nUnitsId = 7;  | 
1540  | 0  |     sTABProj.adProjParams[0] = sTABProj.adProjParams[1] = 0.0;  | 
1541  | 0  |     sTABProj.adProjParams[2] = sTABProj.adProjParams[3] = 0.0;  | 
1542  | 0  |     sTABProj.adProjParams[4] = sTABProj.adProjParams[5] = 0.0;  | 
1543  |  | 
  | 
1544  | 0  |     sTABProj.nDatumId = 0;  | 
1545  | 0  |     sTABProj.dDatumShiftX = 0.0;  | 
1546  | 0  |     sTABProj.dDatumShiftY = 0.0;  | 
1547  | 0  |     sTABProj.dDatumShiftZ = 0.0;  | 
1548  | 0  |     sTABProj.adDatumParams[0] = 0.0;  | 
1549  | 0  |     sTABProj.adDatumParams[1] = 0.0;  | 
1550  | 0  |     sTABProj.adDatumParams[2] = 0.0;  | 
1551  | 0  |     sTABProj.adDatumParams[3] = 0.0;  | 
1552  | 0  |     sTABProj.adDatumParams[4] = 0.0;  | 
1553  |  | 
  | 
1554  | 0  |     sTABProj.nAffineFlag = 0;  | 
1555  | 0  |     sTABProj.nAffineUnits = 7;  | 
1556  | 0  |     sTABProj.dAffineParamA = 0.0;  | 
1557  | 0  |     sTABProj.dAffineParamB = 0.0;  | 
1558  | 0  |     sTABProj.dAffineParamC = 0.0;  | 
1559  | 0  |     sTABProj.dAffineParamD = 0.0;  | 
1560  | 0  |     sTABProj.dAffineParamE = 0.0;  | 
1561  | 0  |     sTABProj.dAffineParamF = 0.0;  | 
1562  |  |  | 
1563  |  |     /*-----------------------------------------------------------------  | 
1564  |  |      * Get the linear units and conversion.  | 
1565  |  |      *----------------------------------------------------------------*/  | 
1566  | 0  |     const char *pszLinearUnits = nullptr;  | 
1567  | 0  |     double dfLinearConv = poSpatialRef->GetLinearUnits(&pszLinearUnits);  | 
1568  | 0  |     if (dfLinearConv == 0.0)  | 
1569  | 0  |         dfLinearConv = 1.0;  | 
1570  |  |  | 
1571  |  |     // Get datum information  | 
1572  | 0  |     const char *pszWKTDatum = poSpatialRef->GetAttrValue("DATUM"); | 
1573  |  | 
  | 
1574  | 0  |     const auto GetDatumCode = [](const OGRSpatialReference *poSRS)  | 
1575  | 0  |     { | 
1576  | 0  |         const char *pszDatumAuthority = poSRS->GetAuthorityName("DATUM"); | 
1577  | 0  |         const char *pszDatumCode = poSRS->GetAuthorityCode("DATUM"); | 
1578  | 0  |         if (pszDatumCode && pszDatumAuthority &&  | 
1579  | 0  |             EQUAL(pszDatumAuthority, "EPSG"))  | 
1580  | 0  |         { | 
1581  | 0  |             return atoi(pszDatumCode);  | 
1582  | 0  |         }  | 
1583  | 0  |         return -1;  | 
1584  | 0  |     };  | 
1585  |  | 
  | 
1586  | 0  |     int nDatumEPSGCode = GetDatumCode(poSpatialRef);  | 
1587  | 0  |     if (nDatumEPSGCode < 0)  | 
1588  | 0  |     { | 
1589  | 0  |         const auto GetDatumCodeFromCRSIndirect =  | 
1590  | 0  |             [&GetDatumCode](const OGRSpatialReference *poSRS,  | 
1591  | 0  |                             const char *pszNode)  | 
1592  | 0  |         { | 
1593  | 0  |             const char *pszAuthorityName = poSRS->GetAuthorityName(pszNode);  | 
1594  | 0  |             const char *pszAuthorityCode = poSRS->GetAuthorityCode(pszNode);  | 
1595  | 0  |             if (pszAuthorityName && pszAuthorityCode)  | 
1596  | 0  |             { | 
1597  | 0  |                 OGRSpatialReference oSRSTmp;  | 
1598  | 0  |                 if (oSRSTmp.SetFromUserInput(CPLSPrintf(  | 
1599  | 0  |                         "%s:%s", pszAuthorityName, pszAuthorityCode)) ==  | 
1600  | 0  |                     OGRERR_NONE)  | 
1601  | 0  |                 { | 
1602  | 0  |                     return GetDatumCode(&oSRSTmp);  | 
1603  | 0  |                 }  | 
1604  | 0  |             }  | 
1605  | 0  |             return -1;  | 
1606  | 0  |         };  | 
1607  |  |  | 
1608  |  |         // When the CRS is built from WKT2 CRS string, the DATUM code will  | 
1609  |  |         // typically be absent from the CRS string.  | 
1610  |  |         // Try to get the AUTHORITY:CODE from the CRS to instantiate  | 
1611  |  |         // a temporary CRS and get its DATUM code.  | 
1612  | 0  |         nDatumEPSGCode = GetDatumCodeFromCRSIndirect(poSpatialRef, nullptr);  | 
1613  | 0  |         if (nDatumEPSGCode < 0 && !poSpatialRef->IsGeographic())  | 
1614  | 0  |         { | 
1615  |  |             // If there's no AUTHORITY:CODE on the CRS, then retry with its  | 
1616  |  |             // geographic CRS  | 
1617  | 0  |             nDatumEPSGCode =  | 
1618  | 0  |                 GetDatumCodeFromCRSIndirect(poSpatialRef, "GEOGCS");  | 
1619  | 0  |         }  | 
1620  | 0  |     }  | 
1621  |  |  | 
1622  |  |     /*-----------------------------------------------------------------  | 
1623  |  |      * Transform the projection and projection parameters.  | 
1624  |  |      *----------------------------------------------------------------*/  | 
1625  | 0  |     const char *pszProjection = poSpatialRef->GetAttrValue("PROJECTION"); | 
1626  | 0  |     double *params = sTABProj.adProjParams;  | 
1627  | 0  |     nParamCount = 0;  | 
1628  |  | 
  | 
1629  | 0  |     if (pszProjection == nullptr &&  | 
1630  | 0  |         poSpatialRef->GetAttrNode("GEOGCS") == nullptr) | 
1631  | 0  |     { | 
1632  |  |         /* nonearth */  | 
1633  | 0  |         sTABProj.nProjId = 0;  | 
1634  | 0  |     }  | 
1635  |  |  | 
1636  | 0  |     else if (pszProjection == nullptr)  | 
1637  | 0  |     { | 
1638  | 0  |         sTABProj.nProjId = 1;  | 
1639  | 0  |     }  | 
1640  |  |  | 
1641  | 0  |     else if (EQUAL(pszProjection, SRS_PT_ALBERS_CONIC_EQUAL_AREA))  | 
1642  | 0  |     { | 
1643  | 0  |         sTABProj.nProjId = 9;  | 
1644  | 0  |         params[0] =  | 
1645  | 0  |             poSpatialRef->GetNormProjParm(SRS_PP_LONGITUDE_OF_CENTER, 0.0);  | 
1646  | 0  |         params[1] =  | 
1647  | 0  |             poSpatialRef->GetNormProjParm(SRS_PP_LATITUDE_OF_CENTER, 0.0);  | 
1648  | 0  |         params[2] =  | 
1649  | 0  |             poSpatialRef->GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1, 0.0);  | 
1650  | 0  |         params[3] =  | 
1651  | 0  |             poSpatialRef->GetNormProjParm(SRS_PP_STANDARD_PARALLEL_2, 0.0);  | 
1652  | 0  |         params[4] = poSpatialRef->GetProjParm(SRS_PP_FALSE_EASTING, 0.0);  | 
1653  | 0  |         params[5] = poSpatialRef->GetProjParm(SRS_PP_FALSE_NORTHING, 0.0);  | 
1654  | 0  |         nParamCount = 6;  | 
1655  | 0  |     }  | 
1656  |  |  | 
1657  | 0  |     else if (EQUAL(pszProjection, SRS_PT_AZIMUTHAL_EQUIDISTANT))  | 
1658  | 0  |     { | 
1659  | 0  |         sTABProj.nProjId = 5;  | 
1660  | 0  |         params[0] =  | 
1661  | 0  |             poSpatialRef->GetNormProjParm(SRS_PP_LONGITUDE_OF_CENTER, 0.0);  | 
1662  | 0  |         params[1] =  | 
1663  | 0  |             poSpatialRef->GetNormProjParm(SRS_PP_LATITUDE_OF_CENTER, 0.0);  | 
1664  | 0  |         params[2] = 90.0;  | 
1665  | 0  |         nParamCount = 3;  | 
1666  |  | 
  | 
1667  | 0  |         if (std::abs((std::abs(params[1]) - 90)) > 0.001)  | 
1668  | 0  |             sTABProj.nProjId = 28;  | 
1669  | 0  |     }  | 
1670  |  |  | 
1671  | 0  |     else if (EQUAL(pszProjection, SRS_PT_CYLINDRICAL_EQUAL_AREA))  | 
1672  | 0  |     { | 
1673  | 0  |         sTABProj.nProjId = 2;  | 
1674  | 0  |         params[0] = poSpatialRef->GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0);  | 
1675  | 0  |         params[1] =  | 
1676  | 0  |             poSpatialRef->GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1, 0.0);  | 
1677  | 0  |         nParamCount = 2;  | 
1678  | 0  |     }  | 
1679  |  |  | 
1680  | 0  |     else if (EQUAL(pszProjection, SRS_PT_ECKERT_IV))  | 
1681  | 0  |     { | 
1682  | 0  |         sTABProj.nProjId = 14;  | 
1683  | 0  |         params[0] = poSpatialRef->GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0);  | 
1684  | 0  |         nParamCount = 1;  | 
1685  | 0  |     }  | 
1686  |  |  | 
1687  | 0  |     else if (EQUAL(pszProjection, SRS_PT_ECKERT_VI))  | 
1688  | 0  |     { | 
1689  | 0  |         sTABProj.nProjId = 15;  | 
1690  | 0  |         params[0] = poSpatialRef->GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0);  | 
1691  | 0  |         nParamCount = 1;  | 
1692  | 0  |     }  | 
1693  |  |  | 
1694  | 0  |     else if (EQUAL(pszProjection, SRS_PT_EQUIDISTANT_CONIC))  | 
1695  | 0  |     { | 
1696  | 0  |         sTABProj.nProjId = 6;  | 
1697  | 0  |         params[0] =  | 
1698  | 0  |             poSpatialRef->GetNormProjParm(SRS_PP_LONGITUDE_OF_CENTER, 0.0);  | 
1699  | 0  |         params[1] =  | 
1700  | 0  |             poSpatialRef->GetNormProjParm(SRS_PP_LATITUDE_OF_CENTER, 0.0);  | 
1701  | 0  |         params[2] =  | 
1702  | 0  |             poSpatialRef->GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1, 0.0);  | 
1703  | 0  |         params[3] =  | 
1704  | 0  |             poSpatialRef->GetNormProjParm(SRS_PP_STANDARD_PARALLEL_2, 0.0);  | 
1705  | 0  |         params[4] = poSpatialRef->GetProjParm(SRS_PP_FALSE_EASTING, 0.0);  | 
1706  | 0  |         params[5] = poSpatialRef->GetProjParm(SRS_PP_FALSE_NORTHING, 0.0);  | 
1707  | 0  |         nParamCount = 6;  | 
1708  | 0  |     }  | 
1709  |  |  | 
1710  | 0  |     else if (EQUAL(pszProjection, SRS_PT_GALL_STEREOGRAPHIC))  | 
1711  | 0  |     { | 
1712  | 0  |         sTABProj.nProjId = 17;  | 
1713  | 0  |         params[0] = poSpatialRef->GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0);  | 
1714  | 0  |         nParamCount = 1;  | 
1715  | 0  |     }  | 
1716  |  |  | 
1717  | 0  |     else if (EQUAL(pszProjection, SRS_PT_HOTINE_OBLIQUE_MERCATOR))  | 
1718  | 0  |     { | 
1719  | 0  |         if (std::abs(poSpatialRef->GetNormProjParm(SRS_PP_RECTIFIED_GRID_ANGLE,  | 
1720  | 0  |                                                    90.0) -  | 
1721  | 0  |                      90.0) < 1e-8)  | 
1722  | 0  |         { | 
1723  | 0  |             sTABProj.nProjId = 7;  | 
1724  | 0  |             params[0] =  | 
1725  | 0  |                 poSpatialRef->GetNormProjParm(SRS_PP_LONGITUDE_OF_CENTER, 0.0);  | 
1726  | 0  |             params[1] =  | 
1727  | 0  |                 poSpatialRef->GetNormProjParm(SRS_PP_LATITUDE_OF_CENTER, 0.0);  | 
1728  | 0  |             params[2] = poSpatialRef->GetNormProjParm(SRS_PP_AZIMUTH, 0.0);  | 
1729  | 0  |             params[3] = poSpatialRef->GetProjParm(SRS_PP_SCALE_FACTOR, 1.0);  | 
1730  | 0  |             params[4] = poSpatialRef->GetProjParm(SRS_PP_FALSE_EASTING, 0.0);  | 
1731  | 0  |             params[5] = poSpatialRef->GetProjParm(SRS_PP_FALSE_NORTHING, 0.0);  | 
1732  | 0  |             nParamCount = 6;  | 
1733  | 0  |         }  | 
1734  | 0  |         else  | 
1735  | 0  |         { | 
1736  | 0  |             sTABProj.nProjId = 35;  | 
1737  | 0  |             params[0] =  | 
1738  | 0  |                 poSpatialRef->GetNormProjParm(SRS_PP_LONGITUDE_OF_CENTER, 0.0);  | 
1739  | 0  |             params[1] =  | 
1740  | 0  |                 poSpatialRef->GetNormProjParm(SRS_PP_LATITUDE_OF_CENTER, 0.0);  | 
1741  | 0  |             params[2] = poSpatialRef->GetNormProjParm(SRS_PP_AZIMUTH, 0.0);  | 
1742  | 0  |             params[3] =  | 
1743  | 0  |                 poSpatialRef->GetNormProjParm(SRS_PP_RECTIFIED_GRID_ANGLE, 0.0);  | 
1744  | 0  |             params[4] = poSpatialRef->GetProjParm(SRS_PP_SCALE_FACTOR, 1.0);  | 
1745  | 0  |             params[5] = poSpatialRef->GetProjParm(SRS_PP_FALSE_EASTING, 0.0);  | 
1746  | 0  |             params[6] = poSpatialRef->GetProjParm(SRS_PP_FALSE_NORTHING, 0.0);  | 
1747  | 0  |             nParamCount = 7;  | 
1748  | 0  |         }  | 
1749  | 0  |     }  | 
1750  |  |  | 
1751  | 0  |     else if (EQUAL(pszProjection, SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA))  | 
1752  | 0  |     { | 
1753  | 0  |         sTABProj.nProjId = 4;  | 
1754  | 0  |         params[0] =  | 
1755  | 0  |             poSpatialRef->GetNormProjParm(SRS_PP_LONGITUDE_OF_CENTER, 0.0);  | 
1756  | 0  |         params[1] =  | 
1757  | 0  |             poSpatialRef->GetNormProjParm(SRS_PP_LATITUDE_OF_CENTER, 0.0);  | 
1758  | 0  |         params[2] = 90.0;  | 
1759  | 0  |         nParamCount = 3;  | 
1760  |  | 
  | 
1761  | 0  |         if (std::abs((std::abs(params[1]) - 90)) > 0.001)  | 
1762  | 0  |             sTABProj.nProjId = 29;  | 
1763  | 0  |     }  | 
1764  |  |  | 
1765  | 0  |     else if (EQUAL(pszProjection, SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP))  | 
1766  | 0  |     { | 
1767  | 0  |         sTABProj.nProjId = 3;  | 
1768  | 0  |         params[0] = poSpatialRef->GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0);  | 
1769  | 0  |         params[1] =  | 
1770  | 0  |             poSpatialRef->GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0);  | 
1771  | 0  |         params[2] =  | 
1772  | 0  |             poSpatialRef->GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1, 0.0);  | 
1773  | 0  |         params[3] =  | 
1774  | 0  |             poSpatialRef->GetNormProjParm(SRS_PP_STANDARD_PARALLEL_2, 0.0);  | 
1775  | 0  |         params[4] = poSpatialRef->GetProjParm(SRS_PP_FALSE_EASTING, 0.0);  | 
1776  | 0  |         params[5] = poSpatialRef->GetProjParm(SRS_PP_FALSE_NORTHING, 0.0);  | 
1777  | 0  |         nParamCount = 6;  | 
1778  | 0  |     }  | 
1779  |  |  | 
1780  | 0  |     else if (EQUAL(pszProjection, SRS_PT_LAMBERT_CONFORMAL_CONIC_1SP))  | 
1781  | 0  |     { | 
1782  | 0  |         OGRSpatialReference *poOtherSRS =  | 
1783  | 0  |             poSpatialRef->convertToOtherProjection(  | 
1784  | 0  |                 SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP);  | 
1785  | 0  |         if (poOtherSRS)  | 
1786  | 0  |         { | 
1787  | 0  |             sTABProj.nProjId = 3;  | 
1788  | 0  |             params[0] =  | 
1789  | 0  |                 poOtherSRS->GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0);  | 
1790  | 0  |             params[1] =  | 
1791  | 0  |                 poOtherSRS->GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0);  | 
1792  | 0  |             params[2] =  | 
1793  | 0  |                 poOtherSRS->GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1, 0.0);  | 
1794  | 0  |             params[3] =  | 
1795  | 0  |                 poOtherSRS->GetNormProjParm(SRS_PP_STANDARD_PARALLEL_2, 0.0);  | 
1796  | 0  |             params[4] = poOtherSRS->GetProjParm(SRS_PP_FALSE_EASTING, 0.0);  | 
1797  | 0  |             params[5] = poOtherSRS->GetProjParm(SRS_PP_FALSE_NORTHING, 0.0);  | 
1798  | 0  |             nParamCount = 6;  | 
1799  | 0  |             delete poOtherSRS;  | 
1800  | 0  |         }  | 
1801  | 0  |     }  | 
1802  |  |  | 
1803  | 0  |     else if (EQUAL(pszProjection, SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP_BELGIUM))  | 
1804  | 0  |     { | 
1805  | 0  |         sTABProj.nProjId = 19;  | 
1806  | 0  |         params[0] = poSpatialRef->GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0);  | 
1807  | 0  |         params[1] =  | 
1808  | 0  |             poSpatialRef->GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0);  | 
1809  | 0  |         params[2] =  | 
1810  | 0  |             poSpatialRef->GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1, 0.0);  | 
1811  | 0  |         params[3] =  | 
1812  | 0  |             poSpatialRef->GetNormProjParm(SRS_PP_STANDARD_PARALLEL_2, 0.0);  | 
1813  | 0  |         params[4] = poSpatialRef->GetProjParm(SRS_PP_FALSE_EASTING, 0.0);  | 
1814  | 0  |         params[5] = poSpatialRef->GetProjParm(SRS_PP_FALSE_NORTHING, 0.0);  | 
1815  | 0  |         nParamCount = 6;  | 
1816  | 0  |     }  | 
1817  |  |  | 
1818  | 0  |     else if (EQUAL(pszProjection, SRS_PT_MERCATOR_1SP))  | 
1819  | 0  |     { | 
1820  | 0  |         sTABProj.nProjId = 10;  | 
1821  | 0  |         params[0] = poSpatialRef->GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0);  | 
1822  | 0  |         params[1] =  | 
1823  | 0  |             poSpatialRef->GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0);  | 
1824  | 0  |         params[2] = poSpatialRef->GetProjParm(SRS_PP_SCALE_FACTOR, 1.0);  | 
1825  | 0  |         nParamCount = 1;  // FIXME for MIF export ?  | 
1826  |  | 
  | 
1827  | 0  |         if (params[1] != 0.0)  | 
1828  | 0  |         { | 
1829  | 0  |             sTABProj.nProjId = 26;  | 
1830  | 0  |             nParamCount = 2;  // FIXME for MIF export ?  | 
1831  | 0  |         }  | 
1832  | 0  |     }  | 
1833  |  |  | 
1834  | 0  |     else if (EQUAL(pszProjection, SRS_PT_MERCATOR_2SP))  | 
1835  | 0  |     { | 
1836  | 0  |         sTABProj.nProjId = 26;  | 
1837  | 0  |         params[0] = poSpatialRef->GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0);  | 
1838  | 0  |         params[1] =  | 
1839  | 0  |             poSpatialRef->GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1, 0.0);  | 
1840  | 0  |         nParamCount = 2;  // FIXME for MIF export ?  | 
1841  | 0  |     }  | 
1842  |  |  | 
1843  | 0  |     else if (EQUAL(pszProjection, SRS_PT_MILLER_CYLINDRICAL))  | 
1844  | 0  |     { | 
1845  | 0  |         sTABProj.nProjId = 11;  | 
1846  | 0  |         params[0] =  | 
1847  | 0  |             poSpatialRef->GetNormProjParm(SRS_PP_LONGITUDE_OF_CENTER, 0.0);  | 
1848  | 0  |         nParamCount = 1;  | 
1849  | 0  |     }  | 
1850  |  |  | 
1851  | 0  |     else if (EQUAL(pszProjection, SRS_PT_MOLLWEIDE))  | 
1852  | 0  |     { | 
1853  | 0  |         sTABProj.nProjId = 13;  | 
1854  | 0  |         params[0] = poSpatialRef->GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0);  | 
1855  | 0  |         nParamCount = 1;  | 
1856  | 0  |     }  | 
1857  |  |  | 
1858  | 0  |     else if (EQUAL(pszProjection, SRS_PT_NEW_ZEALAND_MAP_GRID))  | 
1859  | 0  |     { | 
1860  | 0  |         sTABProj.nProjId = 18;  | 
1861  | 0  |         params[0] = poSpatialRef->GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0);  | 
1862  | 0  |         params[1] =  | 
1863  | 0  |             poSpatialRef->GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0);  | 
1864  | 0  |         params[2] = poSpatialRef->GetProjParm(SRS_PP_FALSE_EASTING, 0.0);  | 
1865  | 0  |         params[3] = poSpatialRef->GetProjParm(SRS_PP_FALSE_NORTHING, 0.0);  | 
1866  | 0  |         nParamCount = 4;  | 
1867  | 0  |     }  | 
1868  |  |  | 
1869  | 0  |     else if (EQUAL(pszProjection, SRS_PT_SWISS_OBLIQUE_CYLINDRICAL))  | 
1870  | 0  |     { | 
1871  | 0  |         sTABProj.nProjId = 25;  | 
1872  | 0  |         params[0] = poSpatialRef->GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0);  | 
1873  | 0  |         params[1] =  | 
1874  | 0  |             poSpatialRef->GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0);  | 
1875  | 0  |         params[2] = poSpatialRef->GetProjParm(SRS_PP_FALSE_EASTING, 0.0);  | 
1876  | 0  |         params[3] = poSpatialRef->GetProjParm(SRS_PP_FALSE_NORTHING, 0.0);  | 
1877  | 0  |         nParamCount = 4;  | 
1878  | 0  |     }  | 
1879  |  |  | 
1880  |  |     // Swiss Oblique expressed as Hotine Oblique Mercator Azimuth Center  | 
1881  | 0  |     else if (EQUAL(pszProjection,  | 
1882  | 0  |                    SRS_PT_HOTINE_OBLIQUE_MERCATOR_AZIMUTH_CENTER) &&  | 
1883  | 0  |              std::abs(poSpatialRef->GetNormProjParm(SRS_PP_AZIMUTH, 90.0) -  | 
1884  | 0  |                       90.0) < 1e-8 &&  | 
1885  | 0  |              std::abs(poSpatialRef->GetNormProjParm(SRS_PP_RECTIFIED_GRID_ANGLE,  | 
1886  | 0  |                                                     90.0) -  | 
1887  | 0  |                       90.0) < 1e-8 &&  | 
1888  | 0  |              std::abs(poSpatialRef->GetProjParm(SRS_PP_SCALE_FACTOR, 1.0) -  | 
1889  | 0  |                       1.0) < 1e-8)  | 
1890  | 0  |     { | 
1891  | 0  |         sTABProj.nProjId = 25;  | 
1892  | 0  |         params[0] =  | 
1893  | 0  |             poSpatialRef->GetNormProjParm(SRS_PP_LONGITUDE_OF_CENTER, 0.0);  | 
1894  | 0  |         params[1] =  | 
1895  | 0  |             poSpatialRef->GetNormProjParm(SRS_PP_LATITUDE_OF_CENTER, 0.0);  | 
1896  | 0  |         params[2] = poSpatialRef->GetProjParm(SRS_PP_FALSE_EASTING, 0.0);  | 
1897  | 0  |         params[3] = poSpatialRef->GetProjParm(SRS_PP_FALSE_NORTHING, 0.0);  | 
1898  | 0  |         nParamCount = 4;  | 
1899  | 0  |     }  | 
1900  |  |  | 
1901  | 0  |     else if (EQUAL(pszProjection, SRS_PT_ROBINSON))  | 
1902  | 0  |     { | 
1903  | 0  |         sTABProj.nProjId = 12;  | 
1904  | 0  |         params[0] = poSpatialRef->GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0);  | 
1905  | 0  |         nParamCount = 1;  | 
1906  | 0  |     }  | 
1907  |  |  | 
1908  | 0  |     else if (EQUAL(pszProjection, SRS_PT_SINUSOIDAL))  | 
1909  | 0  |     { | 
1910  | 0  |         sTABProj.nProjId = 16;  | 
1911  | 0  |         params[0] = poSpatialRef->GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0);  | 
1912  | 0  |         nParamCount = 1;  | 
1913  | 0  |     }  | 
1914  |  |  | 
1915  | 0  |     else if (EQUAL(pszProjection, SRS_PT_STEREOGRAPHIC))  | 
1916  | 0  |     { | 
1917  | 0  |         sTABProj.nProjId = 20;  | 
1918  | 0  |         params[0] = poSpatialRef->GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0);  | 
1919  | 0  |         params[1] =  | 
1920  | 0  |             poSpatialRef->GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0);  | 
1921  | 0  |         params[2] = poSpatialRef->GetProjParm(SRS_PP_SCALE_FACTOR, 1.0);  | 
1922  | 0  |         params[3] = poSpatialRef->GetProjParm(SRS_PP_FALSE_EASTING, 0.0);  | 
1923  | 0  |         params[4] = poSpatialRef->GetProjParm(SRS_PP_FALSE_NORTHING, 0.0);  | 
1924  | 0  |         nParamCount = 5;  | 
1925  | 0  |     }  | 
1926  |  |  | 
1927  | 0  |     else if (EQUAL(pszProjection, SRS_PT_OBLIQUE_STEREOGRAPHIC))  | 
1928  | 0  |     { | 
1929  | 0  |         sTABProj.nProjId = 31;  | 
1930  | 0  |         params[0] = poSpatialRef->GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0);  | 
1931  | 0  |         params[1] =  | 
1932  | 0  |             poSpatialRef->GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0);  | 
1933  | 0  |         params[2] = poSpatialRef->GetProjParm(SRS_PP_SCALE_FACTOR, 1.0);  | 
1934  | 0  |         params[3] = poSpatialRef->GetProjParm(SRS_PP_FALSE_EASTING, 0.0);  | 
1935  | 0  |         params[4] = poSpatialRef->GetProjParm(SRS_PP_FALSE_NORTHING, 0.0);  | 
1936  | 0  |         nParamCount = 5;  | 
1937  | 0  |     }  | 
1938  |  |  | 
1939  | 0  |     else if (EQUAL(pszProjection, SRS_PT_TRANSVERSE_MERCATOR))  | 
1940  | 0  |     { | 
1941  | 0  |         sTABProj.nProjId = 8;  | 
1942  | 0  |         if ((pszWKTDatum &&  | 
1943  | 0  |              EQUAL(pszWKTDatum, "Kartastokoordinaattijarjestelma_1966")) ||  | 
1944  | 0  |             nDatumEPSGCode == 6123)  | 
1945  | 0  |         { | 
1946  |  |             // Special case for Finnish KKJ  | 
1947  | 0  |             sTABProj.nProjId = 24;  | 
1948  | 0  |         }  | 
1949  | 0  |         params[0] = poSpatialRef->GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0);  | 
1950  | 0  |         params[1] =  | 
1951  | 0  |             poSpatialRef->GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0);  | 
1952  | 0  |         params[2] = poSpatialRef->GetProjParm(SRS_PP_SCALE_FACTOR, 1.0);  | 
1953  | 0  |         params[3] = poSpatialRef->GetProjParm(SRS_PP_FALSE_EASTING, 0.0);  | 
1954  | 0  |         params[4] = poSpatialRef->GetProjParm(SRS_PP_FALSE_NORTHING, 0.0);  | 
1955  | 0  |         nParamCount = 5;  | 
1956  | 0  |     }  | 
1957  |  |  | 
1958  | 0  |     else if (EQUAL(pszProjection,  | 
1959  | 0  |                    SRS_PT_TRANSVERSE_MERCATOR_MI_21))  // Encom 2003  | 
1960  | 0  |     { | 
1961  | 0  |         sTABProj.nProjId = 21;  | 
1962  | 0  |         params[0] = poSpatialRef->GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0);  | 
1963  | 0  |         params[1] =  | 
1964  | 0  |             poSpatialRef->GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0);  | 
1965  | 0  |         params[2] = poSpatialRef->GetProjParm(SRS_PP_SCALE_FACTOR, 1.0);  | 
1966  | 0  |         params[3] = poSpatialRef->GetProjParm(SRS_PP_FALSE_EASTING, 0.0);  | 
1967  | 0  |         params[4] = poSpatialRef->GetProjParm(SRS_PP_FALSE_NORTHING, 0.0);  | 
1968  | 0  |         nParamCount = 5;  | 
1969  | 0  |     }  | 
1970  |  |  | 
1971  | 0  |     else if (EQUAL(pszProjection,  | 
1972  | 0  |                    SRS_PT_TRANSVERSE_MERCATOR_MI_22))  // Encom 2003  | 
1973  | 0  |     { | 
1974  | 0  |         sTABProj.nProjId = 22;  | 
1975  | 0  |         params[0] = poSpatialRef->GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0);  | 
1976  | 0  |         params[1] =  | 
1977  | 0  |             poSpatialRef->GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0);  | 
1978  | 0  |         params[2] = poSpatialRef->GetProjParm(SRS_PP_SCALE_FACTOR, 1.0);  | 
1979  | 0  |         params[3] = poSpatialRef->GetProjParm(SRS_PP_FALSE_EASTING, 0.0);  | 
1980  | 0  |         params[4] = poSpatialRef->GetProjParm(SRS_PP_FALSE_NORTHING, 0.0);  | 
1981  | 0  |         nParamCount = 5;  | 
1982  | 0  |     }  | 
1983  |  |  | 
1984  | 0  |     else if (EQUAL(pszProjection,  | 
1985  | 0  |                    SRS_PT_TRANSVERSE_MERCATOR_MI_23))  // Encom 2003  | 
1986  | 0  |     { | 
1987  | 0  |         sTABProj.nProjId = 23;  | 
1988  | 0  |         params[0] = poSpatialRef->GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0);  | 
1989  | 0  |         params[1] =  | 
1990  | 0  |             poSpatialRef->GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0);  | 
1991  | 0  |         params[2] = poSpatialRef->GetProjParm(SRS_PP_SCALE_FACTOR, 1.0);  | 
1992  | 0  |         params[3] = poSpatialRef->GetProjParm(SRS_PP_FALSE_EASTING, 0.0);  | 
1993  | 0  |         params[4] = poSpatialRef->GetProjParm(SRS_PP_FALSE_NORTHING, 0.0);  | 
1994  | 0  |         nParamCount = 5;  | 
1995  | 0  |     }  | 
1996  |  |  | 
1997  | 0  |     else if (EQUAL(pszProjection,  | 
1998  | 0  |                    SRS_PT_TRANSVERSE_MERCATOR_MI_24))  // Encom 2003  | 
1999  | 0  |     { | 
2000  | 0  |         sTABProj.nProjId = 24;  | 
2001  | 0  |         params[0] = poSpatialRef->GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0);  | 
2002  | 0  |         params[1] =  | 
2003  | 0  |             poSpatialRef->GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0);  | 
2004  | 0  |         params[2] = poSpatialRef->GetProjParm(SRS_PP_SCALE_FACTOR, 1.0);  | 
2005  | 0  |         params[3] = poSpatialRef->GetProjParm(SRS_PP_FALSE_EASTING, 0.0);  | 
2006  | 0  |         params[4] = poSpatialRef->GetProjParm(SRS_PP_FALSE_NORTHING, 0.0);  | 
2007  | 0  |         nParamCount = 5;  | 
2008  | 0  |     }  | 
2009  |  |  | 
2010  | 0  |     else if (EQUAL(pszProjection, SRS_PT_CASSINI_SOLDNER))  | 
2011  | 0  |     { | 
2012  | 0  |         sTABProj.nProjId = 30;  | 
2013  | 0  |         params[0] = poSpatialRef->GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0);  | 
2014  | 0  |         params[1] =  | 
2015  | 0  |             poSpatialRef->GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0);  | 
2016  | 0  |         params[2] = poSpatialRef->GetProjParm(SRS_PP_FALSE_EASTING, 0.0);  | 
2017  | 0  |         params[3] = poSpatialRef->GetProjParm(SRS_PP_FALSE_NORTHING, 0.0);  | 
2018  | 0  |         nParamCount = 4;  | 
2019  | 0  |     }  | 
2020  |  |  | 
2021  | 0  |     else if (EQUAL(pszProjection, SRS_PT_POLYCONIC))  | 
2022  | 0  |     { | 
2023  | 0  |         sTABProj.nProjId = 27;  | 
2024  | 0  |         params[0] = poSpatialRef->GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0);  | 
2025  | 0  |         params[1] =  | 
2026  | 0  |             poSpatialRef->GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0);  | 
2027  | 0  |         params[2] = poSpatialRef->GetProjParm(SRS_PP_FALSE_EASTING, 0.0);  | 
2028  | 0  |         params[3] = poSpatialRef->GetProjParm(SRS_PP_FALSE_NORTHING, 0.0);  | 
2029  | 0  |         nParamCount = 4;  | 
2030  | 0  |     }  | 
2031  |  |  | 
2032  | 0  |     else if (EQUAL(pszProjection, SRS_PT_KROVAK))  | 
2033  | 0  |     { | 
2034  | 0  |         sTABProj.nProjId = 32;  | 
2035  | 0  |         params[0] = poSpatialRef->GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0);  | 
2036  | 0  |         params[1] =  | 
2037  | 0  |             poSpatialRef->GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0);  | 
2038  | 0  |         params[2] =  | 
2039  | 0  |             poSpatialRef->GetNormProjParm(SRS_PP_PSEUDO_STD_PARALLEL_1, 0.0);  | 
2040  | 0  |         params[3] = poSpatialRef->GetNormProjParm(SRS_PP_AZIMUTH, 0.0);  | 
2041  | 0  |         params[4] = poSpatialRef->GetProjParm(SRS_PP_FALSE_EASTING, 0.0);  | 
2042  | 0  |         params[5] = poSpatialRef->GetProjParm(SRS_PP_FALSE_NORTHING, 0.0);  | 
2043  | 0  |         nParamCount = 6;  | 
2044  | 0  |     }  | 
2045  |  |  | 
2046  | 0  |     else if (EQUAL(pszProjection, SRS_PT_EQUIRECTANGULAR))  | 
2047  | 0  |     { | 
2048  | 0  |         sTABProj.nProjId = 33;  | 
2049  | 0  |         params[0] = poSpatialRef->GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0);  | 
2050  | 0  |         params[1] =  | 
2051  | 0  |             poSpatialRef->GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0);  | 
2052  | 0  |         params[2] = poSpatialRef->GetProjParm(SRS_PP_FALSE_EASTING, 0.0);  | 
2053  | 0  |         params[3] = poSpatialRef->GetProjParm(SRS_PP_FALSE_NORTHING, 0.0);  | 
2054  | 0  |         nParamCount = 4;  | 
2055  | 0  |     }  | 
2056  |  |  | 
2057  | 0  |     else  | 
2058  | 0  |     { | 
2059  | 0  |         CPLError(CE_Warning, CPLE_AppDefined,  | 
2060  | 0  |                  "No translation from %s to MapInfo known", pszProjection);  | 
2061  | 0  |     }  | 
2062  |  |  | 
2063  |  |     /* ==============================================================  | 
2064  |  |      * Translate Datum and Ellipsoid  | 
2065  |  |      * ============================================================== */  | 
2066  | 0  |     const MapInfoDatumInfo *psDatumInfo = nullptr;  | 
2067  |  |  | 
2068  |  |     /*-----------------------------------------------------------------  | 
2069  |  |      * Default to WGS84 if we have no datum at all.  | 
2070  |  |      *----------------------------------------------------------------*/  | 
2071  | 0  |     if (pszWKTDatum == nullptr)  | 
2072  | 0  |     { | 
2073  | 0  |         CPLDebug("MITAB", | 
2074  | 0  |                  "Cannot find MapInfo datum matching %d. Defaulting to WGS 84",  | 
2075  | 0  |                  nDatumEPSGCode);  | 
2076  | 0  |         psDatumInfo = asDatumInfoList + 0; /* WGS 84 */  | 
2077  |  |         // From MIF export code. FIXME?  | 
2078  |  |         // if( nProjection == 1 )  | 
2079  |  |         //    nProjection = 0;  | 
2080  | 0  |     }  | 
2081  |  |  | 
2082  |  |     /*-----------------------------------------------------------------  | 
2083  |  |      * We know the MIF datum number, and need to look it up to  | 
2084  |  |      * translate into datum parameters.  | 
2085  |  |      *----------------------------------------------------------------*/  | 
2086  | 0  |     else if (STARTS_WITH_CI(pszWKTDatum, "MIF ") &&  | 
2087  | 0  |              atoi(pszWKTDatum + 4) != 999 && atoi(pszWKTDatum + 4) != 9999)  | 
2088  | 0  |     { | 
2089  | 0  |         int nDatum = atoi(pszWKTDatum + 4);  | 
2090  | 0  |         for (int i = 0; asDatumInfoList[i].nMapInfoDatumID != -1; i++)  | 
2091  | 0  |         { | 
2092  | 0  |             if (nDatum == asDatumInfoList[i].nMapInfoDatumID)  | 
2093  | 0  |             { | 
2094  | 0  |                 psDatumInfo = asDatumInfoList + i;  | 
2095  | 0  |                 break;  | 
2096  | 0  |             }  | 
2097  | 0  |         }  | 
2098  |  | 
  | 
2099  | 0  |         if (psDatumInfo == nullptr)  | 
2100  | 0  |         { | 
2101  | 0  |             CPLDebug(  | 
2102  | 0  |                 "MITAB",  | 
2103  | 0  |                 "Cannot find MapInfo datum matching %s. Defaulting to WGS 84",  | 
2104  | 0  |                 pszWKTDatum);  | 
2105  | 0  |             psDatumInfo = asDatumInfoList + 0; /* WGS 84 */  | 
2106  | 0  |         }  | 
2107  | 0  |     }  | 
2108  |  |  | 
2109  |  |     /*-----------------------------------------------------------------  | 
2110  |  |      * We have the MIF datum parameters, and apply those directly.  | 
2111  |  |      *----------------------------------------------------------------*/  | 
2112  | 0  |     else if (STARTS_WITH_CI(pszWKTDatum, "MIF ") &&  | 
2113  | 0  |              (atoi(pszWKTDatum + 4) == 999 || atoi(pszWKTDatum + 4) == 9999))  | 
2114  | 0  |     { | 
2115  | 0  |         sTABProj.nDatumId = static_cast<GInt16>(atoi(pszWKTDatum + 4));  | 
2116  | 0  |         char **papszFields =  | 
2117  | 0  |             CSLTokenizeStringComplex(pszWKTDatum + 4, ",", FALSE, TRUE);  | 
2118  |  | 
  | 
2119  | 0  |         if (CSLCount(papszFields) >= 5)  | 
2120  | 0  |         { | 
2121  | 0  |             sTABProj.nEllipsoidId = static_cast<GByte>(atoi(papszFields[1]));  | 
2122  | 0  |             sTABProj.dDatumShiftX = CPLAtof(papszFields[2]);  | 
2123  | 0  |             sTABProj.dDatumShiftY = CPLAtof(papszFields[3]);  | 
2124  | 0  |             sTABProj.dDatumShiftZ = CPLAtof(papszFields[4]);  | 
2125  | 0  |         }  | 
2126  |  | 
  | 
2127  | 0  |         if (CSLCount(papszFields) >= 10)  | 
2128  | 0  |         { | 
2129  | 0  |             sTABProj.adDatumParams[0] = CPLAtof(papszFields[5]);  | 
2130  | 0  |             sTABProj.adDatumParams[1] = CPLAtof(papszFields[6]);  | 
2131  | 0  |             sTABProj.adDatumParams[2] = CPLAtof(papszFields[7]);  | 
2132  | 0  |             sTABProj.adDatumParams[3] = CPLAtof(papszFields[8]);  | 
2133  | 0  |             sTABProj.adDatumParams[4] = CPLAtof(papszFields[9]);  | 
2134  | 0  |         }  | 
2135  |  | 
  | 
2136  | 0  |         if (CSLCount(papszFields) < 5)  | 
2137  | 0  |         { | 
2138  | 0  |             CPLDebug(  | 
2139  | 0  |                 "MITAB",  | 
2140  | 0  |                 "Cannot find MapInfo datum matching %s. Defaulting to WGS 84",  | 
2141  | 0  |                 pszWKTDatum);  | 
2142  | 0  |             psDatumInfo = asDatumInfoList + 0; /* WGS 84 */  | 
2143  | 0  |         }  | 
2144  |  | 
  | 
2145  | 0  |         CSLDestroy(papszFields);  | 
2146  | 0  |     }  | 
2147  |  |  | 
2148  |  |     /*-----------------------------------------------------------------  | 
2149  |  |      * We have a "real" datum name, and possibly an EPSG code for the  | 
2150  |  |      * datum.  Try to look it up (using EPSG code first) and get the  | 
2151  |  |      * parameters.  If we don't find it with either just use WGS84.  | 
2152  |  |      *----------------------------------------------------------------*/  | 
2153  | 0  |     else  | 
2154  | 0  |     { | 
2155  | 0  |         for (int i = 0; asDatumInfoList[i].nMapInfoDatumID != -1; i++)  | 
2156  | 0  |         { | 
2157  | 0  |             if ((nDatumEPSGCode > 0 &&  | 
2158  | 0  |                  asDatumInfoList[i].nDatumEPSGCode == nDatumEPSGCode) ||  | 
2159  | 0  |                 EQUAL(pszWKTDatum, asDatumInfoList[i].pszOGCDatumName))  | 
2160  | 0  |             { | 
2161  | 0  |                 psDatumInfo = asDatumInfoList + i;  | 
2162  | 0  |                 break;  | 
2163  | 0  |             }  | 
2164  | 0  |         }  | 
2165  |  | 
  | 
2166  | 0  |         if (psDatumInfo == nullptr &&  | 
2167  | 0  |             !MITABGetCustomDatum(poSpatialRef, sTABProj))  | 
2168  | 0  |         { | 
2169  | 0  |             CPLDebug("MITAB", | 
2170  | 0  |                      "Cannot find MapInfo datum matching %s,%d. Defaulting to "  | 
2171  | 0  |                      "WGS 84",  | 
2172  | 0  |                      pszWKTDatum, nDatumEPSGCode);  | 
2173  | 0  |             psDatumInfo = asDatumInfoList + 0; /* WGS 84 */  | 
2174  | 0  |         }  | 
2175  | 0  |     }  | 
2176  |  | 
  | 
2177  | 0  |     if (psDatumInfo != nullptr)  | 
2178  | 0  |     { | 
2179  | 0  |         sTABProj.nEllipsoidId = static_cast<GByte>(psDatumInfo->nEllipsoid);  | 
2180  | 0  |         sTABProj.nDatumId = static_cast<GInt16>(psDatumInfo->nMapInfoDatumID);  | 
2181  | 0  |         sTABProj.dDatumShiftX = psDatumInfo->dfShiftX;  | 
2182  | 0  |         sTABProj.dDatumShiftY = psDatumInfo->dfShiftY;  | 
2183  | 0  |         sTABProj.dDatumShiftZ = psDatumInfo->dfShiftZ;  | 
2184  | 0  |         sTABProj.adDatumParams[0] = psDatumInfo->dfDatumParm0;  | 
2185  | 0  |         sTABProj.adDatumParams[1] = psDatumInfo->dfDatumParm1;  | 
2186  | 0  |         sTABProj.adDatumParams[2] = psDatumInfo->dfDatumParm2;  | 
2187  | 0  |         sTABProj.adDatumParams[3] = psDatumInfo->dfDatumParm3;  | 
2188  | 0  |         sTABProj.adDatumParams[4] = psDatumInfo->dfDatumParm4;  | 
2189  |  |  | 
2190  |  |         /* For LCC, standard parallel 1 and 2 can be switched indifferently */  | 
2191  |  |         /* So the MapInfo order and the EPSG order are not generally identical  | 
2192  |  |          */  | 
2193  |  |         /* which may cause recognition problems when reading in MapInfo */  | 
2194  | 0  |         if (sTABProj.nProjId == 3)  | 
2195  | 0  |         { | 
2196  | 0  |             const double dfCenterLong = params[0];  | 
2197  | 0  |             const double dfCenterLat = params[1];  | 
2198  | 0  |             const double dfStdP1 = params[2];  | 
2199  | 0  |             const double dfStdP2 = params[3];  | 
2200  |  |  | 
2201  |  |             // EPSG:3301 "Estonian Coordinate System of 1997"  | 
2202  | 0  |             if (std::fabs(dfCenterLong - 24) <= 1e-10 &&  | 
2203  | 0  |                 std::fabs(dfCenterLat - 57.51755393056) <= 1e-10 &&  | 
2204  |  |                 // MapInfo uses a less accurate value of StdP2 than EPSG  | 
2205  | 0  |                 std::fabs(dfStdP1 - 59.33333333) <= 1e-8 &&  | 
2206  | 0  |                 std::fabs(dfStdP2 - 58) <= 1e-8)  | 
2207  | 0  |             { | 
2208  | 0  |                 CPLDebug("MITAB", "Switching standard parallel 1 and 2"); | 
2209  | 0  |                 std::swap(params[2], params[3]);  | 
2210  | 0  |             }  | 
2211  | 0  |             else  | 
2212  | 0  |             { | 
2213  | 0  |                 for (size_t i = 0; i < sizeof(asMapInfoLCCSRSList) /  | 
2214  | 0  |                                            sizeof(asMapInfoLCCSRSList[0]);  | 
2215  | 0  |                      i++)  | 
2216  | 0  |                 { | 
2217  | 0  |                     if (sTABProj.nDatumId ==  | 
2218  | 0  |                             asMapInfoLCCSRSList[i].nMapInfoDatumID &&  | 
2219  | 0  |                         TAB_EQUAL(dfCenterLong,  | 
2220  | 0  |                                   asMapInfoLCCSRSList[i].dfCenterLong) &&  | 
2221  | 0  |                         TAB_EQUAL(dfCenterLat,  | 
2222  | 0  |                                   asMapInfoLCCSRSList[i].dfCenterLat))  | 
2223  | 0  |                     { | 
2224  | 0  |                         if (TAB_EQUAL(dfStdP1,  | 
2225  | 0  |                                       asMapInfoLCCSRSList[i].dfStdP1) &&  | 
2226  | 0  |                             TAB_EQUAL(dfStdP2, asMapInfoLCCSRSList[i].dfStdP2))  | 
2227  | 0  |                         { | 
2228  | 0  |                             break;  | 
2229  | 0  |                         }  | 
2230  | 0  |                         else if (TAB_EQUAL(dfStdP1,  | 
2231  | 0  |                                            asMapInfoLCCSRSList[i].dfStdP2) &&  | 
2232  | 0  |                                  TAB_EQUAL(dfStdP2,  | 
2233  | 0  |                                            asMapInfoLCCSRSList[i].dfStdP1))  | 
2234  | 0  |                         { | 
2235  | 0  |                             CPLDebug("MITAB", | 
2236  | 0  |                                      "Switching standard parallel 1 and 2");  | 
2237  | 0  |                             std::swap(params[2], params[3]);  | 
2238  | 0  |                             break;  | 
2239  | 0  |                         }  | 
2240  | 0  |                     }  | 
2241  | 0  |                 }  | 
2242  | 0  |             }  | 
2243  | 0  |         }  | 
2244  | 0  |     }  | 
2245  |  |  | 
2246  |  |     // Google Merc  | 
2247  | 0  |     const char *pszAuthorityName = nullptr;  | 
2248  | 0  |     const char *pszAuthorityCode = nullptr;  | 
2249  | 0  |     const char *pszExtension = nullptr;  | 
2250  | 0  |     if (((pszAuthorityName = poSpatialRef->GetAuthorityName(nullptr)) !=  | 
2251  | 0  |              nullptr &&  | 
2252  | 0  |          EQUAL(pszAuthorityName, "EPSG") &&  | 
2253  | 0  |          (pszAuthorityCode = poSpatialRef->GetAuthorityCode(nullptr)) !=  | 
2254  | 0  |              nullptr &&  | 
2255  | 0  |          atoi(pszAuthorityCode) == 3857) ||  | 
2256  | 0  |         ((pszExtension = poSpatialRef->GetExtension(nullptr, "PROJ4")) !=  | 
2257  | 0  |              nullptr &&  | 
2258  | 0  |          (EQUAL(pszExtension, "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 "  | 
2259  | 0  |                               "+lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m "  | 
2260  | 0  |                               "+nadgrids=@null +wktext  +no_defs") ||  | 
2261  | 0  |           EQUAL(pszExtension,  | 
2262  | 0  |                 "+proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 "  | 
2263  | 0  |                 "+y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defs"))))  | 
2264  | 0  |     { | 
2265  | 0  |         sTABProj.nDatumId = 157;  | 
2266  | 0  |         sTABProj.nEllipsoidId = 54;  | 
2267  | 0  |     }  | 
2268  |  |  | 
2269  |  |     /*-----------------------------------------------------------------  | 
2270  |  |      * Translate the units  | 
2271  |  |      *----------------------------------------------------------------*/  | 
2272  | 0  |     if (sTABProj.nProjId == 1 || pszLinearUnits == nullptr)  | 
2273  | 0  |         sTABProj.nUnitsId = 13;  | 
2274  | 0  |     else if (dfLinearConv == 1000.0)  | 
2275  | 0  |         sTABProj.nUnitsId = 1;  | 
2276  | 0  |     else if (dfLinearConv == 0.0254 || EQUAL(pszLinearUnits, "Inch") ||  | 
2277  | 0  |              EQUAL(pszLinearUnits, "IINCH"))  | 
2278  | 0  |         sTABProj.nUnitsId = 2;  | 
2279  | 0  |     else if (fabs(dfLinearConv - CPLAtof(SRS_UL_FOOT_CONV)) <  | 
2280  | 0  |                  1e-15 * dfLinearConv ||  | 
2281  | 0  |              EQUAL(pszLinearUnits, SRS_UL_FOOT))  | 
2282  | 0  |         sTABProj.nUnitsId = 3;  | 
2283  | 0  |     else if (EQUAL(pszLinearUnits, "YARD") || EQUAL(pszLinearUnits, "IYARD") ||  | 
2284  | 0  |              dfLinearConv == 0.9144)  | 
2285  | 0  |         sTABProj.nUnitsId = 4;  | 
2286  | 0  |     else if (dfLinearConv == 0.001)  | 
2287  | 0  |         sTABProj.nUnitsId = 5;  | 
2288  | 0  |     else if (dfLinearConv == 0.01)  | 
2289  | 0  |         sTABProj.nUnitsId = 6;  | 
2290  | 0  |     else if (dfLinearConv == 1.0)  | 
2291  | 0  |         sTABProj.nUnitsId = 7;  | 
2292  | 0  |     else if (fabs(dfLinearConv - CPLAtof(SRS_UL_US_FOOT_CONV)) <  | 
2293  | 0  |                  1e-15 * dfLinearConv ||  | 
2294  | 0  |              EQUAL(pszLinearUnits, SRS_UL_US_FOOT))  | 
2295  | 0  |         sTABProj.nUnitsId = 8;  | 
2296  | 0  |     else if (dfLinearConv == 1852.0 ||  | 
2297  | 0  |              EQUAL(pszLinearUnits, SRS_UL_NAUTICAL_MILE))  | 
2298  | 0  |         sTABProj.nUnitsId = 9;  | 
2299  | 0  |     else if (EQUAL(pszLinearUnits, SRS_UL_LINK) ||  | 
2300  | 0  |              EQUAL(pszLinearUnits, "GUNTERLINK"))  | 
2301  | 0  |         sTABProj.nUnitsId = 30;  | 
2302  | 0  |     else if (EQUAL(pszLinearUnits, SRS_UL_CHAIN) ||  | 
2303  | 0  |              EQUAL(pszLinearUnits, "GUNTERCHAIN"))  | 
2304  | 0  |         sTABProj.nUnitsId = 31;  | 
2305  | 0  |     else if (EQUAL(pszLinearUnits, SRS_UL_ROD))  | 
2306  | 0  |         sTABProj.nUnitsId = 32;  | 
2307  | 0  |     else if (EQUAL(pszLinearUnits, "Mile") || EQUAL(pszLinearUnits, "IMILE"))  | 
2308  | 0  |         sTABProj.nUnitsId = 0;  | 
2309  | 0  |     else  | 
2310  | 0  |         sTABProj.nUnitsId = 7;  | 
2311  |  | 
  | 
2312  | 0  |     return 0;  | 
2313  | 0  | }  | 
2314  |  |  | 
2315  |  | extern const MapInfoDatumInfo asDatumInfoList[];  | 
2316  |  | extern const MapInfoSpheroidInfo asSpheroidInfoList[];  | 
2317  |  |  | 
2318  |  | /************************************************************************/  | 
2319  |  | /*                      MITABCoordSys2SpatialRef()                      */  | 
2320  |  | /*                                                                      */  | 
2321  |  | /*      Convert a MIF COORDSYS string into a new OGRSpatialReference    */  | 
2322  |  | /*      object.                                                         */  | 
2323  |  | /************************************************************************/  | 
2324  |  |  | 
2325  |  | OGRSpatialReference *MITABCoordSys2SpatialRef(const char *pszCoordSys)  | 
2326  |  |  | 
2327  | 0  | { | 
2328  | 0  |     TABProjInfo sTABProj;  | 
2329  | 0  |     if (MITABCoordSys2TABProjInfo(pszCoordSys, &sTABProj) < 0)  | 
2330  | 0  |         return nullptr;  | 
2331  | 0  |     OGRSpatialReference *poSR = TABFileGetSpatialRefFromTABProj(sTABProj);  | 
2332  |  |  | 
2333  |  |     // Report on translation.  | 
2334  | 0  |     char *pszWKT = nullptr;  | 
2335  |  | 
  | 
2336  | 0  |     poSR->exportToWkt(&pszWKT);  | 
2337  | 0  |     if (pszWKT != nullptr)  | 
2338  | 0  |     { | 
2339  | 0  |         CPLDebug("MITAB", "This CoordSys value:\n%s\nwas translated to:\n%s", | 
2340  | 0  |                  pszCoordSys, pszWKT);  | 
2341  | 0  |         CPLFree(pszWKT);  | 
2342  | 0  |     }  | 
2343  |  | 
  | 
2344  | 0  |     return poSR;  | 
2345  | 0  | }  | 
2346  |  |  | 
2347  |  | /************************************************************************/  | 
2348  |  | /*                      MITABSpatialRef2CoordSys()                      */  | 
2349  |  | /*                                                                      */  | 
2350  |  | /*      Converts a OGRSpatialReference object into a MIF COORDSYS       */  | 
2351  |  | /*      string.                                                         */  | 
2352  |  | /*                                                                      */  | 
2353  |  | /*      The function returns a newly allocated string that should be    */  | 
2354  |  | /*      CPLFree()'d by the caller.                                      */  | 
2355  |  | /************************************************************************/  | 
2356  |  |  | 
2357  |  | char *MITABSpatialRef2CoordSys(const OGRSpatialReference *poSR)  | 
2358  |  |  | 
2359  | 0  | { | 
2360  | 0  |     if (poSR == nullptr)  | 
2361  | 0  |         return nullptr;  | 
2362  |  |  | 
2363  | 0  |     TABProjInfo sTABProj;  | 
2364  | 0  |     int nParamCount = 0;  | 
2365  | 0  |     TABFileGetTABProjFromSpatialRef(poSR, sTABProj, nParamCount);  | 
2366  |  |  | 
2367  |  |     // Do coordsys lookup.  | 
2368  | 0  |     double dXMin = 0.0;  | 
2369  | 0  |     double dYMin = 0.0;  | 
2370  | 0  |     double dXMax = 0.0;  | 
2371  | 0  |     double dYMax = 0.0;  | 
2372  | 0  |     bool bHasBounds = false;  | 
2373  | 0  |     if (sTABProj.nProjId > 1 &&  | 
2374  | 0  |         MITABLookupCoordSysBounds(&sTABProj, dXMin, dYMin, dXMax, dYMax, true))  | 
2375  | 0  |     { | 
2376  | 0  |         bHasBounds = true;  | 
2377  | 0  |     }  | 
2378  |  |  | 
2379  |  |     // Translate the units.  | 
2380  | 0  |     const char *pszMIFUnits = TABUnitIdToString(sTABProj.nUnitsId);  | 
2381  |  |  | 
2382  |  |     // Build coordinate system definition.  | 
2383  | 0  |     CPLString osCoordSys;  | 
2384  |  | 
  | 
2385  | 0  |     if (sTABProj.nProjId != 0)  | 
2386  | 0  |     { | 
2387  | 0  |         osCoordSys.Printf("Earth Projection %d", sTABProj.nProjId); | 
2388  | 0  |     }  | 
2389  | 0  |     else  | 
2390  | 0  |     { | 
2391  | 0  |         osCoordSys.Printf("NonEarth Units"); | 
2392  | 0  |     }  | 
2393  |  |  | 
2394  |  |     // Append Datum.  | 
2395  | 0  |     if (sTABProj.nProjId != 0)  | 
2396  | 0  |     { | 
2397  | 0  |         osCoordSys += CPLSPrintf(", %d", sTABProj.nDatumId); | 
2398  |  | 
  | 
2399  | 0  |         if (sTABProj.nDatumId == 999 || sTABProj.nDatumId == 9999)  | 
2400  | 0  |         { | 
2401  | 0  |             osCoordSys +=  | 
2402  | 0  |                 CPLSPrintf(", %d, %.15g, %.15g, %.15g", sTABProj.nEllipsoidId, | 
2403  | 0  |                            sTABProj.dDatumShiftX, sTABProj.dDatumShiftY,  | 
2404  | 0  |                            sTABProj.dDatumShiftZ);  | 
2405  | 0  |         }  | 
2406  |  | 
  | 
2407  | 0  |         if (sTABProj.nDatumId == 9999)  | 
2408  | 0  |         { | 
2409  | 0  |             osCoordSys +=  | 
2410  | 0  |                 CPLSPrintf(", %.15g, %.15g, %.15g, %.15g, %.15g", | 
2411  | 0  |                            sTABProj.adDatumParams[0], sTABProj.adDatumParams[1],  | 
2412  | 0  |                            sTABProj.adDatumParams[2], sTABProj.adDatumParams[3],  | 
2413  | 0  |                            sTABProj.adDatumParams[4]);  | 
2414  | 0  |         }  | 
2415  | 0  |     }  | 
2416  |  |  | 
2417  |  |     // Append units.  | 
2418  | 0  |     if (sTABProj.nProjId != 1 && pszMIFUnits != nullptr)  | 
2419  | 0  |     { | 
2420  | 0  |         if (sTABProj.nProjId != 0)  | 
2421  | 0  |             osCoordSys += ",";  | 
2422  |  | 
  | 
2423  | 0  |         osCoordSys += CPLSPrintf(" \"%s\"", pszMIFUnits); | 
2424  | 0  |     }  | 
2425  |  |  | 
2426  |  |     // Append Projection Params.  | 
2427  | 0  |     for (int iParam = 0; iParam < nParamCount; iParam++)  | 
2428  | 0  |         osCoordSys += CPLSPrintf(", %.15g", sTABProj.adProjParams[iParam]); | 
2429  |  |  | 
2430  |  |     // Append user bounds.  | 
2431  | 0  |     if (bHasBounds)  | 
2432  | 0  |     { | 
2433  | 0  |         if (fabs(dXMin - floor(dXMin + 0.5)) < 1e-8 &&  | 
2434  | 0  |             fabs(dYMin - floor(dYMin + 0.5)) < 1e-8 &&  | 
2435  | 0  |             fabs(dXMax - floor(dXMax + 0.5)) < 1e-8 &&  | 
2436  | 0  |             fabs(dYMax - floor(dYMax + 0.5)) < 1e-8)  | 
2437  | 0  |         { | 
2438  | 0  |             osCoordSys +=  | 
2439  | 0  |                 CPLSPrintf(" Bounds (%d, %d) (%d, %d)", static_cast<int>(dXMin), | 
2440  | 0  |                            static_cast<int>(dYMin), static_cast<int>(dXMax),  | 
2441  | 0  |                            static_cast<int>(dYMax));  | 
2442  | 0  |         }  | 
2443  | 0  |         else  | 
2444  | 0  |         { | 
2445  | 0  |             osCoordSys += CPLSPrintf(" Bounds (%f, %f) (%f, %f)", dXMin, dYMin, | 
2446  | 0  |                                      dXMax, dYMax);  | 
2447  | 0  |         }  | 
2448  | 0  |     }  | 
2449  |  |  | 
2450  |  |     // Report on translation.  | 
2451  | 0  |     char *pszWKT = nullptr;  | 
2452  |  | 
  | 
2453  | 0  |     poSR->exportToWkt(&pszWKT);  | 
2454  | 0  |     if (pszWKT != nullptr)  | 
2455  | 0  |     { | 
2456  | 0  |         CPLDebug("MITAB", "This WKT Projection:\n%s\n\ntranslates to:\n%s", | 
2457  | 0  |                  pszWKT, osCoordSys.c_str());  | 
2458  | 0  |         CPLFree(pszWKT);  | 
2459  | 0  |     }  | 
2460  |  | 
  | 
2461  | 0  |     return CPLStrdup(osCoordSys.c_str());  | 
2462  | 0  | }  | 
2463  |  |  | 
2464  |  | /************************************************************************/  | 
2465  |  | /*                      MITABExtractCoordSysBounds                      */  | 
2466  |  | /*                                                                      */  | 
2467  |  | /* Return true if MIF coordsys string contains a BOUNDS parameter and   */  | 
2468  |  | /* Set x/y min/max values.                                              */  | 
2469  |  | /************************************************************************/  | 
2470  |  |  | 
2471  |  | bool MITABExtractCoordSysBounds(const char *pszCoordSys, double &dXMin,  | 
2472  |  |                                 double &dYMin, double &dXMax, double &dYMax)  | 
2473  |  |  | 
2474  | 0  | { | 
2475  | 0  |     if (pszCoordSys == nullptr)  | 
2476  | 0  |         return false;  | 
2477  |  |  | 
2478  | 0  |     char **papszFields =  | 
2479  | 0  |         CSLTokenizeStringComplex(pszCoordSys, " ,()", TRUE, FALSE);  | 
2480  |  | 
  | 
2481  | 0  |     int iBounds = CSLFindString(papszFields, "Bounds");  | 
2482  |  | 
  | 
2483  | 0  |     if (iBounds >= 0 && iBounds + 4 < CSLCount(papszFields))  | 
2484  | 0  |     { | 
2485  | 0  |         dXMin = CPLAtof(papszFields[++iBounds]);  | 
2486  | 0  |         dYMin = CPLAtof(papszFields[++iBounds]);  | 
2487  | 0  |         dXMax = CPLAtof(papszFields[++iBounds]);  | 
2488  | 0  |         dYMax = CPLAtof(papszFields[++iBounds]);  | 
2489  | 0  |         CSLDestroy(papszFields);  | 
2490  | 0  |         return true;  | 
2491  | 0  |     }  | 
2492  |  |  | 
2493  | 0  |     CSLDestroy(papszFields);  | 
2494  | 0  |     return false;  | 
2495  | 0  | }  | 
2496  |  |  | 
2497  |  | /**********************************************************************  | 
2498  |  |  *                     MITABCoordSys2TABProjInfo()  | 
2499  |  |  *  | 
2500  |  |  * Convert a MIF COORDSYS string into a TABProjInfo structure.  | 
2501  |  |  *  | 
2502  |  |  * Returns 0 on success, -1 on error.  | 
2503  |  |  **********************************************************************/  | 
2504  |  | int MITABCoordSys2TABProjInfo(const char *pszCoordSys, TABProjInfo *psProj)  | 
2505  |  |  | 
2506  | 0  | { | 
2507  |  |     // Set all fields to zero, equivalent of NonEarth Units "mi"  | 
2508  | 0  |     memset(psProj, 0, sizeof(TABProjInfo));  | 
2509  |  | 
  | 
2510  | 0  |     if (pszCoordSys == nullptr)  | 
2511  | 0  |         return -1;  | 
2512  |  |  | 
2513  |  |     // Parse the passed string into words.  | 
2514  | 0  |     while (*pszCoordSys == ' ')  | 
2515  | 0  |         pszCoordSys++;  // Eat leading spaces.  | 
2516  | 0  |     if (STARTS_WITH_CI(pszCoordSys, "CoordSys") && pszCoordSys[8] != '\0')  | 
2517  | 0  |         pszCoordSys += 9;  | 
2518  |  | 
  | 
2519  | 0  |     char **papszFields =  | 
2520  | 0  |         CSLTokenizeStringComplex(pszCoordSys, " ,", TRUE, FALSE);  | 
2521  |  |  | 
2522  |  |     // Clip off Bounds information.  | 
2523  | 0  |     int iBounds = CSLFindString(papszFields, "Bounds");  | 
2524  |  | 
  | 
2525  | 0  |     while (iBounds != -1 && papszFields[iBounds] != nullptr)  | 
2526  | 0  |     { | 
2527  | 0  |         CPLFree(papszFields[iBounds]);  | 
2528  | 0  |         papszFields[iBounds] = nullptr;  | 
2529  | 0  |         iBounds++;  | 
2530  | 0  |     }  | 
2531  |  |  | 
2532  |  |     // Fetch the projection.  | 
2533  | 0  |     char **papszNextField = nullptr;  | 
2534  |  | 
  | 
2535  | 0  |     if (CSLCount(papszFields) >= 3 && EQUAL(papszFields[0], "Earth") &&  | 
2536  | 0  |         EQUAL(papszFields[1], "Projection"))  | 
2537  | 0  |     { | 
2538  | 0  |         int nProjId = atoi(papszFields[2]);  | 
2539  | 0  |         if (nProjId >= 3000)  | 
2540  | 0  |             nProjId -= 3000;  | 
2541  | 0  |         else if (nProjId >= 2000)  | 
2542  | 0  |             nProjId -= 2000;  | 
2543  | 0  |         else if (nProjId >= 1000)  | 
2544  | 0  |             nProjId -= 1000;  | 
2545  |  | 
  | 
2546  | 0  |         psProj->nProjId = static_cast<GByte>(nProjId);  | 
2547  | 0  |         papszNextField = papszFields + 3;  | 
2548  | 0  |     }  | 
2549  | 0  |     else if (CSLCount(papszFields) >= 2 && EQUAL(papszFields[0], "NonEarth"))  | 
2550  | 0  |     { | 
2551  |  |         // NonEarth Units "..." Bounds (x, y) (x, y)  | 
2552  | 0  |         psProj->nProjId = 0;  | 
2553  | 0  |         papszNextField = papszFields + 2;  | 
2554  |  | 
  | 
2555  | 0  |         if (papszNextField[0] != nullptr && EQUAL(papszNextField[0], "Units"))  | 
2556  | 0  |             papszNextField++;  | 
2557  | 0  |     }  | 
2558  | 0  |     else  | 
2559  | 0  |     { | 
2560  |  |         // Invalid projection string ???  | 
2561  | 0  |         if (CSLCount(papszFields) > 0)  | 
2562  | 0  |             CPLError(CE_Warning, CPLE_IllegalArg,  | 
2563  | 0  |                      "Failed parsing CoordSys: '%s'", pszCoordSys);  | 
2564  | 0  |         CSLDestroy(papszFields);  | 
2565  | 0  |         return -1;  | 
2566  | 0  |     }  | 
2567  |  |  | 
2568  |  |     // Fetch the datum information.  | 
2569  | 0  |     int nDatum = 0;  | 
2570  |  | 
  | 
2571  | 0  |     if (psProj->nProjId != 0 && CSLCount(papszNextField) > 0)  | 
2572  | 0  |     { | 
2573  | 0  |         nDatum = atoi(papszNextField[0]);  | 
2574  | 0  |         papszNextField++;  | 
2575  | 0  |     }  | 
2576  |  | 
  | 
2577  | 0  |     if ((nDatum == 999 || nDatum == 9999) && CSLCount(papszNextField) >= 4)  | 
2578  | 0  |     { | 
2579  | 0  |         psProj->nEllipsoidId = static_cast<GByte>(atoi(papszNextField[0]));  | 
2580  | 0  |         psProj->dDatumShiftX = CPLAtof(papszNextField[1]);  | 
2581  | 0  |         psProj->dDatumShiftY = CPLAtof(papszNextField[2]);  | 
2582  | 0  |         psProj->dDatumShiftZ = CPLAtof(papszNextField[3]);  | 
2583  | 0  |         papszNextField += 4;  | 
2584  |  | 
  | 
2585  | 0  |         if (nDatum == 9999 && CSLCount(papszNextField) >= 5)  | 
2586  | 0  |         { | 
2587  | 0  |             psProj->adDatumParams[0] = CPLAtof(papszNextField[0]);  | 
2588  | 0  |             psProj->adDatumParams[1] = CPLAtof(papszNextField[1]);  | 
2589  | 0  |             psProj->adDatumParams[2] = CPLAtof(papszNextField[2]);  | 
2590  | 0  |             psProj->adDatumParams[3] = CPLAtof(papszNextField[3]);  | 
2591  | 0  |             psProj->adDatumParams[4] = CPLAtof(papszNextField[4]);  | 
2592  | 0  |             papszNextField += 5;  | 
2593  | 0  |         }  | 
2594  | 0  |     }  | 
2595  | 0  |     else if (nDatum != 999 && nDatum != 9999)  | 
2596  | 0  |     { | 
2597  |  |         // Find the datum, and collect its parameters if possible.  | 
2598  | 0  |         const MapInfoDatumInfo *psDatumInfo = nullptr;  | 
2599  |  | 
  | 
2600  | 0  |         int iDatum = 0;  // Used after for.  | 
2601  | 0  |         for (; asDatumInfoList[iDatum].nMapInfoDatumID != -1; iDatum++)  | 
2602  | 0  |         { | 
2603  | 0  |             if (asDatumInfoList[iDatum].nMapInfoDatumID == nDatum)  | 
2604  | 0  |             { | 
2605  | 0  |                 psDatumInfo = asDatumInfoList + iDatum;  | 
2606  | 0  |                 break;  | 
2607  | 0  |             }  | 
2608  | 0  |         }  | 
2609  |  | 
  | 
2610  | 0  |         if (asDatumInfoList[iDatum].nMapInfoDatumID == -1)  | 
2611  | 0  |         { | 
2612  |  |             // Use WGS84.  | 
2613  | 0  |             psDatumInfo = asDatumInfoList + 0;  | 
2614  | 0  |         }  | 
2615  |  | 
  | 
2616  | 0  |         if (psDatumInfo != nullptr)  | 
2617  | 0  |         { | 
2618  | 0  |             psProj->nEllipsoidId = static_cast<GByte>(psDatumInfo->nEllipsoid);  | 
2619  | 0  |             psProj->nDatumId =  | 
2620  | 0  |                 static_cast<GInt16>(psDatumInfo->nMapInfoDatumID);  | 
2621  | 0  |             psProj->dDatumShiftX = psDatumInfo->dfShiftX;  | 
2622  | 0  |             psProj->dDatumShiftY = psDatumInfo->dfShiftY;  | 
2623  | 0  |             psProj->dDatumShiftZ = psDatumInfo->dfShiftZ;  | 
2624  | 0  |             psProj->adDatumParams[0] = psDatumInfo->dfDatumParm0;  | 
2625  | 0  |             psProj->adDatumParams[1] = psDatumInfo->dfDatumParm1;  | 
2626  | 0  |             psProj->adDatumParams[2] = psDatumInfo->dfDatumParm2;  | 
2627  | 0  |             psProj->adDatumParams[3] = psDatumInfo->dfDatumParm3;  | 
2628  | 0  |             psProj->adDatumParams[4] = psDatumInfo->dfDatumParm4;  | 
2629  | 0  |         }  | 
2630  | 0  |     }  | 
2631  |  |  | 
2632  |  |     // Fetch the units string.  | 
2633  | 0  |     if (CSLCount(papszNextField) > 0)  | 
2634  | 0  |     { | 
2635  | 0  |         if (isdigit(static_cast<unsigned char>(papszNextField[0][0])))  | 
2636  | 0  |         { | 
2637  | 0  |             psProj->nUnitsId = static_cast<GByte>(atoi(papszNextField[0]));  | 
2638  | 0  |         }  | 
2639  | 0  |         else  | 
2640  | 0  |         { | 
2641  | 0  |             psProj->nUnitsId =  | 
2642  | 0  |                 static_cast<GByte>(TABUnitIdFromString(papszNextField[0]));  | 
2643  | 0  |         }  | 
2644  | 0  |         papszNextField++;  | 
2645  | 0  |     }  | 
2646  |  |  | 
2647  |  |     // Finally the projection parameters.  | 
2648  | 0  |     for (int iParam = 0; iParam < 7 && CSLCount(papszNextField) > 0; iParam++)  | 
2649  | 0  |     { | 
2650  | 0  |         psProj->adProjParams[iParam] = CPLAtof(papszNextField[0]);  | 
2651  | 0  |         papszNextField++;  | 
2652  | 0  |     }  | 
2653  |  | 
  | 
2654  | 0  |     CSLDestroy(papszFields);  | 
2655  |  | 
  | 
2656  | 0  |     return 0;  | 
2657  | 0  | }  | 
2658  |  |  | 
2659  |  | /*! @endcond */  |