Coverage Report

Created: 2025-06-09 07:42

/src/gdal/frmts/ilwis/ilwiscoordinatesystem.cpp
Line
Count
Source (jump to first uncovered line)
1
/******************************************************************************
2
 *
3
 * Purpose: Translation from ILWIS coordinate system information.
4
 * Author:   Lichun Wang, lichun@itc.nl
5
 *
6
 ******************************************************************************
7
 * Copyright (c) 2004, ITC
8
 * Copyright (c) 2008-2012, Even Rouault <even dot rouault at spatialys.com>
9
 *
10
 * SPDX-License-Identifier: MIT
11
 ****************************************************************************/
12
#include "cpl_conv.h"
13
#include "ilwisdataset.h"
14
15
#include <string>
16
17
namespace GDAL
18
{
19
20
typedef struct
21
{
22
    const char *pszIlwisDatum;
23
    const char *pszWKTDatum;
24
    int nEPSGCode;
25
} IlwisDatums;
26
27
typedef struct
28
{
29
    const char *pszIlwisEllips;
30
    int nEPSGCode;
31
    double semiMajor;
32
    double invFlattening;
33
} IlwisEllips;
34
35
static const IlwisDatums iwDatums[] = {
36
    {"Adindan", "Adindan", 4201},
37
    {"Afgooye", "Afgooye", 4205},
38
    // AGREF --- skipped
39
    {"Ain el Abd 1970", "Ain_el_Abd_1970", 4204},
40
    {"American Samoa 1962", "American_Samoa_1962", 4169},
41
    // Anna 1 Astro 1965 --- skipped
42
    {"Antigua Island Astro 1943", "Antigua_1943", 4601},
43
    {"Arc 1950", "Arc_1950", 4209},  // Arc 1950
44
    {"Arc 1960", "Arc_1960", 4210},  // Arc 1960
45
    // Ascension Island 1958
46
    // Astro Beacon E 1945
47
    // Astro DOS 71/4
48
    // Astro Tern Island (FRIG) 1961
49
    // Astronomical Station 1952
50
    {"Australian Geodetic 1966", "Australian_Geodetic_Datum_1966", 4202},
51
    {"Australian Geodetic 1984", "Australian_Geodetic_Datum_1984", 4203},
52
    // Ayabelle Lighthouse
53
    // Bellevue (IGN)
54
    {"Bermuda 1957", "Bermuda_1957", 4216},
55
    {"Bissau", "Bissau", 4165},
56
    {"Bogota Observatory  (1975)", "Bogota", 4218},
57
    {"Bukit Rimpah", "Bukit_Rimpah", 4219},
58
    // Camp Area Astro
59
    {"Campo Inchauspe", "Campo_Inchauspe", 4221},
60
    // Canton Astro 1966
61
    {"Cape", "Cape", 4222},
62
    // Cape Canaveral
63
    {"Carthage", "Carthage", 4223},
64
    {"CH1903", "CH1903", 4149},
65
    // Chatham Island Astro 1971
66
    {"Chua Astro", "Chua", 4224},
67
    {"Corrego Alegre", "Corrego_Alegre", 4225},
68
    // Croatia
69
    // D-PAF (Orbits)
70
    {"Dabola", "Dabola_1981", 4155},
71
    // Deception Island
72
    // Djakarta (Batavia)
73
    // DOS 1968
74
    // Easter Island 1967
75
    // Estonia 1937
76
    {"European 1950 (ED 50)", "European_Datum_1950", 4154},
77
    // European 1979 (ED 79
78
    // Fort Thomas 1955
79
    {"Gan 1970", "Gandajika_1970", 4233},
80
    // Geodetic Datum 1949
81
    // Graciosa Base SW 1948
82
    // Guam 1963
83
    {"Gunung Segara", "Gunung_Segara", 4613},
84
    // GUX 1 Astro
85
    {"Herat North", "Herat_North", 4255},
86
    // Hermannskogel
87
    // Hjorsey 1955
88
    // Hong Kong 1963
89
    {"Hu-Tzu-Shan", "Hu_Tzu_Shan", 4236},
90
    // Indian (Bangladesh)
91
    // Indian (India, Nepal)
92
    // Indian (Pakistan)
93
    {"Indian 1954", "Indian_1954", 4239},
94
    {"Indian 1960", "Indian_1960", 4131},
95
    {"Indian 1975", "Indian_1975", 4240},
96
    {"Indonesian 1974", "Indonesian_Datum_1974", 4238},
97
    // Ireland 1965
98
    // ISTS 061 Astro 1968
99
    // ISTS 073 Astro 1969
100
    // Johnston Island 1961
101
    {"Kandawala", "Kandawala", 4244},
102
    // Kerguelen Island 1949
103
    {"Kertau 1948", "Kertau", 4245},
104
    // Kusaie Astro 1951
105
    // L. C. 5 Astro 1961
106
    {"Leigon", "Leigon", 4250},
107
    {"Liberia 1964", "Liberia_1964", 4251},
108
    {"Luzon", "Luzon_1911", 4253},
109
    // M'Poraloko
110
    {"Mahe 1971", "Mahe_1971", 4256},
111
    {"Massawa", "Massawa", 4262},
112
    {"Merchich", "Merchich", 4261},
113
    {"MGI (Hermannskogel)", "Militar_Geographische_Institute", 4312},
114
    // Midway Astro 1961
115
    {"Minna", "Minna", 4263},
116
    {"Montserrat Island Astro 1958", "Montserrat_1958", 4604},
117
    {"Nahrwan", "Nahrwan_1967", 4270},
118
    {"Naparima BWI", "Naparima_1955", 4158},
119
    {"North American 1927 (NAD 27)", "North_American_Datum_1927", 4267},
120
    {"North American 1983 (NAD 83)", "North_American_Datum_1983", 4269},
121
    // North Sahara 1959
122
    {"NTF (Nouvelle Triangulation de France)",
123
     "Nouvelle_Triangulation_Francaise", 4807},
124
    // Observatorio Meteorologico 1939
125
    // Old Egyptian 1907
126
    {"Old Hawaiian", "Old_Hawaiian", 4135},
127
    // Oman
128
    // Ordnance Survey Great Britain 1936
129
    // Pico de las Nieves
130
    // Pitcairn Astro 1967
131
    // Point 58
132
    {"Pointe Noire 1948", "Pointe_Noire", 4282},
133
    {"Porto Santo 1936", "Porto_Santo", 4615},
134
    // Potsdam (Rauenburg)
135
    {"Potsdam (Rauenburg)", "Deutsches_Hauptdreiecksnetz", 4314},
136
    {"Provisional South American 1956", "Provisional_South_American_Datum_1956",
137
     4248},
138
    // Provisional South Chilean 1963
139
    {"Puerto Rico", "Puerto_Rico", 4139},
140
    {"Pulkovo 1942", "Pulkovo_1942", 4178},
141
    //{ "Qatar National", "Qatar_National_Datum_1995", 4614 },
142
    {"Qornoq", "Qornoq", 4287},
143
    {"Puerto Rico", "Puerto_Rico", 4139},
144
    // Reunion
145
    {"Rome 1940", "Monte_Mario", 4806},
146
    {"RT90", "Rikets_koordinatsystem_1990", 4124},
147
    {"Rijks Driehoeksmeting", "Amersfoort", 4289},
148
    {"S-42 (Pulkovo 1942)", "Pulkovo_1942", 4178},
149
    //{ "S-JTSK", "Jednotne_Trigonometricke_Site_Katastralni", 4156 },
150
    // Santo (DOS) 1965
151
    // Sao Braz
152
    {"Sapper Hill 1943", "Sapper_Hill_1943", 4292},
153
    {"Schwarzeck", "Schwarzeck", 4293},
154
    {"Selvagem Grande 1938", "Selvagem_Grande", 4616},
155
    // vSGS 1985
156
    // Sierra Leone 1960
157
    {"South American 1969", "South_American_Datum_1969", 4291},
158
    // South Asia
159
    {"Tananarive Observatory 1925", "Tananarive_1925", 4297},
160
    {"Timbalai 1948", "Timbalai_1948", 4298},
161
    {"Tokyo", "Tokyo", 4301},
162
    // Tristan Astro 1968
163
    // Viti Levu 1916
164
    {"Voirol 1874", "Voirol_1875", 4304},
165
    // Voirol 1960
166
    // Wake Island Astro 1952
167
    // Wake-Eniwetok 1960
168
    {"WGS 1972", "WGS_1972", 4322},
169
    {"WGS 1984", "WGS_1984", 4326},
170
    {"Yacare", "Yacare", 4309},
171
    {"Zanderij", "Zanderij", 4311},
172
    {nullptr, nullptr, 0}};
173
174
static const IlwisEllips iwEllips[] = {
175
    {"Sphere", 7035, 6371007, 0.0},  // rad 6370997 m (normal sphere)
176
    {"Airy 1830", 7031, 6377563.396, 299.3249646},
177
    {"Modified Airy", 7002, 6377340.189, 299.3249646},
178
    {"ATS77", 7204, 6378135.0, 298.257000006},
179
    {"Australian National", 7003, 6378160, 298.249997276},
180
    {"Bessel 1841", 7042, 6377397.155, 299.1528128},
181
    {"Bessel 1841 (Japan By Law)", 7046, 6377397.155, 299.152815351},
182
    {"Bessel 1841 (Namibia)", 7006, 6377483.865, 299.1528128},
183
    {"Clarke 1866", 7008, 6378206.4, 294.9786982},
184
    {"Clarke 1880", 7034, 6378249.145, 293.465},
185
    {"Clarke 1880 (IGN)", 7011, 6378249.2, 293.466},
186
    // FIXME: D-PAF (Orbits) --- skipped
187
    // FIXME: Du Plessis Modified --- skipped
188
    // FIXME: Du Plessis Reconstituted --- skipped
189
    {"Everest (India 1830)", 7015, 6377276.345, 300.8017},
190
    // Everest (India 1956) --- skipped
191
    // Everest (Malaysia 1969) --- skipped
192
    {"Everest (E. Malaysia and Brunei)", 7016, 6377298.556, 300.8017},
193
    {"Everest (Malay. and Singapore 1948)", 7018, 6377304.063, 300.8017},
194
    {"Everest (Pakistan)", 7044, 6377309.613, 300.8017},
195
    // Everest (Sabah Sarawak) --- skipped
196
    // Fischer 1960 --- skipped
197
    // Fischer 1960 (Modified) --- skipped
198
    // Fischer 1968 --- skipped
199
    {"GRS 80", 7019, 6378137, 298.257222101},
200
    {"Helmert 1906", 7020, 6378200, 298.3},
201
    // Hough 1960 --- skipped
202
    {"Indonesian 1974", 7021, 6378160, 298.247},
203
    {"International 1924", 7022, 6378388, 297},
204
    {"Krassovsky 1940", 7024, 6378245, 298.3},
205
    // New_International 1967
206
    // SGS 85
207
    // South American 1969
208
    // WGS 60
209
    // WGS 66
210
    {"WGS 72", 7020, 6378135.0, 298.259998590},
211
    {"WGS 84", 7030, 6378137, 298.257223563},
212
    {nullptr, 0, 0.0, 0.0}};
213
214
#ifndef R2D
215
#define R2D (180 / M_PI)
216
#endif
217
#ifndef D2R
218
#define D2R (M_PI / 180)
219
#endif
220
221
/* ==================================================================== */
222
/*      Some "standard" std::strings.                                        */
223
/* ==================================================================== */
224
225
static const char ILW_False_Easting[] = "False Easting";
226
static const char ILW_False_Northing[] = "False Northing";
227
static const char ILW_Central_Meridian[] = "Central Meridian";
228
static const char ILW_Central_Parallel[] = "Central Parallel";
229
static const char ILW_Standard_Parallel_1[] = "Standard Parallel 1";
230
static const char ILW_Standard_Parallel_2[] = "Standard Parallel 2";
231
static const char ILW_Scale_Factor[] = "Scale Factor";
232
static const char ILW_Latitude_True_Scale[] = "Latitude of True Scale";
233
static const char ILW_Height_Persp_Center[] = "Height Persp. Center";
234
235
static double ReadPrjParams(const std::string &section,
236
                            const std::string &entry,
237
                            const std::string &filename)
238
0
{
239
0
    std::string str = ReadElement(section, entry, filename);
240
    // string str="";
241
0
    if (!str.empty())
242
0
        return CPLAtof(str.c_str());
243
244
0
    return 0.0;
245
0
}
246
247
static int fetchParams(const std::string &csyFileName, double *padfPrjParams)
248
0
{
249
    // Fill all projection parameters with zero
250
0
    for (int i = 0; i < 13; i++)
251
0
        padfPrjParams[i] = 0.0;
252
253
    // std::string pszProj = ReadElement("CoordSystem", "Projection",
254
    // csyFileName);
255
0
    std::string pszEllips =
256
0
        ReadElement("CoordSystem", "Ellipsoid", csyFileName);
257
258
    // fetch info about a custom ellipsoid
259
0
    if (STARTS_WITH_CI(pszEllips.c_str(), "User Defined"))
260
0
    {
261
0
        padfPrjParams[0] = ReadPrjParams("Ellipsoid", "a", csyFileName);
262
0
        padfPrjParams[2] = ReadPrjParams("Ellipsoid", "1/f", csyFileName);
263
0
    }
264
0
    else if (STARTS_WITH_CI(pszEllips.c_str(), "Sphere"))
265
0
    {
266
0
        padfPrjParams[0] =
267
0
            ReadPrjParams("CoordSystem", "Sphere Radius", csyFileName);
268
0
    }
269
270
0
    padfPrjParams[3] =
271
0
        ReadPrjParams("Projection", "False Easting", csyFileName);
272
0
    padfPrjParams[4] =
273
0
        ReadPrjParams("Projection", "False Northing", csyFileName);
274
275
0
    padfPrjParams[5] =
276
0
        ReadPrjParams("Projection", "Central Parallel", csyFileName);
277
0
    padfPrjParams[6] =
278
0
        ReadPrjParams("Projection", "Central Meridian", csyFileName);
279
280
0
    padfPrjParams[7] =
281
0
        ReadPrjParams("Projection", "Standard Parallel 1", csyFileName);
282
0
    padfPrjParams[8] =
283
0
        ReadPrjParams("Projection", "Standard Parallel 2", csyFileName);
284
285
0
    padfPrjParams[9] = ReadPrjParams("Projection", "Scale Factor", csyFileName);
286
0
    padfPrjParams[10] =
287
0
        ReadPrjParams("Projection", "Latitude of True Scale", csyFileName);
288
0
    padfPrjParams[11] = ReadPrjParams("Projection", "Zone", csyFileName);
289
0
    padfPrjParams[12] =
290
0
        ReadPrjParams("Projection", ILW_Height_Persp_Center, csyFileName);
291
292
0
    return true;
293
0
}
294
295
/************************************************************************/
296
/*                          mapTMParams                                  */
297
/************************************************************************/
298
/**
299
 * fetch the parameters from ILWIS projection definition for
300
 * --- Gauss-Krueger Germany.
301
 * --- Gauss Colombia
302
 * --- Gauss-Boaga Italy
303
 **/
304
static int mapTMParams(const std::string &sProj, double dfZone,
305
                       double &dfFalseEasting, double &dfCentralMeridian)
306
0
{
307
0
    if (STARTS_WITH_CI(sProj.c_str(), "Gauss-Krueger Germany"))
308
0
    {
309
        // Zone number must be in the range 1 to 3
310
0
        dfCentralMeridian = 6.0 + (dfZone - 1) * 3;
311
0
        dfFalseEasting = 2500000 + (dfZone - 1) * 1000000;
312
0
    }
313
0
    else if (STARTS_WITH_CI(sProj.c_str(), "Gauss-Boaga Italy"))
314
0
    {
315
0
        if (dfZone == 1)
316
0
        {
317
0
            dfCentralMeridian = 9;
318
0
            dfFalseEasting = 1500000;
319
0
        }
320
0
        else if (dfZone == 2)
321
0
        {
322
0
            dfCentralMeridian = 15;
323
0
            dfFalseEasting = 2520000;
324
0
        }
325
0
        else
326
0
            return false;
327
0
    }
328
0
    else if (STARTS_WITH_CI(sProj.c_str(), "Gauss Colombia"))
329
0
    {
330
        // Zone number must be in the range 1 to 4
331
0
        dfCentralMeridian = -77.08097220 + (dfZone - 1) * 3;
332
0
    }
333
0
    return true;
334
0
}
335
336
/************************************************************************/
337
/*                          scaleFromLATTS()                             */
338
/************************************************************************/
339
/**
340
 * Compute the scale factor from Latitude_Of_True_Scale parameter.
341
 *
342
 **/
343
static void scaleFromLATTS(const std::string &sEllips, double phits,
344
                           double &scale)
345
0
{
346
0
    if (STARTS_WITH_CI(sEllips.c_str(), "Sphere"))
347
0
    {
348
0
        scale = cos(phits);
349
0
    }
350
0
    else
351
0
    {
352
0
        const IlwisEllips *piwEllips = iwEllips;
353
0
        double e2 = 0.0;
354
0
        while (piwEllips->pszIlwisEllips)
355
0
        {
356
0
            if (EQUALN(sEllips.c_str(), piwEllips->pszIlwisEllips,
357
0
                       strlen(piwEllips->pszIlwisEllips)))
358
0
            {
359
0
                double a = piwEllips->semiMajor;
360
0
                double b = a * (1 - piwEllips->invFlattening);
361
0
                e2 = (a * a - b * b) / (a * a);
362
0
                break;
363
0
            }
364
0
            piwEllips++;
365
0
        }
366
0
        scale = cos(phits) / sqrt(1. - e2 * sin(phits) * sin(phits));
367
0
    }
368
0
}
369
370
/************************************************************************/
371
/*                          ReadProjection()                           */
372
/************************************************************************/
373
374
/**
375
 * Import coordinate system from ILWIS projection definition.
376
 *
377
 * The method will import projection definition in ILWIS,
378
 * It uses 13 parameters to define the coordinate system
379
 * and datum/ellipsoid specified in the padfPrjParams array.
380
 *
381
 * @param csyFileName Name of .csy file
382
 **/
383
384
CPLErr ILWISDataset::ReadProjection(const std::string &csyFileName)
385
0
{
386
0
    std::string pszEllips;
387
0
    std::string pszDatum;
388
0
    std::string pszProj;
389
390
    // translate ILWIS pre-defined coordinate systems
391
0
    if (STARTS_WITH_CI(csyFileName.c_str(), "latlon.csy"))
392
0
    {
393
0
        pszProj = "LatLon";
394
0
        pszDatum = "";
395
0
        pszEllips = "Sphere";
396
0
    }
397
0
    else if (STARTS_WITH_CI(csyFileName.c_str(), "LatlonWGS84.csy"))
398
0
    {
399
0
        pszProj = "LatLon";
400
0
        pszDatum = "WGS 1984";
401
0
        pszEllips = "WGS 84";
402
0
    }
403
0
    else
404
0
    {
405
0
        pszProj = ReadElement("CoordSystem", "Type", csyFileName);
406
0
        if (!STARTS_WITH_CI(pszProj.c_str(), "LatLon"))
407
0
            pszProj = ReadElement("CoordSystem", "Projection", csyFileName);
408
0
        pszDatum = ReadElement("CoordSystem", "Datum", csyFileName);
409
0
        pszEllips = ReadElement("CoordSystem", "Ellipsoid", csyFileName);
410
0
    }
411
412
    /* -------------------------------------------------------------------- */
413
    /*      Fetch array containing 13 coordinate system parameters          */
414
    /* -------------------------------------------------------------------- */
415
0
    double padfPrjParams[13];
416
0
    fetchParams(csyFileName, padfPrjParams);
417
418
0
    m_oSRS.Clear();
419
    /* -------------------------------------------------------------------- */
420
    /*      Operate on the basis of the projection name.                    */
421
    /* -------------------------------------------------------------------- */
422
0
    if (STARTS_WITH_CI(pszProj.c_str(), "LatLon"))
423
0
    {
424
        // set datum later
425
0
    }
426
0
    else if (STARTS_WITH_CI(pszProj.c_str(), "Albers EqualArea Conic"))
427
0
    {
428
0
        m_oSRS.SetProjCS("Albers EqualArea Conic");
429
0
        m_oSRS.SetACEA(padfPrjParams[7], padfPrjParams[8], padfPrjParams[5],
430
0
                       padfPrjParams[6], padfPrjParams[3], padfPrjParams[4]);
431
0
    }
432
0
    else if (STARTS_WITH_CI(pszProj.c_str(), "Azimuthal Equidistant"))
433
0
    {
434
0
        m_oSRS.SetProjCS("Azimuthal Equidistant");
435
0
        m_oSRS.SetAE(padfPrjParams[5], padfPrjParams[6], padfPrjParams[3],
436
0
                     padfPrjParams[4]);
437
0
    }
438
0
    else if (STARTS_WITH_CI(pszProj.c_str(), "Central Cylindrical"))
439
0
    {
440
        // Use Central Parallel for dfStdP1
441
        // padfPrjParams[5] is always to zero
442
0
        m_oSRS.SetProjCS("Central Cylindrical");
443
0
        m_oSRS.SetCEA(padfPrjParams[5], padfPrjParams[6], padfPrjParams[3],
444
0
                      padfPrjParams[4]);
445
0
    }
446
0
    else if (STARTS_WITH_CI(pszProj.c_str(), "Cassini"))
447
0
    {
448
        // Use Latitude_Of_True_Scale for dfCenterLat
449
        // Scale Factor 1.0 should always be defined
450
0
        m_oSRS.SetProjCS("Cassini");
451
0
        m_oSRS.SetCS(padfPrjParams[10], padfPrjParams[6], padfPrjParams[3],
452
0
                     padfPrjParams[4]);
453
0
    }
454
0
    else if (STARTS_WITH_CI(pszProj.c_str(), "DutchRD"))
455
0
    {
456
0
        m_oSRS.SetProjCS("DutchRD");
457
0
        m_oSRS.SetStereographic(52.156160556, 5.387638889, 0.9999079, 155000,
458
0
                                463000);
459
0
    }
460
0
    else if (STARTS_WITH_CI(pszProj.c_str(), "Equidistant Conic"))
461
0
    {
462
0
        m_oSRS.SetProjCS("Equidistant Conic");
463
0
        m_oSRS.SetEC(padfPrjParams[7], padfPrjParams[8], padfPrjParams[5],
464
0
                     padfPrjParams[6], padfPrjParams[3], padfPrjParams[4]);
465
0
    }
466
0
    else if (STARTS_WITH_CI(pszProj.c_str(), "Gauss-Krueger Germany"))
467
0
    {
468
        // FalseNorthing and CenterLat are always set to 0
469
        // Scale 1.0 is defined
470
        // FalseEasting and CentralMeridian are defined by the selected zone
471
0
        mapTMParams("Gauss-Krueger Germany", padfPrjParams[11],
472
0
                    padfPrjParams[3], padfPrjParams[6]);
473
0
        m_oSRS.SetProjCS("Gauss-Krueger Germany");
474
0
        m_oSRS.SetTM(0, padfPrjParams[6], 1.0, padfPrjParams[3], 0);
475
0
    }
476
0
    else if (STARTS_WITH_CI(pszProj.c_str(), "Gauss-Boaga Italy"))
477
0
    {
478
        // FalseNorthing and CenterLat are always set to 0
479
        // Scale 0.9996 is defined
480
        // FalseEasting and CentralMeridian are defined by the selected zone
481
0
        mapTMParams("Gauss-Boaga Italy", padfPrjParams[11], padfPrjParams[3],
482
0
                    padfPrjParams[6]);
483
0
        m_oSRS.SetProjCS("Gauss-Boaga Italy");
484
0
        m_oSRS.SetTM(0, padfPrjParams[6], 0.9996, padfPrjParams[3], 0);
485
0
    }
486
0
    else if (STARTS_WITH_CI(pszProj.c_str(), "Gauss Colombia"))
487
0
    {
488
        // 1000000 used for FalseNorthing and FalseEasting
489
        // 1.0 used for scale
490
        // CenterLat is defined 45.1609259259259
491
        // CentralMeridian is defined by the selected zone
492
0
        mapTMParams("Gauss Colombia", padfPrjParams[11], padfPrjParams[3],
493
0
                    padfPrjParams[6]);
494
0
        m_oSRS.SetProjCS("Gauss Colombia");
495
0
        m_oSRS.SetTM(45.1609259259259, padfPrjParams[6], 1.0, 1000000, 1000000);
496
0
    }
497
0
    else if (STARTS_WITH_CI(pszProj.c_str(), "Gnomonic"))
498
0
    {
499
0
        m_oSRS.SetProjCS("Gnomonic");
500
0
        m_oSRS.SetGnomonic(padfPrjParams[5], padfPrjParams[6], padfPrjParams[3],
501
0
                           padfPrjParams[4]);
502
0
    }
503
0
    else if (STARTS_WITH_CI(pszProj.c_str(), "Lambert Conformal Conic"))
504
0
    {
505
        // should use 1.0 for scale factor in Ilwis definition
506
0
        m_oSRS.SetProjCS("Lambert Conformal Conic");
507
0
        m_oSRS.SetLCC(padfPrjParams[7], padfPrjParams[8], padfPrjParams[5],
508
0
                      padfPrjParams[6], padfPrjParams[3], padfPrjParams[4]);
509
0
    }
510
0
    else if (STARTS_WITH_CI(pszProj.c_str(), "Lambert Cylind EqualArea"))
511
0
    {
512
        // Latitude_Of_True_Scale used for dfStdP1 ?
513
0
        m_oSRS.SetProjCS("Lambert Conformal Conic");
514
0
        m_oSRS.SetCEA(padfPrjParams[10], padfPrjParams[6], padfPrjParams[3],
515
0
                      padfPrjParams[4]);
516
0
    }
517
0
    else if (STARTS_WITH_CI(pszProj.c_str(), "Mercator"))
518
0
    {
519
        // use 0 for CenterLat, scale is computed from the
520
        // Latitude_Of_True_Scale
521
0
        scaleFromLATTS(pszEllips, padfPrjParams[10], padfPrjParams[9]);
522
0
        m_oSRS.SetProjCS("Mercator");
523
0
        m_oSRS.SetMercator(0, padfPrjParams[6], padfPrjParams[9],
524
0
                           padfPrjParams[3], padfPrjParams[4]);
525
0
    }
526
0
    else if (STARTS_WITH_CI(pszProj.c_str(), "Miller"))
527
0
    {
528
        // use 0 for CenterLat
529
0
        m_oSRS.SetProjCS("Miller");
530
0
        m_oSRS.SetMC(0, padfPrjParams[6], padfPrjParams[3], padfPrjParams[4]);
531
0
    }
532
0
    else if (STARTS_WITH_CI(pszProj.c_str(), "Mollweide"))
533
0
    {
534
0
        m_oSRS.SetProjCS("Mollweide");
535
0
        m_oSRS.SetMollweide(padfPrjParams[6], padfPrjParams[3],
536
0
                            padfPrjParams[4]);
537
0
    }
538
0
    else if (STARTS_WITH_CI(pszProj.c_str(), "Orthographic"))
539
0
    {
540
0
        m_oSRS.SetProjCS("Orthographic");
541
0
        m_oSRS.SetOrthographic(padfPrjParams[5], padfPrjParams[6],
542
0
                               padfPrjParams[3], padfPrjParams[4]);
543
0
    }
544
0
    else if (STARTS_WITH_CI(pszProj.c_str(), "Plate Carree") ||
545
0
             STARTS_WITH_CI(pszProj.c_str(), "Plate Rectangle"))
546
0
    {
547
        // set 0.0 for CenterLat for Plate Carree projection
548
        // skip Latitude_Of_True_Scale for Plate Rectangle projection definition
549
0
        m_oSRS.SetProjCS(pszProj.c_str());
550
0
        m_oSRS.SetEquirectangular(padfPrjParams[5], padfPrjParams[6],
551
0
                                  padfPrjParams[3], padfPrjParams[4]);
552
0
    }
553
0
    else if (STARTS_WITH_CI(pszProj.c_str(), "PolyConic"))
554
0
    {
555
        // skip scale factor
556
0
        m_oSRS.SetProjCS("PolyConic");
557
0
        m_oSRS.SetPolyconic(padfPrjParams[5], padfPrjParams[6],
558
0
                            padfPrjParams[3], padfPrjParams[4]);
559
0
    }
560
0
    else if (STARTS_WITH_CI(pszProj.c_str(), "Robinson"))
561
0
    {
562
0
        m_oSRS.SetProjCS("Robinson");
563
0
        m_oSRS.SetRobinson(padfPrjParams[6], padfPrjParams[3],
564
0
                           padfPrjParams[4]);
565
0
    }
566
0
    else if (STARTS_WITH_CI(pszProj.c_str(), "Sinusoidal"))
567
0
    {
568
0
        m_oSRS.SetProjCS("Sinusoidal");
569
0
        m_oSRS.SetSinusoidal(padfPrjParams[6], padfPrjParams[3],
570
0
                             padfPrjParams[4]);
571
0
    }
572
0
    else if (STARTS_WITH_CI(pszProj.c_str(), "Stereographic"))
573
0
    {
574
0
        m_oSRS.SetProjCS("Stereographic");
575
0
        m_oSRS.SetStereographic(padfPrjParams[5], padfPrjParams[6],
576
0
                                padfPrjParams[9], padfPrjParams[3],
577
0
                                padfPrjParams[4]);
578
0
    }
579
0
    else if (STARTS_WITH_CI(pszProj.c_str(), "Transverse Mercator"))
580
0
    {
581
0
        m_oSRS.SetProjCS("Transverse Mercator");
582
0
        m_oSRS.SetStereographic(padfPrjParams[5], padfPrjParams[6],
583
0
                                padfPrjParams[9], padfPrjParams[3],
584
0
                                padfPrjParams[4]);
585
0
    }
586
0
    else if (STARTS_WITH_CI(pszProj.c_str(), "UTM"))
587
0
    {
588
0
        std::string pszNH =
589
0
            ReadElement("Projection", "Northern Hemisphere", csyFileName);
590
0
        m_oSRS.SetProjCS("UTM");
591
0
        if (STARTS_WITH_CI(pszNH.c_str(), "Yes"))
592
0
            m_oSRS.SetUTM((int)padfPrjParams[11], 1);
593
0
        else
594
0
            m_oSRS.SetUTM((int)padfPrjParams[11], 0);
595
0
    }
596
0
    else if (STARTS_WITH_CI(pszProj.c_str(), "VanderGrinten"))
597
0
    {
598
0
        m_oSRS.SetVDG(padfPrjParams[6], padfPrjParams[3], padfPrjParams[4]);
599
0
    }
600
0
    else if (STARTS_WITH_CI(pszProj.c_str(), "GeoStationary Satellite"))
601
0
    {
602
0
        m_oSRS.SetGEOS(padfPrjParams[6], padfPrjParams[12], padfPrjParams[3],
603
0
                       padfPrjParams[4]);
604
0
    }
605
0
    else if (STARTS_WITH_CI(pszProj.c_str(), "MSG Perspective"))
606
0
    {
607
0
        m_oSRS.SetGEOS(padfPrjParams[6], padfPrjParams[12], padfPrjParams[3],
608
0
                       padfPrjParams[4]);
609
0
    }
610
0
    else
611
0
    {
612
0
        m_oSRS.SetLocalCS(pszProj.c_str());
613
0
    }
614
    /* -------------------------------------------------------------------- */
615
    /*      Try to translate the datum/spheroid.                            */
616
    /* -------------------------------------------------------------------- */
617
618
0
    if (!m_oSRS.IsLocal())
619
0
    {
620
0
        const IlwisDatums *piwDatum = iwDatums;
621
622
        // Search for matching datum
623
0
        while (piwDatum->pszIlwisDatum)
624
0
        {
625
0
            if (EQUALN(pszDatum.c_str(), piwDatum->pszIlwisDatum,
626
0
                       strlen(piwDatum->pszIlwisDatum)))
627
0
            {
628
0
                OGRSpatialReference oOGR;
629
0
                oOGR.importFromEPSG(piwDatum->nEPSGCode);
630
0
                m_oSRS.CopyGeogCSFrom(&oOGR);
631
0
                break;
632
0
            }
633
0
            piwDatum++;
634
0
        }  // End of searching for matching datum.
635
636
        /* --------------------------------------------------------------------
637
         */
638
        /*      If no matching for datum definition, fetch info about an */
639
        /*      ellipsoid.  semi major axis is always returned in meters */
640
        /* --------------------------------------------------------------------
641
         */
642
0
        const IlwisEllips *piwEllips = iwEllips;
643
0
        if (pszEllips.empty())
644
0
            pszEllips = "Sphere";
645
0
        if (!piwDatum->pszIlwisDatum)
646
0
        {
647
0
            while (piwEllips->pszIlwisEllips)
648
0
            {
649
0
                if (EQUALN(pszEllips.c_str(), piwEllips->pszIlwisEllips,
650
0
                           strlen(piwEllips->pszIlwisEllips)))
651
0
                {
652
0
                    double dfSemiMajor = piwEllips->semiMajor;
653
0
                    if (STARTS_WITH_CI(pszEllips.c_str(), "Sphere") &&
654
0
                        padfPrjParams[0] != 0)
655
0
                    {
656
0
                        dfSemiMajor = padfPrjParams[0];
657
0
                    }
658
0
                    m_oSRS.SetGeogCS(
659
0
                        CPLSPrintf("Unknown datum based upon the %s ellipsoid",
660
0
                                   piwEllips->pszIlwisEllips),
661
0
                        CPLSPrintf("Not specified (based on %s spheroid)",
662
0
                                   piwEllips->pszIlwisEllips),
663
0
                        piwEllips->pszIlwisEllips, dfSemiMajor,
664
0
                        piwEllips->invFlattening, nullptr, 0.0, nullptr, 0.0);
665
0
                    m_oSRS.SetAuthority("SPHEROID", "EPSG",
666
0
                                        piwEllips->nEPSGCode);
667
668
0
                    break;
669
0
                }
670
0
                piwEllips++;
671
0
            }  // end of searching for matching ellipsoid
672
0
        }
673
674
        /* --------------------------------------------------------------------
675
         */
676
        /*      If no matching for ellipsoid definition, fetch info about an */
677
        /*      user defined ellipsoid. If cannot find, default to WGS 84 */
678
        /* --------------------------------------------------------------------
679
         */
680
0
        if (!piwEllips->pszIlwisEllips)
681
0
        {
682
683
0
            if (STARTS_WITH_CI(pszEllips.c_str(), "User Defined"))
684
0
            {
685
0
                m_oSRS.SetGeogCS(
686
0
                    "Unknown datum based upon the custom ellipsoid",
687
0
                    "Not specified (based on custom ellipsoid)",
688
0
                    "Custom ellipsoid", padfPrjParams[0], padfPrjParams[2],
689
0
                    nullptr, 0, nullptr, 0);
690
0
            }
691
0
            else
692
0
            {
693
                // if cannot find the user defined ellips, default to WGS84
694
0
                m_oSRS.SetWellKnownGeogCS("WGS84");
695
0
            }
696
0
        }
697
0
    }  // end of if ( !IsLocal() )
698
699
    /* -------------------------------------------------------------------- */
700
    /*      Units translation                                          */
701
    /* -------------------------------------------------------------------- */
702
0
    if (m_oSRS.IsLocal() || m_oSRS.IsProjected())
703
0
    {
704
0
        m_oSRS.SetLinearUnits(SRS_UL_METER, 1.0);
705
0
    }
706
707
0
    return CE_None;
708
0
}
709
710
static void WriteFalseEastNorth(const std::string &csFileName,
711
                                const OGRSpatialReference &oSRS)
712
0
{
713
0
    WriteElement("Projection", ILW_False_Easting, csFileName,
714
0
                 oSRS.GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0));
715
0
    WriteElement("Projection", ILW_False_Northing, csFileName,
716
0
                 oSRS.GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0));
