Esempio n. 1
0
void GradientEditor::pointsUpdated()
{
    qreal w = m_alpha_shade->width();

    QGradientStops stops;

    QPolygonF points;

    points += m_red_shade->points();
    points += m_green_shade->points();
    points += m_blue_shade->points();
    points += m_alpha_shade->points();

    qSort(points.begin(), points.end(), x_less_than);

    for (int i=0; i<points.size(); ++i) {
        qreal x = int(points.at(i).x());
        if (i < points.size() - 1 && x == points.at(i+1).x())
            continue;
        QColor color((0x00ff0000 & m_red_shade->colorAt(int(x))) >> 16,
                     (0x0000ff00 & m_green_shade->colorAt(int(x))) >> 8,
                     (0x000000ff & m_blue_shade->colorAt(int(x))),
                     (0xff000000 & m_alpha_shade->colorAt(int(x))) >> 24);

        if (x / w > 1)
            return;

        stops << QGradientStop(x / w, color);
    }

    m_alpha_shade->setGradientStops(stops);

    emit gradientStopsChanged(stops);
}
Esempio n. 2
0
void QgsAnnotation::drawFrame( QgsRenderContext &context ) const
{
  if ( !mFillSymbol )
    return;

  context.painter()->setRenderHint( QPainter::Antialiasing, context.flags() & QgsRenderContext::Antialiasing );

  QPolygonF poly;
  QList<QPolygonF> rings; //empty list
  for ( int i = 0; i < 4; ++i )
  {
    QLineF currentSegment = segment( i );
    poly << currentSegment.p1();
    if ( i == mBalloonSegment && mHasFixedMapPosition )
    {
      poly << mBalloonSegmentPoint1;
      poly << QPointF( 0, 0 );
      poly << mBalloonSegmentPoint2;
    }
    poly << currentSegment.p2();
  }
  if ( poly.at( 0 ) != poly.at( poly.count() - 1 ) )
    poly << poly.at( 0 );

  mFillSymbol->startRender( context );
  mFillSymbol->renderPolygon( poly, &rings, nullptr, context );
  mFillSymbol->stopRender( context );
}
Esempio n. 3
0
 /**
  * Return the point in \a poly which follows the point at index \a index.
  * If \a index is the last index then return the first (or, if
  * \a poly.isClosed() is true, the second) point.
  */
 QPointF nextPoint(int index, const QPolygonF& poly) {
     if (poly.size() < 3 || index >= poly.size())
         return QPoint();
     if (index == poly.size() - 1)
         return poly.at((int)poly.isClosed());
     return poly.at(index + 1);
 }
Esempio n. 4
0
 /**
  * Find the line of \a poly with the smallest or largest value (controlled by \a seek)
  * along the axis controlled by \a axis.
  * In case \a axis is X, do not consider lines whose Y values lie outside the Y values
  * defined by \a boundingRect.
  * In case \a axis is Y, do not consider lines whose X values lie outside the X values
  * defined by \a boundingRect.
  */
 QLineF findLine(const QPolygonF& poly, Axis_Type axis, Comparison_Type seek, const QRectF& boundingRect)
 {
     const int lastIndex = poly.size() - 1 - (int)poly.isClosed();
     QPointF prev = poly.at(lastIndex), curr;
     QPointF p1(seek == Smallest ? QPointF(1.0e6, 1.0e6) : QPointF(-1.0e6, -1.0e6));
     QPointF p2;
     for (int i = 0; i <= lastIndex; i++) {
         curr = poly.at(i);
         // uDebug() << "  poly[" << i << "] = " << curr;
         if (axis == X) {
             if (fmin(prev.y(), curr.y()) > boundingRect.y() + boundingRect.height() ||
                 fmax(prev.y(), curr.y()) < boundingRect.y()) {
                 // line is outside Y-axis range defined by boundingRect
             } else if ((seek == Smallest && curr.x() <= p1.x()) ||
                        (seek == Largest  && curr.x() >= p1.x())) {
                 p1 = curr;
                 p2 = prev;
             }
         } else {
             if (fmin(prev.x(), curr.x()) > boundingRect.x() + boundingRect.width() ||
                 fmax(prev.x(), curr.x()) < boundingRect.x()) {
                 // line is outside X-axis range defined by boundingRect
             } else if ((seek == Smallest && curr.y() <= p1.y()) ||
                        (seek == Largest  && curr.y() >= p1.y())) {
                 p1 = curr;
                 p2 = prev;
             }
         }
         prev = curr;
     }
     return QLineF(p1, p2);
 }
