/*! \brief Load geometry (polygon BUD/PAR layers) \return number of invalid features */ int VFKDataBlockSQLite::LoadGeometryPolygon() { VFKReaderSQLite *poReader = (VFKReaderSQLite*) m_poReader; VFKDataBlockSQLite *poDataBlockLines1 = NULL; VFKDataBlockSQLite *poDataBlockLines2 = NULL; bool bIsPar = false; 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 ) { CPLError(CE_Warning, CPLE_FileIO, "Data block %s not found. Unable to build geometry for %s.", bIsPar ? "HP" : "OB", m_pszName); return -1; } if( NULL == poDataBlockLines2 ) { CPLError(CE_Warning, CPLE_FileIO, "Data block %s not found. Unable to build geometry for %s.", "SBP", m_pszName); return -1; } poDataBlockLines1->LoadGeometry(); poDataBlockLines2->LoadGeometry(); if( LoadGeometryFromDB() ) // Try to load geometry from DB. return 0; const char *vrColumn[2] = { NULL, NULL }; GUIntBig vrValue[2] = { 0, 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; } CPLString osSQL; osSQL.Printf("SELECT ID,%s,rowid FROM %s", FID_COLUMN, m_pszName); sqlite3_stmt *hStmt = poReader->PrepareStatement(osSQL.c_str()); if (poReader->IsSpatial()) poReader->ExecuteSQL("BEGIN"); VFKFeatureSQLiteList poLineList; /* first is to be considered as exterior */ PointListArray poRingList; std::vector<OGRLinearRing *> poLinearRingList; OGRPolygon ogrPolygon; int nInvalidNoLines = 0; int nInvalidNoRings = 0; int nGeometries = 0; while(poReader->ExecuteSQL(hStmt) == OGRERR_NONE) { /* read values */ const GUIntBig id = sqlite3_column_int64(hStmt, 0); const long iFID = static_cast<long>(sqlite3_column_int64(hStmt, 1)); const int rowId = sqlite3_column_int(hStmt, 2); VFKFeatureSQLite *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 { // std::vector<VFKFeatureSQLite *> poLineListOb; 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; } sqlite3_stmt *hStmtOb = poReader->PrepareStatement(osSQL.c_str()); while(poReader->ExecuteSQL(hStmtOb) == OGRERR_NONE) { const GUIntBig idOb = sqlite3_column_int64(hStmtOb, 0); vrValue[0] = idOb; VFKFeatureSQLite *poLineSbp = poDataBlockLines2->GetFeature(vrColumn, vrValue, 2); if (poLineSbp) poLineList.push_back(poLineSbp); } } size_t 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 */ bool bFound = false; int nCount = 0; const int nCountMax = static_cast<int>(nLines) * 2; while( poLineList.size() > 0 && nCount < nCountMax ) { bool bNewRing = !bFound; 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(); OGRLinearRing *poOgrRing = NULL; int i = 1; for( PointListArray::const_iterator iRing = poRingList.begin(), eRing = poRingList.end(); iRing != eRing; ++iRing) { 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) { OGRPoint *poPoint = &(*iPoint); poOgrRing->addPoint(poPoint); } i++; } /* find exterior ring */ if( poLinearRingList.size() > 1 ) { std::vector<OGRLinearRing *>::iterator exteriorRing; exteriorRing = poLinearRingList.begin(); double dMaxArea = -1.0; for( std::vector<OGRLinearRing *>::iterator iRing = poLinearRingList.begin(), eRing = poLinearRingList.end(); iRing != eRing; ++iRing ) { poOgrRing = *iRing; if (!IsRingClosed(poOgrRing)) continue; /* skip unclosed rings */ const double dArea = poOgrRing->get_Area(); if (dArea > dMaxArea) { dMaxArea = dArea; exteriorRing = iRing; } } if (exteriorRing != poLinearRingList.begin()) { std::swap(*poLinearRingList.begin(), *exteriorRing); } } /* build polygon from rings */ int nBridges = 0; 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 from DB \return true if geometry successfully loaded otherwise false */ bool VFKDataBlockSQLite::LoadGeometryFromDB() { VFKReaderSQLite *poReader = (VFKReaderSQLite*) m_poReader; if (!poReader->IsSpatial()) /* check if DB is spatial */ return false; CPLString osSQL; osSQL.Printf("SELECT num_geometries FROM %s WHERE table_name = '%s'", VFK_DB_TABLE, m_pszName); sqlite3_stmt *hStmt = poReader->PrepareStatement(osSQL.c_str()); if (poReader->ExecuteSQL(hStmt) != OGRERR_NONE) return false; const int nGeometries = sqlite3_column_int(hStmt, 0); sqlite3_finalize(hStmt); if( nGeometries < 1 ) return false; const bool bSkipInvalid = EQUAL(m_pszName, "OB") || EQUAL(m_pszName, "OP") || EQUAL(m_pszName, "OBBP"); /* load geometry from DB */ 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()); int rowId = 0; int nInvalid = 0; int nGeometriesCount = 0; while(poReader->ExecuteSQL(hStmt) == OGRERR_NONE) { rowId++; // =sqlite3_column_int(hStmt, 1); #ifdef DEBUG const GIntBig iFID = sqlite3_column_int64(hStmt, 2); #endif VFKFeatureSQLite *poFeature = (VFKFeatureSQLite *) GetFeatureByIndex(rowId - 1); CPLAssert(NULL != poFeature && poFeature->GetFID() == iFID); // read geometry from DB const int nBytes = sqlite3_column_bytes(hStmt, 0); OGRGeometry *poGeometry = NULL; 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 (linestring HP/DPM layer) \return number of invalid features */ int VFKDataBlockSQLite::LoadGeometryLineStringHP() { int nInvalid = 0; VFKReaderSQLite *poReader = (VFKReaderSQLite*) m_poReader; VFKDataBlockSQLite *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; CPLString osColumn; osColumn.Printf("%s_ID", m_pszName); const char *vrColumn[2] = { osColumn.c_str(), "PORADOVE_CISLO_BODU" }; GUIntBig vrValue[2] = { 0, 1 }; // Reduce to first segment. CPLString osSQL; 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"; sqlite3_stmt *hStmt = poReader->PrepareStatement(osSQL.c_str()); if (poReader->IsSpatial()) poReader->ExecuteSQL("BEGIN"); int nGeometries = 0; while( poReader->ExecuteSQL(hStmt) == OGRERR_NONE ) { /* read values */ vrValue[0] = sqlite3_column_int64(hStmt, 0); const long iFID = static_cast<long>(sqlite3_column_int64(hStmt, 1)); const int rowId = sqlite3_column_int(hStmt, 2); VFKFeatureSQLite *poFeature = (VFKFeatureSQLite *) GetFeatureByIndex(rowId - 1); CPLAssert(NULL != poFeature && poFeature->GetFID() == iFID); VFKFeatureSQLite *poLine = poDataBlockLines->GetFeature(vrColumn, vrValue, 2, TRUE); OGRGeometry *poOgrGeometry = NULL; 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; }