717
0
}
718
719
static void WriteProjectionName(const std::string &csFileName,
720
                                const std::string &stProjection)
721
0
{
722
0
    WriteElement("CoordSystem", "Type", csFileName, "Projection");
723
0
    WriteElement("CoordSystem", "Projection", csFileName, stProjection);
724
0
}
725
726
static void WriteUTM(const std::string &csFileName,
727
                     const OGRSpatialReference &oSRS)
728
0
{
729
0
    int bNorth;
730
731
0
    int nZone = oSRS.GetUTMZone(&bNorth);
732
0
    WriteElement("CoordSystem", "Type", csFileName, "Projection");
733
0
    WriteElement("CoordSystem", "Projection", csFileName, "UTM");
734
0
    if (bNorth)
735
0
        WriteElement("Projection", "Northern Hemisphere", csFileName, "Yes");
736
0
    else
737
0
        WriteElement("Projection", "Northern Hemisphere", csFileName, "No");
738
0
    WriteElement("Projection", "Zone", csFileName, nZone);
739
0
}
740
741
static void WriteAlbersConicEqualArea(const std::string &csFileName,
742
                                      const OGRSpatialReference &oSRS)
743
0
{
744
0
    WriteProjectionName(csFileName, "Albers EqualArea Conic");
745
0
    WriteFalseEastNorth(csFileName, oSRS);
746
0
    WriteElement("Projection", ILW_Central_Meridian, csFileName,
747
0
                 oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
748
0
    WriteElement("Projection", ILW_Central_Parallel, csFileName,
749
0
                 oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0));
750
0
    WriteElement("Projection", ILW_Standard_Parallel_1, csFileName,
751
0
                 oSRS.GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1, 0.0));
