49 : nbPoints( nbPoints )
50 , type( GEOS_POLYGON )
121 bool needClose =
false;
127 GEOSCoordSequence *coord = GEOSCoordSeq_create_r( geosctxt,
nbPoints + ( needClose ? 1 : 0 ), 2 );
128 for (
int i = 0; i <
nbPoints; ++i )
130 #if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=8
131 GEOSCoordSeq_setXY_r( geosctxt, coord, i,
x[i],
y[i] );
133 GEOSCoordSeq_setX_r( geosctxt, coord, i,
x[i] );
134 GEOSCoordSeq_setY_r( geosctxt, coord, i,
y[i] );
141 #if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=8
142 GEOSCoordSeq_setXY_r( geosctxt, coord,
nbPoints,
x[0],
y[0] );
144 GEOSCoordSeq_setX_r( geosctxt, coord,
nbPoints,
x[0] );
145 GEOSCoordSeq_setY_r( geosctxt, coord,
nbPoints,
y[0] );
152 mGeos = GEOSGeom_createPolygon_r( geosctxt, GEOSGeom_createLinearRing_r( geosctxt, coord ),
nullptr, 0 );
155 case GEOS_LINESTRING:
156 mGeos = GEOSGeom_createLineString_r( geosctxt, coord );
160 mGeos = GEOSGeom_createPoint_r( geosctxt, coord );
172 if ( !mPreparedGeom )
176 return mPreparedGeom;
183 GEOSGeom_destroy_r( geosctxt,
mGeos );
184 GEOSPreparedGeom_destroy_r( geosctxt, mPreparedGeom );
187 if ( mGeosPreparedBoundary )
189 GEOSPreparedGeom_destroy_r( geosctxt, mGeosPreparedBoundary );
190 mGeosPreparedBoundary =
nullptr;
192 mPreparedGeom =
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;
225 std::unique_ptr<PointSet>
PointSet::extractShape(
int nbPtSh,
int imin,
int imax,
int fps,
int fpe,
double fptx,
double fpty )
229 std::unique_ptr<PointSet> newShape = qgis::make_unique< PointSet >();
230 newShape->type = GEOS_POLYGON;
231 newShape->nbPoints = nbPtSh;
232 newShape->x.resize( newShape->nbPoints );
233 newShape->y.resize( newShape->nbPoints );
236 for ( j = 0, i = imin; i != ( imax + 1 ) %
nbPoints; i = ( i + 1 ) %
nbPoints, j++ )
238 newShape->x[j] =
x[i];
239 newShape->y[j] =
y[i];
245 newShape->x[j] = fptx;
246 newShape->y[j] = fpty;
254 return std::unique_ptr< PointSet>(
new PointSet( *
this ) );
262 #if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=8
265 GEOSCoordSequence *seq = GEOSCoordSeq_create_r( geosctxt, 1, 2 );
266 GEOSCoordSeq_setX_r( geosctxt, seq, 0,
x );
267 GEOSCoordSeq_setY_r( geosctxt, seq, 0,
y );
270 bool result = ( GEOSPreparedContainsProperly_r( geosctxt,
preparedGeom(), point.get() ) == 1 );
274 catch ( GEOSException &e )
276 qWarning(
"GEOS exception: %s", e.what() );
289 QLinkedList<PointSet *> &outputShapes,
290 double xrm,
double yrm )
295 std::vector< double >
x;
296 std::vector< double >
y;
300 int *
cHull =
nullptr;
325 double labelArea = xrm * yrm;
329 while ( !inputShapes.isEmpty() )
331 shape = inputShapes.takeFirst();
338 for ( i = 0; i < nbp; i++ )
359 ipn = ( ips + 1 ) % nbp;
360 if ( ipn !=
cHull[ihn] )
365 for ( i = ips; i !=
cHull[ihn]; i = ( i + 1 ) % nbp )
389 s = ( base + b +
c ) / 2;
390 area = s * ( s - base ) * ( s - b ) * ( s -
c );
412 bestArea = std::sqrt( bestArea );
413 double cx, cy, dx, dy, ex, ey, fx, fy, seg_length, ptx = 0, pty = 0, fptx = 0, fpty = 0;
414 int ps = -1, pe = -1, fps = -1, fpe = -1;
415 if ( retainedPt >= 0 && bestArea > labelArea )
417 c = std::numeric_limits<double>::max();
422 for ( i = (
cHull[holeE] + 1 ) % nbp; i != (
cHull[holeS] - 1 + nbp ) % nbp; i = j )
430 cx = (
x[i] +
x[j] ) / 2.0;
431 cy = (
y[i] +
y[j] ) / 2.0;
469 double pointX, pointY;
481 for ( k =
cHull[holeS]; k !=
cHull[holeE]; k = ( k + 1 ) % nbp )
492 if ( isValid && b <
c )
503 int imin = retainedPt;
504 int imax = ( ( ( fps < retainedPt && fpe < retainedPt ) || ( fps > retainedPt && fpe > retainedPt ) ) ? std::min( fps, fpe ) : std::max( fps, fpe ) );
506 int nbPtSh1, nbPtSh2;
508 nbPtSh1 = imax - imin + 1 + ( fpe != fps );
510 nbPtSh1 = imax + nbp - imin + 1 + ( fpe != fps );
512 if ( ( imax == fps ? fpe : fps ) < imin )
513 nbPtSh2 = imin - ( imax == fps ? fpe : fps ) + 1 + ( fpe != fps );
515 nbPtSh2 = imin + nbp - ( imax == fps ? fpe : fps ) + 1 + ( fpe != fps );
517 if ( retainedPt == -1 || fps == -1 || fpe == -1 )
523 else if ( imax == imin || nbPtSh1 <= 2 || nbPtSh2 <= 2 || nbPtSh1 == nbp || nbPtSh2 == nbp )
525 outputShapes.append( shape );
530 PointSet *newShape = shape->
extractShape( nbPtSh1, imin, imax, fps, fpe, fptx, fpty ).release();
537 inputShapes.append( newShape );
544 newShape = shape->
extractShape( nbPtSh2, imax, imin, fps, fpe, fptx, fpty ).release();
551 inputShapes.append( newShape );
559 outputShapes.append( shape );
572 if ( startDistance > 0 )
578 double distanceConsumed = 0;
581 for (
int i = 1; i <
nbPoints; ++i )
585 const double thisSegmentLength = std::sqrt( ( thisX - lastX ) * ( thisX - lastX ) + ( thisY - lastY ) * ( thisY - lastY ) );
586 distanceConsumed += thisSegmentLength;
587 if ( distanceConsumed >= smoothDistance )
589 double c = ( distanceConsumed - smoothDistance ) / thisSegmentLength;
590 x1 = lastX +
c * ( thisX - lastX );
591 y1 = lastY +
c * ( thisY - lastY );
598 const double distance = std::sqrt( ( x1 - x0 ) * ( x1 - x0 ) + ( y1 - y0 ) * ( y1 - y0 ) );
599 const double extensionFactor = ( startDistance + distance ) / distance;
606 if ( endDistance > 0 )
614 double distanceConsumed = 0;
617 for (
int i =
nbPoints - 2; i >= 0; --i )
621 const double thisSegmentLength = std::sqrt( ( thisX - lastX ) * ( thisX - lastX ) + ( thisY - lastY ) * ( thisY - lastY ) );
622 distanceConsumed += thisSegmentLength;
623 if ( distanceConsumed >= smoothDistance )
625 double c = ( distanceConsumed - smoothDistance ) / thisSegmentLength;
626 xend1 = lastX +
c * ( thisX - lastX );
627 yend1 = lastY +
c * ( thisY - lastY );
634 const double distance = std::sqrt( ( xend1 - xend0 ) * ( xend1 - xend0 ) + ( yend1 - yend0 ) * ( yend1 - yend0 ) );
635 const double extensionFactor = ( endDistance + distance ) / distance;
637 x.emplace_back( newEnd.
x() );
638 y.emplace_back( newEnd.
y() );
642 if ( startDistance > 0 )
644 x.insert(
x.begin(), x0 );
645 y.insert(
y.begin(), y0 );
666 double best_area = std::numeric_limits<double>::max();
667 double best_alpha = -1;
669 double best_length = 0;
670 double best_width = 0;
673 bbox[0] = std::numeric_limits<double>::max();
674 bbox[1] = std::numeric_limits<double>::max();
675 bbox[2] = std::numeric_limits<double>::lowest();
676 bbox[3] = std::numeric_limits<double>::lowest();
680 if (
x[
cHull[i]] < bbox[0] )
683 if (
x[
cHull[i]] > bbox[2] )
686 if (
y[
cHull[i]] < bbox[1] )
689 if (
y[
cHull[i]] > bbox[3] )
695 const double dref = bbox[2] - bbox[0];
702 for ( alpha_d = 0; alpha_d < 90; alpha_d++ )
704 alpha = alpha_d * M_PI / 180.0;
705 d1 = std::cos( alpha ) * dref;
706 d2 = std::sin( alpha ) * dref;
727 bb[14] = bb[12] + d2;
728 bb[15] = bb[13] - d1;
731 for (
int i = 0; i < 16; i += 4 )
734 alpha_seg = ( ( i / 4 > 0 ? ( i / 4 ) - 1 : 3 ) ) * M_PI_2 + alpha;
736 double best_cp = std::numeric_limits<double>::max();
737 for (
int j = 0; j <
nbPoints; j++ )
746 const double distNearestPoint = best_cp / dref;
748 d1 = std::cos( alpha_seg ) * distNearestPoint;
749 d2 = std::sin( alpha_seg ) * distNearestPoint;
773 memcpy( best_bb, bb,
sizeof(
double ) * 16 );
778 for (
int i = 0; i < 16; i = i + 4 )
781 best_bb[( i + 4 ) % 16], best_bb[( i + 5 ) % 16], best_bb[( i + 6 ) % 16], best_bb[( i + 7 ) % 16],
782 &finalBb.
x[int ( i / 4 )], &finalBb.
y[int ( i / 4 )] );
785 finalBb.
alpha = best_alpha;
786 finalBb.
width = best_width;
787 finalBb.
length = best_length;
804 #if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=8
805 geos::unique_ptr geosPt( GEOSGeom_createPointFromXY_r( geosctxt, px, py ) );
807 GEOSCoordSequence *coord = GEOSCoordSeq_create_r( geosctxt, 1, 2 );
808 GEOSCoordSeq_setX_r( geosctxt, coord, 0, px );
809 GEOSCoordSeq_setY_r( geosctxt, coord, 0, py );
812 int type = GEOSGeomTypeId_r( geosctxt,
mGeos );
813 const GEOSGeometry *extRing =
nullptr;
814 #if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=9
815 const GEOSPreparedGeometry *preparedExtRing =
nullptr;
818 if (
type != GEOS_POLYGON )
821 #if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=9
828 extRing = GEOSGetExteriorRing_r( geosctxt,
mGeos );
829 #if GEOS_VERSION_MAJOR>3 || ( GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR>=9 )
830 if ( ! mGeosPreparedBoundary )
832 mGeosPreparedBoundary = GEOSPrepare_r( geosctxt, extRing );
834 preparedExtRing = mGeosPreparedBoundary;
838 #if GEOS_VERSION_MAJOR>3 || ( GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR>=9 )
845 #if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=8
846 unsigned int nPoints = 0;
847 GEOSCoordSeq_getSize_r( geosctxt, nearestCoord.get(), &nPoints );
851 ( void )GEOSCoordSeq_getXY_r( geosctxt, nearestCoord.get(), 0, &nx, &ny );
853 ( void )GEOSCoordSeq_getX_r( geosctxt, nearestCoord.get(), 0, &nx );
854 ( void )GEOSCoordSeq_getY_r( geosctxt, nearestCoord.get(), 0, &ny );
864 catch ( GEOSException &e )
866 qWarning(
"GEOS exception: %s", e.what() );
886 const GEOSCoordSequence *coordSeq = GEOSGeom_getCoordSeq_r( geosctxt, centroidGeom.get() );
887 #if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=8
888 unsigned int nPoints = 0;
889 GEOSCoordSeq_getSize_r( geosctxt, coordSeq, &nPoints );
892 GEOSCoordSeq_getXY_r( geosctxt, coordSeq, 0, &px, &py );
894 GEOSCoordSeq_getX_r( geosctxt, coordSeq, 0, &px );
895 GEOSCoordSeq_getY_r( geosctxt, coordSeq, 0, &py );
906 const GEOSCoordSequence *coordSeq = GEOSGeom_getCoordSeq_r( geosctxt, pointGeom.get() );
907 #if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=8
908 unsigned int nPoints = 0;
909 GEOSCoordSeq_getSize_r( geosctxt, coordSeq, &nPoints );
913 GEOSCoordSeq_getXY_r( geosctxt, coordSeq, 0, &px, &py );
915 GEOSCoordSeq_getX_r( geosctxt, coordSeq, 0, &px );
916 GEOSCoordSeq_getY_r( geosctxt, coordSeq, 0, &py );
921 catch ( GEOSException &e )
923 qWarning(
"GEOS exception: %s", e.what() );
949 while ( i <
nbPoints && ad[i] <= dl ) i++;
959 di = std::sqrt( dx * dx + dy * dy );
963 dx =
x[i + 1] -
x[i];
964 dy =
y[i + 1] -
y[i];
969 *px =
x[i] + dx * distr / di;
970 *py =
y[i] + dy * distr / di;
1005 catch ( GEOSException &e )
1007 qWarning(
"GEOS exception: %s", e.what() );
1028 ( void )GEOSArea_r( geosctxt,
mGeos, &
mArea );
1032 catch ( GEOSException &e )
1034 qWarning(
"GEOS exception: %s", e.what() );
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::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 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 int convexHullId(int *id, const std::vector< double > &x, const std::vector< double > &y, int n, int *&cHull)
Compute the convex hull in O(n·log(n))
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
const GEOSPreparedGeometry * preparedGeom() const
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.
static void splitPolygons(QLinkedList< PointSet * > &inputShapes, QLinkedList< PointSet * > &outputShapes, double xrm, double yrm)
Split a concave shape into several convex shapes.
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.