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 const 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 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 );
557 GEOSGeometry *newGeos;
560 newGeos = GEOSOffsetCurve_r( geosctxt,
mGeos, distance, 0, GEOSBUF_JOIN_MITRE, 2 );
565 if ( GEOSGeomTypeId_r( geosctxt, newGeos ) == GEOS_MULTILINESTRING )
568 const int nParts = GEOSGetNumGeometries_r( geosctxt, newGeos );
569 double maximumLength = -1;
570 const GEOSGeometry *longestPart =
nullptr;
571 for (
int i = 0; i < nParts; ++i )
573 const GEOSGeometry *part = GEOSGetGeometryN_r( geosctxt, newGeos, i );
574 double partLength = -1;
575 if ( GEOSLength_r( geosctxt, part, &partLength ) == 1 )
577 if ( partLength > maximumLength )
579 maximumLength = partLength;
588 GEOSGeom_destroy_r( geosctxt, newGeos );
592 geos::unique_ptr longestPartClone( GEOSGeom_clone_r( geosctxt, longestPart ) );
593 GEOSGeom_destroy_r( geosctxt, newGeos );
594 newGeos = longestPartClone.release();
597 const int newNbPoints = GEOSGeomGetNumPoints_r( geosctxt, newGeos );
598 const GEOSCoordSequence *coordSeq = GEOSGeom_getCoordSeq_r( geosctxt, newGeos );
599 std::vector< double > newX;
600 std::vector< double > newY;
601 newX.resize( newNbPoints );
602 newY.resize( newNbPoints );
603 for (
int i = 0; i < newNbPoints; i++ )
605 GEOSCoordSeq_getX_r( geosctxt, coordSeq, i, &newX[i] );
606 GEOSCoordSeq_getY_r( geosctxt, coordSeq, i, &newY[i] );
612 catch ( GEOSException &e )
614 qWarning(
"GEOS exception: %s", e.what() );
631 if ( startDistance > 0 )
637 double distanceConsumed = 0;
640 for (
int i = 1; i <
nbPoints; ++i )
642 const double thisX =
x[i];
643 const double thisY =
y[i];
644 const double thisSegmentLength = std::sqrt( ( thisX - lastX ) * ( thisX - lastX ) + ( thisY - lastY ) * ( thisY - lastY ) );
645 distanceConsumed += thisSegmentLength;
646 if ( distanceConsumed >= smoothDistance )
648 const double c = ( distanceConsumed - smoothDistance ) / thisSegmentLength;
649 x1 = lastX +
c * ( thisX - lastX );
650 y1 = lastY +
c * ( thisY - lastY );
657 const double distance = std::sqrt( ( x1 - x0 ) * ( x1 - x0 ) + ( y1 - y0 ) * ( y1 - y0 ) );
658 const double extensionFactor = ( startDistance + distance ) / distance;
665 if ( endDistance > 0 )
673 double distanceConsumed = 0;
676 for (
int i =
nbPoints - 2; i >= 0; --i )
678 const double thisX =
x[i];
679 const double thisY =
y[i];
680 const double thisSegmentLength = std::sqrt( ( thisX - lastX ) * ( thisX - lastX ) + ( thisY - lastY ) * ( thisY - lastY ) );
681 distanceConsumed += thisSegmentLength;
682 if ( distanceConsumed >= smoothDistance )
684 const double c = ( distanceConsumed - smoothDistance ) / thisSegmentLength;
685 xend1 = lastX +
c * ( thisX - lastX );
686 yend1 = lastY +
c * ( thisY - lastY );
693 const double distance = std::sqrt( ( xend1 - xend0 ) * ( xend1 - xend0 ) + ( yend1 - yend0 ) * ( yend1 - yend0 ) );
694 const double extensionFactor = ( endDistance + distance ) / distance;
696 x.emplace_back( newEnd.
x() );
697 y.emplace_back( newEnd.
y() );
701 if ( startDistance > 0 )
703 x.insert(
x.begin(), x0 );
704 y.insert(
y.begin(), y0 );
725 double best_area = std::numeric_limits<double>::max();
726 double best_alpha = -1;
728 double best_length = 0;
729 double best_width = 0;
732 bbox[0] = std::numeric_limits<double>::max();
733 bbox[1] = std::numeric_limits<double>::max();
734 bbox[2] = std::numeric_limits<double>::lowest();
735 bbox[3] = std::numeric_limits<double>::lowest();
737 for ( std::size_t i = 0; i <
convexHull.size(); i++ )
754 const double dref = bbox[2] - bbox[0];
761 for ( alpha_d = 0; alpha_d < 90; alpha_d++ )
763 alpha = alpha_d * M_PI / 180.0;
764 d1 = std::cos( alpha ) * dref;
765 d2 = std::sin( alpha ) * dref;
786 bb[14] = bb[12] + d2;
787 bb[15] = bb[13] - d1;
790 for (
int i = 0; i < 16; i += 4 )
793 alpha_seg = ( ( i / 4 > 0 ? ( i / 4 ) - 1 : 3 ) ) * M_PI_2 + alpha;
795 double best_cp = std::numeric_limits<double>::max();
797 for ( std::size_t j = 0; j <
convexHull.size(); j++ )
806 const double distNearestPoint = best_cp / dref;
808 d1 = std::cos( alpha_seg ) * distNearestPoint;
809 d2 = std::sin( alpha_seg ) * distNearestPoint;
833 memcpy( best_bb, bb,
sizeof(
double ) * 16 );
838 for (
int i = 0; i < 16; i = i + 4 )
841 best_bb[( i + 4 ) % 16], best_bb[( i + 5 ) % 16], best_bb[( i + 6 ) % 16], best_bb[( i + 7 ) % 16],
842 &finalBb.
x[int ( i / 4 )], &finalBb.
y[int ( i / 4 )] );
845 finalBb.
alpha = best_alpha;
846 finalBb.
width = best_width;
847 finalBb.
length = best_length;
864 #if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=8
865 geos::unique_ptr geosPt( GEOSGeom_createPointFromXY_r( geosctxt, px, py ) );
867 GEOSCoordSequence *coord = GEOSCoordSeq_create_r( geosctxt, 1, 2 );
868 GEOSCoordSeq_setX_r( geosctxt, coord, 0, px );
869 GEOSCoordSeq_setY_r( geosctxt, coord, 0, py );
872 const int type = GEOSGeomTypeId_r( geosctxt,
mGeos );
873 const GEOSGeometry *extRing =
nullptr;
874 #if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=9
875 const GEOSPreparedGeometry *preparedExtRing =
nullptr;
878 if (
type != GEOS_POLYGON )
881 #if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=9
888 extRing = GEOSGetExteriorRing_r( geosctxt,
mGeos );
889 #if GEOS_VERSION_MAJOR>3 || ( GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR>=9 )
890 if ( ! mGeosPreparedBoundary )
892 mGeosPreparedBoundary = GEOSPrepare_r( geosctxt, extRing );
894 preparedExtRing = mGeosPreparedBoundary;
898 #if GEOS_VERSION_MAJOR>3 || ( GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR>=9 )
905 #if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=8
906 unsigned int nPoints = 0;
907 GEOSCoordSeq_getSize_r( geosctxt, nearestCoord.get(), &nPoints );
911 ( void )GEOSCoordSeq_getXY_r( geosctxt, nearestCoord.get(), 0, &nx, &ny );
913 ( void )GEOSCoordSeq_getX_r( geosctxt, nearestCoord.get(), 0, &nx );
914 ( void )GEOSCoordSeq_getY_r( geosctxt, nearestCoord.get(), 0, &ny );
924 catch ( GEOSException &e )
926 qWarning(
"GEOS exception: %s", e.what() );
946 const GEOSCoordSequence *coordSeq = GEOSGeom_getCoordSeq_r( geosctxt, centroidGeom.get() );
947 #if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=8
948 unsigned int nPoints = 0;
949 GEOSCoordSeq_getSize_r( geosctxt, coordSeq, &nPoints );
952 GEOSCoordSeq_getXY_r( geosctxt, coordSeq, 0, &px, &py );
954 GEOSCoordSeq_getX_r( geosctxt, coordSeq, 0, &px );
955 GEOSCoordSeq_getY_r( geosctxt, coordSeq, 0, &py );
966 const GEOSCoordSequence *coordSeq = GEOSGeom_getCoordSeq_r( geosctxt, pointGeom.get() );
967 #if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=8
968 unsigned int nPoints = 0;
969 GEOSCoordSeq_getSize_r( geosctxt, coordSeq, &nPoints );
973 GEOSCoordSeq_getXY_r( geosctxt, coordSeq, 0, &px, &py );
975 GEOSCoordSeq_getX_r( geosctxt, coordSeq, 0, &px );
976 GEOSCoordSeq_getY_r( geosctxt, coordSeq, 0, &py );
981 catch ( GEOSException &e )
983 qWarning(
"GEOS exception: %s", e.what() );
1009 while ( i <
nbPoints && ad[i] <= dl ) i++;
1019 di = std::sqrt( dx * dx + dy * dy );
1023 dx =
x[i + 1] -
x[i];
1024 dy =
y[i + 1] -
y[i];
1029 *px =
x[i] + dx * distr / di;
1030 *py =
y[i] + dy * distr / di;
1041 const GEOSGeometry *thisGeos =
geos();
1050 catch ( GEOSException &e )
1052 qWarning(
"GEOS exception: %s", e.what() );
1059 const GEOSGeometry *thisGeos =
geos();
1063 double distance = -1;
1068 catch ( GEOSException &e )
1070 qWarning(
"GEOS exception: %s", e.what() );
1103 catch ( GEOSException &e )
1105 qWarning(
"GEOS exception: %s", e.what() );
1126 ( void )GEOSArea_r( geosctxt,
mGeos, &
mArea );
1130 catch ( GEOSException &e )
1132 qWarning(
"GEOS exception: %s", e.what() );
1152 GEOSWKTWriter *writer = GEOSWKTWriter_create_r( geosctxt );
1154 char *wkt = GEOSWKTWriter_write_r( geosctxt, writer,
mGeos );
1155 const QString res( wkt );
1157 GEOSFree_r( geosctxt, wkt );
1159 GEOSWKTWriter_destroy_r( geosctxt, writer );
1164 catch ( GEOSException &e )
1166 qWarning(
"GEOS exception: %s", e.what() );
1174 std::vector< double > distances(
nbPoints );
1175 double totalDistance = 0;
1176 double oldX = -1.0, oldY = -1.0;
1177 for (
int i = 0; i <
nbPoints; i++ )
1182 distances[i] = std::sqrt( std::pow( oldX -
x[i], 2 ) + std::pow( oldY -
y[i], 2 ) );
1186 totalDistance += distances[i];
1188 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.
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.
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.