Coverage Report

Created: 2026-02-14 09:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gdal/ogr/ogrsf_frmts/sxf/ogrsxflayer.cpp
Line
Count
Source
1
/******************************************************************************
2
 *
3
 * Project:  SXF Translator
4
 * Purpose:  Definition of classes for OGR SXF Layers.
5
 * Author:   Ben Ahmed Daho Ali, bidandou(at)yahoo(dot)fr
6
 *           Dmitry Baryshnikov, polimax@mail.ru
7
 *           Alexandr Lisovenko, alexander.lisovenko@gmail.com
8
 *
9
 ******************************************************************************
10
 * Copyright (c) 2011, Ben Ahmed Daho Ali
11
 * Copyright (c) 2013, NextGIS
12
 * Copyright (c) 2014, Even Rouault <even dot rouault at spatialys.com>
13
 *
14
 * SPDX-License-Identifier: MIT
15
 ****************************************************************************/
16
17
#include "ogr_sxf.h"
18
#include "cpl_conv.h"
19
#include "cpl_string.h"
20
#include "ogr_p.h"
21
#include "ogr_srs_api.h"
22
#include "cpl_multiproc.h"
23
24
/************************************************************************/
25
/*                            OGRSXFLayer()                             */
26
/************************************************************************/
27
28
OGRSXFLayer::OGRSXFLayer(VSILFILE *fp, CPLMutex **hIOMutex, GByte nID,
29
                         const char *pszLayerName, int nVer,
30
                         const SXFMapDescription &sxfMapDesc)
31
0
    : OGRLayer(), poFeatureDefn(new OGRFeatureDefn(pszLayerName)), fpSXF(fp),
32
0
      nLayerID(nID), stSXFMapDescription(sxfMapDesc), m_nSXFFormatVer(nVer),
33
0
      sFIDColumn_("ogc_fid"), m_hIOMutex(hIOMutex),
34
0
      m_dfCoeff(sxfMapDesc.nResolution == 0
35
0
                    ? 0.0
36
0
                    : sxfMapDesc.dfScale / sxfMapDesc.nResolution)
37
0
{
38
0
    stSXFMapDescription.pSpatRef->Reference();
39
0
    oNextIt = mnRecordDesc.begin();
40
0
    SetDescription(poFeatureDefn->GetName());
41
0
    poFeatureDefn->Reference();
42
43
0
    poFeatureDefn->SetGeomType(wkbUnknown);
44
0
    if (poFeatureDefn->GetGeomFieldCount() != 0)
45
0
        poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(
46
0
            stSXFMapDescription.pSpatRef);
47
48
0
    OGRFieldDefn oFIDField(sFIDColumn_, OFTInteger);
49
0
    poFeatureDefn->AddFieldDefn(&oFIDField);
50
51
0
    OGRFieldDefn oClCodeField("CLCODE", OFTInteger);
52
0
    oClCodeField.SetWidth(10);
53
0
    poFeatureDefn->AddFieldDefn(&oClCodeField);
54
55
0
    OGRFieldDefn oClNameField("CLNAME", OFTString);
56
0
    oClNameField.SetWidth(32);
57
0
    poFeatureDefn->AddFieldDefn(&oClNameField);
58
59
0
    OGRFieldDefn oNumField("OBJECTNUMB", OFTInteger);
60
0
    oNumField.SetWidth(10);
61
0
    poFeatureDefn->AddFieldDefn(&oNumField);
62
63
0
    OGRFieldDefn oAngField("ANGLE", OFTReal);
64
0
    poFeatureDefn->AddFieldDefn(&oAngField);
65
66
0
    OGRFieldDefn oTextField("TEXT", OFTString);
67
0
    oTextField.SetWidth(255);
68
0
    poFeatureDefn->AddFieldDefn(&oTextField);
69
0
}
70
71
/************************************************************************/
72
/*                            ~OGRSXFLayer()                            */
73
/************************************************************************/
74
75
OGRSXFLayer::~OGRSXFLayer()
76
0
{
77
0
    stSXFMapDescription.pSpatRef->Release();
78
0
    poFeatureDefn->Release();
79
0
}
80
81
/************************************************************************/
82
/*                AddClassifyCode(unsigned nClassCode)                  */
83
/* Add layer supported classify codes. Only records with this code can  */
84
/* be in layer                                                          */
85
/************************************************************************/
86
87
void OGRSXFLayer::AddClassifyCode(unsigned nClassCode, const char *szName)
88
0
{
89
0
    if (szName != nullptr)
90
0
    {
91
0
        mnClassificators[nClassCode] = CPLString(szName);
92
0
    }
93
0
    else
94
0
    {
95
0
        mnClassificators[nClassCode] = CPLString().Printf("%d", nClassCode);
96
0
    }
97
0
}
98
99
/************************************************************************/
100
/*                             AddRecord()                              */
101
/************************************************************************/
102
103
bool OGRSXFLayer::AddRecord(long nFID, unsigned nClassCode,
104
                            vsi_l_offset nOffset, bool bHasSemantic,
105
                            size_t nSemanticsSize)
