Exemplo n.º 1
0
MeasureToolPlugin::MeasureToolPlugin( const MarbleModel *marbleModel )
    : RenderPlugin( marbleModel ),
      m_measureLineString( GeoDataLineString( Tessellate ) ),
#ifdef Q_OS_MACX
      m_font_regular( QFont( "Sans Serif", 10, 50, false ) ),
#else
      m_font_regular( QFont( "Sans Serif",  8, 50, false ) ),
#endif
      m_fontascent( QFontMetrics( m_font_regular ).ascent() ),
      m_pen( Qt::red ),
      m_marbleWidget( 0 ),
      m_configDialog( 0 ),
      m_uiConfigWidget( 0 ),
      m_showSegmentLabels( false )
{
    m_pen.setWidthF( 2.0 );
}
Exemplo n.º 2
0
void MeasureToolPlugin::drawSegments( GeoPainter* painter )
{
    for ( int segmentIndex = 0; segmentIndex < m_measureLineString.size() - 1; ++segmentIndex ) {
        GeoDataLineString segment( Tessellate );
        segment << m_measureLineString[segmentIndex] ;
        segment << m_measureLineString[segmentIndex + 1];

        QPen shadowPen( Oxygen::aluminumGray5 );
        shadowPen.setWidthF(4.0);
        painter->setPen( shadowPen );
        painter->drawPolyline( segment );

        QString infoString;

        if ( (m_paintMode == Polygon && m_showDistanceLabel)
             || (m_paintMode == Circular && m_showRadius) ) {
            const qreal segmentLength = segment.length( marbleModel()->planet()->radius() );
            m_radius = segmentLength;

            infoString = meterToPreferredUnit(segmentLength);
        }

        if ( m_showBearingLabel && m_paintMode != Circular ) {
            GeoDataCoordinates coordinates = segment.first();
            qreal bearing = coordinates.bearing( segment.last(), GeoDataCoordinates::Degree );

            if ( bearing < 0 ) {
                bearing += 360;
            }
            QString bearingString = QString::fromUtf8( "%1°" ).arg( bearing, 0, 'f', 2 );
            if ( !infoString.isEmpty() ) {
                infoString.append( "\n" );
            }
            infoString.append( bearingString );
        }

        if ( m_showBearingChangeLabel && segmentIndex != 0 ) {
            GeoDataCoordinates currentCoordinates = m_measureLineString[segmentIndex];
            qreal currentBearing = currentCoordinates.bearing(m_measureLineString[segmentIndex+1]);
            qreal previousBearing = currentCoordinates.bearing( m_measureLineString[segmentIndex-1]);

            GeoDataLinearRing ring;
            painter->setPen( Qt::NoPen );
            painter->setBrush( QBrush ( QColor ( 127, 127, 127, 127 ) ) );

            if (currentBearing < previousBearing) currentBearing += 2 * M_PI;
            ring << currentCoordinates;

            qreal angleLength = qAbs(m_latLonAltBox.north() - m_latLonAltBox.south()) / 20;

            qreal iterBearing = previousBearing;
            while ( iterBearing < currentBearing ) {
                ring << currentCoordinates.moveByBearing( iterBearing, angleLength );;
                iterBearing += 0.1;
            }

            ring << currentCoordinates.moveByBearing( currentBearing, angleLength );;

            painter->drawPolygon( ring );

            qreal currentBearingChange = (currentBearing - previousBearing) * RAD2DEG;
            if (currentBearingChange < 0) currentBearingChange += 360;
            QString bearingChangedString = QString::fromUtf8( "%1°" ).arg( currentBearingChange, 0, 'f', 2 );
            painter->setPen( Qt::black );
            GeoDataCoordinates textPosition = ring.latLonAltBox().center();
            qreal deltaEast = ring.latLonAltBox().east() - currentCoordinates.longitude();
            qreal deltaWest = currentCoordinates.longitude() - ring.latLonAltBox().west();
            if (deltaEast > deltaWest) {
                textPosition.setLongitude(currentCoordinates.longitude() + deltaEast / 2);
            }
            else {
                textPosition.setLongitude(currentCoordinates.longitude() - deltaWest);
            }
            painter->drawText(textPosition, bearingChangedString );
       }

        // Drawing ellipse around 1st point towards the 2nd
        if ( m_paintMode == Circular ) {
            GeoDataCoordinates currentCoordinates = m_measureLineString[segmentIndex];

            GeoDataLinearRing ring;

            // planetRadius - planet radius
            // d - distance between points
            // S - area of the painted circle
            qreal planetRadius = marbleModel()->planet()->radius();
            qreal d = m_measureLineString.length(1);
            m_circularArea = 2 * M_PI * planetRadius * planetRadius * (1 - qCos(d));

            qreal iterBearing = 0;
            while ( iterBearing < 2 * M_PI ) {
                ring << currentCoordinates.moveByBearing(iterBearing, d);
                iterBearing += 0.1;
            }

            painter->setPen( Qt::NoPen );
            painter->setBrush( QBrush ( QColor ( 127, 127, 127, 127 ) ) );
            painter->drawPolygon(ring);

            if ( m_showCircularArea ) {
                painter->setPen(Qt::white);
                GeoDataCoordinates textPosition = ring.latLonAltBox().center();

                QString areaText = tr("Area:\n%1").arg(meterToPreferredUnit(m_circularArea, true));

                QFontMetrics fontMetrics = painter->fontMetrics();
                QRect boundingRect = fontMetrics.boundingRect(QRect(), Qt::AlignCenter, areaText);

                painter->drawText(textPosition,
                                  areaText,
                                  -boundingRect.width()/2, -boundingRect.height()*1.5,
                                  boundingRect.width(), boundingRect.height(),
                                  QTextOption(Qt::AlignCenter));
            }

            if ( m_showCircumference ) {
                painter->setPen(Qt::white);
                GeoDataCoordinates textPosition = ring.latLonAltBox().center();

                m_circumference = 2 * M_PI * planetRadius * qSin(d);

                QString circumferenceText = tr("Circumference:\n%1").arg(meterToPreferredUnit(m_circumference));

                QFontMetrics fontMetrics = painter->fontMetrics();
                QRect boundingRect = fontMetrics.boundingRect(QRect(),Qt::AlignCenter,
                                                              circumferenceText);

                painter->drawText(textPosition,
                                  circumferenceText,
                                  -boundingRect.width()/2, boundingRect.height(),
                                  boundingRect.width(), boundingRect.height(),
                                  QTextOption(Qt::AlignCenter));
            }
        }

        if ( !infoString.isEmpty() ) {
            QPen linePen;

            // have three alternating colors for the segments
            switch ( segmentIndex % 3 ) {
            case 0:
                linePen.setColor( Oxygen::brickRed4 );
                break;
            case 1:
                linePen.setColor( Oxygen::forestGreen4 );
                break;
            case 2:
                linePen.setColor( Oxygen::skyBlue4 );
                break;
            }

            linePen.setWidthF(2.0);
            painter->setPen( linePen );
            painter->drawPolyline( segment, infoString, LineCenter );
        }
    }

    if (m_paintMode == Polygon && m_measureLineString.size() > 2) {
        GeoDataLinearRing measureRing = m_measureLineString;

        if (m_showPolygonArea || m_showPerimeter) {
            painter->setPen( Qt::NoPen );
            painter->setBrush( QBrush ( QColor ( 127, 127, 127, 127 ) ) );
            painter->drawPolygon(measureRing);

            QPen shadowPen( Oxygen::aluminumGray5 );
            shadowPen.setStyle(Qt::DashLine);
            shadowPen.setWidthF(3.0);
            painter->setPen( shadowPen );
            painter->drawPolyline(GeoDataLineString( Tessellate ) << m_measureLineString.first()
                                                      << m_measureLineString.last());
        }

        if (m_showPolygonArea) {
            qreal theta1 = 0.0;
            qreal n = m_measureLineString.size();

            for (int segmentIndex = 1; segmentIndex < m_measureLineString.size()-1; segmentIndex++) {
                GeoDataCoordinates current = m_measureLineString[segmentIndex];
                qreal prevBearing = current.bearing(m_measureLineString[segmentIndex-1]);
                qreal nextBearing = current.bearing(m_measureLineString[segmentIndex+1]);
                if (nextBearing < prevBearing)
                    nextBearing += 2 * M_PI;

                qreal angle = nextBearing - prevBearing;
                theta1 += angle;
            }

            // Traversing first vertex
            GeoDataCoordinates current = m_measureLineString[0];
            qreal prevBearing = current.bearing(m_measureLineString[n-1]);
            qreal nextBearing = current.bearing(m_measureLineString[1]);
            if (nextBearing < prevBearing)
                nextBearing += 2 * M_PI;
            qreal angle = nextBearing - prevBearing;
            theta1 += angle;

            // And the last one
            current = m_measureLineString[n-1];
            prevBearing = current.bearing(m_measureLineString[n-2]);
            nextBearing = current.bearing(m_measureLineString[0]);
            if (nextBearing < prevBearing)
                nextBearing += 2 * M_PI;
            angle = nextBearing - prevBearing;
            theta1 += angle;

            qreal theta2 = 2 * M_PI * n - theta1;

            // theta = smaller of theta1 and theta2
            qreal theta = (theta1 < theta2) ? theta1 : theta2;

            qreal planetRadius = marbleModel()->planet()->radius();
            qreal S = qAbs((theta - (n-2) * M_PI) * planetRadius * planetRadius);
            m_polygonArea = S;

            painter->setPen(Qt::white);
            GeoDataCoordinates textPosition = measureRing.latLonAltBox().center();

            QString areaText = tr("Area:\n%1").arg(meterToPreferredUnit(S, true));

            QFontMetrics fontMetrics = painter->fontMetrics();
            QRect boundingRect = fontMetrics.boundingRect(QRect(), Qt::AlignCenter, areaText);

            painter->drawText(textPosition,
                              areaText,
                              -boundingRect.width()/2, -(boundingRect.height()+fontMetrics.height()*0.25),
                              boundingRect.width(), boundingRect.height(),
                              QTextOption(Qt::AlignCenter));
        }

        if (m_showPerimeter) {
            painter->setPen(Qt::white);
            GeoDataCoordinates textPosition = measureRing.latLonAltBox().center();

            qreal P = measureRing.length(marbleModel()->planet()->radius());
            m_perimeter = P;
            QString perimeterText = tr("Perimeter:\n%1").arg(meterToPreferredUnit(P));

            QFontMetrics fontMetrics = painter->fontMetrics();
            QRect boundingRect = fontMetrics.boundingRect(QRect(),Qt::AlignCenter,
                                                          perimeterText);

            painter->drawText(textPosition,
                              perimeterText,
                              -boundingRect.width()/2, 0,
                              boundingRect.width(), boundingRect.height(),
                              QTextOption(Qt::AlignCenter));
        }
    }
}