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"