/********************************************************************** * * Name: mitab_spatialref.cpp * Project: MapInfo TAB Read/Write library * Language: C++ * Purpose: Implementation of the SpatialRef stuff in the TABFile class. * Author: Frank Warmerdam, warmerdam@pobox.com * ********************************************************************** * Copyright (c) 1999-2001, Frank Warmerdam * Copyright (c) 2014, Even Rouault * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. **********************************************************************/ #include "cpl_port.h" #include "mitab.h" #include #include #include #include #include #include "cpl_conv.h" #include "cpl_error.h" #include "cpl_string.h" #include "mitab_priv.h" #include "ogr_spatialref.h" #include "ogr_srs_api.h" CPL_CVSID("$Id: mitab_spatialref.cpp fa752ad6eabafaf630a704e1892a9d837d683cb3 2021-03-06 17:04:38 +0100 Even Rouault $") /* -------------------------------------------------------------------- */ /* This table was automatically generated by doing translations */ /* between mif and tab for each datum, and extracting the */ /* parameters from the tab file. The EPSG codes and OGC names */ /* were added afterwards and may be incomplete or inaccurate. */ /* -------------------------------------------------------------------- */ extern const MapInfoDatumInfo asDatumInfoList[]; extern const MapInfoSpheroidInfo asSpheroidInfoList[]; /* EPSG code, MapInfo datum ID (or 9999), OGC Name, datum parameters... */ const MapInfoDatumInfo asDatumInfoList[] = { { 0, 104, "WGS_1984", 28,0, 0, 0, 0, 0, 0, 0, 0}, { 6269, 74, "North_American_Datum_1983", 0, 0, 0, 0, 0, 0, 0, 0, 0}, { 0, 0, "", 29, 0, 0, 0, 0, 0, 0, 0, 0}, // Datum ignore { 6201, 1, "Adindan", 6, -162, -12, 206, 0, 0, 0, 0, 0}, { 6205, 2, "Afgooye", 3, -43, -163, 45, 0, 0, 0, 0, 0}, { 6204, 3, "Ain_el_Abd_1970", 4, -150, -251, -2, 0, 0, 0, 0, 0}, { 0, 4, "Anna_1_Astro_1965", 2, -491, -22, 435, 0, 0, 0, 0, 0}, { 6209, 5, "Arc_1950", 15,-143, -90, -294,0, 0, 0, 0, 0}, { 6210, 6, "Arc_1960", 6, -160, -8, -300,0, 0, 0, 0, 0}, { 0, 7, "Ascension_Islands", 4, -207, 107, 52, 0, 0, 0, 0, 0}, { 0, 8, "Astro_Beacon_E", 4, 145, 75, -272,0, 0, 0, 0, 0}, { 0, 9, "Astro_B4_Sorol_Atoll", 4, 114, -116, -333,0, 0, 0, 0, 0}, { 0, 10, "Astro_Dos_71_4", 4, -320, 550, -494,0, 0, 0, 0, 0}, { 0, 11, "Astronomic_Station_1952", 4, 124, -234, -25, 0, 0, 0, 0, 0}, { 6202, 12, "Australian_Geodetic_Datum_66",2, -133, -48, 148, 0, 0, 0, 0, 0}, { 6203, 13, "Australian_Geodetic_Datum_84",2, -134, -48, 149, 0, 0, 0, 0, 0}, { 0, 14, "Bellevue_Ign", 4, -127, -769, 472, 0, 0, 0, 0, 0}, { 6216, 15, "Bermuda_1957", 7, -73, 213, 296, 0, 0, 0, 0, 0}, { 6218, 16, "Bogota", 4, 307, 304, -318,0, 0, 0, 0, 0}, { 6221, 17, "Campo_Inchauspe", 4, -148, 136, 90, 0, 0, 0, 0, 0}, { 0, 18, "Canton_Astro_1966", 4, 298, -304, -375,0, 0, 0, 0, 0}, { 6222, 19, "Cape", 6, -136, -108, -292,0, 0, 0, 0, 0}, { 6717, 20, "Cape_Canaveral", 7, -2, 150, 181, 0, 0, 0, 0, 0}, { 6223, 21, "Carthage", 6, -263, 6, 431, 0, 0, 0, 0, 0}, { 6672, 22, "Chatham_1971", 4, 175, -38, 113, 0, 0, 0, 0, 0}, { 6224, 23, "Chua", 4, -134, 229, -29, 0, 0, 0, 0, 0}, { 6225, 24, "Corrego_Alegre", 4, -206, 172, -6, 0, 0, 0, 0, 0}, { 6211, 25, "Batavia", 10,-377,681, -50, 0, 0, 0, 0, 0}, { 0, 26, "Dos_1968", 4, 230, -199, -752,0, 0, 0, 0, 0}, { 6719, 27, "Easter_Island_1967", 4, 211, 147, 111, 0, 0, 0, 0, 0}, { 6230, 28, "European_Datum_1950", 4, -87, -98, -121,0, 0, 0, 0, 0}, { 6668, 29, "European_Datum_1979", 4, -86, -98, -119,0, 0, 0, 0, 0}, { 6233, 30, "Gandajika_1970", 4, -133, -321, 50, 0, 0, 0, 0, 0}, { 6272, 31, "New_Zealand_GD49", 4, 84, -22, 209, 0, 0, 0, 0, 0}, { 6272, 31, "New_Zealand_Geodetic_Datum_1949",4,84, -22, 209, 0, 0, 0, 0, 0}, { 0, 32, "GRS_67", 21,0, 0, 0, 0, 0, 0, 0, 0}, { 0, 33, "GRS_80", 0, 0, 0, 0, 0, 0, 0, 0, 0}, { 6171, 33, "Reseau_Geodesique_Francais_1993",0, 0, 0, 0, 0, 0, 0, 0, 0}, { 6619, 33, "SWEREF99", 0, 0, 0, 0, 0, 0, 0, 0, 0}, { 6675, 34, "Guam_1963", 7, -100, -248, 259, 0, 0, 0, 0, 0}, { 0, 35, "Gux_1_Astro", 4, 252, -209, -751,0, 0, 0, 0, 0}, { 6254, 36, "Hito_XVIII_1963", 4, 16, 196, 93, 0, 0, 0, 0, 0}, { 6658, 37, "Hjorsey_1955", 4, -73, 46, -86, 0, 0, 0, 0, 0}, { 6738, 38, "Hong_Kong_1963", 4, -156, -271, -189,0, 0, 0, 0, 0}, { 6236, 39, "Hu_Tzu_Shan", 4, -634, -549, -201,0, 0, 0, 0, 0}, { 0, 40, "Indian_Thailand_Vietnam", 11,214, 836, 303, 0, 0, 0, 0, 0}, { 0, 41, "Indian_Bangladesh", 11,289, 734, 257, 0, 0, 0, 0, 0}, { 6299, 42, "Ireland_1965", 13,506, -122, 611, 0, 0, 0, 0, 0}, { 0, 43, "ISTS_073_Astro_1969", 4, 208, -435, -229,0, 0, 0, 0, 0}, { 6725, 44, "Johnston_Island_1961", 4, 191, -77, -204,0, 0, 0, 0, 0}, { 6244, 45, "Kandawala", 11,-97, 787, 86, 0, 0, 0, 0, 0}, { 0, 46, "Kerguyelen_Island", 4, 145, -187, 103, 0, 0, 0, 0, 0}, { 6245, 47, "Kertau", 17,-11, 851, 5, 0, 0, 0, 0, 0}, { 0, 48, "L_C_5_Astro", 7, 42, 124, 147, 0, 0, 0, 0, 0}, { 6251, 49, "Liberia_1964", 6, -90, 40, 88, 0, 0, 0, 0, 0}, { 0, 50, "Luzon_Phillippines", 7, -133, -77, -51, 0, 0, 0, 0, 0}, { 0, 51, "Luzon_Mindanao_Island", 7, -133, -79, -72, 0, 0, 0, 0, 0}, { 6256, 52, "Mahe_1971", 6, 41, -220, -134,0, 0, 0, 0, 0}, { 0, 53, "Marco_Astro", 4, -289, -124, 60, 0, 0, 0, 0, 0}, { 6262, 54, "Massawa", 10,639, 405, 60, 0, 0, 0, 0, 0}, { 6261, 55, "Merchich", 16,31, 146, 47, 0, 0, 0, 0, 0}, { 0, 56, "Midway_Astro_1961", 4, 912, -58, 1227,0, 0, 0, 0, 0}, { 6263, 57, "Minna", 6, -92, -93, 122, 0, 0, 0, 0, 0}, { 0, 58, "Nahrwan_Masirah_Island", 6, -247, -148, 369, 0, 0, 0, 0, 0}, { 0, 59, "Nahrwan_Un_Arab_Emirates", 6, -249, -156, 381, 0, 0, 0, 0, 0}, { 0, 60, "Nahrwan_Saudi_Arabia", 6, -231, -196, 482, 0, 0, 0, 0, 0}, { 6271, 61, "Naparima_1972", 4, -2, 374, 172, 0, 0, 0, 0, 0}, { 6267, 62, "NAD_1927", 7, -8, 160, 176, 0, 0, 0, 0, 0}, { 6267, 62, "North_American_Datum_1927", 7, -8, 160, 176, 0, 0, 0, 0, 0}, { 0, 63, "NAD_27_Alaska", 7, -5, 135, 172, 0, 0, 0, 0, 0}, { 0, 64, "NAD_27_Bahamas", 7, -4, 154, 178, 0, 0, 0, 0, 0}, { 0, 65, "NAD_27_San_Salvador", 7, 1, 140, 165, 0, 0, 0, 0, 0}, { 0, 66, "NAD_27_Canada", 7, -10, 158, 187, 0, 0, 0, 0, 0}, { 0, 67, "NAD_27_Canal_Zone", 7, 0, 125, 201, 0, 0, 0, 0, 0}, { 0, 68, "NAD_27_Caribbean", 7, -7, 152, 178, 0, 0, 0, 0, 0}, { 0, 69, "NAD_27_Central_America", 7, 0, 125, 194, 0, 0, 0, 0, 0}, { 0, 70, "NAD_27_Cuba", 7, -9, 152, 178, 0, 0, 0, 0, 0}, { 0, 71, "NAD_27_Greenland", 7, 11, 114, 195, 0, 0, 0, 0, 0}, { 0, 72, "NAD_27_Mexico", 7, -12, 130, 190, 0, 0, 0, 0, 0}, { 0, 73, "NAD_27_Michigan", 8, -8, 160, 176, 0, 0, 0, 0, 0}, { 0, 75, "Observatorio_1966", 4, -425, -169, 81, 0, 0, 0, 0, 0}, { 0, 76, "Old_Egyptian", 22,-130, 110, -13, 0, 0, 0, 0, 0}, { 6135, 77, "Old_Hawaiian", 7, 61, -285, -181,0, 0, 0, 0, 0}, { 0, 78, "Oman", 6, -346, -1, 224, 0, 0, 0, 0, 0}, { 6277, 79, "OSGB_1936", 9, 375, -111, 431, 0, 0, 0, 0, 0}, { 0, 80, "Pico_De_Las_Nieves", 4, -307, -92, 127, 0, 0, 0, 0, 0}, { 6729, 81, "Pitcairn_Astro_1967", 4, 185, 165, 42, 0, 0, 0, 0, 0}, { 6248, 82, "Provisional_South_American", 4, -288, 175, -376,0, 0, 0, 0, 0}, { 6139, 83, "Puerto_Rico", 7, 11, 72, -101,0, 0, 0, 0, 0}, { 6614, 84, "Qatar_National", 4, -128, -283, 22, 0, 0, 0, 0, 0}, { 6287, 85, "Qornoq", 4, 164, 138, -189, 0, 0, 0, 0, 0}, { 6627, 86, "Reunion", 4, 94, -948,-1262,0, 0, 0, 0, 0}, { 6265, 87, "Monte_Mario", 4, -225, -65, 9, 0, 0, 0, 0, 0}, { 0, 88, "Santo_Dos", 4, 170, 42, 84, 0, 0, 0, 0, 0}, { 0, 89, "Sao_Braz", 4, -203, 141, 53, 0, 0, 0, 0, 0}, { 6292, 90, "Sapper_Hill_1943", 4, -355, 16, 74, 0, 0, 0, 0, 0}, { 6293, 91, "Schwarzeck", 14,616, 97, -251, 0, 0, 0, 0, 0}, { 6618, 92, "South_American_Datum_1969", 24,-57, 1, -41, 0, 0, 0, 0, 0}, { 0, 93, "South_Asia", 19,7, -10, -26, 0, 0, 0, 0, 0}, { 0, 94, "Southeast_Base", 4, -499, -249,314, 0, 0, 0, 0, 0}, { 0, 95, "Southwest_Base", 4, -104, 167, -38, 0, 0, 0, 0, 0}, { 6298, 96, "Timbalai_1948", 11,-689, 691, -46, 0, 0, 0, 0, 0}, { 6301, 97, "Tokyo", 10,-128, 481, 664, 0, 0, 0, 0, 0}, { 0, 98, "Tristan_Astro_1968", 4, -632, 438, -609, 0, 0, 0, 0, 0}, { 6731, 99, "Viti_Levu_1916", 6, 51, 391, -36, 0, 0, 0, 0, 0}, { 0, 100, "Wake_Entiwetok_1960", 23,101, 52, -39, 0, 0, 0, 0, 0}, { 0, 101, "WGS_60", 26,0, 0, 0, 0, 0, 0, 0, 0}, { 6760, 102, "WGS_66", 27,0, 0, 0, 0, 0, 0, 0, 0}, { 6322, 103, "WGS_1972", 1, 0, 8, 10, 0, 0, 0, 0, 0}, { 6322, 103, "World_Geodetic_System_1972", 1, 0, 8, 10, 0, 0, 0, 0, 0}, { 6326, 104, "WGS_1984", 28,0, 0, 0, 0, 0, 0, 0, 0}, { 6309, 105, "Yacare", 4, -155, 171, 37, 0, 0, 0, 0, 0}, { 6311, 106, "Zanderij", 4, -265, 120, -358, 0, 0, 0, 0, 0}, { 0, 107, "NTF", 30,-168, -60, 320, 0, 0, 0, 0, 0}, { 6231, 108, "European_Datum_1987", 4, -83, -96, -113, 0, 0, 0, 0, 0}, { 0, 109, "Netherlands_Bessel", 10,593, 26, 478, 0, 0, 0, 0, 0}, { 0, 110, "Belgium_Hayford", 4, 81, 120, 129, 0, 0, 0, 0, 0}, { 0, 111, "NWGL_10", 1, -1, 15, 1, 0, 0, 0, 0, 0}, { 6124, 112, "Rikets_koordinatsystem_1990",10,498, -36, 568, 0, 0, 0, 0, 0}, { 0, 113, "Lisboa_DLX", 4, -303, -62, 105, 0, 0, 0, 0, 0}, { 0, 114, "Melrica_1973_D73", 4, -223, 110, 37, 0, 0, 0, 0, 0}, { 6258, 115, "Euref_89", 0, 0, 0, 0, 0, 0, 0, 0, 0}, { 6283, 116, "GDA94", 0, 0, 0, 0, 0, 0, 0, 0, 0}, { 6283, 116, "Geocentric_Datum_of_Australia_1994", 0, 0, 0, 0, 0, 0, 0, 0, 0}, { 6167, 117, "NZGD2000", 0, 0, 0, 0, 0, 0, 0, 0, 0}, { 6167, 117, "New_Zealand_Geodetic_Datum_2000",0,0, 0, 0, 0, 0, 0, 0, 0}, { 6169, 118, "America_Samoa", 7, -115, 118, 426, 0, 0, 0, 0, 0}, { 0, 119, "Antigua_Astro_1965", 6, -270, 13, 62, 0, 0, 0, 0, 0}, { 6713, 120, "Ayabelle_Lighthouse", 6, -79, -129, 145, 0, 0, 0, 0, 0}, { 6219, 121, "Bukit_Rimpah", 10,-384, 664, -48, 0, 0, 0, 0, 0}, { 0, 122, "Estonia_1937", 10,374, 150, 588, 0, 0, 0, 0, 0}, { 6155, 123, "Dabola", 6, -83, 37, 124, 0, 0, 0, 0, 0}, { 6736, 124, "Deception_Island", 6, 260, 12, -147, 0, 0, 0, 0, 0}, { 0, 125, "Fort_Thomas_1955", 6, -7, 215, 225, 0, 0, 0, 0, 0}, { 0, 126, "Graciosa_base_1948", 4, -104, 167, -38, 0, 0, 0, 0, 0}, { 6255, 127, "Herat_North", 4, -333, -222,114, 0, 0, 0, 0, 0}, { 0, 128, "Hermanns_Kogel", 10,682, -203, 480, 0, 0, 0, 0, 0}, { 6240, 129, "Indian", 50,283, 682, 231, 0, 0, 0, 0, 0}, { 6239, 130, "Indian_1954", 11,217, 823, 299, 0, 0, 0, 0, 0}, { 6131, 131, "Indian_1960", 11,198, 881, 317, 0, 0, 0, 0, 0}, { 6240, 132, "Indian_1975", 11,210, 814, 289, 0, 0, 0, 0, 0}, { 6238, 133, "Indonesian_Datum_1974", 4, -24, -15, 5, 0, 0, 0, 0, 0}, { 0, 134, "ISTS061_Astro_1968", 4, -794, 119, -298, 0, 0, 0, 0, 0}, { 0, 135, "Kusaie_Astro_1951", 4, 647, 1777, -1124,0, 0, 0, 0, 0}, { 6250, 136, "Leigon", 6, -130, 29, 364, 0, 0, 0, 0, 0}, { 0, 137, "Montserrat_Astro_1958", 6, 174, 359, 365, 0, 0, 0, 0, 0}, { 6266, 138, "Mporaloko", 6, -74, -130, 42, 0, 0, 0, 0, 0}, { 0, 139, "North_Sahara_1959", 6, -186, -93, 310, 0, 0, 0, 0, 0}, { 0, 140, "Observatorio_Met_1939", 4, -425, -169,81, 0, 0, 0, 0, 0}, { 6620, 141, "Point_58", 6, -106, -129,165, 0, 0, 0, 0, 0}, { 6282, 142, "Pointe_Noire", 6, -148, 51, -291, 0, 0, 0, 0, 0}, { 6615, 143, "Porto_Santo_1936", 4, -499, -249,314, 0, 0, 0, 0, 0}, { 6616, 144, "Selvagem_Grande_1938", 4, -289, -124,60, 0, 0, 0, 0, 0}, { 0, 145, "Sierra_Leone_1960", 6, -88, 4, 101, 0, 0, 0, 0, 0}, { 6156, 146, "S_JTSK_Ferro", 10, 589, 76, 480, 0, 0, 0, 0, 0}, { 6297, 147, "Tananarive_1925", 4, -189, -242,-91, 0, 0, 0, 0, 0}, { 6811, 148, "Voirol_1874", 6, -73, -247,227, 0, 0, 0, 0, 0}, { 0, 149, "Virol_1960", 6, -123, -206,219, 0, 0, 0, 0, 0}, { 6148, 150, "Hartebeesthoek94", 28, 0, 0, 0, 0, 0, 0, 0, 0}, { 6122, 151, "ATS77", 51, 0, 0, 0, 0, 0, 0, 0, 0}, { 6612, 152, "JGD2000", 0, 0, 0, 0, 0, 0, 0, 0, 0}, { 0, 153, "HGRS87", 0, -199.87, 74.79, 246.62, 0, 0, 0, 0, 0}, { 6214, 154, "Beijing 1954", 3, -31.4, 144.3, 81.2, 0, 0, 0, 0, 0}, { 6754, 155, "Libya (LGD 2006)", 4, 208.4058, 109.8777, 2.5764, 0, 0, 0, 0, 0}, { 6317, 156, "Dealul Piscului 1970", 3, 28, -121, -77, 0, 0, 0, 0, 0}, { 0, 157, "WGS_1984", 54, 0, 0, 0, 0, 0, 0, 0, 0}, // Google merc { 6150, 158, "CH1903+ datum for Switzerland", 10, 674.374, 15.056, 405.346, 0, 0, 0, 0, 0}, { 0, 159, "Schwarzeck (updated) datum for Namibia", 14, 616.8, 103.3, -256.9, 0, 0, 0, 0, 0 }, { 0, 161, "NOAA GCS_Sphere", 55, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 1000,"DHDN_Potsdam_Rauenberg", 10,582, 105, 414, -1.04, -0.35, 3.08, 8.3, 0}, { 6284, 1001,"Pulkovo_1942", 3, 24, -123, -94, -0.02, 0.25, 0.13, 1.1, 0}, { 6807, 1002,"NTF_Paris_Meridian", 30,-168, -60, 320, 0, 0, 0, 0, 2.337229166667}, { 6149, 1003,"Switzerland_CH_1903", 10,660.077,13.551, 369.344, 0.804816, 0.577692, 0.952236, 5.66,0}, { 6237, 1004,"Hungarian_Datum_1972", 21,-56, 75.77, 15.31, -0.37, -0.2, -0.21, -1.01, 0}, { 0, 1005,"Cape_7_Parameter", 28,-134.73,-110.92, -292.66, 0, 0, 0, 1, 0}, { 6203, 1006,"AGD84_7_Param_Aust", 2, -117.763,-51.51, 139.061, -0.292, -0.443, -0.277, -0.191, 0}, { 0, 1007,"AGD66_7_Param_ACT", 2, -129.193,-41.212, 130.73, -0.246, -0.374, -0.329, -2.955, 0}, { 0, 1008,"AGD66_7_Param_TAS", 2, -120.271,-64.543, 161.632, -0.2175, 0.0672, 0.1291, 2.4985, 0}, { 0, 1009,"AGD66_7_Param_VIC_NSW", 2, -119.353,-48.301, 139.484, -0.415, -0.26, -0.437, -0.613, 0}, { 6272, 1010,"NZGD_7_Param_49", 4, 59.47, -5.04, 187.44, -0.47, 0.1, -1.024, -4.5993, 0}, { 0, 1011,"Rikets_Tri_7_Param_1990", 10,419.3836, 99.3335, 591.3451, -0.850389, -1.817277, 7.862238, -0.99496, 0}, { 0, 1012,"Russia_PZ90", 52, -1.08,-0.27,-0.9,0, 0, -0.16,-0.12, 0}, { 0, 1013,"Russia_SK42", 52, 23.92,-141.27,-80.9, 0, -0.35,-0.82, -0.12, 0}, { 0, 1014,"Russia_SK95", 52, 24.82,-131.21,-82.66,0,0,-0.16,-0.12, 0}, { 6301, 1015,"Tokyo", 10, -146.414, 507.337, 680.507,0,0,0,0,0}, { 6123, 1016,"Kartastokoordinaattijarjestelma_1966", 4, -96.062, -82.428, -121.754, -4.801, -0.345, 1.376, 1.496, 0}, { 6610, 1017,"Xian 1980", 53, 24, -123, -94, -0.02, -0.25, 0.13, 1.1, 0}, { 0, 1018,"Lithuanian Pulkovo 1942", 4, -40.59527, -18.54979, -69.33956, -2.508, -1.8319, 2.6114, -4.2991, 0}, { 6313, 1019,"Belgian 1972 7 Parameter", 4, -99.059, 53.322, -112.486, -0.419, 0.83, -1.885, 0.999999, 0}, { 6818, 1020,"S-JTSK with Ferro prime meridian", 10, 589, 76, 480, 0, 0, 0, 0, -17.666666666667}, { 1031, 1021,"Serbia datum MGI 1901", 10, 574.027, 170.175, 401.545, 4.88786, -0.66524, -13.24673, 6.88933, 0}, { 0, 1022,"North Sahara 7-parameter", 6, -38.7086, -128.8054, 118.8837, 0.83822, 7.38459, -1.57989, 3.9904, 0}, { 0, 1023,"Hungarian Projection System (EOV) - updated", 21, 52.684, -71.194, -13.975, 0.312, 0.1063, 0.3729, 1.0191, 0 }, { 1052, 1024,"S-JTSK (Krovak) Coordinate system - updated", 10, 570.6934, 85.6936, 462.8393, -4.99825, -1.58663, -5.26114, 3.5430155, 0 }, { 0, 1025,"JTSK03 (Slovak Republic)", 10, 485.014055, 169.473618, 483.842943, -7.78625453, -4.39770887, -4.10248899, 0, 0 }, { 1168, 1028,"Geocentric Datum of Australia 2020", 0,-0.06155, 0.01087, 0.04019, 0.0394924, 0.0327221, 0.0328979, 0.009994,0 }, { 0, 9999,"Bosnia-Herzegovina", 10, 472.8677, 187.8769, 544.7084, -5.76198422, -5.3222842, 12.80666941, 1.54517287, 0 }, { 6181, 9999,"Luxembourg 1930 / Gauss", 4, -192.986, 13.673, -39.309, 0.4099, 2.9332, -2.6881, 0.43, 0 }, { 1168, 9999,"Geocentric Datum of Australia 2020", 0,-0.06155, 0.01087, 0.04019, 0.0394924, 0.0327221, 0.0328979, 0.009994,0 }, { -1, -1, nullptr, 0, 0, 0, 0, 0, 0, 0, 0, 0} }; /* -------------------------------------------------------------------- */ /* This table was hand entered from Appendix I of the mapinfo 6 */ /* manuals. */ /* -------------------------------------------------------------------- */ const MapInfoSpheroidInfo asSpheroidInfoList[] = { { 9,"Airy 1930", 6377563.396, 299.3249646}, {13,"Airy 1930 (modified for Ireland 1965", 6377340.189, 299.3249646}, {51,"ATS77 (Average Terrestrial System 1977)", 6378135, 298.257}, { 2,"Australian", 6378160.0, 298.25}, {10,"Bessel 1841", 6377397.155, 299.1528128}, {35,"Bessel 1841 (modified for NGO 1948)", 6377492.0176, 299.15281}, {14,"Bessel 1841 (modified for Schwarzeck)", 6377483.865, 299.1528128}, {36,"Clarke 1858", 6378293.639, 294.26068}, { 7,"Clarke 1866", 6378206.4, 294.9786982}, { 8,"Clarke 1866 (modified for Michigan)", 6378450.047484481,294.9786982}, { 6,"Clarke 1880", 6378249.145, 293.465}, {15,"Clarke 1880 (modified for Arc 1950)", 6378249.145326, 293.4663076}, {30,"Clarke 1880 (modified for IGN)", 6378249.2, 293.4660213}, {37,"Clarke 1880 (modified for Jamaica)", 6378249.136, 293.46631}, {16,"Clarke 1880 (modified for Merchich)", 6378249.2, 293.46598}, {38,"Clarke 1880 (modified for Palestine)", 6378300.79, 293.46623}, {39,"Everest (Brunei and East Malaysia)", 6377298.556, 300.8017}, {11,"Everest (India 1830)", 6377276.345, 300.8017}, {40,"Everest (India 1956)", 6377301.243, 300.80174}, {50,"Everest (Pakistan)", 6377309.613, 300.8017}, {17,"Everest (W. Malaysia and Singapore 1948)", 6377304.063, 300.8017}, {48,"Everest (West Malaysia 1969)", 6377304.063, 300.8017}, {18,"Fischer 1960", 6378166.0, 298.3}, {19,"Fischer 1960 (modified for South Asia)", 6378155.0, 298.3}, {20,"Fischer 1968", 6378150.0, 298.3}, {21,"GRS 67", 6378160.0, 298.247167427}, { 0,"GRS 80", 6378137.0, 298.257222101}, { 5,"Hayford", 6378388.0, 297.0}, {22,"Helmert 1906", 6378200.0, 298.3}, {23,"Hough", 6378270.0, 297.0}, {31,"IAG 75", 6378140.0, 298.257222}, {41,"Indonesian", 6378160.0, 298.247}, { 4,"International 1924", 6378388.0, 297.0}, {49,"Irish (WOFO)", 6377542.178, 299.325}, { 3,"Krassovsky", 6378245.0, 298.3}, {32,"MERIT 83", 6378137.0, 298.257}, {33,"New International 1967", 6378157.5, 298.25}, {42,"NWL 9D", 6378145.0, 298.25}, {43,"NWL 10D", 6378135.0, 298.26}, {44,"OSU86F", 6378136.2, 298.25722}, {45,"OSU91A", 6378136.3, 298.25722}, {46,"Plessis 1817", 6376523.0, 308.64}, {52,"PZ90", 6378136.0, 298.257839303}, {24,"South American", 6378160.0, 298.25}, {12,"Sphere", 6370997.0, 0.0}, {47,"Struve 1860", 6378297.0, 294.73}, {34,"Walbeck", 6376896.0, 302.78}, {25,"War Office", 6378300.583, 296.0}, {26,"WGS 60", 6378165.0, 298.3}, {27,"WGS 66", 6378145.0, 298.25}, { 1,"WGS 72", 6378135.0, 298.26}, {28,"WGS 84", 6378137.0, 298.257223563}, {29,"WGS 84 (MAPINFO Datum 0)", 6378137.01, 298.257223563}, {54,"WGS 84 (MAPINFO Datum 157)", 6378137.01, 298.257223563}, {-1,nullptr, 0.0, 0.0} }; /* For LCC, standard parallel 1 and 2 can be switched indifferently */ /* So the MapInfo order and the EPSG order are not generally identical */ /* which may cause recognition problems when reading in MapInfo */ /* This table contains the parameters in the order expected by MapInfo */ typedef struct { int nEPSGCode; int bReverseStdP; int nMapInfoDatumID; double dfCenterLong; double dfCenterLat; double dfStdP1; double dfStdP2; } MapInfoLCCSRS; static const MapInfoLCCSRS asMapInfoLCCSRSList[] = { {2154,1,33,3,46.5,44,49}, {2154,1,33,3,46.5,44,49.00000000001}, {2154,1,33,3,46.5,44,49.00000000002}, {2225,1,74,-122,39.3333333333,40,41.6666666667}, {2226,1,74,-122,37.6666666667,38.3333333333,39.8333333333}, {2227,1,74,-120.5,36.5,37.0666666667,38.4333333333}, {2228,1,74,-119,35.3333333333,36,37.25}, {2229,1,74,-118,33.5,34.0333333333,35.4666666667}, {2230,1,74,-116.25,32.1666666667,32.7833333333,33.8833333333}, {2231,1,74,-105.5,39.3333333333,39.7166666667,40.7833333333}, {2232,1,74,-105.5,37.8333333333,38.45,39.75}, {2233,1,74,-105.5,36.6666666667,37.2333333333,38.4333333333}, {2234,1,74,-72.75,40.8333333333,41.2,41.8666666667}, {2238,1,74,-84.5,29,29.5833333333,30.75}, {2246,0,74,-84.25,37.5,37.9666666667,38.9666666667}, {2247,1,74,-85.75,36.3333333333,36.7333333333,37.9333333333}, {2248,1,74,-77,37.6666666667,38.3,39.45}, {2249,1,74,-71.5,41,41.7166666667,42.6833333333}, {2250,1,74,-70.5,41,41.2833333333,41.4833333333}, {2251,1,74,-87,44.7833333333,45.4833333333,47.0833333333}, {2252,1,74,-84.3666666667,43.3166666667,44.1833333333,45.7}, {2253,1,74,-84.3666666667,41.5,42.1,43.6666666667}, {2256,1,74,-109.5,44.25,45,49}, {2263,1,74,-74,40.1666666667,40.6666666667,41.0333333333}, {2264,1,74,-79,33.75,34.3333333333,36.1666666667}, {2265,1,74,-100.5,47,47.4333333333,48.7333333333}, {2266,1,74,-100.5,45.6666666667,46.1833333333,47.4833333333}, {2267,1,74,-98,35,35.5666666667,36.7666666667}, {2268,1,74,-98,33.3333333333,33.9333333333,35.2333333333}, {2269,1,74,-120.5,43.6666666667,44.3333333333,46}, {2270,1,74,-120.5,41.6666666667,42.3333333333,44}, {2271,1,74,-77.75,40.1666666667,40.8833333333,41.95}, {2272,1,74,-77.75,39.3333333333,39.9333333333,40.9666666667}, {2273,1,74,-81,31.8333333333,32.5,34.8333333333}, {2274,1,74,-86,34.3333333333,35.25,36.4166666667}, {2275,1,74,-101.5,34,34.65,36.1833333333}, {2276,1,74,-98.5,31.6666666667,32.1333333333,33.9666666667}, {2277,1,74,-100.3333333333,29.6666666667,30.1166666667,31.8833333333}, {2278,1,74,-99,27.8333333333,28.3833333333,30.2833333333}, {2279,1,74,-98.5,25.6666666667,26.1666666667,27.8333333333}, {2280,1,74,-111.5,40.3333333333,40.7166666667,41.7833333333}, {2281,1,74,-111.5,38.3333333333,39.0166666667,40.65}, {2282,1,74,-111.5,36.6666666667,37.2166666667,38.35}, {2283,1,74,-78.5,37.6666666667,38.0333333333,39.2}, {2284,1,74,-78.5,36.3333333333,36.7666666667,37.9666666667}, {2285,1,74,-120.8333333333,47,47.5,48.7333333333}, {2286,1,74,-120.5,45.3333333333,45.8333333333,47.3333333333}, {2287,1,74,-90,45.1666666667,45.5666666667,46.7666666667}, {2288,1,74,-90,43.8333333333,44.25,45.5}, {2289,1,74,-90,42,42.7333333333,44.0666666667}, {26740,1,63,-176,51,51.8333333333,53.8333333333}, {26741,1,62,-122,39.3333333333,40,41.6666666667}, {26742,1,62,-122,37.6666666667,38.3333333333,39.8333333333}, {26743,1,62,-120.5,36.5,37.0666666667,38.4333333333}, {26744,1,62,-119,35.3333333333,36,37.25}, {26745,1,62,-118,33.5,34.0333333333,35.4666666667}, {26746,1,62,-116.25,32.1666666667,32.7833333333,33.8833333333}, {26747,1,62,-118.3333333333,34.1333333333,33.8666666667,34.4166666667}, {26751,1,62,-92,34.3333333333,34.9333333333,36.2333333333}, {26752,1,62,-92,32.6666666667,33.3,34.7666666667}, {26753,0,62,-105.5,39.3333333333,39.7166666667,40.7833333333}, {26754,1,62,-105.5,37.8333333333,38.45,39.75}, {26755,1,62,-105.5,36.6666666667,37.2333333333,38.4333333333}, {26756,1,62,-72.75,40.8333333333,41.2,41.8666666667}, {26760,1,62,-84.5,29,29.5833333333,30.75}, {26775,1,62,-93.5,41.5,42.0666666667,43.2666666667}, {26776,1,62,-93.5,40,40.6166666667,41.7833333333}, {26777,1,62,-98,38.3333333333,38.7166666667,39.7833333333}, {26778,0,62,-98.5,36.6666666667,38.5666666667,37.2666666667}, {26779,0,62,-84.25,37.5,37.9666666667,38.9666666667}, {26780,0,62,-85.75,36.3333333333,36.7333333333,37.9333333333}, {26781,0,62,-92.5,30.6666666667,31.1666666667,32.6666666667}, {26785,0,62,-77,37.8333333333,38.3,39.45}, {26786,0,62,-71.5,41,41.7166666667,42.6833333333}, {26788,0,73,-87,44.7833333333,45.4833333333,47.0833333333}, {26789,0,73,-84.3333333333,43.3166666667,44.1833333333,45.7}, {26790,0,73,-84.3333333333,41.5,42.1,43.6666666667}, {26791,0,62,-93.1,46.5,47.0333333333,48.6333333333}, {26792,0,62,-94.25,45,45.6166666667,47.05}, {26793,0,62,-94,43,43.7833333333,45.2166666667}, {26940,1,74,-176,51,51.8333333333,53.8333333333}, {26941,1,74,-122,39.3333333333,40,41.6666666667}, {26942,1,74,-122,37.6666666667,38.3333333333,39.8333333333}, {26943,1,74,-120.5,36.5,37.0666666667,38.4333333333}, {26944,1,74,-119,35.3333333333,36,37.25}, {26945,1,74,-118,33.5,34.0333333333,35.4666666667}, {26946,1,74,-116.25,32.1666666667,32.7833333333,33.8833333333}, {26951,1,74,-92,34.3333333333,34.9333333333,36.2333333333}, {26952,1,74,-92,32.6666666667,33.3,34.7666666667}, {26953,1,74,-105.5,39.3333333333,39.7166666667,40.7833333333}, {26954,1,74,-105.5,37.8333333333,38.45,39.75}, {26955,1,74,-105.5,36.6666666667,37.2333333333,38.4333333333}, {26956,1,74,-72.75,40.8333333333,41.2,41.8666666667}, {26960,1,74,-84.5,29,29.5833333333,30.75}, {26975,1,74,-93.5,41.5,42.0666666667,43.2666666667}, {26976,1,74,-93.5,40,40.6166666667,41.7833333333}, {26977,1,74,-98,38.3333333333,38.7166666667,39.7833333333}, {26978,0,74,-98.5,36.6666666667,38.5666666667,37.2666666667}, {26980,1,74,-85.75,36.3333333333,36.7333333333,37.9333333333}, {26981,1,74,-92.5,30.5,31.1666666667,32.6666666667}, {26982,1,74,-91.3333333333,28.5,29.3,30.7}, {26985,1,74,-77,37.6666666667,38.3,39.45}, {26986,1,74,-71.5,41,41.7166666667,42.6833333333}, {26987,1,74,-70.5,41,41.2833333333,41.4833333333}, {26988,1,74,-87,44.7833333333,45.4833333333,47.0833333333}, {26989,1,74,-84.3666666667,43.3166666667,44.1833333333,45.7}, {26990,1,74,-84.3666666667,41.5,42.1,43.6666666667}, {26991,1,74,-93.1,46.5,47.0333333333,48.6333333333}, {26992,1,74,-94.25,45,45.6166666667,47.05}, {26993,1,74,-94,43,43.7833333333,45.2166666667}, {3111,0,116,145,-37,-36,-38}, {31370,1,1019,4.3674866667,90,49.8333339000,51.1666672333}, {32001,1,62,-109.5,47,47.85,48.7166666667}, {32002,1,62,-109.5,45.8333333333,46.45,47.8833333333}, {32003,1,62,-109.5,44,44.8666666667,46.4}, {32005,0,62,-100,41.3333333333,41.85,42.8166666667}, {32006,0,62,-99.5,39.6666666667,40.2833333333,41.7166666667}, {32018,1,62,-74,40.5,40.6666666667,41.0333333333}, {32019,0,62,-79,33.75,34.3333333333,36.1666666667}, {32020,0,62,-100.5,47,47.4333333333,48.7333333333}, {32021,0,62,-100.5,45.6666666667,46.1833333333,47.4833333333}, {32022,0,62,-82.5,39.6666666667,40.4333333333,41.7}, {32023,0,62,-82.5,38,38.7333333333,40.0333333333}, {32024,0,62,-98,35,35.5666666667,36.7666666667}, {32025,0,62,-98,33.3333333333,33.9333333333,35.2333333333}, {32026,0,62,-120.5,43.6666666667,44.3333333333,46}, {32027,0,62,-120.5,41.6666666667,42.3333333333,44}, {32028,0,62,-77.75,40.1666666667,40.8833333333,41.95}, {32031,0,62,-81,33,33.7666666667,34.9666666667}, {32033,0,62,-81,31.8333333333,32.3333333333,33.6666666667}, {32034,0,62,-100,43.8333333333,44.4166666667,45.6833333333}, {32035,0,62,-100.3333333333,42.3333333333,42.8333333333,44.4}, {32036,0,62,-86,34.6666666667,35.25,36.4166666667}, {32037,0,62,-101.5,34,34.65,36.1833333333}, {32038,0,62,-97.5,31.6666666667,32.1333333333,33.9666666667}, {32039,0,62,-100.3333333333,29.6666666667,30.1166666667,31.8833333333}, {32040,0,62,-99,27.8333333333,28.3833333333,30.2833333333}, {32041,0,62,-98.5,25.6666666667,26.1666666667,27.8333333333}, {32042,0,62,-111.5,40.3333333333,40.7166666667,41.7833333333}, {32043,0,62,-111.5,38.3333333333,39.0166666667,40.65}, {32044,0,62,-111.5,36.6666666667,37.2166666667,38.35}, {32046,0,62,-78.5,37.6666666667,38.0333333333,39.2}, {32047,0,62,-78.5,36.3333333333,36.7666666667,37.9666666667}, {32048,0,62,-120.8333333333,47,47.5,48.7333333333}, {32049,0,62,-120.5,45.3333333333,45.8333333333,47.3333333333}, {32050,0,62,-79.5,38.5,39,40.25}, {32051,0,62,-81,37,37.4833333333,38.8833333333}, {32052,0,62,-90,45.1666666667,45.5666666667,46.7666666667}, {32053,0,62,-90,43.8333333333,44.25,45.5}, {32054,0,62,-90,42,42.7333333333,44.0666666667}, {32059,0,62,-66.4333333333,18.4333333333,18.0333333333,18.4333333333}, {32060,0,62,-66.4333333333,18.4333333333,18.0333333333,18.4333333333}, {32100,1,74,-109.5,44.25,45,49}, {32104,1,74,-100,39.8333333333,40,43}, {32118,1,74,-74,40.1666666667,40.6666666667,41.0333333333}, {32119,1,74,-79,33.75,34.3333333333,36.1666666667}, {32120,1,74,-100.5,47,47.4333333333,48.7333333333}, {32121,1,74,-100.5,45.6666666667,46.1833333333,47.4833333333}, {32122,1,74,-82.5,39.6666666667,40.4333333333,41.7}, {32123,1,74,-82.5,38,38.7333333333,40.0333333333}, {32124,1,74,-98,35,35.5666666667,36.7666666667}, {32125,1,74,-98,33.3333333333,33.9333333333,35.2333333333}, {32126,1,74,-120.5,43.6666666667,44.3333333333,46}, {32127,1,74,-120.5,41.6666666667,42.3333333333,44}, {32128,1,74,-77.75,40.1666666667,40.8833333333,41.95}, {32129,1,74,-77.75,39.3333333333,39.9333333333,40.9666666667}, {32133,1,74,-81,31.8333333333,32.5,34.8333333333}, {32134,1,74,-100,43.8333333333,44.4166666667,45.6833333333}, {32135,1,74,-100.3333333333,42.3333333333,42.8333333333,44.4}, {32136,1,74,-86,34.3333333333,35.25,36.4166666667}, {32137,1,74,-101.5,34,34.65,36.1833333333}, {32138,1,74,-98.5,31.6666666667,32.1333333333,33.9666666667}, {32139,1,74,-100.3333333333,29.6666666667,30.1166666667,31.8833333333}, {32140,1,74,-99,27.8333333333,28.3833333333,30.2833333333}, {32141,1,74,-98.5,25.6666666667,26.1666666667,27.8333333333}, {32142,1,74,-111.5,40.3333333333,40.7166666667,41.7833333333}, {32143,1,74,-111.5,38.3333333333,39.0166666667,40.65}, {32144,1,74,-111.5,36.6666666667,37.2166666667,38.35}, {32146,1,74,-78.5,37.6666666667,38.0333333333,39.2}, {32147,1,74,-78.5,36.3333333333,36.7666666667,37.9666666667}, {32148,1,74,-120.8333333333,47,47.5,48.7333333333}, {32149,1,74,-120.5,45.3333333333,45.8333333333,47.3333333333}, {32150,1,74,-79.5,38.5,39,40.25}, {32151,1,74,-81,37,37.4833333333,38.8833333333}, {32152,1,74,-90,45.1666666667,45.5666666667,46.7666666667}, {32153,1,74,-90,43.8333333333,44.25,45.5}, {32154,1,74,-90,42,42.7333333333,44.0666666667}, {32161,1,74,-66.4333333333,17.8333333333,18.0333333333,18.4333333333}, {3300,1,115,24,57.51755394,58,59.33333333}, {3301,1,115,24,57.51755393056,58,59.33333333}, {3797,0,66,-70,44,50,46}, {3798,0,74,-70,44,50,46}, {3799,0,74,-70,44,50,46}, {3942,0,33,3,42,41.25,42.75}, {3943,0,33,3,43,42.25,43.75}, {3944,0,33,3,44,43.25,44.75}, {3945,0,33,3,45,44.25,45.75}, {3946,0,33,3,46,45.25,46.75}, {3947,0,33,3,47,46.25,47.75}, {3948,0,33,3,48,47.25,48.75}, {3949,0,33,3,49,48.25,49.75}, {3950,0,33,3,50,49.25,50.75}, {42101,0,104,-95,0,49,77}, {42103,0,104,-100,0,33,45}, {42304,0,74,-95,49,49,77}, {0,0,0,110,10,25,40}, {0,0,0,132.5,-10,-21.5,-33.5}, {0,0,0,25,35,40,65}, {0,0,0,47.5,25,15,35}, {0,0,0,95,40,20,60}, {0,0,1002,0,42.165,41.5603877778,42.76766333}, {0,0,1002,0,42.165,41.5603877778,42.767663333}, {0,0,1002,0,42.165,41.560387778,42.76766333}, {0,0,1002,0,42.165,41.560387778,42.767663333}, {0,0,1002,0,42.165,41.56038778,42.76766333}, {0,0,1002,0,42.165,41.560387840948,42.76766346965}, {0,0,1002,0,44.1,43.199291275544,44.996093814511}, {0,0,1002,0,44.1,43.1992913889,44.99609389}, {0,0,1002,0,44.1,43.199291389,44.99609389}, {0,0,1002,0,44.1,43.19929139,44.99609389}, {0,0,1002,0,46.8,45.8989188889,47.69601444}, {0,0,1002,0,46.8,45.898918889,47.69601444}, {0,0,1002,0,46.8,45.89891889,47.69601444}, {0,0,1002,0,46.8,45.898918964419,47.696014502038}, {0,0,1002,0,49.5,48.5985227778,50.39591167}, {0,0,1002,0,49.5,48.598522778,50.39591167}, {0,0,1002,0,49.5,48.59852278,50.39591167}, {0,0,1002,0,49.5,48.598522847174,50.395911631678}, {0,0,1005,23,-23,-18,-32}, {0,0,1022,2.7,36,37.575,34.425}, {0,0,104,13.33333333,47.5,46,49}, {0,0,104,13.33333333,48,46,49}, {0,0,104,-19,65,64.25,65.75}, {0,0,104,36.0,25.0,37.5,40.5}, {0,0,104,36,25,37.5,40.5}, {0,0,104,70,-50,-68.5,-74.5}, {0,0,110,4.367975,90,49.8333333333,51.1666666667}, {0,0,115,10,52,35,45}, {0,0,116,135,-24,-18,-36}, {0,0,116,135,-32,-28,-36}, {0,0,12,135,-24,-18,-36}, {0,0,12,145,-37,-36,-38}, {0,0,13,135,-24,-18,-36}, {0,0,19,23,-23,-18,-32}, {0,0,28,17,29.77930555,42,56}, {0,0,28,19,29.77930555,42,56}, {0,0,28,36.0,25.0,37.5,40.5}, {0,0,33,13.5,0,52.6666666667,55.3333333333}, {0,0,33,15,0,56.5,60.5}, {0,0,33,15,0,58,66}, {0,0,33,15,0,63.5,67.5}, {0,0,33,15.5,0,56.6666666667,59.3333333333}, {0,0,33,15.5,0,60.6666666667,63.3333333333}, {0,0,33,16.5,0,60.6666666667,63.3333333333}, {0,0,33,18.5,0,64.6666666667,67.3333333333}, {0,0,33,19,0,64.6666666667,67.3333333333}, {0,0,55,-5.4,22.5,20.9075742561,24.0921050540}, {0,0,55,-5.4,26.1,24.5075340813,27.6921073632}, {0,0,55,-5.4,29.7,28.1063294800,31.2932791054}, {0,0,55,-5.4,33.3,31.72786641202,34.8717272112}, {0,0,62,-70.5,41,41.2833333333,41.4833333333}, {0,0,62,-77.75,39.3333333333,39.9333333333,40.9666666667}, {0,0,62,-91.3333333333,25.6666666667,26.1666666667,27.8333333333}, {0,0,62,-91.3333333333,28.6666666667,29.3,30.67}, {0,0,62,-96,23,20,60}, {0,0,62,-96,23,33,45}, {0,0,62,-96,39,33,45}, {0,0,66,-68.5,44,46,60}, {0,0,74,-100.3333333333,42.3333333333,42.8333333333,44.4}, {0,0,74,-100,39.8333333333,40,43}, {0,0,74,-100,43.8333333333,44.4166666667,45.6833333333}, {0,0,74,-109.5,44.25,45,49}, {0,0,74,-111.5,36.6666666667,37.2166666667,38.35}, {0,0,74,-111.5,38.3333333333,39.0166666667,40.65}, {0,0,74,-111.5,40.3333333333,40.7166666667,41.7833333333}, {0,0,74,-120.5,41.6666666667,42.3333333333,44}, {0,0,74,-120.5,43.6666666667,44.3333333333,46}, {0,0,74,-176,51,51.8333333333,53.8333333333}, {0,0,74,-66.4333333333,17.8333333333,18.0333333333,18.4333333333}, {0,0,74,-68.5,44,46,60}, {0,0,74,-79.5,38.5,39,40.25}, {0,0,74,-81,31.8333333333,32.5,34.8333333333}, {0,0,74,-81,37,37.4833333333,38.8833333333}, {0,0,74,-82.5,38,38.7333333333,40.0333333333}, {0,0,74,-82.5,39.6666666667,40.4333333333,41.7}, {0,0,74,-84.25,37.5,37.9666666667,38.9666666667}, {0,0,74,-84.3666666667,41.5,42.1,43.6666666667}, {0,0,74,-84.3666666667,43.3166666667,44.1833333333,45.7}, {0,0,74,-87,44.7833333333,45.4833333333,47.0833333333}, {0,0,74,-91.3333333333,25.5,26.1666666667,27.8333333333}, {0,0,74,-91.3333333333,28.5,29.3,30.7}, {0,0,74,-92,32.6666666667,33.3,34.7666666667}, {0,0,74,-92,34.3333333333,34.9333333333,36.2333333333}, {0,0,74,-92.5,30.5,31.1666666667,32.6666666667}, {0,0,74,-93.1,46.5,47.0333333333,48.6333333333}, {0,0,74,-93.5,40,40.6166666667,41.7833333333}, {0,0,74,-93.5,41.5,42.0666666667,43.2666666667}, {0,0,74,-94.25,45,45.6166666667,47.05}, {0,0,74,-94,43,43.7833333333,45.2166666667}, {0,0,74,-98,38.3333333333,38.7166666667,39.7833333333}, {0,0,74,-98.5,36.6666666667,38.5666666667,37.2666666667}, }; /********************************************************************** * TABFile::GetSpatialRef() * * Returns a reference to an OGRSpatialReference for this dataset. * If the projection parameters have not been parsed yet, then we will * parse them before returning. * * The returned object is owned and maintained by this TABFile and * should not be modified or freed by the caller. * * Returns NULL if the SpatialRef cannot be accessed. **********************************************************************/ OGRSpatialReference *TABFile::GetSpatialRef() { if (m_poMAPFile == nullptr ) { CPLError(CE_Failure, CPLE_AssertionFailed, "GetSpatialRef() failed: file has not been opened yet."); return nullptr; } if( GetGeomType() == wkbNone ) return nullptr; /*----------------------------------------------------------------- * If projection params have already been processed, just use them. *----------------------------------------------------------------*/ if (m_poSpatialRef != nullptr) return m_poSpatialRef; /*----------------------------------------------------------------- * Fetch the parameters from the header. *----------------------------------------------------------------*/ TABProjInfo sTABProj; TABMAPHeaderBlock *poHeader = nullptr; if ((poHeader = m_poMAPFile->GetHeaderBlock()) == nullptr || poHeader->GetProjInfo( &sTABProj ) != 0) { CPLError(CE_Failure, CPLE_FileIO, "GetSpatialRef() failed reading projection parameters."); return nullptr; } m_poSpatialRef = GetSpatialRefFromTABProj(sTABProj); return m_poSpatialRef; } /********************************************************************** * TABFile::GetSpatialRefFromTABProj() **********************************************************************/ static bool TAB_EQUAL( double a, double b ) { // TODO(schwehr): Use std::abs. return (a < b ? (b - a) : (a - b)) < 1.0e-10; } OGRSpatialReference* TABFile::GetSpatialRefFromTABProj(const TABProjInfo& sTABProj) { /*----------------------------------------------------------------- * Get the units name, and translation factor. *----------------------------------------------------------------*/ const char *pszUnitsName = nullptr; const char *pszUnitsConv = nullptr; /* double dfConv = 1.0; */ switch( sTABProj.nUnitsId ) { case 0: pszUnitsName = "Mile"; pszUnitsConv = "1609.344"; break; case 1: pszUnitsName = "Kilometer"; pszUnitsConv = "1000.0"; break; case 2: pszUnitsName = "IINCH"; pszUnitsConv = "0.0254"; break; case 3: pszUnitsName = SRS_UL_FOOT; pszUnitsConv = SRS_UL_FOOT_CONV; break; case 4: pszUnitsName = "IYARD"; pszUnitsConv = "0.9144"; break; case 5: pszUnitsName = "Millimeter"; pszUnitsConv = "0.001"; break; case 6: pszUnitsName = "Centimeter"; pszUnitsConv = "0.01"; break; case 7: pszUnitsName = SRS_UL_METER; pszUnitsConv = "1.0"; break; case 8: pszUnitsName = SRS_UL_US_FOOT; pszUnitsConv = SRS_UL_US_FOOT_CONV; break; case 9: pszUnitsName = SRS_UL_NAUTICAL_MILE; pszUnitsConv = SRS_UL_NAUTICAL_MILE_CONV; break; case 30: pszUnitsName = SRS_UL_LINK; pszUnitsConv = SRS_UL_LINK_CONV; break; case 31: pszUnitsName = SRS_UL_CHAIN; pszUnitsConv = SRS_UL_CHAIN_CONV; break; case 32: pszUnitsName = SRS_UL_ROD; pszUnitsConv = SRS_UL_ROD_CONV; break; default: pszUnitsName = SRS_UL_METER; pszUnitsConv = "1.0"; break; } /* dfConv = CPLAtof(pszUnitsConv); */ /*----------------------------------------------------------------- * Transform them into an OGRSpatialReference. *----------------------------------------------------------------*/ OGRSpatialReference* poSpatialRef = new OGRSpatialReference; poSpatialRef->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER); /*----------------------------------------------------------------- * Handle the PROJCS style projections, but add the datum later. *----------------------------------------------------------------*/ switch( sTABProj.nProjId ) { case 0: poSpatialRef->SetLocalCS( "Nonearth" ); poSpatialRef->SetLinearUnits(pszUnitsName, CPLAtof(pszUnitsConv)); break; /*-------------------------------------------------------------- * lat/long .. just add the GEOGCS later. *-------------------------------------------------------------*/ case 1: break; /*-------------------------------------------------------------- * Cylindrical Equal Area *-------------------------------------------------------------*/ case 2: poSpatialRef->SetCEA( sTABProj.adProjParams[1], sTABProj.adProjParams[0], sTABProj.adProjParams[2], sTABProj.adProjParams[3] ); break; /*-------------------------------------------------------------- * Lambert Conic Conformal *-------------------------------------------------------------*/ case 3: poSpatialRef->SetLCC( sTABProj.adProjParams[2], sTABProj.adProjParams[3], sTABProj.adProjParams[1], sTABProj.adProjParams[0], sTABProj.adProjParams[4], sTABProj.adProjParams[5] ); break; /*-------------------------------------------------------------- * Lambert Azimuthal Equal Area *-------------------------------------------------------------*/ case 4: case 29: poSpatialRef->SetLAEA( sTABProj.adProjParams[1], sTABProj.adProjParams[0], 0.0, 0.0 ); break; /*-------------------------------------------------------------- * Azimuthal Equidistant (Polar aspect only) *-------------------------------------------------------------*/ case 5: case 28: poSpatialRef->SetAE( sTABProj.adProjParams[1], sTABProj.adProjParams[0], 0.0, 0.0 ); break; /*-------------------------------------------------------------- * Equidistant Conic *-------------------------------------------------------------*/ case 6: poSpatialRef->SetEC( sTABProj.adProjParams[2], sTABProj.adProjParams[3], sTABProj.adProjParams[1], sTABProj.adProjParams[0], sTABProj.adProjParams[4], sTABProj.adProjParams[5] ); break; /*-------------------------------------------------------------- * Hotine Oblique Mercator *-------------------------------------------------------------*/ case 7: poSpatialRef->SetHOM( sTABProj.adProjParams[1], sTABProj.adProjParams[0], sTABProj.adProjParams[2], 90.0, sTABProj.adProjParams[3], sTABProj.adProjParams[4], sTABProj.adProjParams[5] ); break; /*-------------------------------------------------------------- * Transverse Mercator *-------------------------------------------------------------*/ case 8: poSpatialRef->SetTM( sTABProj.adProjParams[1], sTABProj.adProjParams[0], sTABProj.adProjParams[2], sTABProj.adProjParams[3], sTABProj.adProjParams[4] ); break; /*---------------------------------------------------------------- * Transverse Mercator,(modified for Danish System 34 Jylland-Fyn) *---------------------------------------------------------------*/ case 21: //poSpatialRef->SetTMVariant( SRS_PT_TRANSVERSE_MERCATOR_MI_21, poSpatialRef->SetTM( sTABProj.adProjParams[1], sTABProj.adProjParams[0], sTABProj.adProjParams[2], sTABProj.adProjParams[3], sTABProj.adProjParams[4] ); break; /*-------------------------------------------------------------- * Transverse Mercator,(modified for Danish System 34 Sjaelland) *-------------------------------------------------------------*/ case 22: //poSpatialRef->SetTMVariant( SRS_PT_TRANSVERSE_MERCATOR_MI_22, poSpatialRef->SetTM( sTABProj.adProjParams[1], sTABProj.adProjParams[0], sTABProj.adProjParams[2], sTABProj.adProjParams[3], sTABProj.adProjParams[4] ); break; /*---------------------------------------------------------------- * Transverse Mercator,(modified for Danish System 34/45 Bornholm) *---------------------------------------------------------------*/ case 23: //poSpatialRef->SetTMVariant( SRS_PT_TRANSVERSE_MERCATOR_MI_23, poSpatialRef->SetTM( sTABProj.adProjParams[1], sTABProj.adProjParams[0], sTABProj.adProjParams[2], sTABProj.adProjParams[3], sTABProj.adProjParams[4] ); break; /*-------------------------------------------------------------- * Transverse Mercator,(modified for Finnish KKJ) *-------------------------------------------------------------*/ case 24: //poSpatialRef->SetTMVariant( SRS_PT_TRANSVERSE_MERCATOR_MI_24, poSpatialRef->SetTM( sTABProj.adProjParams[1], sTABProj.adProjParams[0], sTABProj.adProjParams[2], sTABProj.adProjParams[3], sTABProj.adProjParams[4] ); break; /*-------------------------------------------------------------- * Albers Conic Equal Area *-------------------------------------------------------------*/ case 9: poSpatialRef->SetACEA( sTABProj.adProjParams[2], sTABProj.adProjParams[3], sTABProj.adProjParams[1], sTABProj.adProjParams[0], sTABProj.adProjParams[4], sTABProj.adProjParams[5] ); break; /*-------------------------------------------------------------- * Mercator *-------------------------------------------------------------*/ case 10: poSpatialRef->SetMercator( 0.0, sTABProj.adProjParams[0], 1.0, 0.0, 0.0 ); break; /*-------------------------------------------------------------- * Miller Cylindrical *-------------------------------------------------------------*/ case 11: poSpatialRef->SetMC( 0.0, sTABProj.adProjParams[0], 0.0, 0.0 ); break; /*-------------------------------------------------------------- * Robinson *-------------------------------------------------------------*/ case 12: poSpatialRef->SetRobinson( sTABProj.adProjParams[0], 0.0, 0.0 ); break; /*-------------------------------------------------------------- * Mollweide *-------------------------------------------------------------*/ case 13: poSpatialRef->SetMollweide( sTABProj.adProjParams[0], 0.0, 0.0 ); break; /*-------------------------------------------------------------- * Eckert IV *-------------------------------------------------------------*/ case 14: poSpatialRef->SetEckertIV( sTABProj.adProjParams[0], 0.0, 0.0 ); break; /*-------------------------------------------------------------- * Eckert VI *-------------------------------------------------------------*/ case 15: poSpatialRef->SetEckertVI( sTABProj.adProjParams[0], 0.0, 0.0 ); break; /*-------------------------------------------------------------- * Sinusoidal *-------------------------------------------------------------*/ case 16: poSpatialRef->SetSinusoidal( sTABProj.adProjParams[0], 0.0, 0.0 ); break; /*-------------------------------------------------------------- * Gall Stereographic *-------------------------------------------------------------*/ case 17: poSpatialRef->SetGS( sTABProj.adProjParams[0], 0.0, 0.0 ); break; /*-------------------------------------------------------------- * New Zealand Map Grid *-------------------------------------------------------------*/ case 18: poSpatialRef->SetNZMG( sTABProj.adProjParams[1], sTABProj.adProjParams[0], sTABProj.adProjParams[2], sTABProj.adProjParams[3] ); break; /*-------------------------------------------------------------- * Lambert Conic Conformal (Belgium) *-------------------------------------------------------------*/ case 19: poSpatialRef->SetLCCB( sTABProj.adProjParams[2], sTABProj.adProjParams[3], sTABProj.adProjParams[1], sTABProj.adProjParams[0], sTABProj.adProjParams[4], sTABProj.adProjParams[5] ); break; /*-------------------------------------------------------------- * Stereographic *-------------------------------------------------------------*/ case 20: poSpatialRef->SetStereographic( sTABProj.adProjParams[1], sTABProj.adProjParams[0], sTABProj.adProjParams[2], sTABProj.adProjParams[3], sTABProj.adProjParams[4] ); break; /*-------------------------------------------------------------- * Swiss Oblique Mercator / Cylindrical *-------------------------------------------------------------*/ case 25: poSpatialRef->SetSOC( sTABProj.adProjParams[1], sTABProj.adProjParams[0], sTABProj.adProjParams[2], sTABProj.adProjParams[3] ); break; /*-------------------------------------------------------------- * Regional Mercator (regular mercator with a latitude). *-------------------------------------------------------------*/ case 26: poSpatialRef->SetMercator2SP( sTABProj.adProjParams[1], 0.0, sTABProj.adProjParams[0], 0.0, 0.0 ); break; /*-------------------------------------------------------------- * Polyconic *-------------------------------------------------------------*/ case 27: poSpatialRef->SetPolyconic( sTABProj.adProjParams[1], sTABProj.adProjParams[0], sTABProj.adProjParams[2], sTABProj.adProjParams[3] ); break; /*-------------------------------------------------------------- * Cassini/Soldner *-------------------------------------------------------------*/ case 30: poSpatialRef->SetCS( sTABProj.adProjParams[1], sTABProj.adProjParams[0], sTABProj.adProjParams[2], sTABProj.adProjParams[3] ); break; /*-------------------------------------------------------------- * Oblique Stereographic *-------------------------------------------------------------*/ case 31: poSpatialRef->SetOS( sTABProj.adProjParams[1], sTABProj.adProjParams[0], sTABProj.adProjParams[2], sTABProj.adProjParams[3], sTABProj.adProjParams[4] ); break; /*-------------------------------------------------------------- * Krovak *-------------------------------------------------------------*/ case 32: poSpatialRef->SetKrovak( sTABProj.adProjParams[1], // dfCenterLat sTABProj.adProjParams[0], // dfCenterLong sTABProj.adProjParams[3], // dfAzimuth sTABProj.adProjParams[2], // dfPseudoStdParallelLat 1.0, // dfScale sTABProj.adProjParams[4], // dfFalseEasting sTABProj.adProjParams[5] ); // dfFalseNorthing break; /*-------------------------------------------------------------- * Equidistant Cylindrical / Equirectangular *-------------------------------------------------------------*/ case 33: poSpatialRef->SetEquirectangular( sTABProj.adProjParams[1], sTABProj.adProjParams[0], sTABProj.adProjParams[2], sTABProj.adProjParams[3] ); break; default: break; } /*----------------------------------------------------------------- * Collect units definition. *----------------------------------------------------------------*/ if( sTABProj.nProjId != 0 && sTABProj.nProjId != 1 && CPLAtof( pszUnitsConv ) != 1 ) { poSpatialRef->SetTargetLinearUnits(nullptr, pszUnitsName, CPLAtof( pszUnitsConv )); } /*----------------------------------------------------------------- * Local (nonearth) coordinate systems have no Geographic relationship * so we just return from here. *----------------------------------------------------------------*/ if( sTABProj.nProjId == 0 ) return poSpatialRef; /*----------------------------------------------------------------- * Set the datum. We are only given the X, Y and Z shift for * the datum, so for now we just synthesize a name from this. * It would be better if we could lookup a name based on the shift. * * Since we have already encountered files in which adDatumParams[] values * were in the order of 1e-150 when they should have actually been zeros, * we will use an epsilon in our scan instead of looking for equality. *----------------------------------------------------------------*/ const MapInfoDatumInfo *psDatumInfo = nullptr; for( int iDatumInfo = 0; asDatumInfoList[iDatumInfo].nMapInfoDatumID != -1; iDatumInfo++ ) { psDatumInfo = asDatumInfoList + iDatumInfo; if( TAB_EQUAL(psDatumInfo->nEllipsoid, sTABProj.nEllipsoidId) && ((sTABProj.nDatumId > 0 && sTABProj.nDatumId == psDatumInfo->nMapInfoDatumID) || (sTABProj.nDatumId <= 0 && TAB_EQUAL(psDatumInfo->dfShiftX, sTABProj.dDatumShiftX) && TAB_EQUAL(psDatumInfo->dfShiftY, sTABProj.dDatumShiftY) && TAB_EQUAL(psDatumInfo->dfShiftZ, sTABProj.dDatumShiftZ) && TAB_EQUAL(psDatumInfo->dfDatumParm0,sTABProj.adDatumParams[0]) && TAB_EQUAL(psDatumInfo->dfDatumParm1,sTABProj.adDatumParams[1]) && TAB_EQUAL(psDatumInfo->dfDatumParm2,sTABProj.adDatumParams[2]) && TAB_EQUAL(psDatumInfo->dfDatumParm3,sTABProj.adDatumParams[3]) && TAB_EQUAL(psDatumInfo->dfDatumParm4,sTABProj.adDatumParams[4])))) break; psDatumInfo = nullptr; } char szDatumName[200] = {}; if( psDatumInfo == nullptr ) { if( sTABProj.adDatumParams[0] == 0.0 && sTABProj.adDatumParams[1] == 0.0 && sTABProj.adDatumParams[2] == 0.0 && sTABProj.adDatumParams[3] == 0.0 && sTABProj.adDatumParams[4] == 0.0 ) { snprintf( szDatumName, sizeof(szDatumName), "MIF 999,%u,%.15g,%.15g,%.15g", sTABProj.nEllipsoidId, sTABProj.dDatumShiftX, sTABProj.dDatumShiftY, sTABProj.dDatumShiftZ ); } else { snprintf( szDatumName, sizeof(szDatumName), "MIF 9999,%u,%.15g,%.15g,%.15g,%.15g,%.15g,%.15g,%.15g,%.15g", sTABProj.nEllipsoidId, sTABProj.dDatumShiftX, sTABProj.dDatumShiftY, sTABProj.dDatumShiftZ, sTABProj.adDatumParams[0], sTABProj.adDatumParams[1], sTABProj.adDatumParams[2], sTABProj.adDatumParams[3], sTABProj.adDatumParams[4] ); } } else if( strlen(psDatumInfo->pszOGCDatumName) > 0 ) { CPLStrlcpy( szDatumName, psDatumInfo->pszOGCDatumName, sizeof(szDatumName) ); } else { snprintf( szDatumName, sizeof(szDatumName), "MIF %d", psDatumInfo->nMapInfoDatumID ); } /*----------------------------------------------------------------- * Set the spheroid. *----------------------------------------------------------------*/ double dfSemiMajor = 0.0; double dfInvFlattening = 0.0; const char *pszSpheroidName = nullptr; for( int i = 0; asSpheroidInfoList[i].nMapInfoId != -1; i++ ) { if( asSpheroidInfoList[i].nMapInfoId == sTABProj.nEllipsoidId ) { dfSemiMajor = asSpheroidInfoList[i].dfA; dfInvFlattening = asSpheroidInfoList[i].dfInvFlattening; pszSpheroidName = asSpheroidInfoList[i].pszMapinfoName; break; } } // use WGS 84 if nothing is known. if( pszSpheroidName == nullptr ) { pszSpheroidName = "unknown"; dfSemiMajor = 6378137.0; dfInvFlattening = 298.257223563; } /*----------------------------------------------------------------- * Set the prime meridian. *----------------------------------------------------------------*/ double dfPMOffset = 0.0; const char *pszPMName = "Greenwich"; if( /*sTABProj.nDatumId == 9999 ||*/ sTABProj.adDatumParams[4] != 0.0 ) { dfPMOffset = sTABProj.adDatumParams[4]; if( fabs(dfPMOffset - 2.337229166667) < 1e-10) pszPMName = "Paris"; else pszPMName = "non-Greenwich"; } /*----------------------------------------------------------------- * Create a GEOGCS definition. *----------------------------------------------------------------*/ poSpatialRef->SetGeogCS( "unnamed", szDatumName, pszSpheroidName, dfSemiMajor, dfInvFlattening, pszPMName, dfPMOffset, SRS_UA_DEGREE, CPLAtof(SRS_UA_DEGREE_CONV)); if( psDatumInfo != nullptr ) { if( CPLTestBool(CPLGetConfigOption("MITAB_SET_TOWGS84_ON_KNOWN_DATUM", "NO")) ) { poSpatialRef->SetTOWGS84( psDatumInfo->dfShiftX, psDatumInfo->dfShiftY, psDatumInfo->dfShiftZ, psDatumInfo->dfDatumParm0 == 0 ? 0 : -psDatumInfo->dfDatumParm0, /* avoids 0 to be transformed into -0 */ psDatumInfo->dfDatumParm1 == 0 ? 0 : -psDatumInfo->dfDatumParm1, psDatumInfo->dfDatumParm2 == 0 ? 0 : -psDatumInfo->dfDatumParm2, psDatumInfo->dfDatumParm3 ); } } else { poSpatialRef->SetTOWGS84( sTABProj.dDatumShiftX, sTABProj.dDatumShiftY, sTABProj.dDatumShiftZ, sTABProj.adDatumParams[0] == 0 ? 0 : -sTABProj.adDatumParams[0], sTABProj.adDatumParams[1] == 0 ? 0 : -sTABProj.adDatumParams[1], sTABProj.adDatumParams[2] == 0 ? 0 : -sTABProj.adDatumParams[2], sTABProj.adDatumParams[3] ); } /*----------------------------------------------------------------- * Special case for Google Mercator (datum=157, ellipse=54, gdal #4115) *----------------------------------------------------------------*/ if( sTABProj.nProjId == 10 && sTABProj.nDatumId == 157 && sTABProj.nEllipsoidId == 54 ) { poSpatialRef->SetNode( "PROJCS", "WGS 84 / Pseudo-Mercator" ); poSpatialRef->SetExtension( "PROJCS", "PROJ4", "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs" ); } /*----------------------------------------------------------------- * Special case for France Lambert-93 *----------------------------------------------------------------*/ if( sTABProj.nProjId == 3 && sTABProj.nDatumId == 33 && sTABProj.nEllipsoidId == 0 && TAB_EQUAL(poSpatialRef->GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0), 3.0) && TAB_EQUAL(poSpatialRef->GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0), 46.5) ) { poSpatialRef->SetNode( "PROJCS", "RGF93 / Lambert-93" ); poSpatialRef->SetNode( "PROJCS|GEOGCS", "RGF93"); poSpatialRef->SetNode( "PROJCS|GEOGCS|DATUM", "Reseau_Geodesique_Francais_1993"); } if( sTABProj.nProjId == 3 ) { // If the LCC_2SP can be turned into a LCC_1SP that has the same // latitude of origin, then it is a better candidate OGRSpatialReference* poLCC1SP = poSpatialRef->convertToOtherProjection(SRS_PT_LAMBERT_CONFORMAL_CONIC_1SP); if( poLCC1SP ) { if( TAB_EQUAL(poSpatialRef->GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0), poLCC1SP->GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0)) ) { delete poSpatialRef; poSpatialRef = poLCC1SP; } else { delete poLCC1SP; } } } /* For LCC, standard parallel 1 and 2 can be switched indifferently */ /* So the MapInfo order and the EPSG order are not generally identical */ /* which may cause recognition problems when reading in MapInfo */ if( sTABProj.nProjId == 3 ) { double dfCenterLong = sTABProj.adProjParams[0]; double dfCenterLat = sTABProj.adProjParams[1]; double dfStdP1 = sTABProj.adProjParams[2]; double dfStdP2 = sTABProj.adProjParams[3]; for(size_t i=0;iSetLCC( sTABProj.adProjParams[3], sTABProj.adProjParams[2], sTABProj.adProjParams[1], sTABProj.adProjParams[0], sTABProj.adProjParams[4], sTABProj.adProjParams[5] ); } if( asMapInfoLCCSRSList[i].nEPSGCode > 0 ) poSpatialRef->SetAuthority( "PROJCS", "EPSG", asMapInfoLCCSRSList[i].nEPSGCode ); break; } } } } return poSpatialRef; } /********************************************************************** * TABFile::SetSpatialRef() * * Set the OGRSpatialReference for this dataset. * A reference to the OGRSpatialReference will be kept, and it will also * be converted into a TABProjInfo to be stored in the .MAP header. * * Returns 0 on success, and -1 on error. **********************************************************************/ int TABFile::SetSpatialRef(OGRSpatialReference *poSpatialRef) { if (m_eAccessMode != TABWrite) { CPLError(CE_Failure, CPLE_NotSupported, "SetSpatialRef() can be used only with Write access."); return -1; } if (m_poMAPFile == nullptr ) { CPLError(CE_Failure, CPLE_AssertionFailed, "SetSpatialRef() failed: file has not been opened yet."); return -1; } if( poSpatialRef == nullptr ) { CPLError(CE_Failure, CPLE_AssertionFailed, "SetSpatialRef() failed: Called with NULL poSpatialRef."); return -1; } /*----------------------------------------------------------------- * Keep a copy of the OGRSpatialReference... * Note: we have to take the reference count into account... *----------------------------------------------------------------*/ if (m_poSpatialRef && m_poSpatialRef->Dereference() == 0) delete m_poSpatialRef; m_poSpatialRef = poSpatialRef->Clone(); TABProjInfo sTABProj; int nParamCount = 0; GetTABProjFromSpatialRef(poSpatialRef, sTABProj, nParamCount); /*----------------------------------------------------------------- * Set the new parameters in the .MAP header. * This will also trigger lookup of default bounds for the projection. *----------------------------------------------------------------*/ if ( SetProjInfo( &sTABProj ) != 0 ) { CPLError(CE_Failure, CPLE_FileIO, "SetSpatialRef() failed setting projection parameters."); return -1; } return 0; } static int MITABGetCustomDatum(const OGRSpatialReference* poSpatialRef, TABProjInfo& sTABProj) { double adfTOWGS[7] = {0}; if(OGRERR_NONE != poSpatialRef->GetTOWGS84(adfTOWGS, sizeof(adfTOWGS)/sizeof(adfTOWGS[0]))) { return FALSE; } sTABProj.nDatumId = 9999; sTABProj.dDatumShiftX = adfTOWGS[0]; sTABProj.dDatumShiftY = adfTOWGS[1]; sTABProj.dDatumShiftZ = adfTOWGS[2]; sTABProj.adDatumParams[0] = -adfTOWGS[3]; sTABProj.adDatumParams[1] = -adfTOWGS[4]; sTABProj.adDatumParams[2] = -adfTOWGS[5]; sTABProj.adDatumParams[3] = -adfTOWGS[6]; int nSpheroidId = -1; const char *pszWKTSpheroid = poSpatialRef->GetAttrValue("SPHEROID"); for( int i = 0; asSpheroidInfoList[i].nMapInfoId != -1; i++ ) { if(EQUAL(pszWKTSpheroid, asSpheroidInfoList[i].pszMapinfoName)) { nSpheroidId = asSpheroidInfoList[i].nMapInfoId; break; } } if(nSpheroidId == -1) { double adSemiMajor = poSpatialRef->GetSemiMajor(); double adInvFlattening = poSpatialRef->GetInvFlattening(); for( int i = 0; asSpheroidInfoList[i].nMapInfoId != -1; i++ ) { if(CPLIsEqual(adSemiMajor, asSpheroidInfoList[i].dfA) && CPLIsEqual(adInvFlattening, asSpheroidInfoList[i].dfInvFlattening)) { nSpheroidId = asSpheroidInfoList[i].nMapInfoId; break; } } } if(nSpheroidId == -1) { CPLDebug("MITAB", "Cannot find MapInfo spheroid matching %s. Defaulting to WGS 84", pszWKTSpheroid); nSpheroidId = 28; /* WGS 84 */ } sTABProj.nEllipsoidId = static_cast(nSpheroidId); return TRUE; } int TABFile::GetTABProjFromSpatialRef(const OGRSpatialReference* poSpatialRef, TABProjInfo& sTABProj, int& nParamCount) { /*----------------------------------------------------------------- * Initialize TABProjInfo *----------------------------------------------------------------*/ sTABProj.nProjId = 0; sTABProj.nEllipsoidId = 0; /* how will we set this? */ sTABProj.nUnitsId = 7; sTABProj.adProjParams[0] = sTABProj.adProjParams[1] = 0.0; sTABProj.adProjParams[2] = sTABProj.adProjParams[3] = 0.0; sTABProj.adProjParams[4] = sTABProj.adProjParams[5] = 0.0; sTABProj.nDatumId = 0; sTABProj.dDatumShiftX = 0.0; sTABProj.dDatumShiftY = 0.0; sTABProj.dDatumShiftZ = 0.0; sTABProj.adDatumParams[0] = 0.0; sTABProj.adDatumParams[1] = 0.0; sTABProj.adDatumParams[2] = 0.0; sTABProj.adDatumParams[3] = 0.0; sTABProj.adDatumParams[4] = 0.0; sTABProj.nAffineFlag = 0; sTABProj.nAffineUnits = 7; sTABProj.dAffineParamA = 0.0; sTABProj.dAffineParamB = 0.0; sTABProj.dAffineParamC = 0.0; sTABProj.dAffineParamD = 0.0; sTABProj.dAffineParamE = 0.0; sTABProj.dAffineParamF = 0.0; /*----------------------------------------------------------------- * Get the linear units and conversion. *----------------------------------------------------------------*/ const char *pszLinearUnits = nullptr; double dfLinearConv = poSpatialRef->GetLinearUnits( &pszLinearUnits ); if( dfLinearConv == 0.0 ) dfLinearConv = 1.0; // Get datum information const char *pszWKTDatum = poSpatialRef->GetAttrValue("DATUM"); int nDatumEPSGCode = -1; const char *pszDatumAuthority = poSpatialRef->GetAuthorityName("DATUM"); const char *pszDatumCode = poSpatialRef->GetAuthorityCode("DATUM"); if (pszDatumCode && pszDatumAuthority && EQUAL(pszDatumAuthority, "EPSG")) { nDatumEPSGCode = atoi(pszDatumCode); } /*----------------------------------------------------------------- * Transform the projection and projection parameters. *----------------------------------------------------------------*/ const char *pszProjection = poSpatialRef->GetAttrValue("PROJECTION"); double *params = sTABProj.adProjParams; nParamCount = 0; if( pszProjection == nullptr && poSpatialRef->GetAttrNode("GEOGCS") == nullptr) { /* nonearth */ sTABProj.nProjId = 0; } else if( pszProjection == nullptr ) { sTABProj.nProjId = 1; } else if( EQUAL(pszProjection,SRS_PT_ALBERS_CONIC_EQUAL_AREA) ) { sTABProj.nProjId = 9; params[0] = poSpatialRef->GetNormProjParm(SRS_PP_LONGITUDE_OF_CENTER,0.0); params[1] = poSpatialRef->GetNormProjParm(SRS_PP_LATITUDE_OF_CENTER,0.0); params[2] = poSpatialRef->GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1,0.0); params[3] = poSpatialRef->GetNormProjParm(SRS_PP_STANDARD_PARALLEL_2,0.0); params[4] = poSpatialRef->GetProjParm(SRS_PP_FALSE_EASTING,0.0); params[5] = poSpatialRef->GetProjParm(SRS_PP_FALSE_NORTHING,0.0); nParamCount = 6; } else if( EQUAL(pszProjection,SRS_PT_AZIMUTHAL_EQUIDISTANT) ) { sTABProj.nProjId = 5; params[0] = poSpatialRef->GetNormProjParm(SRS_PP_LONGITUDE_OF_CENTER,0.0); params[1] = poSpatialRef->GetNormProjParm(SRS_PP_LATITUDE_OF_CENTER,0.0); params[2] = 90.0; nParamCount = 3; if( std::abs((std::abs(params[1]) - 90)) > 0.001 ) sTABProj.nProjId = 28; } else if( EQUAL(pszProjection,SRS_PT_CYLINDRICAL_EQUAL_AREA) ) { sTABProj.nProjId = 2; params[0] = poSpatialRef->GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0); params[1] = poSpatialRef->GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1,0.0); nParamCount = 2; } else if( EQUAL(pszProjection,SRS_PT_ECKERT_IV) ) { sTABProj.nProjId = 14; params[0] = poSpatialRef->GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0); nParamCount = 1; } else if( EQUAL(pszProjection,SRS_PT_ECKERT_VI) ) { sTABProj.nProjId = 15; params[0] = poSpatialRef->GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0); nParamCount = 1; } else if( EQUAL(pszProjection,SRS_PT_EQUIDISTANT_CONIC) ) { sTABProj.nProjId = 6; params[0] = poSpatialRef->GetNormProjParm(SRS_PP_LONGITUDE_OF_CENTER,0.0); params[1] = poSpatialRef->GetNormProjParm(SRS_PP_LATITUDE_OF_CENTER,0.0); params[2] = poSpatialRef->GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1,0.0); params[3] = poSpatialRef->GetNormProjParm(SRS_PP_STANDARD_PARALLEL_2,0.0); params[4] = poSpatialRef->GetProjParm(SRS_PP_FALSE_EASTING,0.0); params[5] = poSpatialRef->GetProjParm(SRS_PP_FALSE_NORTHING,0.0); nParamCount = 6; } else if( EQUAL(pszProjection,SRS_PT_GALL_STEREOGRAPHIC) ) { sTABProj.nProjId = 17; params[0] = poSpatialRef->GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0); nParamCount = 1; } else if( EQUAL(pszProjection,SRS_PT_HOTINE_OBLIQUE_MERCATOR) ) { sTABProj.nProjId = 7; params[0] = poSpatialRef->GetNormProjParm(SRS_PP_LONGITUDE_OF_CENTER,0.0); params[1] = poSpatialRef->GetNormProjParm(SRS_PP_LATITUDE_OF_CENTER,0.0); params[2] = poSpatialRef->GetNormProjParm(SRS_PP_AZIMUTH,0.0); params[3] = poSpatialRef->GetProjParm(SRS_PP_SCALE_FACTOR,1.0); params[4] = poSpatialRef->GetProjParm(SRS_PP_FALSE_EASTING,0.0); params[5] = poSpatialRef->GetProjParm(SRS_PP_FALSE_NORTHING,0.0); nParamCount = 6; } else if( EQUAL(pszProjection,SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA) ) { sTABProj.nProjId = 4; params[0] = poSpatialRef->GetNormProjParm(SRS_PP_LONGITUDE_OF_CENTER,0.0); params[1] = poSpatialRef->GetNormProjParm(SRS_PP_LATITUDE_OF_CENTER,0.0); params[2] = 90.0; nParamCount = 3; if( std::abs((std::abs(params[1]) - 90)) > 0.001 ) sTABProj.nProjId = 29; } else if( EQUAL(pszProjection,SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP) ) { sTABProj.nProjId = 3; params[0] = poSpatialRef->GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0); params[1] = poSpatialRef->GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0); params[2] = poSpatialRef->GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1,0.0); params[3] = poSpatialRef->GetNormProjParm(SRS_PP_STANDARD_PARALLEL_2,0.0); params[4] = poSpatialRef->GetProjParm(SRS_PP_FALSE_EASTING,0.0); params[5] = poSpatialRef->GetProjParm(SRS_PP_FALSE_NORTHING,0.0); nParamCount = 6; } else if( EQUAL(pszProjection,SRS_PT_LAMBERT_CONFORMAL_CONIC_1SP) ) { OGRSpatialReference* poOtherSRS = poSpatialRef->convertToOtherProjection(SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP); if( poOtherSRS ) { sTABProj.nProjId = 3; params[0] = poOtherSRS->GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0); params[1] = poOtherSRS->GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0); params[2] = poOtherSRS->GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1,0.0); params[3] = poOtherSRS->GetNormProjParm(SRS_PP_STANDARD_PARALLEL_2,0.0); params[4] = poOtherSRS->GetProjParm(SRS_PP_FALSE_EASTING,0.0); params[5] = poOtherSRS->GetProjParm(SRS_PP_FALSE_NORTHING,0.0); nParamCount = 6; delete poOtherSRS; } } else if( EQUAL(pszProjection,SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP_BELGIUM) ) { sTABProj.nProjId = 19; params[0] = poSpatialRef->GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0); params[1] = poSpatialRef->GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0); params[2] = poSpatialRef->GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1,0.0); params[3] = poSpatialRef->GetNormProjParm(SRS_PP_STANDARD_PARALLEL_2,0.0); params[4] = poSpatialRef->GetProjParm(SRS_PP_FALSE_EASTING,0.0); params[5] = poSpatialRef->GetProjParm(SRS_PP_FALSE_NORTHING,0.0); nParamCount = 6; } else if( EQUAL(pszProjection,SRS_PT_MERCATOR_1SP) ) { sTABProj.nProjId = 10; params[0] = poSpatialRef->GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0); params[1] = poSpatialRef->GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0); params[2] = poSpatialRef->GetProjParm(SRS_PP_SCALE_FACTOR,1.0); nParamCount = 1; // FIXME for MIF export ? if( params[1] != 0.0 ) { sTABProj.nProjId = 26; nParamCount = 2; // FIXME for MIF export ? } } else if( EQUAL(pszProjection,SRS_PT_MERCATOR_2SP) ) { sTABProj.nProjId = 26; params[0] = poSpatialRef->GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0); params[1] = poSpatialRef->GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1,0.0); nParamCount = 2; // FIXME for MIF export ? } else if( EQUAL(pszProjection,SRS_PT_MILLER_CYLINDRICAL) ) { sTABProj.nProjId = 11; params[0] = poSpatialRef->GetNormProjParm(SRS_PP_LONGITUDE_OF_CENTER,0.0); nParamCount = 1; } else if( EQUAL(pszProjection,SRS_PT_MOLLWEIDE) ) { sTABProj.nProjId = 13; params[0] = poSpatialRef->GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0); nParamCount = 1; } else if( EQUAL(pszProjection,SRS_PT_NEW_ZEALAND_MAP_GRID) ) { sTABProj.nProjId = 18; params[0] = poSpatialRef->GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0); params[1] = poSpatialRef->GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0); params[2] = poSpatialRef->GetProjParm(SRS_PP_FALSE_EASTING,0.0); params[3] = poSpatialRef->GetProjParm(SRS_PP_FALSE_NORTHING,0.0); nParamCount = 4; } else if( EQUAL(pszProjection,SRS_PT_SWISS_OBLIQUE_CYLINDRICAL) ) { sTABProj.nProjId = 25; params[0] = poSpatialRef->GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0); params[1] = poSpatialRef->GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0); params[2] = poSpatialRef->GetProjParm(SRS_PP_FALSE_EASTING,0.0); params[3] = poSpatialRef->GetProjParm(SRS_PP_FALSE_NORTHING,0.0); nParamCount = 4; } // Swiss Oblique expressed as Hotine Oblique Mercator Azimuth Center else if( EQUAL(pszProjection,SRS_PT_HOTINE_OBLIQUE_MERCATOR_AZIMUTH_CENTER) && std::abs( poSpatialRef->GetNormProjParm(SRS_PP_AZIMUTH, 90.0) - 90.0 ) < 1e-8 && std::abs( poSpatialRef->GetNormProjParm(SRS_PP_RECTIFIED_GRID_ANGLE, 90.0) - 90.0 ) < 1e-8 && std::abs( poSpatialRef->GetProjParm(SRS_PP_SCALE_FACTOR,1.0) - 1.0 ) < 1e-8 ) { sTABProj.nProjId = 25; params[0] = poSpatialRef->GetNormProjParm(SRS_PP_LONGITUDE_OF_CENTER,0.0); params[1] = poSpatialRef->GetNormProjParm(SRS_PP_LATITUDE_OF_CENTER,0.0); params[2] = poSpatialRef->GetProjParm(SRS_PP_FALSE_EASTING,0.0); params[3] = poSpatialRef->GetProjParm(SRS_PP_FALSE_NORTHING,0.0); nParamCount = 4; } else if( EQUAL(pszProjection,SRS_PT_ROBINSON) ) { sTABProj.nProjId = 12; params[0] = poSpatialRef->GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0); nParamCount = 1; } else if( EQUAL(pszProjection,SRS_PT_SINUSOIDAL) ) { sTABProj.nProjId = 16; params[0] = poSpatialRef->GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0); nParamCount = 1; } else if( EQUAL(pszProjection,SRS_PT_STEREOGRAPHIC) ) { sTABProj.nProjId = 20; params[0] = poSpatialRef->GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0); params[1] = poSpatialRef->GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0); params[2] = poSpatialRef->GetProjParm(SRS_PP_SCALE_FACTOR,1.0); params[3] = poSpatialRef->GetProjParm(SRS_PP_FALSE_EASTING,0.0); params[4] = poSpatialRef->GetProjParm(SRS_PP_FALSE_NORTHING,0.0); nParamCount = 5; } else if (EQUAL(pszProjection,SRS_PT_OBLIQUE_STEREOGRAPHIC)) { sTABProj.nProjId = 31; params[0] = poSpatialRef->GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0); params[1] = poSpatialRef->GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0); params[2] = poSpatialRef->GetProjParm(SRS_PP_SCALE_FACTOR, 1.0); params[3] = poSpatialRef->GetProjParm(SRS_PP_FALSE_EASTING, 0.0); params[4] = poSpatialRef->GetProjParm(SRS_PP_FALSE_NORTHING, 0.0); nParamCount = 5; } else if( EQUAL(pszProjection,SRS_PT_TRANSVERSE_MERCATOR) ) { sTABProj.nProjId = 8; if( (pszWKTDatum && EQUAL(pszWKTDatum, "Kartastokoordinaattijarjestelma_1966")) || nDatumEPSGCode == 6123 ) { // Special case for Finnish KKJ sTABProj.nProjId = 24; } params[0] = poSpatialRef->GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0); params[1] = poSpatialRef->GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0); params[2] = poSpatialRef->GetProjParm(SRS_PP_SCALE_FACTOR,1.0); params[3] = poSpatialRef->GetProjParm(SRS_PP_FALSE_EASTING,0.0); params[4] = poSpatialRef->GetProjParm(SRS_PP_FALSE_NORTHING,0.0); nParamCount = 5; } else if( EQUAL(pszProjection,SRS_PT_TRANSVERSE_MERCATOR_MI_21) ) // Encom 2003 { sTABProj.nProjId = 21; params[0] = poSpatialRef->GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0); params[1] = poSpatialRef->GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0); params[2] = poSpatialRef->GetProjParm(SRS_PP_SCALE_FACTOR,1.0); params[3] = poSpatialRef->GetProjParm(SRS_PP_FALSE_EASTING,0.0); params[4] = poSpatialRef->GetProjParm(SRS_PP_FALSE_NORTHING,0.0); nParamCount = 5; } else if( EQUAL(pszProjection,SRS_PT_TRANSVERSE_MERCATOR_MI_22) ) // Encom 2003 { sTABProj.nProjId = 22; params[0] = poSpatialRef->GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0); params[1] = poSpatialRef->GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0); params[2] = poSpatialRef->GetProjParm(SRS_PP_SCALE_FACTOR,1.0); params[3] = poSpatialRef->GetProjParm(SRS_PP_FALSE_EASTING,0.0); params[4] = poSpatialRef->GetProjParm(SRS_PP_FALSE_NORTHING,0.0); nParamCount = 5; } else if( EQUAL(pszProjection,SRS_PT_TRANSVERSE_MERCATOR_MI_23) ) // Encom 2003 { sTABProj.nProjId = 23; params[0] = poSpatialRef->GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0); params[1] = poSpatialRef->GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0); params[2] = poSpatialRef->GetProjParm(SRS_PP_SCALE_FACTOR,1.0); params[3] = poSpatialRef->GetProjParm(SRS_PP_FALSE_EASTING,0.0); params[4] = poSpatialRef->GetProjParm(SRS_PP_FALSE_NORTHING,0.0); nParamCount = 5; } else if( EQUAL(pszProjection,SRS_PT_TRANSVERSE_MERCATOR_MI_24) ) // Encom 2003 { sTABProj.nProjId = 24; params[0] = poSpatialRef->GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0); params[1] = poSpatialRef->GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0); params[2] = poSpatialRef->GetProjParm(SRS_PP_SCALE_FACTOR,1.0); params[3] = poSpatialRef->GetProjParm(SRS_PP_FALSE_EASTING,0.0); params[4] = poSpatialRef->GetProjParm(SRS_PP_FALSE_NORTHING,0.0); nParamCount = 5; } else if( EQUAL(pszProjection,SRS_PT_CASSINI_SOLDNER) ) { sTABProj.nProjId = 30; params[0] = poSpatialRef->GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0); params[1] = poSpatialRef->GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0); params[2] = poSpatialRef->GetProjParm(SRS_PP_FALSE_EASTING,0.0); params[3] = poSpatialRef->GetProjParm(SRS_PP_FALSE_NORTHING,0.0); nParamCount = 4; } else if( EQUAL(pszProjection,SRS_PT_POLYCONIC) ) { sTABProj.nProjId = 27; params[0] = poSpatialRef->GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0); params[1] = poSpatialRef->GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0); params[2] = poSpatialRef->GetProjParm(SRS_PP_FALSE_EASTING,0.0); params[3] = poSpatialRef->GetProjParm(SRS_PP_FALSE_NORTHING,0.0); nParamCount = 4; } else if( EQUAL(pszProjection,SRS_PT_KROVAK) ) { sTABProj.nProjId = 32; params[0] = poSpatialRef->GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0); params[1] = poSpatialRef->GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0); params[2] = poSpatialRef->GetNormProjParm(SRS_PP_PSEUDO_STD_PARALLEL_1,0.0); params[3] = poSpatialRef->GetNormProjParm(SRS_PP_AZIMUTH,0.0); params[4] = poSpatialRef->GetProjParm(SRS_PP_FALSE_EASTING,0.0); params[5] = poSpatialRef->GetProjParm(SRS_PP_FALSE_NORTHING,0.0); nParamCount = 6; } else if( EQUAL(pszProjection,SRS_PT_EQUIRECTANGULAR) ) { sTABProj.nProjId = 33; params[0] = poSpatialRef->GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0); params[1] = poSpatialRef->GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0); params[2] = poSpatialRef->GetProjParm(SRS_PP_FALSE_EASTING,0.0); params[3] = poSpatialRef->GetProjParm(SRS_PP_FALSE_NORTHING,0.0); nParamCount = 4; } else { CPLError(CE_Warning, CPLE_AppDefined, "No translation from %s to MapInfo known", pszProjection); } /* ============================================================== * Translate Datum and Ellipsoid * ============================================================== */ const MapInfoDatumInfo *psDatumInfo = nullptr; /*----------------------------------------------------------------- * Default to WGS84 if we have no datum at all. *----------------------------------------------------------------*/ if( pszWKTDatum == nullptr ) { CPLDebug("MITAB", "Cannot find MapInfo datum matching %d. Defaulting to WGS 84", nDatumEPSGCode); psDatumInfo = asDatumInfoList+0; /* WGS 84 */ // From MIF export code. FIXME? //if( nProjection == 1 ) // nProjection = 0; } /*----------------------------------------------------------------- * We know the MIF datum number, and need to look it up to * translate into datum parameters. *----------------------------------------------------------------*/ else if( STARTS_WITH_CI(pszWKTDatum, "MIF ") && atoi(pszWKTDatum+4) != 999 && atoi(pszWKTDatum+4) != 9999 ) { int nDatum = atoi(pszWKTDatum+4); for( int i = 0; asDatumInfoList[i].nMapInfoDatumID != -1; i++ ) { if( nDatum == asDatumInfoList[i].nMapInfoDatumID ) { psDatumInfo = asDatumInfoList + i; break; } } if( psDatumInfo == nullptr ) { CPLDebug("MITAB", "Cannot find MapInfo datum matching %s. Defaulting to WGS 84", pszWKTDatum); psDatumInfo = asDatumInfoList+0; /* WGS 84 */ } } /*----------------------------------------------------------------- * We have the MIF datum parameters, and apply those directly. *----------------------------------------------------------------*/ else if( STARTS_WITH_CI(pszWKTDatum, "MIF ") && (atoi(pszWKTDatum+4) == 999 || atoi(pszWKTDatum+4) == 9999) ) { sTABProj.nDatumId = static_cast(atoi(pszWKTDatum+4)); char **papszFields = CSLTokenizeStringComplex( pszWKTDatum+4, ",", FALSE, TRUE); if( CSLCount(papszFields) >= 5 ) { sTABProj.nEllipsoidId = static_cast(atoi(papszFields[1])); sTABProj.dDatumShiftX = CPLAtof(papszFields[2]); sTABProj.dDatumShiftY = CPLAtof(papszFields[3]); sTABProj.dDatumShiftZ = CPLAtof(papszFields[4]); } if( CSLCount(papszFields) >= 10 ) { sTABProj.adDatumParams[0] = CPLAtof(papszFields[5]); sTABProj.adDatumParams[1] = CPLAtof(papszFields[6]); sTABProj.adDatumParams[2] = CPLAtof(papszFields[7]); sTABProj.adDatumParams[3] = CPLAtof(papszFields[8]); sTABProj.adDatumParams[4] = CPLAtof(papszFields[9]); } if( CSLCount(papszFields) < 5 ) { CPLDebug("MITAB", "Cannot find MapInfo datum matching %s. Defaulting to WGS 84", pszWKTDatum); psDatumInfo = asDatumInfoList+0; /* WGS 84 */ } CSLDestroy( papszFields ); } /*----------------------------------------------------------------- * We have a "real" datum name, and possibly an EPSG code for the * datum. Try to look it up (using EPSG code first) and get the * parameters. If we don't find it with either just use WGS84. *----------------------------------------------------------------*/ else { for( int i = 0; asDatumInfoList[i].nMapInfoDatumID != -1; i++ ) { if ( (nDatumEPSGCode > 0 && asDatumInfoList[i].nDatumEPSGCode == nDatumEPSGCode) || EQUAL(pszWKTDatum,asDatumInfoList[i].pszOGCDatumName) ) { psDatumInfo = asDatumInfoList + i; break; } } if( psDatumInfo == nullptr && !MITABGetCustomDatum(poSpatialRef, sTABProj)) { CPLDebug("MITAB", "Cannot find MapInfo datum matching %s,%d. Defaulting to WGS 84", pszWKTDatum, nDatumEPSGCode); psDatumInfo = asDatumInfoList+0; /* WGS 84 */ } } if( psDatumInfo != nullptr ) { sTABProj.nEllipsoidId = static_cast(psDatumInfo->nEllipsoid); sTABProj.nDatumId = static_cast(psDatumInfo->nMapInfoDatumID); sTABProj.dDatumShiftX = psDatumInfo->dfShiftX; sTABProj.dDatumShiftY = psDatumInfo->dfShiftY; sTABProj.dDatumShiftZ = psDatumInfo->dfShiftZ; sTABProj.adDatumParams[0] = psDatumInfo->dfDatumParm0; sTABProj.adDatumParams[1] = psDatumInfo->dfDatumParm1; sTABProj.adDatumParams[2] = psDatumInfo->dfDatumParm2; sTABProj.adDatumParams[3] = psDatumInfo->dfDatumParm3; sTABProj.adDatumParams[4] = psDatumInfo->dfDatumParm4; /* For LCC, standard parallel 1 and 2 can be switched indifferently */ /* So the MapInfo order and the EPSG order are not generally identical */ /* which may cause recognition problems when reading in MapInfo */ if( sTABProj.nProjId == 3 ) { double dfCenterLong = params[0]; double dfCenterLat = params[1]; double dfStdP1 = params[2]; double dfStdP2 = params[3]; for(size_t i=0;iGetAuthorityName(nullptr)) != nullptr && EQUAL(pszAuthorityName, "EPSG") && (pszAuthorityCode = poSpatialRef->GetAuthorityCode(nullptr)) != nullptr && atoi(pszAuthorityCode) == 3857) || ((pszExtension = poSpatialRef->GetExtension(nullptr, "PROJ4")) != nullptr && (EQUAL(pszExtension, "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs") || EQUAL(pszExtension, "+proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defs"))) ) { sTABProj.nDatumId = 157; sTABProj.nEllipsoidId = 54; } /*----------------------------------------------------------------- * Translate the units *----------------------------------------------------------------*/ if( sTABProj.nProjId == 1 || pszLinearUnits == nullptr ) sTABProj.nUnitsId = 13; else if( dfLinearConv == 1000.0 ) sTABProj.nUnitsId = 1; else if( dfLinearConv == 0.0254 || EQUAL(pszLinearUnits,"Inch") || EQUAL(pszLinearUnits,"IINCH") ) sTABProj.nUnitsId = 2; else if( fabs(dfLinearConv - CPLAtof(SRS_UL_FOOT_CONV)) < 1e-15 * dfLinearConv || EQUAL(pszLinearUnits,SRS_UL_FOOT) ) sTABProj.nUnitsId = 3; else if( EQUAL(pszLinearUnits,"YARD") || EQUAL(pszLinearUnits,"IYARD") || dfLinearConv == 0.9144 ) sTABProj.nUnitsId = 4; else if( dfLinearConv == 0.001 ) sTABProj.nUnitsId = 5; else if( dfLinearConv == 0.01 ) sTABProj.nUnitsId = 6; else if( dfLinearConv == 1.0 ) sTABProj.nUnitsId = 7; else if( fabs(dfLinearConv - CPLAtof(SRS_UL_US_FOOT_CONV)) < 1e-15 * dfLinearConv || EQUAL(pszLinearUnits,SRS_UL_US_FOOT) ) sTABProj.nUnitsId = 8; else if( dfLinearConv == 1852.0 || EQUAL(pszLinearUnits,SRS_UL_NAUTICAL_MILE) ) sTABProj.nUnitsId = 9; else if( EQUAL(pszLinearUnits,SRS_UL_LINK) || EQUAL(pszLinearUnits,"GUNTERLINK") ) sTABProj.nUnitsId = 30; else if( EQUAL(pszLinearUnits,SRS_UL_CHAIN) || EQUAL(pszLinearUnits,"GUNTERCHAIN") ) sTABProj.nUnitsId = 31; else if( EQUAL(pszLinearUnits,SRS_UL_ROD) ) sTABProj.nUnitsId = 32; else if( EQUAL(pszLinearUnits,"Mile") || EQUAL(pszLinearUnits,"IMILE") ) sTABProj.nUnitsId = 0; else sTABProj.nUnitsId = 7; return 0; }