752
0
    WriteElement("Projection", ILW_Standard_Parallel_2, csFileName,
753
0
                 oSRS.GetNormProjParm(SRS_PP_STANDARD_PARALLEL_2, 0.0));
754
0
}
755
756
static void WriteAzimuthalEquidistant(const std::string &csFileName,
757
                                      const OGRSpatialReference &oSRS)
758
0
{
759
0
    WriteProjectionName(csFileName, "Azimuthal Equidistant");
760
0
    WriteFalseEastNorth(csFileName, oSRS);
761
0
    WriteElement("Projection", ILW_Central_Meridian, csFileName,
762
0
                 oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
763
0
    WriteElement("Projection", ILW_Central_Parallel, csFileName,
764
0
                 oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0));
765
0
    WriteElement("Projection", ILW_Scale_Factor, csFileName, "1.0000000000");
766
0
}
767
768
static void WriteCylindricalEqualArea(const std::string &csFileName,
769
                                      const OGRSpatialReference &oSRS)
770
0
{
771
0
    WriteProjectionName(csFileName, "Central Cylindrical");
772
0
    WriteFalseEastNorth(csFileName, oSRS);
773
0
    WriteElement("Projection", ILW_Central_Meridian, csFileName,
774
0
                 oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
775
0
}
776
777
static void WriteCassiniSoldner(const std::string &csFileName,
778
                                const OGRSpatialReference &oSRS)
779
0
{
780
0
    WriteProjectionName(csFileName, "Cassini");
781
0
    WriteFalseEastNorth(csFileName, oSRS);
782
0
    WriteElement("Projection", ILW_Central_Meridian, csFileName,
783
0
                 oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
784
0
    WriteElement("Projection", ILW_Latitude_True_Scale, csFileName,
785
0
                 oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0));
786
0
    WriteElement("Projection", ILW_Scale_Factor, csFileName, "1.0000000000");
787
0
}
788
789
static void WriteStereographic(const std::string &csFileName,
790
                               const OGRSpatialReference &oSRS)
791
0
{
792
0
    WriteProjectionName(csFileName, "Stereographic");
793
0
    WriteFalseEastNorth(csFileName, oSRS);
794
0
    WriteElement("Projection", ILW_Central_Meridian, csFileName,
795
0
                 oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
796
0
    WriteElement("Projection", ILW_Central_Parallel, csFileName,
797
0
                 oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0));
798
0
    WriteElement("Projection", ILW_Scale_Factor, csFileName,
799
0
                 oSRS.GetNormProjParm(SRS_PP_SCALE_FACTOR, 0.0));
800
0
}
801
802
static void WriteEquidistantConic(const std::string &csFileName,
803
                                  const OGRSpatialReference &oSRS)
804
0
{
805
0
    WriteProjectionName(csFileName, "Equidistant Conic");
806
0
    WriteFalseEastNorth(csFileName, oSRS);
807
0
    WriteElement("Projection", ILW_Central_Meridian, csFileName,
808
0
                 oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
809
0
    WriteElement("Projection", ILW_Central_Parallel, csFileName,
810
0
                 oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0));
811
0
    WriteElement("Projection", ILW_Standard_Parallel_1, csFileName,
812
0
                 oSRS.GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1, 0.0));
813
0
    WriteElement("Projection", ILW_Standard_Parallel_2, csFileName,
814
0
                 oSRS.GetNormProjParm(SRS_PP_STANDARD_PARALLEL_2, 0.0));
815
0
}
816
817
static void WriteTransverseMercator(const std::string &csFileName,
818
                                    const OGRSpatialReference &oSRS)
