40 void heapsort( std::vector< int > &sid,
int *
id,
const std::vector< double > &x, std::size_t N )
43 std::size_t i = n / 2;
65 if ( child + 1 < n && x[
id[sid[child + 1]]] > x[
id[sid[child]]] )
69 if ( x[
id[sid[child]]] > x[
id[tx]] )
71 sid[parent] = sid[child];
73 child = parent * 2 + 1;
85 void heapsort2(
int *x,
double *heap, std::size_t N )
88 std::size_t i = n / 2;
104 if ( n == 0 )
return;
114 if ( child + 1 < n && heap[child + 1] > heap[child] )
118 if ( heap[child] > t )
120 heap[parent] = heap[child];
121 x[parent] = x[child];
123 child = parent * 2 + 1;
136 double x3,
double y3,
double x4,
double y4 )
138 return (
cross_product( x1, y1, x2, y2, x3, y3 ) *
cross_product( x1, y1, x2, y2, x4, y4 ) < 0
139 &&
cross_product( x3, y3, x4, y4, x1, y1 ) *
cross_product( x3, y3, x4, y4, x2, y2 ) < 0 );
143 double x3,
double y3,
double x4,
double y4,
144 double *x,
double *y )
147 double a1, a2, b1, b2, c1, c2;
152 c1 = x2 * y1 - x1 * y2;
156 c2 = x4 * y3 - x3 * y4;
158 denom = a1 * b2 - a2 * b1;
165 *x = ( b1 * c2 - b2 * c1 ) / denom;
166 *y = ( a2 * c1 - a1 * c2 ) / denom;
174 std::vector< int > convexHull( x.size() );
175 for ( std::size_t i = 0; i < x.size(); i++ )
177 convexHull[i] =
static_cast< int >( i );
183 std::vector< int > stack( x.size() );
184 std::vector< double > tan( x.size() );
187 heapsort( convexHull,
id.data(), y, y.size() );
191 while ( ref < x.size() &&
qgsDoubleNear( y[
id[convexHull[ref]]], y[
id[convexHull[0]]] ) )
194 heapsort( convexHull,
id.data(), x, ref );
197 for ( std::size_t i = ref; i < x.size(); i++ )
199 if (
qgsDoubleNear( y[
id[convexHull[i]]], y[
id[convexHull[0]]] ) )
202 tan[i] = ( x[
id[convexHull[0]]] - x[
id[convexHull[i]]] ) / ( y[
id[convexHull[i]]] - y[
id[convexHull[0]]] );
205 if ( ref < x.size() )
206 heapsort2( convexHull.data() + ref, tan.data() + ref, x.size() - ref );
209 stack[0] = convexHull[0];
212 stack[1] = convexHull[1];
216 stack[1] = convexHull[ref - 1];
219 std::size_t second = 0;
221 for ( std::size_t i = ref; i < x.size(); i++ )
223 double result =
cross_product( x[
id[stack[second]]], y[
id[stack[second]]],
224 x[
id[stack[top]]], y[
id[stack[top]]], x[
id[convexHull[i]]], y[
id[convexHull[i]]] );
228 if (
dist_euc2d_sq( x[
id[stack[second]]], y[
id[stack[second]]], x[
id[convexHull[i]]], y[
id[convexHull[i]]] )
229 >
dist_euc2d_sq( x[
id[stack[second]]], y[
id[stack[second]]], x[
id[stack[top]]], y[
id[stack[top]]] ) )
231 stack[top] = convexHull[i];
234 else if ( result > 0 )
238 stack[top] = convexHull[i];
242 while ( result < 0 && top > 1 )
247 y[
id[stack[second]]], x[
id[stack[top]]],
248 y[
id[stack[top]]], x[
id[convexHull[i]]], y[
id[convexHull[i]]] );
252 stack[top] = convexHull[i];
256 for ( std::size_t i = 0; i <= top; i++ )
258 convexHull[i] = stack[i];
261 convexHull.resize( top + 1 );
267 std::vector< int > pts( x.size() );
268 for ( std::size_t i = 0; i < x.size(); i++ )
269 pts[i] =
static_cast< int >( i );
271 std::vector< int > convexHull =
convexHullId( pts, x, y );
274 if ( pts[convexHull[0]] < pts[convexHull[1]] && pts[convexHull[1]] < pts[convexHull[2]] )
276 else if ( pts[convexHull[0]] > pts[convexHull[1]] && pts[convexHull[1]] > pts[convexHull[2]] )
278 else if ( pts[convexHull[0]] > pts[convexHull[1]] && pts[convexHull[1]] < pts[convexHull[2]] && pts[convexHull[2]] < pts[convexHull[0]] )
280 else if ( pts[convexHull[0]] > pts[convexHull[1]] && pts[convexHull[1]] < pts[convexHull[2]] && pts[convexHull[2]] > pts[convexHull[0]] )
282 else if ( pts[convexHull[0]] < pts[convexHull[1]] && pts[convexHull[1]] > pts[convexHull[2]] && pts[convexHull[2]] > pts[convexHull[0]] )
284 else if ( pts[convexHull[0]] < pts[convexHull[1]] && pts[convexHull[1]] > pts[convexHull[2]] && pts[convexHull[2]] < pts[convexHull[0]] )
294 for ( std::size_t i = 0, j = x.size() - 1; i <= j; i++, j-- )
296 std::swap( x[i], x[j] );
297 std::swap( y[i], y[j] );
311 GEOSCoordSequence *coord = GEOSCoordSeq_create_r( geosctxt, 5, 2 );
313 #if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=8
314 GEOSCoordSeq_setXY_r( geosctxt, coord, 0, x, y );
316 GEOSCoordSeq_setX_r( geosctxt, coord, 0, x );
317 GEOSCoordSeq_setY_r( geosctxt, coord, 0, y );
321 double beta = alpha + M_PI_2;
322 double dx1 = std::cos( alpha ) * width;
323 double dy1 = std::sin( alpha ) * width;
324 double dx2 = std::cos( beta ) * height;
325 double dy2 = std::sin( beta ) * height;
326 #if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=8
327 GEOSCoordSeq_setXY_r( geosctxt, coord, 1, x + dx1, y + dy1 );
328 GEOSCoordSeq_setXY_r( geosctxt, coord, 2, x + dx1 + dx2, y + dy1 + dy2 );
329 GEOSCoordSeq_setXY_r( geosctxt, coord, 3, x + dx2, y + dy2 );
331 GEOSCoordSeq_setX_r( geosctxt, coord, 1, x + dx1 );
332 GEOSCoordSeq_setY_r( geosctxt, coord, 1, y + dy1 );
333 GEOSCoordSeq_setX_r( geosctxt, coord, 2, x + dx1 + dx2 );
334 GEOSCoordSeq_setY_r( geosctxt, coord, 2, y + dy1 + dy2 );
335 GEOSCoordSeq_setX_r( geosctxt, coord, 3, x + dx2 );
336 GEOSCoordSeq_setY_r( geosctxt, coord, 3, y + dy2 );
341 #if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=8
342 GEOSCoordSeq_setXY_r( geosctxt, coord, 1, x + width, y );
343 GEOSCoordSeq_setXY_r( geosctxt, coord, 2, x + width, y + height );
344 GEOSCoordSeq_setXY_r( geosctxt, coord, 3, x, y + height );
346 GEOSCoordSeq_setX_r( geosctxt, coord, 1, x + width );
347 GEOSCoordSeq_setY_r( geosctxt, coord, 1, y );
348 GEOSCoordSeq_setX_r( geosctxt, coord, 2, x + width );
349 GEOSCoordSeq_setY_r( geosctxt, coord, 2, y + height );
350 GEOSCoordSeq_setX_r( geosctxt, coord, 3, x );
351 GEOSCoordSeq_setY_r( geosctxt, coord, 3, y + height );
355 #if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=8
356 GEOSCoordSeq_setXY_r( geosctxt, coord, 4, x, y );
358 GEOSCoordSeq_setX_r( geosctxt, coord, 4, x );
359 GEOSCoordSeq_setY_r( geosctxt, coord, 4, y );
362 geos::unique_ptr bboxGeos( GEOSGeom_createLinearRing_r( geosctxt, coord ) );
363 bool result = ( GEOSPreparedContainsProperly_r( geosctxt, geom, bboxGeos.get() ) == 1 );
366 catch ( GEOSException &e )
368 qWarning(
"GEOS exception: %s", e.what() );
378 double x1,
double y1,
double x2,
double y2,
379 double &xRes,
double &yRes )
381 double multiplier = 1;
393 radius *= multiplier;
399 double A = dx * dx + dy * dy;
400 double B = 2 * ( dx * ( x1 - cx ) + dy * ( y1 - cy ) );
401 double C = ( x1 - cx ) * ( x1 - cx ) + ( y1 - cy ) * ( y1 - cy ) - radius * radius;
403 double det = B * B - 4 * A * C;
404 if ( A <= 0.000000000001 || det < 0 )
411 double t = -B / ( 2 * A );
420 double t = ( -B + std::sqrt( det ) ) / ( 2 * A );
425 if ( multiplier != 1 )
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).
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 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.
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