Beispiel #1
0
  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;
    }
  }
Beispiel #2
0
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;
}
Beispiel #4
0
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;
}
Beispiel #5
0
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
}
Beispiel #6
0
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;
}
Beispiel #7
0
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);
}