Ejemplo n.º 1
0
static VALUE cmethod_create_line(VALUE module, VALUE factory, VALUE start, VALUE end)
{
  VALUE result = Qnil;
  RGeo_FactoryData* factory_data = RGEO_FACTORY_DATA_PTR(factory);
  char has_z = (char)(factory_data->flags & RGEO_FACTORYFLAGS_SUPPORTS_Z_OR_M);
  VALUE point_type = factory_data->globals->feature_point;
  GEOSContextHandle_t context = factory_data->geos_context;
  
  const GEOSGeometry* start_geom = rgeo_convert_to_geos_geometry(factory, start, point_type);
  if (start_geom) {
    const GEOSGeometry* end_geom = rgeo_convert_to_geos_geometry(factory, end, point_type);
    if (end_geom) {
      GEOSCoordSequence* coord_seq = GEOSCoordSeq_create_r(context, 2, 3);
      if (coord_seq) {
        populate_geom_into_coord_seq(context, start_geom, coord_seq, 0, has_z);
        populate_geom_into_coord_seq(context, end_geom, coord_seq, 1, has_z);
        GEOSGeometry* geom = GEOSGeom_createLineString_r(context, coord_seq);
        if (geom) {
          result = rgeo_wrap_geos_geometry(factory, geom, factory_data->globals->geos_line);
        }
      }
    }
  }
  
  return result;
}
Ejemplo n.º 2
0
static VALUE impl_copy_from(VALUE klass, VALUE factory, VALUE original, char subtype)
{
  VALUE result;
  const GEOSGeometry* original_geom;
  GEOSContextHandle_t context;
  const GEOSCoordSequence* original_coord_seq;
  GEOSCoordSequence* coord_seq;
  GEOSGeometry* geom;

  result = Qnil;
  original_geom = RGEO_GEOMETRY_DATA_PTR(original)->geom;
  if (original_geom) {
    context = RGEO_FACTORY_DATA_PTR(factory)->geos_context;
    if (subtype == 1 && GEOSGetNumCoordinates_r(context, original_geom) != 2) {
      original_geom = NULL;
    }
    if (original_geom) {
      original_coord_seq = GEOSGeom_getCoordSeq_r(context, original_geom);
      if (original_coord_seq) {
        coord_seq = GEOSCoordSeq_clone_r(context, original_coord_seq);
        if (coord_seq) {
          geom = subtype == 2 ? GEOSGeom_createLinearRing_r(context, coord_seq) : GEOSGeom_createLineString_r(context, coord_seq);
          if (geom) {
            result = rgeo_wrap_geos_geometry(factory, geom, klass);
          }
        }
      }
    }
  }
  return result;
}
Ejemplo n.º 3
0
static VALUE cmethod_create_line_string(VALUE module, VALUE factory, VALUE array)
{
  VALUE result = Qnil;
  GEOSCoordSequence* coord_seq = coord_seq_from_array(factory, array, 0);
  if (coord_seq) {
    RGeo_FactoryData* factory_data = RGEO_FACTORY_DATA_PTR(factory);
    GEOSGeometry* geom = GEOSGeom_createLineString_r(factory_data->geos_context, coord_seq);
    if (geom) {
      result = rgeo_wrap_geos_geometry(factory, geom, factory_data->globals->geos_line_string);
    }
  }
  return result;
}
Ejemplo n.º 4
0
GEOSGeometry *LineAccumulator::as_geom(GEOSContextHandle_t handle)
{
    m_lines.remove_if(degenerate_line);

    if(m_lines.size() > 1)
    {
        //std::cerr << "Checking first & last" << std::endl;
        Point first, last;
        first = m_lines.front().front();
        last = m_lines.back().back();
        //std::cerr << "first: " << first.x << ", " << first.y << std::endl;
        //std::cerr << "last: " << last.x << ", " << last.y << std::endl;
        if(close(first.x, last.x) && close(first.y, last.y))
        {
            m_lines.front().pop_front();
            m_lines.back().splice(m_lines.back().end(), m_lines.front());
            m_lines.pop_front();
        }
    }

    std::vector<GEOSGeometry *> geoms;
    std::list<Line>::const_iterator ilines;
    for(ilines = m_lines.begin(); ilines != m_lines.end(); ++ilines)
    {
        std::list<Point>::const_iterator ipoints;
        int i;

        GEOSCoordSequence *coords = GEOSCoordSeq_create_r(handle, (*ilines).size(), 2);
        for(ipoints = (*ilines).begin(), i = 0; ipoints != (*ilines).end(); ++ipoints, ++i)
        {
            GEOSCoordSeq_setX_r(handle, coords, i, ipoints->x);
            GEOSCoordSeq_setY_r(handle, coords, i, ipoints->y);
        }
        geoms.push_back(GEOSGeom_createLineString_r(handle, coords));
    }

    GEOSGeometry *geom;
    if(geoms.empty())
    {
        geom = GEOSGeom_createEmptyCollection_r(handle, GEOS_MULTILINESTRING);
    }
    else
    {
        geom = GEOSGeom_createCollection_r(handle, GEOS_MULTILINESTRING,
                                           &geoms[0], geoms.size());
    }
    return geom;
}
Ejemplo n.º 5
0
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;
}
Ejemplo n.º 6
0
/*
 * Return whether the given line segment is suitable as an
 * approximation of the projection of the source line.
 *
 * t_start: Interpolation parameter for the start point.
 * p_start: Projected start point.
 * t_end: Interpolation parameter for the end point.
 * p_start: Projected end point.
 * interpolator: Interpolator for current source line.
 * threshold: Lateral tolerance in target projection coordinates.
 * handle: Thread-local context handle for GEOS.
 * gp_domain: Prepared polygon of target map domain.
 * inside: Whether the start point is within the map domain.
 */
