from math import cos, cosh, floor, pi, sin, sinh
import matplotlib.pyplot as plt
import numpy as np
from scipy.spatial.transform import Rotation
def set_axes_equal_3d(ax):
# https://stackoverflow.com/a/13701747/31611660
lims = [ax.get_xlim3d(), ax.get_ylim3d(), ax.get_zlim3d()]
ranges = [x[1] - x[0] for x in lims]
mids = [np.mean(x) for x in lims]
plot_radius = 0.5 * max([abs(x) for x in ranges])
for setl, r, m in zip([ax.set_xlim3d, ax.set_ylim3d, ax.set_zlim3d], ranges, mids):
setl(m - np.sign(r) * plot_radius, m + np.sign(r) * plot_radius)
rot = Rotation.from_euler("ZXZ", (25, 75, 75))
proj = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 0]])
points = rot.apply([[1.0 * cosh(a), 2 * sinh(a), 0] for a in np.arange(-3, 3, 0.01)])
points += np.array([0, 0, -min(points[:, 2])])
circ = np.array([[cos(a), sin(a), 0] for a in np.arange(-pi, pi, 0.01)])
fig = plt.figure(figsize=(10, 8))
ax = fig.add_subplot(111, projection="3d")
# trajectory
ax.plot(*zip(points.T), linewidth=3)
# projection
ax.plot(*zip(proj.dot(points.T)), "--", linewidth=1)
# vertical guidelines
for idx in range(0, len(points), floor(len(points) / 6)):
ax.plot(
[points[idx][0]] * 2,
[points[idx][1]] * 2,
[0, points[idx][2]],
"--",
linewidth=1,
)
# polar grid of poverty
for r in [10, 15, 20, 25]:
ax.plot(*zip(*(r * circ)), ":", linewidth=0.5, color="gray")
for ang in np.arange(0, 360, 30) * pi / 180:
ax.plot(
[0, 25 * cos(ang)], [0, 25 * sin(ang)], [0, 0], ":", linewidth=0.5, color="gray"
)
# config
ax.set_xlabel("X")
ax.set_ylabel("Y")
ax.set_zlabel("Z")
ax.set_title("Simple 3D Hyperbola")
set_axes_equal_3d(ax)
ax.axis("off")
plt.show()
Мне бы хотелось, чтобы сетка в плоскости XY была такой, как эта, которую я адаптировал из https://dev.to/labex/custom-grid-and-po ... otlib-3e2m. Я хочу, чтобы сетка была обрезана по границам оси и имела метки для расстояния и угла, как здесь. Делительные отметки выглядят великолепно, но в этом нет необходимости.
Я хочу построить трехмерную кривую, показывающую сетку XY в полярных координатах. Вот эскиз [img]https://i.sstatic.net/HPAyftOy.png[/img]
и мой скрипт, который его сгенерировал: [code] from math import cos, cosh, floor, pi, sin, sinh
import matplotlib.pyplot as plt import numpy as np from scipy.spatial.transform import Rotation
def set_axes_equal_3d(ax): # https://stackoverflow.com/a/13701747/31611660 lims = [ax.get_xlim3d(), ax.get_ylim3d(), ax.get_zlim3d()] ranges = [x[1] - x[0] for x in lims] mids = [np.mean(x) for x in lims] plot_radius = 0.5 * max([abs(x) for x in ranges]) for setl, r, m in zip([ax.set_xlim3d, ax.set_ylim3d, ax.set_zlim3d], ranges, mids): setl(m - np.sign(r) * plot_radius, m + np.sign(r) * plot_radius)
rot = Rotation.from_euler("ZXZ", (25, 75, 75)) proj = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 0]]) points = rot.apply([[1.0 * cosh(a), 2 * sinh(a), 0] for a in np.arange(-3, 3, 0.01)]) points += np.array([0, 0, -min(points[:, 2])]) circ = np.array([[cos(a), sin(a), 0] for a in np.arange(-pi, pi, 0.01)]) fig = plt.figure(figsize=(10, 8)) ax = fig.add_subplot(111, projection="3d") # trajectory ax.plot(*zip(points.T), linewidth=3) # projection ax.plot(*zip(proj.dot(points.T)), "--", linewidth=1) # vertical guidelines for idx in range(0, len(points), floor(len(points) / 6)): ax.plot( [points[idx][0]] * 2, [points[idx][1]] * 2, [0, points[idx][2]], "--", linewidth=1, ) # polar grid of poverty for r in [10, 15, 20, 25]: ax.plot(*zip(*(r * circ)), ":", linewidth=0.5, color="gray") for ang in np.arange(0, 360, 30) * pi / 180: ax.plot( [0, 25 * cos(ang)], [0, 25 * sin(ang)], [0, 0], ":", linewidth=0.5, color="gray" ) # config ax.set_xlabel("X") ax.set_ylabel("Y") ax.set_zlabel("Z") ax.set_title("Simple 3D Hyperbola") set_axes_equal_3d(ax) ax.axis("off") plt.show() [/code] Мне бы хотелось, чтобы сетка в плоскости XY была такой, как эта, которую я адаптировал из https://dev.to/labex/custom-grid-and-polar-projection-in-matplotlib-3e2m. Я хочу, чтобы сетка была обрезана по границам оси и имела метки для расстояния и угла, как здесь. Делительные отметки выглядят великолепно, но в этом нет необходимости. [img]https://i.sstatic.net/oTVaV19A.png[/img]
Вот этот скрипт [code]from math import cosh, sinh
import matplotlib.pyplot as plt import numpy as np from matplotlib.projections import PolarAxes from matplotlib.transforms import Affine2D from mpl_toolkits.axisartist import HostAxes, angle_helper from mpl_toolkits.axisartist.grid_helper_curvelinear import \ GridHelperCurveLinear from scipy.spatial.transform import Rotation
# -- set up for Polar grid # https://dev.to/labex/custom-grid-and-polar-projection-in-matplotlib-3e2m tr = Affine2D().scale(np.pi / 180, 1) + PolarAxes.PolarTransform() extreme_finder = angle_helper.ExtremeFinderCycle( nx=20, ny=20, lon_cycle=360, lat_cycle=None, lon_minmax=None, lat_minmax=(0, np.inf), ) grid_locator1 = angle_helper.LocatorDMS(12) tick_formatter1 = angle_helper.FormatterDMS() # Create GridHelperCurveLinear object grid_helper = GridHelperCurveLinear( tr, extreme_finder=extreme_finder, grid_locator1=grid_locator1, tick_formatter1=tick_formatter1, ) # compute hyperbola rot = Rotation.from_euler("ZXZ", (25, 75, 75)) points = rot.apply([[1.0 * cosh(a), 2 * sinh(a), 0] for a in np.arange(-3, 3, 0.01)]) fig = plt.figure(figsize=(10, 8)) ax = fig.add_subplot(111, axes_class=HostAxes, grid_helper=grid_helper) # trajectory ax.plot(*points.T[:2], linewidth=3) ax.set_xlabel("X") ax.set_ylabel("Y") # Make ticklabels of right and top axis visible ax.axis["right"].major_ticklabels.set_visible(True) ax.axis["top"].major_ticklabels.set_visible(True) # Let right axis show ticklabels for 1st coordinate (angle) ax.axis["right"].get_helper().nth_coord_ticks = 0 # Let bottom axis show ticklabels for 2nd coordinate (radius) ax.axis["bottom"].get_helper().nth_coord_ticks = 1 # Add grid lines ax.grid(True, zorder=0, color="lightgrey", linewidth=0.5) ax.set_aspect("equal") plt.show() [/code] Я хочу создать трехмерный линейный график, но заменю набросок полярной сетки гораздо более привлекательной полярной сеткой, показанной выше. Я просмотрел документацию matplotlib и не увидел никаких упоминаний об использовании 3D-графиков на https://matplotlib.org/stable/gallery/axisartist/demo_curvelinear_grid.html или о настройке 3D-сетки на странице https://matplotlib.org/stable/api/_as_gen/mpl_toolkits.mplot3d.axes3d.Axes3D.grid.html#mpl_toolkits.mplot3d.axes3d.Axes3D.grid