819
0
{
820
0
    WriteProjectionName(csFileName, "Transverse Mercator");
821
0
    WriteFalseEastNorth(csFileName, oSRS);
822
0
    WriteElement("Projection", ILW_Central_Meridian, csFileName,
823
0
                 oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
824
0
    WriteElement("Projection", ILW_Central_Parallel, csFileName,
825
0
                 oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0));
826
0
    WriteElement("Projection", ILW_Scale_Factor, csFileName,
827
0
                 oSRS.GetNormProjParm(SRS_PP_SCALE_FACTOR, 0.0));
828
0
}
829
830
static void WriteGnomonic(const std::string &csFileName,
831
                          const OGRSpatialReference &oSRS)
832
0
{
833
0
    WriteProjectionName(csFileName, "Gnomonic");
834
0
    WriteFalseEastNorth(csFileName, oSRS);
835
0
    WriteElement("Projection", ILW_Central_Meridian, csFileName,
836
0
                 oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
837
0
    WriteElement("Projection", ILW_Central_Parallel, csFileName,
838
0
                 oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0));
839
0
}
840
841
static void WriteLambertConformalConic(const std::string &csFileName,
842
                                       const OGRSpatialReference &oSRS)
843
0
{
844
0
    WriteProjectionName(csFileName, "Lambert Conformal Conic");
845
0
    WriteFalseEastNorth(csFileName, oSRS);
846
0
    WriteElement("Projection", ILW_Central_Meridian, csFileName,
847
0
                 oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
848
0
    WriteElement("Projection", ILW_Central_Parallel, csFileName,
849
0
                 oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0));
850
0
    WriteElement("Projection", ILW_Scale_Factor, csFileName, "1.0000000000");
851
0
}
852
853
static void WriteLambertConformalConic2SP(const std::string &csFileName,
854
                                          const OGRSpatialReference &oSRS)