Esempio n. 5
0
QVector<QLineF> Polygon::_getSegments(const QPolygonF& polygon)
{
    QVector<QLineF> segments;
    for (int i=0; i<polygon.size(); i++)
        segments.push_back(QLineF(polygon.at(i), polygon.at( (i+1) % polygon.size() )));
    return segments;
}
Esempio n. 6
0
 /**
  * Return the point in \a poly which precedes the point at index \a index.
  * If \a index is 0 then return the last (or, if \a poly.isClosed() is
  * true, the second to last) point.
  */
 QPointF prevPoint(int index, const QPolygonF& poly) {
     if (poly.size() < 3 || index >= poly.size())
         return QPoint();
     if (index == 0)
         return poly.at(poly.size() - 1 - (int)poly.isClosed());
     return poly.at(index - 1);
 }
int ObstacleBitmap::findFirstVertex(const QPolygonF& polygon)const{
	std::vector<int> tmp;
	qreal minY = DBL_MAX;
	for(int i = 0; i < polygon.size(); i++){
		if(polygon.at(i).y() < minY){
			tmp.clear();
			minY = polygon.at(i).y();
			tmp.push_back(i);
		}
		else if(minY == polygon.at(i).y()){
			tmp.push_back(i);
		}
	}

	if(tmp.size() == 1){
		return tmp.at(0);
	}

	qreal minX = DBL_MAX;
	int ret = -1;

	for(size_t i = 0; i < tmp.size(); i++){
		if(polygon.at(tmp.at(i)).x() < minX){
			minX = polygon.at(tmp.at(i)).x();
			ret = tmp.at(i);
		}
	}

	return ret;
}
Esempio n. 8
0
void GLUtils::fillPolygon( const QPolygonF& p )
{
#if 1
    GLUtesselator *tobj;
    GLdouble* polygon = new GLdouble[p.size()*3];
    for(int i=0;i<p.size();i++)
    {
        polygon[i*3 + 0] = p.at(i).x();
        polygon[i*3 + 1] = p.at(i).y();
        polygon[i*3 + 2] = 0.0;
    }

    tobj = gluNewTess();
    gluTessCallback(tobj, GLU_TESS_VERTEX, (void (CALLBACK *) ())&glVertex3dv);
    gluTessCallback(tobj, GLU_TESS_BEGIN, (void (CALLBACK*) ())&glBegin);
    gluTessCallback(tobj, GLU_TESS_END, (void (CALLBACK*) ())&glEnd);

    glShadeModel(GL_SMOOTH);
    gluTessBeginPolygon(tobj, NULL);
    gluTessBeginContour(tobj);
        for(int i=0;i<p.size();i++)
            gluTessVertex(tobj, polygon+i*3, polygon+i*3);
    gluTessEndContour(tobj);
    gluTessEndPolygon(tobj);
    glEndList();
    gluDeleteTess(tobj);
#else
    glBegin(GL_POLYGON);
    for(int i=0;i<p.size();i++)
    {
        glVertex2f(p.at(i).x(), p.at(i).y());
    }
    glEnd();
#endif
}
Esempio n. 9
0
QPointF Meshing::addMiddlePoint(int id)
{
    QPointF point(0,0);
    QPolygonF poly = mesh_.at(id);
    if(poly.isEmpty())
        return point;

    if(!poly.isClosed())
        poly << poly.at(0);

    mesh_.removeAt(id);

    for(int i=0;i<poly.size()-1;i++)
        point += poly.at(i);
    point /= (double)(poly.size()-1);

    /*while(!poly.containsPoint(point,Qt::WindingFill)){
        point += QPointF(-50+rand()%100,-50+rand()%100);
    }*/

    for(int i=0;i<poly.size()-1;i++){
        QPolygonF p;
        p << poly.at(i) << poly.at(i+1) << point << poly.at(i);
        mesh_.push_back(p);
    }
    return point;
}
void QgsLineDecorationSymbolLayerV2::renderPolyline( const QPolygonF& points, QgsSymbolV2RenderContext& context )
{
  // draw arrow at the end of line

  QPainter* p = context.renderContext().painter();
  if ( !p )
  {
    return;
  }

  int cnt = points.count();
  QPointF p2 = points.at( --cnt );
  QPointF p1 = points.at( --cnt );
  while ( p2 == p1 && cnt )
    p1 = points.at( --cnt );
  if ( p1 == p2 ) {
    // this is a collapsed line... don't bother drawing an arrow
    // with arbitrary orientation
    return;
  }

  double angle = atan2( p2.y() - p1.y(), p2.x() - p1.x() );
  double size = context.outputLineWidth( mWidth * 8 );
  double angle1 = angle + M_PI / 6;
  double angle2 = angle - M_PI / 6;

  QPointF p2_1 = p2 - QPointF( size * cos( angle1 ), size * sin( angle1 ) );
  QPointF p2_2 = p2 - QPointF( size * cos( angle2 ), size * sin( angle2 ) );

  p->setPen( context.selected() ? mSelPen : mPen );
  p->drawLine( p2, p2_1 );
  p->drawLine( p2, p2_2 );
}
Esempio n. 11
0
bool clipByRect( QLineF& line, const QPolygonF& rect )
{
  QVector<QLineF> borderLines;
  borderLines << QLineF( rect.at( 0 ), rect.at( 1 ) );
  borderLines << QLineF( rect.at( 1 ), rect.at( 2 ) );
  borderLines << QLineF( rect.at( 2 ), rect.at( 3 ) );
  borderLines << QLineF( rect.at( 3 ), rect.at( 0 ) );

  QVector<QPointF> intersectionList;
  QVector<QLineF>::const_iterator it = borderLines.constBegin();
  for ( ; it != borderLines.constEnd(); ++it )
  {
    QPointF intersectionPoint;
    if ( it->intersect( line, &intersectionPoint ) == QLineF::BoundedIntersection )
    {
      intersectionList.push_back( intersectionPoint );
      if ( intersectionList.size() >= 2 )
      {
        break; //we already have two intersections, skip further tests
      }
    }
  }
  if ( intersectionList.size() < 2 ) return false; // no intersection

  line = QLineF( intersectionList.at( 0 ), intersectionList.at( 1 ) );
  return true;
}
Esempio n. 12
0
void VLCStatsView::addHistoryValue( float value )
{
    /* We keep a full history by creating virtual blocks for inserts, growing
       by power of 2 when no more space is available. At this time, we also
       free space by agregating the oldest values 2 by 2.
       Each shown value finally being a mean of blocksize samples.
    */
    bool doinsert = false;
    int next_blocksize = blocksize;
    QPolygonF shape = historyShape->polygon();
    int count = shape.count();
    if ( count == 0 )
    {
        shape << QPointF( 0, 0 ); /* begin and close shape */
        shape << QPointF( count, 0 );
    }

    valuesaccumulator += ( value / blocksize );
    valuesaccumulatorcount++;

    if ( valuesaccumulatorcount == blocksize )
    {
        valuesaccumulator = 0;
        valuesaccumulatorcount = 0;
        doinsert = true;
    }

    if ( doinsert )
    {
        if ( count > ( STATS_LENGTH + 2 ) )
        {
            float y = 0;
            y += ((QPointF &) shape.at( historymergepointer + 1 )).y();
            y += ((QPointF &) shape.at( historymergepointer + 2 )).y();
            y /= 2;

            /* merge */
            shape.remove( historymergepointer + 2 );
            ( (QPointF &) shape.at( historymergepointer + 1 ) ).setY( y );
            for(int i=historymergepointer +1; i<( STATS_LENGTH + 2 ); i++)
                ( (QPointF &) shape.at(i) ).setX( i - 1 ); /*move back values*/
            historymergepointer++;
            if ( historymergepointer > ( STATS_LENGTH - 1 ) )
            {
                historymergepointer = 0;
                next_blocksize = ( blocksize << 1 );
            }
        }

        shape.insert( shape.end() - 1, QPointF( count, value ) );
        ( (QPointF &) shape.last() ).setX( count );
    }
    else
        ( (QPointF &) shape.last() ).setX( count - 1 );

    historyShape->setPolygon( shape );

    blocksize = next_blocksize;
}
Esempio n. 13
0
void UwMath::fromConformalInverted(QPolygonF &object) {
    QPointF * data = object.data();

    for(int i = 0; i < object.size(); i++) {
        data[i].setX(UwMath::toDegrees(object.at(i).x()));
        data[i].setY(UwMath::fromMercator(object.at(i).y() * (-1)));
    }
}
Esempio n. 14
0
/** Converts a list of points from degrees to a conformal
  * point in Mercator projection
  * @param points in longitude, latitude given in degrees (DD)
  * @return conformal points in radians
  */
