Exemplo n.º 1
0
/*!
  \brief Load geometry (point layers)

  \return number of invalid features
*/
int VFKDataBlockSQLite::LoadGeometryPoint()
{
    int   nInvalid, rowId, nGeometries;
    bool  bSkipInvalid;
    /* long iFID; */
    double x, y;

    CPLString     osSQL;
    sqlite3_stmt *hStmt;

    VFKFeatureSQLite *poFeature;
    VFKReaderSQLite  *poReader;

    nInvalid  = nGeometries = 0;
    poReader  = (VFKReaderSQLite*) m_poReader;

    if (LoadGeometryFromDB()) /* try to load geometry from DB */
	return 0;

    bSkipInvalid = EQUAL(m_pszName, "OB") || EQUAL(m_pszName, "OP") || EQUAL(m_pszName, "OBBP");
    osSQL.Printf("SELECT SOURADNICE_Y,SOURADNICE_X,%s,rowid FROM %s",
                 FID_COLUMN, m_pszName);
    hStmt = poReader->PrepareStatement(osSQL.c_str());

    if (poReader->IsSpatial())
	poReader->ExecuteSQL("BEGIN");

    while(poReader->ExecuteSQL(hStmt) == OGRERR_NONE) {
        /* read values */
        x = -1.0 * sqlite3_column_double(hStmt, 0); /* S-JTSK coordinate system expected */
        y = -1.0 * sqlite3_column_double(hStmt, 1);
#ifdef DEBUG
	const long iFID = sqlite3_column_double(hStmt, 2);
#endif
	rowId = sqlite3_column_int(hStmt, 3);

        poFeature = (VFKFeatureSQLite *) GetFeatureByIndex(rowId - 1);
        CPLAssert(NULL != poFeature && poFeature->GetFID() == iFID);

        /* create geometry */
	OGRPoint pt(x, y);
        if (!poFeature->SetGeometry(&pt)) {
            nInvalid++;
            continue;
        }

	/* store also geometry in DB */
	if (poReader->IsSpatial() &&
	    SaveGeometryToDB(&pt, rowId) != OGRERR_FAILURE)
	    nGeometries++;
    }
    
    /* update number of geometries in VFK_DB_TABLE table */
    UpdateVfkBlocks(nGeometries);

    if (poReader->IsSpatial())
	poReader->ExecuteSQL("COMMIT");
    
    return bSkipInvalid ? 0 : nInvalid;
}
Exemplo n.º 2
0
/*!
  \brief Load geometry from DB

  \return TRUE geometry successfully loaded otherwise FALSE
*/
bool VFKDataBlockSQLite::LoadGeometryFromDB()
{
    int nInvalid, nGeometries, nGeometriesCount, nBytes, rowId;
#ifdef DEBUG
    long iFID;
#endif
    bool bSkipInvalid;

    CPLString osSQL;

    OGRGeometry      *poGeometry;

    VFKFeatureSQLite *poFeature;
    VFKReaderSQLite  *poReader;

    sqlite3_stmt *hStmt;

    poReader = (VFKReaderSQLite*) m_poReader;

    if (!poReader->IsSpatial())   /* check if DB is spatial */
	return FALSE;

    osSQL.Printf("SELECT num_geometries FROM %s WHERE table_name = '%s'",
		 VFK_DB_TABLE, m_pszName);
    hStmt = poReader->PrepareStatement(osSQL.c_str());
    if (poReader->ExecuteSQL(hStmt) != OGRERR_NONE)
        return FALSE;
    nGeometries = sqlite3_column_int(hStmt, 0);
    sqlite3_finalize(hStmt);
    
    if (nGeometries < 1)
	return FALSE;
    
    bSkipInvalid = EQUAL(m_pszName, "OB") || EQUAL(m_pszName, "OP") || EQUAL(m_pszName, "OBBP");

    /* load geometry from DB */
    nInvalid = nGeometriesCount = 0;
    osSQL.Printf("SELECT %s,rowid,%s FROM %s ",
		 GEOM_COLUMN, FID_COLUMN, m_pszName);
    if (EQUAL(m_pszName, "SBP"))
	osSQL += "WHERE PORADOVE_CISLO_BODU = 1 ";
    osSQL += "ORDER BY ";
    osSQL += FID_COLUMN;
    hStmt = poReader->PrepareStatement(osSQL.c_str());

    rowId = 0;
    while(poReader->ExecuteSQL(hStmt) == OGRERR_NONE) {
        rowId++; // =sqlite3_column_int(hStmt, 1);
#ifdef DEBUG
        iFID =
#endif
            sqlite3_column_double(hStmt, 2);

        poFeature = (VFKFeatureSQLite *) GetFeatureByIndex(rowId - 1);
        CPLAssert(NULL != poFeature && poFeature->GetFID() == iFID);

        // read geometry from DB
	nBytes = sqlite3_column_bytes(hStmt, 0);
	if (nBytes > 0 &&
	    OGRGeometryFactory::createFromWkb((GByte*) sqlite3_column_blob(hStmt, 0),
					      NULL, &poGeometry, nBytes) == OGRERR_NONE) {
	    nGeometriesCount++;
	    if (!poFeature->SetGeometry(poGeometry)) {
		nInvalid++;
	    }
	    delete poGeometry;
	}
	else {
	    nInvalid++;
	}
    }

    CPLDebug("OGR-VFK", "%s: %d geometries loaded from DB",
	     m_pszName, nGeometriesCount);

    if (nGeometriesCount != nGeometries) {
	CPLError(CE_Warning, CPLE_AppDefined, 
                 "%s: %d geometries loaded (should be %d)",
		 m_pszName, nGeometriesCount, nGeometries);
    }

    if (nInvalid > 0 && !bSkipInvalid) {
	CPLError(CE_Warning, CPLE_AppDefined, 
                 "%s: %d features with invalid or empty geometry",
		 m_pszName, nInvalid);
    }

    return TRUE;
}
Exemplo n.º 3
0
/*!
  \brief Load geometry (polygon BUD/PAR layers)

  \return number of invalid features
*/
int VFKDataBlockSQLite::LoadGeometryPolygon()
{
    int  nInvalidNoLines, nInvalidNoRings, nGeometries, nBridges;
    int  rowId, nCount, nCountMax;
    size_t nLines;
    long iFID;
    bool bIsPar, bNewRing, bFound;
        
    CPLString    osSQL;
    const char  *vrColumn[2];
    GUIntBig     vrValue[2];
    GUIntBig     id, idOb;
    
    sqlite3_stmt *hStmt;
    
    VFKReaderSQLite    *poReader;
    VFKDataBlockSQLite *poDataBlockLines1, *poDataBlockLines2;
    VFKFeatureSQLite   *poFeature;

    VFKFeatureSQLiteList  poLineList;
    /* first is to be considered as exterior */
    PointListArray        poRingList;
    
    std::vector<OGRLinearRing *> poLinearRingList;
    OGRPolygon     ogrPolygon;
    OGRLinearRing *poOgrRing;

    nInvalidNoLines = nInvalidNoRings = nGeometries = 0;
    poReader  = (VFKReaderSQLite*) m_poReader;
    
    if (EQUAL (m_pszName, "PAR")) {
        poDataBlockLines1 = (VFKDataBlockSQLite *) m_poReader->GetDataBlock("HP");
        poDataBlockLines2 = poDataBlockLines1;
        bIsPar = TRUE;
    }
    else {
        poDataBlockLines1 = (VFKDataBlockSQLite *) m_poReader->GetDataBlock("OB");
        poDataBlockLines2 = (VFKDataBlockSQLite *) m_poReader->GetDataBlock("SBP");
        bIsPar = FALSE;
    }
    if (NULL == poDataBlockLines1 || NULL == poDataBlockLines2) {
        CPLError(CE_Failure, CPLE_FileIO, 
                 "Data block %s not found", m_pszName);
        return -1;
    }
    
    poDataBlockLines1->LoadGeometry();
    poDataBlockLines2->LoadGeometry();
    
    if (LoadGeometryFromDB()) /* try to load geometry from DB */
	return 0;
    
    if (bIsPar) {
        vrColumn[0] = "PAR_ID_1";
        vrColumn[1] = "PAR_ID_2";
    }
    else {
        vrColumn[0] = "OB_ID";
        vrColumn[1] = "PORADOVE_CISLO_BODU";
        vrValue[1]  = 1;
    }

    osSQL.Printf("SELECT ID,%s,rowid FROM %s", FID_COLUMN, m_pszName);
    hStmt = poReader->PrepareStatement(osSQL.c_str());
    
    if (poReader->IsSpatial())
	poReader->ExecuteSQL("BEGIN");

    while(poReader->ExecuteSQL(hStmt) == OGRERR_NONE) {
        nBridges = 0;
        
        /* read values */
        id        = sqlite3_column_double(hStmt, 0);
        iFID      = sqlite3_column_double(hStmt, 1);
        rowId     = sqlite3_column_int(hStmt, 2);
        
        poFeature = (VFKFeatureSQLite *) GetFeatureByIndex(rowId - 1);
        CPLAssert(NULL != poFeature && poFeature->GetFID() == iFID);

        if (bIsPar) {
            vrValue[0] = vrValue[1] = id;
            poLineList = poDataBlockLines1->GetFeatures(vrColumn, vrValue, 2);
        }
        else {
            VFKFeatureSQLite *poLineSbp;
            std::vector<VFKFeatureSQLite *> poLineListOb;
            sqlite3_stmt *hStmtOb;
            
            osSQL.Printf("SELECT ID FROM %s WHERE BUD_ID = " CPL_FRMT_GUIB,
                         poDataBlockLines1->GetName(), id);
            if (poReader->IsSpatial()) {
                CPLString osColumn;
                
                osColumn.Printf(" AND %s IS NULL", GEOM_COLUMN);
                osSQL += osColumn;
            }
            hStmtOb = poReader->PrepareStatement(osSQL.c_str());
            
            while(poReader->ExecuteSQL(hStmtOb) == OGRERR_NONE) {
                idOb = sqlite3_column_double(hStmtOb, 0); 
                vrValue[0] = idOb;
                poLineSbp = poDataBlockLines2->GetFeature(vrColumn, vrValue, 2);
                if (poLineSbp)
                    poLineList.push_back(poLineSbp);
            }
        }
        nLines = poLineList.size();
        if (nLines < 1) {
            CPLDebug("OGR-VFK", 
                     "%s: unable to collect rings for polygon fid = %ld (no lines)",
                     m_pszName, iFID);
            nInvalidNoLines++;
            continue;
        }
        
        /* clear */
        ogrPolygon.empty();
        poRingList.clear();
        
        /* collect rings from lines */
        bFound = FALSE;
        nCount = 0;
        nCountMax = nLines * 2;
	while (poLineList.size() > 0 && nCount < nCountMax) {
            bNewRing = !bFound ? TRUE : FALSE;
            bFound = FALSE;
            int i = 1;
            for (VFKFeatureSQLiteList::iterator iHp = poLineList.begin(), eHp = poLineList.end();
                 iHp != eHp; ++iHp, ++i) {
                const OGRLineString *pLine = (OGRLineString *) (*iHp)->GetGeometry();
                if (pLine && AppendLineToRing(&poRingList, pLine, bNewRing)) {
                    bFound = TRUE;
                    poLineList.erase(iHp);
                    break;
                }
            }
            nCount++;
        }
        CPLDebug("OGR-VFK", "%s: fid = %ld nlines = %d -> nrings = %d", m_pszName,
                 iFID, (int)nLines, (int)poRingList.size());

        if (poLineList.size() > 0) {
            CPLDebug("OGR-VFK", 
                     "%s: unable to collect rings for polygon fid = %ld",
                     m_pszName, iFID);
            nInvalidNoRings++;
            continue;
        }

        /* build rings */
	poLinearRingList.clear();
	int i = 1;
        for (PointListArray::const_iterator iRing = poRingList.begin(), eRing = poRingList.end();
             iRing != eRing; ++iRing) {
	    OGRPoint *poPoint;
            PointList *poList = *iRing;
	    
            poLinearRingList.push_back(new OGRLinearRing());
	    poOgrRing = poLinearRingList.back();
	    CPLAssert(NULL != poOgrRing);
	    
            for (PointList::iterator iPoint = poList->begin(), ePoint = poList->end();
                 iPoint != ePoint; ++iPoint) {
		poPoint = &(*iPoint);
                poOgrRing->addPoint(poPoint);
            }
	    i++;
	}

	/* find exterior ring */
	if (poLinearRingList.size() > 1) {
	    double dArea, dMaxArea;
	    std::vector<OGRLinearRing *>::iterator exteriorRing;
	    
	    exteriorRing = poLinearRingList.begin();
	    dMaxArea = -1.;
	    for (std::vector<OGRLinearRing *>::iterator iRing = poLinearRingList.begin(),
		     eRing = poLinearRingList.end(); iRing != eRing; ++iRing) {
		poOgrRing = *iRing;
		if (!IsRingClosed(poOgrRing))
		    continue; /* skip unclosed rings */
		
		dArea = poOgrRing->get_Area();
		if (dArea > dMaxArea) {
		    dMaxArea = dArea;
		    exteriorRing = iRing;
		}
	    }
	    if (exteriorRing != poLinearRingList.begin()) {
		std::swap(*poLinearRingList.begin(), *exteriorRing);
	    }
	}
	
	/* build polygon from rings */
        for (std::vector<OGRLinearRing *>::iterator iRing = poLinearRingList.begin(),
		 eRing = poLinearRingList.end(); iRing != eRing; ++iRing) {
	    poOgrRing = *iRing;
	    
	    /* check if ring is closed */
	    if (IsRingClosed(poOgrRing)) {
		ogrPolygon.addRing(poOgrRing);
            }
	    else {
                if (poOgrRing->getNumPoints() == 2) {
                    CPLDebug("OGR-VFK", "%s: Polygon (fid = %ld) bridge removed",
                             m_pszName, iFID);
                    nBridges++;
                }
                else {
                    CPLDebug("OGR-VFK",
                             "%s: Polygon (fid = %ld) unclosed ring skipped",
                             m_pszName, iFID);
                }
            }
	    delete poOgrRing;
            *iRing = NULL;
        }

        /* set polygon */
        ogrPolygon.setCoordinateDimension(2); /* force 2D */
        if (ogrPolygon.getNumInteriorRings() + nBridges != (int) poLinearRingList.size() - 1 ||
            !poFeature->SetGeometry(&ogrPolygon)) {
            nInvalidNoRings++;
            continue;
        }
	
        /* store also geometry in DB */
        if (poReader->IsSpatial() && 
	    SaveGeometryToDB(&ogrPolygon, rowId) != OGRERR_FAILURE)
            nGeometries++;
    }
    
    /* free ring list */
    for (PointListArray::iterator iRing = poRingList.begin(), eRing = poRingList.end();
         iRing != eRing; ++iRing) {
        delete (*iRing);
        *iRing = NULL;
    }
    
    CPLDebug("OGR-VFK", "%s: nolines = %d norings = %d",
             m_pszName, nInvalidNoLines, nInvalidNoRings);
    
    /* update number of geometries in VFK_DB_TABLE table */
    UpdateVfkBlocks(nGeometries);

    if (poReader->IsSpatial())
	poReader->ExecuteSQL("COMMIT");

    return nInvalidNoLines + nInvalidNoRings;
}
Exemplo n.º 4
0
/*!
  \brief Load geometry (linestring HP/DPM layer)

  \return number of invalid features
*/
int VFKDataBlockSQLite::LoadGeometryLineStringHP()
{
    int          nInvalid, nGeometries;
    int          rowId;
    long         iFID;
    
    CPLString    osColumn, osSQL;
    const char  *vrColumn[2];
    GUIntBig     vrValue[2];
    
    sqlite3_stmt *hStmt;
    
    OGRGeometry        *poOgrGeometry;
    VFKReaderSQLite    *poReader;
    VFKDataBlockSQLite *poDataBlockLines;
    VFKFeatureSQLite   *poFeature, *poLine;
    
    nInvalid = nGeometries = 0;
    poReader  = (VFKReaderSQLite*) m_poReader;
    
    poDataBlockLines = (VFKDataBlockSQLite *) m_poReader->GetDataBlock("SBP");
    if (NULL == poDataBlockLines) {
        CPLError(CE_Failure, CPLE_FileIO, 
                 "Data block %s not found", m_pszName);
        return nInvalid;
    }
    
    poDataBlockLines->LoadGeometry();

    if (LoadGeometryFromDB()) /* try to load geometry from DB */
	return 0;
    
    osColumn.Printf("%s_ID", m_pszName);
    vrColumn[0] = osColumn.c_str();
    vrColumn[1] = "PORADOVE_CISLO_BODU";
    vrValue[1]  = 1; /* reduce to first segment */
    
    osSQL.Printf("SELECT ID,%s,rowid FROM %s", FID_COLUMN, m_pszName);
    /* TODO: handle points in DPM */
    if (EQUAL(m_pszName, "DPM"))
        osSQL += " WHERE SOURADNICE_X IS NULL";
    hStmt = poReader->PrepareStatement(osSQL.c_str());
    
    if (poReader->IsSpatial())
	poReader->ExecuteSQL("BEGIN");

    while(poReader->ExecuteSQL(hStmt) == OGRERR_NONE) {
        /* read values */
        vrValue[0] = sqlite3_column_double(hStmt, 0);
        iFID       = sqlite3_column_double(hStmt, 1);
        rowId      = sqlite3_column_int(hStmt, 2);

        poFeature = (VFKFeatureSQLite *) GetFeatureByIndex(rowId - 1);
        CPLAssert(NULL != poFeature && poFeature->GetFID() == iFID);

        poLine = poDataBlockLines->GetFeature(vrColumn, vrValue, 2, TRUE);
	if (!poLine) {
	    poOgrGeometry = NULL;
	}
	else {
	    poOgrGeometry = poLine->GetGeometry();
	}
	if (!poOgrGeometry || !poFeature->SetGeometry(poOgrGeometry)) {
            CPLDebug("OGR-VFK", "VFKDataBlockSQLite::LoadGeometryLineStringHP(): name=%s fid=%ld "
                     "id=" CPL_FRMT_GUIB " -> %s geometry", m_pszName, iFID, vrValue[0],
                     poOgrGeometry ? "invalid" : "empty");
	    nInvalid++;
            continue;
        }
	
	/* store also geometry in DB */
	if (poReader->IsSpatial() &&
	    SaveGeometryToDB(poOgrGeometry, rowId) != OGRERR_FAILURE &&
	    poOgrGeometry)
	    nGeometries++;
    }
    
    /* update number of geometries in VFK_DB_TABLE table */
    UpdateVfkBlocks(nGeometries);
    
    if (poReader->IsSpatial())
	poReader->ExecuteSQL("COMMIT");

    return nInvalid;
}
Exemplo n.º 5
0
/*!
  \brief Load geometry (linestring SBP layer)

  \return number of invalid features
*/
int VFKDataBlockSQLite::LoadGeometryLineStringSBP()
{
    int       nInvalid, nGeometries, rowId, iIdx;
    CPLString szFType, szFTypeLine;
    
    GUIntBig id, ipcb;
    bool     bValid;
    
    std::vector<int> rowIdFeat;
    CPLString     osSQL;
    sqlite3_stmt *hStmt;
    
    VFKReaderSQLite    *poReader;
    VFKDataBlockSQLite *poDataBlockPoints;
    VFKFeatureSQLite   *poFeature, *poPoint, *poLine;
    
    OGRLineString oOGRLine;
    
    nInvalid  = nGeometries = 0;
    poReader  = (VFKReaderSQLite*) m_poReader;
    poLine    = NULL;
    
    poDataBlockPoints = (VFKDataBlockSQLite *) m_poReader->GetDataBlock("SOBR");
    if (NULL == poDataBlockPoints) {
        CPLError(CE_Failure, CPLE_FileIO, 
                 "Data block %s not found.\n", m_pszName);
        return nInvalid;
    }
    
    poDataBlockPoints->LoadGeometry();

    if (LoadGeometryFromDB()) /* try to load geometry from DB */
	return 0;

    osSQL.Printf("UPDATE %s SET %s = -1", m_pszName, FID_COLUMN);
    poReader->ExecuteSQL(osSQL.c_str());
    bValid = TRUE;
    iIdx = 0;
    for (int i = 0; i < 2; i++) {
	/* first collect linestrings related to HP, OB or DPM
	   then collect rest of linestrings */
        if (i == 0)
            osSQL.Printf("SELECT BP_ID,PORADOVE_CISLO_BODU,PARAMETRY_SPOJENI,_rowid_ FROM '%s' WHERE "
                         "HP_ID IS NOT NULL OR OB_ID IS NOT NULL OR DPM_ID IS NOT NULL "
                         "ORDER BY HP_ID,OB_ID,DPM_ID,PORADOVE_CISLO_BODU", m_pszName);
        else
            osSQL.Printf("SELECT BP_ID,PORADOVE_CISLO_BODU,PARAMETRY_SPOJENI,_rowid_ FROM '%s' WHERE "
                         "OB_ID IS NULL AND HP_ID IS NULL AND DPM_ID IS NULL "
                         "ORDER BY ID,PORADOVE_CISLO_BODU", m_pszName);
	
        hStmt = poReader->PrepareStatement(osSQL.c_str());
    
	if (poReader->IsSpatial())
	    poReader->ExecuteSQL("BEGIN");
	
        while(poReader->ExecuteSQL(hStmt) == OGRERR_NONE) {
            // read values
            id    = sqlite3_column_double(hStmt, 0);
            ipcb  = sqlite3_column_double(hStmt, 1);
            szFType = (char *) sqlite3_column_text(hStmt, 2);
            rowId = sqlite3_column_int(hStmt, 3);

            if (ipcb == 1) {
                poFeature = (VFKFeatureSQLite *) GetFeatureByIndex(iIdx);
                CPLAssert(NULL != poFeature);
                poFeature->SetRowId(rowId);
                
                /* set geometry & reset */
                if (poLine && !SetGeometryLineString(poLine, &oOGRLine,
                                                     bValid, szFTypeLine, rowIdFeat, nGeometries)) {
                    nInvalid++;
                }
                
		bValid = TRUE;
                poLine = poFeature;
                szFTypeLine = szFType;
                iIdx++;
            }
            
            poPoint = (VFKFeatureSQLite *) poDataBlockPoints->GetFeature("ID", id);
	    if (poPoint) {
		OGRPoint *pt = (OGRPoint *) poPoint->GetGeometry();
		if (pt) {
		    oOGRLine.addPoint(pt);
		}
		else {
		    CPLDebug("OGR-VFK", 
			     "Geometry (point ID = " CPL_FRMT_GUIB ") not valid", id);
		    bValid = FALSE;
		}
	    }
	    else {
                CPLDebug("OGR-VFK", 
                         "Point ID = " CPL_FRMT_GUIB " not found (rowid = %d)",
                         id, rowId);
		bValid = FALSE;
            }
	    
	    /* add vertex to the linestring */
	    rowIdFeat.push_back(rowId);
        }

        /* add last line */
        if (poLine && !SetGeometryLineString(poLine, &oOGRLine,
                                             bValid, szFType.c_str(), rowIdFeat, nGeometries)) {
            nInvalid++;
        }
	poLine = NULL;

	if (poReader->IsSpatial())
	    poReader->ExecuteSQL("COMMIT");
    }

    /* update number of geometries in VFK_DB_TABLE table */
    UpdateVfkBlocks(nGeometries);
    
    return nInvalid;
}
Exemplo n.º 6
0
/*!
  \brief Set geometry for linestrings

  \param poLine VFK feature
  \param oOGRLine line geometry
  \param[in,out] bValid TRUE when feature's geometry is valid
  \param[in,out] rowIdFeat list of row ids which forms linestring
  \param[in,out] nGeometries number of features with valid geometry
*/
bool VFKDataBlockSQLite::SetGeometryLineString(VFKFeatureSQLite *poLine, OGRLineString *oOGRLine,
                                               bool& bValid, const char *ftype,
                                               std::vector<int>& rowIdFeat, int& nGeometries)
{
    int              npoints;
    VFKReaderSQLite *poReader;

    poReader  = (VFKReaderSQLite*) m_poReader;

    oOGRLine->setCoordinateDimension(2); /* force 2D */

    /* check also VFK validity */
    if (bValid) {
        /* Feature types
           
           - '3'    - line       (2 points)
           - '4'    - linestring (at least 2 points)
           - '11'   - curve      (at least 2 points)
           - '15'   - circle     (3 points)
           - '15 r' - circle     (center point & radius)
           - '16'   - arc        (3 points)
        */

        npoints = oOGRLine->getNumPoints();
        if (EQUAL(ftype, "3") && npoints > 2) {
            /* be less pedantic, just inform user about data
             * inconsistency

               bValid = FALSE;
            */
            CPLDebug("OGR-VFK", 
                     "Line (fid=" CPL_FRMT_GIB ") defined by more than two vertices",
                     poLine->GetFID());
        }
        else if (EQUAL(ftype, "11") && npoints < 2) { 
            bValid = FALSE;
            CPLError(CE_Warning, CPLE_AppDefined, 
                     "Curve (fid=" CPL_FRMT_GIB ") defined by less than two vertices",
                     poLine->GetFID());
        }
        else if (EQUAL(ftype, "15") && npoints != 3) {
            bValid = FALSE;
            CPLError(CE_Warning, CPLE_AppDefined, 
                     "Circle (fid=" CPL_FRMT_GIB ") defined by invalid number of vertices (%d)",
                     poLine->GetFID(), oOGRLine->getNumPoints());
        }
        else if (strlen(ftype) > 2 && EQUALN(ftype, "15", 2) && npoints != 1) {
            bValid = FALSE;
            CPLError(CE_Warning, CPLE_AppDefined, 
                     "Circle (fid=" CPL_FRMT_GIB ") defined by invalid number of vertices (%d)",
                     poLine->GetFID(), oOGRLine->getNumPoints());
        }
        else if (EQUAL(ftype, "16") && npoints != 3) {
            bValid = FALSE;
            CPLError(CE_Warning, CPLE_AppDefined, 
                     "Arc (fid=" CPL_FRMT_GIB ") defined by invalid number of vertices (%d)",
                     poLine->GetFID(), oOGRLine->getNumPoints());
        }
    }

    /* set geometry (NULL for invalid features) */
    if (bValid) {
        if (!poLine->SetGeometry(oOGRLine, ftype)) {
            bValid = FALSE;
        }
    }
    else {
        poLine->SetGeometry(NULL);
    }
    
    /* update fid column */
    UpdateFID(poLine->GetFID(), rowIdFeat);        
    
    /* store also geometry in DB */
    CPLAssert(0 != rowIdFeat.size());
    if (bValid && poReader->IsSpatial() &&
        SaveGeometryToDB(bValid ? poLine->GetGeometry() : NULL,
                         rowIdFeat[0]) != OGRERR_FAILURE)
        nGeometries++;

    rowIdFeat.clear();
    oOGRLine->empty(); /* restore line */

    return bValid;
}