File indexing completed on 2025-01-05 03:59:24

0001 // SPDX-License-Identifier: LGPL-2.1-or-later
0002 //
0003 // SPDX-FileCopyrightText: 2009 Torsten Rahn <tackat@kde.org>
0004 //
0005 
0006 #include "GraticulePlugin.h"
0007 
0008 // Qt includes
0009 
0010 #include <QPushButton>
0011 #include <QRect>
0012 #include <QColor>
0013 #include <QBrush>
0014 #include <QDebug>
0015 
0016 #include <klocalizedstring.h>
0017 
0018 #include "ui_GraticuleConfigWidget.h"
0019 #include "MarbleDirs.h"
0020 #include "GeoPainter.h"
0021 #include "GeoDataLineString.h"
0022 #include "Planet.h"
0023 #include "MarbleModel.h"
0024 #include "ViewportParams.h"
0025 #include "digikam_debug.h"
0026 
0027 namespace Marble
0028 {
0029 
0030 GraticulePlugin::GraticulePlugin()
0031     : RenderPlugin( nullptr ),
0032       m_showPrimaryLabels( true ),
0033       m_showSecondaryLabels( true ),
0034       m_isInitialized( false ),
0035       ui_configWidget( nullptr ),
0036       m_configDialog( nullptr )
0037 {
0038 }
0039 
0040 GraticulePlugin::GraticulePlugin( const MarbleModel *marbleModel )
0041     : RenderPlugin( marbleModel ),
0042       m_equatorCirclePen( Qt::yellow ),
0043       m_tropicsCirclePen( Qt::yellow ),
0044       m_gridCirclePen( Qt::white ),
0045       m_showPrimaryLabels( true ),
0046       m_showSecondaryLabels( true ),
0047       m_isInitialized( false ),
0048       ui_configWidget( nullptr ),
0049       m_configDialog( nullptr )
0050 {
0051 }
0052 
0053 QStringList GraticulePlugin::backendTypes() const
0054 {
0055     return QStringList(QStringLiteral("graticule"));
0056 }
0057 
0058 QString GraticulePlugin::renderPolicy() const
0059 {
0060     return QStringLiteral("ALWAYS");
0061 }
0062 
0063 QStringList GraticulePlugin::renderPosition() const
0064 {
0065     return QStringList(QStringLiteral("GRATICULE"));
0066 }
0067 
0068 QString GraticulePlugin::name() const
0069 {
0070     return i18n( "Coordinate Grid" );
0071 }
0072 
0073 QString GraticulePlugin::guiString() const
0074 {
0075     return i18n( "Coordinate &Grid" );
0076 }
0077 
0078 QString GraticulePlugin::nameId() const
0079 {
0080     return QStringLiteral("coordinate-grid");
0081 }
0082 
0083 QString GraticulePlugin::version() const
0084 {
0085     return QStringLiteral("1.0");
0086 }
0087 
0088 QString GraticulePlugin::description() const
0089 {
0090     return i18n( "A plugin that shows a coordinate grid over the map." );
0091 }
0092 
0093 QString GraticulePlugin::copyrightYears() const
0094 {
0095     return QStringLiteral("2009");
0096 }
0097 
0098 QVector<PluginAuthor> GraticulePlugin::pluginAuthors() const
0099 {
0100     return QVector<PluginAuthor>()
0101             << PluginAuthor(QStringLiteral("Torsten Rahn"), QStringLiteral("tackat@kde.org"));
0102 }
0103 
0104 QIcon GraticulePlugin::icon () const
0105 {
0106     return QIcon::fromTheme(QStringLiteral("coordinate"));
0107 }
0108 
0109 void GraticulePlugin::initialize ()
0110 {
0111     // Initialize range maps that map the zoom to the number of coordinate grid lines.
0112 
0113     initLineMaps( GeoDataCoordinates::defaultNotation() );
0114 
0115     m_isInitialized = true;
0116 }
0117 
0118 bool GraticulePlugin::isInitialized () const
0119 {
0120     return m_isInitialized;
0121 }
0122 
0123 QDialog *GraticulePlugin::configDialog()
0124 {
0125     if ( !m_configDialog ) {
0126         m_configDialog = new QDialog();
0127         ui_configWidget = new Ui::GraticuleConfigWidget;
0128         ui_configWidget->setupUi( m_configDialog );
0129 
0130         connect( ui_configWidget->gridPushButton, SIGNAL(clicked()), this,
0131                 SLOT(gridGetColor()) );
0132 
0133         connect( ui_configWidget->tropicsPushButton, SIGNAL(clicked()), this,
0134                 SLOT(tropicsGetColor()) );
0135 
0136         connect( ui_configWidget->equatorPushButton, SIGNAL(clicked()), this,
0137                 SLOT(equatorGetColor()) );
0138 
0139         connect( ui_configWidget->m_buttonBox, SIGNAL(accepted()), this,
0140                 SLOT(writeSettings()) );
0141 
0142         connect( ui_configWidget->m_buttonBox->button( QDialogButtonBox::Reset ), SIGNAL(clicked()),
0143                  SLOT(restoreDefaultSettings()) );
0144 
0145         QPushButton *applyButton = ui_configWidget->m_buttonBox->button( QDialogButtonBox::Apply );
0146 
0147         connect( applyButton, SIGNAL(clicked()),
0148                  this,        SLOT(writeSettings()) );
0149     }
0150 
0151     readSettings();
0152 
0153     return m_configDialog;
0154 }
0155 
0156 QHash<QString,QVariant> GraticulePlugin::settings() const
0157 {
0158     QHash<QString, QVariant> settings = RenderPlugin::settings();
0159 
0160     settings.insert(QStringLiteral("gridColor"), m_gridCirclePen.color().name());
0161     settings.insert(QStringLiteral("tropicsColor"), m_tropicsCirclePen.color().name());
0162     settings.insert(QStringLiteral("equatorColor"), m_equatorCirclePen.color().name());
0163     settings.insert(QStringLiteral("primaryLabels"), m_showPrimaryLabels);
0164     settings.insert(QStringLiteral("secondaryLabels"), m_showSecondaryLabels);
0165 
0166     return settings;
0167 }
0168 
0169 void GraticulePlugin::setSettings( const QHash<QString,QVariant> &settings )
0170 {
0171     RenderPlugin::setSettings( settings );
0172 
0173     const QColor gridColor = settings.value(QStringLiteral("gridColor"), QColor(Qt::white)).value<QColor>();
0174     const QColor tropicsColor = settings.value(QStringLiteral("tropicsColor"), QColor(Qt::yellow)).value<QColor>();
0175     const QColor equatorColor = settings.value(QStringLiteral("equatorColor"), QColor(Qt::yellow)).value<QColor>();
0176     bool primaryLabels = settings.value(QStringLiteral("primaryLabels"), true).toBool();
0177     bool secondaryLabels = settings.value(QStringLiteral("secondaryLabels"), true).toBool();
0178 
0179     m_gridCirclePen.setColor( gridColor );
0180     m_tropicsCirclePen.setColor( tropicsColor );
0181     m_equatorCirclePen.setColor( equatorColor );
0182 
0183     m_showPrimaryLabels = primaryLabels;
0184     m_showSecondaryLabels = secondaryLabels;
0185 
0186     readSettings();
0187 }
0188 
0189 void GraticulePlugin::readSettings()
0190 {
0191     if ( !m_configDialog )
0192         return;
0193 
0194     QPalette gridPalette;
0195     gridPalette.setColor( QPalette::Button, m_gridCirclePen.color() );
0196     ui_configWidget->gridPushButton->setPalette( gridPalette );
0197 
0198     QPalette tropicsPalette;
0199     tropicsPalette.setColor( QPalette::Button, m_tropicsCirclePen.color() );
0200     ui_configWidget->tropicsPushButton->setPalette( tropicsPalette );
0201 
0202 
0203     QPalette equatorPalette;
0204     equatorPalette.setColor( QPalette::Button, m_equatorCirclePen.color() );
0205     ui_configWidget->equatorPushButton->setPalette( equatorPalette );
0206     ui_configWidget->primaryCheckBox->setChecked( m_showPrimaryLabels );
0207     ui_configWidget->secondaryCheckBox->setChecked( m_showSecondaryLabels );
0208 }
0209 
0210 void GraticulePlugin::gridGetColor()
0211 {
0212     const QColor c = QColorDialog::getColor( m_gridCirclePen.color(), nullptr, i18n("Please choose the color for the coordinate grid.") );
0213 
0214     if ( c.isValid() ) {
0215         QPalette palette = ui_configWidget->gridPushButton->palette();
0216         palette.setColor( QPalette::Button, c );
0217         ui_configWidget->gridPushButton->setPalette( palette );
0218     }
0219 }
0220 
0221 void GraticulePlugin::tropicsGetColor()
0222 {
0223     const QColor c = QColorDialog::getColor( m_tropicsCirclePen.color(), nullptr, i18n("Please choose the color for the tropic circles.") );
0224 
0225     if ( c.isValid() ) {
0226         QPalette palette = ui_configWidget->tropicsPushButton->palette();
0227         palette.setColor( QPalette::Button, c );
0228         ui_configWidget->tropicsPushButton->setPalette( palette );
0229     }
0230 }
0231 
0232 void GraticulePlugin::equatorGetColor()
0233 {
0234     const QColor c = QColorDialog::getColor( m_equatorCirclePen.color(), nullptr, i18n("Please choose the color for the equator.") );
0235 
0236     if ( c.isValid() ) {
0237         QPalette palette = ui_configWidget->equatorPushButton->palette();
0238         palette.setColor( QPalette::Button, c );
0239         ui_configWidget->equatorPushButton->setPalette( palette );
0240     }
0241 }
0242 
0243 void GraticulePlugin::writeSettings()
0244 {
0245     m_equatorCirclePen.setColor( ui_configWidget->equatorPushButton->palette().color( QPalette::Button ) );
0246     m_tropicsCirclePen.setColor( ui_configWidget->tropicsPushButton->palette().color( QPalette::Button ) );
0247     m_gridCirclePen.setColor( ui_configWidget->gridPushButton->palette().color( QPalette::Button) );
0248     m_showPrimaryLabels = ui_configWidget->primaryCheckBox->isChecked();
0249     m_showSecondaryLabels = ui_configWidget->secondaryCheckBox->isChecked();
0250 
0251     Q_EMIT settingsChanged( nameId() );
0252 }
0253 
0254 bool GraticulePlugin::render( GeoPainter *painter, ViewportParams *viewport,
0255                               const QString& renderPos,
0256                               GeoSceneLayer * layer )
0257 {
0258     Q_UNUSED( layer )
0259     Q_UNUSED( renderPos )
0260 
0261     if ( m_currentNotation != GeoDataCoordinates::defaultNotation() ) {
0262         initLineMaps( GeoDataCoordinates::defaultNotation() );
0263     }
0264 
0265     // Setting the label font for the coordinate lines.
0266 
0267 #ifdef Q_OS_MACX
0268 
0269     int defaultFontSize = 10;
0270 
0271 #else
0272 
0273     int defaultFontSize = 8;
0274 
0275 #endif
0276 
0277     QFont gridFont(QLatin1String("Sans Serif"));
0278     gridFont.setPointSize( defaultFontSize );
0279     gridFont.setBold( true );
0280 
0281     painter->save();
0282 
0283     painter->setFont( gridFont );
0284 
0285     renderGrid( painter, viewport, m_equatorCirclePen, m_tropicsCirclePen, m_gridCirclePen );
0286 
0287     painter->restore();
0288 
0289     return true;
0290 }
0291 
0292 qreal GraticulePlugin::zValue() const
0293 {
0294     return 1.0;
0295 }
0296 
0297 void GraticulePlugin::renderGrid( GeoPainter *painter, ViewportParams *viewport,
0298                                   const QPen& equatorCirclePen,
0299                                   const QPen& tropicsCirclePen,
0300                                   const QPen& gridCirclePen )
0301 {
0302     GeoDataLatLonAltBox viewLatLonAltBox = viewport->viewLatLonAltBox();
0303 
0304     painter->setPen( equatorCirclePen );
0305 
0306     LabelPositionFlags mainPosition(NoLabel);
0307 
0308     if ( m_showPrimaryLabels ) {
0309         mainPosition = LineCenter;
0310     }
0311 
0312     // Render the equator
0313 
0314     renderLatitudeLine( painter, 0.0, viewLatLonAltBox, i18n( "Equator" ), mainPosition );
0315 
0316     // Render the Prime Meridian and Antimeridian
0317     GeoDataCoordinates::Notation notation = GeoDataCoordinates::defaultNotation();
0318     if (marbleModel()->planet()->id() != QLatin1String("sky") && notation != GeoDataCoordinates::Astro) {
0319         renderLongitudeLine( painter, 0.0, viewLatLonAltBox, 0.0, 0.0, i18n( "Prime Meridian" ), mainPosition );
0320         renderLongitudeLine( painter, 180.0, viewLatLonAltBox, 0.0, 0.0, i18n( "Antimeridian" ), mainPosition );
0321     }
0322 
0323     painter->setPen( gridCirclePen );
0324     // painter->setPen( QPen( QBrush( Qt::white ), 0.75 ) );
0325 
0326     // Render UTM grid zones
0327     if ( m_currentNotation == GeoDataCoordinates::UTM ) {
0328         renderLatitudeLine( painter, 84.0, viewLatLonAltBox );
0329 
0330         renderLongitudeLines( painter, viewLatLonAltBox,
0331                     6.0, 0.0,
0332                     18.0, 154.0, LineEnd | IgnoreXMargin );
0333         renderLongitudeLines( painter, viewLatLonAltBox,
0334                     6.0, 0.0,
0335                     34.0, 10.0, LineStart | IgnoreXMargin );
0336 
0337         // Paint longitudes with exceptions
0338         renderLongitudeLines( painter, viewLatLonAltBox,
0339                     6.0, 0.0,
0340                     6.0, 162.0, LineEnd | IgnoreXMargin );
0341         renderLongitudeLines( painter, viewLatLonAltBox,
0342                     6.0, 0.0,
0343                     26.0, 146.0, LineEnd | IgnoreXMargin  );
0344 
0345         renderLatitudeLines( painter, viewLatLonAltBox, 8.0, 0.0 /*,
0346                              LineStart | IgnoreYMargin */ );
0347 
0348         return;
0349     }
0350 
0351     // Render the normal grid
0352 
0353     // calculate the angular distance between coordinate lines of the normal grid
0354     qreal normalDegreeStep = 360.0 / m_normalLineMap.lowerBound(viewport->radius()).value();
0355 
0356     LabelPositionFlags labelXPosition(NoLabel), labelYPosition(NoLabel);
0357     if ( m_showSecondaryLabels ) {
0358         labelXPosition = LineStart | IgnoreXMargin;
0359         labelYPosition = LineStart | IgnoreYMargin;
0360     }
0361     qreal boldDegreeStep = 360.0 / m_boldLineMap.lowerBound(viewport->radius()).value();
0362     renderLongitudeLines( painter, viewLatLonAltBox,
0363                           normalDegreeStep, boldDegreeStep,
0364                           normalDegreeStep, normalDegreeStep,
0365                           labelXPosition );
0366     renderLatitudeLines(  painter, viewLatLonAltBox, normalDegreeStep, boldDegreeStep,
0367                           labelYPosition );
0368 
0369     // Render some non-cut off longitude lines ..
0370     renderLongitudeLine( painter, +90.0, viewLatLonAltBox );
0371     renderLongitudeLine( painter, -90.0, viewLatLonAltBox );
0372 
0373     // Render the bold grid
0374 
0375     if (    painter->mapQuality() == HighQuality
0376          || painter->mapQuality() == PrintQuality ) {
0377 
0378         QPen boldPen = gridCirclePen;
0379         boldPen.setWidthF( 2.0 );
0380         painter->setPen( boldPen );
0381     }
0382 
0383     // calculate the angular distance between coordinate lines of the bold grid
0384 
0385     renderLongitudeLines( painter, viewLatLonAltBox,
0386                         boldDegreeStep, 0.0,
0387                         normalDegreeStep, normalDegreeStep,
0388                         NoLabel
0389                         );
0390 
0391     renderLatitudeLines(  painter, viewLatLonAltBox, boldDegreeStep, 0.0,
0392                         NoLabel );
0393 
0394     QPen tropicsPen = tropicsCirclePen;
0395     if (   painter->mapQuality() != OutlineQuality
0396         && painter->mapQuality() != LowQuality ) {
0397         tropicsPen.setStyle( Qt::DotLine );
0398     }
0399     painter->setPen( tropicsPen );
0400 
0401     // Determine the planet's axial tilt
0402     qreal axialTilt = RAD2DEG * marbleModel()->planet()->epsilon();
0403 
0404     if ( axialTilt > 0 ) {
0405         // Render the tropics
0406         renderLatitudeLine( painter, +axialTilt, viewLatLonAltBox, i18n( "Tropic of Cancer" ), mainPosition  );
0407         renderLatitudeLine( painter, -axialTilt, viewLatLonAltBox, i18n( "Tropic of Capricorn" ), mainPosition );
0408 
0409         // Render the arctics
0410         renderLatitudeLine( painter, +90.0 - axialTilt, viewLatLonAltBox, i18n( "Arctic Circle" ), mainPosition );
0411         renderLatitudeLine( painter, -90.0 + axialTilt, viewLatLonAltBox, i18n( "Antarctic Circle" ), mainPosition );
0412     }
0413 }
0414 
0415 void GraticulePlugin::renderLatitudeLine( GeoPainter *painter, qreal latitude,
0416                                           const GeoDataLatLonAltBox& viewLatLonAltBox,
0417                                           const QString& lineLabel,
0418                                           LabelPositionFlags labelPositionFlags )
0419 {
0420     qreal fromSouthLat = viewLatLonAltBox.south( GeoDataCoordinates::Degree );
0421     qreal toNorthLat   = viewLatLonAltBox.north( GeoDataCoordinates::Degree );
0422 
0423     // Coordinate line is not displayed inside the viewport
0424     if ( latitude < fromSouthLat || toNorthLat < latitude ) {
0425         // mDebug() << "Lat: Out of View";
0426         return;
0427     }
0428 
0429     GeoDataLineString line( Tessellate | RespectLatitudeCircle ) ;
0430 
0431     qreal fromWestLon = viewLatLonAltBox.west( GeoDataCoordinates::Degree );
0432     qreal toEastLon   = viewLatLonAltBox.east( GeoDataCoordinates::Degree );
0433 
0434     if ( fromWestLon < toEastLon ) {
0435         qreal step = ( toEastLon - fromWestLon ) * 0.25;
0436 
0437         for ( int i = 0; i < 5; ++i ) {
0438             line << GeoDataCoordinates( fromWestLon + i * step, latitude, 0.0, GeoDataCoordinates::Degree );
0439         }
0440     }
0441     else {
0442         qreal step = ( +180.0 - toEastLon ) * 0.25;
0443 
0444         for ( int i = 0; i < 5; ++i ) {
0445             line << GeoDataCoordinates( toEastLon + i * step, latitude, 0.0, GeoDataCoordinates::Degree );
0446         }
0447 
0448         step = ( +180 + fromWestLon ) * 0.25;
0449 
0450         for ( int i = 0; i < 5; ++i ) {
0451             line << GeoDataCoordinates( -180 + i * step, latitude, 0.0, GeoDataCoordinates::Degree );
0452         }
0453     }
0454 
0455     painter->drawPolyline( line, lineLabel, labelPositionFlags, painter->pen().color() );
0456 }
0457 
0458 void GraticulePlugin::renderLongitudeLine( GeoPainter *painter, qreal longitude,
0459                                            const GeoDataLatLonAltBox& viewLatLonAltBox,
0460                                            qreal northPolarGap, qreal southPolarGap,
0461                                            const QString& lineLabel,
0462                                            LabelPositionFlags labelPositionFlags )
0463 {
0464     const qreal fromWestLon = viewLatLonAltBox.west();
0465     const qreal toEastLon   = viewLatLonAltBox.east();
0466 
0467     // Coordinate line is not displayed inside the viewport
0468 
0469     if ( ( !viewLatLonAltBox.crossesDateLine()
0470            && ( longitude * DEG2RAD < fromWestLon || toEastLon < longitude * DEG2RAD ) ) ||
0471          (  viewLatLonAltBox.crossesDateLine() &&
0472             longitude * DEG2RAD < toEastLon && fromWestLon < longitude * DEG2RAD &&
0473             fromWestLon != -M_PI && toEastLon != +M_PI )
0474        ) {
0475         // mDebug() << "Lon: Out of View:" << viewLatLonAltBox.toString() << " Crossing: "<< viewLatLonAltBox.crossesDateLine() << "Longitude: " << longitude;
0476         return;
0477     }
0478 
0479     qreal fromSouthLat = viewLatLonAltBox.south( GeoDataCoordinates::Degree );
0480     qreal toNorthLat   = viewLatLonAltBox.north( GeoDataCoordinates::Degree );
0481 
0482     qreal southLat = ( fromSouthLat < -90.0 + southPolarGap ) ? -90.0 + southPolarGap : fromSouthLat;
0483     qreal northLat = ( toNorthLat   > +90.0 - northPolarGap ) ? +90.0 - northPolarGap : toNorthLat;
0484 
0485     GeoDataCoordinates n1( longitude, southLat, 0.0, GeoDataCoordinates::Degree );
0486     GeoDataCoordinates n3( longitude, northLat, 0.0, GeoDataCoordinates::Degree );
0487 
0488     GeoDataLineString line( Tessellate );
0489 
0490     if ( northLat > 0 && southLat < 0 )
0491     {
0492         GeoDataCoordinates n2( longitude, 0.0, 0.0, GeoDataCoordinates::Degree );
0493         line << n1 << n2 << n3;
0494     }
0495     else {
0496         line << n1 << n3;
0497     }
0498 
0499     painter->drawPolyline( line, lineLabel, labelPositionFlags, painter->pen().color() );
0500 }
0501 
0502 void GraticulePlugin::renderLatitudeLines( GeoPainter *painter,
0503                                            const GeoDataLatLonAltBox& viewLatLonAltBox,
0504                                            qreal step, qreal skipStep,
0505                                            LabelPositionFlags labelPositionFlags
0506                                          )
0507 {
0508     if ( step <= 0 ) {
0509         return;
0510     }
0511 
0512     // Latitude
0513     qreal southLat = viewLatLonAltBox.south( GeoDataCoordinates::Degree );
0514     qreal northLat = viewLatLonAltBox.north( GeoDataCoordinates::Degree );
0515 
0516     qreal southLineLat = step * static_cast<int>( southLat / step );
0517     qreal northLineLat = step * ( static_cast<int>( northLat / step ) + 1 );
0518 
0519     if ( m_currentNotation == GeoDataCoordinates::UTM ) {
0520         if ( northLineLat > 84.0 ) {
0521             northLineLat = 76.0;
0522         }
0523 
0524         if ( southLineLat < -80.0 ) {
0525             southLineLat = -80.0;
0526         }
0527     }
0528 
0529     qreal itStep = southLineLat;
0530 
0531     GeoDataCoordinates::Notation notation = GeoDataCoordinates::defaultNotation();
0532 
0533     while ( itStep < northLineLat ) {
0534         // Create a matching label
0535         QString label = GeoDataCoordinates::latToString( itStep, notation,
0536                                  GeoDataCoordinates::Degree, -1, 'g' );
0537 
0538         // No additional labels for the equator
0539         if ( labelPositionFlags.testFlag( LineCenter ) && itStep == 0.0 ) {
0540             label.clear();
0541         }
0542 
0543         // Paint all latitude coordinate lines except for the equator
0544         if ( itStep != 0.0 && fmod(itStep, skipStep) != 0 ) {
0545             renderLatitudeLine( painter, itStep, viewLatLonAltBox, label, labelPositionFlags );
0546         }
0547 
0548         itStep += step;
0549     }
0550 }
0551 
0552 
0553 void GraticulePlugin::renderUtmExceptions( GeoPainter *painter,
0554                                             const GeoDataLatLonAltBox& viewLatLonAltBox,
0555                                             qreal itStep, qreal northPolarGap, qreal southPolarGap,
0556                                             const QString & label,
0557                                             LabelPositionFlags labelPositionFlags )
0558 {
0559     // This code renders the so called "exceptions" in the UTM coordinate grid
0560     // See: https://en.wikipedia.org/wiki/Universal_Transverse_Mercator_coordinate_system#Exceptions
0561     if ( northPolarGap == 6.0 && southPolarGap == 162.0) {
0562         if (label == QLatin1String("33")) {
0563             renderLongitudeLine( painter, itStep-3.0, viewLatLonAltBox, northPolarGap,
0564             southPolarGap, label, labelPositionFlags );
0565         } else if (label == QLatin1String("35")) {
0566             renderLongitudeLine( painter, itStep-3.0, viewLatLonAltBox, northPolarGap,
0567             southPolarGap, label, labelPositionFlags );
0568         } else if (label == QLatin1String("37")) {
0569             renderLongitudeLine( painter, itStep-3.0, viewLatLonAltBox, northPolarGap,
0570             southPolarGap, label, labelPositionFlags );
0571         } else if (label == QLatin1String("32") || label == QLatin1String("34") || label == QLatin1String("36")) {
0572             // paint nothing
0573         } else {
0574             renderLongitudeLine( painter, itStep, viewLatLonAltBox, northPolarGap,
0575             southPolarGap, label, labelPositionFlags );
0576         }
0577     }
0578     else if ( northPolarGap == 26.0 && southPolarGap == 146.0 ) {
0579         if (label == QLatin1String("32")) {
0580             renderLongitudeLine( painter, itStep-3.0, viewLatLonAltBox, northPolarGap,
0581             southPolarGap, label, labelPositionFlags );
0582         } else {
0583             renderLongitudeLine( painter, itStep, viewLatLonAltBox, northPolarGap,
0584             southPolarGap, label, labelPositionFlags );
0585         }
0586     }
0587     else {
0588         renderLongitudeLine( painter, itStep, viewLatLonAltBox, northPolarGap,
0589         southPolarGap, label, labelPositionFlags );
0590     }
0591 }
0592 
0593 void GraticulePlugin::renderLongitudeLines( GeoPainter *painter,
0594                                             const GeoDataLatLonAltBox& viewLatLonAltBox,
0595                                             qreal step, qreal skipStep,
0596                                             qreal northPolarGap, qreal southPolarGap,
0597                                             LabelPositionFlags labelPositionFlags) const
0598 {
0599     if ( step <= 0 ) {
0600         return;
0601     }
0602 
0603     const bool isSky = (marbleModel()->planet()->id() == QLatin1String("sky"));
0604     const GeoDataCoordinates::Notation notation = isSky ? GeoDataCoordinates::Astro : GeoDataCoordinates::defaultNotation();
0605 
0606     // Set precision to 0 in UTM in order to show only zone number.
0607     int precision = (notation == GeoDataCoordinates::UTM) ? 0 : -1;
0608 
0609     // Longitude
0610     qreal westLon = viewLatLonAltBox.west( GeoDataCoordinates::Degree );
0611     qreal eastLon = viewLatLonAltBox.east( GeoDataCoordinates::Degree );
0612 
0613     qreal westLineLon = step * static_cast<int>( westLon / step );
0614     qreal eastLineLon = step * ( static_cast<int>( eastLon / step ) + 1 );
0615 
0616     if ( !viewLatLonAltBox.crossesDateLine() ||
0617          ( westLon == -180.0 && eastLon == +180.0 ) ) {
0618         qreal itStep = westLineLon;
0619 
0620         while ( itStep < eastLineLon ) {
0621             // Create a matching label
0622             QString label = GeoDataCoordinates::lonToString( itStep,
0623                                   notation, GeoDataCoordinates::Degree,
0624                                   precision, 'g' );
0625 
0626             // No additional labels for the prime meridian and the antimeridian
0627 
0628             if ( labelPositionFlags.testFlag( LineCenter ) && ( itStep == 0.0 || itStep == 180.0 || itStep == -180.0 ) )
0629             {
0630                 label.clear();
0631             }
0632 
0633             // Paint all longitude coordinate lines (except for the meridians in non-UTM mode)
0634             if (notation == GeoDataCoordinates::UTM ) {
0635                 renderUtmExceptions( painter, viewLatLonAltBox, itStep, northPolarGap,
0636                 southPolarGap, label, labelPositionFlags );
0637             } else if ( itStep != 0.0 && itStep != 180.0 && itStep != -180.0 ) {
0638                 if (fmod(itStep, skipStep) != 0 || skipStep == 0.0) {
0639                     renderLongitudeLine( painter, itStep, viewLatLonAltBox, northPolarGap,
0640                     southPolarGap, label, labelPositionFlags );
0641                 }
0642             }
0643             itStep += step;
0644         }
0645     }
0646     else {
0647         qreal itStep = eastLineLon;
0648 
0649         while ( itStep < 180.0 ) {
0650             // Create a matching label
0651             QString label = GeoDataCoordinates::lonToString( itStep,
0652                                   notation, GeoDataCoordinates::Degree,
0653                                   precision, 'g' );
0654 
0655             // No additional labels for the prime meridian and the antimeridian
0656 
0657             if ( labelPositionFlags.testFlag( LineCenter ) && ( itStep == 0.0 || itStep == 180.0 || itStep == -180.0 ) )
0658             {
0659                 label.clear();
0660             }
0661 
0662             // Paint all longitude coordinate lines (except for the meridians in non-UTM mode)
0663             if (notation == GeoDataCoordinates::UTM ) {
0664                 renderUtmExceptions( painter, viewLatLonAltBox, itStep, northPolarGap,
0665                 southPolarGap, label, labelPositionFlags );
0666             } else if ( itStep != 0.0 && itStep != 180.0 && itStep != -180.0 ) {
0667                 if (fmod((itStep), skipStep) != 0 || skipStep == 0.0) {
0668                     renderLongitudeLine( painter, itStep, viewLatLonAltBox, northPolarGap,
0669                     southPolarGap, label, labelPositionFlags );
0670                 }
0671             }
0672             itStep += step;
0673         }
0674 
0675         itStep = -180.0;
0676 
0677         while ( itStep < westLineLon ) {
0678             // Create a matching label
0679             QString label = GeoDataCoordinates::lonToString( itStep,
0680                                   notation, GeoDataCoordinates::Degree,
0681                                   precision, 'g' );
0682 
0683             // No additional labels for the prime meridian and the antimeridian
0684             if ( labelPositionFlags.testFlag( LineCenter ) && ( itStep == 0.0 || itStep == 180.0 || itStep == -180.0 ) )
0685             {
0686                 label.clear();
0687             }
0688 
0689             // Paint all longitude coordinate lines (except for the meridians in non-UTM mode)
0690             if (notation == GeoDataCoordinates::UTM ) {
0691                 renderUtmExceptions( painter, viewLatLonAltBox, itStep, northPolarGap,
0692                 southPolarGap, label, labelPositionFlags );
0693             } else if ( itStep != 0.0 && itStep != 180.0 && itStep != -180.0 ) {
0694                 if (fmod((itStep+180), skipStep) != 0 || skipStep == 0.0) {
0695                     renderLongitudeLine( painter, itStep, viewLatLonAltBox, northPolarGap,
0696                     southPolarGap, label, labelPositionFlags );
0697                 }
0698             }
0699             itStep += step;
0700         }
0701     }
0702 }
0703 
0704 void GraticulePlugin::initLineMaps( GeoDataCoordinates::Notation notation)
0705 {
0706     /* Define Upper Bound keys and associated values:
0707        The key number is the globe radius in pixel.
0708        The value number is the amount of grid lines for the full range.
0709 
0710        Example: up to a 100 pixel radius the globe is covered
0711        with 4 longitude lines (4 half-circles).
0712      */
0713 
0714     if (marbleModel()->planet()->id() == QLatin1String("sky") ||
0715         notation == GeoDataCoordinates::Astro) {
0716         m_normalLineMap[100]     = 4;          // 6h
0717         m_normalLineMap[1000]    = 12;          // 2h
0718         m_normalLineMap[2000]   = 24;         // 1h
0719         m_normalLineMap[4000]   = 48;         // 30 min
0720         m_normalLineMap[8000]   = 96;         // 15 min
0721         m_normalLineMap[16000]  = 288;        // 5 min
0722         m_normalLineMap[100000]  = 24 * 60;     // 1 min
0723         m_normalLineMap[200000]  = 24 * 60 * 2; // 30 sec
0724         m_normalLineMap[400000]  = 24 * 60 * 4; // 15 sec
0725         m_normalLineMap[1200000] = 24 * 60 * 12; // 5 sec
0726         m_normalLineMap[6000000] = 24 * 60 * 60; // 1 sec
0727         m_normalLineMap[12000000] = 24 * 60 * 60 * 2; // 0.5 sec
0728         m_normalLineMap[24000000] = 24 * 60 * 60 * 4; // 0.25 sec
0729 
0730         m_boldLineMap[1000]     = 0;        // 0h
0731         m_boldLineMap[2000]    = 4;         //  6h
0732         m_boldLineMap[16000]    = 24;       //  30 deg
0733         return;
0734     }
0735 
0736     m_normalLineMap[100]     = 4;          // 90 deg
0737     m_normalLineMap[1000]    = 12;          // 30 deg
0738     m_normalLineMap[4000]   = 36;         // 10 deg
0739     m_normalLineMap[16000]   = 72;         // 5 deg
0740     m_normalLineMap[64000]  = 360;         //  1 deg
0741     m_normalLineMap[128000] = 720;        //  0.5 deg
0742 
0743     m_boldLineMap[1000]     = 0;         //  0 deg
0744     m_boldLineMap[4000]    = 12;         //  30 deg
0745     m_boldLineMap[16000]   = 36;         //  10 deg
0746 
0747     switch ( notation )
0748     {
0749         case GeoDataCoordinates::Decimal :
0750 
0751             m_normalLineMap[512000]  = 360 * 10;       //  0.1 deg
0752             m_normalLineMap[2048000] = 360 * 20;       //  0.05 deg
0753             m_normalLineMap[8192000] = 360 * 100;      //  0.01 deg
0754             m_normalLineMap[16384000] = 360 * 200;      //  0.005 deg
0755             m_normalLineMap[32768000] = 360 * 1000;    //  0.001 deg
0756             m_normalLineMap[131072000] = 360 * 2000;    //  0.0005 deg
0757             m_normalLineMap[524288000] = 360 * 10000;  //  0.00001 deg
0758 
0759             m_boldLineMap[512000]     = 360;          // 0.1 deg
0760             m_boldLineMap[2048000]    = 720;          // 0.05 deg
0761             m_boldLineMap[8192000]   = 360 * 10;     // 0.01 deg
0762             m_boldLineMap[1638400]   = 360 * 20;     // 0.005 deg
0763             m_boldLineMap[32768000]  = 360 * 100;    // 0.001 deg
0764             m_boldLineMap[131072000]  = 360 * 200;    // 0.0005 deg
0765             m_boldLineMap[524288000] = 360 * 1000;   // 0.00001 deg
0766 
0767         break;
0768         default:
0769         case GeoDataCoordinates::DMS :
0770             m_normalLineMap[512000]  = 360 * 6;         //  10'
0771             m_normalLineMap[1024000] = 360 * 12;        //  5'
0772             m_normalLineMap[4096000] = 360 * 60;        //  1'
0773             m_normalLineMap[8192000] = 360 * 60 * 2;    //  30"
0774             m_normalLineMap[16384000] = 360 * 60 * 6;   //  10"
0775             m_normalLineMap[65535000] = 360 * 60 * 12;  //  5"
0776             m_normalLineMap[524288000] = 360 * 60 * 60; //  1"
0777 
0778             m_boldLineMap[512000]     = 360;          // 10'
0779             m_boldLineMap[1024000]    = 720;          // 5'
0780             m_boldLineMap[4096000]   = 360 * 6;      // 1'
0781             m_boldLineMap[8192000]   = 360 * 12;     // 30"
0782             m_boldLineMap[16384000]  = 360 * 60;     // 10"
0783             m_boldLineMap[65535000]  = 360 * 60 * 2; // 5"
0784             m_boldLineMap[524288000] = 360 * 60 * 6; // 1"
0785 
0786         break;
0787     }
0788     m_normalLineMap[999999999] = m_normalLineMap.value(262144000);     //  last
0789     m_boldLineMap[999999999]   = m_boldLineMap.value(262144000);     //  last
0790 
0791     m_currentNotation = notation;
0792 }
0793 
0794 } // namespace Marble
0795 
0796 #include "moc_GraticulePlugin.cpp"