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 = 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 );
 
  279   return isInConflictMultiPart( lp );
 
  282 bool LabelPosition::isInConflictMultiPart( 
const LabelPosition *lp )
 const 
  284   if ( !mMultipartGeos )
 
  285     createMultiPartGeosGeom();
 
  287   if ( !lp->mMultipartGeos )
 
  288     lp->createMultiPartGeosGeom();
 
  293     bool result = ( GEOSPreparedIntersects_r( geosctxt, 
preparedMultiPartGeom(), lp->mMultipartGeos ) == 1 );
 
  296   catch ( GEOSException &e )
 
  298     qWarning( 
"GEOS exception: %s", e.what() );
 
  306 int LabelPosition::partCount()
 const 
  309     return mNextPart->partCount() + 1;
 
  316   for ( 
int i = 0; i < 4; i++ )
 
  323     mNextPart->offsetPosition( xOffset, yOffset );
 
  335   return ( i >= 0 && i < 4 ? 
x[i] : -1 );
 
  340   return ( i >= 0 && i < 4 ? 
y[i] : -1 );
 
  352     mCost -= int ( mCost ); 
 
  365     mNextPart->getBoundingBox( amin, amax );
 
  369     amin[0] = std::numeric_limits<double>::max();
 
  370     amax[0] = std::numeric_limits<double>::lowest();
 
  371     amin[1] = std::numeric_limits<double>::max();
 
  372     amax[1] = std::numeric_limits<double>::lowest();
 
  374   for ( 
int c = 0; 
c < 4; 
c++ )
 
  376     if ( 
x[
c] < amin[0] )
 
  378     if ( 
x[
c] > amax[0] )
 
  380     if ( 
y[
c] < amin[1] )
 
  382     if ( 
y[
c] > amax[1] )
 
  389   mHasObstacleConflict = conflicts;
 
  391     mNextPart->setConflictsWithObstacle( conflicts );
 
  396   mHasHardConflict = conflicts;
 
  398     mNextPart->setHasHardObstacleConflict( conflicts );
 
  418 void LabelPosition::createMultiPartGeosGeom()
 const 
  422   std::vector< const GEOSGeometry * > geometries;
 
  426     const GEOSGeometry *partGeos = tmp1->
geos();
 
  427     if ( !GEOSisEmpty_r( geosctxt, partGeos ) )
 
  428       geometries.emplace_back( partGeos );
 
  432   const std::size_t partCount = geometries.size();
 
  433   GEOSGeometry **geomarr = 
new GEOSGeometry*[ partCount ];
 
  434   for ( std::size_t i = 0; i < partCount; ++i )
 
  436     geomarr[i ] = GEOSGeom_clone_r( geosctxt, geometries[i] );
 
  439   mMultipartGeos = GEOSGeom_createCollection_r( geosctxt, GEOS_MULTIPOLYGON, geomarr, partCount );
 
  445   if ( !mMultipartGeos )
 
  446     createMultiPartGeosGeom();
 
  448   if ( !mMultipartPreparedGeos )
 
  452   return mMultipartPreparedGeos;
 
  458   bool contains = 
false;
 
  462     contains = 
x[0] <= xp && 
x[1] >= xp && 
y[0] <= yp && 
y[2] >= yp;
 
  469   double distance = -1;
 
  474       const double dx = std::max( std::max( 
x[0] - xp, 0.0 ), xp - 
x[1] );
 
  475       const double dy = std::max( std::max( 
y[0] - yp, 0.0 ), yp - 
y[2] );
 
  476       distance = std::sqrt( dx * dx + dy * dy );
 
  484   if ( mNextPart && distance > 0 )
 
  485     return std::min( distance, mNextPart->getDistanceToPoint( xp, yp ) );
 
  505     else if ( mNextPart )
 
  507       return mNextPart->crossesLine( line );
 
  510   catch ( GEOSException &e )
 
  512     qWarning( 
"GEOS exception: %s", e.what() );
 
  525   if ( !polygon->
mGeos )
 
  536     else if ( mNextPart )
 
  538       return mNextPart->crossesBoundary( polygon );
 
  541   catch ( GEOSException &e )
 
  543     qWarning( 
"GEOS exception: %s", e.what() );
 
  554   double totalCost = polygonIntersectionCostForParts( polygon );
 
  556   return std::ceil( totalCost / n );
 
  564   if ( !polygon->
mGeos )
 
  575   catch ( GEOSException &e )
 
  577     qWarning( 
"GEOS exception: %s", e.what() );
 
  583     return mNextPart->intersectsWithPolygon( polygon );
 
  591 double LabelPosition::polygonIntersectionCostForParts( 
PointSet *polygon )
 const 
  596   if ( !polygon->
mGeos )
 
  611       for ( 
int i = 0; i < 4; ++i )
 
  616         for ( 
int a = 0; a < 2; ++a ) 
 
  620           px = ( 
x[i] + 
x[( i + 1 ) % 4] ) / 2.0;
 
  621           py = ( 
y[i] + 
y[( i + 1 ) % 4] ) / 2.0;
 
  625       px = ( 
x[0] + 
x[2] ) / 2.0;
 
  626       py = ( 
y[0] + 
y[2] ) / 2.0;
 
  633   catch ( GEOSException &e )
 
  635     qWarning( 
"GEOS exception: %s", e.what() );
 
  644     cost += mNextPart->polygonIntersectionCostForParts( polygon );
 
  652   double angleDiff = 0.0, angleLast = 0.0, diff;
 
  653   double sinAvg = 0, cosAvg = 0;
 
  659       diff = std::fabs( tmp->
getAlpha() - angleLast );
 
  660       if ( diff > 2 * M_PI ) diff -= 2 * M_PI;
 
  661       diff = std::min( diff, 2 * M_PI - diff ); 
 
  665     sinAvg += std::sin( tmp->
getAlpha() );
 
  666     cosAvg += std::cos( tmp->
getAlpha() );
 
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::MessageLevel::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.
bool onlyShowUprightLabels() const
Returns true if feature's label must be displayed upright.
Layer * layer()
Returns the layer that feature belongs to.
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
double angleDifferential()
Returns the angle differential of all LabelPosition parts.
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.
const GEOSPreparedGeometry * preparedMultiPartGeom() const
Returns a prepared GEOS representation of all label parts as a multipolygon.
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
const GEOSGeometry * geos() const
Returns the point set's GEOS geometry.
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)