855
0
{
856
0
    WriteProjectionName(csFileName, "Lambert Conformal Conic");
857
0
    WriteFalseEastNorth(csFileName, oSRS);
858
0
    WriteElement("Projection", ILW_Central_Meridian, csFileName,
859
0
                 oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
860
0
    WriteElement("Projection", ILW_Central_Parallel, csFileName,
861
0
                 oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0));
862
0
    WriteElement("Projection", ILW_Scale_Factor, csFileName, "1.0000000000");
863
0
    WriteElement("Projection", ILW_Standard_Parallel_1, csFileName,
864
0
                 oSRS.GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1, 0.0));
865
0
    WriteElement("Projection", ILW_Standard_Parallel_2, csFileName,
866
0
                 oSRS.GetNormProjParm(SRS_PP_STANDARD_PARALLEL_2, 0.0));
867
0
}
868
869
static void WriteLambertAzimuthalEqualArea(const std::string &csFileName,
870
                                           const OGRSpatialReference &oSRS)
871
0
{
872
0
    WriteProjectionName(csFileName, "Lambert Azimuthal EqualArea");
873
0
    WriteFalseEastNorth(csFileName, oSRS);
874
0
    WriteElement("Projection", ILW_Central_Meridian, csFileName,
875
0
                 oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
876
0
    WriteElement("Projection", ILW_Central_Parallel, csFileName,
877
0
                 oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0));
878
0
}
879
880
static void WriteMercator_1SP(const std::string &csFileName,
881
                              const OGRSpatialReference &oSRS)
