LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/vfk - vfkdatablock.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 427 166 38.9 %
Date: 2012-12-26 Functions: 33 18 54.5 %

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

Generated by: LCOV version 1.7