43void heapsort( std::vector< int > &sid,
int *
id,
const std::vector< double > &x, std::size_t N )
46 std::size_t i = n / 2;
69 if ( child + 1 < n && x[
id[sid[child + 1]]] > x[
id[sid[child]]] )
73 if ( x[
id[sid[child]]] > x[
id[tx]] )
75 sid[parent] = sid[child];
77 child = parent * 2 + 1;
89void heapsort2(
int *x,
double *heap, std::size_t N )
92 std::size_t i = n / 2;
119 if ( child + 1 < n && heap[child + 1] > heap[child] )
123 if ( heap[child] > t )
125 heap[parent] = heap[child];
126 x[parent] = x[child];
128 child = parent * 2 + 1;
151 return (
cross_product( x1, y1, x2, y2, x3, y3 ) *
cross_product( x1, y1, x2, y2, x4, y4 ) < 0 &&
cross_product( x3, y3, x4, y4, x1, y1 ) *
cross_product( x3, y3, x4, y4, x2, y2 ) < 0 );
167 double a1, a2, b1, b2, c1, c2;
172 c1 = x2 * y1 - x1 * y2;
176 c2 = x4 * y3 - x3 * y4;
178 denom = a1 * b2 - a2 * b1;
185 *x = ( b1 * c2 - b2 * c1 ) / denom;
186 *y = ( a2 * c1 - a1 * c2 ) / denom;
194 std::vector< int > convexHull( x.size() );
195 for ( std::size_t i = 0; i < x.size(); i++ )
197 convexHull[i] =
static_cast< int >( i );
203 std::vector< int > stack( x.size() );
204 std::vector< double > tan( x.size() );
207 heapsort( convexHull,
id.data(), y, y.size() );
211 while ( ref < x.size() &&
qgsDoubleNear( y[
id[convexHull[ref]]], y[
id[convexHull[0]]] ) )
214 heapsort( convexHull,
id.data(), x, ref );
217 for ( std::size_t i = ref; i < x.size(); i++ )
219 if (
qgsDoubleNear( y[
id[convexHull[i]]], y[
id[convexHull[0]]] ) )
222 tan[i] = ( x[
id[convexHull[0]]] - x[
id[convexHull[i]]] ) / ( y[
id[convexHull[i]]] - y[
id[convexHull[0]]] );
225 if ( ref < x.size() )
226 heapsort2( convexHull.data() + ref, tan.data() + ref, x.size() - ref );
229 stack[0] = convexHull[0];
232 stack[1] = convexHull[1];
236 stack[1] = convexHull[ref - 1];
239 std::size_t second = 0;
241 for ( std::size_t i = ref; i < x.size(); i++ )
243 double result =
cross_product( x[
id[stack[second]]], y[
id[stack[second]]], x[
id[stack[top]]], y[
id[stack[top]]], x[
id[convexHull[i]]], y[
id[convexHull[i]]] );
250 stack[top] = convexHull[i];
253 else if ( result > 0 )
257 stack[top] = convexHull[i];
261 while ( result < 0 && top > 1 )
265 result =
cross_product( x[
id[stack[second]]], y[
id[stack[second]]], x[
id[stack[top]]], y[
id[stack[top]]], x[
id[convexHull[i]]], y[
id[convexHull[i]]] );
269 stack[top] = convexHull[i];
273 for ( std::size_t i = 0; i <= top; i++ )
275 convexHull[i] = stack[i];
278 convexHull.resize( top + 1 );
284 std::vector< int > pts( x.size() );
285 for ( std::size_t i = 0; i < x.size(); i++ )
286 pts[i] =
static_cast< int >( i );
288 std::vector< int > convexHull =
convexHullId( pts, x, y );
291 if ( pts[convexHull[0]] < pts[convexHull[1]] && pts[convexHull[1]] < pts[convexHull[2]] )
293 else if ( pts[convexHull[0]] > pts[convexHull[1]] && pts[convexHull[1]] > pts[convexHull[2]] )
295 else if ( pts[convexHull[0]] > pts[convexHull[1]] && pts[convexHull[1]] < pts[convexHull[2]] && pts[convexHull[2]] < pts[convexHull[0]] )
297 else if ( pts[convexHull[0]] > pts[convexHull[1]] && pts[convexHull[1]] < pts[convexHull[2]] && pts[convexHull[2]] > pts[convexHull[0]] )
299 else if ( pts[convexHull[0]] < pts[convexHull[1]] && pts[convexHull[1]] > pts[convexHull[2]] && pts[convexHull[2]] > pts[convexHull[0]] )
301 else if ( pts[convexHull[0]] < pts[convexHull[1]] && pts[convexHull[1]] > pts[convexHull[2]] && pts[convexHull[2]] < pts[convexHull[0]] )
311 for ( std::size_t i = 0, j = x.size() - 1; i <= j; i++, j-- )
313 std::swap( x[i], x[j] );
314 std::swap( y[i], y[j] );
328 GEOSCoordSequence *coord = GEOSCoordSeq_create_r( geosctxt, 5, 2 );
330 GEOSCoordSeq_setXY_r( geosctxt, coord, 0, x, y );
333 const double beta = alpha + M_PI_2;
334 const double dx1 = std::cos( alpha ) * width;
335 const double dy1 = std::sin( alpha ) * width;
336 const double dx2 = std::cos( beta ) * height;
337 const double dy2 = std::sin( beta ) * height;
338 GEOSCoordSeq_setXY_r( geosctxt, coord, 1, x + dx1, y + dy1 );
339 GEOSCoordSeq_setXY_r( geosctxt, coord, 2, x + dx1 + dx2, y + dy1 + dy2 );
340 GEOSCoordSeq_setXY_r( geosctxt, coord, 3, x + dx2, y + dy2 );
344 GEOSCoordSeq_setXY_r( geosctxt, coord, 1, x + width, y );
345 GEOSCoordSeq_setXY_r( geosctxt, coord, 2, x + width, y + height );
346 GEOSCoordSeq_setXY_r( geosctxt, coord, 3, x, y + height );
349 GEOSCoordSeq_setXY_r( geosctxt, coord, 4, x, y );
351 geos::unique_ptr bboxGeos( GEOSGeom_createLinearRing_r( geosctxt, coord ) );
352 const bool result = ( GEOSPreparedContainsProperly_r( geosctxt, geom, bboxGeos.get() ) == 1 );
355 catch ( QgsGeosException &e )
357 qWarning(
"GEOS exception: %s", e.what() );
368 double multiplier = 1;
380 radius *= multiplier;
383 const double dx = x2 - x1;
384 const double dy = y2 - y1;
386 const double A = dx * dx + dy * dy;
387 const double B = 2 * ( dx * ( x1 - cx ) + dy * ( y1 - cy ) );
388 const double C = ( x1 - cx ) * ( x1 - cx ) + ( y1 - cy ) * ( y1 - cy ) - radius * radius;
390 const double det = B * B - 4 * A * C;
391 if ( A <= 0.000000000001 || det < 0 )
398 const double t = -B / ( 2 * A );
407 const double t = ( -B + std::sqrt( det ) ) / ( 2 * A );
412 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(), Qgis::StringFormat format=Qgis::StringFormat::PlainText)
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