43LabelPosition::LabelPosition( 
int id, 
double x1, 
double y1, 
double w, 
double h, 
double alpha, 
double cost, 
FeaturePart *feature, 
bool isReversed, 
Quadrant quadrant )
 
   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 );
 
  287bool 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() );
 
  311int 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 );
 
  423void 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 );
 
  596double 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 ); 
 
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.
 
@ AllowOverlapAtNoCost
Labels may freely overlap other labels, at no cost.
 
static GEOSContextHandle_t getGEOSHandler()
 
Qgis::LabelOverlapHandling overlapHandling() const
Returns the technique to use for handling overlapping labels for the feature.
 
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.
 
QgsLabelFeature * feature()
Returns the parent feature.
 
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.
 
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).
 
LabelPosition * nextPart() const
Returns the next part of this label position (i.e.
 
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.
 
void invalidateGeos() 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)