Bug 461569 - centerOn(GeoDataLatLonBox) behaviour does not match documentation
Summary: centerOn(GeoDataLatLonBox) behaviour does not match documentation
Status: CONFIRMED
Alias: None
Product: marble
Classification: Applications
Component: general (show other bugs)
Version: unspecified
Platform: RedHat Enterprise Linux Linux
: NOR normal
Target Milestone: ---
Assignee: marble-bugs
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2022-11-08 01:54 UTC by Samuel OMalley
Modified: 2023-04-22 13:31 UTC (History)
1 user (show)

See Also:
Latest Commit:
Version Fixed In:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Samuel OMalley 2022-11-08 01:54:57 UTC
SUMMARY
***
NOTE: If you are reporting a crash, please try to attach a backtrace with debug symbols.
See https://community.kde.org/Guidelines_and_HOWTOs/Debugging/How_to_create_useful_crash_reports
***

The documentation for centerOn(GeoDataLatLonBox) specifies: "Center the view on a bounding box so that it **completely fills the viewport**"

However, the actual behaviour of this function is that the map is correctly centered, but zoomed *out* from the bounding box.


STEPS TO REPRODUCE
1. Define a bounding box
2. call centerOn the bounding box

OBSERVED RESULT
Bounding box does _not_ completely fill the viewport as described in the documentation.

EXPECTED RESULT
Bounding box should completely fill the viewport.

SOFTWARE/OS VERSIONS
Linux/KDE Plasma: RHEL7 and RHEL8
Qt Version: 5.10
Comment 1 Torsten Rahn 2023-04-22 13:31:12 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.