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