Skip to content

[BUG]: fitbounds="locations" thinks the world is flat and goes through longitude zero when dealing with positive and negative longitudes #7844

Description

@rl-utility-man

Description

The Scatter_geo fitbounds='locations' parameter is supposed to show just the relevant part of the world. When the points are on both sides of longitude +/-180, it includes longitude zero on the map even if a map that shows longitude 180 would be far more compact. The two maps below are trivially different; when the eastern most coordinate is 179, the map is compact and fitbounds works as expected. When the eastern most coordinate is -179, the map includes a large amount of unnecessary, blank geography.

Specifying longitude and latitude ranges manually is a workaround.

Let me know if this would be a good PR for someone new to the codebase

Screenshots/Video

Image Image

Steps to reproduce

Run this code

import plotly.graph_objects as go
for lon in [-179, 179]:
    # Coordinates for the points
    lats = [43.1155, 32.7157]
    lons = [131.8855, lon]

    fig = go.Figure(go.Scattergeo(
        lat=lats,
        lon=lons,
        mode='markers+text',
        textposition='top center',
        marker=dict(size=10, color='red')
    ))

    fig.update_layout(
        title=f'eastern most longitude is {lon}',
        geo=dict(
            fitbounds="locations",
            visible=True,
            projection_type='equirectangular'

        )
    )

    fig.show()

Activity

  1. changed the title [-][BUG]: fitbounds="locations" thinks the world is flat and goes through longitude zero when dealing with positive and negative values[/-] [+][BUG]: fitbounds="locations" thinks the world is flat and goes through longitude zero when dealing with positive and negative longitudes[/+] on Mar 16, 2026
  2. camdecoster commented on Mar 18, 2026

    @camdecoster
    Contributor

    Thanks for the report! We're going to look into this a bit and follow up. There's some other work being done in this area.

  3. rl-utility-man commented on Mar 20, 2026

    @rl-utility-man
    Author

    much appreciated! because the map is effectively cylindrical, the best area to omit is where the greatest gap is between any two longitudes. the pseudocode for the correct bounds is roughly:

    largest_gap = sorted_longitudes[0]-sorted_longitudes[-1]
    largest_left_edge_index = -1
    
    for i in range(len(sorted_longitudes)-1):
       if sorted_longitudes[i+1]-sorted_longitudes[i] > largest_gap:
               #capture the index of the left edge of the largest gap; 
               #the right edge of the largest gap is largest_left_edge_index+1
               largest_left_edge_index= i
               largest_gap = sorted_longitudes[i+1]-sorted_longitudes[i]
    
    #largest left_edge tells us where the right most coordinate to keep is
    latitude_range = [sorted_longitudes[largest_left_edge_index+1], sorted_longitudes[largest_left_edge_index]]
    

    thanks to Eli Lebow for suggesting this clean solution!

  4. emilykl commented on Mar 25, 2026

    @emilykl
    Contributor

    Hi @rl-utility-man , thanks for looking into this. We have some work ongoing for a related issue in the map traces, but those are separate from the geo traces.

    This does seem like a bug and we would welcome a PR.

  5. SharadhNaidu commented on Jun 8, 2026

    @SharadhNaidu
    Contributor

    hey, mind if i take a shot at this one? had a look and the issue is in geo.js updateProjection , the lon range for fitbounds comes straight from 'getAutoRange', so it's a naive min/max and any pair of points across +/-180 drags the range through lon 0.

    @rl-utility-man's largest-gap idea works nicely , sort the lons, find the biggest gap (including the wrap from last back to first), and use the complement as the range. tight antimeridian clusters go from '~358°' down to a few degrees, and normal spread-out data is left alone

    one thing i wanted to check before writing it up: do you want this applied whenever it's more compact, or only when points genuinely straddle the antimeridian? the pure largest-gap version will also re-center a few cases that look fine today, so it depends how aggressive you want it. happy to go whichever way.

  6. rl-utility-man commented on Jun 9, 2026

    @rl-utility-man
    Author

    Feel free to submit a PR. I'm far more experienced in Python than JS.

    As for whether to e.g. show London or Tokyo when the map has only points at say 91 degrees east and 91 degrees west, remember that we can document this behavior and ways to override the default -- so I think I lean toward a simple to code, simple to document default that bakes in no preference between the Atlantic and the Pacific. Then we can document the default and how users can customize the behavior. But I defer to Plotly engineers

  7. camdecoster commented on Jun 16, 2026

    @camdecoster
    Contributor

    Given that this is a bug in plotly.js, I'm going to transfer the issue. See @SharadhNaidu's PR for JS examples of how to reproduce the bug.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bugsomething broken

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions