10 #include <MarbleAbstractPresenter.h>
12 #include <Quaternion.h>
14 #include <MarbleLocale.h>
18 #include "GeoDataGeometry.h"
19 #include "GeoDataLatLonAltBox.h"
20 #include <GeoDataPlacemark.h>
21 #include <GeoDataLookAt.h>
22 #include <MarbleClock.h>
23 #include <MarbleDebug.h>
27 MarbleAbstractPresenter::MarbleAbstractPresenter(MarbleMap *map,
QObject *parent) :
31 ,m_animationsEnabled(false)
33 ,m_zoomStep(MarbleGlobal::getInstance()->profiles() & MarbleGlobal::SmallScreen ? 60 : 40)
38 MarbleAbstractPresenter::~MarbleAbstractPresenter()
42 qreal MarbleAbstractPresenter::zoom(qreal radius)
const
44 return (200.0 * log(radius));
47 qreal MarbleAbstractPresenter::radius(qreal zoom)
const
49 return pow(M_E, (zoom / 200.0));
52 void MarbleAbstractPresenter::rotateBy(
const qreal deltaLon,
const qreal deltaLat,
FlyToMode mode)
55 GeoDataLookAt target = lookAt();
56 GeoDataCoordinates coords(
map()->viewport()->centerLongitude(),
map()->viewport()->centerLatitude());
57 GeoDataCoordinates movedCoords = coords.moveByBearing(-
map()->heading() * DEG2RAD, -deltaLat * DEG2RAD);
58 movedCoords = movedCoords.moveByBearing((-
map()->heading() - 90) * DEG2RAD, -deltaLon * DEG2RAD *
map()->viewport()->polarity());
60 target.setLongitude(movedCoords.longitude());
61 target.setLatitude(movedCoords.latitude());
66 void MarbleAbstractPresenter::flyTo(
const GeoDataLookAt &newLookAt,
FlyToMode mode)
68 if (!m_animationsEnabled || mode ==
Instant)
70 const int radius = qRound(radiusFromDistance(newLookAt.range() * METER2KM));
71 qreal
const zoomVal =
zoom(radius);
74 if (qRound(zoomVal) >= minimumZoom() && qRound(zoomVal) <= maximumZoom())
76 map()->setRadius(radius);
77 m_logzoom = qRound(
zoom(radius));
80 map()->centerOn(newLookAt.longitude(deg), newLookAt.latitude(deg));
82 emit zoomChanged(m_logzoom);
83 emit distanceChanged(distanceString());
88 m_physics.flyTo(newLookAt, mode);
92 QString MarbleAbstractPresenter::distanceString()
const
95 qreal dist =
distance() * KM2METER, convertedDistance;
97 MarbleLocale::MeasureUnit unit;
98 MarbleLocale *
locale = MarbleGlobal::getInstance()->locale();
99 locale->meterToTargetUnit(dist,
locale->measurementSystem(),
100 convertedDistance, unit);
107 GeoDataLookAt MarbleAbstractPresenter::lookAt()
const
109 GeoDataLookAt result;
111 result.setLongitude(
map()->viewport()->centerLongitude());
112 result.setLatitude(
map()->viewport()->centerLatitude());
113 result.setAltitude(0.0);
114 result.setRange(
distance() * KM2METER);
119 qreal MarbleAbstractPresenter::distance()
const
121 return distanceFromRadius(radius());
124 qreal MarbleAbstractPresenter::distanceFromRadius(qreal radius)
const
136 return (model()->planet()->radius() * 0.4
137 / radius / tan(0.5 * m_viewAngle * DEG2RAD));
140 qreal MarbleAbstractPresenter::radiusFromDistance(qreal distance)
const
142 return model()->planet()->radius() /
143 (
distance * tan(0.5 * m_viewAngle * DEG2RAD) / 0.4 );
146 int MarbleAbstractPresenter::polarity()
const
148 return map()->viewport()->polarity();
151 int MarbleAbstractPresenter::zoom()
const
156 int MarbleAbstractPresenter::minimumZoom()
const
158 return map()->minimumZoom();
161 int MarbleAbstractPresenter::maximumZoom()
const
163 return map()->maximumZoom();
166 void MarbleAbstractPresenter::setZoom(
int newZoom,
FlyToMode mode)
169 if (!m_animationsEnabled || mode ==
Instant)
172 if (newZoom < minimumZoom())
173 newZoom = minimumZoom();
174 else if (newZoom > maximumZoom())
175 newZoom = maximumZoom();
178 if (newZoom == m_logzoom)
181 map()->setRadius(radius(newZoom));
184 emit zoomChanged(m_logzoom);
185 emit distanceChanged(distanceString());
189 GeoDataLookAt target = lookAt();
190 target.setRange(KM2METER * distanceFromZoom(newZoom));
195 void MarbleAbstractPresenter::zoomView(
int zoom,
FlyToMode mode)
200 void MarbleAbstractPresenter::zoomViewBy(
int zoomStep,
FlyToMode mode)
202 setZoom(
zoom() + zoomStep, mode);
205 void MarbleAbstractPresenter::zoomIn(
FlyToMode mode)
207 if (
map()->tileZoomLevel() < 0)
209 zoomViewBy(m_zoomStep, mode);
213 qreal radiusVal =
map()->preferredRadiusCeil(
map()->radius() / 0.95);
214 radiusVal = qBound( radius(minimumZoom()), radiusVal, radius(maximumZoom()) );
216 GeoDataLookAt target = lookAt();
217 target.setRange(KM2METER * distanceFromRadius(radiusVal));
223 void MarbleAbstractPresenter::zoomOut(
FlyToMode mode)
225 if (
map()->tileZoomLevel() <= 0)
227 zoomViewBy(-m_zoomStep, mode);
231 qreal radiusVal =
map()->preferredRadiusFloor(
map()->radius() * 0.95);
232 radiusVal = qBound( radius(minimumZoom()), radiusVal, radius(maximumZoom()) );
234 GeoDataLookAt target = lookAt();
235 target.setRange(KM2METER * distanceFromRadius(radiusVal));
241 void MarbleAbstractPresenter::zoomAtBy(
const QPoint &pos,
int zoomStep)
244 if (
map()->tileZoomLevel() <= 0) {
245 radiusVal = radius(
zoom() + zoomStep);
248 radiusVal = zoomStep > 0 ?
map()->preferredRadiusCeil(
map()->radius() / 0.95) :
249 map()->preferredRadiusFloor(
map()->radius() * 0.95);
250 radiusVal = qBound( radius(minimumZoom()), radiusVal, radius(maximumZoom()) );
253 zoomAt(pos, distanceFromRadius(radiusVal));
256 qreal MarbleAbstractPresenter::distanceFromZoom(qreal zoom)
const
258 return distanceFromRadius(radius(zoom));
261 qreal MarbleAbstractPresenter::zoomFromDistance(qreal distance)
const
263 return zoom(radiusFromDistance(distance));
266 void MarbleAbstractPresenter::goHome(
FlyToMode mode)
271 model()->home(homeLon, homeLat, homeZoom);
273 GeoDataLookAt target;
274 target.setLongitude(homeLon, GeoDataCoordinates::Degree);
275 target.setLatitude(homeLat, GeoDataCoordinates::Degree);
276 target.setRange(1000 * distanceFromZoom(homeZoom));
281 void MarbleAbstractPresenter::moveByStep(
int stepsRight,
int stepsDown,
FlyToMode mode)
283 int polarity =
map()->viewport()->polarity();
284 qreal
left = polarity * stepsRight * moveStep();
285 qreal down = stepsDown * moveStep();
286 rotateBy(left, down, mode);
289 qreal MarbleAbstractPresenter::moveStep()
const
291 int width =
map()->width();
292 int height =
map()->height();
294 if (radius() < qSqrt((qreal)(width * width + height * height)))
297 return 180.0 * qAtan((qreal)width
298 / (qreal)(2 * radius())) * 0.2;
301 int MarbleAbstractPresenter::radius()
const
303 return map()->radius();
306 void MarbleAbstractPresenter::setRadius(
int radiusVal)
308 Q_ASSERT(radiusVal >= 0);
309 bool adjustRadius = radiusVal !=
map()->radius();
311 qreal
const zoomVal =
zoom(radiusVal);
314 if (zoomVal < minimumZoom())
316 radiusVal = radius(minimumZoom());
319 else if (zoomVal > maximumZoom())
321 radiusVal = radius(maximumZoom());
327 map()->setRadius(radiusVal);
328 m_logzoom = qRound(zoomVal);
330 emit zoomChanged(m_logzoom);
331 emit distanceChanged(distanceString());
337 void MarbleAbstractPresenter::zoomAt(
const QPoint &pos, qreal newDistance)
339 Q_ASSERT(newDistance > 0.0);
343 if (!
map()->geoCoordinates(pos.
x(), pos.
y(), destLon, destLat, GeoDataCoordinates::Degree))
348 ViewportParams* now =
map()->viewport();
350 if (!now->screenCoordinates(destLon * DEG2RAD, destLat * DEG2RAD, x, y))
356 soon.setProjection(now->projection());
357 soon.centerOn(now->centerLongitude(), now->centerLatitude());
358 soon.setSize(now->size());
360 qreal newRadius = radiusFromDistance(newDistance);
361 soon.setRadius(newRadius);
363 qreal mouseLon, mouseLat;
364 if (!soon.geoCoordinates(
int(x),
int(y), mouseLon, mouseLat, GeoDataCoordinates::Degree ))
369 const qreal lon = destLon - (mouseLon -
map()->centerLongitude());
370 const qreal lat = destLat - (mouseLat -
map()->centerLatitude());
372 GeoDataLookAt lookAt;
373 lookAt.setLongitude(lon, GeoDataCoordinates::Degree);
374 lookAt.setLatitude(lat, GeoDataCoordinates::Degree);
375 lookAt.setAltitude(0.0);
376 lookAt.setRange(newDistance * KM2METER);
378 map()->viewport()->setFocusPoint(GeoDataCoordinates(destLon, destLat, 0, GeoDataCoordinates::Degree));
382 void MarbleAbstractPresenter::moveTo(
const QPoint &pos, qreal factor)
384 Q_ASSERT(factor > 0.0);
388 map()->geoCoordinates(pos.
x(), pos.
y(), destLon, destLat, GeoDataCoordinates::Radian);
390 GeoDataLookAt lookAt;
391 lookAt.setLongitude(destLon);
392 lookAt.setLatitude(destLat);
393 lookAt.setAltitude(0.0);
394 lookAt.setRange(
distance() * factor * KM2METER);
399 void MarbleAbstractPresenter::centerOn(
const qreal lon,
const qreal lat,
bool animated)
401 GeoDataCoordinates target(lon, lat, 0.0, GeoDataCoordinates::Degree);
402 centerOn(target, animated);
405 void MarbleAbstractPresenter::centerOn(
const GeoDataCoordinates &position,
bool animated)
407 GeoDataLookAt target = lookAt();
408 target.setCoordinates(position);
412 void MarbleAbstractPresenter::centerOn(
const GeoDataLatLonBox &box,
bool animated)
419 int newRadius = radius();
420 ViewportParams* viewparams =
map()->viewport();
422 if(box.height() && box.width())
425 int const horizontalRadius = ( 0.25 * M_PI ) * (viewparams->height() / box.height());
426 int const verticalRadius = ( 0.25 * M_PI ) * (viewparams->width() / box.width());
427 newRadius = qMin<int>(horizontalRadius, verticalRadius );
428 newRadius = qMax<int>(radius(minimumZoom()), qMin<int>(newRadius, radius(maximumZoom())));
432 GeoDataLookAt target;
433 target.setCoordinates(box.center());
434 target.setAltitude(box.center().altitude());
435 target.setRange(KM2METER * distanceFromRadius(newRadius));
439 void MarbleAbstractPresenter::centerOn(
const GeoDataPlacemark& placemark,
bool animated)
441 const GeoDataLookAt *lookAt(placemark.lookAt());
449 GeoDataCoordinates coords = placemark.coordinate(model()->clock()->dateTime(), &icon);
452 centerOn(coords, animated);
456 centerOn(placemark.geometry()->latLonAltBox(), animated);
461 void MarbleAbstractPresenter::headingOn(qreal heading)
463 map()->setHeading(heading);
466 void MarbleAbstractPresenter::setCenterLatitude(qreal lat,
FlyToMode mode)
468 centerOn(centerLongitude(), lat, mode);
471 void MarbleAbstractPresenter::setCenterLongitude(qreal lon,
FlyToMode mode)
473 centerOn(lon, centerLatitude(), mode);
476 qreal MarbleAbstractPresenter::centerLatitude()
const
478 return map()->centerLatitude();
481 qreal MarbleAbstractPresenter::centerLongitude()
const
483 return map()->centerLongitude();
486 ViewContext MarbleAbstractPresenter::viewContext()
const
488 return map()->viewContext();
491 void MarbleAbstractPresenter::setViewContext(
ViewContext viewContext)
493 map()->setViewContext(viewContext);
496 bool MarbleAbstractPresenter::animationsEnabled()
const
498 return m_animationsEnabled;
501 void MarbleAbstractPresenter::setAnimationsEnabled(
bool enabled)
503 m_animationsEnabled = enabled;
506 int MarbleAbstractPresenter::logzoom()
const
511 void MarbleAbstractPresenter::setLogzoom(
int value)
516 int MarbleAbstractPresenter::zoomStep()
const
521 qreal MarbleAbstractPresenter::viewAngle()
const
526 MarbleMap* MarbleAbstractPresenter::map()
531 const MarbleMap* MarbleAbstractPresenter::map()
const
536 MarbleModel* MarbleAbstractPresenter::model()
538 return m_map->model();
541 const MarbleModel* MarbleAbstractPresenter::model()
const
543 return m_map->model();
546 ViewportParams* MarbleAbstractPresenter::viewport()
548 return map()->viewport();
551 const ViewportParams* MarbleAbstractPresenter::viewport()
const
553 return map()->viewport();
556 void MarbleAbstractPresenter::setDistance(qreal newDistance)
558 qreal minDistance = 0.001;
560 if (newDistance <= minDistance)
562 mDebug() <<
"Invalid distance: 0 m";
563 newDistance = minDistance;
566 int newRadius = radiusFromDistance(newDistance);
567 setRadius(newRadius);
570 void MarbleAbstractPresenter::setSelection(
const QRect& region)
574 mDebug() <<
"Selection region: (" << tl.
x() <<
", " << tl.
y() <<
") ("
575 << br.
x() <<
", " << br.
y() <<
")" <<
endl;
577 const GeoDataLatLonAltBox box = viewport()->latLonAltBox(region);
579 emit regionSelected(box);
584 #include "moc_MarbleAbstractPresenter.cpp"