void Polygon::initializeFromBounds(const BOX3D& box) { GEOSCoordSequence* coords = GEOSCoordSeq_create_r(m_ctx, 5, 3); auto set_coordinate = [coords, this](int pt_num, const double&x, const double& y, const double& z) { if (!GEOSCoordSeq_setX_r(m_ctx, coords, pt_num, x)) throw pdal_error("unable to set x for coordinate sequence"); if (!GEOSCoordSeq_setY_r(m_ctx, coords, pt_num, y)) throw pdal_error("unable to set y for coordinate sequence"); if (!GEOSCoordSeq_setZ_r(m_ctx, coords, pt_num, z)) throw pdal_error("unable to set z for coordinate sequence"); }; set_coordinate(0, box.minx, box.miny, box.minz); set_coordinate(1, box.minx, box.maxy, box.minz); set_coordinate(2, box.maxx, box.maxy, box.maxz); set_coordinate(3, box.maxx, box.miny, box.maxz); set_coordinate(4, box.minx, box.miny, box.minz); GEOSGeometry* ring = GEOSGeom_createLinearRing_r(m_ctx, coords); if (!ring) throw pdal_error("unable to create linear ring from BOX2D"); m_geom = GEOSGeom_createPolygon_r(m_ctx, ring, 0, 0); if (!m_geom) throw pdal_error("unable to create polygon from linear ring in " "BOX2D constructor"); prepare(); }
bool Polygon::covers(PointRef& ref) const { GEOSCoordSequence* coords = GEOSCoordSeq_create_r(m_ctx, 1, 3); if (!coords) throw pdal_error("Unable to allocate coordinate sequence"); const double x = ref.getFieldAs<double>(Dimension::Id::X); const double y = ref.getFieldAs<double>(Dimension::Id::Y); const double z = ref.getFieldAs<double>(Dimension::Id::Z); if (!GEOSCoordSeq_setX_r(m_ctx, coords, 0, x)) throw pdal_error("unable to set x for coordinate sequence"); if (!GEOSCoordSeq_setY_r(m_ctx, coords, 0, y)) throw pdal_error("unable to set y for coordinate sequence"); if (!GEOSCoordSeq_setZ_r(m_ctx, coords, 0, z)) throw pdal_error("unable to set z for coordinate sequence"); GEOSGeometry* p = GEOSGeom_createPoint_r(m_ctx, coords); if (!p) throw pdal_error("unable to allocate candidate test point"); bool covers = (bool)(GEOSPreparedCovers_r(m_ctx, m_prepGeom, p)); GEOSGeom_destroy_r(m_ctx, p); return covers; }
void QgsZonalStatistics::statisticsFromMiddlePointTest( void* band, QgsGeometry* poly, int pixelOffsetX, int pixelOffsetY, int nCellsX, int nCellsY, double cellSizeX, double cellSizeY, const QgsRectangle& rasterBBox, double& sum, double& count ) { double cellCenterX, cellCenterY; float* scanLine = ( float * ) CPLMalloc( sizeof( float ) * nCellsX ); cellCenterY = rasterBBox.yMaximum() - pixelOffsetY * cellSizeY - cellSizeY / 2; count = 0; sum = 0; const GEOSGeometry* polyGeos = poly->asGeos(); if ( !polyGeos ) { return; } GEOSContextHandle_t geosctxt = QgsGeometry::getGEOSHandler(); const GEOSPreparedGeometry* polyGeosPrepared = GEOSPrepare_r( geosctxt, poly->asGeos() ); if ( !polyGeosPrepared ) { return; } GEOSCoordSequence* cellCenterCoords = 0; GEOSGeometry* currentCellCenter = 0; for ( int i = 0; i < nCellsY; ++i ) { if ( GDALRasterIO( band, GF_Read, pixelOffsetX, pixelOffsetY + i, nCellsX, 1, scanLine, nCellsX, 1, GDT_Float32, 0, 0 ) != CPLE_None ) { continue; } cellCenterX = rasterBBox.xMinimum() + pixelOffsetX * cellSizeX + cellSizeX / 2; for ( int j = 0; j < nCellsX; ++j ) { GEOSGeom_destroy_r( geosctxt, currentCellCenter ); cellCenterCoords = GEOSCoordSeq_create_r( geosctxt, 1, 2 ); GEOSCoordSeq_setX_r( geosctxt, cellCenterCoords, 0, cellCenterX ); GEOSCoordSeq_setY_r( geosctxt, cellCenterCoords, 0, cellCenterY ); currentCellCenter = GEOSGeom_createPoint_r( geosctxt, cellCenterCoords ); if ( scanLine[j] != mInputNodataValue ) //don't consider nodata values { if ( GEOSPreparedContains_r( geosctxt, polyGeosPrepared, currentCellCenter ) ) { if ( !qIsNaN( scanLine[j] ) ) { sum += scanLine[j]; } ++count; } } cellCenterX += cellSizeX; } cellCenterY -= cellSizeY; } CPLFree( scanLine ); GEOSPreparedGeom_destroy_r( geosctxt, polyGeosPrepared ); }
void Crop::crop(PointBuffer& input, PointBuffer& output) { bool logOutput = (log()->getLevel() > LogLevel::Debug4); if (logOutput) log()->floatPrecision(8); for (PointId idx = 0; idx < input.size(); ++idx) { double x = input.getFieldAs<double>(Dimension::Id::X, idx); double y = input.getFieldAs<double>(Dimension::Id::Y, idx); double z = input.getFieldAs<double>(Dimension::Id::Z, idx); if (logOutput) { log()->floatPrecision(10); log()->get(LogLevel::Debug5) << "input: " << x << " y: " << y << " z: " << z << std::endl; } if (m_poly.empty()) { // We don't have a polygon, just a bounds. Filter on that // by itself. if (!m_cropOutside && m_bounds.contains(x, y, z)) output.appendPoint(input, idx); } #ifdef PDAL_HAVE_GEOS else { int ret(0); // precise filtering based on the geometry GEOSCoordSequence* coords = GEOSCoordSeq_create_r(m_geosEnvironment, 1, 3); if (!coords) throw pdal_error("unable to allocate coordinate sequence"); ret = GEOSCoordSeq_setX_r(m_geosEnvironment, coords, 0, x); if (!ret) throw pdal_error("unable to set x for coordinate sequence"); ret = GEOSCoordSeq_setY_r(m_geosEnvironment, coords, 0, y); if (!ret) throw pdal_error("unable to set y for coordinate sequence"); ret = GEOSCoordSeq_setZ_r(m_geosEnvironment, coords, 0, z); if (!ret) throw pdal_error("unable to set z for coordinate sequence"); GEOSGeometry* p = GEOSGeom_createPoint_r(m_geosEnvironment, coords); if (!p) throw pdal_error("unable to allocate candidate test point"); if (static_cast<bool>(GEOSPreparedContains_r(m_geosEnvironment, m_geosPreparedGeometry, p)) != m_cropOutside) output.appendPoint(input, idx); GEOSGeom_destroy_r(m_geosEnvironment, p); } #endif } }
void QgsZonalStatistics::statisticsFromMiddlePointTest( void* band, const QgsGeometry& poly, int pixelOffsetX, int pixelOffsetY, int nCellsX, int nCellsY, double cellSizeX, double cellSizeY, const QgsRectangle& rasterBBox, FeatureStats &stats ) { double cellCenterX, cellCenterY; float* scanLine = ( float * ) CPLMalloc( sizeof( float ) * nCellsX ); cellCenterY = rasterBBox.yMaximum() - pixelOffsetY * cellSizeY - cellSizeY / 2; stats.reset(); GEOSGeometry* polyGeos = poly.exportToGeos(); if ( !polyGeos ) { return; } GEOSContextHandle_t geosctxt = QgsGeometry::getGEOSHandler(); const GEOSPreparedGeometry* polyGeosPrepared = GEOSPrepare_r( geosctxt, polyGeos ); if ( !polyGeosPrepared ) { GEOSGeom_destroy_r( geosctxt, polyGeos ); return; } GEOSCoordSequence* cellCenterCoords = nullptr; GEOSGeometry* currentCellCenter = nullptr; for ( int i = 0; i < nCellsY; ++i ) { if ( GDALRasterIO( band, GF_Read, pixelOffsetX, pixelOffsetY + i, nCellsX, 1, scanLine, nCellsX, 1, GDT_Float32, 0, 0 ) != CPLE_None ) { continue; } cellCenterX = rasterBBox.xMinimum() + pixelOffsetX * cellSizeX + cellSizeX / 2; for ( int j = 0; j < nCellsX; ++j ) { if ( validPixel( scanLine[j] ) ) { GEOSGeom_destroy_r( geosctxt, currentCellCenter ); cellCenterCoords = GEOSCoordSeq_create_r( geosctxt, 1, 2 ); GEOSCoordSeq_setX_r( geosctxt, cellCenterCoords, 0, cellCenterX ); GEOSCoordSeq_setY_r( geosctxt, cellCenterCoords, 0, cellCenterY ); currentCellCenter = GEOSGeom_createPoint_r( geosctxt, cellCenterCoords ); if ( GEOSPreparedContains_r( geosctxt, polyGeosPrepared, currentCellCenter ) ) { stats.addValue( scanLine[j] ); } } cellCenterX += cellSizeX; } cellCenterY -= cellSizeY; } GEOSGeom_destroy_r( geosctxt, currentCellCenter ); CPLFree( scanLine ); GEOSPreparedGeom_destroy_r( geosctxt, polyGeosPrepared ); GEOSGeom_destroy_r( geosctxt, polyGeos ); }
void terms_to_coordseq(GEOSCommand *command) { char *buffer = command->param_bytes; int *index = &command->index; int size; GEOSCoordSequence *coordSeq = NULL; GEOSContextHandle_t handle = command->driver_data->handle; if(ei_decode_list_header(buffer, index, &size)) { erl_send_error(command, "notalist"); return; } unsigned int i; for(i = 0; i < size; i++) { //for each element int digitc; double x,y,z; if(ei_decode_tuple_header(buffer, index, &digitc)) { erl_send_error(command, "invalidlist"); if(coordSeq!=NULL) GEOSCoordSeq_destroy_r(handle, coordSeq); return; } if(coordSeq == NULL) { coordSeq = GEOSCoordSeq_create_r(handle, size, digitc); if(coordSeq == NULL) { erl_send_error(command, "create"); return; } } if(next_number(command, &x) || GEOSCoordSeq_setX_r(handle, coordSeq, i, x)==0) { erl_send_error(command, "setx"); GEOSCoordSeq_destroy_r(handle, coordSeq); return; } if(next_number(command, &y) || GEOSCoordSeq_setY_r(handle, coordSeq, i, y)==0) { erl_send_error(command, "sety"); GEOSCoordSeq_destroy_r(handle, coordSeq); return; } if(digitc == 3) { if(next_number(command, &z) || GEOSCoordSeq_setZ_r(handle, coordSeq, i, z)==0) { erl_send_error(command, "setz"); GEOSCoordSeq_destroy_r(handle, coordSeq); return; } } } ERL_WRITE_PTR_GEOSCOORDSEQUENCE(command, coordSeq); }
void QgsZonalStatistics::statisticsFromMiddlePointTest( const QgsGeometry &poly, int pixelOffsetX, int pixelOffsetY, int nCellsX, int nCellsY, double cellSizeX, double cellSizeY, const QgsRectangle &rasterBBox, FeatureStats &stats ) { double cellCenterX, cellCenterY; cellCenterY = rasterBBox.yMaximum() - pixelOffsetY * cellSizeY - cellSizeY / 2; stats.reset(); GEOSGeometry *polyGeos = poly.exportToGeos(); if ( !polyGeos ) { return; } GEOSContextHandle_t geosctxt = QgsGeometry::getGEOSHandler(); const GEOSPreparedGeometry *polyGeosPrepared = GEOSPrepare_r( geosctxt, polyGeos ); if ( !polyGeosPrepared ) { GEOSGeom_destroy_r( geosctxt, polyGeos ); return; } GEOSCoordSequence *cellCenterCoords = nullptr; GEOSGeometry *currentCellCenter = nullptr; QgsRectangle featureBBox = poly.boundingBox().intersect( &rasterBBox ); QgsRectangle intersectBBox = rasterBBox.intersect( &featureBBox ); QgsRasterBlock *block = mRasterProvider->block( mRasterBand, intersectBBox, nCellsX, nCellsY ); for ( int i = 0; i < nCellsY; ++i ) { cellCenterX = rasterBBox.xMinimum() + pixelOffsetX * cellSizeX + cellSizeX / 2; for ( int j = 0; j < nCellsX; ++j ) { if ( validPixel( block->value( i, j ) ) ) { GEOSGeom_destroy_r( geosctxt, currentCellCenter ); cellCenterCoords = GEOSCoordSeq_create_r( geosctxt, 1, 2 ); GEOSCoordSeq_setX_r( geosctxt, cellCenterCoords, 0, cellCenterX ); GEOSCoordSeq_setY_r( geosctxt, cellCenterCoords, 0, cellCenterY ); currentCellCenter = GEOSGeom_createPoint_r( geosctxt, cellCenterCoords ); if ( GEOSPreparedContains_r( geosctxt, polyGeosPrepared, currentCellCenter ) ) { stats.addValue( block->value( i, j ) ); } } cellCenterX += cellSizeX; } cellCenterY -= cellSizeY; } GEOSGeom_destroy_r( geosctxt, currentCellCenter ); GEOSPreparedGeom_destroy_r( geosctxt, polyGeosPrepared ); GEOSGeom_destroy_r( geosctxt, polyGeos ); delete block; }
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; }
static void populate_geom_into_coord_seq(GEOSContextHandle_t context, const GEOSGeometry* geom, GEOSCoordSequence* coord_seq, unsigned int i, char has_z) { const GEOSCoordSequence* cs = GEOSGeom_getCoordSeq_r(context, geom); double x = 0; if (cs) { GEOSCoordSeq_getX_r(context, cs, 0, &x); } GEOSCoordSeq_setX_r(context, coord_seq, i, x); x = 0; if (cs) { GEOSCoordSeq_getY_r(context, cs, 0, &x); } GEOSCoordSeq_setY_r(context, coord_seq, i, x); x = 0; if (has_z && cs) { GEOSCoordSeq_getZ_r(context, cs, 0, &x); } GEOSCoordSeq_setZ_r(context, coord_seq, i, x); }
VALUE rgeo_create_geos_point(VALUE factory, double x, double y, double z) { VALUE result = Qnil; RGeo_FactoryData* factory_data = RGEO_FACTORY_DATA_PTR(factory); GEOSContextHandle_t context = factory_data->geos_context; GEOSCoordSequence* coord_seq = GEOSCoordSeq_create_r(context, 1, 3); if (coord_seq) { if (GEOSCoordSeq_setX_r(context, coord_seq, 0, x)) { if (GEOSCoordSeq_setY_r(context, coord_seq, 0, y)) { if (GEOSCoordSeq_setZ_r(context, coord_seq, 0, z)) { GEOSGeometry* geom = GEOSGeom_createPoint_r(context, coord_seq); if (geom) { result = rgeo_wrap_geos_geometry(factory, geom, factory_data->globals->geos_point); } } } } } return result; }
State get_state(const Point &point, const GEOSPreparedGeometry *gp_domain, GEOSContextHandle_t handle) { State state; if (isfinite(point.x) && isfinite(point.y)) { // TODO: Avoid create-destroy GEOSCoordSequence *coords = GEOSCoordSeq_create_r(handle, 1, 2); GEOSCoordSeq_setX_r(handle, coords, 0, point.x); GEOSCoordSeq_setY_r(handle, coords, 0, point.y); GEOSGeometry *g_point = GEOSGeom_createPoint_r(handle, coords); state = GEOSPreparedCovers_r(handle, gp_domain, g_point) ? POINT_IN : POINT_OUT; GEOSGeom_destroy_r(handle, g_point); } else { state = POINT_NAN; } return state; }
GEOSGeometry* createGEOSPoint(GEOSContextHandle_t ctx, double x, double y, double z) { int ret(0); // precise filtering based on the geometry GEOSCoordSequence* coords = GEOSCoordSeq_create_r(ctx, 1, 3); if (!coords) throw pdal_error("unable to allocate coordinate sequence"); ret = GEOSCoordSeq_setX_r(ctx, coords, 0, x); if (!ret) throw pdal_error("unable to set x for coordinate sequence"); ret = GEOSCoordSeq_setY_r(ctx, coords, 0, y); if (!ret) throw pdal_error("unable to set y for coordinate sequence"); ret = GEOSCoordSeq_setZ_r(ctx, coords, 0, z); if (!ret) throw pdal_error("unable to set z for coordinate sequence"); GEOSGeometry* p = GEOSGeom_createPoint_r(ctx, coords); if (!p) throw pdal_error("unable to allocate candidate test point"); return p; }
QgsGeometry QgsGeometryAnalyzer::createOffsetGeometry( const QgsGeometry& geom, const QgsGeometry& lineGeom, double offset ) { if ( !geom || lineGeom.isEmpty() ) { return QgsGeometry(); } QList<QgsGeometry> inputGeomList; if ( geom.isMultipart() ) { inputGeomList = geom.asGeometryCollection(); } else { inputGeomList.push_back( geom ); } QList<GEOSGeometry*> outputGeomList; QList<QgsGeometry>::const_iterator inputGeomIt = inputGeomList.constBegin(); GEOSContextHandle_t geosctxt = QgsGeometry::getGEOSHandler(); for ( ; inputGeomIt != inputGeomList.constEnd(); ++inputGeomIt ) { if ( geom.type() == QgsWkbTypes::LineGeometry ) { GEOSGeometry* inputGeomItGeos = inputGeomIt->exportToGeos(); GEOSGeometry* offsetGeom = GEOSOffsetCurve_r( geosctxt, inputGeomItGeos, -offset, 8 /*quadSegments*/, 0 /*joinStyle*/, 5.0 /*mitreLimit*/ ); GEOSGeom_destroy_r( geosctxt, inputGeomItGeos ); if ( !offsetGeom || !GEOSisValid_r( geosctxt, offsetGeom ) ) { return QgsGeometry(); } if ( !GEOSisValid_r( geosctxt, offsetGeom ) || GEOSGeomTypeId_r( geosctxt, offsetGeom ) != GEOS_LINESTRING || GEOSGeomGetNumPoints_r( geosctxt, offsetGeom ) < 1 ) { GEOSGeom_destroy_r( geosctxt, offsetGeom ); return QgsGeometry(); } outputGeomList.push_back( offsetGeom ); } else if ( geom.type() == QgsWkbTypes::PointGeometry ) { QgsPoint p = ( *inputGeomIt ).asPoint(); p = createPointOffset( p.x(), p.y(), offset, lineGeom ); GEOSCoordSequence* ptSeq = GEOSCoordSeq_create_r( geosctxt, 1, 2 ); GEOSCoordSeq_setX_r( geosctxt, ptSeq, 0, p.x() ); GEOSCoordSeq_setY_r( geosctxt, ptSeq, 0, p.y() ); GEOSGeometry* geosPt = GEOSGeom_createPoint_r( geosctxt, ptSeq ); outputGeomList.push_back( geosPt ); } } QgsGeometry outGeometry; if ( !geom.isMultipart() ) { GEOSGeometry* outputGeom = outputGeomList.at( 0 ); if ( outputGeom ) { outGeometry.fromGeos( outputGeom ); } } else { GEOSGeometry** geomArray = new GEOSGeometry*[outputGeomList.size()]; for ( int i = 0; i < outputGeomList.size(); ++i ) { geomArray[i] = outputGeomList.at( i ); } GEOSGeometry* collection = nullptr; if ( geom.type() == QgsWkbTypes::PointGeometry ) { collection = GEOSGeom_createCollection_r( geosctxt, GEOS_MULTIPOINT, geomArray, outputGeomList.size() ); } else if ( geom.type() == QgsWkbTypes::LineGeometry ) { collection = GEOSGeom_createCollection_r( geosctxt, GEOS_MULTILINESTRING, geomArray, outputGeomList.size() ); } outGeometry.fromGeos( collection ); delete[] geomArray; } return outGeometry; }
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; }
bool QgsGeometryAnalyzer::createOffsetGeometry( QgsGeometry* geom, QgsGeometry* lineGeom, double offset ) { if ( !geom || !lineGeom ) { return false; } QList<QgsGeometry*> inputGeomList; if ( geom->isMultipart() ) { inputGeomList = geom->asGeometryCollection(); } else { inputGeomList.push_back( geom ); } QList<GEOSGeometry*> outputGeomList; QList<QgsGeometry*>::const_iterator inputGeomIt = inputGeomList.constBegin(); GEOSContextHandle_t geosctxt = QgsGeometry::getGEOSHandler(); for ( ; inputGeomIt != inputGeomList.constEnd(); ++inputGeomIt ) { if ( geom->type() == QGis::Line ) { //geos 3.3 needed for line offsets #if defined(GEOS_VERSION_MAJOR) && defined(GEOS_VERSION_MINOR) && \ ((GEOS_VERSION_MAJOR>3) || ((GEOS_VERSION_MAJOR==3) && (GEOS_VERSION_MINOR>=3))) GEOSGeometry* offsetGeom = GEOSOffsetCurve_r( geosctxt, ( *inputGeomIt )->asGeos(), -offset, 8 /*quadSegments*/, 0 /*joinStyle*/, 5.0 /*mitreLimit*/ ); if ( !offsetGeom || !GEOSisValid_r( geosctxt, offsetGeom ) ) { return false; } if ( !GEOSisValid_r( geosctxt, offsetGeom ) || GEOSGeomTypeId_r( geosctxt, offsetGeom ) != GEOS_LINESTRING || GEOSGeomGetNumPoints_r( geosctxt, offsetGeom ) < 1 ) { GEOSGeom_destroy_r( geosctxt, offsetGeom ); return false; } outputGeomList.push_back( offsetGeom ); #else outputGeomList.push_back( GEOSGeom_clone_r( geosctxt, ( *inputGeomIt )->asGeos() ) ); #endif } else if ( geom->type() == QGis::Point ) { QgsPoint p = ( *inputGeomIt )->asPoint(); p = createPointOffset( p.x(), p.y(), offset, lineGeom ); GEOSCoordSequence* ptSeq = GEOSCoordSeq_create_r( geosctxt, 1, 2 ); GEOSCoordSeq_setX_r( geosctxt, ptSeq, 0, p.x() ); GEOSCoordSeq_setY_r( geosctxt, ptSeq, 0, p.y() ); GEOSGeometry* geosPt = GEOSGeom_createPoint_r( geosctxt, ptSeq ); outputGeomList.push_back( geosPt ); } } if ( !geom->isMultipart() ) { GEOSGeometry* outputGeom = outputGeomList.at( 0 ); if ( outputGeom ) { geom->fromGeos( outputGeom ); } } else { GEOSGeometry** geomArray = new GEOSGeometry*[outputGeomList.size()]; for ( int i = 0; i < outputGeomList.size(); ++i ) { geomArray[i] = outputGeomList.at( i ); } GEOSGeometry* collection = 0; if ( geom->type() == QGis::Point ) { collection = GEOSGeom_createCollection_r( geosctxt, GEOS_MULTIPOINT, geomArray, outputGeomList.size() ); } else if ( geom->type() == QGis::Line ) { collection = GEOSGeom_createCollection_r( geosctxt, GEOS_MULTILINESTRING, geomArray, outputGeomList.size() ); } geom->fromGeos( collection ); delete[] geomArray; } return true; }
static GEOSCoordSequence* coord_seq_from_array(VALUE factory, VALUE array, char close) { Check_Type(array, T_ARRAY); RGeo_FactoryData* factory_data = RGEO_FACTORY_DATA_PTR(factory); VALUE point_type = factory_data->globals->feature_point; unsigned int len = (unsigned int)RARRAY_LEN(array); char has_z = (char)(RGEO_FACTORY_DATA_PTR(factory)->flags & RGEO_FACTORYFLAGS_SUPPORTS_Z_OR_M); unsigned int dims = has_z ? 3 : 2; double* coords = ALLOC_N(double, len == 0 ? 1 : len * dims); if (!coords) { return NULL; } GEOSContextHandle_t context = factory_data->geos_context; unsigned int i; for (i=0; i<len; ++i) { char good = 0; const GEOSGeometry* entry_geom = rgeo_convert_to_geos_geometry(factory, rb_ary_entry(array, i), point_type); if (entry_geom) { const GEOSCoordSequence* entry_cs = GEOSGeom_getCoordSeq_r(context, entry_geom); if (entry_cs) { double x; if (GEOSCoordSeq_getX_r(context, entry_cs, 0, &x)) { coords[i*dims] = x; if (GEOSCoordSeq_getY_r(context, entry_cs, 0, &x)) { coords[i*dims+1] = x; good = 1; if (has_z) { if (GEOSCoordSeq_getZ_r(context, entry_cs, 0, &x)) { coords[i*dims+2] = x; } else { good = 0; } } } } } } if (!good) { free(coords); return NULL; } } if (len > 0 && close) { if (coords[0] == coords[(len-1)*dims] && coords[1] == coords[(len-1)*dims+1]) { close = 0; } } else { close = 0; } GEOSCoordSequence* coord_seq = GEOSCoordSeq_create_r(context, len + close, 3); if (coord_seq) { for (i=0; i<len; ++i) { GEOSCoordSeq_setX_r(context, coord_seq, i, coords[i*dims]); GEOSCoordSeq_setY_r(context, coord_seq, i, coords[i*dims+1]); GEOSCoordSeq_setZ_r(context, coord_seq, i, has_z ? coords[i*dims+2] : 0); } if (close) { GEOSCoordSeq_setX_r(context, coord_seq, len, coords[0]); GEOSCoordSeq_setY_r(context, coord_seq, len, coords[1]); GEOSCoordSeq_setZ_r(context, coord_seq, len, has_z ? coords[2] : 0); } } free(coords); return coord_seq; }
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 ); }