106
0
{
107
0
    if (mnClassificators.find(nClassCode) != mnClassificators.end() ||
108
0
        EQUAL(GetName(), "Not_Classified"))
109
0
    {
110
0
        mnRecordDesc[nFID] = nOffset;
111
        // Add additional semantics (attribute fields).
112
0
        if (bHasSemantic)
113
0
        {
114
0
            size_t offset = 0;
115
116
0
            while (offset < nSemanticsSize)
117
0
            {
118
0
                SXFRecordAttributeInfo stAttrInfo;
119
0
                bool bAddField = false;
120
0
                vsi_l_offset nCurrOff = 0;
121
0
                int nReadObj =
122
0
                    static_cast<int>(VSIFReadL(&stAttrInfo, 4, 1, fpSXF));
123
0
                if (nReadObj == 1)
124
0
                {
125
0
                    CPL_LSBPTR16(&(stAttrInfo.nCode));
126
0
                    CPLString oFieldName;
127
0
                    if (snAttributeCodes.find(stAttrInfo.nCode) ==
128
0
                        snAttributeCodes.end())
129
0
                    {
130
0
                        bAddField = true;
131
0
                        snAttributeCodes.insert(stAttrInfo.nCode);
132
0
                        oFieldName.Printf("SC_%d", stAttrInfo.nCode);
133
0
                    }
134
135
0
                    SXFRecordAttributeType eType =
136
0
                        (SXFRecordAttributeType)stAttrInfo.nType;
137
138
0
                    offset += 4;
139
140
0
                    switch (eType)  // TODO: set field type form RSC as here
141
                                    // sometimes we have the codes and string
142
                                    // values can be get from RSC by this code
143
0
                    {
144
0
                        case SXF_RAT_ASCIIZ_DOS:
145
0
                        {
146
0
                            if (bAddField)
147
0
                            {
148
0
                                OGRFieldDefn oField(oFieldName, OFTString);
149
0
                                oField.SetWidth(255);
150
0
                                poFeatureDefn->AddFieldDefn(&oField);
151
0
                            }
152
0
                            offset += stAttrInfo.nScale + 1;
153
0
                            nCurrOff = stAttrInfo.nScale + 1;
154
0
                            break;
155
0
                        }
156
0
                        case SXF_RAT_ONEBYTE:
157
0
                        {
158
0
                            if (bAddField)
159
0
                            {
160
0
                                OGRFieldDefn oField(oFieldName, OFTReal);
161
0
                                poFeatureDefn->AddFieldDefn(&oField);
162
0
                            }
163
0
                            offset += 1;
164
0
                            nCurrOff = 1;
165
0
                            break;
166
0
                        }
167
0
                        case SXF_RAT_TWOBYTE:
168
0
                        {
169
0
                            if (bAddField)
170
0
                            {
171
0
                                OGRFieldDefn oField(oFieldName, OFTReal);
172
0
                                poFeatureDefn->AddFieldDefn(&oField);
173
0
                            }
174
0
                            offset += 2;
175
0
                            nCurrOff = 2;
176
0
                            break;
177
0
                        }
178
0
                        case SXF_RAT_FOURBYTE:
179
0
                        {
180
0
                            if (bAddField)
181
0
                            {
182
0
                                OGRFieldDefn oField(oFieldName, OFTReal);
183
0
                                poFeatureDefn->AddFieldDefn(&oField);
184
0
                            }
185
0
                            offset += 4;
186
0
                            nCurrOff = 4;
187
0
                            break;
188
0
                        }
189
0
                        case SXF_RAT_EIGHTBYTE:
190
0
                        {
191
0
                            if (bAddField)
192
0
                            {
193
0
                                OGRFieldDefn oField(oFieldName, OFTReal);
194
0
                                poFeatureDefn->AddFieldDefn(&oField);
195
0
                            }
196
0
                            offset += 8;
197
0
                            nCurrOff = 8;
198
0
                            break;
199
0
                        }
200
0
                        case SXF_RAT_ANSI_WIN:
201
0
                        {
202
0
                            if (bAddField)
203
0
                            {
204
0
                                OGRFieldDefn oField(oFieldName, OFTString);
205
0
                                oField.SetWidth(255);
206
0
                                poFeatureDefn->AddFieldDefn(&oField);
207
0
                            }
208
0
                            unsigned nLen = unsigned(stAttrInfo.nScale) + 1;
209
0
                            offset += nLen;
210
0
                            nCurrOff = nLen;
211
0
                            break;
212
0
                        }
213
0
                        case SXF_RAT_UNICODE:
214
0
                        {
215
0
                            if (bAddField)
216
0
                            {
217
0
                                OGRFieldDefn oField(oFieldName, OFTString);
218
0
                                oField.SetWidth(255);
219
0
                                poFeatureDefn->AddFieldDefn(&oField);
220
0
                            }
221
0
                            unsigned nLen =
222
0
                                (unsigned(stAttrInfo.nScale) + 1) * 2;
223
0
                            offset += nLen;
224
0
                            nCurrOff = nLen;
225
0
                            break;
226
0
                        }
227
0
                        case SXF_RAT_BIGTEXT:
228
0
                        {
229
0
                            if (bAddField)
230
0
                            {
231
0
                                OGRFieldDefn oField(oFieldName, OFTString);
232
0
                                oField.SetWidth(1024);
233
0
                                poFeatureDefn->AddFieldDefn(&oField);
234
0
                            }
235
0
                            GUInt32 scale2 = 0;
236
0
                            VSIFReadL(&scale2, sizeof(GUInt32), 1, fpSXF);
237
0
                            CPL_LSBPTR32(&scale2);
238
239
0
                            offset += scale2;
240
0
                            nCurrOff = scale2;
241
0
                            break;
242
0
                        }
243
0
                        default:
244
0
                            break;
245
0
                    }
246
0
                }
247
0
                if (nCurrOff == 0)
248
0
                    break;
249
0
                VSIFSeekL(fpSXF, nCurrOff, SEEK_CUR);
250
0
            }
251
0
        }
252
0
        return true;
253
0
    }
254
255
0
    return false;
256
0
}
257
258
/************************************************************************/
259
/*                           SetNextByIndex()                           */
260
/************************************************************************/
261
262
OGRErr OGRSXFLayer::SetNextByIndex(GIntBig nIndex)
263
0
{
264
0
    m_bEOF = false;
265
0
    if (nIndex < 0 || nIndex > (long)mnRecordDesc.size())
266
0
    {
267
0
        m_bEOF = true;
268
0
        return OGRERR_NON_EXISTING_FEATURE;
269
0
    }
270
271
0
    oNextIt = mnRecordDesc.begin();
272
0
    std::advance(oNextIt, static_cast<size_t>(nIndex));
273
274
0
    return OGRERR_NONE;
275
0
}
276
277
/************************************************************************/
278
/*                             GetFeature()                             */
279
/************************************************************************/
280
281
OGRFeature *OGRSXFLayer::GetFeature(GIntBig nFID)
282
0
{
283
0
    const auto IT = mnRecordDesc.find(static_cast<long>(nFID));
284
0
    if (IT != mnRecordDesc.end())
285
0
    {
286
0
        VSIFSeekL(fpSXF, IT->second, SEEK_SET);
287
0
        OGRFeature *poFeature = GetNextRawFeature(IT->first);
288
0
        if (poFeature != nullptr && poFeature->GetGeometryRef() != nullptr &&
289
0
            GetSpatialRef() != nullptr)
290
0
        {
291
0
            poFeature->GetGeometryRef()->assignSpatialReference(
292
0
                GetSpatialRef());
293
0
        }
294
0
        return poFeature;
295
0
    }
296
297
0
    return nullptr;
298
0
}
299
300
/************************************************************************/
301
/*                           GetSpatialRef()                            */
302
/************************************************************************/
303
304
const OGRSpatialReference *OGRSXFLayer::GetSpatialRef() const
305
0
{
306
0
    return stSXFMapDescription.pSpatRef;
307
0
}
308
309
/************************************************************************/
310
/*                             IGetExtent()                             */
311
/************************************************************************/
312
313
OGRErr OGRSXFLayer::IGetExtent(int iGeomField, OGREnvelope *psExtent,
314
                               bool bForce)
315
0
{
316
0
    if (bForce)
317
0
    {
318
0
        return OGRLayer::IGetExtent(iGeomField, psExtent, bForce);
319
0
    }
320
0
    else
321
0
    {
322
0
        psExtent->MinX = stSXFMapDescription.Env.MinX;
323
0
        psExtent->MaxX = stSXFMapDescription.Env.MaxX;
324
0
        psExtent->MinY = stSXFMapDescription.Env.MinY;
325
0
        psExtent->MaxY = stSXFMapDescription.Env.MaxY;
326
327
0
        return OGRERR_NONE;
328
0
    }
329
0
}
330
331
/************************************************************************/
332
/*                          GetFeatureCount()                           */
333
/************************************************************************/
334
335
GIntBig OGRSXFLayer::GetFeatureCount(int bForce)
336
0
{
337
0
    if (m_poFilterGeom == nullptr && m_poAttrQuery == nullptr)
338
0
        return static_cast<int>(mnRecordDesc.size());
339
0
    else
340
0
        return OGRLayer::GetFeatureCount(bForce);
341
0
}
342
343
/************************************************************************/
344
/*                            ResetReading()                            */
345
/************************************************************************/
346
347
void OGRSXFLayer::ResetReading()
348
349
0
{
350
0
    m_bEOF = false;
351
0
    oNextIt = mnRecordDesc.begin();
352
0
}
353
354
/************************************************************************/
355
/*                           GetNextFeature()                           */
356
/************************************************************************/
357
358
OGRFeature *OGRSXFLayer::GetNextFeature()
359
0
{
360
0
    if (m_bEOF)
361
0
        return nullptr;
362
0
    CPLMutexHolderD(m_hIOMutex);
363
0
    while (oNextIt != mnRecordDesc.end())
364
0
    {
365
0
        VSIFSeekL(fpSXF, oNextIt->second, SEEK_SET);
366
0
        OGRFeature *poFeature = GetNextRawFeature(oNextIt->first);
367
368
0
        ++oNextIt;
369
370
0
        if (poFeature == nullptr)
371
0
            continue;
372
373
0
        if ((m_poFilterGeom == nullptr ||
374
0
             FilterGeometry(poFeature->GetGeometryRef())) &&
375
0
            (m_poAttrQuery == nullptr || m_poAttrQuery->Evaluate(poFeature)))
376
0
        {
377
0
            if (poFeature->GetGeometryRef() != nullptr &&
378
0
                GetSpatialRef() != nullptr)
379
0
            {
380
0
                poFeature->GetGeometryRef()->assignSpatialReference(
381
0
                    GetSpatialRef());
382
0
            }
383
384
0
            return poFeature;
385
0
        }
386
387
0
        delete poFeature;
388
0
    }
389
0
    return nullptr;
390
0
}
391
392
/************************************************************************/
393
/*                           TestCapability()                           */
394
/************************************************************************/
395
396
int OGRSXFLayer::TestCapability(const char *pszCap) const
397
398
0
{
399
0
    if (EQUAL(pszCap, OLCStringsAsUTF8) &&
400
0
        CPLCanRecode("test", "CP1251", CPL_ENC_UTF8) &&
401
0
        CPLCanRecode("test", "KOI8-R", CPL_ENC_UTF8))
402
0
        return TRUE;
403
0
    else if (EQUAL(pszCap, OLCRandomRead))
404
0
        return TRUE;
405
0
    else if (EQUAL(pszCap, OLCFastFeatureCount))
406
0
        return TRUE;
407
0
    else if (EQUAL(pszCap, OLCFastGetExtent))
408
0
        return TRUE;
409
0
    else if (EQUAL(pszCap, OLCFastSetNextByIndex))
410
0
        return TRUE;
411
0
    else if (EQUAL(pszCap, OLCZGeometries))
412
0
        return TRUE;
413
414
0
    return FALSE;
415
0
}
416
417
/************************************************************************/
418
/*                            TranslateXYH()                            */
419
/************************************************************************/
420
/****
421
 * TODO : Take into account information given in the passport
422
 * like unit of measurement, type and dimensions (integer, float, double) of
423
 * coordinate, the vector format, etc.
424
 */
