31 using namespace Marble;
34 : m_zBoundingBoxLimit( 0.0 ),
50 sphericalCreateFromPntMap( pntmap, viewport );
53 rectangularCreateFromPntMap( pntmap, viewport );
56 mercatorCreateFromPntMap( pntmap, viewport );
61 void VectorMap::sphericalCreateFromPntMap(
const PntMap* pntmap,
69 qreal radius = viewport->
radius();
70 qreal imgradius2 = ( viewport->
width() / 2 ) * ( viewport->
width() / 2 ) + ( viewport->
height() / 2 ) * ( viewport->
height() / 2 );
75 qreal zlimit = ( ( imgradius2 < radius * radius )
76 ? sqrt( 1 - imgradius2 / ( radius * radius ) )
80 m_zBoundingBoxLimit = ( ( m_zBoundingBoxLimit >= 0.0
81 && zlimit < m_zBoundingBoxLimit )
82 || m_zBoundingBoxLimit < 0.0 )
83 ? zlimit : m_zBoundingBoxLimit;
84 m_zPointLimit = ( ( m_zPointLimit >= 0.0 && zlimit < m_zPointLimit )
85 || m_zPointLimit < 0.0 )
86 ? zlimit : m_zPointLimit;
88 GeoPolygon::PtrVector::ConstIterator itPolyLine = pntmap->constBegin();
89 GeoPolygon::PtrVector::ConstIterator itEndPolyLine = pntmap->constEnd();
92 const int detail = getDetailLevel( viewport->
radius() );
94 for (; itPolyLine != itEndPolyLine; ++itPolyLine )
99 if(boundary.size() < 5)
continue;
101 for (
int i = 0; i < 5; ++i ) {
102 Quaternion qbound = boundary[i]->quaternion();
105 if ( qbound.
v[
Q_Z] > m_zBoundingBoxLimit ) {
108 sphericalCreatePolyLine( *itPolyLine, detail, viewport );
118 void VectorMap::rectangularCreateFromPntMap(
const PntMap* pntmap,
122 int radius = viewport->
radius();
128 const qreal rad2Pixel = (float)( 2 * radius ) /
M_PI;
130 GeoPolygon::PtrVector::ConstIterator itPolyLine = pntmap->constBegin();
131 GeoPolygon::PtrVector::ConstIterator itEndPolyLine = pntmap->constEnd();
133 const QRectF visibleArea ( 0, 0, viewport->
width(), viewport->
height() );
134 const int detail = getDetailLevel( radius );
136 for (; itPolyLine != itEndPolyLine; ++itPolyLine )
144 if ( boundary.size() < 3 )
149 for (
int i = 1; i < 3; ++i ) {
151 boundary[i]->geoCoordinates(lon, lat);
152 const qreal x = (qreal)(viewport->
width()) / 2.0 - rad2Pixel * (centerLon - lon);
153 const qreal y = (qreal)(viewport->
height()) / 2.0 + rad2Pixel * (centerLat - lat);
154 boundingPolygon << QPointF( x, y );
160 if ( boundingPolygon.at(0).x() < 0 || boundingPolygon.at(1).x() < 0 ) {
161 boundingPolygon.translate( 4 * radius, 0 );
162 offset += 4 * radius;
166 offset -= 4 * radius;
167 boundingPolygon.translate( -4 * radius, 0 );
171 && visibleArea.intersects( (QRectF)( boundingPolygon.boundingRect() ) ) )
173 && ( visibleArea.intersects( QRectF( boundingPolygon.at(1),
174 QPointF( (qreal)(viewport->
width()) / 2.0
175 - rad2Pixel * ( centerLon -
M_PI )
177 boundingPolygon.at(0).y() ) ) )
178 || visibleArea.intersects( QRectF( QPointF( (qreal)(viewport->
width()) / 2.0
179 - rad2Pixel * ( centerLon
182 boundingPolygon.at(1).y() ),
183 boundingPolygon.at(0) ) ) ) ) );
184 offset += 4 * radius;
185 boundingPolygon.translate( 4 * radius, 0 );
190 && visibleArea.intersects( (QRectF)( boundingPolygon.boundingRect() ) ) )
192 && ( visibleArea.intersects(
193 QRectF( boundingPolygon.at(1),
194 QPointF( (qreal)(viewport->
width()) / 2.0
195 - rad2Pixel * ( centerLon -
M_PI )
197 boundingPolygon.at(0).y() ) ) )
198 || visibleArea.intersects(
199 QRectF( QPointF( (qreal)(viewport->
width()) / 2.0
200 - rad2Pixel * ( centerLon +
M_PI )
202 boundingPolygon.at(1).y() ),
203 boundingPolygon.at(0) ) ) ) )
206 rectangularCreatePolyLine( *itPolyLine, detail, viewport, offset );
208 offset += 4 * radius;
209 boundingPolygon.translate( 4 * radius, 0 );
214 void VectorMap::mercatorCreateFromPntMap(
const PntMap* pntmap,
218 int radius = viewport->
radius();
224 const qreal rad2Pixel = (float)( 2 * radius ) /
M_PI;
226 GeoPolygon::PtrVector::ConstIterator itPolyLine = pntmap->constBegin();
227 GeoPolygon::PtrVector::ConstIterator itEndPolyLine = pntmap->constEnd();
229 const QRectF visibleArea ( 0, 0, viewport->
width(), viewport->
height() );
230 const int detail = getDetailLevel( radius );
232 for (; itPolyLine != itEndPolyLine; ++itPolyLine )
240 if ( boundary.size() < 3 )
245 for (
int i = 1; i < 3; ++i ) {
247 boundary[i]->geoCoordinates(lon, lat);
248 const qreal x = (qreal)(viewport->
width()) / 2.0 + rad2Pixel * (lon - centerLon);
249 const qreal y = (qreal)(viewport->
height()) / 2.0 - rad2Pixel * ( atanh( sin( lat ) )
250 - atanh( sin( centerLat ) ) );
252 boundingPolygon << QPointF( x, y );
258 if ( boundingPolygon.at(0).x() < 0 || boundingPolygon.at(1).x() < 0 ) {
259 boundingPolygon.translate( 4 * radius, 0 );
260 offset += 4 * radius;
264 offset -= 4 * radius;
265 boundingPolygon.translate( -4 * radius, 0 );
269 && visibleArea.intersects( (QRectF)( boundingPolygon.boundingRect() ) ) )
271 && ( visibleArea.intersects( QRectF( boundingPolygon.at(1),
272 QPointF( (qreal)(viewport->
width()) / 2.0
273 - rad2Pixel * ( centerLon
276 boundingPolygon.at(0).y() ) ) )
277 || visibleArea.intersects( QRectF( QPointF( (qreal)(viewport->
width()) / 2.0
278 - rad2Pixel * ( centerLon
281 boundingPolygon.at(1).y() ),
282 boundingPolygon.at(0) ) ) ) ) );
283 offset += 4 * radius;
284 boundingPolygon.translate( 4 * radius, 0 );
289 && visibleArea.intersects( (QRectF)( boundingPolygon.boundingRect() ) ) )
291 && ( visibleArea.intersects(
292 QRectF( boundingPolygon.at(1),
293 QPointF( (qreal)(viewport->
width()) / 2.0
294 - rad2Pixel * ( centerLon -
M_PI )
296 boundingPolygon.at(0).y() ) ) )
297 || visibleArea.intersects(
298 QRectF( QPointF( (qreal)(viewport->
width()) / 2.0
299 - rad2Pixel * ( centerLon +
M_PI )
301 boundingPolygon.at(1).y() ),
302 boundingPolygon.at(0) ) ) ) )
305 mercatorCreatePolyLine( *itPolyLine, detail, viewport, offset );
307 offset += 4 * radius;
308 boundingPolygon.translate( 4 * radius, 0 );
313 void VectorMap::sphericalCreatePolyLine(
const GeoPolygon *geoPolygon,
316 const int radius = viewport->
radius();
318 const int rLimit = (int)( ( radius * radius )
319 * (1.0 - m_zPointLimit * m_zPointLimit ) );
322 polygon.reserve( geoPolygon->size() );
325 GeoDataCoordinates::Vector::ConstIterator
const &itStartPoint = geoPolygon->constBegin();
326 GeoDataCoordinates::Vector::ConstIterator
const &itEndPoint = geoPolygon->constEnd();
329 bool firsthorizon =
false;
330 bool currentlyvisible =
false;
331 bool horizonpair =
false;
332 QPointF firstHorizonPoint;
335 GeoDataCoordinates::Vector::const_iterator itPoint = itStartPoint;
336 for (; itPoint != itEndPoint; ++itPoint ) {
337 if ( itPoint->detail() < detail )
346 const QPointF currentPoint( ( viewport->
width() / 2 ) + radius * qpos.
v[
Q_X] + 1.0,
347 ( viewport->
height() / 2 ) - radius * qpos.
v[
Q_Y] + 1.0 );
350 bool lastvisible = currentlyvisible;
354 currentlyvisible = ( qpos.
v[
Q_Z] >= 0 );
355 if ( itPoint == itStartPoint ) {
357 lastvisible = currentlyvisible;
358 lastPoint = QPointF( currentPoint.x() + 1.0,
359 currentPoint.y() + 1.0 );
362 if ( currentlyvisible != lastvisible ) {
367 if ( !horizonpair ) {
370 if ( !currentlyvisible ) {
371 horizona = horizonPoint(viewport, currentPoint, rLimit);
376 firstHorizonPoint = horizonPoint(viewport, currentPoint, rLimit);
382 const QPointF horizonb = horizonPoint(viewport, currentPoint, rLimit);
384 createArc(viewport, horizona, horizonb, rLimit, polygon);
391 if ( currentlyvisible && currentPoint != lastPoint ) {
393 polygon << currentPoint;
399 if ( z < -0.2) step = 10;
400 if ( z < -0.4) step = 30;
401 if ( step > remain ) step = 1;
405 lastPoint = currentPoint;
410 if ( firsthorizon ) {
411 const QPointF horizonb = firstHorizonPoint;
413 createArc(viewport, horizona, horizonb, rLimit, polygon);
415 firsthorizon =
false;
419 if ( polygon.size() >= 2 ) {
420 m_polygons.append(polygon);
424 void VectorMap::rectangularCreatePolyLine(
433 const qreal rad2Pixel = (float)( 2 * viewport->
radius() ) /
M_PI;
436 polygon.reserve( geoPolygon->size() );
442 GeoDataCoordinates::Vector::ConstIterator
const &itStartPoint = geoPolygon->constBegin();
443 GeoDataCoordinates::Vector::ConstIterator
const &itEndPoint = geoPolygon->constEnd();
445 bool CrossedDateline =
false;
446 bool firstPoint =
true;
451 GeoDataCoordinates::Vector::const_iterator itPoint = itStartPoint;
452 for (; itPoint != itEndPoint; ++itPoint ) {
454 if ( itPoint->detail() < detail )
463 itPoint->geoCoordinates( lon, lat);
464 const qreal x = (qreal)(viewport->
width()) / 2.0 - rad2Pixel * (centerLon - lon) + offset;
465 const qreal y = (qreal)(viewport->
height()) / 2.0 + rad2Pixel * (centerLat - lat);
466 int currentSign = ( lon > 0.0 ) ? 1 : -1 ;
469 lastSign = currentSign;
472 const QPointF currentPoint = QPointF( x, y );
475 if ( lastSign != currentSign && fabs(lastLon) + fabs(lon) >
M_PI ) {
479 qreal lastXAtDateLine = (qreal)(viewport->
width()) / 2.0
480 + rad2Pixel * ( lastSign *
M_PI - centerLon ) + offset;
481 qreal xAtDateLine = (qreal)(viewport->
width()) / 2.0
482 + rad2Pixel * ( -lastSign *
M_PI - centerLon ) + offset;
483 qreal lastYAtDateLine = (qreal)(viewport->
height()) / 2.0
484 - ( lastLat - centerLat ) * rad2Pixel;
485 qreal yAtSouthPole = (qreal)(viewport->
height()) / 2.0
490 if ( lat < -
M_PI / 3 ) {
494 if ( lastXAtDateLine > (qreal)(viewport->
width()) - 1.0 )
495 lastXAtDateLine = (qreal)(viewport->
width()) - 1.0;
496 if ( lastXAtDateLine < 0.0 )
497 lastXAtDateLine = 0.0;
498 if ( xAtDateLine > (qreal)(viewport->
width()) - 1.0 )
499 xAtDateLine = (qreal)(viewport->
width()) - 1.0;
500 if ( xAtDateLine < 0.0 )
503 polygon << QPointF( lastXAtDateLine, y );
504 polygon << QPointF( lastXAtDateLine, yAtSouthPole );
505 polygon << QPointF( xAtDateLine, yAtSouthPole );
506 polygon << QPointF( xAtDateLine, y );
509 if ( CrossedDateline ) {
510 polygon << QPointF( xAtDateLine, y );
511 otherPolygon << QPointF( lastXAtDateLine, lastYAtDateLine);
514 polygon << QPointF( lastXAtDateLine, lastYAtDateLine );
515 otherPolygon << QPointF( xAtDateLine, y );
517 CrossedDateline = !CrossedDateline;
521 if ( CrossedDateline )
522 otherPolygon << currentPoint;
524 polygon << currentPoint;
528 lastSign = currentSign;
532 if ( polygon.size() >= 2 ) {
533 m_polygons.append(polygon);
536 if ( otherPolygon.size() >= 2 ) {
537 m_polygons.append( otherPolygon );
541 void VectorMap::mercatorCreatePolyLine(
const GeoPolygon *geoPolygon,
549 const qreal rad2Pixel = (qreal)( 2 * viewport->
radius() ) /
M_PI;
552 polygon.reserve( geoPolygon->size() );
558 GeoDataCoordinates::Vector::ConstIterator
const &itStartPoint = geoPolygon->constBegin();
559 GeoDataCoordinates::Vector::ConstIterator
const &itEndPoint = geoPolygon->constEnd();
561 bool CrossedDateline =
false;
562 bool firstPoint =
true;
567 GeoDataCoordinates::Vector::const_iterator itPoint = itStartPoint;
568 for (; itPoint != itEndPoint; ++itPoint ) {
570 if ( itPoint->detail() < detail )
581 itPoint->geoCoordinates( lon, lat );
587 const qreal x = (qreal)(viewport->
width()) / 2.0 + rad2Pixel * (lon - centerLon) + offset;
588 const qreal y = (qreal)(viewport->
height()) / 2.0
589 - rad2Pixel * ( atanh( sin( lat ) ) - atanh( sin( centerLat ) ) );
590 int currentSign = ( lon > 0.0 ) ? 1 : -1 ;
593 lastSign = currentSign;
596 const QPointF currentPoint = QPointF( x, y );
600 if ( lastSign != currentSign && fabs(lastLon) + fabs(lon) >
M_PI ) {
605 qreal lastXAtDateLine = (qreal)(viewport->
width()) / 2.0
606 + rad2Pixel * ( lastSign *
M_PI - centerLon ) + offset;
607 qreal xAtDateLine = (qreal)(viewport->
width()) / 2.0
608 + rad2Pixel * ( -lastSign *
M_PI - centerLon ) + offset;
609 qreal lastYAtDateLine = (qreal)( viewport->
height() / 2 - rad2Pixel
610 * ( atanh( sin( lastLat ) )
611 - atanh( sin( centerLat ) ) ) );
612 qreal yAtSouthPole = (qreal)( viewport->
height() / 2
615 - atanh( sin( centerLat ) ) ) );
619 if ( lat < -
M_PI / 3 ) {
623 if ( lastXAtDateLine > (qreal)(viewport->
width()) - 1.0 )
624 lastXAtDateLine = (qreal)(viewport->
width()) - 1.0;
625 if ( lastXAtDateLine < 0.0 )
626 lastXAtDateLine = 0.0;
627 if ( xAtDateLine > (qreal)(viewport->
width()) - 1.0 )
628 xAtDateLine = (qreal)(viewport->
width()) - 1.0;
629 if ( xAtDateLine < 0.0 )
632 polygon << QPointF( lastXAtDateLine, y );
633 polygon << QPointF( lastXAtDateLine, yAtSouthPole );
634 polygon << QPointF( xAtDateLine, yAtSouthPole );
635 polygon << QPointF( xAtDateLine, y );
638 if ( CrossedDateline ) {
639 polygon << QPointF( xAtDateLine, y );
640 otherPolygon << QPointF( lastXAtDateLine, lastYAtDateLine);
643 polygon << QPointF( lastXAtDateLine, lastYAtDateLine );
644 otherPolygon << QPointF( xAtDateLine, y );
646 CrossedDateline = !CrossedDateline;
650 if ( CrossedDateline )
651 otherPolygon << currentPoint;
653 polygon << currentPoint;
657 lastSign = currentSign;
661 if ( polygon.size() >= 2 ) {
662 m_polygons.append(polygon);
665 if ( otherPolygon.size() >= 2 ) {
666 m_polygons.append( otherPolygon );
675 ScreenPolygon::Vector::const_iterator itEndPolygon = m_polygons.constEnd();
677 for ( ScreenPolygon::Vector::const_iterator itPolygon = m_polygons.constBegin();
678 itPolygon != itEndPolygon;
681 if ( itPolygon->closed() )
689 QPointF VectorMap::horizonPoint(
const ViewportParams *viewport,
const QPointF ¤tPoint,
int rLimit )
const
692 const qreal xa = currentPoint.x() - ( ( viewport->
width() / 2 ) + 1 );
696 qreal ya = ( rLimit > xa * xa )
697 ? sqrt( (qreal)(rLimit) - (qreal)( xa * xa ) ) : 0;
699 if ( ( currentPoint.y() - ( ( viewport->
height() / 2 ) + 1 ) ) < 0 )
702 return QPointF( ( viewport->
width() / 2 ) + xa + 1, ( viewport->
height() / 2 ) + ya + 1 );
706 void VectorMap::createArc(
const ViewportParams *viewport,
const QPointF &horizona,
const QPointF &horizonb,
int rLimit,
ScreenPolygon &polygon )
710 * atan2( horizonb.y() - ( viewport->
height() / 2 ) - 1,
711 horizonb.x() - ( viewport->
width() / 2 ) - 1 ) );
713 * atan2( horizona.y() - ( viewport->
height() / 2 ) - 1,
714 horizona.x() - ( viewport->
width() / 2 ) - 1 ) );
716 qreal diff = beta - alpha;
718 if ( diff != 0.0 && diff != 180.0 && diff != -180.0 ) {
720 polygon.append( horizona );
722 qreal sgndiff = diff / fabs(diff);
724 if (fabs(diff) > 180.0)
725 diff = - sgndiff * (360.0 - fabs(diff));
728 sgndiff = diff / fabs(diff);
736 qreal arcradius = sqrt( (qreal)( rLimit ) );
738 for (
int it = 1; it < fabs(diff); ++it ) {
739 qreal
angle =
DEG2RAD * (qreal)( alpha + (sgndiff * it) );
740 itx = (int)( ( viewport->
width() / 2 ) + arcradius * cos( angle ) + 1 );
741 ity = (int)( ( viewport->
height() / 2 ) + arcradius * sin( angle ) + 1 );
743 polygon.append( QPoint( itx, ity ) );
746 polygon.append( horizonb );
751 int VectorMap::getDetailLevel(
int radius )
const
755 if ( radius > 5000 ) detail = 0;
756 else if ( radius > 2500 ) detail = 1;
757 else if ( radius > 1000 ) detail = 2;
758 else if ( radius > 600 ) detail = 3;
759 else if ( radius > 50 ) detail = 4;
762 return smallScreen ? qMin( 5, detail + 1 ) : detail;
void drawPolygon(const GeoDataLinearRing &linearRing, Qt::FillRule fillRule=Qt::OddEvenFill)
Draws a given linear ring (a "polygon without holes").
double angle(double vec1[3], double vec2[3])
A painter that allows to draw geometric primitives on the map.
void drawPolyline(const GeoDataLineString &lineString, const QString &labelText=QString(), LabelPositionFlags labelPositionFlags=LineCenter)
Draws a given line string (a "polyline").
Projection projection() const
This file contains the headers for AbstractProjection.
void rotateAroundAxis(const Quaternion &q)
Flat projection ("plate carree")
const AbstractProjection * currentProjection() const
const matrix & planetAxisMatrix() const
A public class that controls what is visible in the viewport of a Marble map.
This file contains the headers for ViewportParams.
static MarbleGlobal * getInstance()
qreal centerLatitude() const
QVector< GeoDataCoordinates * > PtrVector
void paintMap(GeoPainter *painter)
Paint the background, i.e.
qreal centerLongitude() const
void createFromPntMap(const PntMap *, const ViewportParams *viewport)
Profiles profiles() const
void setClosed(bool closed)