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