425
426
GUInt32 OGRSXFLayer::TranslateXYH(const SXFRecordDescription &certifInfo,
427
                                  const char *psBuff, GUInt32 nBufLen,
428
                                  double *dfX, double *dfY, double *dfH)
429
0
{
430
    // Xp, Yp(м) = Xo, Yo(м) + (Xd, Yd / R * S), (1)
431
432
0
    int offset = 0;
433
0
    switch (certifInfo.eValType)
434
0
    {
435
0
        case SXF_VT_SHORT:
436
0
        {
437
0
            if (nBufLen < 4)
438
0
                return 0;
439
0
            GInt16 x = 0;
440
0
            GInt16 y = 0;
441
0
            memcpy(&y, psBuff, 2);
442
0
            CPL_LSBPTR16(&y);
443
0
            memcpy(&x, psBuff + 2, 2);
444
0
            CPL_LSBPTR16(&x);
445
446
0
            if (stSXFMapDescription.bIsRealCoordinates)
447
0
            {
448
0
                *dfX = (double)x;
449
0
                *dfY = (double)y;
450
0
            }
451
0
            else
452
0
            {
453
0
                if (m_nSXFFormatVer == 3)
454
0
                {
455
0
                    *dfX = stSXFMapDescription.dfXOr + (double)x * m_dfCoeff;
456
0
                    *dfY = stSXFMapDescription.dfYOr + (double)y * m_dfCoeff;
457
0
                }
458
0
                else if (m_nSXFFormatVer == 4)
459
0
                {
460
                    // TODO: check on real data
461
0
                    *dfX = stSXFMapDescription.dfXOr + (double)x * m_dfCoeff;
462
0
                    *dfY = stSXFMapDescription.dfYOr + (double)y * m_dfCoeff;
463
0
                }
464
0
            }
465
466
0
            offset += 4;
467
468
0
            if (dfH != nullptr)
469
0
            {
470
0
                if (nBufLen < 4 + 4)
471
0
                    return 0;
472
0
                float h = 0.0f;
473
0
                memcpy(&h, psBuff + 4, 4);  // H always in float
474
0
                CPL_LSBPTR32(&h);
475
0
                *dfH = (double)h;
476
477
0
                offset += 4;
478
0
            }
479
0
        }
480
0
        break;
481
0
        case SXF_VT_FLOAT:
482
0
        {
483
0
            if (nBufLen < 8)
484
0
                return 0;
485
0
            float y = 0.0f;
486
0
            memcpy(&y, psBuff, 4);
487
0
            CPL_LSBPTR32(&y);
488
0
            float x = 0.0f;
489
0
            memcpy(&x, psBuff + 4, 4);
490
0
            CPL_LSBPTR32(&x);
491
492
0
            if (stSXFMapDescription.bIsRealCoordinates)
493
0
            {
494
0
                *dfX = (double)x;
495
0
                *dfY = (double)y;
496
0
            }
497
0
            else
498
0
            {
499
0
                *dfX = stSXFMapDescription.dfXOr + (double)x * m_dfCoeff;
500
0
                *dfY = stSXFMapDescription.dfYOr + (double)y * m_dfCoeff;
501
0
            }
502
503
0
            offset += 8;
504
505
0
            if (dfH != nullptr)
506
0
            {
507
0
                if (nBufLen < 8 + 4)
508
0
                    return 0;
509
0
                float h = 0.0f;
510
0
                memcpy(&h, psBuff + 8, 4);  // H always in float
511
0
                CPL_LSBPTR32(&h);
512
0
                *dfH = (double)h;
513
514
0
                offset += 4;
515
0
            }
516
0
        }
517
0
        break;
518
0
        case SXF_VT_INT:
519
0
        {
520
0
            if (nBufLen < 8)
521
0
                return 0;
522
0
            GInt32 x, y;
523
0
            memcpy(&y, psBuff, 4);
524
0
            CPL_LSBPTR32(&y);
525
0
            memcpy(&x, psBuff + 4, 4);
526
0
            CPL_LSBPTR32(&x);
527
528
0
            if (stSXFMapDescription.bIsRealCoordinates)
529
0
            {
530
0
                *dfX = (double)x;
531
0
                *dfY = (double)y;
532
0
            }
533
0
            else
534
0
            {
535
                // TODO: check on real data
536
0
                if (m_nSXFFormatVer == 3)
537
0
                {
538
0
                    *dfX = stSXFMapDescription.dfXOr + (double)x * m_dfCoeff;
539
0
                    *dfY = stSXFMapDescription.dfYOr + (double)y * m_dfCoeff;
540
0
                }
541
0
                else if (m_nSXFFormatVer == 4)
542
0
                {
543
0
                    *dfX = stSXFMapDescription.dfXOr + (double)x * m_dfCoeff;
544
0
                    *dfY = stSXFMapDescription.dfYOr + (double)y * m_dfCoeff;
545
0
                }
546
0
            }
547
0
            offset += 8;
548
549
0
            if (dfH != nullptr)
550
0
            {
551
0
                if (nBufLen < 8 + 4)
552
0
                    return 0;
553
0
                float h = 0.0f;
554
0
                memcpy(&h, psBuff + 8, 4);  // H always in float
555
0
                CPL_LSBPTR32(&h);
556
0
                *dfH = (double)h;
557
558
0
                offset += 4;
559
0
            }
560
0
        }
561
0
        break;
562
0
        case SXF_VT_DOUBLE:
563
0
        {
564
0
            if (nBufLen < 16)
565
0
                return 0;
566
0
            double x = 0.0;
567
0
            double y = 0.0;
568
0
            memcpy(&y, psBuff, 8);
569
0
            CPL_LSBPTR64(&y);
570
0
            memcpy(&x, psBuff + 8, 8);
571
0
            CPL_LSBPTR64(&x);
572
573
0
            if (stSXFMapDescription.bIsRealCoordinates)
574
0
            {
575
0
                *dfX = x;
576
0
                *dfY = y;
577
0
            }
578
0
            else
579
0
            {
580
0
                *dfX = stSXFMapDescription.dfXOr + x * m_dfCoeff;
581
0
                *dfY = stSXFMapDescription.dfYOr + y * m_dfCoeff;
582
0
            }
583
584
0
            offset += 16;
585
586
0
            if (dfH != nullptr)
587
0
            {
588
0
                if (nBufLen < 16 + 8)
589
0
                    return 0;
590
0
                double h = 0.0;
591
0
                memcpy(&h, psBuff + 16, 8);  // H in double
592
0
                CPL_LSBPTR64(&h);
593
0
                *dfH = (double)h;
594
595
0
                offset += 8;
596
0
            }
597
0
        }
598
0
        break;
599
0
    };
600
601
0
    return offset;
602
0
}
603
604
/************************************************************************/
605
/*                         GetNextRawFeature()                          */
606
/************************************************************************/
607
608
OGRFeature *OGRSXFLayer::GetNextRawFeature(long nFID)
609
0
{
610
0
    SXFRecordHeader stRecordHeader;
611
0
    int nObjectRead = static_cast<int>(
612
0
        VSIFReadL(&stRecordHeader, sizeof(SXFRecordHeader), 1, fpSXF));
613
614
0
    if (nObjectRead != 1)
615
0
    {
616
0
        CPLError(CE_Failure, CPLE_FileIO, "SXF. Read record failed.");
617
0
        return nullptr;
618
0
    }
619
0
    CPL_LSBPTR32(&(stRecordHeader.nID));
620
0
    if (stRecordHeader.nID != IDSXFOBJ)
621
0
    {
622
0
        CPLError(CE_Failure, CPLE_FileIO, "SXF. Read record failed.");
623
0
        return nullptr;
624
0
    }
625
0
    CPL_LSBPTR32(&(stRecordHeader.nFullLength));
626
0
    CPL_LSBPTR32(&(stRecordHeader.nGeometryLength));
627
0
    CPL_LSBPTR32(&(stRecordHeader.nClassifyCode));
628
0
    CPL_LSBPTR16(&(stRecordHeader.anGroup[0]));
629
0
    CPL_LSBPTR16(&(stRecordHeader.anGroup[1]));
630
0
    CPL_LSBPTR32(&(stRecordHeader.nPointCount));
631
0
    CPL_LSBPTR16(&(stRecordHeader.nSubObjectCount));
632
0
    CPL_LSBPTR16(&(stRecordHeader.nPointCountSmall));
633
634
0
    SXFGeometryType eGeomType = SXF_GT_Unknown;
635
0
    GByte code = 0;
636
637
0
    if (m_nSXFFormatVer == 3)
638
0
    {
639
0
        if (CHECK_BIT(stRecordHeader.nRef[2], 3))
640
0
        {
641
0
            if (CHECK_BIT(stRecordHeader.nRef[2], 4))
642
0
            {
643
0
                code = 0x22;
644
0
                stRecordHeader.nSubObjectCount = 0;
645
0
            }
646
0
            else
647
0
            {
648
0
                code = 0x21;
649
0
                stRecordHeader.nSubObjectCount = 0;
650
0
            }
651
0
        }
652
0
        else
653
0
        {
654
0
            code = stRecordHeader.nRef[0] & 3;  // get first 2 bits
655
0
        }
656
0
    }
657
0
    else if (m_nSXFFormatVer == 4)
658
0
    {
659
0
        if (CHECK_BIT(stRecordHeader.nRef[2], 5))
660
0
        {
661
0
            stRecordHeader.nSubObjectCount = 0;
662
0
        }
663
664
        // check if vector
665
0
        code = stRecordHeader.nRef[0] & 15;  // get first 4 bits
666
0
        if (code == 0x04)                    // xxxx0100
667
0
        {
668
0
            code = 0x21;
669
0
            stRecordHeader.nSubObjectCount = 0;
670
            // if (CHECK_BIT(stRecordHeader.nRef[2], 5))
671
            //{
672
            //     code = 0x22;
673
            //     stRecordHeader.nSubObjectCount = 0;
674
            // }
675
            // else
676
            //{
677
            //     code = 0x21;
678
            //     stRecordHeader.nSubObjectCount = 0;
679
            // }
680
            // if (CHECK_BIT(stRecordHeader.nRef[2], 4))
681
            //{
682
            // }
683
            // else
684
            //{
685
            // }
686
0
        }
687
0
    }
688
689
0
    if (code == 0x00)  // xxxx0000
690
0
        eGeomType = SXF_GT_Line;
691
0
    else if (code == 0x01)  // xxxx0001
692
0
        eGeomType = SXF_GT_Polygon;
693
0
    else if (code == 0x02)  // xxxx0010
694
0
        eGeomType = SXF_GT_Point;
695
0
    else if (code == 0x03)  // xxxx0011
696
0
        eGeomType = SXF_GT_Text;
697
#ifdef not_possible_given_above_code /* see below code too if re-enabling this \
698
                                      */
699
    // beginning 4.0
700
    else if (code == 0x04)  // xxxx0100
701
    {
702
        CPLError(CE_Warning, CPLE_NotSupported, "SXF. Not support type.");
703
        eGeomType = SXF_GT_Vector;
704
    }
705
#endif
706
0
    else if (code == 0x05)  // xxxx0101
707
0
        eGeomType = SXF_GT_TextTemplate;
708
0
    else if (code == 0x21)
709
0
        eGeomType = SXF_GT_VectorAngle;
710
0
    else if (code == 0x22)
711
0
        eGeomType = SXF_GT_VectorScaled;
712
713
0
    bool bHasAttributes = CHECK_BIT(stRecordHeader.nRef[1], 1);
714
0
    bool bHasRefVector = CHECK_BIT(stRecordHeader.nRef[1], 3);
715
0
    if (bHasRefVector == true)
716
0
        CPLError(CE_Failure, CPLE_NotSupported,
717
0
                 "SXF. Parsing the vector of the tying not support.");
718
719
0
    SXFRecordDescription stCertInfo;
720
0
    if (stRecordHeader.nPointCountSmall == 65535)
721
0
    {
722
0
        stCertInfo.nPointCount = stRecordHeader.nPointCount;
723
0
    }
724
0
    else
725
0
    {
726
0
        stCertInfo.nPointCount = stRecordHeader.nPointCountSmall;
727
0
    }
728
0
    stCertInfo.nSubObjectCount = stRecordHeader.nSubObjectCount;
729
730
0
    bool bFloatType(false), bBigType(false);
731
0
    bool b3D(true);
732
0
    if (m_nSXFFormatVer == 3)
733
0
    {
734
0
        b3D = CHECK_BIT(stRecordHeader.nRef[2], 1);
735
0
        bFloatType = CHECK_BIT(stRecordHeader.nRef[2], 2);
736
0
        bBigType = CHECK_BIT(stRecordHeader.nRef[1], 2);
737
0
        stCertInfo.bHasTextSign = CHECK_BIT(stRecordHeader.nRef[2], 5);
738
0
    }
739
0
    else if (m_nSXFFormatVer == 4)
740
0
    {
741
0
        b3D = CHECK_BIT(stRecordHeader.nRef[2], 1);
742
0
        bFloatType = CHECK_BIT(stRecordHeader.nRef[2], 2);
743
0
        bBigType = CHECK_BIT(stRecordHeader.nRef[1], 2);
744
0
        stCertInfo.bHasTextSign = CHECK_BIT(stRecordHeader.nRef[2], 3);
745
0
    }
746
    // Else trouble.
747
748
0
    if (b3D)  // xxxxxx1x
749
0
        stCertInfo.bDim = 1;
750
0
    else
751
0
        stCertInfo.bDim = 0;
752
753
0
    if (bFloatType)
754
0
    {
755
0
        if (bBigType)
756
0
        {
757
0
            stCertInfo.eValType = SXF_VT_DOUBLE;
758
0
        }
759
0
        else
760
0
        {
761
0
            stCertInfo.eValType = SXF_VT_FLOAT;
762
0
        }
763
0
    }
764
0
    else
765
0
    {
766
0
        if (bBigType)
767
0
        {
768
0
            stCertInfo.eValType = SXF_VT_INT;
769
0
        }
770
0
        else
771
0
        {
772
0
            stCertInfo.eValType = SXF_VT_SHORT;
773
0
        }
774
0
    }
775
776
0
    stCertInfo.bFormat = CHECK_BIT(stRecordHeader.nRef[2], 0);
777
0
    stCertInfo.eGeomType = eGeomType;
778
779
0
    OGRFeature *poFeature = nullptr;
780
0
    if (stRecordHeader.nGeometryLength > 100 * 1024 * 1024)
781
0
        return nullptr;
782
0
    char *recordCertifBuf =
783
0
        (char *)VSI_MALLOC_VERBOSE(stRecordHeader.nGeometryLength);
784
0
    if (recordCertifBuf == nullptr)
785
0
        return nullptr;
786
0
    nObjectRead = static_cast<int>(
787
0
        VSIFReadL(recordCertifBuf, stRecordHeader.nGeometryLength, 1, fpSXF));
788
0
    if (nObjectRead != 1)
789
0
    {
790
0
        CPLError(CE_Failure, CPLE_FileIO, "SXF. Read geometry failed.");
791
0
        CPLFree(recordCertifBuf);
792
0
        return nullptr;
793
0
    }
794
795
0
    if (eGeomType == SXF_GT_Point)
796
0
        poFeature = TranslatePoint(stCertInfo, recordCertifBuf,
797
0
                                   stRecordHeader.nGeometryLength);
798
0
    else if (eGeomType == SXF_GT_Line || eGeomType == SXF_GT_VectorScaled)
799
0
        poFeature = TranslateLine(stCertInfo, recordCertifBuf,
800
0
                                  stRecordHeader.nGeometryLength);
801
0
    else if (eGeomType == SXF_GT_Polygon)
802
0
        poFeature = TranslatePolygon(stCertInfo, recordCertifBuf,
803
0
                                     stRecordHeader.nGeometryLength);
804
0
    else if (eGeomType == SXF_GT_Text)
805
0
        poFeature = TranslateText(stCertInfo, recordCertifBuf,
806
0
                                  stRecordHeader.nGeometryLength);
807
0
    else if (eGeomType == SXF_GT_VectorAngle)
808
0
    {
809
0
        poFeature = TranslateVetorAngle(stCertInfo, recordCertifBuf,
810
0
                                        stRecordHeader.nGeometryLength);
811
0
    }
812
#ifdef not_possible_given_above_code
813
    else if (eGeomType == SXF_GT_Vector)
814
    {
815
        CPLError(CE_Warning, CPLE_NotSupported,
816
                 "SXF. Geometry type Vector do not support.");
817
        CPLFree(recordCertifBuf);
818
        return NULL;
819
    }
820
#endif
821
0
    else if (eGeomType == SXF_GT_TextTemplate)  // TODO realize this
822
0
    {
823
0
        CPLError(CE_Warning, CPLE_NotSupported,
824
0
                 "SXF. Geometry type Text Template do not support.");
825
0
        CPLFree(recordCertifBuf);
826
0
        return nullptr;
827
0
    }
828
0
    else
829
0
    {
830
0
        CPLError(CE_Failure, CPLE_NotSupported,
831
0
                 "SXF. Unsupported geometry type.");
832
0
        CPLFree(recordCertifBuf);
833
0
        return nullptr;
834
0
    }
835
836
0
    if (poFeature == nullptr)
837
0
    {
838
0
        CPLFree(recordCertifBuf);
839
0
        return nullptr;
840
0
    }
841
842
0
    poFeature->SetField(sFIDColumn_, (int)nFID);
843
844
0
    poFeature->SetField("CLCODE", (int)stRecordHeader.nClassifyCode);
845
846
0
    CPLString szName = mnClassificators[stRecordHeader.nClassifyCode];
847
848
0
    if (szName.empty())
849
0
    {
850
0
        szName.Printf("%d", stRecordHeader.nClassifyCode);
851
0
    }
852
0
    poFeature->SetField("CLNAME", szName);
853
854
0
    poFeature->SetField("OBJECTNUMB", stRecordHeader.nSubObjectCount);
855
856
0
    if (bHasAttributes)
857
0
    {
858
0
        if (stRecordHeader.nFullLength < 32 ||
859
0
            stRecordHeader.nGeometryLength > stRecordHeader.nFullLength - 32)
860
0
        {
861
0
            CPLFree(recordCertifBuf);
862
0
            delete poFeature;
863
0
            return nullptr;
864
0
        }
865
0
        size_t nSemanticsSize =
866
0
            stRecordHeader.nFullLength - 32 - stRecordHeader.nGeometryLength;
867
0
        if (nSemanticsSize > 1024 * 1024)
868
0
        {
869
0
            CPLFree(recordCertifBuf);
870
0
            delete poFeature;
871
0
            return nullptr;
872
0
        }
873
0
        char *psSemanticsdBuf = (char *)VSI_MALLOC_VERBOSE(nSemanticsSize);
874
0
        if (psSemanticsdBuf == nullptr)
875
0
        {
876
0
            CPLFree(recordCertifBuf);
877
0
            delete poFeature;
878
0
            return nullptr;
879
0
        }
880
0
        char *psSemanticsdBufOrig = psSemanticsdBuf;
881
0
        nObjectRead = static_cast<int>(
882
0
            VSIFReadL(psSemanticsdBuf, nSemanticsSize, 1, fpSXF));
883
0
        if (nObjectRead == 1)
884
0
        {
885
0
            size_t offset = 0;
886
0
            double nVal = 0;
887
888
0
            while (offset + sizeof(SXFRecordAttributeInfo) < nSemanticsSize)
889
0
            {
890
0
                char *psSemanticsdBufBeg = psSemanticsdBuf + offset;
891
0
                SXFRecordAttributeInfo stAttInfo =
892
0
                    *reinterpret_cast<SXFRecordAttributeInfo *>(
893
0
                        psSemanticsdBufBeg);
894
0
                CPL_LSBPTR16(&(stAttInfo.nCode));
895
0
                offset += 4;
896
897
0
                CPLString oFieldName;
898
0
                oFieldName.Printf("SC_%d", stAttInfo.nCode);
899
900
0
                CPLString oFieldValue;
901
902
0
                SXFRecordAttributeType eType =
903
0
                    (SXFRecordAttributeType)stAttInfo.nType;
904
905
0
                switch (eType)
906
0
                {
907
0
                    case SXF_RAT_ASCIIZ_DOS:
908
0
                    {
909
0
                        unsigned nLen = unsigned(stAttInfo.nScale) + 1;
910
0
                        if (nLen > nSemanticsSize ||
911
0
                            nSemanticsSize - nLen < offset)
912
0
                        {
913
0
                            nSemanticsSize = 0;
914
0
                            break;
915
0
                        }
916
0
                        char *value = (char *)CPLMalloc(nLen);
917
0
                        memcpy(value, psSemanticsdBuf + offset, nLen);
918
0
                        value[nLen - 1] = 0;
919
0
                        char *pszRecoded =
920
0
                            CPLRecode(value, "CP866", CPL_ENC_UTF8);
921
0
                        poFeature->SetField(oFieldName, pszRecoded);
922
0
                        CPLFree(pszRecoded);
923
0
                        CPLFree(value);
924
925
0
                        offset += stAttInfo.nScale + 1;
926
0
                        break;
927
0
                    }
928
0
                    case SXF_RAT_ONEBYTE:
929
0
                    {
930
0
                        if (offset + sizeof(GByte) > nSemanticsSize)
931
0
                        {
932
0
                            nSemanticsSize = 0;
933
0
                            break;
934
0
                        }
935
0
                        GByte nTmpVal = 0;
936
0
                        memcpy(&nTmpVal, psSemanticsdBuf + offset,
937
0
                               sizeof(GByte));
938
0
                        nVal = double(nTmpVal) *
939
0
                               pow(10.0, (double)stAttInfo.nScale);
940
941
0
                        poFeature->SetField(oFieldName, nVal);
942
0
                        offset += 1;
943
0
                        break;
944
0
                    }
945
0
                    case SXF_RAT_TWOBYTE:
946
0
                    {
947
0
                        if (offset + sizeof(GInt16) > nSemanticsSize)
948
0
                        {
949
0
                            nSemanticsSize = 0;
950
0
                            break;
951
0
                        }
952
0
                        GInt16 nTmpVal = 0;
953
0
                        memcpy(&nTmpVal, psSemanticsdBuf + offset,
954
0
                               sizeof(GInt16));
955
0
                        nVal = double(CPL_LSBWORD16(nTmpVal)) *
956
0
                               pow(10.0, (double)stAttInfo.nScale);
957
958
0
                        poFeature->SetField(oFieldName, nVal);
959
0
                        offset += 2;
960
0
                        break;
961
0
                    }
962
0
                    case SXF_RAT_FOURBYTE:
963
0
                    {
964
0
                        if (offset + sizeof(GInt32) > nSemanticsSize)
965
0
                        {
966
0
                            nSemanticsSize = 0;
967
0
                            break;
968
0
                        }
969
0
                        GInt32 nTmpVal = 0;
970
0
                        memcpy(&nTmpVal, psSemanticsdBuf + offset,
971
0
                               sizeof(GInt32));
972
0
                        nVal = double(CPL_LSBWORD32(nTmpVal)) *
973
0
                               pow(10.0, (double)stAttInfo.nScale);
974
975
0
                        poFeature->SetField(oFieldName, nVal);
976
0
                        offset += 4;
977
0
                        break;
978
0
                    }
979
0
                    case SXF_RAT_EIGHTBYTE:
980
0
                    {
981
0
                        if (offset + sizeof(double) > nSemanticsSize)
982
0
                        {
983
0
                            nSemanticsSize = 0;
984
0
                            break;
985
0
                        }
986
0
                        double dfTmpVal = 0.0;
987
0
                        memcpy(&dfTmpVal, psSemanticsdBuf + offset,
988
0
                               sizeof(double));
989
0
                        CPL_LSBPTR64(&dfTmpVal);
990
0
                        const double d =
991
0
                            dfTmpVal * pow(10.0, (double)stAttInfo.nScale);
992
993
0
                        poFeature->SetField(oFieldName, d);
994
995
0
                        offset += 8;
996
0
                        break;
997
0
                    }
998
0
                    case SXF_RAT_ANSI_WIN:
999
0
                    {
1000
0
                        unsigned nLen = unsigned(stAttInfo.nScale) + 1;
1001
0
                        if (nLen > nSemanticsSize ||
1002
0
                            nSemanticsSize - nLen < offset)
1003
0
                        {
1004
0
                            nSemanticsSize = 0;
1005
0
                            break;
1006
0
                        }
1007
0
                        char *value = (char *)CPLMalloc(nLen);
1008
0
                        memcpy(value, psSemanticsdBuf + offset, nLen);
1009
0
                        value[nLen - 1] = 0;
1010
0
                        char *pszRecoded =
1011
0
                            CPLRecode(value, "CP1251", CPL_ENC_UTF8);
1012
0
                        poFeature->SetField(oFieldName, pszRecoded);
1013
0
                        CPLFree(pszRecoded);
1014
0
                        CPLFree(value);
1015
1016
0
                        offset += nLen;
1017
0
                        break;
1018
0
                    }
1019
0
                    case SXF_RAT_UNICODE:
1020
0
                    {
1021
0
                        uint64_t nLen64 =
1022
0
                            (static_cast<uint64_t>(stAttInfo.nScale) + 1) * 2;
1023
0
                        unsigned nLen = static_cast<unsigned>(nLen64);
1024
0
                        if (/* nLen < 2 || */ nLen64 > nSemanticsSize ||
1025
0
                            nSemanticsSize - nLen < offset)
1026
0
                        {
1027
0
                            nSemanticsSize = 0;
1028
0
                            break;
1029
0
                        }
1030
0
                        char *value = (char *)CPLMalloc(nLen);
1031
0
                        memcpy(value, psSemanticsdBuf + offset, nLen - 2);
1032
0
                        value[nLen - 1] = 0;
1033
0
                        value[nLen - 2] = 0;
1034
0
                        char *dst = (char *)CPLMalloc(nLen);
1035
0
                        int nCount = 0;
1036
0
                        for (int i = 0; (unsigned)i < nLen; i += 2)
1037
0
                        {
1038
0
                            unsigned char ucs = value[i];
1039
1040
0
                            if (ucs < 0x80U)
1041
0
                            {
1042
0
                                dst[nCount++] = ucs;
1043
0
                            }
1044
0
                            else
1045
0
                            {
1046
0
                                dst[nCount++] = 0xc0 | (ucs >> 6);
1047
0
                                dst[nCount++] = 0x80 | (ucs & 0x3F);
1048
0
                            }
1049
0
                        }
1050
1051
0
                        poFeature->SetField(oFieldName, dst);
1052
0
                        CPLFree(dst);
1053
0
                        CPLFree(value);
1054
1055
0
                        offset += nLen;
1056
0
                        break;
1057
0
                    }
1058
0
                    case SXF_RAT_BIGTEXT:
1059
0
                    {
1060
0
                        if (offset + sizeof(GUInt32) > nSemanticsSize)
1061
0
                        {
1062
0
                            nSemanticsSize = 0;
1063
0
                            break;
1064
0
                        }
1065
0
                        GUInt32 scale2 = 0;
1066
0
                        memcpy(&scale2, psSemanticsdBuf + offset,
1067
0
                               sizeof(GUInt32));
1068
0
                        CPL_LSBPTR32(&scale2);
1069
                        /* FIXME add ?: offset += sizeof(GUInt32); */
1070
0
                        if (scale2 > nSemanticsSize - 1 ||
1071
0
                            nSemanticsSize - (scale2 + 1) < offset)
1072
0
                        {
1073
0
                            nSemanticsSize = 0;
1074
0
                            break;
1075
0
                        }
1076
1077
0
                        char *value = (char *)CPLMalloc(scale2 + 1);
1078
0
                        memcpy(value, psSemanticsdBuf + offset, scale2 + 1);
1079
0
                        value[scale2] = 0;
1080
0
                        char *pszRecoded =
1081
0
                            CPLRecode(value, CPL_ENC_UTF16, CPL_ENC_UTF8);
1082
0
                        poFeature->SetField(oFieldName, pszRecoded);
1083
0
                        CPLFree(pszRecoded);
1084
0
                        CPLFree(value);
1085
1086
0
                        offset += scale2;
1087
0
                        break;
1088
0
                    }
1089
0
                    default:
1090
0
                        CPLFree(recordCertifBuf);
1091
0
                        CPLFree(psSemanticsdBufOrig);
1092
0
                        delete poFeature;
1093
0
                        return nullptr;
1094
0
                }
1095
0
            }
1096
0
        }
1097
0
        CPLFree(psSemanticsdBufOrig);
1098
0
    }
1099
1100
0
    poFeature->SetFID(nFID);
1101
1102
0
    CPLFree(recordCertifBuf);
1103
1104
0
    return poFeature;
1105
0
}
1106
1107
/************************************************************************/
1108
/*                         TranslatePoint   ()                          */
1109
/************************************************************************/
1110
1111
OGRFeature *OGRSXFLayer::TranslatePoint(const SXFRecordDescription &certifInfo,
1112
                                        const char *psRecordBuf,
1113
                                        GUInt32 nBufLen)
