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; }
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; }
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; }
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; }
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; }
/* * 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; }