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