1114
0
{
1115
0
    double dfX = 1.0;
1116
0
    double dfY = 1.0;
1117
0
    double dfZ = 0.0;
1118
0
    GUInt32 nOffset = 0;
1119
0
    GUInt32 nDelta = 0;
1120
1121
0
    if (certifInfo.bDim == 1)
1122
0
    {
1123
0
        nDelta =
1124
0
            TranslateXYH(certifInfo, psRecordBuf, nBufLen, &dfX, &dfY, &dfZ);
1125
0
    }
1126
0
    else
1127
0
    {
1128
0
        nDelta = TranslateXYH(certifInfo, psRecordBuf, nBufLen, &dfX, &dfY);
1129
0
    }
1130
1131
0
    if (nDelta == 0)
1132
0
        return nullptr;
1133
0
    nOffset += nDelta;
1134
1135
    // OGRFeatureDefn *fd = poFeatureDefn->Clone();
1136
    // fd->SetGeomType( wkbMultiPoint );
1137
    //   OGRFeature *poFeature = new OGRFeature(fd);
1138
0
    OGRFeature *poFeature = new OGRFeature(poFeatureDefn);
1139
0
    OGRMultiPoint *poMPt = new OGRMultiPoint();
1140
1141
0
    poMPt->addGeometryDirectly(new OGRPoint(dfX, dfY, dfZ));
1142
1143
    /*---------------------- Reading SubObjects
1144
     * --------------------------------*/
1145
1146
0
    for (int count = 0; count < certifInfo.nSubObjectCount; count++)
1147
0
    {
1148
0
        if (nOffset + 4 > nBufLen)
1149
0
            break;
1150
1151
0
        GUInt16 nSubObj = 0;
1152
0
        memcpy(&nSubObj, psRecordBuf + nOffset, 2);
1153
0
        CPL_LSBPTR16(&nSubObj);
1154
1155
0
        GUInt16 nCoords = 0;
1156
0
        memcpy(&nCoords, psRecordBuf + nOffset + 2, 2);
1157
0
        CPL_LSBPTR16(&nCoords);
1158
1159
0
        nOffset += 4;
1160
1161
0
        for (int i = 0; i < nCoords; i++)
1162
0
        {
1163
0
            const char *psCoords = psRecordBuf + nOffset;
1164
1165
0
            if (certifInfo.bDim == 1)
1166
0
            {
1167
0
                nDelta = TranslateXYH(certifInfo, psCoords, nBufLen - nOffset,
1168
0
                                      &dfX, &dfY, &dfZ);
1169
0
            }
1170
0
            else
1171
0
            {
1172
0
                dfZ = 0.0;
1173
0
                nDelta = TranslateXYH(certifInfo, psCoords, nBufLen - nOffset,
1174
0
                                      &dfX, &dfY);
1175
0
            }
1176
1177
0
            if (nDelta == 0)
1178
0
                break;
1179
0
            nOffset += nDelta;
1180
1181
0
            poMPt->addGeometryDirectly(new OGRPoint(dfX, dfY, dfZ));
1182
0
        }
1183
0
    }
1184
1185
    /*****
1186
     * TODO :
1187
     *          - Translate graphics
1188
     *          - Translate 3D vector
1189
     */
1190
1191
0
    poFeature->SetGeometryDirectly(poMPt);
1192
1193
0
    return poFeature;
1194
0
}
1195
1196
/************************************************************************/
1197
/*                         TranslateLine    ()                          */
1198
/************************************************************************/
1199
1200
OGRFeature *OGRSXFLayer::TranslateLine(const SXFRecordDescription &certifInfo,
1201
                                       const char *psRecordBuf, GUInt32 nBufLen)
