Reputation: 69
I am trying to get the code contained in
https://basemaptutorial.readthedocs.io/en/latest/basemap3d.html
to work. However, I get an error already in the first snippet:
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from mpl_toolkits.basemap import Basemap
map = Basemap()
fig = plt.figure()
ax = Axes3D(fig)
'''
ax.azim = 270
ax.elev = 90
ax.dist = 5
'''
ax.add_collection3d(map.drawcoastlines(linewidth=0.25))
ax.add_collection3d(map.drawcountries(linewidth=0.35))
plt.show()
The error reads:
Traceback (most recent call last):
File ".../main.py", line 16, in <module>
ax.add_collection3d(map.drawcoastlines(linewidth=0.25))
File ".../venv/lib/python3.12/site-packages/mpl_toolkits/mplot3d/axes3d.py", line 2314, in add_collection3d
collection = super().add_collection(col)
^^^^^^^^^^^^^^^^^^^^^^^^^^^
File ".../venv/lib/python3.12/site-packages/matplotlib/axes/_base.py", line 2260, in add_collection
self._set_artist_props(collection)
File ".../venv/lib/python3.12/site-packages/matplotlib/axes/_base.py", line 1177, in _set_artist_props
a.axes = self
^^^^^^
File ".../venv/lib/python3.12/site-packages/matplotlib/artist.py", line 302, in axes
raise ValueError("Can not reset the axes. You are probably "
ValueError: Can not reset the axes. You are probably trying to re-use an artist in more than one Axes which is not supported
Process finished with exit code 1
I cannot find a solution to this yet. My final goal is to achieve something similar to what user guidocioni shows here: https://community.plotly.com/t/adding-a-world-map-to-a-3d-volume-graph-python/33592/2
Upvotes: 1
Views: 43
Reputation: 3896
drawcoastlines
creates a Matplotlib LineCollection
and adds that to a 2D axes before returning it. Modern Matplotlib does not let you add the same artist to two axes. We can instead create a LineCollection
directly from the coastsegs
attribute and add that to the 3D axes. drawcountries
is similar, except that it calls a private method to make sure the cntrysegs
attribute exists. So as a workaround I add first add the countries to a 2D plot, which is then discarded.
import matplotlib.pyplot as plt
from mpl_toolkits.basemap import Basemap
from matplotlib.collections import LineCollection
map = Basemap()
# Draw and discard a dummy 2D plot so that country data is added as the
# cntrysegs attribute.
dummy_fig, dummy_ax = plt.subplots()
map.drawcountries(ax=dummy_ax)
plt.close(dummy_fig)
# Create the figure and 3D axes we are actually going to use.
fig = plt.figure()
ax = fig.add_subplot(projection='3d')
# Create and add boundary LineCollections.
coastlines = LineCollection(map.coastsegs, linewidth=0.25, color='black')
countries = LineCollection(map.cntrysegs, linewidth=0.35, color='black')
ax.add_collection3d(coastlines)
ax.add_collection3d(countries)
# Set global x and y limits.
ax.set_xlim(-180, 180)
ax.set_ylim(-90, 90)
plt.show()
Upvotes: 0