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

[Bug]: Basemap drawgreatcircle generating gaps in Mercator projection #606

Open
glumr opened this issue Aug 26, 2024 · 3 comments
Open

[Bug]: Basemap drawgreatcircle generating gaps in Mercator projection #606

glumr opened this issue Aug 26, 2024 · 3 comments

Comments

@glumr
Copy link

glumr commented Aug 26, 2024

Bug summary

I see an issue where drawgreatcircle() produces paths with gaps in with the Mercator projection.

I can see from web searches that others have seen the same issue and suggestions point to gathering the path using computations with other projections.

Code for reproduction

from mpl_toolkits.basemap import Basemap
import numpy as np
import matplotlib.pyplot as plt

# setup mercator map projection.
m = Basemap(llcrnrlon=-180.,llcrnrlat=-65.,\
            urcrnrlon=180.,urcrnrlat=85.,\
            projection='merc',\
            lat_0=40.,lon_0=-20.,lat_ts=20.)
m.drawcoastlines()
m.fillcontinents()

# AMS
amslat = np.float64(52.309)
amslon = np.float64(4.764)
# Seattle
sealat = np.float64(47.449)
sealon = np.float64(-122.309)
# Helsinki
hellat = np.float64(60.320)
hellon = np.float64(24.956)

m.drawgreatcircle(amslon,amslat,sealon,sealat,linewidth=2,color='b')
m.drawgreatcircle(sealon,sealat,hellon,hellat,linewidth=2,color='b')

# draw parallels
m.drawparallels(np.arange(-60,65,20))
# draw meridians
m.drawmeridians(np.arange(-180,180,30))
plt.show()

Actual outcome

Gaps_times2

Expected outcome

Gaps_times5

Additional information

I don't understand the basemap calculations and how projections enter into it but I can recover the correct output if I change the test for cuts in the source code by making max_dist much larger...

diff -c __init*py.orig **init*py
*** __init__.py.orig    Mon Aug 26 08:40:10 2024
--- __init__.py Mon Aug 26 09:28:34 2024
***************
*** 2901,2907 ****
          p = _p[0].get_path()

          # since we know the difference between any two points, we can use this to find wrap arounds on the plot
!         max_dist = 1000*del_s*2

          # calculate distances and compare with max allowable distance
          dists = np.abs(np.diff(p.vertices[:,0]))
--- 2901,2907 ----
          p = _p[0].get_path()

          # since we know the difference between any two points, we can use this to find wrap arounds on the plot
!         max_dist = 1000*del_s*5

          # calculate distances and compare with max allowable distance
          dists = np.abs(np.diff(p.vertices[:,0]))

This is what I did to generate the output in the expected result box.
It would be helpful if the defaults did allow great circle paths into high lattitudes.

Operating system

Windows 10

Matplotlib Version

3.8.4

Matplotlib Backend

3.8.4

Python version

3.12.2

Jupyter version

No response

Installation

conda

@matplotlib matplotlib deleted a comment Aug 26, 2024
@matplotlib matplotlib deleted a comment Aug 26, 2024
@matplotlib matplotlib deleted a comment Aug 26, 2024
@rcomer
Copy link
Member

rcomer commented Aug 26, 2024

Hi @glumr it looks like this issue is specifically about basemap, so I’ll transfer it to that repository.

@rcomer rcomer transferred this issue from matplotlib/matplotlib Aug 26, 2024
@glumr
Copy link
Author

glumr commented Aug 26, 2024

Ir seems this has been noted a long time ago: #171

I initially searched in matplotlib/matplotlib issues so did not find the above.

@DWesl
Copy link
Contributor

DWesl commented Aug 30, 2024

You can create arbitrarily-long great-circle paths on the Mercator projection by making the path arbitrarily close to the pole, so any fixed number will break down in some circumstance. Perhaps the logic should change to take the plot limits into account if the projection can be infinite (Mercator and variants, Lambert Conformal, and Stereographic and variants are the ones that come to mind as relevant for this)?

It might also be possible to make that scale factor a keyword-argument of the function, defaulting to two and only getting used when needed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants
@rcomer @DWesl @glumr and others