Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Label Blinking Issue at Integer Zoom Levels with animateCamera #2477

Open
geolives-contact opened this issue Jun 6, 2024 · 6 comments · May be fixed by #2479
Open

Label Blinking Issue at Integer Zoom Levels with animateCamera #2477

geolives-contact opened this issue Jun 6, 2024 · 6 comments · May be fixed by #2479
Labels
android bug Something isn't working

Comments

@geolives-contact
Copy link
Contributor

Describe the bug
Starting with MapLibre v11, when the map zoom is set to an exact integer value (such as 15.0, 16.0 or 17.0 for instance), some labels blink when animateCamera is called.
The issue does not occur when using moveCamera or when the zoom is set between integer values (e.g., 16.4 or 17.1).

Here are some videos to demonstrate the issue:

  • First video: Shows the issue with labels for roads blinking during the animation.
  • Second video: Shows the labels not blinking when the zoom is set between integer values.

To Reproduce

  1. Download and use this sample activity file: SimpleMapActivity.kt.zip
  2. This activity file contains code to run animateCamera at short intervals with the zoom set exactly to 15.0.
  3. If needed, we can create a branch with this edit in our fork.

Expected behavior
On the MapLibre v10 version, labels didn't blink when zoom are set at integer values.

Platform information (please complete the following information):

  • Platform: Android, iOS not tested
  • Version 11
@geolives-contact geolives-contact added the bug Something isn't working label Jun 6, 2024
@louwers
Copy link
Collaborator

louwers commented Jun 6, 2024

Thanks for the great bug report with reproduction!

That's a really strange bug, but we'll have a look at it.

I can reproduce this with other styles as well.

@louwers louwers added the android label Jun 6, 2024
@louwers
Copy link
Collaborator

louwers commented Jun 6, 2024

I tried iOS, doesn't seem to be a problem there:

struct SimpleMap: UIViewRepresentable {

    func makeUIView(context _: Context) -> MLNMapView {
        let mapView = MLNMapView(frame: .zero, styleURL: VERSATILES_COLORFUL_STYLE)
        mapView.zoomLevel = 15.0
        
        mapView.centerCoordinate = CLLocationCoordinate2D(latitude: 50.15, longitude: 5.2)
        
        startTimer(mapView: mapView)
        return mapView
    }

    func updateUIView(_: MLNMapView, context _: Context) {}
    
    private func startTimer(mapView: MLNMapView) {
        Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { i in
            // Update coordinates
            var currentCenter = mapView.centerCoordinate
            
            // Update coordinates
            currentCenter.latitude += 0.001
            currentCenter.longitude += 0.001
            
            // Animate camera to new coordinates
            let camera = MLNMapCamera(lookingAtCenter: currentCenter, altitude: mapView.camera.altitude, pitch: mapView.camera.pitch, heading: mapView.camera.heading)
//            mapView.setCamera(camera, withDuration: 1, animationTimingFunction: CAMediaTimingFunction(name: .easeInEaseOut))
//            mapView.setCamera(camera, withDuration: 1, animationTimingFunction: CAMediaTimingFunction(name: .easeInEaseOut))
            mapView.fly(to: camera)
        }
    }
}

@louwers
Copy link
Collaborator

louwers commented Jun 6, 2024

I think we're losing a lot of accuracy on Android somewhere.

constexpr double kEpsilon = 1e-9;
// To avoid flickering issue due to "zoom = 13.9999999..".
double roundForAccuracy(double x) {
    double round_x = std::round(x);
    double diff = std::abs(round_x - x);
    if (diff < kEpsilon && diff > 0) {
        return round_x;
    } else {
        return x;
    }
}

is meant to account for this problem but the zoom goes from 15.0 to 14.993487604307171 during the animation

@louwers
Copy link
Collaborator

louwers commented Jun 6, 2024

@geolives-contact animateCamera uses flyTo which is implemented using the Smooth and efficient zooming and panning algorithm. So it zooms out a little, with longer distances and a longer animation duration this is more pronounced. The zooming out causes (re)placement.

This looks related: #16

@geolives-contact
Copy link
Contributor Author

Thank you for your prompt feedback on this issue!

From what I understand, the symbol flickers because the zooming/panning algorithm briefly changes the zoom level from 15.0 to 14.999, then back to 15.0 when the camera reaches its destination.

The real problem seems to be why the labels flicker during these zoom level transitions. It’s particularly strange since some labels do not flicker at all.

I will investigate this further next week, specifically to see if the arrangement of layers in the styleJSON affect this behavior.

@louwers
Copy link
Collaborator

louwers commented Jun 7, 2024

@geolives-contact Yes I think it's a bug, with such a small zoom change I don't expect such dramatic label placement changes. I also don't see it on iOS for some reason.

I see this problem in other styles as well, so I don't think it's related to your style. The solution is probably in the placement code but it quite complex so it may be hard to find the problem.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
android bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants