LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/vfk - vfkdatablock.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 417 316 75.8 %
Date: 2010-01-09 Functions: 25 18 72.0 %

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

Generated by: LCOV version 1.7