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 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 = qgis::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 );
271 return isInConflictSinglePart( lp );
273 return isInConflictMultiPart( lp );
276 bool LabelPosition::isInConflictSinglePart(
const LabelPosition *lp )
const
293 bool result = ( GEOSPreparedIntersects_r( geosctxt,
preparedGeom(), lp->
mGeos ) == 1 );
296 catch ( GEOSException &e )
298 qWarning(
"GEOS exception: %s", e.what() );
304 bool LabelPosition::isInConflictMultiPart(
const LabelPosition *lp )
const
314 if ( tmp1->isInConflictSinglePart( tmp2 ) )
324 int LabelPosition::partCount()
const
327 return mNextPart->partCount() + 1;
334 for (
int i = 0; i < 4; i++ )
341 mNextPart->offsetPosition( xOffset, yOffset );
353 return ( i >= 0 && i < 4 ?
x[i] : -1 );
358 return ( i >= 0 && i < 4 ?
y[i] : -1 );
370 mCost -= int ( mCost );
383 mNextPart->getBoundingBox( amin, amax );
387 amin[0] = std::numeric_limits<double>::max();
388 amax[0] = std::numeric_limits<double>::lowest();
389 amin[1] = std::numeric_limits<double>::max();
390 amax[1] = std::numeric_limits<double>::lowest();
392 for (
int c = 0;
c < 4;
c++ )
394 if (
x[
c] < amin[0] )
396 if (
x[
c] > amax[0] )
398 if (
y[
c] < amin[1] )
400 if (
y[
c] > amax[1] )
407 mHasObstacleConflict = conflicts;
409 mNextPart->setConflictsWithObstacle( conflicts );
414 mHasHardConflict = conflicts;
416 mNextPart->setHasHardObstacleConflict( conflicts );
438 bool contains =
false;
442 contains =
x[0] <= xp &&
x[1] >= xp &&
y[0] <= yp &&
y[2] >= yp;
449 double distance = -1;
454 const double dx = std::max( std::max(
x[0] - xp, 0.0 ), xp -
x[1] );
455 const double dy = std::max( std::max(
y[0] - yp, 0.0 ), yp -
y[2] );
456 distance = std::sqrt( dx * dx + dy * dy );
464 if ( mNextPart && distance > 0 )
465 return std::min( distance, mNextPart->getDistanceToPoint( xp, yp ) );
485 else if ( mNextPart )
487 return mNextPart->crossesLine( line );
490 catch ( GEOSException &e )
492 qWarning(
"GEOS exception: %s", e.what() );
505 if ( !polygon->
mGeos )
516 else if ( mNextPart )
518 return mNextPart->crossesBoundary( polygon );
521 catch ( GEOSException &e )
523 qWarning(
"GEOS exception: %s", e.what() );
534 double totalCost = polygonIntersectionCostForParts( polygon );
536 return std::ceil( totalCost / n );
544 if ( !polygon->
mGeos )
555 catch ( GEOSException &e )
557 qWarning(
"GEOS exception: %s", e.what() );
563 return mNextPart->intersectsWithPolygon( polygon );
571 double LabelPosition::polygonIntersectionCostForParts(
PointSet *polygon )
const
576 if ( !polygon->
mGeos )
591 for (
int i = 0; i < 4; ++i )
596 for (
int a = 0; a < 2; ++a )
600 px = (
x[i] +
x[( i + 1 ) % 4] ) / 2.0;
601 py = (
y[i] +
y[( i + 1 ) % 4] ) / 2.0;
605 px = (
x[0] +
x[2] ) / 2.0;
606 py = (
y[0] +
y[2] ) / 2.0;
613 catch ( GEOSException &e )
615 qWarning(
"GEOS exception: %s", e.what() );
624 cost += mNextPart->polygonIntersectionCostForParts( polygon );
A rtree spatial index for use in the pal labeling engine.
void insert(T *data, const QgsRectangle &bounds)
Inserts new data into the spatial index, with the specified bounds.
void remove(T *data, const QgsRectangle &bounds)
Removes existing data from the spatial index, with the specified bounds.
static GEOSContextHandle_t getGEOSHandler()
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).
A rectangle specified with double values.
Main class to handle feature.
Layer * layer()
Returns the layer that feature belongs to.
bool showUprightLabels() const
Returns true if feature's label must be displayed upright.
LabelPosition is a candidate feature label position.
bool intersectsWithPolygon(PointSet *polygon) const
Returns true if any intersection between polygon and position exists.
bool isInConflict(const LabelPosition *ls) const
Check whether or not this overlap with another labelPosition.
bool isIntersect(double *bbox)
Is the labelposition intersect the bounding-box ?
double getAlpha() const
Returns the angle to rotate text (in rad).
Quadrant
Position of label candidate relative to feature.
LabelPosition::Quadrant quadrant
void removeFromIndex(PalRtree< LabelPosition > &index)
Removes the label position from the specified index.
bool isInside(double *bbox)
Is the labelposition inside the bounding-box ?
bool crossesLine(PointSet *line) const
Returns true if this label crosses the specified line.
int getId() const
Returns the id.
void validateCost()
Make sure the cost is less than 1.
bool isIn(double *bbox)
Is the labelposition in the bounding-box ? (intersect or inside????)
double cost() const
Returns the candidate label position's geographical cost.
void setConflictsWithObstacle(bool conflicts)
Sets whether the position is marked as conflicting with an obstacle feature.
bool intersects(const GEOSPreparedGeometry *geometry)
Returns true if the label position intersects a geometry.
void setHasHardObstacleConflict(bool conflicts)
Sets whether the position is marked as having a hard conflict with an obstacle feature.
bool crossesBoundary(PointSet *polygon) const
Returns true if this label crosses the boundary of the specified polygon.
LabelPosition * nextPart() const
Returns the next part of this label position (i.e.
void offsetPosition(double xOffset, double yOffset)
Shift the label by specified offset.
double getDistanceToPoint(double xp, double yp) const
Gets distance from this label to a point. If point lies inside, returns negative number.
FeaturePart * getFeaturePart() const
Returns the feature corresponding to this labelposition.
double getX(int i=0) const
Returns the down-left x coordinate.
void getBoundingBox(double amin[2], double amax[2]) const
Returns bounding box - amin: xmin,ymin - amax: xmax,ymax.
double getY(int i=0) const
Returns the down-left y coordinate.
bool within(const GEOSPreparedGeometry *geometry)
Returns true if the label position is within a geometry.
void insertIntoIndex(PalRtree< LabelPosition > &index)
Inserts the label position into the specified index.
int polygonIntersectionCost(PointSet *polygon) const
Returns cost of position intersection with polygon (testing area of intersection and center).
bool isCurved() const
Returns true if the layer has curved labels.
The underlying raw pal geometry class.
friend class LabelPosition
void createGeosGeom() const
bool boundingBoxIntersects(const PointSet *other) const
Returns true if the bounding box of this pointset intersects the bounding box of another pointset.
const GEOSPreparedGeometry * preparedGeom() const
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,...
bool containsPoint(double x, double y) const
Tests whether point set contains a specified point.
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
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)