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 : *(SXFRecordAttributeInfo *)psSemanticsdBufBeg;
886 2291 : CPL_LSBPTR16(&(stAttInfo.nCode));
887 2291 : offset += 4;
888 :
889 2291 : CPLString oFieldName;
890 2291 : oFieldName.Printf("SC_%d", stAttInfo.nCode);
891 :
892 2291 : CPLString oFieldValue;
893 :
894 2291 : SXFRecordAttributeType eType =
895 2291 : (SXFRecordAttributeType)stAttInfo.nType;
896 :
897 2291 : switch (eType)
898 : {
899 0 : case SXF_RAT_ASCIIZ_DOS:
900 : {
901 0 : unsigned nLen = unsigned(stAttInfo.nScale) + 1;
902 0 : if (nLen > nSemanticsSize ||
903 0 : nSemanticsSize - nLen < offset)
904 : {
905 0 : nSemanticsSize = 0;
906 0 : break;
907 : }
908 0 : char *value = (char *)CPLMalloc(nLen);
909 0 : memcpy(value, psSemanticsdBuf + offset, nLen);
910 0 : value[nLen - 1] = 0;
911 : char *pszRecoded =
912 0 : CPLRecode(value, "CP866", CPL_ENC_UTF8);
913 0 : poFeature->SetField(oFieldName, pszRecoded);
914 0 : CPLFree(pszRecoded);
915 0 : CPLFree(value);
916 :
917 0 : offset += stAttInfo.nScale + 1;
918 0 : break;
919 : }
920 0 : case SXF_RAT_ONEBYTE:
921 : {
922 0 : if (offset + sizeof(GByte) > nSemanticsSize)
923 : {
924 0 : nSemanticsSize = 0;
925 0 : break;
926 : }
927 0 : GByte nTmpVal = 0;
928 0 : memcpy(&nTmpVal, psSemanticsdBuf + offset,
929 : sizeof(GByte));
930 0 : nVal = double(nTmpVal) *
931 0 : pow(10.0, (double)stAttInfo.nScale);
932 :
933 0 : poFeature->SetField(oFieldName, nVal);
934 0 : offset += 1;
935 0 : break;
936 : }
937 914 : case SXF_RAT_TWOBYTE:
938 : {
939 914 : if (offset + sizeof(GInt16) > nSemanticsSize)
940 : {
941 0 : nSemanticsSize = 0;
942 0 : break;
943 : }
944 914 : GInt16 nTmpVal = 0;
945 914 : memcpy(&nTmpVal, psSemanticsdBuf + offset,
946 : sizeof(GInt16));
947 914 : nVal = double(CPL_LSBWORD16(nTmpVal)) *
948 914 : pow(10.0, (double)stAttInfo.nScale);
949 :
950 914 : poFeature->SetField(oFieldName, nVal);
951 914 : offset += 2;
952 914 : break;
953 : }
954 28 : case SXF_RAT_FOURBYTE:
955 : {
956 28 : if (offset + sizeof(GInt32) > nSemanticsSize)
957 : {
958 0 : nSemanticsSize = 0;
959 0 : break;
960 : }
961 28 : GInt32 nTmpVal = 0;
962 28 : memcpy(&nTmpVal, psSemanticsdBuf + offset,
963 : sizeof(GInt32));
964 28 : nVal = double(CPL_LSBWORD32(nTmpVal)) *
965 28 : pow(10.0, (double)stAttInfo.nScale);
966 :
967 28 : poFeature->SetField(oFieldName, nVal);
968 28 : offset += 4;
969 28 : break;
970 : }
971 340 : case SXF_RAT_EIGHTBYTE:
972 : {
973 340 : if (offset + sizeof(double) > nSemanticsSize)
974 : {
975 0 : nSemanticsSize = 0;
976 0 : break;
977 : }
978 340 : double dfTmpVal = 0.0;
979 340 : memcpy(&dfTmpVal, psSemanticsdBuf + offset,
980 : sizeof(double));
981 340 : CPL_LSBPTR64(&dfTmpVal);
982 : const double d =
983 340 : dfTmpVal * pow(10.0, (double)stAttInfo.nScale);
984 :
985 340 : poFeature->SetField(oFieldName, d);
986 :
987 340 : offset += 8;
988 340 : break;
989 : }
990 1009 : case SXF_RAT_ANSI_WIN:
991 : {
992 1009 : unsigned nLen = unsigned(stAttInfo.nScale) + 1;
993 1009 : if (nLen > nSemanticsSize ||
994 1009 : nSemanticsSize - nLen < offset)
995 : {
996 0 : nSemanticsSize = 0;
997 0 : break;
998 : }
999 1009 : char *value = (char *)CPLMalloc(nLen);
1000 1009 : memcpy(value, psSemanticsdBuf + offset, nLen);
1001 1009 : value[nLen - 1] = 0;
1002 : char *pszRecoded =
1003 1009 : CPLRecode(value, "CP1251", CPL_ENC_UTF8);
1004 1009 : poFeature->SetField(oFieldName, pszRecoded);
1005 1009 : CPLFree(pszRecoded);
1006 1009 : CPLFree(value);
1007 :
1008 1009 : offset += nLen;
1009 1009 : break;
1010 : }
1011 0 : case SXF_RAT_UNICODE:
1012 : {
1013 0 : uint64_t nLen64 =
1014 0 : (static_cast<uint64_t>(stAttInfo.nScale) + 1) * 2;
1015 0 : unsigned nLen = static_cast<unsigned>(nLen64);
1016 0 : if (/* nLen < 2 || */ nLen64 > nSemanticsSize ||
1017 0 : nSemanticsSize - nLen < offset)
1018 : {
1019 0 : nSemanticsSize = 0;
1020 0 : break;
1021 : }
1022 0 : char *value = (char *)CPLMalloc(nLen);
1023 0 : memcpy(value, psSemanticsdBuf + offset, nLen - 2);
1024 0 : value[nLen - 1] = 0;
1025 0 : value[nLen - 2] = 0;
1026 0 : char *dst = (char *)CPLMalloc(nLen);
1027 0 : int nCount = 0;
1028 0 : for (int i = 0; (unsigned)i < nLen; i += 2)
1029 : {
1030 0 : unsigned char ucs = value[i];
1031 :
1032 0 : if (ucs < 0x80U)
1033 : {
1034 0 : dst[nCount++] = ucs;
1035 : }
1036 : else
1037 : {
1038 0 : dst[nCount++] = 0xc0 | (ucs >> 6);
1039 0 : dst[nCount++] = 0x80 | (ucs & 0x3F);
1040 : }
1041 : }
1042 :
1043 0 : poFeature->SetField(oFieldName, dst);
1044 0 : CPLFree(dst);
1045 0 : CPLFree(value);
1046 :
1047 0 : offset += nLen;
1048 0 : break;
1049 : }
1050 0 : case SXF_RAT_BIGTEXT:
1051 : {
1052 0 : if (offset + sizeof(GUInt32) > nSemanticsSize)
1053 : {
1054 0 : nSemanticsSize = 0;
1055 0 : break;
1056 : }
1057 0 : GUInt32 scale2 = 0;
1058 0 : memcpy(&scale2, psSemanticsdBuf + offset,
1059 : sizeof(GUInt32));
1060 0 : CPL_LSBPTR32(&scale2);
1061 : /* FIXME add ?: offset += sizeof(GUInt32); */
1062 0 : if (scale2 > nSemanticsSize - 1 ||
1063 0 : nSemanticsSize - (scale2 + 1) < offset)
1064 : {
1065 0 : nSemanticsSize = 0;
1066 0 : break;
1067 : }
1068 :
1069 0 : char *value = (char *)CPLMalloc(scale2 + 1);
1070 0 : memcpy(value, psSemanticsdBuf + offset, scale2 + 1);
1071 0 : value[scale2] = 0;
1072 : char *pszRecoded =
1073 0 : CPLRecode(value, CPL_ENC_UTF16, CPL_ENC_UTF8);
1074 0 : poFeature->SetField(oFieldName, pszRecoded);
1075 0 : CPLFree(pszRecoded);
1076 0 : CPLFree(value);
1077 :
1078 0 : offset += scale2;
1079 0 : break;
1080 : }
1081 0 : default:
1082 0 : CPLFree(recordCertifBuf);
1083 0 : CPLFree(psSemanticsdBufOrig);
1084 0 : delete poFeature;
1085 0 : return nullptr;
1086 : }
1087 : }
1088 : }
1089 1548 : CPLFree(psSemanticsdBufOrig);
1090 : }
1091 :
1092 2377 : poFeature->SetFID(nFID);
1093 :
1094 2377 : CPLFree(recordCertifBuf);
1095 :
1096 2377 : return poFeature;
1097 : }
1098 :
1099 : /************************************************************************/
1100 : /* TranslatePoint () */
1101 : /************************************************************************/
1102 :
1103 323 : OGRFeature *OGRSXFLayer::TranslatePoint(const SXFRecordDescription &certifInfo,
1104 : const char *psRecordBuf,
1105 : GUInt32 nBufLen)
1106 : {
1107 323 : double dfX = 1.0;
1108 323 : double dfY = 1.0;
1109 323 : double dfZ = 0.0;
1110 323 : GUInt32 nOffset = 0;
1111 323 : GUInt32 nDelta = 0;
1112 :
1113 323 : if (certifInfo.bDim == 1)
1114 : {
1115 : nDelta =
1116 0 : TranslateXYH(certifInfo, psRecordBuf, nBufLen, &dfX, &dfY, &dfZ);
1117 : }
1118 : else
1119 : {
1120 323 : nDelta = TranslateXYH(certifInfo, psRecordBuf, nBufLen, &dfX, &dfY);
1121 : }
1122 :
1123 323 : if (nDelta == 0)
1124 0 : return nullptr;
1125 323 : nOffset += nDelta;
1126 :
1127 : // OGRFeatureDefn *fd = poFeatureDefn->Clone();
1128 : // fd->SetGeomType( wkbMultiPoint );
1129 : // OGRFeature *poFeature = new OGRFeature(fd);
1130 323 : OGRFeature *poFeature = new OGRFeature(poFeatureDefn);
1131 323 : OGRMultiPoint *poMPt = new OGRMultiPoint();
1132 :
1133 323 : poMPt->addGeometryDirectly(new OGRPoint(dfX, dfY, dfZ));
1134 :
1135 : /*---------------------- Reading SubObjects
1136 : * --------------------------------*/
1137 :
1138 323 : for (int count = 0; count < certifInfo.nSubObjectCount; count++)
1139 : {
1140 0 : if (nOffset + 4 > nBufLen)
1141 0 : break;
1142 :
1143 0 : GUInt16 nSubObj = 0;
1144 0 : memcpy(&nSubObj, psRecordBuf + nOffset, 2);
1145 0 : CPL_LSBPTR16(&nSubObj);
1146 :
1147 0 : GUInt16 nCoords = 0;
1148 0 : memcpy(&nCoords, psRecordBuf + nOffset + 2, 2);
1149 0 : CPL_LSBPTR16(&nCoords);
1150 :
1151 0 : nOffset += 4;
1152 :
1153 0 : for (int i = 0; i < nCoords; i++)
1154 : {
1155 0 : const char *psCoords = psRecordBuf + nOffset;
1156 :
1157 0 : if (certifInfo.bDim == 1)
1158 : {
1159 0 : nDelta = TranslateXYH(certifInfo, psCoords, nBufLen - nOffset,
1160 : &dfX, &dfY, &dfZ);
1161 : }
1162 : else
1163 : {
1164 0 : dfZ = 0.0;
1165 0 : nDelta = TranslateXYH(certifInfo, psCoords, nBufLen - nOffset,
1166 : &dfX, &dfY);
1167 : }
1168 :
1169 0 : if (nDelta == 0)
1170 0 : break;
1171 0 : nOffset += nDelta;
1172 :
1173 0 : poMPt->addGeometryDirectly(new OGRPoint(dfX, dfY, dfZ));
1174 : }
1175 : }
1176 :
1177 : /*****
1178 : * TODO :
1179 : * - Translate graphics
1180 : * - Translate 3D vector
1181 : */
1182 :
1183 323 : poFeature->SetGeometryDirectly(poMPt);
1184 :
1185 323 : return poFeature;
1186 : }
1187 :
1188 : /************************************************************************/
1189 : /* TranslateLine () */
1190 : /************************************************************************/
1191 :
1192 984 : OGRFeature *OGRSXFLayer::TranslateLine(const SXFRecordDescription &certifInfo,
1193 : const char *psRecordBuf, GUInt32 nBufLen)
1194 : {
1195 984 : double dfX = 1.0;
1196 984 : double dfY = 1.0;
1197 984 : double dfZ = 0.0;
1198 984 : GUInt32 nOffset = 0;
1199 :
1200 : // OGRFeatureDefn *fd = poFeatureDefn->Clone();
1201 : // fd->SetGeomType( wkbMultiLineString );
1202 : // OGRFeature *poFeature = new OGRFeature(fd);
1203 :
1204 984 : OGRFeature *poFeature = new OGRFeature(poFeatureDefn);
1205 984 : OGRMultiLineString *poMLS = new OGRMultiLineString();
1206 :
1207 : /*---------------------- Reading Primary Line
1208 : * --------------------------------*/
1209 :
1210 984 : OGRLineString *poLS = new OGRLineString();
1211 :
1212 29158 : for (GUInt32 count = 0; count < certifInfo.nPointCount; count++)
1213 : {
1214 28174 : const char *psCoords = psRecordBuf + nOffset;
1215 :
1216 : GInt32 nDelta;
1217 28174 : if (certifInfo.bDim == 1)
1218 : {
1219 0 : nDelta = TranslateXYH(certifInfo, psCoords, nBufLen - nOffset, &dfX,
1220 : &dfY, &dfZ);
1221 : }
1222 : else
1223 : {
1224 28174 : dfZ = 0.0;
1225 28174 : nDelta = TranslateXYH(certifInfo, psCoords, nBufLen - nOffset, &dfX,
1226 : &dfY);
1227 : }
1228 :
1229 28174 : if (nDelta == 0)
1230 0 : break;
1231 28174 : nOffset += nDelta;
1232 :
1233 28174 : poLS->addPoint(dfX, dfY, dfZ);
1234 : }
1235 :
1236 984 : poMLS->addGeometry(poLS);
1237 :
1238 : /*---------------------- Reading Sub Lines
1239 : * --------------------------------*/
1240 :
1241 984 : for (GUInt16 count = 0; count < certifInfo.nSubObjectCount; count++)
1242 : {
1243 0 : poLS->empty();
1244 :
1245 0 : if (nOffset + 4 > nBufLen)
1246 0 : break;
1247 :
1248 0 : GUInt16 nSubObj = 0;
1249 0 : memcpy(&nSubObj, psRecordBuf + nOffset, 2);
1250 0 : CPL_LSBPTR16(&nSubObj);
1251 :
1252 0 : GUInt16 nCoords = 0;
1253 0 : memcpy(&nCoords, psRecordBuf + nOffset + 2, 2);
1254 0 : CPL_LSBPTR16(&nCoords);
1255 :
1256 0 : nOffset += 4;
1257 :
1258 0 : for (GUInt16 i = 0; i < nCoords; i++)
1259 : {
1260 0 : const char *psCoords = psRecordBuf + nOffset;
1261 : GInt32 nDelta;
1262 0 : if (certifInfo.bDim == 1)
1263 : {
1264 0 : nDelta = TranslateXYH(certifInfo, psCoords, nBufLen - nOffset,
1265 : &dfX, &dfY, &dfZ);
1266 : }
1267 : else
1268 : {
1269 0 : dfZ = 0.0;
1270 0 : nDelta = TranslateXYH(certifInfo, psCoords, nBufLen - nOffset,
1271 : &dfX, &dfY);
1272 : }
1273 :
1274 0 : if (nDelta == 0)
1275 0 : break;
1276 0 : nOffset += nDelta;
1277 :
1278 0 : poLS->addPoint(dfX, dfY, dfZ);
1279 : }
1280 :
1281 0 : poMLS->addGeometry(poLS);
1282 : } // for
1283 :
1284 984 : delete poLS;
1285 984 : poFeature->SetGeometryDirectly(poMLS);
1286 :
1287 : /*****
1288 : * TODO :
1289 : * - Translate graphics
1290 : * - Translate 3D vector
1291 : */
1292 :
1293 984 : return poFeature;
1294 : }
1295 :
1296 : /************************************************************************/
1297 : /* TranslateVetorAngle() */
1298 : /************************************************************************/
1299 :
1300 : OGRFeature *
1301 420 : OGRSXFLayer::TranslateVetorAngle(const SXFRecordDescription &certifInfo,
1302 : const char *psRecordBuf, GUInt32 nBufLen)
1303 : {
1304 420 : if (certifInfo.nPointCount != 2)
1305 : {
1306 0 : CPLError(CE_Failure, CPLE_NotSupported,
1307 : "SXF. The vector object should have 2 points, but not.");
1308 0 : return nullptr;
1309 : }
1310 :
1311 420 : GUInt32 nOffset = 0;
1312 :
1313 420 : OGRFeature *poFeature = new OGRFeature(poFeatureDefn);
1314 420 : OGRPoint *poPT = new OGRPoint();
1315 :
1316 : /*---------------------- Reading Primary Line
1317 : * --------------------------------*/
1318 :
1319 420 : OGRLineString *poLS = new OGRLineString();
1320 :
1321 1260 : for (GUInt32 count = 0; count < certifInfo.nPointCount; count++)
1322 : {
1323 840 : const char *psCoords = psRecordBuf + nOffset;
1324 :
1325 840 : double dfX = 1.0;
1326 840 : double dfY = 1.0;
1327 840 : double dfZ = 0.0;
1328 : GInt32 nDelta;
1329 840 : if (certifInfo.bDim == 1)
1330 : {
1331 0 : nDelta = TranslateXYH(certifInfo, psCoords, nBufLen - nOffset, &dfX,
1332 : &dfY, &dfZ);
1333 : }
1334 : else
1335 : {
1336 840 : dfZ = 0.0;
1337 840 : nDelta = TranslateXYH(certifInfo, psCoords, nBufLen - nOffset, &dfX,
1338 : &dfY);
1339 : }
1340 840 : if (nDelta == 0)
1341 0 : break;
1342 840 : nOffset += nDelta;
1343 :
1344 840 : poLS->addPoint(dfX, dfY, dfZ);
1345 : }
1346 :
1347 420 : poLS->StartPoint(poPT);
1348 :
1349 420 : OGRPoint *poAngPT = new OGRPoint();
1350 420 : poLS->EndPoint(poAngPT);
1351 :
1352 420 : const double xDiff = poPT->getX() - poAngPT->getX();
1353 420 : const double yDiff = poPT->getY() - poAngPT->getY();
1354 420 : double dfAngle = atan2(xDiff, yDiff) * TO_DEGREES - 90;
1355 420 : if (dfAngle < 0)
1356 280 : dfAngle += 360;
1357 :
1358 420 : poFeature->SetGeometryDirectly(poPT);
1359 420 : poFeature->SetField("ANGLE", dfAngle);
1360 :
1361 420 : delete poAngPT;
1362 420 : delete poLS;
1363 :
1364 420 : return poFeature;
1365 : }
1366 :
1367 : /************************************************************************/
1368 : /* TranslatePolygon () */
1369 : /************************************************************************/
1370 :
1371 : OGRFeature *
1372 510 : OGRSXFLayer::TranslatePolygon(const SXFRecordDescription &certifInfo,
1373 : const char *psRecordBuf, GUInt32 nBufLen)
1374 : {
1375 510 : double dfX = 1.0;
1376 510 : double dfY = 1.0;
1377 510 : double dfZ = 0.0;
1378 510 : GUInt32 nOffset = 0;
1379 510 : GUInt32 nDelta = 0;
1380 :
1381 510 : OGRFeature *poFeature = new OGRFeature(poFeatureDefn);
1382 510 : OGRPolygon *poPoly = new OGRPolygon();
1383 510 : OGRLineString *poLS = new OGRLineString();
1384 :
1385 : /*---------------------- Reading Primary Polygon
1386 : * --------------------------------*/
1387 28991 : for (GUInt32 count = 0; count < certifInfo.nPointCount; count++)
1388 : {
1389 28481 : const char *psBuf = psRecordBuf + nOffset;
1390 28481 : if (certifInfo.bDim == 1)
1391 : {
1392 0 : nDelta = TranslateXYH(certifInfo, psBuf, nBufLen - nOffset, &dfX,
1393 : &dfY, &dfZ);
1394 : }
1395 : else
1396 : {
1397 28481 : dfZ = 0.0;
1398 : nDelta =
1399 28481 : TranslateXYH(certifInfo, psBuf, nBufLen - nOffset, &dfX, &dfY);
1400 : }
1401 :
1402 28481 : if (nDelta == 0)
1403 0 : break;
1404 28481 : nOffset += nDelta;
1405 28481 : poLS->addPoint(dfX, dfY, dfZ);
1406 : } // for
1407 :
1408 510 : OGRLinearRing *poLR = new OGRLinearRing();
1409 510 : poLR->addSubLineString(poLS, 0);
1410 :
1411 510 : poPoly->addRingDirectly(poLR);
1412 :
1413 : /*---------------------- Reading Sub Lines
1414 : * --------------------------------*/
1415 :
1416 542 : for (int count = 0; count < certifInfo.nSubObjectCount; count++)
1417 : {
1418 32 : poLS->empty();
1419 :
1420 32 : if (nOffset + 4 > nBufLen)
1421 0 : break;
1422 :
1423 32 : GUInt16 nSubObj = 0;
1424 32 : memcpy(&nSubObj, psRecordBuf + nOffset, 2);
1425 32 : CPL_LSBPTR16(&nSubObj);
1426 :
1427 32 : GUInt16 nCoords = 0;
1428 32 : memcpy(&nCoords, psRecordBuf + nOffset + 2, 2);
1429 32 : CPL_LSBPTR16(&nCoords);
1430 :
1431 : // TODO: Is this really what the buffer size should be?
1432 32 : if (nCoords * nDelta != nBufLen - nOffset + 2 - 6)
1433 : {
1434 0 : CPLError(CE_Warning, CPLE_FileIO,
1435 : "SXF raw feature size incorrect. "
1436 : "%d %d",
1437 0 : nCoords * nDelta, nBufLen - nOffset + 2 - 6);
1438 : // TODO: How best to gracefully exit and report an issue?
1439 : // break; or cleanup and return NULL?
1440 : }
1441 :
1442 32 : nOffset += 4;
1443 :
1444 480 : for (int i = 0; i < nCoords; i++)
1445 : {
1446 448 : const char *psCoords = psRecordBuf + nOffset;
1447 448 : if (certifInfo.bDim == 1)
1448 : {
1449 0 : nDelta = TranslateXYH(certifInfo, psCoords, nBufLen - nOffset,
1450 : &dfX, &dfY, &dfZ);
1451 : }
1452 : else
1453 : {
1454 448 : dfZ = 0.0;
1455 448 : nDelta = TranslateXYH(certifInfo, psCoords, nBufLen - nOffset,
1456 : &dfX, &dfY);
1457 : }
1458 :
1459 448 : if (nDelta == 0)
1460 0 : break;
1461 448 : nOffset += nDelta;
1462 :
1463 448 : poLS->addPoint(dfX, dfY, dfZ);
1464 : }
1465 :
1466 32 : poLR = new OGRLinearRing();
1467 32 : poLR->addSubLineString(poLS, 0);
1468 :
1469 32 : poPoly->addRingDirectly(poLR);
1470 : } // for
1471 :
1472 510 : poFeature->SetGeometryDirectly(poPoly); // poLS);
1473 510 : delete poLS;
1474 :
1475 : /*****
1476 : * TODO :
1477 : * - Translate graphics
1478 : * - Translate 3D vector
1479 : */
1480 510 : return poFeature;
1481 : }
1482 :
1483 : /************************************************************************/
1484 : /* TranslateText () */
1485 : /************************************************************************/
1486 140 : OGRFeature *OGRSXFLayer::TranslateText(const SXFRecordDescription &certifInfo,
1487 : const char *psRecordBuf, GUInt32 nBufLen)
1488 : {
1489 140 : double dfX = 1.0;
1490 140 : double dfY = 1.0;
1491 140 : double dfZ = 0.0;
1492 140 : GUInt32 nOffset = 0;
1493 :
1494 140 : OGRFeature *poFeature = new OGRFeature(poFeatureDefn);
1495 140 : OGRMultiLineString *poMLS = new OGRMultiLineString();
1496 :
1497 : /*---------------------- Reading Primary Line
1498 : * --------------------------------*/
1499 :
1500 140 : OGRLineString *poLS = new OGRLineString();
1501 :
1502 420 : for (GUInt32 count = 0; count < certifInfo.nPointCount; count++)
1503 : {
1504 280 : const char *psCoords = psRecordBuf + nOffset;
1505 :
1506 : GUInt32 nDelta;
1507 280 : if (certifInfo.bDim == 1)
1508 : {
1509 0 : nDelta = TranslateXYH(certifInfo, psCoords, nBufLen - nOffset, &dfX,
1510 : &dfY, &dfZ);
1511 : }
1512 : else
1513 : {
1514 280 : dfZ = 0.0;
1515 280 : nDelta = TranslateXYH(certifInfo, psCoords, nBufLen - nOffset, &dfX,
1516 : &dfY);
1517 : }
1518 :
1519 280 : if (nDelta == 0)
1520 0 : break;
1521 280 : nOffset += nDelta;
1522 :
1523 280 : poLS->addPoint(dfX, dfY, dfZ);
1524 : }
1525 :
1526 140 : poMLS->addGeometry(poLS);
1527 :
1528 : /*------------------ READING TEXT VALUE
1529 : * --------------------------------*/
1530 280 : CPLString soText;
1531 :
1532 140 : if (certifInfo.bHasTextSign)
1533 : {
1534 140 : if (nOffset + 1 > nBufLen)
1535 0 : return poFeature;
1536 140 : const char *pszTxt = psRecordBuf + nOffset;
1537 140 : GByte nTextL = (GByte)*pszTxt;
1538 140 : if (nOffset + 1 + nTextL > nBufLen)
1539 0 : return poFeature;
1540 :
1541 140 : char *pszTextBuf = (char *)CPLMalloc(nTextL + 1);
1542 :
1543 140 : strncpy(pszTextBuf, (pszTxt + 1), nTextL);
1544 140 : pszTextBuf[nTextL] = '\0';
1545 :
1546 : // TODO: Check encoding from sxf
1547 140 : char *pszRecoded = CPLRecode(pszTextBuf, "CP1251", CPL_ENC_UTF8);
1548 140 : soText += pszRecoded;
1549 140 : CPLFree(pszRecoded);
1550 :
1551 140 : CPLFree(pszTextBuf);
1552 :
1553 140 : nOffset += nTextL + 2;
1554 : }
1555 :
1556 : /*---------------------- Reading Sub Lines
1557 : * --------------------------------*/
1558 :
1559 140 : for (int count = 0; count < certifInfo.nSubObjectCount; count++)
1560 : {
1561 0 : poLS->empty();
1562 :
1563 0 : if (nOffset + 4 > nBufLen)
1564 0 : break;
1565 :
1566 0 : GUInt16 nSubObj = 0;
1567 0 : memcpy(&nSubObj, psRecordBuf + nOffset, 2);
1568 0 : CPL_LSBPTR16(&nSubObj);
1569 :
1570 0 : GUInt16 nCoords = 0;
1571 0 : memcpy(&nCoords, psRecordBuf + nOffset + 2, 2);
1572 0 : CPL_LSBPTR16(&nCoords);
1573 :
1574 0 : nOffset += 4;
1575 :
1576 0 : for (int i = 0; i < nCoords; i++)
1577 : {
1578 0 : const char *psCoords = psRecordBuf + nOffset;
1579 : GUInt32 nDelta;
1580 0 : if (certifInfo.bDim == 1)
1581 : {
1582 0 : nDelta = TranslateXYH(certifInfo, psCoords, nBufLen - nOffset,
1583 : &dfX, &dfY, &dfZ);
1584 : }
1585 : else
1586 : {
1587 0 : dfZ = 0.0;
1588 0 : nDelta = TranslateXYH(certifInfo, psCoords, nBufLen - nOffset,
1589 : &dfX, &dfY);
1590 : }
1591 :
1592 0 : if (nDelta == 0)
1593 0 : break;
1594 0 : nOffset += nDelta;
1595 :
1596 0 : poLS->addPoint(dfX, dfY, dfZ);
1597 : }
1598 :
1599 0 : poMLS->addGeometry(poLS);
1600 :
1601 0 : if (certifInfo.bHasTextSign)
1602 : {
1603 0 : if (nOffset + 1 > nBufLen)
1604 0 : return poFeature;
1605 0 : const char *pszTxt = psRecordBuf + nOffset;
1606 0 : GByte nTextL = (GByte)*pszTxt;
1607 0 : if (nOffset + 1 + nTextL > nBufLen)
1608 0 : return poFeature;
1609 :
1610 0 : char *pszTextBuf = (char *)CPLMalloc(nTextL + 1);
1611 :
1612 0 : strncpy(pszTextBuf, (pszTxt + 1), nTextL);
1613 0 : pszTextBuf[nTextL] = '\0';
1614 :
1615 : // TODO: Check encoding from sxf
1616 0 : char *pszRecoded = CPLRecode(pszTextBuf, "CP1251", CPL_ENC_UTF8);
1617 0 : soText += " " + CPLString(pszRecoded);
1618 0 : CPLFree(pszRecoded);
1619 :
1620 0 : CPLFree(pszTextBuf);
1621 :
1622 0 : nOffset += nTextL + 2;
1623 : }
1624 : } // for
1625 :
1626 140 : delete poLS;
1627 140 : poFeature->SetGeometryDirectly(poMLS);
1628 :
1629 140 : poFeature->SetField("TEXT", soText);
1630 140 : return poFeature;
1631 : }
1632 :
1633 297 : const char *OGRSXFLayer::GetFIDColumn()
1634 : {
1635 297 : return sFIDColumn_.c_str();
1636 : }
|