1 : /******************************************************************************
2 : * $Id: vfkdatablock.cpp 22873 2011-08-06 20:33:55Z rouault $
3 : *
4 : * Project: VFK Reader - Data block definition
5 : * Purpose: Implements VFKDataBlock class.
6 : * Author: Martin Landa, landa.martin gmail.com
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2009-2010, Martin Landa <landa.martin gmail.com>
10 : *
11 : * Permission is hereby granted, free of charge, to any person
12 : * obtaining a copy of this software and associated documentation
13 : * files (the "Software"), to deal in the Software without
14 : * restriction, including without limitation the rights to use, copy,
15 : * modify, merge, publish, distribute, sublicense, and/or sell copies
16 : * of the Software, and to permit persons to whom the Software is
17 : * furnished to do so, subject to the following conditions:
18 : *
19 : * The above copyright notice and this permission notice shall be
20 : * included in all copies or substantial portions of the Software.
21 : *
22 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 : * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 : * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 : * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
26 : * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
27 : * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
28 : * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29 : * SOFTWARE.
30 : ****************************************************************************/
31 :
32 : #include <ctime>
33 :
34 : #include "vfkreader.h"
35 : #include "vfkreaderp.h"
36 :
37 : #include "cpl_conv.h"
38 : #include "cpl_error.h"
39 :
40 : /*!
41 : \brief VFK Data Block constructor
42 :
43 : \param pszName data block name
44 : */
45 61 : VFKDataBlock::VFKDataBlock(const char *pszName, const IVFKReader *poReader)
46 : {
47 61 : m_pszName = CPLStrdup(pszName);
48 :
49 61 : m_nPropertyCount = 0;
50 61 : m_papoProperty = NULL;
51 :
52 61 : m_nFeatureCount = 0;
53 61 : m_papoFeature = NULL;
54 :
55 61 : m_iNextFeature = -1;
56 :
57 61 : m_nGeometryType = wkbUnknown;
58 61 : m_bGeometry = FALSE; /* geometry is not loaded by default */
59 61 : m_bGeometryPerBlock = TRUE; /* load geometry per block/feature */
60 :
61 61 : m_nFID = 0;
62 :
63 61 : m_poReader = (IVFKReader *) poReader;
64 61 : }
65 :
66 : /*!
67 : \brief VFKDataBlock destructor
68 : */
69 61 : VFKDataBlock::~VFKDataBlock()
70 : {
71 61 : CPLFree(m_pszName);
72 :
73 636 : for (int i = 0; i < m_nPropertyCount; i++) {
74 575 : if (m_papoProperty[i])
75 575 : delete m_papoProperty[i];
76 : }
77 61 : CPLFree(m_papoProperty);
78 :
79 114 : for (int i = 0; i < m_nFeatureCount; i++) {
80 53 : if (m_papoFeature[i])
81 53 : delete m_papoFeature[i];
82 : }
83 61 : CPLFree(m_papoFeature);
84 61 : }
85 :
86 : /*!
87 : \brief Get property definition
88 :
89 : \param iIndex property index
90 :
91 : \return pointer to VFKPropertyDefn definition
92 : \return NULL on failure
93 : */
94 1047 : VFKPropertyDefn *VFKDataBlock::GetProperty(int iIndex) const
95 : {
96 1047 : if(iIndex < 0 || iIndex >= m_nPropertyCount)
97 0 : return NULL;
98 :
99 1047 : return m_papoProperty[iIndex];
100 : }
101 :
102 : /*!
103 : \brief Set properties
104 :
105 : \param poLine pointer to line
106 :
107 : \return number of added properties
108 : */
109 61 : int VFKDataBlock::SetProperties(char *poLine)
110 : {
111 : char *poChar;
112 : char *pszName, *poProp, *pszType;
113 : int nLength;
114 :
115 61 : pszName = pszType = NULL;
116 :
117 : /* skip data block name */
118 61 : for (poChar = poLine; *poChar != '0' && *poChar != ';'; poChar++)
119 : ;
120 61 : if (*poChar == '\0')
121 0 : return 0;
122 :
123 61 : poChar++;
124 :
125 : /* read property name/type */
126 61 : poProp = poChar;
127 61 : nLength = 0;
128 7228 : while(*poChar != '\0' && !(*poChar == '\r' && *(poChar+1) == '\n')) {
129 7106 : if (*poChar == ' ') {
130 575 : pszName = (char *) CPLRealloc(pszName, nLength + 1);
131 575 : strncpy(pszName, poProp, nLength);
132 575 : pszName[nLength] = '\0';
133 :
134 575 : poProp = ++poChar;
135 575 : nLength = 0;
136 : }
137 6531 : else if (*poChar == ';') {
138 514 : pszType = (char *) CPLRealloc(pszType, nLength + 1);
139 514 : strncpy(pszType, poProp, nLength);
140 514 : pszType[nLength] = '\0';
141 :
142 : /* add property */
143 514 : if (pszName && *pszName != '\0' &&
144 : pszType && *pszType != '\0')
145 514 : AddProperty(pszName, pszType);
146 :
147 514 : poProp = ++poChar;
148 514 : nLength = 0;
149 : }
150 7106 : poChar++;
151 7106 : nLength++;
152 : }
153 :
154 61 : pszType = (char *) CPLRealloc(pszType, nLength + 1);
155 61 : strncpy(pszType, poProp, nLength);
156 61 : pszType[nLength] = '\0';
157 :
158 : /* add property */
159 61 : if (pszName && *pszName != '\0' &&
160 : pszType && *pszType != '\0')
161 61 : AddProperty(pszName, pszType);
162 :
163 61 : CPLFree(pszName);
164 61 : CPLFree(pszType);
165 :
166 61 : return 0;
167 : }
168 :
169 : /*!
170 : \brief Add data block property
171 :
172 : \param pszName property name
173 : \param pszType property type
174 :
175 : \return number of properties
176 : */
177 575 : int VFKDataBlock::AddProperty(const char *pszName, const char *pszType)
178 : {
179 575 : VFKPropertyDefn *poNewProperty = new VFKPropertyDefn(pszName, pszType);
180 :
181 575 : m_nPropertyCount++;
182 :
183 : m_papoProperty = (VFKPropertyDefn **)
184 575 : CPLRealloc(m_papoProperty, sizeof (VFKPropertyDefn *) * m_nPropertyCount);
185 575 : m_papoProperty[m_nPropertyCount-1] = poNewProperty;
186 :
187 575 : return m_nPropertyCount;
188 : }
189 :
190 : /*!
191 : \brief Set number of features per data block
192 :
193 : \param nNewCount number of features
194 : \param bIncrement increment current value
195 : */
196 0 : void VFKDataBlock::SetFeatureCount(int nNewCount, int bIncrement)
197 : {
198 0 : if (bIncrement) {
199 0 : m_nFeatureCount += nNewCount;
200 : }
201 : else {
202 0 : m_nFeatureCount = nNewCount;
203 : }
204 0 : }
205 :
206 : /*!
207 : \brief Add feature
208 :
209 : \param pszLine pointer to line containing feature definition
210 : */
211 53 : int VFKDataBlock::AddFeature(const char *poLine)
212 : {
213 : int iIndex, nLength;
214 : const char *poChar, *poProp;
215 : char* pszProp;
216 : bool inString;
217 :
218 : VFKFeature *poNewFeature;
219 :
220 53 : poNewFeature = new VFKFeature(this);
221 53 : pszProp = NULL;
222 :
223 : /* set feature properties */
224 318 : for (poChar = poLine; *poChar != '\0' && *poChar != ';'; poChar++)
225 : /* skip data block name */
226 : ;
227 53 : if (poChar == '\0')
228 0 : return m_nFeatureCount;
229 :
230 53 : poChar++;
231 :
232 53 : poProp = poChar;
233 53 : iIndex = 0;
234 53 : nLength = 0;
235 53 : inString = FALSE;
236 3753 : while(*poChar != '\0' && !(*poChar == '\r' && *(poChar+1) == '\n')) {
237 3648 : if (*poChar == '"' &&
238 : (*(poChar-1) == ';' || *(poChar+1) == ';' || *(poChar+1) == '\r')) {
239 177 : poChar++; /* skip '"' */
240 177 : inString = inString ? FALSE : TRUE;
241 177 : if (inString) {
242 109 : poProp = poChar;
243 109 : if (*poChar == '"') {
244 41 : poChar++;
245 41 : inString = FALSE;
246 : }
247 : }
248 177 : if (*poChar == '\r' && *(poChar+1) == '\n')
249 1 : break;
250 : }
251 4246 : if (*poChar == ';' && !inString) {
252 599 : pszProp = (char *) CPLRealloc(pszProp, nLength + 1);
253 599 : if (nLength > 0)
254 445 : strncpy(pszProp, poProp, nLength);
255 599 : pszProp[nLength] = '\0';
256 599 : poNewFeature->SetProperty(iIndex, pszProp);
257 :
258 599 : iIndex++;
259 599 : poProp = ++poChar;
260 599 : nLength = 0;
261 : }
262 : else {
263 3048 : poChar++;
264 3048 : nLength++;
265 : }
266 : }
267 : /* append last property */
268 53 : pszProp = (char *) CPLRealloc(pszProp, nLength + 1);
269 53 : if (nLength > 0)
270 27 : strncpy(pszProp, poProp, nLength);
271 53 : pszProp[nLength] = '\0';
272 53 : poNewFeature->SetProperty(iIndex, pszProp);
273 :
274 : /* set fid */
275 53 : if (EQUAL(m_pszName, "SBP")) {
276 : int id;
277 : const VFKProperty *poVfkProperty;
278 :
279 26 : poVfkProperty = poNewFeature->GetProperty("PORADOVE_CISLO_BODU");
280 26 : id = poVfkProperty->GetValueI();
281 26 : if (id == 1)
282 13 : poNewFeature->SetFID(0); /* set next feature */
283 : else
284 13 : poNewFeature->SetFID(-1); /* set same feature */
285 : }
286 : else {
287 27 : poNewFeature->SetFID(0); /* set next feature */
288 : }
289 53 : SetMaxFID(poNewFeature->GetFID()); /* update max value */
290 :
291 : /* add feature */
292 53 : m_nFeatureCount++;
293 :
294 : m_papoFeature = (VFKFeature **)
295 53 : CPLRealloc(m_papoFeature, sizeof (VFKFeature *) * m_nFeatureCount);
296 53 : m_papoFeature[m_nFeatureCount-1] = poNewFeature;
297 :
298 53 : CPLFree(pszProp);
299 :
300 53 : return m_nFeatureCount;
301 : }
302 :
303 : /*!
304 : \brief Reset reading
305 :
306 : \param iIdx force index
307 : */
308 7 : void VFKDataBlock::ResetReading(int iIdx)
309 : {
310 7 : if (iIdx > -1) {
311 0 : m_iNextFeature = iIdx;
312 : }
313 : else {
314 7 : m_iNextFeature = 0;
315 : }
316 7 : }
317 :
318 : /*!
319 : \brief Get next feature
320 :
321 : \return pointer to VFKFeature instance
322 : \return NULL on error
323 : */
324 15 : VFKFeature *VFKDataBlock::GetNextFeature()
325 : {
326 15 : if (m_bGeometryPerBlock && !m_bGeometry) {
327 1 : LoadGeometry();
328 : }
329 :
330 15 : if (m_iNextFeature < 0)
331 0 : ResetReading();
332 :
333 15 : if (m_iNextFeature < 0 || m_iNextFeature >= m_nFeatureCount)
334 1 : return NULL;
335 :
336 14 : return m_papoFeature[m_iNextFeature++];
337 : }
338 :
339 : /*!
340 : \brief Get previous feature
341 :
342 : \return pointer to VFKFeature instance
343 : \return NULL on error
344 : */
345 0 : VFKFeature *VFKDataBlock::GetPreviousFeature()
346 : {
347 0 : if (m_bGeometryPerBlock && !m_bGeometry) {
348 0 : LoadGeometry();
349 : }
350 :
351 0 : if (m_iNextFeature < 0)
352 0 : ResetReading();
353 :
354 0 : if (m_iNextFeature < 0 || m_iNextFeature >= m_nFeatureCount)
355 0 : return NULL;
356 :
357 0 : return m_papoFeature[m_iNextFeature--];
358 : }
359 :
360 : /*!
361 : \brief Get first feature
362 :
363 : \return pointer to VFKFeature instance
364 : \return NULL on error
365 : */
366 0 : VFKFeature *VFKDataBlock::GetFirstFeature()
367 : {
368 0 : if (m_bGeometryPerBlock && !m_bGeometry) {
369 0 : LoadGeometry();
370 : }
371 :
372 0 : if (m_nFeatureCount < 1)
373 0 : return NULL;
374 :
375 0 : return m_papoFeature[0];
376 : }
377 :
378 : /*!
379 : \brief Get last feature
380 :
381 : \return pointer to VFKFeature instance
382 : \return NULL on error
383 : */
384 0 : VFKFeature *VFKDataBlock::GetLastFeature()
385 : {
386 0 : if (m_bGeometryPerBlock && !m_bGeometry) {
387 0 : LoadGeometry();
388 : }
389 :
390 0 : if (m_nFeatureCount < 1)
391 0 : return NULL;
392 :
393 0 : return m_papoFeature[m_nFeatureCount-1];
394 : }
395 :
396 : /*!
397 : \brief Get property index by name
398 :
399 : \param pszName property name
400 :
401 : \return property index
402 : \return -1 on error (property name not found)
403 : */
404 37 : int VFKDataBlock::GetPropertyIndex(const char *pszName) const
405 : {
406 310 : for (int i = 0; i < m_nPropertyCount; i++)
407 310 : if (EQUAL(pszName,m_papoProperty[i]->GetName()))
408 37 : return i;
409 :
410 0 : return -1;
411 : }
412 :
413 : /*!
414 : \brief Set geometry type (point, linestring, polygon)
415 :
416 : \return geometry type
417 : */
418 61 : OGRwkbGeometryType VFKDataBlock::SetGeometryType()
419 : {
420 61 : m_nGeometryType = wkbNone; /* pure attribute records */
421 :
422 67 : if (EQUAL (m_pszName, "SOBR") ||
423 : EQUAL (m_pszName, "OBBP") ||
424 : EQUAL (m_pszName, "SPOL") ||
425 : EQUAL (m_pszName, "OB") ||
426 : EQUAL (m_pszName, "OP") ||
427 : EQUAL (m_pszName, "OBPEJ"))
428 6 : m_nGeometryType = wkbPoint;
429 :
430 58 : else if (EQUAL (m_pszName, "SBP") ||
431 : EQUAL (m_pszName, "HP") ||
432 : EQUAL (m_pszName, "DPM"))
433 3 : m_nGeometryType = wkbLineString;
434 :
435 52 : else if (EQUAL (m_pszName, "PAR") ||
436 : EQUAL (m_pszName, "BUD"))
437 2 : m_nGeometryType = wkbPolygon;
438 :
439 61 : return m_nGeometryType;
440 : }
441 :
442 : /*!
443 : \brief Get geometry type
444 :
445 : \return geometry type
446 : */
447 114 : OGRwkbGeometryType VFKDataBlock::GetGeometryType() const
448 : {
449 114 : return m_nGeometryType;
450 : }
451 :
452 : /*!
453 : \brief Get vfkfeature
454 :
455 : \param iIndex feature index
456 :
457 : \return pointer to VFKFeature definition
458 : \return NULL on failure
459 : */
460 274 : VFKFeature *VFKDataBlock::GetFeatureByIndex(int iIndex) const
461 : {
462 274 : if(iIndex < 0 || iIndex >= m_nFeatureCount)
463 0 : return NULL;
464 :
465 274 : return m_papoFeature[iIndex];
466 : }
467 :
468 : /*!
469 : \brief Get first vfkfeature based on properties
470 :
471 : Note: modifies next feature.
472 :
473 : \param idx property index
474 : \param value property value
475 : \param poList list of features (NULL to loop all features)
476 :
477 : \return pointer to VFKFeature definition
478 : \return NULL on failure (not found)
479 : */
480 39 : VFKFeature *VFKDataBlock::GetFeature(int idx, int value, VFKFeatureList *poList)
481 : {
482 : int iPropertyValue;
483 : VFKFeature *poVfkFeature;
484 :
485 39 : if (poList) {
486 13 : for (VFKFeatureList::iterator i = poList->begin(), e = poList->end();
487 : i != e; ++i) {
488 13 : poVfkFeature = *i;
489 13 : iPropertyValue = poVfkFeature->GetProperty(idx)->GetValueI();
490 13 : if (iPropertyValue == value) {
491 13 : poList->erase(i); /* ??? */
492 13 : return poVfkFeature;
493 : }
494 : }
495 : }
496 : else {
497 182 : for (int i = 0; i < m_nFeatureCount; i++) {
498 182 : poVfkFeature = GetFeatureByIndex(i);
499 182 : iPropertyValue = poVfkFeature->GetProperty(idx)->GetValueI();
500 182 : if (iPropertyValue == value) {
501 26 : m_iNextFeature = i + 1;
502 26 : return poVfkFeature;
503 : }
504 : }
505 : }
506 :
507 0 : return NULL;
508 : }
509 :
510 : /*!
511 : \brief Get vfkfeatures based on properties
512 :
513 : \param idx property index
514 : \param value property value
515 :
516 : \return pointer to VFKFeature definition
517 : \return NULL on failure (not found)
518 : */
519 1 : std::vector<VFKFeature *> VFKDataBlock::GetFeatures(int idx, int value)
520 : {
521 : int iPropertyValue;
522 : VFKFeature *poVfkFeature;
523 1 : std::vector<VFKFeature *> poResult;
524 :
525 27 : for (int i = 0; i < m_nFeatureCount; i++) {
526 26 : poVfkFeature = GetFeatureByIndex(i);
527 26 : iPropertyValue = poVfkFeature->GetProperty(idx)->GetValueI();
528 26 : if (iPropertyValue == value) {
529 13 : poResult.push_back(poVfkFeature);
530 : }
531 : }
532 :
533 0 : return poResult;
534 : }
535 :
536 : /*!
537 : \brief Get vfkfeatures based on properties
538 :
539 : \param idx1, idx2 property index
540 : \param value property value
541 :
542 : \return pointer to VFKFeature definition
543 : \return NULL on failure (not found)
544 : */
545 1 : std::vector<VFKFeature *> VFKDataBlock::GetFeatures(int idx1, int idx2, int value)
546 : {
547 : int iPropertyValue1, iPropertyValue2;
548 : VFKFeature *poVfkFeature;
549 1 : std::vector<VFKFeature *> poResult;
550 :
551 14 : for (int i = 0; i < m_nFeatureCount; i++) {
552 13 : poVfkFeature = GetFeatureByIndex(i);
553 13 : iPropertyValue1 = poVfkFeature->GetProperty(idx1)->GetValueI();
554 13 : if (idx2 < 0) {
555 0 : if (iPropertyValue1 == value) {
556 0 : poResult.push_back(poVfkFeature);
557 : }
558 : }
559 : else {
560 13 : iPropertyValue2 = poVfkFeature->GetProperty(idx2)->GetValueI();
561 13 : if (iPropertyValue1 == value || iPropertyValue2 == value) {
562 13 : poResult.push_back(poVfkFeature);
563 : }
564 : }
565 : }
566 :
567 0 : return poResult;
568 : }
569 :
570 : /*!
571 : \brief Get vfkfeature by FID
572 :
573 : Modifies next feature id.
574 :
575 : \param nFID feature id
576 :
577 : \return pointer to VFKFeature definition
578 : \return NULL on failure (not found)
579 : */
580 0 : VFKFeature *VFKDataBlock::GetFeature(long nFID)
581 : {
582 0 : if (nFID < 1 || nFID > m_nFeatureCount)
583 0 : return NULL;
584 :
585 0 : if (m_bGeometryPerBlock && !m_bGeometry) {
586 0 : LoadGeometry();
587 : }
588 :
589 0 : if (m_nGeometryType == wkbPoint || m_nGeometryType == wkbPolygon) {
590 0 : m_iNextFeature = (int) nFID;
591 0 : return GetFeatureByIndex(int (nFID) - 1); /* zero-based index */
592 : }
593 0 : else if (m_nGeometryType == wkbLineString) {
594 : /* line string */
595 0 : for (int i = 0; i < m_nFeatureCount; i++) {
596 0 : if (m_papoFeature[i]->GetFID() == nFID) {
597 0 : m_iNextFeature = i + 1;
598 0 : return m_papoFeature[i];
599 : }
600 : }
601 : }
602 :
603 0 : return NULL;
604 : }
605 :
606 : /*!
607 : \brief Get feature count based on property value
608 :
609 : \param pszName property name
610 : \param pszValue property value
611 :
612 : \return number of features
613 : \return -1 on error
614 : */
615 0 : int VFKDataBlock::GetFeatureCount(const char *pszName, const char *pszValue)
616 : {
617 : int nfeatures, propIdx;
618 : VFKFeature *poVFKFeature;
619 :
620 0 : propIdx = GetPropertyIndex(pszName);
621 0 : if (propIdx < 0)
622 0 : return -1;
623 :
624 0 : nfeatures = 0;
625 0 : for (int i = 0; i < GetFeatureCount(); i++) {
626 0 : poVFKFeature = GetFeature(i);
627 0 : if (!poVFKFeature)
628 0 : return -1;
629 0 : if (EQUAL (poVFKFeature->GetProperty(propIdx)->GetValueS(), pszValue))
630 0 : nfeatures++;
631 : }
632 :
633 0 : return nfeatures;
634 : }
635 :
636 : /*!
637 : \brief Set maximum fid in datablock
638 :
639 : \param nFID fid number
640 :
641 : \return max fid
642 : */
643 53 : long VFKDataBlock::SetMaxFID(long nFID)
644 : {
645 53 : if (m_nFID < nFID)
646 40 : m_nFID = nFID;
647 :
648 53 : return m_nFID;
649 : }
650 :
651 : /*!
652 : \brief Load geometry
653 :
654 : \return number of processed features
655 : \return -1 on failure
656 : */
657 5 : long VFKDataBlock::LoadGeometry()
658 : {
659 : long nfeatures;
660 : clock_t start, end;
661 : VFKFeature *poFeature;
662 :
663 5 : if (m_bGeometry)
664 1 : return 0;
665 :
666 4 : nfeatures = 0;
667 4 : m_bGeometry = TRUE;
668 4 : start = clock();
669 :
670 5 : if (EQUAL (m_pszName, "SOBR") ||
671 : EQUAL (m_pszName, "OBBP") ||
672 : EQUAL (m_pszName, "SPOL") ||
673 : EQUAL (m_pszName, "OB") ||
674 : EQUAL (m_pszName, "OP") ||
675 : EQUAL (m_pszName, "OBPEJ")) {
676 : /* -> wkbPoint */
677 : double x, y;
678 : int i_idxX, i_idxY;
679 :
680 1 : i_idxY = GetPropertyIndex("SOURADNICE_Y");
681 1 : i_idxX = GetPropertyIndex("SOURADNICE_X");
682 1 : if (i_idxY < 0 || i_idxX < 0)
683 0 : return -1;
684 14 : for (int j = 0; j < GetFeatureCount(); j++) {
685 13 : poFeature = GetFeatureByIndex(j);
686 13 : x = -1.0 * poFeature->GetProperty(i_idxY)->GetValueD();
687 13 : y = -1.0 * poFeature->GetProperty(i_idxX)->GetValueD();
688 13 : OGRPoint pt(x, y);
689 13 : poFeature->SetGeometry(&pt);
690 13 : nfeatures++;
691 : }
692 : }
693 3 : else if (EQUAL (m_pszName, "SBP")) {
694 : /* -> wkbLineString */
695 : int id, idxId, idxBp_Id, idxPCB, ipcb;
696 :
697 : VFKDataBlock *poDataBlockPoints;
698 1 : VFKFeature *poPoint, *poLine = NULL;
699 :
700 1 : OGRLineString oOGRLine;
701 :
702 1 : poDataBlockPoints = m_poReader->GetDataBlock("SOBR");
703 1 : if (!poDataBlockPoints)
704 0 : return -1;
705 :
706 1 : poDataBlockPoints->LoadGeometry();
707 1 : idxId = poDataBlockPoints->GetPropertyIndex("ID");
708 1 : idxBp_Id = GetPropertyIndex("BP_ID");
709 1 : idxPCB = GetPropertyIndex("PORADOVE_CISLO_BODU");
710 1 : if (idxId < 0 || idxBp_Id < 0 || idxPCB < 0)
711 0 : return -1;
712 :
713 27 : for (int j = 0; j < GetFeatureCount(); j++) {
714 26 : poFeature = GetFeatureByIndex(j);
715 26 : poFeature->SetGeometry(NULL);
716 26 : id = poFeature->GetProperty(idxBp_Id)->GetValueI();
717 26 : ipcb = poFeature->GetProperty(idxPCB)->GetValueI();
718 26 : if (ipcb == 1) {
719 13 : if (!oOGRLine.IsEmpty()) {
720 12 : oOGRLine.setCoordinateDimension(2); /* force 2D */
721 12 : poLine->SetGeometry(&oOGRLine);
722 12 : oOGRLine.empty(); /* restore line */
723 : }
724 13 : poLine = poFeature;
725 : }
726 26 : poPoint = poDataBlockPoints->GetFeature(idxId, id);
727 26 : if (!poPoint)
728 0 : continue;
729 26 : OGRPoint *pt = (OGRPoint *) poPoint->GetGeometry();
730 26 : oOGRLine.addPoint(pt);
731 26 : nfeatures++;
732 : }
733 : /* add last line */
734 1 : oOGRLine.setCoordinateDimension(2); /* force 2D */
735 1 : if (poLine)
736 1 : poLine->SetGeometry(&oOGRLine);
737 :
738 1 : poDataBlockPoints->ResetReading();
739 : }
740 3 : else if (EQUAL (m_pszName, "HP") ||
741 : EQUAL (m_pszName, "DPM")) {
742 : /* -> wkbLineString */
743 : int id, idxId, idxMy_Id, idxPCB;
744 : VFKDataBlock *poDataBlockLines;
745 : VFKFeature *poLine;
746 1 : std::vector<VFKFeature *> poLineList;
747 :
748 1 : poDataBlockLines = m_poReader->GetDataBlock("SBP");
749 1 : if (!poDataBlockLines)
750 0 : return nfeatures;
751 :
752 1 : poDataBlockLines->LoadGeometry();
753 1 : idxId = GetPropertyIndex("ID");
754 1 : if (EQUAL (m_pszName, "HP"))
755 1 : idxMy_Id = poDataBlockLines->GetPropertyIndex("HP_ID");
756 : else
757 0 : idxMy_Id = poDataBlockLines->GetPropertyIndex("DPM_ID");
758 1 : idxPCB = poDataBlockLines->GetPropertyIndex("PORADOVE_CISLO_BODU");
759 1 : if (idxId < 0 || idxMy_Id < 0 || idxPCB < 0)
760 0 : return nfeatures;
761 :
762 1 : poLineList = poDataBlockLines->GetFeatures(idxPCB, 1); /* reduce to first segment */
763 14 : for (int i = 0; i < GetFeatureCount(); i++) {
764 13 : poFeature = GetFeatureByIndex(i);
765 13 : id = poFeature->GetProperty(idxId)->GetValueI();
766 13 : poLine = poDataBlockLines->GetFeature(idxMy_Id, id, &poLineList);
767 13 : if (!poLine || !poLine->GetGeometry())
768 0 : continue;
769 13 : poFeature->SetGeometry(poLine->GetGeometry());
770 13 : nfeatures++;
771 : }
772 1 : poDataBlockLines->ResetReading();
773 : }
774 1 : else if (EQUAL (m_pszName, "PAR") ||
775 : EQUAL (m_pszName, "BUD")) {
776 : /* -> wkbPolygon */
777 : bool bIsPar, bNewRing, bFound;
778 :
779 : int id, idOb;
780 1 : int idxId, idxPar1 = 0, idxPar2 = 0, idxBud = 0, idxOb = 0, idxIdOb = 0;
781 :
782 : VFKDataBlock *poDataBlockLines1, *poDataBlockLines2;
783 :
784 1 : std::vector<VFKFeature *> poLineList;
785 1 : PointListArray poRingList; /* first is to be considered as exterior */
786 :
787 1 : OGRLinearRing ogrRing;
788 1 : OGRPolygon ogrPolygon;
789 :
790 1 : if (EQUAL (m_pszName, "PAR")) {
791 1 : poDataBlockLines1 = m_poReader->GetDataBlock("HP");
792 1 : poDataBlockLines2 = poDataBlockLines1;
793 1 : bIsPar = TRUE;
794 : }
795 : else {
796 0 : poDataBlockLines1 = m_poReader->GetDataBlock("OB");
797 0 : poDataBlockLines2 = m_poReader->GetDataBlock("SBP");
798 0 : bIsPar = FALSE;
799 : }
800 1 : if (!poDataBlockLines1 || !poDataBlockLines2)
801 0 : return nfeatures;
802 :
803 1 : poDataBlockLines1->LoadGeometry();
804 1 : poDataBlockLines2->LoadGeometry();
805 1 : idxId = GetPropertyIndex("ID");
806 1 : if (idxId < 0)
807 0 : return nfeatures;
808 1 : if (bIsPar) {
809 1 : idxPar1 = poDataBlockLines1->GetPropertyIndex("PAR_ID_1");
810 1 : idxPar2 = poDataBlockLines1->GetPropertyIndex("PAR_ID_2");
811 1 : if (idxPar1 < 0 || idxPar2 < 0)
812 0 : return nfeatures;
813 : }
814 : else { /* BUD */
815 0 : idxIdOb = poDataBlockLines1->GetPropertyIndex("ID");
816 0 : idxBud = poDataBlockLines1->GetPropertyIndex("BUD_ID");
817 0 : idxOb = poDataBlockLines2->GetPropertyIndex("OB_ID");
818 0 : if (idxIdOb < 0 || idxBud < 0 || idxOb < 0)
819 0 : return nfeatures;
820 : }
821 :
822 2 : for (int i = 0; i < GetFeatureCount(); i++) {
823 1 : poFeature = GetFeatureByIndex(i);
824 1 : id = poFeature->GetProperty(idxId)->GetValueI();
825 1 : if (bIsPar) {
826 1 : poLineList = poDataBlockLines1->GetFeatures(idxPar1, idxPar2, id);
827 : }
828 : else {
829 : VFKFeature *poLineOb, *poLineSbp;
830 0 : std::vector<VFKFeature *> poLineListOb;
831 0 : poLineListOb = poDataBlockLines1->GetFeatures(idxBud, id);
832 0 : for (std::vector<VFKFeature *>::const_iterator iOb = poLineListOb.begin(), eOb = poLineListOb.end();
833 : iOb != eOb; ++iOb) {
834 0 : poLineOb = (*iOb);
835 0 : idOb = poLineOb->GetProperty(idxIdOb)->GetValueI();
836 0 : poLineSbp = poDataBlockLines2->GetFeature(idxOb, idOb);
837 0 : if (poLineSbp)
838 0 : poLineList.push_back(poLineSbp);
839 0 : }
840 : }
841 1 : if (poLineList.size() < 1)
842 0 : continue;
843 :
844 : /* clear */
845 1 : ogrPolygon.empty();
846 1 : poRingList.clear();
847 :
848 : /* collect rings (points) */
849 1 : bFound = FALSE;
850 15 : while (poLineList.size() > 0) {
851 13 : bNewRing = !bFound ? TRUE : FALSE;
852 13 : bFound = FALSE;
853 41 : for (VFKFeatureList::iterator iHp = poLineList.begin(), eHp = poLineList.end();
854 : iHp != eHp; ++iHp) {
855 41 : const OGRLineString *pLine = (OGRLineString *) (*iHp)->GetGeometry();
856 41 : if (pLine && AppendLineToRing(&poRingList, pLine, bNewRing)) {
857 13 : bFound = TRUE;
858 13 : poLineList.erase(iHp);
859 13 : break;
860 : }
861 : }
862 : }
863 : /* create rings */
864 2 : for (PointListArray::const_iterator iRing = poRingList.begin(), eRing = poRingList.end();
865 : iRing != eRing; ++iRing) {
866 1 : PointList *poList = *iRing;
867 1 : ogrRing.empty();
868 15 : for (PointList::iterator iPoint = poList->begin(), ePoint = poList->end();
869 : iPoint != ePoint; ++iPoint) {
870 14 : ogrRing.addPoint(&(*iPoint));
871 : }
872 1 : ogrPolygon.addRing(&ogrRing);
873 : }
874 : /* set polygon */
875 1 : ogrPolygon.setCoordinateDimension(2); /* force 2D */
876 1 : poFeature->SetGeometry(&ogrPolygon);
877 1 : nfeatures++;
878 : }
879 :
880 : /* free ring list */
881 2 : for (PointListArray::iterator iRing = poRingList.begin(), eRing = poRingList.end();
882 : iRing != eRing; ++iRing) {
883 1 : delete (*iRing);
884 1 : *iRing = NULL;
885 : }
886 1 : poDataBlockLines1->ResetReading();
887 1 : poDataBlockLines2->ResetReading();
888 : }
889 :
890 4 : end = clock();
891 :
892 : CPLDebug("OGR_VFK", "VFKDataBlock::LoadGeometry(): name=%s nfeatures=%ld sec=%ld",
893 4 : m_pszName, nfeatures, (long)((end - start) / CLOCKS_PER_SEC));
894 :
895 4 : return nfeatures;
896 : }
897 :
898 : /*!
899 : \brief Add linestring to a ring (private)
900 :
901 : \param[in,out] papoRing list of rings
902 : \param poLine pointer to linestring to be added to a ring
903 :
904 : \return TRUE on success
905 : \return FALSE on failure
906 : */
907 41 : bool VFKDataBlock::AppendLineToRing(PointListArray *papoRing, const OGRLineString *poLine, bool bNewRing)
908 : {
909 : OGRPoint *poFirst, *poLast;
910 : OGRPoint *poFirstNew, *poLastNew;
911 :
912 41 : OGRPoint pt;
913 41 : PointList poList;
914 :
915 : /* OGRLineString -> PointList */
916 123 : for (int i = 0; i < poLine->getNumPoints(); i++) {
917 82 : poLine->getPoint(i, &pt);
918 82 : poList.push_back(pt);
919 : }
920 :
921 : /* create new ring */
922 41 : if (bNewRing) {
923 1 : papoRing->push_back(new PointList(poList));
924 1 : return TRUE;
925 : }
926 :
927 40 : poFirstNew = &(poList.front());
928 40 : poLastNew = &(poList.back());
929 68 : for (PointListArray::const_iterator i = papoRing->begin(), e = papoRing->end();
930 : i != e; ++i) {
931 40 : PointList *ring = (*i);
932 40 : poFirst = &(ring->front());
933 40 : poLast = &(ring->back());
934 40 : if (!poFirst || !poLast || poLine->getNumPoints() < 2)
935 0 : return FALSE;
936 :
937 40 : if (poFirstNew->Equals(poLast)) {
938 : /* forward, skip first point */
939 0 : ring->insert(ring->end(), poList.begin()+1, poList.end());
940 0 : return TRUE;
941 : }
942 :
943 40 : if (poFirstNew->Equals(poFirst)) {
944 : /* backward, skip last point */
945 3 : ring->insert(ring->begin(), poList.rbegin(), poList.rend()-1);
946 3 : return TRUE;
947 : }
948 :
949 37 : if (poLastNew->Equals(poLast)) {
950 : /* backward, skip first point */
951 0 : ring->insert(ring->end(), poList.rbegin()+1, poList.rend());
952 0 : return TRUE;
953 : }
954 :
955 37 : if (poLastNew->Equals(poFirst)) {
956 : /* forward, skip last point */
957 9 : ring->insert(ring->begin(), poList.begin(), poList.end()-1);
958 9 : return TRUE;
959 : }
960 : }
961 :
962 28 : return FALSE;
963 : }
964 :
965 : /*!
966 : \brief Set next feature
967 :
968 : \param poFeature pointer to current feature
969 :
970 : \return index of current feature
971 : \return -1 on failure
972 : */
973 0 : int VFKDataBlock::SetNextFeature(const VFKFeature *poFeature)
974 : {
975 0 : for (int i = 0; i < m_nFeatureCount; i++) {
976 0 : if (m_papoFeature[i] == poFeature) {
977 0 : m_iNextFeature = i + 1;
978 0 : return i;
979 : }
980 : }
981 :
982 0 : return NULL;
983 : }
|