47 : nbPoints( nbPoints )
48 , type( GEOS_POLYGON )
103 bool needClose =
false;
109 GEOSCoordSequence *coord =
nullptr;
110#if GEOS_VERSION_MAJOR>3 || ( GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR>=10 )
114 coord = GEOSCoordSeq_copyFromArrays_r( geosctxt,
x.data(),
y.data(),
nullptr,
nullptr,
nbPoints );
123 coord = GEOSCoordSeq_create_r( geosctxt,
nbPoints + ( needClose ? 1 : 0 ), 2 );
124 for (
int i = 0; i <
nbPoints; ++i )
126 GEOSCoordSeq_setXY_r( geosctxt, coord, i,
x[i],
y[i] );
132 GEOSCoordSeq_setXY_r( geosctxt, coord,
nbPoints,
x[0],
y[0] );
139 mGeos = GEOSGeom_createPolygon_r( geosctxt, GEOSGeom_createLinearRing_r( geosctxt, coord ),
nullptr, 0 );
142 case GEOS_LINESTRING:
143 mGeos = GEOSGeom_createLineString_r( geosctxt, coord );
147 mGeos = GEOSGeom_createPoint_r( geosctxt, coord );
159 if ( !mPreparedGeom )
163 return mPreparedGeom;
170 GEOSGeom_destroy_r( geosctxt,
mGeos );
176 GEOSPreparedGeom_destroy_r( geosctxt, mPreparedGeom );
177 mPreparedGeom =
nullptr;
180 if ( mGeosPreparedBoundary )
182 GEOSPreparedGeom_destroy_r( geosctxt, mGeosPreparedBoundary );
183 mGeosPreparedBoundary =
nullptr;
186 if ( mMultipartPreparedGeos )
188 GEOSPreparedGeom_destroy_r( geosctxt, mMultipartPreparedGeos );
189 mMultipartPreparedGeos =
nullptr;
191 if ( mMultipartGeos )
193 GEOSGeom_destroy_r( geosctxt, mMultipartGeos );
194 mMultipartGeos =
nullptr;
207 GEOSGeom_destroy_r( geosctxt,
mGeos );
210 GEOSPreparedGeom_destroy_r( geosctxt, mPreparedGeom );
212 if ( mGeosPreparedBoundary )
214 GEOSPreparedGeom_destroy_r( geosctxt, mGeosPreparedBoundary );
215 mGeosPreparedBoundary =
nullptr;
218 if ( mMultipartPreparedGeos )
220 GEOSPreparedGeom_destroy_r( geosctxt, mMultipartPreparedGeos );
221 mMultipartPreparedGeos =
nullptr;
223 if ( mMultipartGeos )
225 GEOSGeom_destroy_r( geosctxt, mMultipartGeos );
226 mMultipartGeos =
nullptr;
238std::unique_ptr<PointSet>
PointSet::extractShape(
int nbPtSh,
int imin,
int imax,
int fps,
int fpe,
double fptx,
double fpty )
242 std::unique_ptr<PointSet> newShape = std::make_unique< PointSet >();
243 newShape->type = GEOS_POLYGON;
244 newShape->nbPoints = nbPtSh;
245 newShape->x.resize( newShape->nbPoints );
246 newShape->y.resize( newShape->nbPoints );
249 for ( j = 0, i = imin; i != ( imax + 1 ) %
nbPoints; i = ( i + 1 ) %
nbPoints, j++ )
251 newShape->x[j] =
x[i];
252 newShape->y[j] =
y[i];
258 newShape->x[j] = fptx;
259 newShape->y[j] = fpty;
267 return std::unique_ptr< PointSet>(
new PointSet( *
this ) );
276 const bool result = ( GEOSPreparedContainsProperly_r( geosctxt,
preparedGeom(), point.get() ) == 1 );
280 catch ( GEOSException &e )
282 qWarning(
"GEOS exception: %s", e.what() );
307 const double labelArea = labelWidth * labelHeight;
309 QLinkedList<PointSet *> inputShapes;
310 inputShapes.push_back( inputShape );
311 QLinkedList<PointSet *> outputShapes;
313 while ( !inputShapes.isEmpty() )
315 PointSet *shape = inputShapes.takeFirst();
317 const std::vector< double > &
x = shape->
x;
318 const std::vector< double > &
y = shape->
y;
320 std::vector< int > pts( nbp );
321 for (
int i = 0; i < nbp; i++ )
333 for ( std::size_t ihs = 0; ihs < shape->
convexHull.size(); ihs++ )
336 const std::size_t ihn = ( ihs + 1 ) % shape->
convexHull.size();
339 const int ipn = ( ips + 1 ) % nbp;
345 for (
int i = ips; i != shape->
convexHull[ihn]; i = ( i + 1 ) % nbp )
369 const double s = ( base + b +
c ) / 2;
370 double area = s * ( s - base ) * ( s - b ) * ( s -
c );
392 bestArea = std::sqrt( bestArea );
393 double cx, cy, dx, dy, ex, ey, fx, fy, seg_length, ptx = 0, pty = 0, fptx = 0, fpty = 0;
394 int ps = -1, pe = -1, fps = -1, fpe = -1;
395 if ( retainedPt >= 0 && bestArea > labelArea )
397 double c = std::numeric_limits<double>::max();
402 for (
int i = ( shape->
convexHull[holeE] + 1 ) % nbp; i != ( shape->
convexHull[holeS] - 1 + nbp ) % nbp; i = j )
410 cx = (
x[i] +
x[j] ) / 2.0;
411 cy = (
y[i] +
y[j] ) / 2.0;
449 double pointX, pointY;
472 if ( isValid && b <
c )
483 const int imin = retainedPt;
484 int imax = ( ( ( fps < retainedPt && fpe < retainedPt ) || ( fps > retainedPt && fpe > retainedPt ) ) ? std::min( fps, fpe ) : std::max( fps, fpe ) );
486 int nbPtSh1, nbPtSh2;
488 nbPtSh1 = imax - imin + 1 + ( fpe != fps );
490 nbPtSh1 = imax + nbp - imin + 1 + ( fpe != fps );
492 if ( ( imax == fps ? fpe : fps ) < imin )
493 nbPtSh2 = imin - ( imax == fps ? fpe : fps ) + 1 + ( fpe != fps );
495 nbPtSh2 = imin + nbp - ( imax == fps ? fpe : fps ) + 1 + ( fpe != fps );
497 if ( retainedPt == -1 || fps == -1 || fpe == -1 )
503 else if ( imax == imin || nbPtSh1 <= 2 || nbPtSh2 <= 2 || nbPtSh1 == nbp || nbPtSh2 == nbp )
505 outputShapes.append( shape );
510 PointSet *newShape = shape->
extractShape( nbPtSh1, imin, imax, fps, fpe, fptx, fpty ).release();
517 inputShapes.append( newShape );
524 newShape = shape->
extractShape( nbPtSh2, imax, imin, fps, fpe, fptx, fpty ).release();
531 inputShapes.append( newShape );
539 outputShapes.append( shape );
557 newGeos.reset( GEOSOffsetCurve_r( geosctxt,
mGeos, distance, 0, GEOSBUF_JOIN_MITRE, 2 ) );
562 if ( GEOSGeomTypeId_r( geosctxt, newGeos.get() ) == GEOS_MULTILINESTRING )
565 const int nParts = GEOSGetNumGeometries_r( geosctxt, newGeos.get() );
566 double maximumLength = -1;
568 for (
int i = 0; i < nParts; ++i )
570 const GEOSGeometry *part = GEOSGetGeometryN_r( geosctxt, newGeos.get(), i );
571 double partLength = -1;
572 if ( GEOSLength_r( geosctxt, part, &partLength ) == 1 )
574 if ( partLength > maximumLength )
576 maximumLength = partLength;
588 geos::unique_ptr longestPartClone( GEOSGeom_clone_r( geosctxt, longestPart ) );
589 newGeos = std::move( longestPartClone );
592#if GEOS_VERSION_MAJOR==3 && GEOS_VERSION_MINOR<11
600 newGeos = std::move( reversed );
604 const int newNbPoints = GEOSGeomGetNumPoints_r( geosctxt, newGeos.get() );
605 const GEOSCoordSequence *coordSeq = GEOSGeom_getCoordSeq_r( geosctxt, newGeos.get() );
606 std::vector< double > newX;
607 std::vector< double > newY;
608 newX.resize( newNbPoints );
609 newY.resize( newNbPoints );
610 for (
int i = 0; i < newNbPoints; i++ )
612 GEOSCoordSeq_getX_r( geosctxt, coordSeq, i, &newX[i] );
613 GEOSCoordSeq_getY_r( geosctxt, coordSeq, i, &newY[i] );
619 catch ( GEOSException &e )
621 qWarning(
"GEOS exception: %s", e.what() );
627 mGeos = newGeos.release();
638 if ( startDistance > 0 )
644 double distanceConsumed = 0;
647 for (
int i = 1; i <
nbPoints; ++i )
649 const double thisX =
x[i];
650 const double thisY =
y[i];
651 const double thisSegmentLength = std::sqrt( ( thisX - lastX ) * ( thisX - lastX ) + ( thisY - lastY ) * ( thisY - lastY ) );
652 distanceConsumed += thisSegmentLength;
653 if ( distanceConsumed >= smoothDistance )
655 const double c = ( distanceConsumed - smoothDistance ) / thisSegmentLength;
656 x1 = lastX +
c * ( thisX - lastX );
657 y1 = lastY +
c * ( thisY - lastY );
664 const double distance = std::sqrt( ( x1 - x0 ) * ( x1 - x0 ) + ( y1 - y0 ) * ( y1 - y0 ) );
665 const double extensionFactor = ( startDistance + distance ) / distance;
672 if ( endDistance > 0 )
680 double distanceConsumed = 0;
683 for (
int i =
nbPoints - 2; i >= 0; --i )
685 const double thisX =
x[i];
686 const double thisY =
y[i];
687 const double thisSegmentLength = std::sqrt( ( thisX - lastX ) * ( thisX - lastX ) + ( thisY - lastY ) * ( thisY - lastY ) );
688 distanceConsumed += thisSegmentLength;
689 if ( distanceConsumed >= smoothDistance )
691 const double c = ( distanceConsumed - smoothDistance ) / thisSegmentLength;
692 xend1 = lastX +
c * ( thisX - lastX );
693 yend1 = lastY +
c * ( thisY - lastY );
700 const double distance = std::sqrt( ( xend1 - xend0 ) * ( xend1 - xend0 ) + ( yend1 - yend0 ) * ( yend1 - yend0 ) );
701 const double extensionFactor = ( endDistance + distance ) / distance;
703 x.emplace_back( newEnd.
x() );
704 y.emplace_back( newEnd.
y() );
708 if ( startDistance > 0 )
710 x.insert(
x.begin(), x0 );
711 y.insert(
y.begin(), y0 );
732 double best_area = std::numeric_limits<double>::max();
733 double best_alpha = -1;
735 double best_length = 0;
736 double best_width = 0;
739 bbox[0] = std::numeric_limits<double>::max();
740 bbox[1] = std::numeric_limits<double>::max();
741 bbox[2] = std::numeric_limits<double>::lowest();
742 bbox[3] = std::numeric_limits<double>::lowest();
744 for ( std::size_t i = 0; i <
convexHull.size(); i++ )
761 const double dref = bbox[2] - bbox[0];
768 for ( alpha_d = 0; alpha_d < 90; alpha_d++ )
770 alpha = alpha_d * M_PI / 180.0;
771 d1 = std::cos( alpha ) * dref;
772 d2 = std::sin( alpha ) * dref;
793 bb[14] = bb[12] + d2;
794 bb[15] = bb[13] - d1;
797 for (
int i = 0; i < 16; i += 4 )
800 alpha_seg = ( ( i / 4 > 0 ? ( i / 4 ) - 1 : 3 ) ) * M_PI_2 + alpha;
802 double best_cp = std::numeric_limits<double>::max();
804 for ( std::size_t j = 0; j <
convexHull.size(); j++ )
813 const double distNearestPoint = best_cp / dref;
815 d1 = std::cos( alpha_seg ) * distNearestPoint;
816 d2 = std::sin( alpha_seg ) * distNearestPoint;
840 memcpy( best_bb, bb,
sizeof(
double ) * 16 );
845 for (
int i = 0; i < 16; i = i + 4 )
848 best_bb[( i + 4 ) % 16], best_bb[( i + 5 ) % 16], best_bb[( i + 6 ) % 16], best_bb[( i + 7 ) % 16],
849 &finalBb.
x[int ( i / 4 )], &finalBb.
y[int ( i / 4 )] );
852 finalBb.
alpha = best_alpha;
853 finalBb.
width = best_width;
854 finalBb.
length = best_length;
871 geos::unique_ptr geosPt( GEOSGeom_createPointFromXY_r( geosctxt, px, py ) );
872 const int type = GEOSGeomTypeId_r( geosctxt,
mGeos );
874 const GEOSPreparedGeometry *preparedExtRing =
nullptr;
876 if (
type != GEOS_POLYGON )
884 extRing = GEOSGetExteriorRing_r( geosctxt,
mGeos );
885 if ( ! mGeosPreparedBoundary )
887 mGeosPreparedBoundary = GEOSPrepare_r( geosctxt, extRing );
889 preparedExtRing = mGeosPreparedBoundary;
895 unsigned int nPoints = 0;
896 GEOSCoordSeq_getSize_r( geosctxt, nearestCoord.get(), &nPoints );
900 ( void )GEOSCoordSeq_getXY_r( geosctxt, nearestCoord.get(), 0, &nx, &ny );
909 catch ( GEOSException &e )
911 qWarning(
"GEOS exception: %s", e.what() );
931 const GEOSCoordSequence *coordSeq = GEOSGeom_getCoordSeq_r( geosctxt, centroidGeom.get() );
932 unsigned int nPoints = 0;
933 GEOSCoordSeq_getSize_r( geosctxt, coordSeq, &nPoints );
936 GEOSCoordSeq_getXY_r( geosctxt, coordSeq, 0, &px, &py );
946 const GEOSCoordSequence *coordSeq = GEOSGeom_getCoordSeq_r( geosctxt, pointGeom.get() );
947 unsigned int nPoints = 0;
948 GEOSCoordSeq_getSize_r( geosctxt, coordSeq, &nPoints );
952 GEOSCoordSeq_getXY_r( geosctxt, coordSeq, 0, &px, &py );
956 catch ( GEOSException &e )
958 qWarning(
"GEOS exception: %s", e.what() );
984 while ( i <
nbPoints && ad[i] <= dl ) i++;
994 di = std::sqrt( dx * dx + dy * dy );
998 dx =
x[i + 1] -
x[i];
999 dy =
y[i + 1] -
y[i];
1004 *px =
x[i] + dx * distr / di;
1005 *py =
y[i] + dy * distr / di;
1025 catch ( GEOSException &e )
1027 qWarning(
"GEOS exception: %s", e.what() );
1038 double distance = -1;
1043 catch ( GEOSException &e )
1045 qWarning(
"GEOS exception: %s", e.what() );
1078 catch ( GEOSException &e )
1080 qWarning(
"GEOS exception: %s", e.what() );
1101 ( void )GEOSArea_r( geosctxt,
mGeos, &
mArea );
1105 catch ( GEOSException &e )
1107 qWarning(
"GEOS exception: %s", e.what() );
1127 GEOSWKTWriter *writer = GEOSWKTWriter_create_r( geosctxt );
1129 char *wkt = GEOSWKTWriter_write_r( geosctxt, writer,
mGeos );
1130 const QString res( wkt );
1132 GEOSFree_r( geosctxt, wkt );
1134 GEOSWKTWriter_destroy_r( geosctxt, writer );
1139 catch ( GEOSException &e )
1141 qWarning(
"GEOS exception: %s", e.what() );
1149 std::vector< double > distances(
nbPoints );
1150 double totalDistance = 0;
1151 double oldX = -1.0, oldY = -1.0;
1152 for (
int i = 0; i <
nbPoints; i++ )
1157 distances[i] = std::sqrt( std::pow( oldX -
x[i], 2 ) + std::pow( oldY -
y[i], 2 ) );
1161 totalDistance += distances[i];
1163 return std::make_tuple( std::move( distances ), totalDistance );
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 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
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
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