1202
0
{
1203
0
    double dfX = 1.0;
1204
0
    double dfY = 1.0;
1205
0
    double dfZ = 0.0;
1206
0
    GUInt32 nOffset = 0;
1207
1208
    // OGRFeatureDefn *fd = poFeatureDefn->Clone();
1209
    // fd->SetGeomType( wkbMultiLineString );
1210
    //   OGRFeature *poFeature = new OGRFeature(fd);
1211
1212
0
    OGRFeature *poFeature = new OGRFeature(poFeatureDefn);
1213
0
    OGRMultiLineString *poMLS = new OGRMultiLineString();
1214
1215
    /*---------------------- Reading Primary Line
1216
     * --------------------------------*/
1217
1218
0
    OGRLineString *poLS = new OGRLineString();
1219
1220
0
    for (GUInt32 count = 0; count < certifInfo.nPointCount; count++)
1221
0
    {
1222
0
        const char *psCoords = psRecordBuf + nOffset;
1223
1224
0
        GInt32 nDelta;
1225
0
        if (certifInfo.bDim == 1)
1226
0
        {
1227
0
            nDelta = TranslateXYH(certifInfo, psCoords, nBufLen - nOffset, &dfX,
1228
0
                                  &dfY, &dfZ);
1229
0
        }
1230
0
        else
1231
0
        {
1232
0
            dfZ = 0.0;
1233
0
            nDelta = TranslateXYH(certifInfo, psCoords, nBufLen - nOffset, &dfX,
1234
0
                                  &dfY);
1235
0
        }
1236
1237
0
        if (nDelta == 0)
1238
0
            break;
1239
0
        nOffset += nDelta;
1240
1241
0
        poLS->addPoint(dfX, dfY, dfZ);
1242
0
    }
1243
1244
0
    poMLS->addGeometry(poLS);
1245
1246
    /*---------------------- Reading Sub Lines
1247
     * --------------------------------*/
1248
1249
0
    for (GUInt16 count = 0; count < certifInfo.nSubObjectCount; count++)
1250
0
    {
1251
0
        poLS->empty();
1252
1253
0
        if (nOffset + 4 > nBufLen)
1254
0
            break;
1255
1256
0
        GUInt16 nSubObj = 0;
1257
0
        memcpy(&nSubObj, psRecordBuf + nOffset, 2);
1258
0
        CPL_LSBPTR16(&nSubObj);
1259
1260
0
        GUInt16 nCoords = 0;
1261
0
        memcpy(&nCoords, psRecordBuf + nOffset + 2, 2);
1262
0
        CPL_LSBPTR16(&nCoords);
1263
1264
0
        nOffset += 4;
1265
1266
0
        for (GUInt16 i = 0; i < nCoords; i++)
1267
0
        {
1268
0
            const char *psCoords = psRecordBuf + nOffset;
1269
0
            GInt32 nDelta;
1270
0
            if (certifInfo.bDim == 1)
1271
0
            {
1272
0
                nDelta = TranslateXYH(certifInfo, psCoords, nBufLen - nOffset,
1273
0
                                      &dfX, &dfY, &dfZ);
1274
0
            }
1275
0
            else
1276
0
            {
1277
0
                dfZ = 0.0;
1278
0
                nDelta = TranslateXYH(certifInfo, psCoords, nBufLen - nOffset,
1279
0
                                      &dfX, &dfY);
1280
0
            }
1281
1282
0
            if (nDelta == 0)
1283
0
                break;
1284
0
            nOffset += nDelta;
1285
1286
0
            poLS->addPoint(dfX, dfY, dfZ);
1287
0
        }
1288
1289
0
        poMLS->addGeometry(poLS);
1290
0
    }  // for
1291
1292
0
    delete poLS;
1293
0
    poFeature->SetGeometryDirectly(poMLS);
1294
1295
    /*****
1296
     * TODO :
1297
     *          - Translate graphics
1298
     *          - Translate 3D vector
1299
     */
1300
1301
0
    return poFeature;
1302
0
}
1303
1304
/************************************************************************/
1305
/*                        TranslateVetorAngle()                         */
1306
/************************************************************************/
1307
1308
OGRFeature *
1309
OGRSXFLayer::TranslateVetorAngle(const SXFRecordDescription &certifInfo,
1310
                                 const char *psRecordBuf, GUInt32 nBufLen)
