48 : nbPoints( nbPoints )
49 , type( GEOS_POLYGON )
104 bool needClose =
false;
110 GEOSCoordSequence *coord = GEOSCoordSeq_create_r( geosctxt,
nbPoints + ( needClose ? 1 : 0 ), 2 );
111 for (
int i = 0; i <
nbPoints; ++i )
113 #if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=8
114 GEOSCoordSeq_setXY_r( geosctxt, coord, i,
x[i],
y[i] );
116 GEOSCoordSeq_setX_r( geosctxt, coord, i,
x[i] );
117 GEOSCoordSeq_setY_r( geosctxt, coord, i,
y[i] );
124 #if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=8
125 GEOSCoordSeq_setXY_r( geosctxt, coord,
nbPoints,
x[0],
y[0] );
127 GEOSCoordSeq_setX_r( geosctxt, coord,
nbPoints,
x[0] );
128 GEOSCoordSeq_setY_r( geosctxt, coord,
nbPoints,
y[0] );
135 mGeos = GEOSGeom_createPolygon_r( geosctxt, GEOSGeom_createLinearRing_r( geosctxt, coord ),
nullptr, 0 );
138 case GEOS_LINESTRING:
139 mGeos = GEOSGeom_createLineString_r( geosctxt, coord );
143 mGeos = GEOSGeom_createPoint_r( geosctxt, coord );
155 if ( !mPreparedGeom )
159 return mPreparedGeom;
166 GEOSGeom_destroy_r( geosctxt,
mGeos );
172 GEOSPreparedGeom_destroy_r( geosctxt, mPreparedGeom );
173 mPreparedGeom =
nullptr;
176 if ( mGeosPreparedBoundary )
178 GEOSPreparedGeom_destroy_r( geosctxt, mGeosPreparedBoundary );
179 mGeosPreparedBoundary =
nullptr;
182 if ( mMultipartPreparedGeos )
184 GEOSPreparedGeom_destroy_r( geosctxt, mMultipartPreparedGeos );
185 mMultipartPreparedGeos =
nullptr;
187 if ( mMultipartGeos )
189 GEOSGeom_destroy_r( geosctxt, mMultipartGeos );
190 mMultipartGeos =
nullptr;
203 GEOSGeom_destroy_r( geosctxt,
mGeos );
206 GEOSPreparedGeom_destroy_r( geosctxt, mPreparedGeom );
208 if ( mGeosPreparedBoundary )
210 GEOSPreparedGeom_destroy_r( geosctxt, mGeosPreparedBoundary );
211 mGeosPreparedBoundary =
nullptr;
214 if ( mMultipartPreparedGeos )
216 GEOSPreparedGeom_destroy_r( geosctxt, mMultipartPreparedGeos );
217 mMultipartPreparedGeos =
nullptr;
219 if ( mMultipartGeos )
221 GEOSGeom_destroy_r( geosctxt, mMultipartGeos );
222 mMultipartGeos =
nullptr;
234 std::unique_ptr<PointSet>
PointSet::extractShape(
int nbPtSh,
int imin,
int imax,
int fps,
int fpe,
double fptx,
double fpty )
238 std::unique_ptr<PointSet> newShape = std::make_unique< PointSet >();
239 newShape->type = GEOS_POLYGON;
240 newShape->nbPoints = nbPtSh;
241 newShape->x.resize( newShape->nbPoints );
242 newShape->y.resize( newShape->nbPoints );
245 for ( j = 0, i = imin; i != ( imax + 1 ) %
nbPoints; i = ( i + 1 ) %
nbPoints, j++ )
247 newShape->x[j] =
x[i];
248 newShape->y[j] =
y[i];
254 newShape->x[j] = fptx;
255 newShape->y[j] = fpty;
263 return std::unique_ptr< PointSet>(
new PointSet( *
this ) );
271 #if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=8
274 GEOSCoordSequence *seq = GEOSCoordSeq_create_r( geosctxt, 1, 2 );
275 GEOSCoordSeq_setX_r( geosctxt, seq, 0,
x );
276 GEOSCoordSeq_setY_r( geosctxt, seq, 0,
y );
279 bool result = ( GEOSPreparedContainsProperly_r( geosctxt,
preparedGeom(), point.get() ) == 1 );
283 catch ( GEOSException &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 std::size_t ihn = ( ihs + 1 ) % shape->
convexHull.size();
342 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 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 );
557 GEOSGeometry *newGeos;
560 newGeos = GEOSOffsetCurve_r( geosctxt,
mGeos, distance, 0, GEOSBUF_JOIN_MITRE, 2 );
563 if ( GEOSGeomTypeId_r( geosctxt, newGeos ) == GEOS_MULTILINESTRING )
566 const int nParts = GEOSGetNumGeometries_r( geosctxt, newGeos );
567 double maximumLength = -1;
568 const GEOSGeometry *longestPart =
nullptr;
569 for (
int i = 0; i < nParts; ++i )
571 const GEOSGeometry *part = GEOSGetGeometryN_r( geosctxt, newGeos, i );
572 double partLength = -1;
573 if ( GEOSLength_r( geosctxt, part, &partLength ) == 1 )
575 if ( partLength > maximumLength )
577 maximumLength = partLength;
586 GEOSGeom_destroy_r( geosctxt, newGeos );
590 geos::unique_ptr longestPartClone( GEOSGeom_clone_r( geosctxt, longestPart ) );
591 GEOSGeom_destroy_r( geosctxt, newGeos );
592 newGeos = longestPartClone.release();
595 const int newNbPoints = GEOSGeomGetNumPoints_r( geosctxt, newGeos );
596 const GEOSCoordSequence *coordSeq = GEOSGeom_getCoordSeq_r( geosctxt, newGeos );
597 std::vector< double > newX;
598 std::vector< double > newY;
599 newX.resize( newNbPoints );
600 newY.resize( newNbPoints );
601 for (
int i = 0; i < newNbPoints; i++ )
603 GEOSCoordSeq_getX_r( geosctxt, coordSeq, i, &newX[i] );
604 GEOSCoordSeq_getY_r( geosctxt, coordSeq, i, &newY[i] );
610 catch ( GEOSException &e )
612 qWarning(
"GEOS exception: %s", e.what() );
629 if ( startDistance > 0 )
635 double distanceConsumed = 0;
638 for (
int i = 1; i <
nbPoints; ++i )
642 const double thisSegmentLength = std::sqrt( ( thisX - lastX ) * ( thisX - lastX ) + ( thisY - lastY ) * ( thisY - lastY ) );
643 distanceConsumed += thisSegmentLength;
644 if ( distanceConsumed >= smoothDistance )
646 double c = ( distanceConsumed - smoothDistance ) / thisSegmentLength;
647 x1 = lastX +
c * ( thisX - lastX );
648 y1 = lastY +
c * ( thisY - lastY );
655 const double distance = std::sqrt( ( x1 - x0 ) * ( x1 - x0 ) + ( y1 - y0 ) * ( y1 - y0 ) );
656 const double extensionFactor = ( startDistance + distance ) / distance;
663 if ( endDistance > 0 )
671 double distanceConsumed = 0;
674 for (
int i =
nbPoints - 2; i >= 0; --i )
678 const double thisSegmentLength = std::sqrt( ( thisX - lastX ) * ( thisX - lastX ) + ( thisY - lastY ) * ( thisY - lastY ) );
679 distanceConsumed += thisSegmentLength;
680 if ( distanceConsumed >= smoothDistance )
682 double c = ( distanceConsumed - smoothDistance ) / thisSegmentLength;
683 xend1 = lastX +
c * ( thisX - lastX );
684 yend1 = lastY +
c * ( thisY - lastY );
691 const double distance = std::sqrt( ( xend1 - xend0 ) * ( xend1 - xend0 ) + ( yend1 - yend0 ) * ( yend1 - yend0 ) );
692 const double extensionFactor = ( endDistance + distance ) / distance;
694 x.emplace_back( newEnd.
x() );
695 y.emplace_back( newEnd.
y() );
699 if ( startDistance > 0 )
701 x.insert(
x.begin(), x0 );
702 y.insert(
y.begin(), y0 );
723 double best_area = std::numeric_limits<double>::max();
724 double best_alpha = -1;
726 double best_length = 0;
727 double best_width = 0;
730 bbox[0] = std::numeric_limits<double>::max();
731 bbox[1] = std::numeric_limits<double>::max();
732 bbox[2] = std::numeric_limits<double>::lowest();
733 bbox[3] = std::numeric_limits<double>::lowest();
735 for ( std::size_t i = 0; i <
convexHull.size(); i++ )
752 const double dref = bbox[2] - bbox[0];
759 for ( alpha_d = 0; alpha_d < 90; alpha_d++ )
761 alpha = alpha_d * M_PI / 180.0;
762 d1 = std::cos( alpha ) * dref;
763 d2 = std::sin( alpha ) * dref;
784 bb[14] = bb[12] + d2;
785 bb[15] = bb[13] - d1;
788 for (
int i = 0; i < 16; i += 4 )
791 alpha_seg = ( ( i / 4 > 0 ? ( i / 4 ) - 1 : 3 ) ) * M_PI_2 + alpha;
793 double best_cp = std::numeric_limits<double>::max();
795 for ( std::size_t j = 0; j <
convexHull.size(); j++ )
804 const double distNearestPoint = best_cp / dref;
806 d1 = std::cos( alpha_seg ) * distNearestPoint;
807 d2 = std::sin( alpha_seg ) * distNearestPoint;
831 memcpy( best_bb, bb,
sizeof(
double ) * 16 );
836 for (
int i = 0; i < 16; i = i + 4 )
839 best_bb[( i + 4 ) % 16], best_bb[( i + 5 ) % 16], best_bb[( i + 6 ) % 16], best_bb[( i + 7 ) % 16],
840 &finalBb.
x[int ( i / 4 )], &finalBb.
y[int ( i / 4 )] );
843 finalBb.
alpha = best_alpha;
844 finalBb.
width = best_width;
845 finalBb.
length = best_length;
862 #if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=8
863 geos::unique_ptr geosPt( GEOSGeom_createPointFromXY_r( geosctxt, px, py ) );
865 GEOSCoordSequence *coord = GEOSCoordSeq_create_r( geosctxt, 1, 2 );
866 GEOSCoordSeq_setX_r( geosctxt, coord, 0, px );
867 GEOSCoordSeq_setY_r( geosctxt, coord, 0, py );
870 int type = GEOSGeomTypeId_r( geosctxt,
mGeos );
871 const GEOSGeometry *extRing =
nullptr;
872 #if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=9
873 const GEOSPreparedGeometry *preparedExtRing =
nullptr;
876 if (
type != GEOS_POLYGON )
879 #if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=9
886 extRing = GEOSGetExteriorRing_r( geosctxt,
mGeos );
887 #if GEOS_VERSION_MAJOR>3 || ( GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR>=9 )
888 if ( ! mGeosPreparedBoundary )
890 mGeosPreparedBoundary = GEOSPrepare_r( geosctxt, extRing );
892 preparedExtRing = mGeosPreparedBoundary;
896 #if GEOS_VERSION_MAJOR>3 || ( GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR>=9 )
903 #if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=8
904 unsigned int nPoints = 0;
905 GEOSCoordSeq_getSize_r( geosctxt, nearestCoord.get(), &nPoints );
909 ( void )GEOSCoordSeq_getXY_r( geosctxt, nearestCoord.get(), 0, &nx, &ny );
911 ( void )GEOSCoordSeq_getX_r( geosctxt, nearestCoord.get(), 0, &nx );
912 ( void )GEOSCoordSeq_getY_r( geosctxt, nearestCoord.get(), 0, &ny );
922 catch ( GEOSException &e )
924 qWarning(
"GEOS exception: %s", e.what() );
944 const GEOSCoordSequence *coordSeq = GEOSGeom_getCoordSeq_r( geosctxt, centroidGeom.get() );
945 #if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=8
946 unsigned int nPoints = 0;
947 GEOSCoordSeq_getSize_r( geosctxt, coordSeq, &nPoints );
950 GEOSCoordSeq_getXY_r( geosctxt, coordSeq, 0, &px, &py );
952 GEOSCoordSeq_getX_r( geosctxt, coordSeq, 0, &px );
953 GEOSCoordSeq_getY_r( geosctxt, coordSeq, 0, &py );
964 const GEOSCoordSequence *coordSeq = GEOSGeom_getCoordSeq_r( geosctxt, pointGeom.get() );
965 #if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=8
966 unsigned int nPoints = 0;
967 GEOSCoordSeq_getSize_r( geosctxt, coordSeq, &nPoints );
971 GEOSCoordSeq_getXY_r( geosctxt, coordSeq, 0, &px, &py );
973 GEOSCoordSeq_getX_r( geosctxt, coordSeq, 0, &px );
974 GEOSCoordSeq_getY_r( geosctxt, coordSeq, 0, &py );
979 catch ( GEOSException &e )
981 qWarning(
"GEOS exception: %s", e.what() );
1007 while ( i <
nbPoints && ad[i] <= dl ) i++;
1017 di = std::sqrt( dx * dx + dy * dy );
1021 dx =
x[i + 1] -
x[i];
1022 dy =
y[i + 1] -
y[i];
1027 *px =
x[i] + dx * distr / di;
1028 *py =
y[i] + dy * distr / di;
1063 catch ( GEOSException &e )
1065 qWarning(
"GEOS exception: %s", e.what() );
1086 ( void )GEOSArea_r( geosctxt,
mGeos, &
mArea );
1090 catch ( GEOSException &e )
1092 qWarning(
"GEOS exception: %s", e.what() );
1112 GEOSWKTWriter *writer = GEOSWKTWriter_create_r( geosctxt );
1114 char *wkt = GEOSWKTWriter_write_r( geosctxt, writer,
mGeos );
1115 const QString res( wkt );
1117 GEOSFree_r( geosctxt, wkt );
1119 GEOSWKTWriter_destroy_r( geosctxt, writer );
1124 catch ( GEOSException &e )
1126 qWarning(
"GEOS exception: %s", e.what() );
1134 std::vector< double > distances(
nbPoints );
1135 double totalDistance = 0;
1136 double oldX = -1.0, oldY = -1.0;
1137 for (
int i = 0; i <
nbPoints; i++ )
1142 distances[i] = std::sqrt( std::pow( oldX -
x[i], 2 ) + std::pow( oldY -
y[i], 2 ) );
1146 totalDistance += distances[i];
1148 return std::make_tuple( std::move( distances ), totalDistance );
static QgsPointXY interpolatePointOnLine(double x1, double y1, double x2, double y2, double fraction) SIP_HOLDGIL
Interpolates the position of a point a fraction of the way along the line from (x1,...
static GEOSContextHandle_t getGEOSHandler()
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
A class to represent a 2D point.
static double dist_euc2d(double x1, double y1, double x2, double y2)
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 double dist_euc2d_sq(double x1, double y1, double x2, double y2)
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.
The underlying raw pal geometry class.
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.
OrientedConvexHullBoundingBox computeConvexHullOrientedBoundingBox(bool &ok)
Computes an oriented bounding box for the shape's convex hull.
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
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
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.
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,...
void getPointByDistance(double *d, double *ad, double dl, double *px, double *py)
Gets a point a set distance along a line geometry.
std::unique_ptr< PointSet > extractShape(int nbPtSh, int imin, int imax, int fps, int fpe, double fptx, double fpty)
Does...
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.