コード例 #1
0
/*!
  \brief Load geometry (polygon BUD/PAR layers)

  \return number of invalid features
*/
int VFKDataBlockDB::LoadGeometryPolygon()
{
    int  nInvalidNoLines, nInvalidNoRings, nGeometries, nBridges;
    int  rowId, nCount, nCountMax;
    size_t nLines;
    GIntBig iFID;
    bool bIsPar, bNewRing, bFound;

    CPLString    osSQL;
    const char  *vrColumn[2];
    GUIntBig     vrValue[2];
    GUIntBig     id, idOb;

    sqlite3_stmt *hStmt;

    VFKReaderDB    *poReader;
    VFKDataBlockDB *poDataBlockLines1, *poDataBlockLines2;
    VFKFeatureDB   *poFeature;

    VFKFeatureDBList  poLineList;
    /* first is to be considered as exterior */
    PointListArray        poRingList;

    std::vector<OGRLinearRing *> poLinearRingList;
    OGRPolygon     ogrPolygon;
    OGRLinearRing *poOgrRing;

    nInvalidNoLines = nInvalidNoRings = nGeometries = 0;
    poReader  = (VFKReaderDB*) m_poReader;

    if (EQUAL (m_pszName, "PAR")) {
        poDataBlockLines1 = (VFKDataBlockDB *) m_poReader->GetDataBlock("HP");
        poDataBlockLines2 = poDataBlockLines1;
        bIsPar = TRUE;
    }
    else {
        poDataBlockLines1 = (VFKDataBlockDB *) m_poReader->GetDataBlock("OB");
        poDataBlockLines2 = (VFKDataBlockDB *) 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;

    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);
    if (poReader->IsSpatial())
	poReader->ExecuteSQL("BEGIN");

    std::vector<VFKDbValue> record;
    record.push_back(VFKDbValue(DT_BIGINT));
    record.push_back(VFKDbValue(DT_BIGINT));
    record.push_back(VFKDbValue(DT_INT));
    poReader->PrepareStatement(osSQL.c_str());
    while(poReader->ExecuteSQL(record) == OGRERR_NONE) {
        nBridges = 0;

        /* read values */
        id        = static_cast<GIntBig> (record[0]);
        iFID      = static_cast<GIntBig> (record[1]);
        rowId     = static_cast<int> (record[2]);

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

        if (bIsPar) {
            vrValue[0] = vrValue[1] = id;
            poLineList = poDataBlockLines1->GetFeatures(vrColumn, vrValue, 2);
        }
        else {
            VFKFeatureDB *poLineSbp;
            std::vector<VFKFeatureDB *> 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;
            }

            std::vector<VFKDbValue> record1;
            record1.push_back(VFKDbValue(DT_BIGINT));
            poReader->PrepareStatement(osSQL.c_str(), 1);
            while(poReader->ExecuteSQL(record, 1) == OGRERR_NONE) {
                idOb = static_cast<GIntBig> (record[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 = static_cast<int>(nLines) * 2;
	while (poLineList.size() > 0 && nCount < nCountMax) {
            bNewRing = !bFound ? TRUE : FALSE;
            bFound = FALSE;
            int i = 1;
            for (VFKFeatureDBList::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;
}
コード例 #2
0
ファイル: vfkdatablock.cpp プロジェクト: sylvainallard/gdal
/*!
  \brief Load geometry (polygon BUD/PAR layers)

  \return number of invalid features
*/
int VFKDataBlock::LoadGeometryPolygon()
{
    long nInvalid;
    bool bIsPar, bNewRing, bFound;
        
    GUIntBig id, idOb;
    int  nCount, nCountMax;
    int idxId, idxPar1, idxPar2, idxBud, idxOb, idxIdOb;
    
    VFKFeature   *poFeature;
    VFKDataBlock *poDataBlockLines1, *poDataBlockLines2;
    
    VFKFeatureList   poLineList;
    PointListArray   poRingList; /* first is to be considered as exterior */
    
    OGRLinearRing ogrRing;
    OGRPolygon    ogrPolygon;
    
    idxPar1 = idxPar2 = idxBud = idxOb = idxIdOb = 0;
    nInvalid = 0;
    if (EQUAL (m_pszName, "PAR")) {
        poDataBlockLines1 = (VFKDataBlock *) m_poReader->GetDataBlock("HP");
        poDataBlockLines2 = poDataBlockLines1;
        bIsPar = TRUE;
    }
    else {
        poDataBlockLines1 = (VFKDataBlock *) m_poReader->GetDataBlock("OB");
        poDataBlockLines2 = (VFKDataBlock *) m_poReader->GetDataBlock("SBP");
        bIsPar = FALSE;
    }
    if (NULL == poDataBlockLines1 || NULL == poDataBlockLines2) {
        CPLError(CE_Failure, CPLE_NotSupported, 
                 "Data block %s not found.\n", m_pszName);
        return nInvalid;
    }
    
    poDataBlockLines1->LoadGeometry();
    poDataBlockLines2->LoadGeometry();
    idxId = GetPropertyIndex("ID");
    if (idxId < 0) {
        CPLError(CE_Failure, CPLE_NotSupported, 
                 "Corrupted data (%s).\n", m_pszName);
        return nInvalid;
    }
    
    if (bIsPar) {
        idxPar1 = poDataBlockLines1->GetPropertyIndex("PAR_ID_1");
        idxPar2 = poDataBlockLines1->GetPropertyIndex("PAR_ID_2");
        if (idxPar1 < 0 || idxPar2 < 0) {
            CPLError(CE_Failure, CPLE_NotSupported, 
                     "Corrupted data (%s).\n", m_pszName);
            return nInvalid;
        }
    }
    else { /* BUD */
        idxIdOb  = poDataBlockLines1->GetPropertyIndex("ID");
        idxBud = poDataBlockLines1->GetPropertyIndex("BUD_ID");
        idxOb  = poDataBlockLines2->GetPropertyIndex("OB_ID");
        if (idxIdOb < 0 || idxBud < 0 || idxOb < 0) {
            CPLError(CE_Failure, CPLE_NotSupported, 
                     "Corrupted data (%s).\n", m_pszName);
            return nInvalid;
        }
    }
    
    for (int i = 0; i < ((IVFKDataBlock *) this)->GetFeatureCount(); i++) {
        poFeature = (VFKFeature *) GetFeatureByIndex(i);
        id = strtoul(poFeature->GetProperty(idxId)->GetValueS(), NULL, 0);
        if (bIsPar) {
            poLineList = poDataBlockLines1->GetFeatures(idxPar1, idxPar2, id);
        }
        else {
            VFKFeature *poLineOb, *poLineSbp;
            std::vector<VFKFeature *> poLineListOb;
            poLineListOb = poDataBlockLines1->GetFeatures(idxBud, id);
            for (std::vector<VFKFeature *>::const_iterator iOb = poLineListOb.begin(), eOb = poLineListOb.end();
                 iOb != eOb; ++iOb) {
                poLineOb = (*iOb);
                idOb = strtoul(poLineOb->GetProperty(idxIdOb)->GetValueS(), NULL, 0);
                poLineSbp = poDataBlockLines2->GetFeature(idxOb, idOb);
                if (poLineSbp)
                    poLineList.push_back(poLineSbp);
            }
        }
        if (poLineList.size() < 1)
            continue;
        
        /* clear */
        ogrPolygon.empty();
        poRingList.clear();
        
        /* collect rings (points) */
        bFound = FALSE;
        nCount = 0;
        nCountMax = poLineList.size() * 2;
        while (poLineList.size() > 0 && nCount < nCountMax) {
            bNewRing = !bFound ? TRUE : FALSE;
            bFound = FALSE;
            for (VFKFeatureList::iterator iHp = poLineList.begin(), eHp = poLineList.end();
                 iHp != eHp; ++iHp) {
                const OGRLineString *pLine = (OGRLineString *) (*iHp)->GetGeometry();
                if (pLine && AppendLineToRing(&poRingList, pLine, bNewRing)) {
                    bFound = TRUE;
                    poLineList.erase(iHp);
                    break;
                }
            }
            nCount++;
        }
        /* create rings */
        for (PointListArray::const_iterator iRing = poRingList.begin(), eRing = poRingList.end();
             iRing != eRing; ++iRing) {
            PointList *poList = *iRing;
            ogrRing.empty();
            for (PointList::iterator iPoint = poList->begin(), ePoint = poList->end();
                 iPoint != ePoint; ++iPoint) {
                ogrRing.addPoint(&(*iPoint));
            }
            ogrPolygon.addRing(&ogrRing);
        }
        /* set polygon */
        ogrPolygon.setCoordinateDimension(2); /* force 2D */
        if (!poFeature->SetGeometry(&ogrPolygon))
            nInvalid++;
    }
    
    /* free ring list */
    for (PointListArray::iterator iRing = poRingList.begin(),
             eRing = poRingList.end(); iRing != eRing; ++iRing) {
        delete (*iRing);
        *iRing = NULL;
    }
    poDataBlockLines1->ResetReading();
    poDataBlockLines2->ResetReading();

    return nInvalid;
}