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