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