void UwMath::toConformal(QPolygonF &object) {
    QPointF * data = object.data();

    for(int i = 0; i < object.size(); i++) {
        data[i].setX(UwMath::toRadians(object.at(i).x()));
        data[i].setY(UwMath::toMercator(object.at(i).y()));
    }
}
Esempio n. 15
0
QPolygonF UwMath::triangleToHalf_OnePointVersion(const QPolygonF &original) {
    QPolygonF half;

    half << original.at(0);
    half << original.at(1);
    half << UwMath::getMiddlePoint(original.at(1), original.at(2));
    return half;
}
Esempio n. 16
0
QPolygonF UwMath::avgTriangle_OnePointVersion(const QPolygonF &tr1, const QPolygonF &tr2) {
    QPolygonF avg;

    avg << tr1.at(0);
    avg << tr1.at(1);
    avg << UwMath::getMiddlePoint(tr1.at(2), tr2.at(2));
    return avg;
}
/**
 * This method aligns both the \b "start" and \b "end" symbols to
 * the current angles of the \b "first" and the \b "last" line
 * segment respectively.
 */
void AssociationLine::alignSymbols()
{
    const int sz = m_points.size();
    if (sz < 2) {
        // cannot align if there is no line (one line = 2 points)
        return;
    }

    QList<QPolygonF> polygons = path().toSubpathPolygons();

    if (m_startSymbol) {
        QPolygonF firstLine = polygons.first();
        QLineF segment(firstLine.at(1), firstLine.at(0));
        m_startSymbol->alignTo(segment);
    }

    if (m_endSymbol) {
        QPolygonF lastLine = polygons.last();
        int maxIndex = lastLine.size();
        QLineF segment(lastLine.at(maxIndex-2), lastLine.at(maxIndex-1));
        m_endSymbol->alignTo(segment);
    }

    if (m_subsetSymbol) {
        QPointF p1 = path().pointAtPercent(0.4);
        QPointF p2 = path().pointAtPercent(0.5);
        QLineF segment(p1, p2);
        m_subsetSymbol->alignTo(segment);
    }

    if (m_collaborationLineItem) {
        const qreal distance = 10;
        const int midSegmentIndex = (sz - 1) / 2;

        const QPointF a = m_points.at(midSegmentIndex);
        const QPointF b = m_points.at(midSegmentIndex + 1);

        if (a == b)
            return;

        const QPointF p1 = (a + b) / 2.0;
        const QPointF p2 = (p1 + b) / 2.0;

        // Reversed line as we want normal in opposite direction.
        QLineF segment(p2, p1);
        QLineF normal = segment.normalVector().unitVector();
        normal.setLength(distance);

        QLineF actualLine;
        actualLine.setP2(normal.p2());

        normal.translate(p1 - p2);
        actualLine.setP1(normal.p2());

        m_collaborationLineItem->setLine(actualLine);
        m_collaborationLineHead->alignTo(actualLine);
    }
}
Esempio n. 18
0
bool CalculateLaylines::checkOffset_OnePointVersion( const QPolygonF &last_triangle, const QPolygonF &present_triangle, const float &offset ) {

    double diff = UwMath::getDistance(last_triangle.at( 2), present_triangle.at( 2));
    double scale = ( UwMath::getDistance(present_triangle.at( 0), present_triangle.at( 2)) +
                     UwMath::getDistance(present_triangle.at( 0), present_triangle.at( 1)) ) / 2 ;
    double criteria = ( abs(scale) == 0 ) ? offset : offset * scale;

    return diff < criteria;
}
Esempio n. 19
0
void GLUtils::drawPolygon( QPolygonF p )
{
    glBegin(GL_LINE_LOOP);
    {
        for(int i=0;i<p.size();i++)
            glVertex2f(p.at(i).x(),p.at(i).y());
    }
    glEnd();
}
Esempio n. 20
0
double Meshing::computeArea(QPolygonF poly)
{
    if(poly.size()<3) return 0.0;
    double a = QLineF(poly.at(0),poly.at(1)).length();
    double b = QLineF(poly.at(1),poly.at(2)).length();
    double c = QLineF(poly.at(2),poly.at(0)).length();
    double s = (a+b+c)/2;

    return sqrt(s*(s-a)*(s-b)*(s-c));
}
Esempio n. 21
0
void Polygon::_constrainVertex(const QPolygonF& polygon, int i, QPointF& v)
{
    // Weird, but nothing to do.
    if (polygon.size() <= 3)
        return;

    // Save previous position of vertex.
    QPointF prevV = polygon.at(i);

    // Look at the two adjunct segments to vertex i and see if they
    // intersect with any non-adjacent segments.

    // Construct the list of segments (with the new candidate vertex).
    QVector<QLineF> segments = _getSegments(polygon);
    int prev = wrapAround(i - 1, segments.size());
    int next = wrapAround(i + 1, segments.size());
    segments[prev] = QLineF(polygon.at(prev), v);
    segments[i]    = QLineF(v, polygon.at(next));

    // We now stretch segments a little bit to cope with approximation errors.
    for (QVector<QLineF>::Iterator it = segments.begin(); it != segments.end(); ++it)
    {
        QLineF& seg = *it;
        QPointF p1 = seg.p1();
        QPointF p2 = seg.p2();
        seg.setP1( p1 + (p1 - p2) * 0.35f);
        seg.setP2( p2 + (p2 - p1) * 0.35f);
    }

    // For each adjunct segment.
    for (int adj=0; adj<2; adj++)
    {
        int idx = wrapAround(i + adj - 1, segments.size());
        for (int j=0; j<segments.size(); j++)
        {
            // If the segment to compare to is valid (ie. if it is not
            // the segment itself nor an adjacent one) then check for
            // intersection.
            if (j != idx &&
                    j != wrapAround(idx-1, segments.size()) &&
                    j != wrapAround(idx+1, segments.size()))
            {
                QPointF intersection;
                if (segments[idx].intersect(segments[j], &intersection) == QLineF::BoundedIntersection)
                {
                    // Rearrange segments with new position at intersection point.
                    v = intersection;
                    segments[prev] = QLineF(polygon.at(prev), v);
                    segments[i]    = QLineF(v, polygon.at(next));
                }
            }
        }
    }
}
Esempio n. 22
0
bool Meshing::intersects(QPolygonF poly, QLineF line)
{
    for(int i=0;i<poly.size()-1;i++){
        QLineF l(poly.at(i) , poly.at(i+1));
        QPointF p;
        if(l.p1()==line.p1() || l.p1()==line.p2() || l.p2()==line.p1() || l.p2()==line.p2())
            continue;
        if(l.intersect(line,&p)==QLineF::BoundedIntersection){
                return true;
        }
    }
    return false;
}
Esempio n. 23
0
bool GeometryUtilities::intersect(const QPolygonF &polygon, const QLineF &line,
                                  QPointF *intersectionPoint, QLineF *intersectionLine)
{
    for (int i = 0; i <= polygon.size() - 2; ++i) {
        QLineF polygonLine(polygon.at(i), polygon.at(i+1));
        QLineF::IntersectType intersectionType = polygonLine.intersect(line, intersectionPoint);
        if (intersectionType == QLineF::BoundedIntersection) {
            if (intersectionLine)
                *intersectionLine = polygonLine;
            return true;
        }
    }
    return false;
}
Esempio n. 24
0
uint ShadeWidget::colorAt(int x)
{
    generateShade();

    QPolygonF pts = m_hoverPoints->points();
    for (int i=1; i < pts.size(); ++i) {
        if (pts.at(i-1).x() <= x && pts.at(i).x() >= x) {
            QLineF l(pts.at(i-1), pts.at(i));
            l.setLength(l.length() * ((x - l.x1()) / l.dx()));
            return m_shade.pixel(qRound(qMin(l.x2(), (qreal(m_shade.width() - 1)))),
                                 qRound(qMin(l.y2(), qreal(m_shade.height() - 1))));
        }
    }
    return 0;
}
Esempio n. 25
0
bool CalculateLaylines::checkOffset( const QPolygonF &last_triangle, const QPolygonF &present_triangle, const QPointF &destiny, const float &offset ) {

    //The distance between original chackpoint and new checkpoint:
    double diff = UwMath::getDistance(last_triangle.at( 2), present_triangle.at( 2));

    //The distance between boat and the checkpoint divided by the distance between boat
    //and new checkpoint:
    double scale = ( UwMath::getDistance(present_triangle.at( 0), destiny) +
                     UwMath::getDistance(present_triangle.at( 0), present_triangle.at( 1)) ) / 2 ;

    //If scale == 0 it means that original checkpoint and new checkpoint are exactly the same point.
    double criteria = ( abs(scale) == 0 ) ? offset : offset * scale;

    return diff < criteria;
}
Esempio n. 26
0
void CWaveView::drawSquareAroundPoints(const QPolygonF &points)
{
   if (points.size() <= 0 || 0 == m_frame)
   {
      return;
   }

   QPen greenThick;
   greenThick.setColor(Qt::black);
   greenThick.setWidth(1);

   QColor transparentGrey(100, 100, 100, 100);

   QPainter painter(m_frame);
   painter.setPen(greenThick);
   for (int i = 0; i < points.size(); i++)
   {
      QPointF currPt = points.at(i);
      QPointF tl(currPt.x() - 6, currPt.y() - 6);
      QPointF br(currPt.x() + 6, currPt.y() + 6);
      QRectF  rect(tl, br);
      painter.fillRect(rect, transparentGrey);
      painter.drawRect(rect);
   }
   painter.end();
}
Esempio n. 27
0
int Polygon::point(lua_State * L) // ( int index ) const : QPoint
{
	QPolygonF* obj = ValueInstaller2<QPolygonF>::check( L, 1 );
	QPointF* res = ValueInstaller2<QPointF>::create( L );
	*res = obj->at( Util::toInt( L, 2 ) );
	return 1;
}
Esempio n. 28
0
void StyledTextboxView::configureObject(void)
{
  QRectF rect;
  QPolygonF pol;
  QPointF pnt;

  this->__configureObject();
  fold->setBrush(box->brush());
  fold->setPen(box->pen());

  rect=box->boundingRect();
  pol=box->polygon();

  if(rect.height() < fold->boundingRect().height())
    rect.setHeight(fold->boundingRect().height() + (2 * VERT_SPACING));

  this->resizePolygon(pol, rect.width() + fold->boundingRect().width(), rect.height());

  pnt=pol.at(2);
  pol.remove(2);
  pol.insert(2, QPointF(pnt.x(), roundf(pnt.y() - fold->boundingRect().height())));
  pol.insert(3, QPointF(roundf(pnt.x() - fold->boundingRect().width()), pnt.y()));
  box->setPolygon(pol);

  rect=box->boundingRect();
  fold->setPos(rect.width() - fold->boundingRect().width(),
               rect.height() - fold->boundingRect().height());

  this->configureObjectShadow();
  this->configureObjectSelection();
}
Esempio n. 29
0
void VLCStatsView::addValue( float value )
{
    value /= 1000;

    QPolygonF shape = totalbitrateShape->polygon();
    if ( shape.count() > ( STATS_LENGTH + 2 ) ) /* keep only STATS_LENGTH samples */
    {
        shape.remove( 1 );
        for(int i=1; i<( STATS_LENGTH + 2 ); i++)
            ( (QPointF &) shape.at(i) ).setX( i - 1 ); /*move back values*/
    }

    int count = shape.count();
    if ( count == 0 )
    {
        shape << QPointF( 0, 0 ); /* begin and close shape */
        shape << QPointF( count, 0 );
    }

    shape.insert( shape.end() - 1, QPointF( count, value ) );
    ( (QPointF &) shape.last() ).setX( count );
    totalbitrateShape->setPolygon( shape );

    addHistoryValue( value );

    QRectF maxsizes = scene()->itemsBoundingRect();
    maxsizes.setRight( STATS_LENGTH );
    fitInView( maxsizes ); /* fix viewport */
    drawRulers( maxsizes );
}
Esempio n. 30
0
void ClipPainterPrivate::labelPosition(const QPolygonF &polygon, QVector<QPointF> &labelNodes,
                                       LabelPositionFlags labelPositionFlags) const
{
    if ( labelPositionFlags.testFlag( LineCenter ) ) {
        // The Label at the center of the polyline:
        if ( polygon.size() > 0 ) {
            const int labelPosition = polygon.size() / 2; // implied: 0 <= labelPosition < polygon.size()
            labelNodes << polygon.at( labelPosition );
        }
    }

    if ( polygon.size() > 0 && labelPositionFlags.testFlag( LineStart ) ) {
        if ( pointAllowsLabel( polygon.first() ) ) {
            labelNodes << polygon.first();
        }

        // The Label at the start of the polyline:
        for ( int it = 1; it < polygon.size(); ++it ) {
            const bool currentAllowsLabel = pointAllowsLabel(polygon.at(it));

            if ( currentAllowsLabel ) {
                // As polygon.size() > 0 it's ensured that it-1 exists.
                QPointF node = interpolateLabelPoint( polygon.at( it -1 ), polygon.at( it ),
                                                    labelPositionFlags );
                if ( node != QPointF( -1.0, -1.0 ) ) {
                    labelNodes << node;
                }
                break;
            }
        }
    }

    if ( polygon.size() > 1 && labelPositionFlags.testFlag( LineEnd ) ) {
        if ( pointAllowsLabel( polygon.at( polygon.size() - 1 ) ) ) {
            labelNodes << polygon.at( polygon.size() - 1 );
        }

        // The Label at the end of the polyline:
        for ( int it = polygon.size() - 2; it > 0; --it ) {
            const bool currentAllowsLabel = pointAllowsLabel(polygon.at(it));

            if ( currentAllowsLabel ) {
                QPointF node = interpolateLabelPoint( polygon.at( it + 1 ), polygon.at( it ),
                                                    labelPositionFlags );
                if ( node != QPointF( -1.0, -1.0 ) ) {
                    labelNodes << node;
                }
                break;
            }
        }
    }
}