43void heapsort( std::vector< int > &sid,
int *
id,
const std::vector< double > &x, std::size_t N )
46 std::size_t i = n / 2;
68 if ( child + 1 < n && x[
id[sid[child + 1]]] > x[
id[sid[child]]] )
72 if ( x[
id[sid[child]]] > x[
id[tx]] )
74 sid[parent] = sid[child];
76 child = parent * 2 + 1;
88void heapsort2(
int *x,
double *heap, std::size_t N )
91 std::size_t i = n / 2;
107 if ( n == 0 )
return;
117 if ( child + 1 < n && heap[child + 1] > heap[child] )
121 if ( heap[child] > t )
123 heap[parent] = heap[child];
124 x[parent] = x[child];
126 child = parent * 2 + 1;
139 double x3,
double y3,
double x4,
double y4 )
141 return (
cross_product( x1, y1, x2, y2, x3, y3 ) *
cross_product( x1, y1, x2, y2, x4, y4 ) < 0
142 &&
cross_product( x3, y3, x4, y4, x1, y1 ) *
cross_product( x3, y3, x4, y4, x2, y2 ) < 0 );
146 double x3,
double y3,
double x4,
double y4,
147 double *x,
double *y )
150 double a1, a2, b1, b2, c1, c2;
155 c1 = x2 * y1 - x1 * y2;
159 c2 = x4 * y3 - x3 * y4;
161 denom = a1 * b2 - a2 * b1;
168 *x = ( b1 * c2 - b2 * c1 ) / denom;
169 *y = ( a2 * c1 - a1 * c2 ) / denom;
177 std::vector< int > convexHull( x.size() );
178 for ( std::size_t i = 0; i < x.size(); i++ )
180 convexHull[i] =
static_cast< int >( i );
186 std::vector< int > stack( x.size() );
187 std::vector< double > tan( x.size() );
190 heapsort( convexHull,
id.data(), y, y.size() );
194 while ( ref < x.size() &&
qgsDoubleNear( y[
id[convexHull[ref]]], y[
id[convexHull[0]]] ) )
197 heapsort( convexHull,
id.data(), x, ref );
200 for ( std::size_t i = ref; i < x.size(); i++ )
202 if (
qgsDoubleNear( y[
id[convexHull[i]]], y[
id[convexHull[0]]] ) )
205 tan[i] = ( x[
id[convexHull[0]]] - x[
id[convexHull[i]]] ) / ( y[
id[convexHull[i]]] - y[
id[convexHull[0]]] );
208 if ( ref < x.size() )
209 heapsort2( convexHull.data() + ref, tan.data() + ref, x.size() - ref );
212 stack[0] = convexHull[0];
215 stack[1] = convexHull[1];
219 stack[1] = convexHull[ref - 1];
222 std::size_t second = 0;
224 for ( std::size_t i = ref; i < x.size(); i++ )
226 double result =
cross_product( x[
id[stack[second]]], y[
id[stack[second]]],
227 x[
id[stack[top]]], y[
id[stack[top]]], x[
id[convexHull[i]]], y[
id[convexHull[i]]] );
234 stack[top] = convexHull[i];
237 else if ( result > 0 )
241 stack[top] = convexHull[i];
245 while ( result < 0 && top > 1 )
250 y[
id[stack[second]]], x[
id[stack[top]]],
251 y[
id[stack[top]]], x[
id[convexHull[i]]], y[
id[convexHull[i]]] );
255 stack[top] = convexHull[i];
259 for ( std::size_t i = 0; i <= top; i++ )
261 convexHull[i] = stack[i];
264 convexHull.resize( top + 1 );
270 std::vector< int > pts( x.size() );
271 for ( std::size_t i = 0; i < x.size(); i++ )
272 pts[i] =
static_cast< int >( i );
274 std::vector< int > convexHull =
convexHullId( pts, x, y );
277 if ( pts[convexHull[0]] < pts[convexHull[1]] && pts[convexHull[1]] < pts[convexHull[2]] )
279 else if ( pts[convexHull[0]] > pts[convexHull[1]] && pts[convexHull[1]] > pts[convexHull[2]] )
281 else if ( pts[convexHull[0]] > pts[convexHull[1]] && pts[convexHull[1]] < pts[convexHull[2]] && pts[convexHull[2]] < pts[convexHull[0]] )
283 else if ( pts[convexHull[0]] > pts[convexHull[1]] && pts[convexHull[1]] < pts[convexHull[2]] && pts[convexHull[2]] > pts[convexHull[0]] )
285 else if ( pts[convexHull[0]] < pts[convexHull[1]] && pts[convexHull[1]] > pts[convexHull[2]] && pts[convexHull[2]] > pts[convexHull[0]] )
287 else if ( pts[convexHull[0]] < pts[convexHull[1]] && pts[convexHull[1]] > pts[convexHull[2]] && pts[convexHull[2]] < pts[convexHull[0]] )
297 for ( std::size_t i = 0, j = x.size() - 1; i <= j; i++, j-- )
299 std::swap( x[i], x[j] );
300 std::swap( y[i], y[j] );
314 GEOSCoordSequence *coord = GEOSCoordSeq_create_r( geosctxt, 5, 2 );
316 GEOSCoordSeq_setXY_r( geosctxt, coord, 0, x, y );
319 const double beta = alpha + M_PI_2;
320 const double dx1 = std::cos( alpha ) * width;
321 const double dy1 = std::sin( alpha ) * width;
322 const double dx2 = std::cos( beta ) * height;
323 const double dy2 = std::sin( beta ) * height;
324 GEOSCoordSeq_setXY_r( geosctxt, coord, 1, x + dx1, y + dy1 );
325 GEOSCoordSeq_setXY_r( geosctxt, coord, 2, x + dx1 + dx2, y + dy1 + dy2 );
326 GEOSCoordSeq_setXY_r( geosctxt, coord, 3, x + dx2, y + dy2 );
330 GEOSCoordSeq_setXY_r( geosctxt, coord, 1, x + width, y );
331 GEOSCoordSeq_setXY_r( geosctxt, coord, 2, x + width, y + height );
332 GEOSCoordSeq_setXY_r( geosctxt, coord, 3, x, y + height );
335 GEOSCoordSeq_setXY_r( geosctxt, coord, 4, x, y );
337 geos::unique_ptr bboxGeos( GEOSGeom_createLinearRing_r( geosctxt, coord ) );
338 const bool result = ( GEOSPreparedContainsProperly_r( geosctxt, geom, bboxGeos.get() ) == 1 );
341 catch ( QgsGeosException &e )
343 qWarning(
"GEOS exception: %s", e.what() );
353 double x1,
double y1,
double x2,
double y2,
354 double &xRes,
double &yRes )
356 double multiplier = 1;
368 radius *= multiplier;
371 const double dx = x2 - x1;
372 const double dy = y2 - y1;
374 const double A = dx * dx + dy * dy;
375 const double B = 2 * ( dx * ( x1 - cx ) + dy * ( y1 - cy ) );
376 const double C = ( x1 - cx ) * ( x1 - cx ) + ( y1 - cy ) * ( y1 - cy ) - radius * radius;
378 const double det = B * B - 4 * A * C;
379 if ( A <= 0.000000000001 || det < 0 )
386 const double t = -B / ( 2 * A );
395 const double t = ( -B + std::sqrt( det ) ) / ( 2 * A );
400 if ( multiplier != 1 )
static double sqrDistance2D(double x1, double y1, double x2, double y2)
Returns the squared 2D distance between (x1, y1) and (x2, y2).
static GEOSContextHandle_t get()
Returns a thread local instance of a GEOS context, safe for use in the current thread.
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true, const char *file=__builtin_FILE(), const char *function=__builtin_FUNCTION(), int line=__builtin_LINE())
Adds a message to the log instance (and creates it if necessary).
static bool reorderPolygon(std::vector< double > &x, std::vector< double > &y)
Reorder points to have cross prod ((x,y)[i], (x,y)[i+1), point) > 0 when point is outside.
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 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.
static void findLineCircleIntersection(double cx, double cy, double radius, double x1, double y1, double x2, double y2, double &xRes, double &yRes)
void heapsort(std::vector< int > &sid, int *id, const std::vector< double > &x, std::size_t N)
void heapsort2(int *x, double *heap, std::size_t N)
std::unique_ptr< GEOSGeometry, GeosDeleter > unique_ptr
Scoped GEOS pointer.
#define Q_NOWARN_UNREACHABLE_PUSH
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference).
#define Q_NOWARN_UNREACHABLE_POP