/*! \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; }
/*! \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; }
/*! \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; }
/*! \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; }
/*! \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; }
/*! \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; }