Esempio n. 1
0
void QgsMarkerLineSymbolLayerV2::renderPolylineCentral( const QPolygonF& points, QgsSymbolV2RenderContext& context )
{
  if ( points.size() > 0 )
  {
    // calc length
    qreal length = 0;
    QPolygonF::const_iterator it = points.constBegin();
    QPointF last = *it;
    for ( ++it; it != points.constEnd(); ++it )
    {
      length += sqrt(( last.x() - it->x() ) * ( last.x() - it->x() ) +
                     ( last.y() - it->y() ) * ( last.y() - it->y() ) );
      last = *it;
    }

    // find the segment where the central point lies
    it = points.constBegin();
    last = *it;
    qreal last_at = 0, next_at = 0;
    QPointF next;
    int segment = 0;
    for ( ++it; it != points.constEnd(); ++it )
    {
      next = *it;
      next_at += sqrt(( last.x() - it->x() ) * ( last.x() - it->x() ) +
                      ( last.y() - it->y() ) * ( last.y() - it->y() ) );
      if ( next_at >= length / 2 )
        break; // we have reached the center
      last = *it;
      last_at = next_at;
      segment++;
    }

    // find out the central point on segment
    MyLine l( last, next ); // for line angle
    qreal k = ( length * 0.5 - last_at ) / ( next_at - last_at );
    QPointF pt = last + ( next - last ) * k;

    // draw the marker
    double origAngle = mMarker->angle();
    if ( mRotateMarker )
      mMarker->setAngle( origAngle + l.angle() * 180 / M_PI );
    mMarker->renderPoint( pt, context.feature(), context.renderContext(), -1, context.selected() );
    if ( mRotateMarker )
      mMarker->setAngle( origAngle );
  }
}
Esempio n. 2
0
void ClipPainterPrivate::clipPolyObject ( const QPolygonF & polygon, 
                                          QVector<QPolygonF> & clippedPolyObjects,
                                          bool isClosed )
{
    //	mDebug() << "ClipPainter enabled." ;

    // Only create a new polyObject as soon as we know for sure that 
    // the current point is on the screen. 
    QPolygonF clippedPolyObject = QPolygonF();

    const QVector<QPointF>::const_iterator  itStartPoint = polygon.constBegin();
    const QVector<QPointF>::const_iterator  itEndPoint   = polygon.constEnd();
    QVector<QPointF>::const_iterator        itPoint      = itStartPoint;

    // We use a while loop to be able to cover linestrings as well as linear rings:
    // Linear rings require to tessellate the path from the last node to the first node
    // which isn't really convenient to achieve with a for loop ...

    bool processingLastNode = false;

    while ( itPoint != itEndPoint ) {
        m_currentPoint = (*itPoint);
        // mDebug() << "m_currentPoint.x()" << m_currentPoint.x() << "m_currentPOint.y()" << m_currentPoint.y();

        // Figure out the sector of the current point.
        m_currentSector = sector( m_currentPoint );

        // Initialize the variables related to the previous point.
        if ( itPoint == itStartPoint && processingLastNode == false ) {
            if ( isClosed ) {
                m_previousPoint = polygon.last();

                // Figure out the sector of the previous point.
                m_previousSector = sector( m_previousPoint );
            }
            else {
                m_previousSector = m_currentSector;
            }
        }

        // If the current point reaches a new sector, take care of clipping.
        if ( m_currentSector != m_previousSector ) {
            if ( m_currentSector == 4 || m_previousSector == 4 ) {
                // In this case the current or the previous point is visible on the
                // screen but not both. Hence we only need to clip once and require
                // only one interpolation for both cases.

                clipOnce( clippedPolyObject, clippedPolyObjects, isClosed );
            }
            else {
                // This case mostly deals with lines that reach from one
                // sector that is located off screen to another one that
                // is located off screen. In this situation the line 
                // can get clipped once, twice, or not at all.
                clipMultiple( clippedPolyObject, clippedPolyObjects, isClosed );
            }

            m_previousSector = m_currentSector;
        }

        // If the current point is onscreen, just add it to our final polygon.
        if ( m_currentSector == 4 ) {

            clippedPolyObject << m_currentPoint;
#ifdef MARBLE_DEBUG
            ++(m_debugNodeCount);
#endif
        }

        m_previousPoint = m_currentPoint;

        // Now let's handle the case where we have a (closed) polygon and where the
        // last point of the polyline is outside the viewport and the start point
        // is inside the viewport. This needs special treatment
        if ( processingLastNode ) {
            break;
        }
        ++itPoint;

        if ( itPoint == itEndPoint  && isClosed ) {
            itPoint = itStartPoint;
            processingLastNode = true;
        }
    }

    // Only add the pointer if there's node data available.
    if ( !clippedPolyObject.isEmpty() ) {
        clippedPolyObjects << clippedPolyObject;
    }
}