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 }
std::string Polygon::validReason() const { int gtype = GEOSGeomTypeId_r(m_ctx, m_geom); if (gtype != GEOS_POLYGON && gtype != GEOS_MULTIPOLYGON) return std::string("Geometry is not Polygon or MultiPolygon"); char *reason = GEOSisValidReason_r(m_ctx, m_geom); std::string output(reason); GEOSFree_r(m_ctx, reason); return output; }
static VALUE method_factory_write_for_psych(VALUE self, VALUE obj) { RGeo_FactoryData* self_data; GEOSContextHandle_t self_context; GEOSWKTWriter* wkt_writer; const GEOSGeometry* geom; VALUE result; char* str; size_t size; char has_3d; #ifndef RGEO_GEOS_SUPPORTS_SETOUTPUTDIMENSION RGeo_Globals* globals; VALUE wkt_generator; #endif self_data = RGEO_FACTORY_DATA_PTR(self); self_context = self_data->geos_context; has_3d = self_data->flags & RGEO_FACTORYFLAGS_SUPPORTS_Z_OR_M; #ifndef RGEO_GEOS_SUPPORTS_SETOUTPUTDIMENSION if (has_3d) { globals = self_data->globals; wkt_generator = globals->psych_wkt_generator; if (NIL_P(wkt_generator)) { wkt_generator = rb_funcall( rb_const_get_at(globals->geos_module, rb_intern("Utils")), rb_intern("psych_wkt_generator"), 0); globals->psych_wkt_generator = wkt_generator; } return rb_funcall(wkt_generator, globals->id_generate, 1, obj); } #endif wkt_writer = self_data->psych_wkt_writer; if (!wkt_writer) { wkt_writer = GEOSWKTWriter_create_r(self_context); if (has_3d) { GEOSWKTWriter_setOutputDimension_r(self_context, wkt_writer, 3); } self_data->psych_wkt_writer = wkt_writer; } result = Qnil; if (wkt_writer) { geom = rgeo_get_geos_geometry_safe(obj); if (geom) { str = GEOSWKTWriter_write_r(self_context, wkt_writer, geom); if (str) { result = rb_str_new2(str); GEOSFree_r(self_context, str); } } } return result; }
std::string Polygon::wkt(double precision, bool bOutputZ) const { GEOSWKTWriter *writer = GEOSWKTWriter_create_r(m_ctx); GEOSWKTWriter_setRoundingPrecision_r(m_ctx, writer, precision); if (bOutputZ) GEOSWKTWriter_setOutputDimension_r(m_ctx, writer, 3); char *smoothWkt = GEOSWKTWriter_write_r(m_ctx, writer, m_geom); std::string output(smoothWkt); GEOSFree_r(m_ctx, smoothWkt); GEOSWKTWriter_destroy_r(m_ctx, writer); return output; }
static VALUE method_geometry_as_text(VALUE self) { VALUE result = Qnil; RGeo_GeometryData* self_data = RGEO_GEOMETRY_DATA_PTR(self); const GEOSGeometry* self_geom = self_data->geom; if (self_geom) { RGeo_FactoryData* factory_data = RGEO_FACTORY_DATA_PTR(self_data->factory); GEOSWKTWriter* wkt_writer = factory_data->wkt_writer; GEOSContextHandle_t geos_context = self_data->geos_context; if (!wkt_writer) { wkt_writer = GEOSWKTWriter_create_r(geos_context); factory_data->wkt_writer = wkt_writer; } char* str = GEOSWKTWriter_write_r(geos_context, wkt_writer, self_geom); if (str) { result = rb_str_new2(str); GEOSFree_r(geos_context, str); } } return result; }
static VALUE method_geometry_as_binary(VALUE self) { VALUE result; RGeo_GeometryData* self_data; const GEOSGeometry* self_geom; RGeo_FactoryData* factory_data; VALUE wkb_generator; GEOSWKBWriter* wkb_writer; GEOSContextHandle_t geos_context; size_t size; char* str; result = Qnil; self_data = RGEO_GEOMETRY_DATA_PTR(self); self_geom = self_data->geom; if (self_geom) { factory_data = RGEO_FACTORY_DATA_PTR(self_data->factory); wkb_generator = factory_data->wkrep_wkb_generator; if (!NIL_P(wkb_generator)) { result = rb_funcall(wkb_generator, factory_data->globals->id_generate, 1, self); } else { wkb_writer = factory_data->wkb_writer; geos_context = self_data->geos_context; if (!wkb_writer) { wkb_writer = GEOSWKBWriter_create_r(geos_context); factory_data->wkb_writer = wkb_writer; } str = (char*)GEOSWKBWriter_write_r(geos_context, wkb_writer, self_geom, &size); if (str) { result = rb_str_new(str, size); GEOSFree_r(geos_context, str); } } } return result; }
void QgsGeometryValidator::run() { mErrorCount = 0; QSettings settings; if ( settings.value( QStringLiteral( "/qgis/digitizing/validate_geometries" ), 1 ).toInt() == 2 ) { char *r = nullptr; const GEOSGeometry *g0 = mG.asGeos(); GEOSContextHandle_t handle = QgsGeometry::getGEOSHandler(); if ( !g0 ) { emit errorFound( QgsGeometry::Error( QObject::tr( "GEOS error:could not produce geometry for GEOS (check log window)" ) ) ); } else { GEOSGeometry *g1 = nullptr; if ( GEOSisValidDetail_r( handle, g0, GEOSVALID_ALLOW_SELFTOUCHING_RING_FORMING_HOLE, &r, &g1 ) != 1 ) { if ( g1 ) { const GEOSCoordSequence *cs = GEOSGeom_getCoordSeq_r( handle, g1 ); unsigned int n; if ( GEOSCoordSeq_getSize_r( handle, cs, &n ) && n == 1 ) { double x, y; GEOSCoordSeq_getX_r( handle, cs, 0, &x ); GEOSCoordSeq_getY_r( handle, cs, 0, &y ); emit errorFound( QgsGeometry::Error( QObject::tr( "GEOS error:%1" ).arg( r ), QgsPoint( x, y ) ) ); mErrorCount++; } GEOSGeom_destroy_r( handle, g1 ); } else { emit errorFound( QgsGeometry::Error( QObject::tr( "GEOS error:%1" ).arg( r ) ) ); mErrorCount++; } GEOSFree_r( handle, r ); } } return; } QgsDebugMsg( "validation thread started." ); QgsWkbTypes::Type flatType = QgsWkbTypes::flatType( mG.wkbType() ); //if ( flatType == QgsWkbTypes::Point || flatType == QgsWkbTypes::MultiPoint ) // break; if ( flatType == QgsWkbTypes::LineString ) { validatePolyline( 0, mG.asPolyline() ); } else if ( flatType == QgsWkbTypes::MultiLineString ) { QgsMultiPolyline mp = mG.asMultiPolyline(); for ( int i = 0; !mStop && i < mp.size(); i++ ) validatePolyline( i, mp[i] ); } else if ( flatType == QgsWkbTypes::Polygon ) { validatePolygon( 0, mG.asPolygon() ); } else if ( flatType == QgsWkbTypes::MultiPolygon ) { QgsMultiPolygon mp = mG.asMultiPolygon(); for ( int i = 0; !mStop && i < mp.size(); i++ ) { validatePolygon( i, mp[i] ); } for ( int i = 0; !mStop && i < mp.size(); i++ ) { if ( mp[i].isEmpty() ) { emit errorFound( QgsGeometry::Error( QObject::tr( "polygon %1 has no rings" ).arg( i ) ) ); mErrorCount++; continue; } for ( int j = i + 1; !mStop && j < mp.size(); j++ ) { if ( mp[j].isEmpty() ) continue; if ( ringInRing( mp[i][0], mp[j][0] ) ) { emit errorFound( QgsGeometry::Error( QObject::tr( "polygon %1 inside polygon %2" ).arg( i ).arg( j ) ) ); mErrorCount++; } else if ( ringInRing( mp[j][0], mp[i][0] ) ) { emit errorFound( QgsGeometry::Error( QObject::tr( "polygon %1 inside polygon %2" ).arg( j ).arg( i ) ) ); mErrorCount++; } else { checkRingIntersections( i, 0, mp[i][0], j, 0, mp[j][0] ); } } } } else if ( flatType == QgsWkbTypes::Unknown ) { QgsDebugMsg( QObject::tr( "Unknown geometry type" ) ); emit errorFound( QgsGeometry::Error( QObject::tr( "Unknown geometry type %1" ).arg( mG.wkbType() ) ) ); mErrorCount++; } QgsDebugMsg( "validation finished." ); if ( mStop ) { emit errorFound( QgsGeometry::Error( QObject::tr( "Geometry validation was aborted." ) ) ); } else if ( mErrorCount > 0 ) { emit errorFound( QgsGeometry::Error( QObject::tr( "Geometry has %1 errors." ).arg( mErrorCount ) ) ); } #if 0 else { emit errorFound( QgsGeometry::Error( QObject::tr( "Geometry is valid." ) ) ); } #endif }
void QgsGeometryValidator::run() { mErrorCount = 0; switch ( mMethod ) { case QgsGeometry::ValidatorGeos: { char *r = nullptr; geos::unique_ptr g0( mGeometry.exportToGeos() ); GEOSContextHandle_t handle = QgsGeometry::getGEOSHandler(); if ( !g0 ) { emit errorFound( QgsGeometry::Error( QObject::tr( "GEOS error: could not produce geometry for GEOS (check log window)" ) ) ); } else { GEOSGeometry *g1 = nullptr; char res = GEOSisValidDetail_r( handle, g0.get(), GEOSVALID_ALLOW_SELFTOUCHING_RING_FORMING_HOLE, &r, &g1 ); if ( res != 1 ) { if ( g1 ) { const GEOSCoordSequence *cs = GEOSGeom_getCoordSeq_r( handle, g1 ); unsigned int n; if ( GEOSCoordSeq_getSize_r( handle, cs, &n ) && n == 1 ) { double x, y; GEOSCoordSeq_getX_r( handle, cs, 0, &x ); GEOSCoordSeq_getY_r( handle, cs, 0, &y ); emit errorFound( QgsGeometry::Error( QObject::tr( "GEOS error: %1" ).arg( r ), QgsPointXY( x, y ) ) ); mErrorCount++; } GEOSGeom_destroy_r( handle, g1 ); } else { emit errorFound( QgsGeometry::Error( QObject::tr( "GEOS error: %1" ).arg( r ) ) ); mErrorCount++; } GEOSFree_r( handle, r ); } } break; } case QgsGeometry::ValidatorQgisInternal: { QgsWkbTypes::Type flatType = QgsWkbTypes::flatType( mGeometry.wkbType() ); //if ( flatType == QgsWkbTypes::Point || flatType == QgsWkbTypes::MultiPoint ) // break; if ( flatType == QgsWkbTypes::LineString ) { validatePolyline( 0, mGeometry.asPolyline() ); } else if ( flatType == QgsWkbTypes::MultiLineString ) { QgsMultiPolylineXY mp = mGeometry.asMultiPolyline(); for ( int i = 0; !mStop && i < mp.size(); i++ ) validatePolyline( i, mp[i] ); } else if ( flatType == QgsWkbTypes::Polygon ) { validatePolygon( 0, mGeometry.asPolygon() ); } else if ( flatType == QgsWkbTypes::MultiPolygon ) { QgsMultiPolygonXY mp = mGeometry.asMultiPolygon(); for ( int i = 0; !mStop && i < mp.size(); i++ ) { validatePolygon( i, mp[i] ); } for ( int i = 0; !mStop && i < mp.size(); i++ ) { if ( mp[i].isEmpty() ) { emit errorFound( QgsGeometry::Error( QObject::tr( "polygon %1 has no rings" ).arg( i ) ) ); mErrorCount++; continue; } for ( int j = i + 1; !mStop && j < mp.size(); j++ ) { if ( mp[j].isEmpty() ) continue; if ( ringInRing( mp[i][0], mp[j][0] ) ) { emit errorFound( QgsGeometry::Error( QObject::tr( "polygon %1 inside polygon %2" ).arg( i ).arg( j ) ) ); mErrorCount++; } else if ( ringInRing( mp[j][0], mp[i][0] ) ) { emit errorFound( QgsGeometry::Error( QObject::tr( "polygon %1 inside polygon %2" ).arg( j ).arg( i ) ) ); mErrorCount++; } else { checkRingIntersections( i, 0, mp[i][0], j, 0, mp[j][0] ); } } } } else if ( flatType == QgsWkbTypes::Unknown ) { QgsDebugMsg( QObject::tr( "Unknown geometry type" ) ); emit errorFound( QgsGeometry::Error( QObject::tr( "Unknown geometry type %1" ).arg( mGeometry.wkbType() ) ) ); mErrorCount++; } if ( mStop ) { emit errorFound( QgsGeometry::Error( QObject::tr( "Geometry validation was aborted." ) ) ); } else if ( mErrorCount > 0 ) { emit errorFound( QgsGeometry::Error( QObject::tr( "Geometry has %1 errors." ).arg( mErrorCount ) ) ); } #if 0 else { emit errorFound( QgsGeometry::Error( QObject::tr( "Geometry is valid." ) ) ); } #endif break; } } }