OGRErr OGROCIWritableLayer::TranslateElementGroup( OGRGeometry *poGeometry ) { switch( wkbFlatten(poGeometry->getGeometryType()) ) { case wkbPoint: { OGRPoint *poPoint = (OGRPoint *) poGeometry; PushElemInfo( nOrdinalCount+1, 1, 1 ); PushOrdinal( poPoint->getX() ); PushOrdinal( poPoint->getY() ); if( nDimension == 3 ) PushOrdinal( poPoint->getZ() ); return OGRERR_NONE; } case wkbLineString: { OGRLineString *poLine = (OGRLineString *) poGeometry; int iVert; PushElemInfo( nOrdinalCount+1, 2, 1 ); for( iVert = 0; iVert < poLine->getNumPoints(); iVert++ ) { PushOrdinal( poLine->getX(iVert) ); PushOrdinal( poLine->getY(iVert) ); if( nDimension == 3 ) PushOrdinal( poLine->getZ(iVert) ); } return OGRERR_NONE; } case wkbPolygon: { OGRPolygon *poPoly = (OGRPolygon *) poGeometry; int iRing; for( iRing = -1; iRing < poPoly->getNumInteriorRings(); iRing++ ) { OGRLinearRing *poRing; int iVert; if( iRing == -1 ) poRing = poPoly->getExteriorRing(); else poRing = poPoly->getInteriorRing(iRing); if( iRing == -1 ) PushElemInfo( nOrdinalCount+1, 1003, 1 ); else PushElemInfo( nOrdinalCount+1, 2003, 1 ); if( (iRing == -1 && poRing->isClockwise()) || (iRing != -1 && !poRing->isClockwise()) ) { for( iVert = poRing->getNumPoints()-1; iVert >= 0; iVert-- ) { PushOrdinal( poRing->getX(iVert) ); PushOrdinal( poRing->getY(iVert) ); if( nDimension == 3 ) PushOrdinal( poRing->getZ(iVert) ); } } else { for( iVert = 0; iVert < poRing->getNumPoints(); iVert++ ) { PushOrdinal( poRing->getX(iVert) ); PushOrdinal( poRing->getY(iVert) ); if( nDimension == 3 ) PushOrdinal( poRing->getZ(iVert) ); } } } return OGRERR_NONE; } default: { return OGRERR_FAILURE; } } }
OGRGeometryH OGRBuildPolygonFromEdges( OGRGeometryH hLines, int bBestEffort, int bAutoClose, double dfTolerance, OGRErr * peErr ) { int bSuccess = TRUE; OGRGeometryCollection *poLines = (OGRGeometryCollection *) hLines; OGRPolygon *poPolygon = new OGRPolygon(); (void) bBestEffort; /* -------------------------------------------------------------------- */ /* Setup array of line markers indicating if they have been */ /* added to a ring yet. */ /* -------------------------------------------------------------------- */ int nEdges = poLines->getNumGeometries(); int *panEdgeConsumed, nRemainingEdges = nEdges; panEdgeConsumed = (int *) CPLCalloc(sizeof(int),nEdges); /* ==================================================================== */ /* Loop generating rings. */ /* ==================================================================== */ while( nRemainingEdges > 0 ) { int iEdge; OGRLineString *poLine; /* -------------------------------------------------------------------- */ /* Find the first unconsumed edge. */ /* -------------------------------------------------------------------- */ for( iEdge = 0; panEdgeConsumed[iEdge]; iEdge++ ) {} poLine = (OGRLineString *) poLines->getGeometryRef(iEdge); /* -------------------------------------------------------------------- */ /* Start a new ring, copying in the current line directly */ /* -------------------------------------------------------------------- */ OGRLinearRing *poRing = new OGRLinearRing(); AddEdgeToRing( poRing, poLine, FALSE ); panEdgeConsumed[iEdge] = TRUE; nRemainingEdges--; /* ==================================================================== */ /* Loop adding edges to this ring until we make a whole pass */ /* within finding anything to add. */ /* ==================================================================== */ int bWorkDone = TRUE; double dfBestDist = dfTolerance; while( !CheckPoints(poRing,0,poRing,poRing->getNumPoints()-1,NULL) && nRemainingEdges > 0 && bWorkDone ) { int iBestEdge = -1, bReverse = FALSE; bWorkDone = FALSE; dfBestDist = dfTolerance; // We consider linking the end to the beginning. If this is // closer than any other option we will just close the loop. //CheckPoints(poRing,0,poRing,poRing->getNumPoints()-1,&dfBestDist); // Find unused edge with end point closest to our loose end. for( iEdge = 0; iEdge < nEdges; iEdge++ ) { if( panEdgeConsumed[iEdge] ) continue; poLine = (OGRLineString *) poLines->getGeometryRef(iEdge); if( CheckPoints(poLine,0,poRing,poRing->getNumPoints()-1, &dfBestDist) ) { iBestEdge = iEdge; bReverse = FALSE; } if( CheckPoints(poLine,poLine->getNumPoints()-1, poRing,poRing->getNumPoints()-1, &dfBestDist) ) { iBestEdge = iEdge; bReverse = TRUE; } } // We found one within tolerance - add it. if( iBestEdge != -1 ) { poLine = (OGRLineString *) poLines->getGeometryRef(iBestEdge); AddEdgeToRing( poRing, poLine, bReverse ); panEdgeConsumed[iBestEdge] = TRUE; nRemainingEdges--; bWorkDone = TRUE; } } /* -------------------------------------------------------------------- */ /* Did we fail to complete the ring? */ /* -------------------------------------------------------------------- */ dfBestDist = dfTolerance; if( !CheckPoints(poRing,0,poRing,poRing->getNumPoints()-1, &dfBestDist) ) { CPLDebug( "OGR", "Failed to close ring %d.\n" "End Points are: (%.8f,%.7f) and (%.7f,%.7f)\n", poPolygon->getNumInteriorRings()+1, poRing->getX(0), poRing->getY(0), poRing->getX(poRing->getNumPoints()-1), poRing->getY(poRing->getNumPoints()-1) ); bSuccess = FALSE; } /* -------------------------------------------------------------------- */ /* Do we need to auto-close this ring? */ /* -------------------------------------------------------------------- */ if( bAutoClose && !CheckPoints(poRing,0,poRing,poRing->getNumPoints()-1,NULL) ) { poRing->addPoint( poRing->getX(0), poRing->getY(0), poRing->getZ(0)); } poPolygon->addRingDirectly( poRing ); } /* next ring */ /* -------------------------------------------------------------------- */ /* Cleanup. */ /* -------------------------------------------------------------------- */ CPLFree( panEdgeConsumed ); // Eventually we should at least identify the external ring properly, // perhaps even ordering the direction of rings, though this isn't // required by the OGC geometry model. if( peErr != NULL ) { if( bSuccess ) *peErr = OGRERR_NONE; else *peErr = OGRERR_FAILURE; } return (OGRGeometryH) poPolygon; }
static void GDALCollectRingsFromGeometry( OGRGeometry *poShape, std::vector<double> &aPointX, std::vector<double> &aPointY, std::vector<double> &aPointVariant, std::vector<int> &aPartSize, GDALBurnValueSrc eBurnValueSrc) { if( poShape == NULL ) return; OGRwkbGeometryType eFlatType = wkbFlatten(poShape->getGeometryType()); int i; if ( eFlatType == wkbPoint ) { OGRPoint *poPoint = (OGRPoint *) poShape; int nNewCount = aPointX.size() + 1; aPointX.reserve( nNewCount ); aPointY.reserve( nNewCount ); aPointX.push_back( poPoint->getX() ); aPointY.push_back( poPoint->getY() ); aPartSize.push_back( 1 ); if( eBurnValueSrc != GBV_UserBurnValue ) { /*switch( eBurnValueSrc ) { case GBV_Z:*/ aPointVariant.reserve( nNewCount ); aPointVariant.push_back( poPoint->getZ() ); /*break; case GBV_M: aPointVariant.reserve( nNewCount ); aPointVariant.push_back( poPoint->getM() ); }*/ } } else if ( eFlatType == wkbLineString ) { OGRLineString *poLine = (OGRLineString *) poShape; int nCount = poLine->getNumPoints(); int nNewCount = aPointX.size() + nCount; aPointX.reserve( nNewCount ); aPointY.reserve( nNewCount ); if( eBurnValueSrc != GBV_UserBurnValue ) aPointVariant.reserve( nNewCount ); for ( i = nCount - 1; i >= 0; i-- ) { aPointX.push_back( poLine->getX(i) ); aPointY.push_back( poLine->getY(i) ); if( eBurnValueSrc != GBV_UserBurnValue ) { /*switch( eBurnValueSrc ) { case GBV_Z:*/ aPointVariant.push_back( poLine->getZ(i) ); /*break; case GBV_M: aPointVariant.push_back( poLine->getM(i) ); }*/ } } aPartSize.push_back( nCount ); } else if ( EQUAL(poShape->getGeometryName(),"LINEARRING") ) { OGRLinearRing *poRing = (OGRLinearRing *) poShape; int nCount = poRing->getNumPoints(); int nNewCount = aPointX.size() + nCount; aPointX.reserve( nNewCount ); aPointY.reserve( nNewCount ); if( eBurnValueSrc != GBV_UserBurnValue ) aPointVariant.reserve( nNewCount ); for ( i = nCount - 1; i >= 0; i-- ) { aPointX.push_back( poRing->getX(i) ); aPointY.push_back( poRing->getY(i) ); } if( eBurnValueSrc != GBV_UserBurnValue ) { /*switch( eBurnValueSrc ) { case GBV_Z:*/ aPointVariant.push_back( poRing->getZ(i) ); /*break; case GBV_M: aPointVariant.push_back( poRing->getM(i) ); }*/ } aPartSize.push_back( nCount ); } else if( eFlatType == wkbPolygon ) { OGRPolygon *poPolygon = (OGRPolygon *) poShape; GDALCollectRingsFromGeometry( poPolygon->getExteriorRing(), aPointX, aPointY, aPointVariant, aPartSize, eBurnValueSrc ); for( i = 0; i < poPolygon->getNumInteriorRings(); i++ ) GDALCollectRingsFromGeometry( poPolygon->getInteriorRing(i), aPointX, aPointY, aPointVariant, aPartSize, eBurnValueSrc ); } else if( eFlatType == wkbMultiPoint || eFlatType == wkbMultiLineString || eFlatType == wkbMultiPolygon || eFlatType == wkbGeometryCollection ) { OGRGeometryCollection *poGC = (OGRGeometryCollection *) poShape; for( i = 0; i < poGC->getNumGeometries(); i++ ) GDALCollectRingsFromGeometry( poGC->getGeometryRef(i), aPointX, aPointY, aPointVariant, aPartSize, eBurnValueSrc ); } else { CPLDebug( "GDAL", "Rasterizer ignoring non-polygonal geometry." ); } }
int NBHeightMapper::loadShapeFile(const std::string& file) { #ifdef HAVE_GDAL #if GDAL_VERSION_MAJOR < 2 OGRRegisterAll(); OGRDataSource* ds = OGRSFDriverRegistrar::Open(file.c_str(), FALSE); #else GDALAllRegister(); GDALDataset* ds = (GDALDataset*)GDALOpenEx(file.c_str(), GDAL_OF_VECTOR | GA_ReadOnly, NULL, NULL, NULL); #endif if (ds == NULL) { throw ProcessError("Could not open shape file '" + file + "'."); } // begin file parsing OGRLayer* layer = ds->GetLayer(0); layer->ResetReading(); // triangle coordinates are stored in WGS84 and later matched with network coordinates in WGS84 // build coordinate transformation OGRSpatialReference* sr_src = layer->GetSpatialRef(); OGRSpatialReference sr_dest; sr_dest.SetWellKnownGeogCS("WGS84"); OGRCoordinateTransformation* toWGS84 = OGRCreateCoordinateTransformation(sr_src, &sr_dest); if (toWGS84 == 0) { WRITE_WARNING("Could not create geocoordinates converter; check whether proj.4 is installed."); } int numFeatures = 0; OGRFeature* feature; layer->ResetReading(); while ((feature = layer->GetNextFeature()) != NULL) { OGRGeometry* geom = feature->GetGeometryRef(); assert(geom != 0); // @todo gracefull handling of shapefiles with unexpected contents or any error handling for that matter assert(std::string(geom->getGeometryName()) == std::string("POLYGON")); // try transform to wgs84 geom->transform(toWGS84); OGRLinearRing* cgeom = ((OGRPolygon*) geom)->getExteriorRing(); // assume TIN with with 4 points and point0 == point3 assert(cgeom->getNumPoints() == 4); PositionVector corners; for (int j = 0; j < 3; j++) { Position pos((double) cgeom->getX(j), (double) cgeom->getY(j), (double) cgeom->getZ(j)); corners.push_back(pos); myBoundary.add(pos); } addTriangle(corners); numFeatures++; /* OGRwkbGeometryType gtype = geom->getGeometryType(); switch (gtype) { case wkbPolygon: { break; } case wkbPoint: { WRITE_WARNING("got wkbPoint"); break; } case wkbLineString: { WRITE_WARNING("got wkbLineString"); break; } case wkbMultiPoint: { WRITE_WARNING("got wkbMultiPoint"); break; } case wkbMultiLineString: { WRITE_WARNING("got wkbMultiLineString"); break; } case wkbMultiPolygon: { WRITE_WARNING("got wkbMultiPolygon"); break; } default: WRITE_WARNING("Unsupported shape type occurred"); break; } */ OGRFeature::DestroyFeature(feature); } #if GDAL_VERSION_MAJOR < 2 OGRDataSource::DestroyDataSource(ds); #else GDALClose(ds); #endif OCTDestroyCoordinateTransformation(toWGS84); OGRCleanupAll(); return numFeatures; #else UNUSED_PARAMETER(file); WRITE_ERROR("Cannot load shape file since SUMO was compiled without GDAL support."); return 0; #endif }