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-04-28 Functions: 33 18 54.5 %

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

Generated by: LCOV version 1.7