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