void Polygon::update(const std::string& wkt_or_json, SpatialReference ref) { bool isJson = wkt_or_json.find("{") != wkt_or_json.npos || wkt_or_json.find("}") != wkt_or_json.npos; if (!isJson) { m_geom = GEOSGeomFromWKT_r(m_ctx, wkt_or_json.c_str()); if (!m_geom) throw pdal_error("Unable to create geometry from input WKT"); } else { // Assume it is GeoJSON and try constructing from that OGRGeometryH json = OGR_G_CreateGeometryFromJson(wkt_or_json.c_str()); if (!json) throw pdal_error("Unable to create geometry from " "input GeoJSON"); char* gdal_wkt(0); OGRErr err = OGR_G_ExportToWkt(json, &gdal_wkt); m_geom = GEOSGeomFromWKT_r(m_ctx, gdal_wkt); //ABELL - Why should this ever throw? Is it worth catching if // we don't know why? if (!m_geom) throw pdal_error("Unable to create GEOS geometry from OGR WKT!"); OGRFree(gdal_wkt); OGR_G_DestroyGeometry(json); } prepare(); }
void Crop::ready(PointContext ctx) { #ifdef PDAL_HAVE_GEOS if (!m_poly.empty()) { m_geosEnvironment = initGEOS_r(pdal::geos::_GEOSWarningHandler, pdal::geos::_GEOSErrorHandler); m_geosGeometry = GEOSGeomFromWKT_r(m_geosEnvironment, m_poly.c_str()); if (!m_geosGeometry) throw pdal_error("unable to import polygon WKT"); int gtype = GEOSGeomTypeId_r(m_geosEnvironment, m_geosGeometry); if (!(gtype == GEOS_POLYGON || gtype == GEOS_MULTIPOLYGON)) throw pdal_error("input WKT was not a POLYGON or MULTIPOLYGON"); char* out_wkt = GEOSGeomToWKT_r(m_geosEnvironment, m_geosGeometry); log()->get(LogLevel::Debug2) << "Ingested WKT for filters.crop: " << std::string(out_wkt) <<std::endl; GEOSFree_r(m_geosEnvironment, out_wkt); if (!GEOSisValid_r(m_geosEnvironment, m_geosGeometry)) { char* reason = GEOSisValidReason_r(m_geosEnvironment, m_geosGeometry); std::ostringstream oss; oss << "WKT is invalid: " << std::string(reason) << std::endl; GEOSFree_r(m_geosEnvironment, reason); throw pdal_error(oss.str()); } m_geosPreparedGeometry = GEOSPrepare_r(m_geosEnvironment, m_geosGeometry); if (!m_geosPreparedGeometry) throw pdal_error("unable to prepare geometry for " "index-accelerated intersection"); m_bounds = computeBounds(m_geosGeometry); log()->get(LogLevel::Debug) << "Computed bounds from given WKT: " << m_bounds <<std::endl; } else { log()->get(LogLevel::Debug) << "Using simple bounds for " "filters.crop: " << m_bounds << std::endl; } #endif }
static CPLErr BlendMaskGenerator( #ifndef HAVE_GEOS CPL_UNUSED int nXOff, CPL_UNUSED int nYOff, CPL_UNUSED int nXSize, CPL_UNUSED int nYSize, CPL_UNUSED GByte *pabyPolyMask, CPL_UNUSED float *pafValidityMask, CPL_UNUSED OGRGeometryH hPolygon, CPL_UNUSED double dfBlendDist #else int nXOff, int nYOff, int nXSize, int nYSize, GByte *pabyPolyMask, float *pafValidityMask, OGRGeometryH hPolygon, double dfBlendDist #endif ) { #ifndef HAVE_GEOS CPLError( CE_Failure, CPLE_AppDefined, "Blend distance support not available without the GEOS library."); return CE_Failure; #else /* HAVE_GEOS */ /* -------------------------------------------------------------------- */ /* Convert the polygon into a collection of lines so that we */ /* measure distance from the edge even on the inside. */ /* -------------------------------------------------------------------- */ OGRGeometry *poLines = OGRGeometryFactory::forceToMultiLineString( ((OGRGeometry *) hPolygon)->clone() ); /* -------------------------------------------------------------------- */ /* Prepare a clipping polygon a bit bigger than the area of */ /* interest in the hopes of simplifying the cutline down to */ /* stuff that will be relavent for this area of interest. */ /* -------------------------------------------------------------------- */ CPLString osClipRectWKT; osClipRectWKT.Printf( "POLYGON((%g %g,%g %g,%g %g,%g %g,%g %g))", nXOff - (dfBlendDist+1), nYOff - (dfBlendDist+1), nXOff + nXSize + (dfBlendDist+1), nYOff - (dfBlendDist+1), nXOff + nXSize + (dfBlendDist+1), nYOff + nYSize + (dfBlendDist+1), nXOff - (dfBlendDist+1), nYOff + nYSize + (dfBlendDist+1), nXOff - (dfBlendDist+1), nYOff - (dfBlendDist+1) ); OGRPolygon *poClipRect = NULL; char *pszWKT = (char *) osClipRectWKT.c_str(); OGRGeometryFactory::createFromWkt( &pszWKT, NULL, (OGRGeometry**) (&poClipRect) ); if( poClipRect ) { /***** if it doesnt intersect the polym zero the mask and return *****/ if ( ! ((OGRGeometry *) hPolygon)->Intersects( poClipRect ) ) { memset( pafValidityMask, 0, sizeof(float) * nXSize * nYSize ); delete poLines; delete poClipRect; return CE_None; } /***** if it doesnt intersect the line at all just return *****/ else if ( ! ((OGRGeometry *) poLines)->Intersects( poClipRect ) ) { delete poLines; delete poClipRect; return CE_None; } OGRGeometry *poClippedLines = poLines->Intersection( poClipRect ); delete poLines; poLines = poClippedLines; delete poClipRect; } /* -------------------------------------------------------------------- */ /* Convert our polygon into GEOS format, and compute an */ /* envelope to accelerate later distance operations. */ /* -------------------------------------------------------------------- */ OGREnvelope sEnvelope; int iXMin, iYMin, iXMax, iYMax; GEOSContextHandle_t hGEOSCtxt = OGRGeometry::createGEOSContext(); GEOSGeom poGEOSPoly; poGEOSPoly = poLines->exportToGEOS(hGEOSCtxt); OGR_G_GetEnvelope( hPolygon, &sEnvelope ); delete poLines; /***** this check was already done in the calling *****/ /***** function and should never be true *****/ /*if( sEnvelope.MinY - dfBlendDist > nYOff+nYSize || sEnvelope.MaxY + dfBlendDist < nYOff || sEnvelope.MinX - dfBlendDist > nXOff+nXSize || sEnvelope.MaxX + dfBlendDist < nXOff ) return CE_None; */ iXMin = MAX(0,(int) floor(sEnvelope.MinX - dfBlendDist - nXOff)); iXMax = MIN(nXSize, (int) ceil(sEnvelope.MaxX + dfBlendDist - nXOff)); iYMin = MAX(0,(int) floor(sEnvelope.MinY - dfBlendDist - nYOff)); iYMax = MIN(nYSize, (int) ceil(sEnvelope.MaxY + dfBlendDist - nYOff)); /* -------------------------------------------------------------------- */ /* Loop over potential area within blend line distance, */ /* processing each pixel. */ /* -------------------------------------------------------------------- */ int iY, iX; double dfLastDist; for( iY = 0; iY < nYSize; iY++ ) { dfLastDist = 0.0; for( iX = 0; iX < nXSize; iX++ ) { if( iX < iXMin || iX >= iXMax || iY < iYMin || iY > iYMax || dfLastDist > dfBlendDist + 1.5 ) { if( pabyPolyMask[iX + iY * nXSize] == 0 ) pafValidityMask[iX + iY * nXSize] = 0.0; dfLastDist -= 1.0; continue; } double dfDist, dfRatio; CPLString osPointWKT; GEOSGeom poGEOSPoint; osPointWKT.Printf( "POINT(%d.5 %d.5)", iX + nXOff, iY + nYOff ); poGEOSPoint = GEOSGeomFromWKT_r( hGEOSCtxt, osPointWKT ); GEOSDistance_r( hGEOSCtxt, poGEOSPoly, poGEOSPoint, &dfDist ); GEOSGeom_destroy_r( hGEOSCtxt, poGEOSPoint ); dfLastDist = dfDist; if( dfDist > dfBlendDist ) { if( pabyPolyMask[iX + iY * nXSize] == 0 ) pafValidityMask[iX + iY * nXSize] = 0.0; continue; } if( pabyPolyMask[iX + iY * nXSize] == 0 ) { /* outside */ dfRatio = 0.5 - (dfDist / dfBlendDist) * 0.5; } else { /* inside */ dfRatio = 0.5 + (dfDist / dfBlendDist) * 0.5; } pafValidityMask[iX + iY * nXSize] *= (float)dfRatio; } } /* -------------------------------------------------------------------- */ /* Cleanup */ /* -------------------------------------------------------------------- */ GEOSGeom_destroy_r( hGEOSCtxt, poGEOSPoly ); OGRGeometry::freeGEOSContext( hGEOSCtxt ); return CE_None; #endif /* HAVE_GEOS */ }