Summary: | centerOn(GeoDataLatLonBox) behaviour does not match documentation | ||
---|---|---|---|
Product: | [Applications] marble | Reporter: | Samuel OMalley <7g7o5v4t> |
Component: | general | Assignee: | marble-bugs |
Status: | CONFIRMED --- | ||
Severity: | normal | CC: | rahn |
Priority: | NOR | ||
Version: | unspecified | ||
Target Milestone: | --- | ||
Platform: | RedHat Enterprise Linux | ||
OS: | Linux | ||
Latest Commit: | Version Fixed In: | ||
Sentry Crash Report: |
Description
Samuel OMalley
2022-11-08 01:54:57 UTC
Yes, the current implementation of void MarbleAbstractPresenter::centerOn(const GeoDataLatLonBox &box, bool animated) is only a rough approximation. In order to center on a boundingbox internally Marble needs to center on the center point and adjust the zoom level (which is internally tied to the pixel-radius that a fully rendered earth would cover in terms of vertical extent). Since Marble allows for usage of different projections the actual calculation of the zoom level would hard to calculate in a generic way. So the only "better" option would be to iteratively approximate the optimal zoom level (while either working on a copy of the view parameters or turning off rendering during the iterative convergence towards the optimal zoom level). The current code looks like this: void MarbleAbstractPresenter::centerOn(const GeoDataLatLonBox &box, bool animated) { if (box.isEmpty()) { return; } int newRadius = radius(); ViewportParams* viewparams = map()->viewport(); //prevent divide by zero if(box.height() && box.width()) { //work out the needed zoom level int const horizontalRadius = ( 0.25 * M_PI ) * (viewparams->height() / box.height()); int const verticalRadius = ( 0.25 * M_PI ) * (viewparams->width() / box.width()); newRadius = qMin<int>(horizontalRadius, verticalRadius ); newRadius = qMax<int>(radius(minimumZoom()), qMin<int>(newRadius, radius(maximumZoom()))); } //move the map GeoDataLookAt target; target.setCoordinates(box.center()); target.setAltitude(box.center().altitude()); target.setRange(KM2METER * distanceFromRadius(newRadius)); flyTo(target, animated ? Automatic : Instant); } Any suggestions for improvements welcome. |