LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/vfk - vfkfeature.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 211 104 49.3 %
Date: 2013-03-30 Functions: 21 8 38.1 %

       1                 : /******************************************************************************
       2                 :  * $Id: vfkfeature.cpp 25702 2013-03-07 17:17:54Z martinl $
       3                 :  *
       4                 :  * Project:  VFK Reader - Feature definition
       5                 :  * Purpose:  Implements IVFKFeature/VFKFeature class.
       6                 :  * Author:   Martin Landa, landa.martin gmail.com
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2009-2010, 2012-2013, 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 "vfkreader.h"
      33                 : #include "vfkreaderp.h"
      34                 : 
      35                 : #include "cpl_conv.h"
      36                 : #include "cpl_error.h"
      37                 : 
      38                 : /*!
      39                 :   \brief IVFKFeature constructor
      40                 : 
      41                 :   \param poDataBlock pointer to VFKDataBlock instance
      42                 : */
      43             133 : IVFKFeature::IVFKFeature(IVFKDataBlock *poDataBlock)
      44                 : {
      45             133 :     CPLAssert(NULL != poDataBlock);
      46             133 :     m_poDataBlock   = poDataBlock;
      47                 :     
      48             133 :     m_nFID          = -1;
      49             133 :     m_nGeometryType = poDataBlock->GetGeometryType();
      50             133 :     m_bGeometry     = FALSE;
      51             133 :     m_bValid        = FALSE;
      52             133 :     m_paGeom        = NULL;
      53             133 : }
      54                 : 
      55                 : /*!
      56                 :   \brief IVFKFeature destructor
      57                 : */
      58             133 : IVFKFeature::~IVFKFeature()
      59                 : {
      60             133 :     if (m_paGeom)
      61              80 :         delete m_paGeom;
      62                 :     
      63             133 :     m_poDataBlock = NULL;
      64             133 : }
      65                 : 
      66                 : /*!
      67                 :   \brief Set feature geometry type
      68                 : */
      69               0 : void IVFKFeature::SetGeometryType(OGRwkbGeometryType nGeomType)
      70                 : {
      71               0 :     m_nGeometryType = nGeomType;
      72               0 : }
      73                 : 
      74                 : /*!
      75                 :   \brief Set feature id
      76                 : 
      77                 :   FID: 0 for next, -1 for same
      78                 :   
      79                 :   \param nFID feature id
      80                 : */
      81               0 : void IVFKFeature::SetFID(long nFID)
      82                 : {
      83               0 :     if (m_nFID > 0) {
      84               0 :         m_nFID = nFID;
      85                 :     }
      86                 :     else {
      87               0 :         m_nFID = m_poDataBlock->GetFeatureCount() + 1;
      88                 :     }
      89               0 : }
      90                 : 
      91                 : /*!
      92                 :   \brief Set feature geometry
      93                 : 
      94                 :   Also checks if given geometry is valid
      95                 : 
      96                 :   \param poGeom pointer to OGRGeometry
      97                 : 
      98                 :   \return TRUE on valid feature or otherwise FALSE
      99                 : */
     100              80 : bool IVFKFeature::SetGeometry(OGRGeometry *poGeom)
     101                 : {
     102              80 :     m_bGeometry = TRUE;
     103                 : 
     104              80 :     delete m_paGeom;
     105              80 :     m_paGeom = NULL;
     106              80 :     m_bValid = TRUE;
     107                 : 
     108              80 :     if (!poGeom) {
     109               0 :   return m_bValid;
     110                 :     }
     111                 : 
     112                 :     /* check empty geometries */
     113              80 :     if (m_nGeometryType == wkbNone && poGeom->IsEmpty()) {
     114                 :   CPLDebug("OGR-VFK", "%s: empty geometry fid = %ld",
     115               0 :      m_poDataBlock->GetName(), m_nFID);
     116               0 :         m_bValid = FALSE;
     117                 :     }
     118                 :     
     119                 :     /* check coordinates */
     120              80 :     if (m_nGeometryType == wkbPoint) {
     121                 :         double x, y;
     122              26 :         x = ((OGRPoint *) poGeom)->getX();
     123              26 :         y = ((OGRPoint *) poGeom)->getY();
     124              26 :         if (x > -430000 || x < -910000 ||
     125                 :             y > -930000 || y < -1230000) {
     126                 :             CPLDebug("OGR-VFK", "%s: invalid point fid = %ld",
     127               0 :                      m_poDataBlock->GetName(), m_nFID);
     128               0 :             m_bValid = FALSE;
     129                 :         }
     130                 :     }
     131                 : 
     132                 :     /* check degenerated linestrings */
     133              80 :     if (m_nGeometryType == wkbLineString &&
     134                 :         ((OGRLineString *) poGeom)->getNumPoints() < 2) {
     135                 :         CPLDebug("OGR-VFK", "%s: invalid linestring fid = %ld",
     136               0 :      m_poDataBlock->GetName(), m_nFID);
     137               0 :         m_bValid = FALSE;
     138                 :     }
     139                 :     
     140                 :     /* check degenerated polygons */
     141              80 :     if (m_nGeometryType == wkbPolygon) {
     142                 :         OGRLinearRing *poRing;
     143               2 :         poRing = ((OGRPolygon *) poGeom)->getExteriorRing();
     144               2 :         if (!poRing || poRing->getNumPoints() < 3) {
     145                 :       CPLDebug("OGR-VFK", "%s: invalid polygon fid = %ld",
     146               0 :          m_poDataBlock->GetName(), m_nFID);
     147               0 :             m_bValid = FALSE;
     148                 :   }
     149                 :     }
     150                 : 
     151              80 :     if (m_bValid)
     152              80 :         m_paGeom = (OGRGeometry *) poGeom->clone(); /* make copy */
     153                 : 
     154              80 :     return m_bValid;
     155                 : }
     156                 : 
     157                 : /*!
     158                 :   \brief Get feature geometry
     159                 : 
     160                 :   \return pointer to OGRGeometry or NULL on error
     161                 : */
     162             105 : OGRGeometry *IVFKFeature::GetGeometry()
     163                 : {
     164             105 :     if (m_nGeometryType != wkbNone && !m_bGeometry)
     165               0 :         LoadGeometry();
     166                 : 
     167             105 :     return m_paGeom;
     168                 : }
     169                 : 
     170                 : 
     171                 : /*!
     172                 :   \brief Load geometry
     173                 : 
     174                 :   \return TRUE on success or FALSE on failure
     175                 : */
     176               0 : bool IVFKFeature::LoadGeometry()
     177                 : {
     178                 :     const char *pszName;
     179               0 :     CPLString osSQL;
     180                 :     
     181               0 :     if (m_bGeometry)
     182               0 :         return TRUE;
     183                 : 
     184               0 :     pszName  = m_poDataBlock->GetName();
     185                 :     
     186               0 :     if (EQUAL (pszName, "SOBR") ||
     187                 :         EQUAL (pszName, "OBBP") ||
     188                 :         EQUAL (pszName, "SPOL") ||
     189                 :         EQUAL (pszName, "OB") ||
     190                 :         EQUAL (pszName, "OP") ||
     191                 :         EQUAL (pszName, "OBPEJ")) {
     192                 :         /* -> wkbPoint */
     193                 :         
     194               0 :         return LoadGeometryPoint();
     195                 :     }
     196               0 :     else if (EQUAL (pszName, "SBP")) {
     197                 :         /* -> wkbLineString */
     198               0 :         return LoadGeometryLineStringSBP();
     199                 :     }
     200               0 :     else if (EQUAL (pszName, "HP") ||
     201                 :              EQUAL (pszName, "DPM")) {
     202                 :         /* -> wkbLineString */
     203               0 :         return LoadGeometryLineStringHP();
     204                 :     }
     205               0 :     else if (EQUAL (pszName, "PAR") ||
     206                 :              EQUAL (pszName, "BUD")) {
     207                 :         /* -> wkbPolygon */
     208               0 :         return LoadGeometryPolygon();
     209                 :     }
     210                 : 
     211               0 :     return FALSE;
     212                 : }
     213                 : 
     214                 : /*!
     215                 :   \brief VFKFeature constructor
     216                 : 
     217                 :   \param poDataBlock pointer to VFKDataBlock instance
     218                 : */
     219              53 : VFKFeature::VFKFeature(IVFKDataBlock *poDataBlock, long iFID) : IVFKFeature(poDataBlock)
     220                 : {
     221              53 :     m_nFID = iFID;
     222              53 :     m_propertyList.assign(poDataBlock->GetPropertyCount(), VFKProperty());
     223              53 :     CPLAssert(size_t (poDataBlock->GetPropertyCount()) == m_propertyList.size());
     224              53 : }
     225                 : 
     226                 : /*!
     227                 :   \brief Set feature properties
     228                 : 
     229                 :   \param pszLine pointer to line containing feature definition
     230                 : 
     231                 :   \return TRUE on success or FALSE on failure
     232                 : */
     233              53 : bool VFKFeature::SetProperties(const char *pszLine)
     234                 : {
     235                 :     unsigned int iIndex, nLength;
     236                 :     const char *poChar, *poProp;
     237                 :     char* pszProp;
     238                 :     bool inString;
     239                 :     
     240              53 :     std::vector<CPLString> oPropList;
     241                 :     
     242              53 :     pszProp = NULL;
     243                 :     
     244              53 :     for (poChar = pszLine; *poChar != '\0' && *poChar != ';'; poChar++)
     245                 :         /* skip data block name */
     246                 :         ;
     247              53 :     if (poChar == '\0')
     248               0 :         return FALSE; /* nothing to read */
     249                 : 
     250              53 :     poChar++; /* skip ';' after data block name*/
     251                 : 
     252                 :     /* read properties into the list */
     253              53 :     poProp = poChar;
     254              53 :     iIndex = nLength = 0;
     255              53 :     inString = FALSE;
     256            3753 :     while(*poChar != '\0') {
     257            3648 :         if (*poChar == '"' && 
     258                 :             (*(poChar-1) == ';' || *(poChar+1) == ';' || *(poChar+1) == '\0')) {
     259             177 :             poChar++; /* skip '"' */
     260             177 :             inString = inString ? FALSE : TRUE;
     261             177 :             if (inString) {
     262             109 :                 poProp = poChar;
     263             109 :                 if (*poChar == '"') { 
     264              41 :                     poChar++;
     265              41 :                     inString = FALSE;
     266                 :                 }
     267                 :             }
     268             177 :             if (*poChar == '\0')
     269               1 :                 break;
     270                 :         }
     271            4246 :         if (*poChar == ';' && !inString) {
     272             599 :             pszProp = (char *) CPLRealloc(pszProp, nLength + 1);
     273             599 :             if (nLength > 0)
     274             445 :                 strncpy(pszProp, poProp, nLength);
     275             599 :             pszProp[nLength] = '\0';
     276             599 :             oPropList.push_back(pszProp);
     277             599 :             iIndex++;
     278             599 :             poProp = ++poChar;
     279             599 :             nLength = 0;
     280                 :         }
     281                 :         else {
     282            3048 :             poChar++;
     283            3048 :             nLength++;
     284                 :         }
     285                 :     }
     286                 :     /* append last property */
     287              53 :     if (inString) {
     288               0 :         nLength--; /* ignore '"' */
     289                 :     }
     290              53 :     pszProp = (char *) CPLRealloc(pszProp, nLength + 1);
     291              53 :     if (nLength > 0)
     292              27 :         strncpy(pszProp, poProp, nLength);
     293              53 :     pszProp[nLength] = '\0';
     294              53 :     oPropList.push_back(pszProp);
     295                 : 
     296                 :     /* set properties from the list */
     297              53 :     if (oPropList.size() != (size_t) m_poDataBlock->GetPropertyCount()) {
     298                 :         /* try to read also invalid records */
     299                 :         CPLDebug("OGR-VFK", "%s: invalid number of properties %d should be %d",
     300                 :                  m_poDataBlock->GetName(),
     301               0 :      (int) oPropList.size(), m_poDataBlock->GetPropertyCount());
     302               0 :         return FALSE;
     303                 :    }
     304              53 :     iIndex = 0;
     305             705 :     for (std::vector<CPLString>::iterator ip = oPropList.begin();
     306                 :    ip != oPropList.end(); ++ip) {
     307             652 :   SetProperty(iIndex++, (*ip).c_str());
     308                 :     }
     309                 :     
     310                 :     /* set fid 
     311                 :     if (EQUAL(m_poDataBlock->GetName(), "SBP")) {
     312                 :         GUIntBig id;
     313                 :         const VFKProperty *poVfkProperty;
     314                 : 
     315                 :         poVfkProperty = GetProperty("PORADOVE_CISLO_BODU");
     316                 :         if (poVfkProperty)
     317                 :         {
     318                 :             id = strtoul(poVfkProperty->GetValueS(), NULL, 0);
     319                 :             if (id == 1)
     320                 :                 SetFID(0); 
     321                 :             else
     322                 :                 SetFID(-1); 
     323                 :         }
     324                 :     }
     325                 :     else {
     326                 :         SetFID(0); 
     327                 :     }
     328                 :     */
     329              53 :     CPLFree(pszProp);
     330                 : 
     331              53 :     return TRUE;
     332                 : }
     333                 : 
     334                 : /*!
     335                 :   \brief Set feature property
     336                 : 
     337                 :   \param iIndex property index
     338                 :   \param pszValue property value
     339                 : 
     340                 :   \return TRUE on success
     341                 :   \return FALSE on failure
     342                 : */
     343             652 : bool VFKFeature::SetProperty(int iIndex, const char *pszValue)
     344                 : {
     345             652 :     if (iIndex < 0 || iIndex >= m_poDataBlock->GetPropertyCount() ||
     346                 :   size_t(iIndex) >= m_propertyList.size())
     347               0 :         return FALSE;
     348                 :     
     349             652 :     if (strlen(pszValue) < 1)
     350             180 :         m_propertyList[iIndex] = VFKProperty();
     351                 :     else {
     352                 :         OGRFieldType fType;
     353                 : 
     354                 :         const char *pszEncoding;
     355                 :         char       *pszValueEnc;
     356                 :                 
     357             472 :         fType = m_poDataBlock->GetProperty(iIndex)->GetType();
     358             472 :         switch (fType) {
     359                 :         case OFTInteger:
     360             139 :             m_propertyList[iIndex] = VFKProperty(atoi(pszValue));
     361             139 :             break;
     362                 :         case OFTReal:
     363              26 :             m_propertyList[iIndex] = VFKProperty(CPLAtof(pszValue));
     364              26 :             break;
     365                 :         default:
     366             307 :             pszEncoding = m_poDataBlock->GetProperty(iIndex)->GetEncoding();
     367             307 :             if (pszEncoding) {
     368                 :                 pszValueEnc = CPLRecode(pszValue, pszEncoding,
     369              28 :                                         CPL_ENC_UTF8);
     370              28 :                 m_propertyList[iIndex] = VFKProperty(pszValueEnc);
     371              28 :                 CPLFree(pszValueEnc);
     372                 :             }
     373                 :             else {
     374             279 :                 m_propertyList[iIndex] = VFKProperty(pszValue);
     375                 :             }
     376                 :             break;
     377                 :         }
     378                 :     }
     379             652 :     return TRUE;
     380                 : }
     381                 : 
     382                 : /*!
     383                 :   \brief Get property value by index
     384                 : 
     385                 :   \param iIndex property index
     386                 : 
     387                 :   \return property value
     388                 :   \return NULL on error
     389                 : */
     390             652 : const VFKProperty *VFKFeature::GetProperty(int iIndex) const
     391                 : {
     392             652 :     if (iIndex < 0 || iIndex >= m_poDataBlock->GetPropertyCount() ||
     393                 :   size_t(iIndex) >= m_propertyList.size())
     394               0 :         return NULL;
     395                 :     
     396             652 :     const VFKProperty* poProperty = &m_propertyList[iIndex];
     397             652 :     return poProperty;
     398                 : }
     399                 : 
     400                 : /*!
     401                 :   \brief Get property value by name
     402                 : 
     403                 :   \param pszName property name
     404                 : 
     405                 :   \return property value
     406                 :   \return NULL on error
     407                 : */
     408               0 : const VFKProperty *VFKFeature::GetProperty(const char *pszName) const
     409                 : {
     410               0 :     return GetProperty(m_poDataBlock->GetPropertyIndex(pszName));
     411                 : }
     412                 : 
     413                 : /*!
     414                 :   \brief Load geometry (point layers)
     415                 : 
     416                 :   \todo Really needed?
     417                 :   
     418                 :   \return TRUE on success
     419                 :   \return FALSE on failure
     420                 : */
     421               0 : bool VFKFeature::LoadGeometryPoint()
     422                 : {
     423                 :     double x, y;
     424                 :     int i_idxX, i_idxY;
     425                 :     
     426               0 :     i_idxY = m_poDataBlock->GetPropertyIndex("SOURADNICE_Y");
     427               0 :     i_idxX = m_poDataBlock->GetPropertyIndex("SOURADNICE_X");
     428               0 :     if (i_idxY < 0 || i_idxX < 0)
     429               0 :         return FALSE;
     430                 :     
     431               0 :     x = -1.0 * GetProperty(i_idxY)->GetValueD();
     432               0 :     y = -1.0 * GetProperty(i_idxX)->GetValueD();
     433               0 :     OGRPoint pt(x, y);
     434               0 :     SetGeometry(&pt);
     435                 :     
     436               0 :     return TRUE;
     437                 : }
     438                 : 
     439                 : /*!
     440                 :   \brief Load geometry (linestring SBP layer)
     441                 : 
     442                 :   \todo Really needed?
     443                 : 
     444                 :   \return TRUE on success or FALSE on failure
     445                 : */
     446               0 : bool VFKFeature::LoadGeometryLineStringSBP()
     447                 : {
     448                 :     int id, idxId, idxBp_Id, idxPCB, ipcb;
     449                 :     
     450                 :     VFKDataBlock *poDataBlockPoints;
     451                 :     VFKFeature   *poPoint, *poLine;
     452                 :     
     453               0 :     OGRLineString OGRLine;
     454                 :     
     455               0 :     poDataBlockPoints = (VFKDataBlock *) m_poDataBlock->GetReader()->GetDataBlock("SOBR");
     456               0 :     if (!poDataBlockPoints)
     457               0 :         return FALSE;
     458                 :     
     459               0 :     idxId    = poDataBlockPoints->GetPropertyIndex("ID");
     460               0 :     idxBp_Id = m_poDataBlock->GetPropertyIndex("BP_ID");
     461               0 :     idxPCB   = m_poDataBlock->GetPropertyIndex("PORADOVE_CISLO_BODU");
     462               0 :     if (idxId < 0 || idxBp_Id < 0 || idxPCB < 0)
     463               0 :         return false;
     464                 :     
     465               0 :     poLine = this;
     466               0 :     while (TRUE)
     467                 :     {
     468               0 :         id   = poLine->GetProperty(idxBp_Id)->GetValueI();
     469               0 :         ipcb = poLine->GetProperty(idxPCB)->GetValueI();
     470               0 :         if (OGRLine.getNumPoints() > 0 && ipcb == 1)
     471                 :         {
     472               0 :             m_poDataBlock->GetPreviousFeature(); /* push back */
     473               0 :             break;
     474                 :         }
     475                 :         
     476               0 :         poPoint = poDataBlockPoints->GetFeature(idxId, id);
     477               0 :         if (!poPoint)
     478                 :         {
     479               0 :             continue;
     480                 :         }
     481               0 :         OGRPoint *pt = (OGRPoint *) poPoint->GetGeometry();
     482               0 :         OGRLine.addPoint(pt);
     483                 :         
     484               0 :         poLine = (VFKFeature *) m_poDataBlock->GetNextFeature();
     485               0 :         if (!poLine)
     486               0 :             break;
     487                 :     };
     488                 :     
     489               0 :     OGRLine.setCoordinateDimension(2); /* force 2D */
     490               0 :     SetGeometry(&OGRLine);
     491                 :     
     492                 :     /* reset reading */
     493               0 :     poDataBlockPoints->ResetReading();
     494                 :     
     495               0 :     return TRUE;
     496                 : }
     497                 : 
     498                 : /*!
     499                 :   \brief Load geometry (linestring HP/DPM layer)
     500                 : 
     501                 :   \todo Really needed?
     502                 : 
     503                 :   \return TRUE on success or FALSE on failure
     504                 : */
     505               0 : bool VFKFeature::LoadGeometryLineStringHP()
     506                 : {
     507                 :     int           id, idxId, idxHp_Id;
     508                 :     VFKDataBlock *poDataBlockLines;
     509                 :     VFKFeature   *poLine;
     510                 :     
     511               0 :     poDataBlockLines = (VFKDataBlock *) m_poDataBlock->GetReader()->GetDataBlock("SBP");
     512               0 :     if (!poDataBlockLines)
     513               0 :         return FALSE;
     514                 :     
     515               0 :     idxId    = m_poDataBlock->GetPropertyIndex("ID");
     516               0 :     idxHp_Id = poDataBlockLines->GetPropertyIndex("HP_ID");
     517               0 :     if (idxId < 0 || idxHp_Id < 0)
     518               0 :         return FALSE;
     519                 :     
     520               0 :     id = GetProperty(idxId)->GetValueI();
     521               0 :     poLine = poDataBlockLines->GetFeature(idxHp_Id, id);
     522               0 :     if (!poLine || !poLine->GetGeometry())
     523               0 :         return FALSE;
     524                 :     
     525               0 :     SetGeometry(poLine->GetGeometry());
     526               0 :     poDataBlockLines->ResetReading();
     527                 :     
     528               0 :     return TRUE;
     529                 : }
     530                 : 
     531                 : /*!
     532                 :   \brief Load geometry (polygon BUD/PAR layers)
     533                 : 
     534                 :   \todo Implement (really needed?)
     535                 : 
     536                 :   \return TRUE on success or FALSE on failure
     537                 : */
     538               0 : bool VFKFeature::LoadGeometryPolygon()
     539                 : {
     540               0 :     return FALSE;
     541                 : }
     542               0 : OGRErr VFKFeature::LoadProperties(OGRFeature *poFeature)
     543                 : {
     544               0 :     for (int iField = 0; iField < m_poDataBlock->GetPropertyCount(); iField++) {
     545               0 :         if (GetProperty(iField)->IsNull())
     546               0 :             continue;
     547               0 :         OGRFieldType fType = poFeature->GetDefnRef()->GetFieldDefn(iField)->GetType();
     548               0 :         if (fType == OFTInteger) 
     549                 :             poFeature->SetField(iField,
     550               0 :                                 GetProperty(iField)->GetValueI());
     551               0 :         else if (fType == OFTReal)
     552                 :             poFeature->SetField(iField,
     553               0 :                                 GetProperty(iField)->GetValueD());
     554                 :         else
     555                 :             poFeature->SetField(iField,
     556               0 :                                 GetProperty(iField)->GetValueS());
     557                 :     }
     558                 : 
     559               0 :     return OGRERR_NONE;
     560                 : }

Generated by: LCOV version 1.7