int LabelPosition::polygonIntersectionCost( PointSet *polygon ) const { if ( !mGeos ) createGeosGeom(); if ( !polygon->mGeos ) polygon->createGeosGeom(); GEOSContextHandle_t geosctxt = geosContext(); int cost = 0; //check the label center. if covered by polygon, initial cost of 4 if ( polygon->containsPoint(( x[0] + x[2] ) / 2.0, ( y[0] + y[2] ) / 2.0 ) ) cost += 4; try { //calculate proportion of label candidate which is covered by polygon GEOSGeometry* intersectionGeom = GEOSIntersection_r( geosctxt, mGeos, polygon->mGeos ); if ( !intersectionGeom ) return cost; double positionArea = 0; if ( GEOSArea_r( geosctxt, mGeos, &positionArea ) != 1 ) { GEOSGeom_destroy_r( geosctxt, intersectionGeom ); return cost; } double intersectionArea = 0; if ( GEOSArea_r( geosctxt, intersectionGeom, &intersectionArea ) != 1 ) { intersectionArea = 0; } GEOSGeom_destroy_r( geosctxt, intersectionGeom ); double portionCovered = intersectionArea / positionArea; cost += ceil( portionCovered * 8.0 ); //cost of 8 if totally covered return cost; } catch ( GEOSException &e ) { QgsMessageLog::logMessage( QObject::tr( "Exception: %1" ).arg( e.what() ), QObject::tr( "GEOS" ) ); return cost; } }
double Polygon::area() const { double output(0.0); int errored = GEOSArea_r(m_ctx, m_geom, &output); if (errored == 0) throw pdal::pdal_error("Unable to get area of ring!"); return output; }
static Face *newFace( const GEOSGeometry *g ) { GEOSContextHandle_t handle = QgsGeos::getGEOSHandler(); Face *f = new Face; f->geom = g; f->env = GEOSEnvelope_r( handle, f->geom ); GEOSArea_r( handle, f->env, &f->envarea ); f->parent = nullptr; return f; }
static VALUE method_polygon_area(VALUE self) { VALUE result = Qnil; RGeo_GeometryData* self_data = RGEO_GEOMETRY_DATA_PTR(self); const GEOSGeometry* self_geom = self_data->geom; if (self_geom) { double area; if (GEOSArea_r(self_data->geos_context, self_geom, &area)) { result = rb_float_new(area); } } return result; }
bool Layer::registerFeature( const QString& geom_id, PalGeometry *userGeom, double label_x, double label_y, const QString &labelText, double labelPosX, double labelPosY, bool fixedPos, double angle, bool fixedAngle, int xQuadOffset, int yQuadOffset, double xOffset, double yOffset, bool alwaysShow, double repeatDistance ) { if ( geom_id.isEmpty() || label_x < 0 || label_y < 0 ) return false; mMutex.lock(); if ( hashtable->contains( geom_id ) ) { mMutex.unlock(); //A feature with this id already exists. Don't throw an exception as sometimes, //the same feature is added twice (dateline split with otf-reprojection) return false; } // Split MULTI GEOM and Collection in simple geometries const GEOSGeometry *the_geom = userGeom->getGeosGeometry(); Feature* f = new Feature( this, geom_id, userGeom, label_x, label_y ); if ( fixedPos ) { f->setFixedPosition( labelPosX, labelPosY ); } if ( xQuadOffset != 0 || yQuadOffset != 0 ) { f->setQuadOffset( xQuadOffset, yQuadOffset ); } if ( xOffset != 0.0 || yOffset != 0.0 ) { f->setPosOffset( xOffset, yOffset ); } if ( fixedAngle ) { f->setFixedAngle( angle ); } // use layer-level defined rotation, but not if position fixed if ( !fixedPos && angle != 0.0 ) { f->setFixedAngle( angle ); } f->setRepeatDistance( repeatDistance ); f->setAlwaysShow( alwaysShow ); bool first_feat = true; double geom_size = -1, biggest_size = -1; FeaturePart* biggest_part = NULL; // break the (possibly multi-part) geometry into simple geometries QLinkedList<const GEOSGeometry*>* simpleGeometries = unmulti( the_geom ); if ( simpleGeometries == NULL ) // unmulti() failed? { mMutex.unlock(); throw InternalException::UnknownGeometry(); } GEOSContextHandle_t geosctxt = geosContext(); while ( simpleGeometries->size() > 0 ) { const GEOSGeometry* geom = simpleGeometries->takeFirst(); // ignore invalid geometries (e.g. polygons with self-intersecting rings) if ( GEOSisValid_r( geosctxt, geom ) != 1 ) // 0=invalid, 1=valid, 2=exception { // std::cerr << "ignoring invalid feature " << geom_id << std::endl; continue; } int type = GEOSGeomTypeId_r( geosctxt, geom ); if ( type != GEOS_POINT && type != GEOS_LINESTRING && type != GEOS_POLYGON ) { mMutex.unlock(); throw InternalException::UnknownGeometry(); } FeaturePart* fpart = new FeaturePart( f, geom ); // ignore invalid geometries if (( type == GEOS_LINESTRING && fpart->nbPoints < 2 ) || ( type == GEOS_POLYGON && fpart->nbPoints < 3 ) ) { delete fpart; continue; } // polygons: reorder coordinates if ( type == GEOS_POLYGON && reorderPolygon( fpart->nbPoints, fpart->x, fpart->y ) != 0 ) { delete fpart; continue; } if ( mMode == LabelPerFeature && ( type == GEOS_POLYGON || type == GEOS_LINESTRING ) ) { if ( type == GEOS_LINESTRING ) GEOSLength_r( geosctxt, geom, &geom_size ); else if ( type == GEOS_POLYGON ) GEOSArea_r( geosctxt, geom, &geom_size ); if ( geom_size > biggest_size ) { biggest_size = geom_size; delete biggest_part; // safe with NULL part biggest_part = fpart; } continue; // don't add the feature part now, do it later // TODO: we should probably add also other parts to act just as obstacles } // feature part is ready! addFeaturePart( fpart, labelText ); first_feat = false; } delete simpleGeometries; userGeom->releaseGeosGeometry( the_geom ); mMutex.unlock(); // if using only biggest parts... if (( mMode == LabelPerFeature || f->fixedPosition() ) && biggest_part != NULL ) { addFeaturePart( biggest_part, labelText ); first_feat = false; } // add feature to layer if we have added something if ( !first_feat ) { features->append( f ); hashtable->insert( geom_id, f ); } else { delete f; } return !first_feat; // true if we've added something }
Polygon Polygon::simplify(double distance_tolerance, double area_tolerance) const { GEOSGeometry *smoothed = GEOSTopologyPreserveSimplify_r(m_ctx, m_geom, distance_tolerance); if (!smoothed) throw pdal_error("Unable to simplify input geometry!"); std::vector<GEOSGeometry*> geometries; int numGeom = GEOSGetNumGeometries_r(m_ctx, smoothed); for (int n = 0; n < numGeom; ++n) { const GEOSGeometry* m = GEOSGetGeometryN_r(m_ctx, smoothed, n); if (!m) throw pdal::pdal_error("Unable to Get GeometryN"); const GEOSGeometry* ering = GEOSGetExteriorRing_r(m_ctx, m); if (!ering) throw pdal::pdal_error("Unable to Get Exterior Ring"); GEOSGeometry* exterior = GEOSGeom_clone_r(m_ctx, GEOSGetExteriorRing_r(m_ctx, m)); if (!exterior) throw pdal::pdal_error("Unable to clone exterior ring!"); std::vector<GEOSGeometry*> keep_rings; int numRings = GEOSGetNumInteriorRings_r(m_ctx, m); for (int i = 0; i < numRings; ++i) { double area(0.0); const GEOSGeometry* iring = GEOSGetInteriorRingN_r(m_ctx, m, i); if (!iring) throw pdal::pdal_error("Unable to Get Interior Ring"); GEOSGeometry* cring = GEOSGeom_clone_r(m_ctx, iring); if (!cring) throw pdal::pdal_error("Unable to clone interior ring!"); GEOSGeometry* aring = GEOSGeom_createPolygon_r(m_ctx, cring, NULL, 0); int errored = GEOSArea_r(m_ctx, aring, &area); if (errored == 0) throw pdal::pdal_error("Unable to get area of ring!"); if (area > area_tolerance) { keep_rings.push_back(cring); } } GEOSGeometry* p = GEOSGeom_createPolygon_r(m_ctx, exterior, keep_rings.data(), keep_rings.size()); if (p == NULL) throw pdal::pdal_error("smooth polygon could not be created!" ); geometries.push_back(p); } GEOSGeometry* o = GEOSGeom_createCollection_r(m_ctx, GEOS_MULTIPOLYGON, geometries.data(), geometries.size()); Polygon p(o, m_srs, m_ctx); GEOSGeom_destroy_r(m_ctx, smoothed); GEOSGeom_destroy_r(m_ctx, o); return p; }
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); }