97 memcpy(
y, ps.
y,
sizeof(
double )* nbPoints );
129 bool needClose =
false;
135 GEOSCoordSequence *coord = GEOSCoordSeq_create_r( geosctxt,
nbPoints + ( needClose ? 1 : 0 ), 2 );
136 for (
int i = 0; i <
nbPoints; ++i )
138 GEOSCoordSeq_setX_r( geosctxt, coord, i,
x[i] );
139 GEOSCoordSeq_setY_r( geosctxt, coord, i,
y[i] );
145 GEOSCoordSeq_setX_r( geosctxt, coord, nbPoints,
x[0] );
146 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 mPreparedGeom =
nullptr;
196 GEOSGeom_destroy_r( geosctxt,
mGeos );
199 GEOSPreparedGeom_destroy_r( geosctxt, mPreparedGeom );
220 newShape->
type = GEOS_POLYGON;
222 newShape->
x =
new double[newShape->
nbPoints];
223 newShape->
y =
new double[newShape->
nbPoints];
226 for ( j = 0, i = imin; i != ( imax + 1 ) %
nbPoints; i = ( i + 1 ) %
nbPoints, j++ )
228 newShape->
x[j] =
x[i];
229 newShape->
y[j] =
y[i];
235 newShape->
x[j] = fptx;
236 newShape->
y[j] = fpty;
247 GEOSCoordSequence *seq = GEOSCoordSeq_create_r( geosctxt, 1, 2 );
248 GEOSCoordSeq_setX_r( geosctxt, seq, 0, x );
249 GEOSCoordSeq_setY_r( geosctxt, seq, 0, y );
251 bool result = ( GEOSPreparedContainsProperly_r( geosctxt,
preparedGeom(), point.get() ) == 1 );
255 catch ( GEOSException &e )
269 QLinkedList<PointSet *> &shapes_final,
270 double xrm,
double yrm )
280 int *
cHull =
nullptr;
305 double labelArea = xrm * yrm;
309 while ( !shapes_toProcess.isEmpty() )
311 shape = shapes_toProcess.takeFirst();
318 for ( i = 0; i < nbp; i++ )
326 cHull = shape->
cHull;
336 ihn = ( ihs + 1 ) % cHullSize;
339 ipn = ( ips + 1 ) % nbp;
340 if ( ipn != cHull[ihn] )
345 for ( i = ips; i != cHull[ihn]; i = ( i + 1 ) % nbp )
348 x[cHull[ihn]], y[cHull[ihn]],
361 x[cHull[ihn]], y[cHull[ihn]] );
369 s = ( base + b +
c ) / 2;
370 area = s * ( s - base ) * ( s - b ) * ( s -
c );
375 if ( area - bestArea >
EPSILON )
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 c = std::numeric_limits<double>::max();
402 for ( i = ( cHull[holeE] + 1 ) % nbp; i != ( cHull[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;
461 for ( k = cHull[holeS]; k != cHull[holeE]; k = ( k + 1 ) % nbp )
472 if ( isValid && b < c )
483 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 shapes_final.append( shape );
517 shapes_toProcess.append( newShape );
524 newShape = shape->
extractShape( nbPtSh2, imax, imin, fps, fpe, fptx, fpty );
531 shapes_toProcess.append( newShape );
539 shapes_final.append( shape );
564 double distNearestPoint;
570 double best_area = std::numeric_limits<double>::max();
571 double best_alpha = -1;
573 double best_length = 0;
574 double best_width = 0;
577 bbox[0] = std::numeric_limits<double>::max();
578 bbox[1] = std::numeric_limits<double>::max();
579 bbox[2] = std::numeric_limits<double>::lowest();
580 bbox[3] = std::numeric_limits<double>::lowest();
584 if (
x[
cHull[i]] < bbox[0] )
587 if (
x[cHull[i]] > bbox[2] )
588 bbox[2] =
x[cHull[i]];
590 if (
y[cHull[i]] < bbox[1] )
591 bbox[1] =
y[cHull[i]];
593 if (
y[cHull[i]] > bbox[3] )
594 bbox[3] =
y[cHull[i]];
598 dref = bbox[2] - bbox[0];
600 for ( alpha_d = 0; alpha_d < 90; alpha_d++ )
602 alpha = alpha_d * M_PI / 180.0;
603 d1 = std::cos( alpha ) * dref;
604 d2 = std::sin( alpha ) * dref;
625 bb[14] = bb[12] + d2;
626 bb[15] = bb[13] - d1;
629 for ( i = 0; i < 16; i += 4 )
632 alpha_seg = ( ( i / 4 > 0 ? ( i / 4 ) - 1 : 3 ) ) * M_PI_2 + alpha;
634 best_cp = std::numeric_limits<double>::max();
644 distNearestPoint = best_cp / dref;
646 d1 = std::cos( alpha_seg ) * distNearestPoint;
647 d2 = std::sin( alpha_seg ) * distNearestPoint;
665 if ( best_area - area >
EPSILON )
671 memcpy( best_bb, bb,
sizeof(
double ) * 16 );
679 for ( i = 0; i < 16; i = i + 4 )
682 best_bb[( i + 4 ) % 16], best_bb[( i + 5 ) % 16], best_bb[( i + 6 ) % 16], best_bb[( i + 7 ) % 16],
683 &finalBb->
x[int ( i / 4 )], &finalBb->
y[int ( i / 4 )] );
686 finalBb->
alpha = best_alpha;
687 finalBb->
width = best_width;
688 finalBb->
length = best_length;
704 GEOSCoordSequence *coord = GEOSCoordSeq_create_r( geosctxt, 1, 2 );
705 GEOSCoordSeq_setX_r( geosctxt, coord, 0, px );
706 GEOSCoordSeq_setY_r( geosctxt, coord, 0, py );
709 int type = GEOSGeomTypeId_r( geosctxt,
mGeos );
710 const GEOSGeometry *extRing =
nullptr;
711 if ( type != GEOS_POLYGON )
718 extRing = GEOSGetExteriorRing_r( geosctxt,
mGeos );
723 ( void )GEOSCoordSeq_getX_r( geosctxt, nearestCoord.get(), 0, &nx );
724 ( void )GEOSCoordSeq_getY_r( geosctxt, nearestCoord.get(), 0, &ny );
733 catch ( GEOSException &e )
754 const GEOSCoordSequence *coordSeq = GEOSGeom_getCoordSeq_r( geosctxt, centroidGeom.get() );
755 GEOSCoordSeq_getX_r( geosctxt, coordSeq, 0, &px );
756 GEOSCoordSeq_getY_r( geosctxt, coordSeq, 0, &py );
766 const GEOSCoordSequence *coordSeq = GEOSGeom_getCoordSeq_r( geosctxt, pointGeom.get() );
767 GEOSCoordSeq_getX_r( geosctxt, coordSeq, 0, &px );
768 GEOSCoordSeq_getY_r( geosctxt, coordSeq, 0, &py );
772 catch ( GEOSException &e )
788 while ( i <
nbPoints && ad[i] <= dl ) i++;
798 di = std::sqrt( dx * dx + dy * dy );
802 dx =
x[i + 1] -
x[i];
803 dy =
y[i + 1] -
y[i];
808 *px =
x[i] + dx * distr / di;
809 *py =
y[i] + dy * distr / di;
839 ( void )GEOSLength_r( geosctxt,
mGeos, &len );
842 catch ( GEOSException &e )
bool containsPoint(double x, double y) const
Tests whether point set contains a specified point.
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.
PointSet * extractShape(int nbPtSh, int imin, int imax, int fps, int fpe, double fptx, double fpty)
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
void createGeosGeom() const
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.
bool isClosed() const
Returns true if pointset is closed.
struct pal::_cHullBox CHullBox
static GEOSContextHandle_t getGEOSHandler()
static double cross_product(double x1, double y1, double x2, double y2, double x3, double y3)
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
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.
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< GEOSGeometry, GeosDeleter > unique_ptr
Scoped GEOS pointer.
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).
static double dist_euc2d(double x1, double y1, double x2, double y2)
CHullBox * compute_chull_bbox()
double length() const
Returns length of line geometry.
const GEOSPreparedGeometry * preparedGeom() const
std::unique_ptr< GEOSCoordSequence, GeosDeleter > coord_sequence_unique_ptr
Scoped GEOS coordinate sequence pointer.
static double dist_euc2d_sq(double x1, double y1, double x2, double y2)
void getCentroid(double &px, double &py, bool forceInside=false) const
static void splitPolygons(QLinkedList< PointSet *> &shapes_toProcess, QLinkedList< PointSet *> &shapes_final, double xrm, double yrm)
Split a concave shape into several convex shapes.
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...
static int convexHullId(int *id, const double *x, const double *y, int n, int *&cHull)
Compute the convex hull in O(n·log(n))
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.