51 ,
type( GEOS_POLYGON )
97 mGeos = GEOSGeom_clone_r( QgsGeosContext::get(), ps.mGeos );
106 bool needClose =
false;
112 GEOSCoordSequence *coord =
nullptr;
113#if GEOS_VERSION_MAJOR>3 || ( GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR>=10 )
117 coord = GEOSCoordSeq_copyFromArrays_r( geosctxt,
x.data(),
y.data(),
nullptr,
nullptr,
nbPoints );
126 coord = GEOSCoordSeq_create_r( geosctxt,
nbPoints + ( needClose ? 1 : 0 ), 2 );
127 for (
int i = 0; i <
nbPoints; ++i )
129 GEOSCoordSeq_setXY_r( geosctxt, coord, i,
x[i],
y[i] );
135 GEOSCoordSeq_setXY_r( geosctxt, coord,
nbPoints,
x[0],
y[0] );
142 mGeos = GEOSGeom_createPolygon_r( geosctxt, GEOSGeom_createLinearRing_r( geosctxt, coord ),
nullptr, 0 );
145 case GEOS_LINESTRING:
146 mGeos = GEOSGeom_createLineString_r( geosctxt, coord );
150 mGeos = GEOSGeom_createPoint_r( geosctxt, coord );
162 if ( !mPreparedGeom )
166 return mPreparedGeom;
173 GEOSGeom_destroy_r( geosctxt,
mGeos );
179 GEOSPreparedGeom_destroy_r( geosctxt, mPreparedGeom );
180 mPreparedGeom =
nullptr;
183 if ( mGeosPreparedBoundary )
185 GEOSPreparedGeom_destroy_r( geosctxt, mGeosPreparedBoundary );
186 mGeosPreparedBoundary =
nullptr;
189 if ( mMultipartPreparedGeos )
191 GEOSPreparedGeom_destroy_r( geosctxt, mMultipartPreparedGeos );
192 mMultipartPreparedGeos =
nullptr;
194 if ( mMultipartGeos )
196 GEOSGeom_destroy_r( geosctxt, mMultipartGeos );
197 mMultipartGeos =
nullptr;
210 GEOSGeom_destroy_r( geosctxt,
mGeos );
213 GEOSPreparedGeom_destroy_r( geosctxt, mPreparedGeom );
215 if ( mGeosPreparedBoundary )
217 GEOSPreparedGeom_destroy_r( geosctxt, mGeosPreparedBoundary );
218 mGeosPreparedBoundary =
nullptr;
221 if ( mMultipartPreparedGeos )
223 GEOSPreparedGeom_destroy_r( geosctxt, mMultipartPreparedGeos );
224 mMultipartPreparedGeos =
nullptr;
226 if ( mMultipartGeos )
228 GEOSGeom_destroy_r( geosctxt, mMultipartGeos );
229 mMultipartGeos =
nullptr;
241std::unique_ptr<PointSet>
PointSet::extractShape(
int nbPtSh,
int imin,
int imax,
int fps,
int fpe,
double fptx,
double fpty )
245 auto newShape = std::make_unique< PointSet >();
246 newShape->type = GEOS_POLYGON;
247 newShape->nbPoints = nbPtSh;
248 newShape->x.resize( newShape->nbPoints );
249 newShape->y.resize( newShape->nbPoints );
252 for ( j = 0, i = imin; i != ( imax + 1 ) %
nbPoints; i = ( i + 1 ) %
nbPoints, j++ )
254 newShape->x[j] =
x[i];
255 newShape->y[j] =
y[i];
261 newShape->x[j] = fptx;
262 newShape->y[j] = fpty;
270 return std::unique_ptr< PointSet>(
new PointSet( *
this ) );
279 const bool result = ( GEOSPreparedContainsProperly_r( geosctxt,
preparedGeom(), point.get() ) == 1 );
283 catch ( QgsGeosException &e )
285 qWarning(
"GEOS exception: %s", e.what() );
310 const double labelArea = labelWidth * labelHeight;
312 QLinkedList<PointSet *> inputShapes;
313 inputShapes.push_back( inputShape );
314 QLinkedList<PointSet *> outputShapes;
316 while ( !inputShapes.isEmpty() )
318 PointSet *shape = inputShapes.takeFirst();
320 const std::vector< double > &
x = shape->
x;
321 const std::vector< double > &
y = shape->
y;
323 std::vector< int > pts( nbp );
324 for (
int i = 0; i < nbp; i++ )
336 for ( std::size_t ihs = 0; ihs < shape->
convexHull.size(); ihs++ )
339 const std::size_t ihn = ( ihs + 1 ) % shape->
convexHull.size();
342 const int ipn = ( ips + 1 ) % nbp;
348 for (
int i = ips; i != shape->
convexHull[ihn]; i = ( i + 1 ) % nbp )
372 const double s = ( base + b +
c ) / 2;
373 double area = s * ( s - base ) * ( s - b ) * ( s -
c );
395 bestArea = std::sqrt( bestArea );
396 double cx, cy, dx, dy, ex, ey, fx, fy, seg_length, ptx = 0, pty = 0, fptx = 0, fpty = 0;
397 int ps = -1, pe = -1, fps = -1, fpe = -1;
398 if ( retainedPt >= 0 && bestArea > labelArea )
400 double c = std::numeric_limits<double>::max();
405 for (
int i = ( shape->
convexHull[holeE] + 1 ) % nbp; i != ( shape->
convexHull[holeS] - 1 + nbp ) % nbp; i = j )
413 cx = (
x[i] +
x[j] ) / 2.0;
414 cy = (
y[i] +
y[j] ) / 2.0;
452 double pointX, pointY;
475 if ( isValid && b <
c )
486 const int imin = retainedPt;
487 int imax = ( ( ( fps < retainedPt && fpe < retainedPt ) || ( fps > retainedPt && fpe > retainedPt ) ) ? std::min( fps, fpe ) : std::max( fps, fpe ) );
489 int nbPtSh1, nbPtSh2;
491 nbPtSh1 = imax - imin + 1 + ( fpe != fps );
493 nbPtSh1 = imax + nbp - imin + 1 + ( fpe != fps );
495 if ( ( imax == fps ? fpe : fps ) < imin )
496 nbPtSh2 = imin - ( imax == fps ? fpe : fps ) + 1 + ( fpe != fps );
498 nbPtSh2 = imin + nbp - ( imax == fps ? fpe : fps ) + 1 + ( fpe != fps );
500 if ( retainedPt == -1 || fps == -1 || fpe == -1 )
506 else if ( imax == imin || nbPtSh1 <= 2 || nbPtSh2 <= 2 || nbPtSh1 == nbp || nbPtSh2 == nbp )
508 outputShapes.append( shape );
513 PointSet *newShape = shape->
extractShape( nbPtSh1, imin, imax, fps, fpe, fptx, fpty ).release();
520 inputShapes.append( newShape );
527 newShape = shape->
extractShape( nbPtSh2, imax, imin, fps, fpe, fptx, fpty ).release();
534 inputShapes.append( newShape );
542 outputShapes.append( shape );
560 newGeos.reset( GEOSOffsetCurve_r( geosctxt,
mGeos, distance, 0, GEOSBUF_JOIN_MITRE, 2 ) );
565 if ( GEOSGeomTypeId_r( geosctxt, newGeos.get() ) == GEOS_MULTILINESTRING )
568 const int nParts = GEOSGetNumGeometries_r( geosctxt, newGeos.get() );
569 double maximumLength = -1;
571 for (
int i = 0; i < nParts; ++i )
573 const GEOSGeometry *part = GEOSGetGeometryN_r( geosctxt, newGeos.get(), i );
574 double partLength = -1;
575 if ( GEOSLength_r( geosctxt, part, &partLength ) == 1 )
577 if ( partLength > maximumLength )
579 maximumLength = partLength;
591 geos::unique_ptr longestPartClone( GEOSGeom_clone_r( geosctxt, longestPart ) );
592 newGeos = std::move( longestPartClone );
595#if GEOS_VERSION_MAJOR==3 && GEOS_VERSION_MINOR<11
603 newGeos = std::move( reversed );
607 const int newNbPoints = GEOSGeomGetNumPoints_r( geosctxt, newGeos.get() );
608 const GEOSCoordSequence *coordSeq = GEOSGeom_getCoordSeq_r( geosctxt, newGeos.get() );
609 std::vector< double > newX;
610 std::vector< double > newY;
611 newX.resize( newNbPoints );
612 newY.resize( newNbPoints );
613 for (
int i = 0; i < newNbPoints; i++ )
615 GEOSCoordSeq_getX_r( geosctxt, coordSeq, i, &newX[i] );
616 GEOSCoordSeq_getY_r( geosctxt, coordSeq, i, &newY[i] );
619 x = std::move( newX );
620 y = std::move( newY );
622 catch ( QgsGeosException &e )
624 qWarning(
"GEOS exception: %s", e.what() );
630 mGeos = newGeos.release();
641 if ( startDistance > 0 )
647 double distanceConsumed = 0;
650 for (
int i = 1; i <
nbPoints; ++i )
652 const double thisX =
x[i];
653 const double thisY =
y[i];
655 distanceConsumed += thisSegmentLength;
656 if ( distanceConsumed >= smoothDistance )
658 const double c = ( distanceConsumed - smoothDistance ) / thisSegmentLength;
659 x1 = lastX +
c * ( thisX - lastX );
660 y1 = lastY +
c * ( thisY - lastY );
668 const double extensionFactor = ( startDistance + distance ) / distance;
675 if ( endDistance > 0 )
683 double distanceConsumed = 0;
686 for (
int i =
nbPoints - 2; i >= 0; --i )
688 const double thisX =
x[i];
689 const double thisY =
y[i];
691 distanceConsumed += thisSegmentLength;
692 if ( distanceConsumed >= smoothDistance )
694 const double c = ( distanceConsumed - smoothDistance ) / thisSegmentLength;
695 xend1 = lastX +
c * ( thisX - lastX );
696 yend1 = lastY +
c * ( thisY - lastY );
704 const double extensionFactor = ( endDistance + distance ) / distance;
706 x.emplace_back( newEnd.
x() );
707 y.emplace_back( newEnd.
y() );
711 if ( startDistance > 0 )
713 x.insert(
x.begin(), x0 );
714 y.insert(
y.begin(), y0 );
735 double best_area = std::numeric_limits<double>::max();
736 double best_alpha = -1;
738 double best_length = 0;
739 double best_width = 0;
742 bbox[0] = std::numeric_limits<double>::max();
743 bbox[1] = std::numeric_limits<double>::max();
744 bbox[2] = std::numeric_limits<double>::lowest();
745 bbox[3] = std::numeric_limits<double>::lowest();
747 for ( std::size_t i = 0; i <
convexHull.size(); i++ )
764 const double dref = bbox[2] - bbox[0];
771 for ( alpha_d = 0; alpha_d < 90; alpha_d++ )
773 alpha = alpha_d * M_PI / 180.0;
774 d1 = std::cos( alpha ) * dref;
775 d2 = std::sin( alpha ) * dref;
796 bb[14] = bb[12] + d2;
797 bb[15] = bb[13] - d1;
800 for (
int i = 0; i < 16; i += 4 )
803 alpha_seg = ( ( i / 4 > 0 ? ( i / 4 ) - 1 : 3 ) ) * M_PI_2 + alpha;
805 double best_cp = std::numeric_limits<double>::max();
807 for ( std::size_t j = 0; j <
convexHull.size(); j++ )
816 const double distNearestPoint = best_cp / dref;
818 d1 = std::cos( alpha_seg ) * distNearestPoint;
819 d2 = std::sin( alpha_seg ) * distNearestPoint;
843 memcpy( best_bb, bb,
sizeof(
double ) * 16 );
848 for (
int i = 0; i < 16; i = i + 4 )
851 best_bb[( i + 4 ) % 16], best_bb[( i + 5 ) % 16], best_bb[( i + 6 ) % 16], best_bb[( i + 7 ) % 16],
852 &finalBb.
x[int ( i / 4 )], &finalBb.
y[int ( i / 4 )] );
855 finalBb.
alpha = best_alpha;
856 finalBb.
width = best_width;
857 finalBb.
length = best_length;
874 geos::unique_ptr geosPt( GEOSGeom_createPointFromXY_r( geosctxt, px, py ) );
875 const int type = GEOSGeomTypeId_r( geosctxt,
mGeos );
877 const GEOSPreparedGeometry *preparedExtRing =
nullptr;
879 if (
type != GEOS_POLYGON )
887 extRing = GEOSGetExteriorRing_r( geosctxt,
mGeos );
888 if ( ! mGeosPreparedBoundary )
890 mGeosPreparedBoundary = GEOSPrepare_r( geosctxt, extRing );
892 preparedExtRing = mGeosPreparedBoundary;
898 unsigned int nPoints = 0;
899 GEOSCoordSeq_getSize_r( geosctxt, nearestCoord.get(), &nPoints );
903 ( void )GEOSCoordSeq_getXY_r( geosctxt, nearestCoord.get(), 0, &nx, &ny );
912 catch ( QgsGeosException &e )
914 qWarning(
"GEOS exception: %s", e.what() );
934 const GEOSCoordSequence *coordSeq = GEOSGeom_getCoordSeq_r( geosctxt, centroidGeom.get() );
935 unsigned int nPoints = 0;
936 GEOSCoordSeq_getSize_r( geosctxt, coordSeq, &nPoints );
939 GEOSCoordSeq_getXY_r( geosctxt, coordSeq, 0, &px, &py );
949 const GEOSCoordSequence *coordSeq = GEOSGeom_getCoordSeq_r( geosctxt, pointGeom.get() );
950 unsigned int nPoints = 0;
951 GEOSCoordSeq_getSize_r( geosctxt, coordSeq, &nPoints );
955 GEOSCoordSeq_getXY_r( geosctxt, coordSeq, 0, &px, &py );
959 catch ( QgsGeosException &e )
961 qWarning(
"GEOS exception: %s", e.what() );
987 while ( i <
nbPoints && ad[i] <= dl ) i++;
997 di = std::sqrt( dx * dx + dy * dy );
1001 dx =
x[i + 1] -
x[i];
1002 dy =
y[i + 1] -
y[i];
1007 *px =
x[i] + dx * distr / di;
1008 *py =
y[i] + dy * distr / di;
1028 catch ( QgsGeosException &e )
1030 qWarning(
"GEOS exception: %s", e.what() );
1041 double distance = -1;
1046 catch ( QgsGeosException &e )
1048 qWarning(
"GEOS exception: %s", e.what() );
1081 catch ( QgsGeosException &e )
1083 qWarning(
"GEOS exception: %s", e.what() );
1104 ( void )GEOSArea_r( geosctxt,
mGeos, &
mArea );
1108 catch ( QgsGeosException &e )
1110 qWarning(
"GEOS exception: %s", e.what() );
1130 GEOSWKTWriter *writer = GEOSWKTWriter_create_r( geosctxt );
1132 char *wkt = GEOSWKTWriter_write_r( geosctxt, writer,
mGeos );
1133 const QString res( wkt );
1135 GEOSFree_r( geosctxt, wkt );
1137 GEOSWKTWriter_destroy_r( geosctxt, writer );
1142 catch ( QgsGeosException &e )
1144 qWarning(
"GEOS exception: %s", e.what() );
1152 std::vector< double > distances(
nbPoints );
1153 double totalDistance = 0;
1154 double oldX = -1.0, oldY = -1.0;
1155 for (
int i = 0; i <
nbPoints; i++ )
1160 distances[i] = std::sqrt( std::pow( oldX -
x[i], 2 ) + std::pow( oldY -
y[i], 2 ) );
1164 totalDistance += distances[i];
1166 return std::make_tuple( std::move( distances ), totalDistance );
static double sqrDistance2D(double x1, double y1, double x2, double y2)
Returns the squared 2D distance between (x1, y1) and (x2, y2).
static double distance2D(double x1, double y1, double x2, double y2)
Returns the 2D distance between (x1, y1) and (x2, y2).
static QgsPointXY interpolatePointOnLine(double x1, double y1, double x2, double y2, double fraction)
Interpolates the position of a point a fraction of the way along the line from (x1,...
static GEOSContextHandle_t get()
Returns a thread local instance of a GEOS context, safe for use in the current thread.
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true, const char *file=__builtin_FILE(), const char *function=__builtin_FUNCTION(), int line=__builtin_LINE())
Adds a message to the log instance (and creates it if necessary).
static std::vector< int > convexHullId(std::vector< int > &id, const std::vector< double > &x, const std::vector< double > &y)
Compute the convex hull in O(n·log(n)).
static bool computeLineIntersection(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4, double *x, double *y)
Compute the point where two lines intersect.
static bool isSegIntersects(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4)
Returns true if the two segments intersect.
static double cross_product(double x1, double y1, double x2, double y2, double x3, double y3)
static bool containsCandidate(const GEOSPreparedGeometry *geom, double x, double y, double width, double height, double alpha)
Returns true if a GEOS prepared geometry totally contains a label candidate.
geos::unique_ptr interpolatePoint(double distance) const
Returns a GEOS geometry representing the point interpolated on the shape by distance.
std::unique_ptr< PointSet > clone() const
Returns a copy of the point set.
bool containsLabelCandidate(double x, double y, double width, double height, double alpha=0) const
Tests whether a possible label candidate will fit completely within the shape.
double lineLocatePoint(const GEOSGeometry *point) const
Returns the distance along the geometry closest to the specified GEOS point.
double length() const
Returns length of line geometry.
void extendLineByDistance(double startDistance, double endDistance, double smoothDistance)
Extends linestrings by the specified amount at the start and end of the line, by extending the existi...
double area() const
Returns area of polygon geometry.
bool isClosed() const
Returns true if pointset is closed.
void createGeosGeom() const
void getPointByDistance(double *d, double *ad, double dl, double *px, double *py) const
Gets a point a set distance along a line geometry.
bool boundingBoxIntersects(const PointSet *other) const
Returns true if the bounding box of this pointset intersects the bounding box of another pointset.
void getCentroid(double &px, double &py, bool forceInside=false) const
OrientedConvexHullBoundingBox computeConvexHullOrientedBoundingBox(bool &ok) const
Computes an oriented bounding box for the shape's convex hull.
void offsetCurveByDistance(double distance)
Offsets linestrings by the specified distance.
std::vector< int > convexHull
const GEOSPreparedGeometry * preparedGeom() const
QString toWkt() const
Returns a WKT representation of the point set.
const GEOSGeometry * geos() const
Returns the point set's GEOS geometry.
void invalidateGeos() const
double minDistanceToPoint(double px, double py, double *rx=nullptr, double *ry=nullptr) const
Returns the squared minimum distance between the point set geometry and the point (px,...
std::unique_ptr< PointSet > extractShape(int nbPtSh, int imin, int imax, int fps, int fpe, double fptx, double fpty)
Does... something completely inscrutable.
bool containsPoint(double x, double y) const
Tests whether point set contains a specified point.
std::tuple< std::vector< double >, double > edgeDistances() const
Returns a vector of edge distances as well as its total length.
static QLinkedList< PointSet * > splitPolygons(PointSet *inputShape, double labelWidth, double labelHeight)
Split a polygon using some random logic into some other polygons.
std::unique_ptr< GEOSGeometry, GeosDeleter > unique_ptr
Scoped GEOS pointer.
std::unique_ptr< GEOSCoordSequence, GeosDeleter > coord_sequence_unique_ptr
Scoped GEOS coordinate sequence pointer.
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference).
Represents the minimum area, oriented bounding box surrounding a convex hull.
struct GEOSGeom_t GEOSGeometry