1311
0
{
1312
0
    if (certifInfo.nPointCount != 2)
1313
0
    {
1314
0
        CPLError(CE_Failure, CPLE_NotSupported,
1315
0
                 "SXF. The vector object should have 2 points, but not.");
1316
0
        return nullptr;
1317
0
    }
1318
1319
0
    GUInt32 nOffset = 0;
1320
1321
0
    OGRFeature *poFeature = new OGRFeature(poFeatureDefn);
1322
0
    OGRPoint *poPT = new OGRPoint();
1323
1324
    /*---------------------- Reading Primary Line
1325
     * --------------------------------*/
1326
1327
0
    OGRLineString *poLS = new OGRLineString();
1328
1329
0
    for (GUInt32 count = 0; count < certifInfo.nPointCount; count++)
1330
0
    {
1331
0
        const char *psCoords = psRecordBuf + nOffset;
1332
1333
0
        double dfX = 1.0;
1334
0
        double dfY = 1.0;
1335
0
        double dfZ = 0.0;
1336
0
        GInt32 nDelta;
1337
0
        if (certifInfo.bDim == 1)
1338
0
        {
1339
0
            nDelta = TranslateXYH(certifInfo, psCoords, nBufLen - nOffset, &dfX,
1340
0
                                  &dfY, &dfZ);
1341
0
        }
1342
0
        else
1343
0
        {
1344
0
            dfZ = 0.0;
1345
0
            nDelta = TranslateXYH(certifInfo, psCoords, nBufLen - nOffset, &dfX,
1346
0
                                  &dfY);
1347
0
        }
1348
0
        if (nDelta == 0)
1349
0
            break;
1350
0
        nOffset += nDelta;
1351
1352
0
        poLS->addPoint(dfX, dfY, dfZ);
1353
0
    }
1354
1355
0
    poLS->StartPoint(poPT);
1356
1357
0
    OGRPoint *poAngPT = new OGRPoint();
1358
0
    poLS->EndPoint(poAngPT);
1359
1360
0
    const double xDiff = poPT->getX() - poAngPT->getX();
1361
0
    const double yDiff = poPT->getY() - poAngPT->getY();
1362
0
    double dfAngle = atan2(xDiff, yDiff) * TO_DEGREES - 90;
1363
0
    if (dfAngle < 0)
1364
0
        dfAngle += 360;
1365
1366
0
    poFeature->SetGeometryDirectly(poPT);
1367
0
    poFeature->SetField("ANGLE", dfAngle);
1368
1369
0
    delete poAngPT;
1370
0
    delete poLS;
1371
1372
0
    return poFeature;
1373
0
}
1374
1375
/************************************************************************/
1376
/*                         TranslatePolygon ()                          */
1377
/************************************************************************/
1378
1379
OGRFeature *
1380
OGRSXFLayer::TranslatePolygon(const SXFRecordDescription &certifInfo,
1381
                              const char *psRecordBuf, GUInt32 nBufLen)
