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;
 
 1065   catch ( GEOSException &e )
 
 1067     qWarning( 
"GEOS exception: %s", e.what() );
 
 1088     ( void )GEOSArea_r( geosctxt, 
mGeos, &
mArea );
 
 1092   catch ( GEOSException &e )
 
 1094     qWarning( 
"GEOS exception: %s", e.what() );
 
 1114     GEOSWKTWriter *writer = GEOSWKTWriter_create_r( geosctxt );
 
 1116     char *wkt = GEOSWKTWriter_write_r( geosctxt, writer, 
mGeos );
 
 1117     const QString res( wkt );
 
 1119     GEOSFree_r( geosctxt, wkt );
 
 1121     GEOSWKTWriter_destroy_r( geosctxt, writer );
 
 1126   catch ( GEOSException &e )
 
 1128     qWarning( 
"GEOS exception: %s", e.what() );
 
 1136   std::vector< double > distances( 
nbPoints );
 
 1137   double totalDistance = 0;
 
 1138   double oldX = -1.0, oldY = -1.0;
 
 1139   for ( 
int i = 0; i < 
nbPoints; i++ )
 
 1144       distances[i] = std::sqrt( std::pow( oldX - 
x[i], 2 ) + std::pow( oldY - 
y[i], 2 ) );
 
 1148     totalDistance += distances[i];
 
 1150   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.