LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/vfk - vfkdatablock.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 426 323 75.8 %
Date: 2011-12-18 Functions: 27 18 66.7 %

       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                 : }

Generated by: LCOV version 1.7