1382
0
{
1383
0
    double dfX = 1.0;
1384
0
    double dfY = 1.0;
1385
0
    double dfZ = 0.0;
1386
0
    GUInt32 nOffset = 0;
1387
0
    GUInt32 nDelta = 0;
1388
1389
0
    OGRFeature *poFeature = new OGRFeature(poFeatureDefn);
1390
0
    OGRPolygon *poPoly = new OGRPolygon();
1391
0
    OGRLineString *poLS = new OGRLineString();
1392
1393
    /*---------------------- Reading Primary Polygon
1394
     * --------------------------------*/
1395
0
    for (GUInt32 count = 0; count < certifInfo.nPointCount; count++)
1396
0
    {
1397
0
        const char *psBuf = psRecordBuf + nOffset;
1398
0
        if (certifInfo.bDim == 1)
1399
0
        {
1400
0
            nDelta = TranslateXYH(certifInfo, psBuf, nBufLen - nOffset, &dfX,
1401
0
                                  &dfY, &dfZ);
1402
0
        }
1403
0
        else
1404
0
        {
1405
0
            dfZ = 0.0;
1406
0
            nDelta =
1407
0
                TranslateXYH(certifInfo, psBuf, nBufLen - nOffset, &dfX, &dfY);
1408
0
        }
1409
1410
0
        if (nDelta == 0)
1411
0
            break;
1412
0
        nOffset += nDelta;
1413
0
        poLS->addPoint(dfX, dfY, dfZ);
1414
0
    }  // for
1415
1416
0
    OGRLinearRing *poLR = new OGRLinearRing();
1417
0
    poLR->addSubLineString(poLS, 0);
1418
1419
0
    poPoly->addRingDirectly(poLR);
1420
1421
    /*---------------------- Reading Sub Lines
1422
     * --------------------------------*/
1423
1424
0
    for (int count = 0; count < certifInfo.nSubObjectCount; count++)
1425
0
    {
1426
0
        poLS->empty();
1427
1428
0
        if (nOffset + 4 > nBufLen)
1429
0
            break;
1430
1431
0
        GUInt16 nSubObj = 0;
1432
0
        memcpy(&nSubObj, psRecordBuf + nOffset, 2);
1433
0
        CPL_LSBPTR16(&nSubObj);
1434
1435
0
        GUInt16 nCoords = 0;
1436
0
        memcpy(&nCoords, psRecordBuf + nOffset + 2, 2);
1437
0
        CPL_LSBPTR16(&nCoords);
1438
1439
        // TODO: Is this really what the buffer size should be?
1440
0
        if (nCoords * nDelta != nBufLen - nOffset + 2 - 6)
1441
0
        {
1442
0
            CPLError(CE_Warning, CPLE_FileIO,
1443
0
                     "SXF raw feature size incorrect.  "
1444
0
                     "%d %d",
1445
0
                     nCoords * nDelta, nBufLen - nOffset + 2 - 6);
1446
            // TODO: How best to gracefully exit and report an issue?
1447
            // break; or cleanup and return NULL?
1448
0
        }
1449
1450
0
        nOffset += 4;
1451
1452
0
        for (int i = 0; i < nCoords; i++)
1453
0
        {
1454
0
            const char *psCoords = psRecordBuf + nOffset;
1455
0
            if (certifInfo.bDim == 1)
1456
0
            {
1457
0
                nDelta = TranslateXYH(certifInfo, psCoords, nBufLen - nOffset,
1458
0
                                      &dfX, &dfY, &dfZ);
1459
0
            }
1460
0
            else
1461
0
            {
1462
0
                dfZ = 0.0;
1463
0
                nDelta = TranslateXYH(certifInfo, psCoords, nBufLen - nOffset,
1464
0
                                      &dfX, &dfY);
1465
0
            }
1466
1467
0
            if (nDelta == 0)
1468
0
                break;
1469
0
            nOffset += nDelta;
1470
1471
0
            poLS->addPoint(dfX, dfY, dfZ);
1472
0
        }
1473
1474
0
        poLR = new OGRLinearRing();
1475
0
        poLR->addSubLineString(poLS, 0);
1476
1477
0
        poPoly->addRingDirectly(poLR);
1478
0
    }  // for
1479
1480
0
    poFeature->SetGeometryDirectly(poPoly);  // poLS);
1481
0
    delete poLS;
1482
1483
    /*****
1484
     * TODO :
1485
     *          - Translate graphics
1486
     *          - Translate 3D vector
1487
     */
1488
0
    return poFeature;
1489
0
}
1490
1491
/************************************************************************/
1492
/*                         TranslateText    ()                          */
1493
/************************************************************************/
1494
OGRFeature *OGRSXFLayer::TranslateText(const SXFRecordDescription &certifInfo,
1495
                                       const char *psRecordBuf, GUInt32 nBufLen)
