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