52 , reversed( isReversed )
54 , quadrant( quadrant )
56 , mHasObstacleConflict( false )
57 , mUpsideDownCharCount( 0 )
65 while ( this->alpha > 2 * M_PI )
66 this->alpha -= 2 * M_PI;
68 while ( this->alpha < 0 )
69 this->alpha += 2 * M_PI;
71 const double beta = this->alpha + M_PI_2;
73 double dx1, dx2, dy1, dy2;
75 dx1 = std::cos( this->alpha ) *
w;
76 dy1 = std::sin( this->alpha ) *
w;
78 dx2 = std::cos( beta ) *
h;
79 dy2 = std::sin( beta ) *
h;
87 x[2] = x1 + dx1 + dx2;
88 y[2] = y1 + dy1 + dy2;
95 this->alpha > M_PI_2 && this->alpha <= 3 * M_PI_2 )
120 if ( this->alpha < M_PI )
131 for (
int i = 0; i <
nbPoints; ++i )
153 if ( other.mNextPart )
154 mNextPart = std::make_unique< LabelPosition >( *other.mNextPart );
160 mHasObstacleConflict = other.mHasObstacleConflict;
161 mUpsideDownCharCount = other.mUpsideDownCharCount;
168 for ( i = 0; i < 4; i++ )
170 if (
x[i] >= bbox[0] &&
x[i] <= bbox[2] &&
171 y[i] >= bbox[1] &&
y[i] <= bbox[3] )
176 return mNextPart->isIn( bbox );
185 for ( i = 0; i < 4; i++ )
187 if (
x[i] >= bbox[0] &&
x[i] <= bbox[2] &&
188 y[i] >= bbox[1] &&
y[i] <= bbox[3] )
193 return mNextPart->isIntersect( bbox );
209 else if ( mNextPart )
211 return mNextPart->intersects( geometry );
214 catch ( GEOSException &e )
216 qWarning(
"GEOS exception: %s", e.what() );
235 else if ( mNextPart )
237 return mNextPart->within( geometry );
240 catch ( GEOSException &e )
242 qWarning(
"GEOS exception: %s", e.what() );
252 for (
int i = 0; i < 4; i++ )
254 if ( !(
x[i] >= bbox[0] &&
x[i] <= bbox[2] &&
255 y[i] >= bbox[1] &&
y[i] <= bbox[3] ) )
260 return mNextPart->isInside( bbox );
284 return isInConflictMultiPart( lp );
287 bool LabelPosition::isInConflictMultiPart(
const LabelPosition *lp )
const
289 if ( !mMultipartGeos )
290 createMultiPartGeosGeom();
292 if ( !lp->mMultipartGeos )
293 lp->createMultiPartGeosGeom();
298 const bool result = ( GEOSPreparedIntersects_r( geosctxt,
preparedMultiPartGeom(), lp->mMultipartGeos ) == 1 );
301 catch ( GEOSException &e )
303 qWarning(
"GEOS exception: %s", e.what() );
311 int LabelPosition::partCount()
const
314 return mNextPart->partCount() + 1;
321 for (
int i = 0; i < 4; i++ )
328 mNextPart->offsetPosition( xOffset, yOffset );
340 return ( i >= 0 && i < 4 ?
x[i] : -1 );
345 return ( i >= 0 && i < 4 ?
y[i] : -1 );
357 mCost -= int ( mCost );
370 mNextPart->getBoundingBox( amin, amax );
374 amin[0] = std::numeric_limits<double>::max();
375 amax[0] = std::numeric_limits<double>::lowest();
376 amin[1] = std::numeric_limits<double>::max();
377 amax[1] = std::numeric_limits<double>::lowest();
379 for (
int c = 0;
c < 4;
c++ )
381 if (
x[
c] < amin[0] )
383 if (
x[
c] > amax[0] )
385 if (
y[
c] < amin[1] )
387 if (
y[
c] > amax[1] )
394 mHasObstacleConflict = conflicts;
396 mNextPart->setConflictsWithObstacle( conflicts );
401 mHasHardConflict = conflicts;
403 mNextPart->setHasHardObstacleConflict( conflicts );
423 void LabelPosition::createMultiPartGeosGeom()
const
427 std::vector< const GEOSGeometry * > geometries;
431 const GEOSGeometry *partGeos = tmp1->
geos();
432 if ( !GEOSisEmpty_r( geosctxt, partGeos ) )
433 geometries.emplace_back( partGeos );
437 const std::size_t partCount = geometries.size();
438 GEOSGeometry **geomarr =
new GEOSGeometry*[ partCount ];
439 for ( std::size_t i = 0; i < partCount; ++i )
441 geomarr[i ] = GEOSGeom_clone_r( geosctxt, geometries[i] );
444 mMultipartGeos = GEOSGeom_createCollection_r( geosctxt, GEOS_MULTIPOLYGON, geomarr, partCount );
450 if ( !mMultipartGeos )
451 createMultiPartGeosGeom();
453 if ( !mMultipartPreparedGeos )
457 return mMultipartPreparedGeos;
463 bool contains =
false;
467 contains =
x[0] <= xp &&
x[1] >= xp &&
y[0] <= yp &&
y[2] >= yp;
474 double distance = -1;
479 const double dx = std::max( std::max(
x[0] - xp, 0.0 ), xp -
x[1] );
480 const double dy = std::max( std::max(
y[0] - yp, 0.0 ), yp -
y[2] );
481 distance = std::sqrt( dx * dx + dy * dy );
489 if ( mNextPart && distance > 0 )
490 return std::min( distance, mNextPart->getDistanceToPoint( xp, yp ) );
510 else if ( mNextPart )
512 return mNextPart->crossesLine( line );
515 catch ( GEOSException &e )
517 qWarning(
"GEOS exception: %s", e.what() );
530 if ( !polygon->
mGeos )
541 else if ( mNextPart )
543 return mNextPart->crossesBoundary( polygon );
546 catch ( GEOSException &e )
548 qWarning(
"GEOS exception: %s", e.what() );
559 const double totalCost = polygonIntersectionCostForParts( polygon );
560 const int n = partCount();
561 return std::ceil( totalCost / n );
569 if ( !polygon->
mGeos )
580 catch ( GEOSException &e )
582 qWarning(
"GEOS exception: %s", e.what() );
588 return mNextPart->intersectsWithPolygon( polygon );
596 double LabelPosition::polygonIntersectionCostForParts(
PointSet *polygon )
const
601 if ( !polygon->
mGeos )
616 for (
int i = 0; i < 4; ++i )
621 for (
int a = 0; a < 2; ++a )
625 px = (
x[i] +
x[( i + 1 ) % 4] ) / 2.0;
626 py = (
y[i] +
y[( i + 1 ) % 4] ) / 2.0;
630 px = (
x[0] +
x[2] ) / 2.0;
631 py = (
y[0] +
y[2] ) / 2.0;
638 catch ( GEOSException &e )
640 qWarning(
"GEOS exception: %s", e.what() );
649 cost += mNextPart->polygonIntersectionCostForParts( polygon );
657 double angleDiff = 0.0;
658 double angleLast = 0.0;
664 double diff = std::fabs( tmp->
getAlpha() - angleLast );
665 if ( diff > 2 * M_PI )
667 diff = std::min( diff, 2 * M_PI - diff );