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