1496
0
{
1497
0
    double dfX = 1.0;
1498
0
    double dfY = 1.0;
1499
0
    double dfZ = 0.0;
1500
0
    GUInt32 nOffset = 0;
1501
1502
0
    OGRFeature *poFeature = new OGRFeature(poFeatureDefn);
1503
0
    OGRMultiLineString *poMLS = new OGRMultiLineString();
1504
1505
    /*---------------------- Reading Primary Line
1506
     * --------------------------------*/
1507
1508
0
    OGRLineString *poLS = new OGRLineString();
1509
1510
0
    for (GUInt32 count = 0; count < certifInfo.nPointCount; count++)
1511
0
    {
1512
0
        const char *psCoords = psRecordBuf + nOffset;
1513
1514
0
        GUInt32 nDelta;
1515
0
        if (certifInfo.bDim == 1)
1516
0
        {
1517
0
            nDelta = TranslateXYH(certifInfo, psCoords, nBufLen - nOffset, &dfX,
1518
0
                                  &dfY, &dfZ);
1519
0
        }
1520
0
        else
1521
0
        {
1522
0
            dfZ = 0.0;
1523
0
            nDelta = TranslateXYH(certifInfo, psCoords, nBufLen - nOffset, &dfX,
1524
0
                                  &dfY);
1525
0
        }
1526
1527
0
        if (nDelta == 0)
1528
0
            break;
1529
0
        nOffset += nDelta;
1530
1531
0
        poLS->addPoint(dfX, dfY, dfZ);
1532
0
    }
1533
1534
0
    poMLS->addGeometry(poLS);
1535
1536
    /*------------------     READING TEXT VALUE
1537
     * --------------------------------*/
1538
0
    CPLString soText;
1539
1540
0
    if (certifInfo.bHasTextSign)
1541
0
    {
1542
0
        if (nOffset + 1 > nBufLen)
1543
0
            return poFeature;
1544
0
        const char *pszTxt = psRecordBuf + nOffset;
1545
0
        GByte nTextL = (GByte)*pszTxt;
1546
0
        if (nOffset + 1 + nTextL > nBufLen)
1547
0
            return poFeature;
1548
1549
0
        char *pszTextBuf = (char *)CPLMalloc(nTextL + 1);
1550
1551
0
        strncpy(pszTextBuf, (pszTxt + 1), nTextL);
1552
0
        pszTextBuf[nTextL] = '\0';
1553
1554
        // TODO: Check encoding from sxf
1555
0
        char *pszRecoded = CPLRecode(pszTextBuf, "CP1251", CPL_ENC_UTF8);
1556
0
        soText += pszRecoded;
1557
0
        CPLFree(pszRecoded);
1558
1559
0
        CPLFree(pszTextBuf);
1560
1561
0
        nOffset += nTextL + 2;
1562
0
    }
1563
1564
    /*---------------------- Reading Sub Lines
1565
     * --------------------------------*/
1566
1567
0
    for (int count = 0; count < certifInfo.nSubObjectCount; count++)
1568
0
    {
1569
0
        poLS->empty();
1570
1571
0
        if (nOffset + 4 > nBufLen)
1572
0
            break;
1573
1574
0
        GUInt16 nSubObj = 0;
1575
0
        memcpy(&nSubObj, psRecordBuf + nOffset, 2);
1576
0
        CPL_LSBPTR16(&nSubObj);
1577
1578
0
        GUInt16 nCoords = 0;
1579
0
        memcpy(&nCoords, psRecordBuf + nOffset + 2, 2);
1580
0
        CPL_LSBPTR16(&nCoords);
1581
1582
0
        nOffset += 4;
1583
1584
0
        for (int i = 0; i < nCoords; i++)
1585
0
        {
1586
0
            const char *psCoords = psRecordBuf + nOffset;
1587
0
            GUInt32 nDelta;
1588
0
            if (certifInfo.bDim == 1)
1589
0
            {
1590
0
                nDelta = TranslateXYH(certifInfo, psCoords, nBufLen - nOffset,
1591
0
                                      &dfX, &dfY, &dfZ);
1592
0
            }
1593
0
            else
1594
0
            {
1595
0
                dfZ = 0.0;
1596
0
                nDelta = TranslateXYH(certifInfo, psCoords, nBufLen - nOffset,
1597
0
                                      &dfX, &dfY);
1598
0
            }
1599
1600
0
            if (nDelta == 0)
1601
0
                break;
1602
0
            nOffset += nDelta;
1603
1604
0
            poLS->addPoint(dfX, dfY, dfZ);
1605
0
        }
1606
1607
0
        poMLS->addGeometry(poLS);
1608
1609
0
        if (certifInfo.bHasTextSign)
1610
0
        {
1611
0
            if (nOffset + 1 > nBufLen)
1612
0
                return poFeature;
1613
0
            const char *pszTxt = psRecordBuf + nOffset;
1614
0
            GByte nTextL = (GByte)*pszTxt;
1615
0
            if (nOffset + 1 + nTextL > nBufLen)
1616
0
                return poFeature;
1617
1618
0
            char *pszTextBuf = (char *)CPLMalloc(nTextL + 1);
1619
1620
0
            strncpy(pszTextBuf, (pszTxt + 1), nTextL);
1621
0
            pszTextBuf[nTextL] = '\0';
1622
1623
            // TODO: Check encoding from sxf
1624
0
            char *pszRecoded = CPLRecode(pszTextBuf, "CP1251", CPL_ENC_UTF8);
1625
0
            soText += " " + CPLString(pszRecoded);
1626
0
            CPLFree(pszRecoded);
1627
1628
0
            CPLFree(pszTextBuf);
1629
1630
0
            nOffset += nTextL + 2;
1631
0
        }
1632
0
    }  // for
1633
1634
0
    delete poLS;
1635
0
    poFeature->SetGeometryDirectly(poMLS);
1636
1637
0
    poFeature->SetField("TEXT", soText);
1638
0
    return poFeature;
1639
0
}
1640
1641
const char *OGRSXFLayer::GetFIDColumn() const
1642
0
{
1643
0
    return sFIDColumn_.c_str();
1644
0
}