Пример #1
0
bool QgsGeometryAnalyzer::clipSegmentByRange( double x1, double y1, double m1, double x2, double y2, double m2, double range1, double range2, QgsPoint& pt1,
    QgsPoint& pt2, bool& secondPointClipped )
{
  bool reversed = m1 > m2;
  double tmp;

  //reverse m1, m2 if necessary (and consequently also x1,x2 / y1, y2)
  if ( reversed )
  {
    tmp = m1;
    m1 = m2;
    m2 = tmp;

    tmp = x1;
    x1 = x2;
    x2 = tmp;

    tmp = y1;
    y1 = y2;
    y2 = tmp;
  }

  //reverse range1, range2 if necessary
  if ( range1 > range2 )
  {
    tmp = range1;
    range1 = range2;
    range2 = tmp;
  }

  //segment completely outside of range
  if ( m2 < range1 || m1 > range2 )
  {
    return false;
  }

  //segment completely inside of range
  if ( m2 <= range2 && m1 >= range1 )
  {
    if ( reversed )
    {
      pt1.setX( x2 ); pt1.setY( y2 );
      pt2.setX( x1 ); pt2.setY( y1 );
    }
    else
    {
      pt1.setX( x1 ); pt1.setY( y1 );
      pt2.setX( x2 ); pt2.setY( y2 );
    }
    secondPointClipped = false;
    return true;
  }

  //m1 inside and m2 not
  if ( m1 >= range1 && m1 <= range2 )
  {
    pt1.setX( x1 ); pt1.setY( y1 );
    double dist = ( range2 - m1 ) / ( m2 - m1 );
    pt2.setX( x1 + ( x2 - x1 ) * dist );
    pt2.setY( y1 + ( y2 - y1 ) * dist );
    secondPointClipped = !reversed;
  }

  //m2 inside and m1 not
  if ( m2 >= range1 && m2 <= range2 )
  {
    pt2.setX( x2 ); pt2.setY( y2 );
    double dist = ( m2 - range1 ) / ( m2 - m1 );
    pt1.setX( x2 - ( x2 - x1 ) * dist );
    pt1.setY( y2 - ( y2 - y1 ) * dist );
    secondPointClipped = reversed;
  }

  //range1 and range 2 both inside the segment
  if ( range1 >= m1 && range2 <= m2 )
  {
    double dist1 = ( range1 - m1 ) / ( m2 - m1 );
    double dist2 = ( range2 - m1 ) / ( m2 - m1 );
    pt1.setX( x1 + ( x2 - x1 ) * dist1 );
    pt1.setY( y1 + ( y2 - y1 ) * dist1 );
    pt2.setX( x1 + ( x2 - x1 ) * dist2 );
    pt2.setY( y1 + ( y2 - y1 ) * dist2 );
    secondPointClipped = true;
  }

  if ( reversed ) //switch p1 and p2
  {
    QgsPoint tmpPt = pt1;
    pt1 = pt2;
    pt2 = tmpPt;
  }

  return true;
}
Пример #2
0
void QgsGeometryAnalyzer::locateAlongSegment( double x1, double y1, double m1, double x2, double y2, double m2, double measure, bool& pt1Ok, QgsPoint& pt1, bool& pt2Ok, QgsPoint& pt2 )
{
  bool reversed = false;
  pt1Ok = false;
  pt2Ok = false;
  double tolerance = 0.000001; //work with a small tolerance to catch e.g. locations at endpoints

  if ( m1 > m2 )
  {
    double tmp = m1;
    m1 = m2;
    m2 = tmp;
    reversed = true;
  }

  //segment does not match
  if (( m1 - measure ) > tolerance || ( measure - m2 ) > tolerance )
  {
    pt1Ok = false;
    pt2Ok = false;
    return;
  }

  //match with vertex1
  if ( qgsDoubleNear( m1, measure, tolerance ) )
  {
    if ( reversed )
    {
      pt2Ok = true;
      pt2.setX( x2 ); pt2.setY( y2 );
    }
    else
    {
      pt1Ok = true;
      pt1.setX( x1 ); pt1.setY( y1 );
    }
  }

  //match with vertex2
  if ( qgsDoubleNear( m2, measure, tolerance ) )
  {
    if ( reversed )
    {
      pt1Ok = true;
      pt1.setX( x1 ); pt1.setY( y1 );
    }
    else
    {
      pt2Ok = true;
      pt2.setX( x2 ); pt2.setY( y2 );
    }
  }


  if ( pt1Ok || pt2Ok )
  {
    return;
  }

  //match between the vertices
  if ( qgsDoubleNear( m1, m2 ) )
  {
    pt1.setX( x1 );
    pt1.setY( y1 );
    pt1Ok = true;
    return;
  }
  double dist = ( measure - m1 ) / ( m2 - m1 );
  if ( reversed )
  {
    dist = 1 - dist;
  }

  pt1.setX( x1 + dist * ( x2 - x1 ) );
  pt1.setY( y1 + dist * ( y2 - y1 ) );
  pt1Ok = true;
}
Пример #3
0
double QgsLineString::closestSegment( const QgsPoint &pt, QgsPoint &segmentPt,  QgsVertexId &vertexAfter, int *leftOf, double epsilon ) const
{
  double sqrDist = std::numeric_limits<double>::max();
  double leftOfDist = std::numeric_limits<double>::max();
  int prevLeftOf = 0;
  double prevLeftOfX = 0.0;
  double prevLeftOfY = 0.0;
  double testDist = 0;
  double segmentPtX, segmentPtY;

  if ( leftOf )
    *leftOf = 0;

  int size = mX.size();
  if ( size == 0 || size == 1 )
  {
    vertexAfter = QgsVertexId( 0, 0, 0 );
    return -1;
  }
  for ( int i = 1; i < size; ++i )
  {
    double prevX = mX.at( i - 1 );
    double prevY = mY.at( i - 1 );
    double currentX = mX.at( i );
    double currentY = mY.at( i );
    testDist = QgsGeometryUtils::sqrDistToLine( pt.x(), pt.y(), prevX, prevY, currentX, currentY, segmentPtX, segmentPtY, epsilon );
    if ( testDist < sqrDist )
    {
      sqrDist = testDist;
      segmentPt.setX( segmentPtX );
      segmentPt.setY( segmentPtY );
      vertexAfter.part = 0;
      vertexAfter.ring = 0;
      vertexAfter.vertex = i;
    }
    if ( leftOf && qgsDoubleNear( testDist, sqrDist ) )
    {
      int left = QgsGeometryUtils::leftOfLine( pt.x(), pt.y(), prevX, prevY, currentX, currentY );
      // if left equals 0, the test could not be performed (e.g. point in line with segment or on segment)
      // so don't set leftOf in this case, and hope that there's another segment that's the same distance
      // where we can perform the check
      if ( left != 0 )
      {
        if ( qgsDoubleNear( testDist, leftOfDist ) && left != prevLeftOf && prevLeftOf != 0 )
        {
          // we have two possible segments each with equal distance to point, but they disagree
          // on whether or not the point is to the left of them.
          // so we test the segments themselves and flip the result.
          // see https://stackoverflow.com/questions/10583212/elegant-left-of-test-for-polyline
          *leftOf = -QgsGeometryUtils::leftOfLine( currentX, currentY, prevLeftOfX, prevLeftOfY, prevX, prevY );
        }
        else
        {
          *leftOf = left;
        }
        prevLeftOf = *leftOf;
        leftOfDist = testDist;
        prevLeftOfX = prevX;
        prevLeftOfY = prevY;
      }
      else if ( testDist < leftOfDist )
      {
        *leftOf = left;
        leftOfDist = testDist;
        prevLeftOf = 0;
      }
    }
  }
  return sqrDist;
}
Пример #4
0
bool QgsTransectSample::closestSegmentPoints( QgsGeometry& g1, QgsGeometry& g2, double& dist, QgsPoint& pt1, QgsPoint& pt2 )
{
  QGis::WkbType t1 = g1.wkbType();
  if ( t1 != QGis::WKBLineString && t1 != QGis::WKBLineString25D )
  {
    return false;
  }

  QGis::WkbType t2 = g2.wkbType();
  if ( t2 != QGis::WKBLineString && t2 != QGis::WKBLineString25D )
  {
    return false;
  }

  QgsPolyline pl1 = g1.asPolyline();
  QgsPolyline pl2 = g2.asPolyline();

  if ( pl1.size() < 2 || pl2.size() < 2 )
  {
    return false;
  }

  QgsPoint p11 = pl1.at( 0 );
  QgsPoint p12 = pl1.at( 1 );
  QgsPoint p21 = pl2.at( 0 );
  QgsPoint p22 = pl2.at( 1 );

  double p1x = p11.x();
  double p1y = p11.y();
  double v1x = p12.x() - p11.x();
  double v1y = p12.y() - p11.y();
  double p2x = p21.x();
  double p2y = p21.y();
  double v2x = p22.x() - p21.x();
  double v2y = p22.y() - p21.y();

  double denominatorU = v2x * v1y - v2y * v1x;
  double denominatorT = v1x * v2y - v1y * v2x;

  if ( qgsDoubleNear( denominatorU, 0 ) || qgsDoubleNear( denominatorT, 0 ) )
  {
    //lines are parallel
    //project all points on the other segment and take the one with the smallest distance
    QgsPoint minDistPoint1;
    double d1 = p11.sqrDistToSegment( p21.x(), p21.y(), p22.x(), p22.y(), minDistPoint1 );
    QgsPoint minDistPoint2;
    double d2 = p12.sqrDistToSegment( p21.x(), p21.y(), p22.x(), p22.y(), minDistPoint2 );
    QgsPoint minDistPoint3;
    double d3 = p21.sqrDistToSegment( p11.x(), p11.y(), p12.x(), p12.y(), minDistPoint3 );
    QgsPoint minDistPoint4;
    double d4 = p22.sqrDistToSegment( p11.x(), p11.y(), p12.x(), p12.y(), minDistPoint4 );

    if ( d1 <= d2 && d1 <= d3 && d1 <= d4 )
    {
      dist = sqrt( d1 ); pt1 = p11; pt2 = minDistPoint1;
      return true;
    }
    else if ( d2 <= d1 && d2 <= d3 && d2 <= d4 )
    {
      dist = sqrt( d2 );  pt1 = p12; pt2 = minDistPoint2;
      return true;
    }
    else if ( d3 <= d1 && d3 <= d2 && d3 <= d4 )
    {
      dist = sqrt( d3 ); pt1 = p21; pt2 = minDistPoint3;
      return true;
    }
    else
    {
      dist = sqrt( d4 ); pt1 = p21; pt2 = minDistPoint4;
      return true;
    }
  }

  double u = ( p1x * v1y - p1y * v1x - p2x * v1y + p2y * v1x ) / denominatorU;
  double t = ( p2x * v2y - p2y * v2x - p1x * v2y + p1y * v2x ) / denominatorT;

  if ( u >= 0 && u <= 1.0 && t >= 0 && t <= 1.0 )
  {
    dist = 0;
    pt1.setX( p2x + u * v2x );
    pt1.setY( p2y + u * v2y );
    pt2 = pt1;
    dist = 0;
    return true;
  }

  if ( t > 1.0 )
  {
    pt1.setX( p12.x() );
    pt1.setY( p12.y() );
  }
  else if ( t < 0.0 )
  {
    pt1.setX( p11.x() );
    pt1.setY( p11.y() );
  }
  if ( u > 1.0 )
  {
    pt2.setX( p22.x() );
    pt2.setY( p22.y() );
  }
  if ( u < 0.0 )
  {
    pt2.setX( p21.x() );
    pt2.setY( p21.y() );
  }
  if ( t >= 0.0 && t <= 1.0 )
  {
    //project pt2 onto g1
    pt2.sqrDistToSegment( p11.x(), p11.y(), p12.x(), p12.y(), pt1 );
  }
  if ( u >= 0.0 && u <= 1.0 )
  {
    //project pt1 onto g2
    pt1.sqrDistToSegment( p21.x(), p21.y(), p22.x(), p22.y(), pt2 );
  }

  dist = sqrt( pt1.sqrDist( pt2 ) );
  return true;
}
Пример #5
0
bool QgsMapToolLabel::rotationPoint( QgsPoint& pos, bool ignoreUpsideDown, bool rotatingUnpinned )
{
  QVector<QgsPoint> cornerPoints = mCurrentLabelPos.cornerPoints;
  if ( cornerPoints.size() < 4 )
  {
    return false;
  }

  if ( mCurrentLabelPos.upsideDown && !ignoreUpsideDown )
  {
    pos = cornerPoints.at( 2 );
  }
  else
  {
    pos = cornerPoints.at( 0 );
  }

  //alignment always center/center and rotation 0 for diagrams
  if ( mCurrentLabelPos.isDiagram )
  {
    pos.setX( pos.x() + mCurrentLabelPos.labelRect.width() / 2.0 );
    pos.setY( pos.y() + mCurrentLabelPos.labelRect.height() / 2.0 );
    return true;
  }

  //adapt pos depending on data defined alignment
  QString haliString, valiString;
  currentAlignment( haliString, valiString );

  // rotate unpinned labels (i.e. no hali/vali settings) as if hali/vali was Center/Half
  if ( rotatingUnpinned )
  {
    haliString = "Center";
    valiString = "Half";
  }

//  QFont labelFont = labelFontCurrentFeature();
  QFontMetricsF labelFontMetrics( mCurrentLabelPos.labelFont );

  // NOTE: this assumes the label corner points comprise a rectangle and that the
  //       CRS supports equidistant measurements to accurately determine hypotenuse
  QgsPoint cp_0 = cornerPoints.at( 0 );
  QgsPoint cp_1 = cornerPoints.at( 1 );
  QgsPoint cp_3 = cornerPoints.at( 3 );
  //  QgsDebugMsg( QString( "cp_0: x=%1, y=%2" ).arg( cp_0.x() ).arg( cp_0.y() ) );
  //  QgsDebugMsg( QString( "cp_1: x=%1, y=%2" ).arg( cp_1.x() ).arg( cp_1.y() ) );
  //  QgsDebugMsg( QString( "cp_3: x=%1, y=%2" ).arg( cp_3.x() ).arg( cp_3.y() ) );
  double labelSizeX = qSqrt( cp_0.sqrDist( cp_1 ) );
  double labelSizeY = qSqrt( cp_0.sqrDist( cp_3 ) );

  double xdiff = 0;
  double ydiff = 0;

  if ( haliString.compare( "Center", Qt::CaseInsensitive ) == 0 )
  {
    xdiff = labelSizeX / 2.0;
  }
  else if ( haliString.compare( "Right", Qt::CaseInsensitive ) == 0 )
  {
    xdiff = labelSizeX;
  }

  if ( valiString.compare( "Top", Qt::CaseInsensitive ) == 0 || valiString.compare( "Cap", Qt::CaseInsensitive ) == 0 )
  {
    ydiff = labelSizeY;
  }
  else
  {
    double descentRatio = 1 / labelFontMetrics.ascent() / labelFontMetrics.height();
    if ( valiString.compare( "Base", Qt::CaseInsensitive ) == 0 )
    {
      ydiff = labelSizeY * descentRatio;
    }
    else if ( valiString.compare( "Half", Qt::CaseInsensitive ) == 0 )
    {
      ydiff = labelSizeY * 0.5 * ( 1 - descentRatio );
    }
  }

  double angle = mCurrentLabelPos.rotation;
  double xd = xdiff * cos( angle ) - ydiff * sin( angle );
  double yd = xdiff * sin( angle ) + ydiff * cos( angle );
  if ( mCurrentLabelPos.upsideDown && !ignoreUpsideDown )
  {
    pos.setX( pos.x() - xd );
    pos.setY( pos.y() - yd );
  }
  else
  {
    pos.setX( pos.x() + xd );
    pos.setY( pos.y() + yd );
  }
  return true;
}
Пример #6
0
bool QgsMapToolLabel::rotationPoint( QgsPoint& pos, bool ignoreUpsideDown )
{
  QVector<QgsPoint> cornerPoints = mCurrentLabelPos.cornerPoints;
  if ( cornerPoints.size() < 4 )
  {
    return false;
  }

  if ( mCurrentLabelPos.upsideDown && !ignoreUpsideDown )
  {
    pos = mCurrentLabelPos.cornerPoints.at( 2 );
  }
  else
  {
    pos = mCurrentLabelPos.cornerPoints.at( 0 );
  }

  //alignment always center/center and rotation 0 for diagrams
  if ( mCurrentLabelPos.isDiagram )
  {
    pos.setX( pos.x() + mCurrentLabelPos.labelRect.width() / 2.0 );
    pos.setY( pos.y() + mCurrentLabelPos.labelRect.height() / 2.0 );
    return true;
  }

  //adapt pos depending on data defined alignment
  QString haliString, valiString;
  currentAlignment( haliString, valiString );

  QFont labelFont = labelFontCurrentFeature();
  QFontMetricsF labelFontMetrics( labelFont );

  //label text?
  QString labelText = currentLabelText();

  bool labelSettingsOk;
  QgsPalLayerSettings& labelSettings = currentLabelSettings( &labelSettingsOk );
  if ( !labelSettingsOk )
  {
    return false;
  }

  double labelSizeX, labelSizeY;
  labelSettings.calculateLabelSize( &labelFontMetrics, labelText, labelSizeX, labelSizeY );

  double xdiff = 0;
  double ydiff = 0;

  if ( haliString.compare( "Center", Qt::CaseInsensitive ) == 0 )
  {
    xdiff = labelSizeX / 2.0;
  }
  else if ( haliString.compare( "Right", Qt::CaseInsensitive ) == 0 )
  {
    xdiff = labelSizeX;
  }

  if ( valiString.compare( "Top", Qt::CaseInsensitive ) == 0 || valiString.compare( "Cap", Qt::CaseInsensitive ) == 0 )
  {
    ydiff = labelSizeY;
  }
  else
  {
    double descentRatio = 1 / labelFontMetrics.ascent() / labelFontMetrics.height();
    if ( valiString.compare( "Base", Qt::CaseInsensitive ) == 0 )
    {
      ydiff = labelSizeY * descentRatio;
    }
    else if ( valiString.compare( "Half", Qt::CaseInsensitive ) == 0 )
    {
      ydiff = labelSizeY * descentRatio;
      ydiff = labelSizeY * 0.5 * ( 1 - descentRatio );
    }
  }

  double angle = mCurrentLabelPos.rotation;
  double xd = xdiff * cos( angle ) - ydiff * sin( angle );
  double yd = xdiff * sin( angle ) + ydiff * cos( angle );
  if ( mCurrentLabelPos.upsideDown && !ignoreUpsideDown )
  {
    pos.setX( pos.x() - xd );
    pos.setY( pos.y() - yd );
  }
  else
  {
    pos.setX( pos.x() + xd );
    pos.setY( pos.y() + yd );
  }
  return true;
}
Пример #7
0
void QgsLabel::renderLabel( QPainter * painter, const QgsRectangle& viewExtent,
                            const QgsCoordinateTransform* coordinateTransform,
                            const QgsMapToPixel *transform,
                            QgsFeature &feature, bool selected, QgsLabelAttributes *classAttributes,
                            double sizeScale, double rasterScaleFactor )
{
  QPen pen;
  QFont font;
  QString value;
  QString text;

  /* Calc scale (not nice) */
  QgsPoint point;
  point = transform->transform( 0, 0 );
  double x1 = point.x();
  point = transform->transform( 1000, 0 );
  double x2 = point.x();
  double scale = ( x2 - x1 ) * 0.001;

  /* Text */
  value = fieldValue( Text, feature );
  if ( value.isEmpty() )
  {
    text = mLabelAttributes->text();
  }
  else
  {
    text = value;
  }

  /* Font */
  value = fieldValue( Family, feature );
  if ( value.isEmpty() )
  {
    font.setFamily( mLabelAttributes->family() );
  }
  else
  {
    font.setFamily( value );
  }

  double size;
  value = fieldValue( Size, feature );
  if ( value.isEmpty() )
  {
    size =  mLabelAttributes->size();
  }
  else
  {
    size =  value.toDouble();
  }
  int sizeType;
  value = fieldValue( SizeType, feature );
  if ( value.isEmpty() )
    sizeType = mLabelAttributes->sizeType();
  else
  {
    value = value.toLower();
    if ( value.compare( "mapunits" ) == 0 )
      sizeType = QgsLabelAttributes::MapUnits;
    else
      sizeType = QgsLabelAttributes::PointUnits;
  }
  if ( sizeType == QgsLabelAttributes::MapUnits )
  {
    size *= scale;
  }
  else //point units
  {
    double sizeMM = size * 0.3527;
    size = sizeMM * sizeScale;
  }

  //Request font larger (multiplied by rasterScaleFactor) as a workaround for the Qt font bug
  //and scale the painter down by rasterScaleFactor when drawing the label
  size *= rasterScaleFactor;

  if (( int )size <= 0 )
    // skip too small labels
    return;

  font.setPixelSize( size );

  value = fieldValue( Color, feature );
  if ( value.isEmpty() )
  {
    pen.setColor( mLabelAttributes->color() );
  }
  else
  {
    pen.setColor( QColor( value ) );
  }

  value = fieldValue( Bold, feature );
  if ( value.isEmpty() )
  {
    font.setBold( mLabelAttributes->bold() );
  }
  else
  {
    font.setBold(( bool ) value.toInt() );
  }

  value = fieldValue( Italic, feature );
  if ( value.isEmpty() )
  {
    font.setItalic( mLabelAttributes->italic() );
  }
  else
  {
    font.setItalic(( bool ) value.toInt() );
  }

  value = fieldValue( Underline, feature );
  if ( value.isEmpty() )
  {
    font.setUnderline( mLabelAttributes->underline() );
  }
  else
  {
    font.setUnderline(( bool ) value.toInt() );
  }

  //
  QgsPoint overridePoint;
  bool useOverridePoint = false;
  value = fieldValue( XCoordinate, feature );
  if ( !value.isEmpty() )
  {
    overridePoint.setX( value.toDouble() );
    useOverridePoint = true;
  }
  value = fieldValue( YCoordinate, feature );
  if ( !value.isEmpty() )
  {
    overridePoint.setY( value.toDouble() );
    useOverridePoint = true;
  }

  /* Alignment */
  int alignment;
  QFontMetrics fm( font );
  int width, height;

  if ( mLabelAttributes->multilineEnabled() )
  {
    QStringList texts = text.split( "\n" );

    width = 0;
    for ( int i = 0; i < texts.size(); i++ )
    {
      int w = fm.width( texts[i] );
      if ( w > width )
        width = w;
    }

    height = fm.height() * texts.size();
  }
  else
  {
    width = fm.width( text );
    height = fm.height();
  }

  int dx = 0;
  int dy = 0;

  value = fieldValue( Alignment, feature );
  if ( value.isEmpty() )
  {
    alignment = mLabelAttributes->alignment();
  }
  else
  {
    value = value.toLower();

    alignment = 0;

    if ( value.contains( "left" ) )
      alignment |= Qt::AlignLeft;
    else if ( value.contains( "right" ) )
      alignment |= Qt::AlignRight;
    else
      alignment |= Qt::AlignHCenter;

    if ( value.contains( "bottom" ) )
      alignment |= Qt::AlignBottom;
    else if ( value.contains( "top" ) )
      alignment |= Qt::AlignTop;
    else
      alignment |= Qt::AlignVCenter;
  }

  if ( alignment & Qt::AlignLeft )
  {
    dx = 0;
  }
  else if ( alignment & Qt::AlignHCenter )
  {
    dx = -width / 2;
  }
  else if ( alignment & Qt::AlignRight )
  {
    dx = -width;
  }

  if ( alignment & Qt::AlignBottom )
  {
    dy = 0;
  }
  else if ( alignment & Qt::AlignVCenter )
  {
    dy = height / 2;
  }
  else if ( alignment & Qt::AlignTop )
  {
    dy = height;
  }

  // Offset
  double xoffset, yoffset;
  value = fieldValue( XOffset, feature );
  if ( value.isEmpty() )
  {
    xoffset = mLabelAttributes->xOffset();
  }
  else
  {
    xoffset = value.toDouble();
  }
  value = fieldValue( YOffset, feature );
  if ( value.isEmpty() )
  {
    yoffset = mLabelAttributes->yOffset();
  }
  else
  {
    yoffset = value.toDouble();
  }

  // recalc offset to pixels
  if ( mLabelAttributes->offsetType() == QgsLabelAttributes::MapUnits )
  {
    xoffset *= scale;
    yoffset *= scale;
  }
  else
  {
    xoffset = xoffset * 0.3527 * sizeScale;
    yoffset = yoffset * 0.3527 * sizeScale;
  }

  // Angle
  double ang;
  value = fieldValue( Angle, feature );
  if ( value.isEmpty() )
  {
    ang = mLabelAttributes->angle();
  }
  else
  {
    ang = value.toDouble();
  }


  // Work out a suitable position to put the label for the
  // feature. For multi-geometries, put the same label on each
  // part.
  if ( useOverridePoint )
  {
    renderLabel( painter, overridePoint, coordinateTransform,
                 transform, text, font, pen, dx, dy,
                 xoffset, yoffset, ang, width, height, alignment, sizeScale, rasterScaleFactor );
  }
  else
  {
    std::vector<labelpoint> points;
    labelPoint( points, feature );
    for ( uint i = 0; i < points.size(); ++i )
    {
      renderLabel( painter, points[i].p, coordinateTransform,
                   transform, text, font, pen, dx, dy,
                   xoffset, yoffset, mLabelAttributes->angleIsAuto() ? points[i].angle : ang, width, height, alignment, sizeScale, rasterScaleFactor );
    }
  }
}