bool straightAndDomain(double t_start, const Point &p_start,
                       double t_end, const Point &p_end,
                       Interpolator *interpolator, double threshold,
                       GEOSContextHandle_t handle,
                       const GEOSPreparedGeometry *gp_domain,
                       bool inside)
{
    // Straight and in-domain (de9im[7] == 'F')
    
    bool valid;

    // This could be optimised out of the loop.
    if (!(isfinite(p_start.x) && isfinite(p_start.y)))
    {
        valid = false;
    }
    else if (!(isfinite(p_end.x) && isfinite(p_end.y)))
    {
        valid = false;
    }
    else
    {
        // TODO: Re-use geometries, instead of create-destroy!

        // Create a LineString for the current end-point.
        GEOSCoordSequence *coords = GEOSCoordSeq_create_r(handle, 2, 2);
        GEOSCoordSeq_setX_r(handle, coords, 0, p_start.x);
        GEOSCoordSeq_setY_r(handle, coords, 0, p_start.y);
        GEOSCoordSeq_setX_r(handle, coords, 1, p_end.x);
        GEOSCoordSeq_setY_r(handle, coords, 1, p_end.y);
        GEOSGeometry *g_segment = GEOSGeom_createLineString_r(handle, coords);

        // Find the projected mid-point
        double t_mid = (t_start + t_end) * 0.5;
        Point p_mid = interpolator->interpolate(t_mid);

        // Make it into a GEOS geometry
        coords = GEOSCoordSeq_create_r(handle, 1, 2);
        GEOSCoordSeq_setX_r(handle, coords, 0, p_mid.x);
        GEOSCoordSeq_setY_r(handle, coords, 0, p_mid.y);
        GEOSGeometry *g_mid = GEOSGeom_createPoint_r(handle, coords);

        double along = GEOSProjectNormalized_r(handle, g_segment, g_mid);
        if(isnan(along))
        {
            valid = true;
        }
        else
        {
            valid = 0.0 < along && along < 1.0;
            if (valid)
            {
                double separation;
                GEOSDistance_r(handle, g_segment, g_mid, &separation);
                if (inside)
                {
                    // Scale the lateral threshold by the distance from
                    // the nearest end. I.e. Near the ends the lateral
                    // threshold is much smaller; it only has its full
                    // value in the middle.
                    valid = separation <= threshold * 2.0 *
                                            (0.5 - fabs(0.5 - along));
                }
                else
                {
                    // Check if the mid-point makes less than ~11 degree
                    // angle with the straight line.
                    // sin(11') => 0.2
                    // To save the square-root we just use the square of
                    // the lengths, hence:
                    // 0.2 ^ 2 => 0.04
                    double hypot_dx = p_mid.x - p_start.x;
                    double hypot_dy = p_mid.y - p_start.y;
                    double hypot = hypot_dx * hypot_dx + hypot_dy * hypot_dy;
                    valid = ((separation * separation) / hypot) < 0.04;
                }
            }
        }

        if (valid)
        {
            if(inside)
                valid = GEOSPreparedCovers_r(handle, gp_domain, g_segment);
            else
                valid = GEOSPreparedDisjoint_r(handle, gp_domain, g_segment);
        }

        GEOSGeom_destroy_r(handle, g_segment);
        GEOSGeom_destroy_r(handle, g_mid);
    }

    return valid;
}