GEOSGeometry *_project_line_string(GEOSContextHandle_t handle, GEOSGeometry *g_line_string, Interpolator *interpolator, GEOSGeometry *g_domain, double threshold) { const GEOSCoordSequence *src_coords = GEOSGeom_getCoordSeq_r(handle, g_line_string); unsigned int src_size, src_idx; const GEOSPreparedGeometry *gp_domain = GEOSPrepare_r(handle, g_domain); GEOSCoordSeq_getSize_r(handle, src_coords, &src_size); // check exceptions LineAccumulator lines; for(src_idx = 1; src_idx < src_size; src_idx++) { _project_segment(handle, src_coords, src_idx - 1, src_idx, interpolator, gp_domain, threshold, lines); } GEOSPreparedGeom_destroy_r(handle, gp_domain); return lines.as_geom(handle); }
st_index_t rgeo_geos_coordseq_hash(GEOSContextHandle_t context, const GEOSGeometry* geom, st_index_t hash) { const GEOSCoordSequence* cs; unsigned int len; unsigned int i; RGeo_Coordseq_Hash_Struct hash_struct; if (geom) { cs = GEOSGeom_getCoordSeq_r(context, geom); if (cs) { if (GEOSCoordSeq_getSize_r(context, cs, &len)) { for (i=0; i<len; ++i) { if (GEOSCoordSeq_getX_r(context, cs, i, &hash_struct.x)) { if (GEOSCoordSeq_getY_r(context, cs, i, &hash_struct.y)) { if (!GEOSCoordSeq_getY_r(context, cs, i, &hash_struct.z)) { hash_struct.z = 0; } hash_struct.seed_hash = hash; hash = rb_memhash(&hash_struct, sizeof(RGeo_Coordseq_Hash_Struct)); } } } } } } return hash; }
BOX3D computeBounds(GEOSContextHandle_t ctx, GEOSGeometry const *geometry) { uint32_t numInputDims; BOX3D output; GEOSGeometry const* ring = GEOSGetExteriorRing_r(ctx, geometry); GEOSCoordSequence const* coords = GEOSGeom_getCoordSeq_r(ctx, ring); GEOSCoordSeq_getDimensions_r(ctx, coords, &numInputDims); uint32_t count(0); GEOSCoordSeq_getSize_r(ctx, coords, &count); double x(0.0); double y(0.0); double z(0.0); for (unsigned i = 0; i < count; ++i) { GEOSCoordSeq_getOrdinate_r(ctx, coords, i, 0, &x); GEOSCoordSeq_getOrdinate_r(ctx, coords, i, 1, &y); if (numInputDims > 2) GEOSCoordSeq_getOrdinate_r(ctx, coords, i, 2, &z); output.grow(x, y, z); } return output; }
BOX3D Polygon::bounds() const { uint32_t numInputDims; BOX3D output; GEOSGeometry* boundary = GEOSGeom_clone_r(m_ctx, m_geom); // Smash out multi* if (GEOSGeomTypeId_r(m_ctx, m_geom) > 3) boundary = GEOSEnvelope_r(m_ctx, m_geom); GEOSGeometry const* ring = GEOSGetExteriorRing_r(m_ctx, boundary); GEOSCoordSequence const* coords = GEOSGeom_getCoordSeq_r(m_ctx, ring); GEOSCoordSeq_getDimensions_r(m_ctx, coords, &numInputDims); uint32_t count(0); GEOSCoordSeq_getSize_r(m_ctx, coords, &count); double x(0.0); double y(0.0); double z(0.0); for (unsigned i = 0; i < count; ++i) { GEOSCoordSeq_getOrdinate_r(m_ctx, coords, i, 0, &x); GEOSCoordSeq_getOrdinate_r(m_ctx, coords, i, 1, &y); if (numInputDims > 2) GEOSCoordSeq_getOrdinate_r(m_ctx, coords, i, 2, &z); output.grow(x, y, z); } GEOSGeom_destroy_r(m_ctx, boundary); return output; }
static VALUE method_line_string_points(VALUE self) { VALUE result = Qnil; RGeo_GeometryData* self_data = RGEO_GEOMETRY_DATA_PTR(self); const GEOSGeometry* self_geom = self_data->geom; if (self_geom) { GEOSContextHandle_t self_context = self_data->geos_context; const GEOSCoordSequence* coord_seq = GEOSGeom_getCoordSeq_r(self_context, self_geom); if (coord_seq) { char has_z = (char)(RGEO_FACTORY_DATA_PTR(self_data->factory)->flags & RGEO_FACTORYFLAGS_SUPPORTS_Z_OR_M); unsigned int size; if (GEOSCoordSeq_getSize_r(self_context, coord_seq, &size)) { result = rb_ary_new2(size); double x, y, z; unsigned int i; for (i=0; i<size; ++i) { VALUE point = get_point_from_coordseq(self, coord_seq, i, has_z); if (!NIL_P(point)) { rb_ary_store(result, i, point); } } } } } return result; }
static VALUE method_line_string_point_n(VALUE self, VALUE n) { VALUE result = Qnil; RGeo_GeometryData* self_data = RGEO_GEOMETRY_DATA_PTR(self); const GEOSGeometry* self_geom = self_data->geom; if (self_geom) { GEOSContextHandle_t self_context = self_data->geos_context; const GEOSCoordSequence* coord_seq = GEOSGeom_getCoordSeq_r(self_context, self_geom); if (coord_seq) { char has_z = (char)(RGEO_FACTORY_DATA_PTR(self_data->factory)->flags & RGEO_FACTORYFLAGS_SUPPORTS_Z_OR_M); int si = NUM2INT(n); if (si >= 0) { unsigned int i = si; unsigned int size; if (GEOSCoordSeq_getSize_r(self_context, coord_seq, &size)) { if (i < size) { unsigned int dims; result = get_point_from_coordseq(self, coord_seq, i, has_z); } } } } } return result; }
BOX3D Crop::computeBounds(GEOSGeometry const *geometry) { uint32_t numInputDims; BOX3D output; #ifdef PDAL_HAVE_GEOS GEOSGeometry const* ring = GEOSGetExteriorRing_r(m_geosEnvironment, geometry); GEOSCoordSequence const* coords = GEOSGeom_getCoordSeq_r(m_geosEnvironment, ring); GEOSCoordSeq_getDimensions_r(m_geosEnvironment, coords, &numInputDims); log()->get(LogLevel::Debug) << "Inputted WKT had " << numInputDims << " dimensions" <<std::endl; uint32_t count(0); GEOSCoordSeq_getSize_r(m_geosEnvironment, coords, &count); double x(0.0); double y(0.0); double z(0.0); for (unsigned i = 0; i < count; ++i) { GEOSCoordSeq_getOrdinate_r(m_geosEnvironment, coords, i, 0, &x); GEOSCoordSeq_getOrdinate_r(m_geosEnvironment, coords, i, 1, &y); if (numInputDims > 2) GEOSCoordSeq_getOrdinate_r(m_geosEnvironment, coords, i, 2, &z); output.grow(x, y, z); } #else boost::ignore_unused_variable_warning(geometry); #endif return output; }
void Point::update(const std::string& wkt_or_json, SpatialReference ref) { Geometry::update(wkt_or_json, ref); int t = GEOSGeomTypeId_r(m_geoserr.ctx(), m_geom.get()); if (t == -1) throw pdal_error("Unable to fetch geometry point type"); if (t > 0) throw pdal_error("Geometry type is not point!"); int nGeometries = GEOSGetNumGeometries_r(m_geoserr.ctx(), m_geom.get()); if (nGeometries > 1) throw pdal_error("Geometry count is > 1!"); const GEOSGeometry* g = GEOSGetGeometryN_r(m_geoserr.ctx(), m_geom.get(), 0); GEOSCoordSequence const* coords = GEOSGeom_getCoordSeq_r(m_geoserr.ctx(), g); uint32_t numInputDims; GEOSCoordSeq_getDimensions_r(m_geoserr.ctx(), coords, &numInputDims); uint32_t count(0); GEOSCoordSeq_getSize_r(m_geoserr.ctx(), coords, &count); if (count == 0) throw pdal_error("No coordinates in geometry!"); for (unsigned i = 0; i < count; ++i) { GEOSCoordSeq_getOrdinate_r(m_geoserr.ctx(), coords, i, 0, &x); GEOSCoordSeq_getOrdinate_r(m_geoserr.ctx(), coords, i, 1, &y); if (numInputDims > 2) GEOSCoordSeq_getOrdinate_r(m_geoserr.ctx(), coords, i, 2, &z); } }
VALUE rgeo_geos_coordseqs_eql(GEOSContextHandle_t context, const GEOSGeometry* geom1, const GEOSGeometry* geom2, char check_z) { VALUE result; const GEOSCoordSequence* cs1; const GEOSCoordSequence* cs2; unsigned int len1; unsigned int len2; unsigned int i; double val1, val2; result = Qnil; if (geom1 && geom2) { cs1 = GEOSGeom_getCoordSeq_r(context, geom1); cs2 = GEOSGeom_getCoordSeq_r(context, geom2); if (cs1 && cs2) { len1 = 0; len2 = 0; if (GEOSCoordSeq_getSize_r(context, cs1, &len1) && GEOSCoordSeq_getSize_r(context, cs2, &len2)) { if (len1 == len2) { result = Qtrue; for (i=0; i<len1; ++i) { if (GEOSCoordSeq_getX_r(context, cs1, i, &val1) && GEOSCoordSeq_getX_r(context, cs2, i, &val2)) { if (val1 == val2) { if (GEOSCoordSeq_getY_r(context, cs1, i, &val1) && GEOSCoordSeq_getY_r(context, cs2, i, &val2)) { if (val1 == val2) { if (check_z) { val1 = 0; if (!GEOSCoordSeq_getZ_r(context, cs1, i, &val1)) { result = Qnil; break; } val2 = 0; if (!GEOSCoordSeq_getZ_r(context, cs2, i, &val2)) { result = Qnil; break; } if (val1 != val2) { result = Qfalse; break; } } } else { // Y coords are different result = Qfalse; break; } } else { // Failed to get Y coords result = Qnil; break; } } else { // X coords are different result = Qfalse; break; } } else { // Failed to get X coords result = Qnil; break; } } // Iteration over coords } else { // Lengths are different result = Qfalse; } } } } 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 Layer::chopFeaturesAtRepeatDistance() { GEOSContextHandle_t geosctxt = geosContext(); QLinkedList<FeaturePart*> * newFeatureParts = new QLinkedList<FeaturePart*>; while ( !featureParts->isEmpty() ) { FeaturePart* fpart = featureParts->takeFirst(); const GEOSGeometry* geom = fpart->geos(); double chopInterval = fpart->getFeature()->repeatDistance(); if ( chopInterval != 0. && GEOSGeomTypeId_r( geosctxt, geom ) == GEOS_LINESTRING ) { double bmin[2], bmax[2]; fpart->getBoundingBox( bmin, bmax ); rtree->Remove( bmin, bmax, fpart ); const GEOSCoordSequence *cs = GEOSGeom_getCoordSeq_r( geosctxt, geom ); // get number of points unsigned int n; GEOSCoordSeq_getSize_r( geosctxt, cs, &n ); // Read points std::vector<Point> points( n ); for ( unsigned int i = 0; i < n; ++i ) { GEOSCoordSeq_getX_r( geosctxt, cs, i, &points[i].x ); GEOSCoordSeq_getY_r( geosctxt, cs, i, &points[i].y ); } // Cumulative length vector std::vector<double> len( n, 0 ); for ( unsigned int i = 1; i < n; ++i ) { double dx = points[i].x - points[i - 1].x; double dy = points[i].y - points[i - 1].y; len[i] = len[i - 1] + std::sqrt( dx * dx + dy * dy ); } // Walk along line unsigned int cur = 0; double lambda = 0; std::vector<Point> part; for ( ;; ) { lambda += chopInterval; for ( ; cur < n && lambda > len[cur]; ++cur ) { part.push_back( points[cur] ); } if ( cur >= n ) { break; } double c = ( lambda - len[cur - 1] ) / ( len[cur] - len[cur - 1] ); Point p; p.x = points[cur - 1].x + c * ( points[cur].x - points[cur - 1].x ); p.y = points[cur - 1].y + c * ( points[cur].y - points[cur - 1].y ); part.push_back( p ); GEOSCoordSequence* cooSeq = GEOSCoordSeq_create_r( geosctxt, part.size(), 2 ); for ( std::size_t i = 0; i < part.size(); ++i ) { GEOSCoordSeq_setX_r( geosctxt, cooSeq, i, part[i].x ); GEOSCoordSeq_setY_r( geosctxt, cooSeq, i, part[i].y ); } GEOSGeometry* newgeom = GEOSGeom_createLineString_r( geosctxt, cooSeq ); FeaturePart* newfpart = new FeaturePart( fpart->getFeature(), newgeom ); newFeatureParts->append( newfpart ); newfpart->getBoundingBox( bmin, bmax ); rtree->Insert( bmin, bmax, newfpart ); part.clear(); part.push_back( p ); } // Create final part part.push_back( points[n - 1] ); GEOSCoordSequence* cooSeq = GEOSCoordSeq_create_r( geosctxt, part.size(), 2 ); for ( std::size_t i = 0; i < part.size(); ++i ) { GEOSCoordSeq_setX_r( geosctxt, cooSeq, i, part[i].x ); GEOSCoordSeq_setY_r( geosctxt, cooSeq, i, part[i].y ); } GEOSGeometry* newgeom = GEOSGeom_createLineString_r( geosctxt, cooSeq ); FeaturePart* newfpart = new FeaturePart( fpart->getFeature(), newgeom ); newFeatureParts->append( newfpart ); newfpart->getBoundingBox( bmin, bmax ); rtree->Insert( bmin, bmax, newfpart ); } else { newFeatureParts->append( fpart ); } } delete featureParts; featureParts = newFeatureParts; }
Q_NOWARN_UNREACHABLE_POP // Return Nth vertex in GEOSGeometry as a POINT. // May return NULL if the geometry has NO vertexex. static GEOSGeometry *LWGEOM_GEOS_getPointN( const GEOSGeometry *g_in, uint32_t n ) { GEOSContextHandle_t handle = QgsGeos::getGEOSHandler(); uint32_t dims; const GEOSCoordSequence *seq_in = nullptr; GEOSCoordSeq seq_out; double val; uint32_t sz; int gn; GEOSGeometry *ret = nullptr; switch ( GEOSGeomTypeId_r( handle, g_in ) ) { case GEOS_MULTIPOINT: case GEOS_MULTILINESTRING: case GEOS_MULTIPOLYGON: case GEOS_GEOMETRYCOLLECTION: { for ( gn = 0; gn < GEOSGetNumGeometries_r( handle, g_in ); ++gn ) { const GEOSGeometry *g = GEOSGetGeometryN_r( handle, g_in, gn ); ret = LWGEOM_GEOS_getPointN( g, n ); if ( ret ) return ret; } break; } case GEOS_POLYGON: { ret = LWGEOM_GEOS_getPointN( GEOSGetExteriorRing_r( handle, g_in ), n ); if ( ret ) return ret; for ( gn = 0; gn < GEOSGetNumInteriorRings_r( handle, g_in ); ++gn ) { const GEOSGeometry *g = GEOSGetInteriorRingN_r( handle, g_in, gn ); ret = LWGEOM_GEOS_getPointN( g, n ); if ( ret ) return ret; } break; } case GEOS_POINT: case GEOS_LINESTRING: case GEOS_LINEARRING: break; } seq_in = GEOSGeom_getCoordSeq_r( handle, g_in ); if ( ! seq_in ) return nullptr; if ( ! GEOSCoordSeq_getSize_r( handle, seq_in, &sz ) ) return nullptr; if ( ! sz ) return nullptr; if ( ! GEOSCoordSeq_getDimensions_r( handle, seq_in, &dims ) ) return nullptr; seq_out = GEOSCoordSeq_create_r( handle, 1, dims ); if ( ! seq_out ) return nullptr; if ( ! GEOSCoordSeq_getX_r( handle, seq_in, n, &val ) ) return nullptr; if ( ! GEOSCoordSeq_setX_r( handle, seq_out, n, val ) ) return nullptr; if ( ! GEOSCoordSeq_getY_r( handle, seq_in, n, &val ) ) return nullptr; if ( ! GEOSCoordSeq_setY_r( handle, seq_out, n, val ) ) return nullptr; if ( dims > 2 ) { if ( ! GEOSCoordSeq_getZ_r( handle, seq_in, n, &val ) ) return nullptr; if ( ! GEOSCoordSeq_setZ_r( handle, seq_out, n, val ) ) return nullptr; } return GEOSGeom_createPoint_r( handle, seq_out ); }
void coordseq_to_terms(GEOSCommand *command) { GEOSContextHandle_t handle = command->driver_data->handle; GEOSCoordSequence *coordSeq; unsigned int dims = 2; ERL_READ_PTR_GEOSCOORDSEQUENCE(command, coordSeq); //ERL_READ_INT(command, dims); unsigned int size; if(GEOSCoordSeq_getSize_r(handle, coordSeq, &size)==0) { erl_send_error(command, "invalidcs"); return; } //if(GEOSCoordSeq_getDimensions_r(handle, coordSeq,&dims)==0) { // erl_send_error(command, "invalidcs"); // return; //} always return 3 int allocSize = 7 + (size * (dims * 2 + 2)); //int allocSize = 6 + (dims*2 + 2) * size + 1; double *digits = driver_alloc(sizeof(double) * dims * size); memset(digits, 0, sizeof(double) * dims * size); ErlDrvTermData *terms = driver_alloc(sizeof(ErlDrvTermData) * (allocSize)); terms[0] = ERL_DRV_ATOM; terms[1] = driver_mk_atom("ok"); int pos = 2; int i,d = 0; for(i = 0; i < size; i++) { GEOSCoordSeq_getX_r(handle,coordSeq,i, &digits[d]); terms[pos++] = ERL_DRV_FLOAT; terms[pos++] = (ErlDrvTermData) &digits[d]; d++; if(dims >= 2) { GEOSCoordSeq_getY_r(handle,coordSeq,i, &digits[d]); terms[pos++] = ERL_DRV_FLOAT; terms[pos++] = (ErlDrvTermData) &digits[d]; d++; } if(dims >= 3) { GEOSCoordSeq_getZ_r(handle,coordSeq,i, &digits[d]); terms[pos++] = ERL_DRV_FLOAT; terms[pos++] = (ErlDrvTermData) &digits[d]; d++; } terms[pos++] = ERL_DRV_TUPLE; terms[pos++] = dims; } terms[pos++] = ERL_DRV_NIL; terms[pos++] = ERL_DRV_LIST; terms[pos++] = size+1; terms[pos++] = ERL_DRV_TUPLE; terms[pos] = 2; driver_output_term(command->driver_data->port, terms, pos+1); driver_free(digits); driver_free(terms); }
SEXP rgeos_geosring2Polygon(SEXP env, GEOSGeom lr, int hole) { GEOSContextHandle_t GEOShandle = getContextHandle(env); int pc=0; GEOSCoordSeq s = (GEOSCoordSequence *) GEOSGeom_getCoordSeq_r(GEOShandle, lr); if (s == NULL) error("rgeos_geosring2Polygon: CoordSeq failure"); unsigned int n; if (GEOSCoordSeq_getSize_r(GEOShandle, s, &n) == 0) error("rgeos_geosring2Polygon: CoordSeq failure"); // Get coordinates SEXP crd; PROTECT(crd = rgeos_crdMatFixDir(PROTECT(rgeos_CoordSeq2crdMat(env, s, FALSE, hole)), hole)); pc += 2; // Calculate area GEOSGeom p = GEOSGeom_createPolygon_r(GEOShandle,GEOSGeom_clone_r(GEOShandle,lr),NULL,0); if (p == NULL) error("rgeos_geosring2Polygon: unable to create polygon"); SEXP area; PROTECT(area = NEW_NUMERIC(1)); pc++; NUMERIC_POINTER(area)[0] = 0.0; if (!GEOSArea_r(GEOShandle, p, NUMERIC_POINTER(area))) error("rgeos_geosring2Polygon: area calculation failure"); // Calculate label position SEXP labpt; PROTECT(labpt = NEW_NUMERIC(2)); pc++; GEOSGeom centroid = GEOSGetCentroid_r(GEOShandle, p); double xc, yc; rgeos_Pt2xy(env, centroid, &xc, &yc); if (!R_FINITE(xc) || !R_FINITE(yc)) { xc = 0.0; yc = 0.0; for(int i=0; i != n; i++) { xc += NUMERIC_POINTER(crd)[i]; yc += NUMERIC_POINTER(crd)[(int) (n) +i]; } xc /= n; yc /= n; } NUMERIC_POINTER(labpt)[0] = xc; NUMERIC_POINTER(labpt)[1] = yc; GEOSGeom_destroy_r(GEOShandle, centroid); GEOSGeom_destroy_r(GEOShandle, p); // Get ring direction SEXP ringDir; PROTECT(ringDir = NEW_INTEGER(1)); pc++; INTEGER_POINTER(ringDir)[0] = hole ? -1 : 1; // Get hole status SEXP Hole; PROTECT(Hole = NEW_LOGICAL(1)); pc++; LOGICAL_POINTER(Hole)[0] = hole; SEXP ans; PROTECT(ans = NEW_OBJECT(MAKE_CLASS("Polygon"))); pc++; SET_SLOT(ans, install("ringDir"), ringDir); SET_SLOT(ans, install("labpt"), labpt); SET_SLOT(ans, install("area"), area); SET_SLOT(ans, install("hole"), Hole); SET_SLOT(ans, install("coords"), crd); SEXP valid; PROTECT(valid = SP_PREFIX(Polygon_validate_c)(ans)); pc++; if (!isLogical(valid)) { UNPROTECT(pc); if (isString(valid)) error(CHAR(STRING_ELT(valid, 0))); else error("invalid Polygon object"); } UNPROTECT(pc); return(ans); }
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; } } }