882
0
{
883
0
    WriteProjectionName(csFileName, "Mercator");
884
0
    WriteFalseEastNorth(csFileName, oSRS);
885
0
    WriteElement("Projection", ILW_Central_Meridian, csFileName,
886
0
                 oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
887
0
    WriteElement("Projection", ILW_Latitude_True_Scale, csFileName,
888
0
                 oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0));
889
0
}
890
891
static void WriteMillerCylindrical(const std::string &csFileName,
892
                                   const OGRSpatialReference &oSRS)
893
0
{
894
0
    WriteProjectionName(csFileName, "Miller");
895
0
    WriteFalseEastNorth(csFileName, oSRS);
896
0
    WriteElement("Projection", ILW_Central_Meridian, csFileName,
897
0
                 oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
898
0
}
899
900
static void WriteMolleweide(const std::string &csFileName,
901
                            const OGRSpatialReference &oSRS)
902
0
{
903
0
    WriteProjectionName(csFileName, "Mollweide");
904
0
    WriteFalseEastNorth(csFileName, oSRS);
905
0
    WriteElement("Projection", ILW_Central_Meridian, csFileName,
906
0
                 oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
907
0
}
908
909
static void WriteOrthographic(const std::string &csFileName,
910
                              const OGRSpatialReference &oSRS)
911
0
{
912
0
    WriteProjectionName(csFileName, "Orthographic");
913
0
    WriteFalseEastNorth(csFileName, oSRS);
914
0
    WriteElement("Projection", ILW_Central_Meridian, csFileName,
915
0
                 oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
916
0
    WriteElement("Projection", ILW_Central_Parallel, csFileName,
917
0
                 oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0));
918
0
}
919
920
static void WritePlateRectangle(const std::string &csFileName,
921
                                const OGRSpatialReference &oSRS)
922
0
{
923
0
    WriteProjectionName(csFileName, "Plate Rectangle");
924
0
    WriteFalseEastNorth(csFileName, oSRS);
925
0
    WriteElement("Projection", ILW_Central_Meridian, csFileName,
926
0
                 oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
927
0
    WriteElement("Projection", ILW_Central_Parallel, csFileName,
928
0
                 oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0));
929
0
    WriteElement("Projection", ILW_Latitude_True_Scale, csFileName,
930
0
                 "0.0000000000");
931
0
}
932
933
static void WritePolyConic(const std::string &csFileName,
934
                           const OGRSpatialReference &oSRS)
935
0
{
936
0
    WriteProjectionName(csFileName, "PolyConic");
937
0
    WriteFalseEastNorth(csFileName, oSRS);
938
0
    WriteElement("Projection", ILW_Central_Meridian, csFileName,
939
0
                 oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
940
0
    WriteElement("Projection", ILW_Central_Parallel, csFileName,
941
0
                 oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0));
942
0
    WriteElement("Projection", ILW_Scale_Factor, csFileName, "1.0000000000");
943
0
}
944
945
static void WriteRobinson(const std::string &csFileName,
946
                          const OGRSpatialReference &oSRS)
947
0
{
948
0
    WriteProjectionName(csFileName, "Robinson");
949
0
    WriteFalseEastNorth(csFileName, oSRS);
950
0
    WriteElement("Projection", ILW_Central_Meridian, csFileName,
951
0
                 oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
952
0
}
953
954
static void WriteSinusoidal(const std::string &csFileName,
955
                            const OGRSpatialReference &oSRS)
956
0
{
957
0
    WriteProjectionName(csFileName, "Sinusoidal");
958
0
    WriteFalseEastNorth(csFileName, oSRS);
959
0
    WriteElement("Projection", ILW_Central_Meridian, csFileName,
960
0
                 oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
961
0
}
962
963
static void WriteVanderGrinten(const std::string &csFileName,
964
                               const OGRSpatialReference &oSRS)
965
0
{
966
0
    WriteProjectionName(csFileName, "VanderGrinten");
967
0
    WriteFalseEastNorth(csFileName, oSRS);
968
0
    WriteElement("Projection", ILW_Central_Meridian, csFileName,
969
0
                 oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
970
0
}
971
972
static void WriteGeoStatSat(const std::string &csFileName,
973
                            const OGRSpatialReference &oSRS)
974
0
{
975
0
    WriteProjectionName(csFileName, "GeoStationary Satellite");
976
0
    WriteFalseEastNorth(csFileName, oSRS);
977
0
    WriteElement("Projection", ILW_Central_Meridian, csFileName,
978
0
                 oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
979
0
    WriteElement("Projection", ILW_Scale_Factor, csFileName, "1.0000000000");
980
0
    WriteElement("Projection", ILW_Height_Persp_Center, csFileName,
981
0
                 oSRS.GetNormProjParm(SRS_PP_SATELLITE_HEIGHT, 35785831.0));
982
0
}
983
984
/************************************************************************/
985
/*                          WriteProjection()                           */
986
/************************************************************************/
987
/**
988
 * Export coordinate system in ILWIS projection definition.
989
 *
990
 * Converts the loaded coordinate reference system into ILWIS projection
991
 * definition to the extent possible.
992
 */
993
CPLErr ILWISDataset::WriteProjection()
994
995
0
{
996
0
    OGRSpatialReference *poGeogSRS = nullptr;
997
998
0
    std::string csFileName = CPLResetExtensionSafe(osFileName, "csy");
999
0
    std::string pszBaseName = std::string(CPLGetBasenameSafe(osFileName));
1000
    // std::string pszPath = std::string(CPLGetPathSafe( osFileName ));
1001
0
    const bool bHaveSRS = !m_oSRS.IsEmpty();
1002
1003
0
    const IlwisDatums *piwDatum = iwDatums;
1004
    // std::string pszEllips;
1005
0
    std::string osDatum;
1006
    // std::string pszProj;
1007
1008
    /* -------------------------------------------------------------------- */
1009
    /*      Collect datum/ellips information. */
1010
    /* -------------------------------------------------------------------- */
1011
0
    if (bHaveSRS)
1012
0
    {
1013
0
        poGeogSRS = m_oSRS.CloneGeogCS();
1014
0
    }
1015
1016
0
    std::string grFileName = CPLResetExtensionSafe(osFileName, "grf");
1017
0
    std::string csy;
1018
0
    if (poGeogSRS)
1019
0
    {
1020
0
        csy = pszBaseName + ".csy";
1021
1022
0
        WriteElement("Ilwis", "Type", csFileName, "CoordSystem");
1023
0
        const char *pszDatum = poGeogSRS->GetAttrValue("GEOGCS|DATUM");
1024
0
        if (pszDatum)
1025
0
            osDatum = pszDatum;
1026
1027
        /* WKT to ILWIS translation */
1028
0
        while (piwDatum->pszWKTDatum)
1029
0
        {
1030
0
            if (EQUALN(osDatum.c_str(), piwDatum->pszWKTDatum,
1031
0
                       strlen(piwDatum->pszWKTDatum)))
1032
0
            {
1033
0
                WriteElement("CoordSystem", "Datum", csFileName,
1034
0
                             piwDatum->pszIlwisDatum);
1035
0
                break;
1036
0
            }
1037
0
            piwDatum++;
1038
0
        }  // End of searching for matching datum.
1039
0
        WriteElement("CoordSystem", "Width", csFileName, 28);
1040
        // pszEllips = poGeogSRS->GetAttrValue( "GEOGCS|DATUM|SPHEROID" );
1041
0
        double a = poGeogSRS->GetSemiMajor();
1042
0
        /* b = */ poGeogSRS->GetSemiMinor();
1043
0
        double f = poGeogSRS->GetInvFlattening();
1044
0
        WriteElement("CoordSystem", "Ellipsoid", csFileName, "User Defined");
1045
0
        WriteElement("Ellipsoid", "a", csFileName, a);
1046
0
        WriteElement("Ellipsoid", "1/f", csFileName, f);
1047
0
    }
1048
0
    else
1049
0
        csy = "unknown.csy";
1050
1051
    /* -------------------------------------------------------------------- */
1052
    /*  Determine to write a geo-referencing file for the dataset to create */
1053
    /* -------------------------------------------------------------------- */
1054
0
    if (adfGeoTransform[0] != 0.0 || adfGeoTransform[1] != 1.0 ||
1055
0
        adfGeoTransform[2] != 0.0 || adfGeoTransform[3] != 0.0 ||
1056
0
        adfGeoTransform[4] != 0.0 || fabs(adfGeoTransform[5]) != 1.0)
1057
0
        WriteElement("GeoRef", "CoordSystem", grFileName, csy);
1058
1059
    /* -------------------------------------------------------------------- */
1060
    /*  Recognise various projections.                                      */
1061
    /* -------------------------------------------------------------------- */
1062
0
    const char *pszProjName = nullptr;
1063
1064
0
    if (bHaveSRS)
1065
0
        pszProjName = m_oSRS.GetAttrValue("PROJCS|PROJECTION");
1066
1067
0
    if (pszProjName == nullptr)
1068
0
    {
1069
0
        if (bHaveSRS && m_oSRS.IsGeographic())
1070
0
        {
1071
0
            WriteElement("CoordSystem", "Type", csFileName, "LatLon");
1072
0
        }
1073
0
    }
1074
0
    else if (m_oSRS.GetUTMZone(nullptr) != 0)
1075
0
    {
1076
0
        WriteUTM(csFileName, m_oSRS);
1077
0
    }
1078
0
    else if (EQUAL(pszProjName, SRS_PT_ALBERS_CONIC_EQUAL_AREA))
1079
0
    {
1080
0
        WriteAlbersConicEqualArea(csFileName, m_oSRS);
1081
0
    }
1082
0
    else if (EQUAL(pszProjName, SRS_PT_AZIMUTHAL_EQUIDISTANT))
1083
0
    {
1084
0
        WriteAzimuthalEquidistant(csFileName, m_oSRS);
1085
0
    }
1086
0
    else if (EQUAL(pszProjName, SRS_PT_CYLINDRICAL_EQUAL_AREA))
1087
0
    {
1088
0
        WriteCylindricalEqualArea(csFileName, m_oSRS);
1089
0
    }
1090
0
    else if (EQUAL(pszProjName, SRS_PT_CASSINI_SOLDNER))
1091
0
    {
1092
0
        WriteCassiniSoldner(csFileName, m_oSRS);
1093
0
    }
1094
0
    else if (EQUAL(pszProjName, SRS_PT_STEREOGRAPHIC))
1095
0
    {
1096
0
        WriteStereographic(csFileName, m_oSRS);
1097
0
    }
1098
0
    else if (EQUAL(pszProjName, SRS_PT_EQUIDISTANT_CONIC))
1099
0
    {
1100
0
        WriteEquidistantConic(csFileName, m_oSRS);
1101
0
    }
1102
0
    else if (EQUAL(pszProjName, SRS_PT_TRANSVERSE_MERCATOR))
1103
0
    {
1104
0
        WriteTransverseMercator(csFileName, m_oSRS);
1105
0
    }
1106
0
    else if (EQUAL(pszProjName, SRS_PT_GNOMONIC))
1107
0
    {
1108
0
        WriteGnomonic(csFileName, m_oSRS);
1109
0
    }
1110
0
    else if (EQUAL(pszProjName, "Lambert_Conformal_Conic"))
1111
0
    {
1112
0
        WriteLambertConformalConic(csFileName, m_oSRS);
1113
0
    }
1114
0
    else if (EQUAL(pszProjName, SRS_PT_LAMBERT_CONFORMAL_CONIC_1SP))
1115
0
    {
1116
0
        WriteLambertConformalConic(csFileName, m_oSRS);
1117
0
    }
1118
0
    else if (EQUAL(pszProjName, SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP))
1119
0
    {
1120
0
        WriteLambertConformalConic2SP(csFileName, m_oSRS);
1121
0
    }
1122
0
    else if (EQUAL(pszProjName, SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA))
1123
0
    {
1124
0
        WriteLambertAzimuthalEqualArea(csFileName, m_oSRS);
1125
0
    }
1126
0
    else if (EQUAL(pszProjName, SRS_PT_MERCATOR_1SP))
1127
0
    {
1128
0
        WriteMercator_1SP(csFileName, m_oSRS);
1129
0
    }
1130
0
    else if (EQUAL(pszProjName, SRS_PT_MILLER_CYLINDRICAL))
1131
0
    {
1132
0
        WriteMillerCylindrical(csFileName, m_oSRS);
1133
0
    }
1134
0
    else if (EQUAL(pszProjName, SRS_PT_MOLLWEIDE))
1135
0
    {
1136
0
        WriteMolleweide(csFileName, m_oSRS);
1137
0
    }
1138
0
    else if (EQUAL(pszProjName, SRS_PT_ORTHOGRAPHIC))
1139
0
    {
1140
0
        WriteOrthographic(csFileName, m_oSRS);
1141
0
    }
1142
0
    else if (EQUAL(pszProjName, SRS_PT_EQUIRECTANGULAR))
1143
0
    {
1144
0
        WritePlateRectangle(csFileName, m_oSRS);
1145
0
    }
1146
0
    else if (EQUAL(pszProjName, SRS_PT_POLYCONIC))
1147
0
    {
1148
0
        WritePolyConic(csFileName, m_oSRS);
1149
0
    }
1150
0
    else if (EQUAL(pszProjName, SRS_PT_ROBINSON))
1151
0
    {
1152
0
        WriteRobinson(csFileName, m_oSRS);
1153
0
    }
1154
0
    else if (EQUAL(pszProjName, SRS_PT_SINUSOIDAL))
1155
0
    {
1156
0
        WriteSinusoidal(csFileName, m_oSRS);
1157
0
    }
1158
0
    else if (EQUAL(pszProjName, SRS_PT_VANDERGRINTEN))
1159
0
    {
1160
0
        WriteVanderGrinten(csFileName, m_oSRS);
1161
0
    }
1162
0
    else if (EQUAL(pszProjName, SRS_PT_GEOSTATIONARY_SATELLITE))
1163
0
    {
1164
0
        WriteGeoStatSat(csFileName, m_oSRS);
1165
0
    }
1166
0
    else
1167
0
    {
1168
        // Projection unknown by ILWIS
1169
0
    }
1170
1171
    /* -------------------------------------------------------------------- */
1172
    /*      Cleanup                                                         */
1173
    /* -------------------------------------------------------------------- */
1174
0
    if (poGeogSRS != nullptr)
1175
0
        delete poGeogSRS;
1176
1177
0
    return CE_None;
1178
0
}
1179
1180
}  // namespace GDAL