cartopy - 在 cartopy 轴之间画线

我画了两组重叠的轴,一组是另一组的放大版。我想在缩放轴的角和它在较大轴上代表的矩形的角之间画线。但是,我画的线稍微偏离了位置。我试图将其浓缩为一个简单的示例:

import cartopy.crs as ccrs
import matplotlib.pyplot as plt


# Create a large figure:
fig = plt.figure(figsize=(10, 10))

# Add an axes set and draw coastlines:
ax1 = plt.axes([0.01, 0.49, 0.8, 0.5], projection=ccrs.PlateCarree())
ax1.set_global()
ax1.coastlines()

# Add a second axes set (overlaps first) and draw coastlines:
ax2 = plt.axes([0.45, 0.35, 0.4, 0.3], projection=ccrs.PlateCarree())
ax2.set_extent([-44, 45, -15, 45], crs=ccrs.PlateCarree())
ax2.coastlines()

# Draw the rectangular extent of the second plot on the first:
x = [-44, 45, 45, -44, -44]
y = [-15, -15, 45, 45, -15]
ax1.fill(x, y, transform=ccrs.PlateCarree(), color='#0323E4', alpha=0.5)
ax1.plot(x, y, transform=ccrs.PlateCarree(), marker='o')

# Now try and draw a line from the bottom left corner of the second axes set
# to the bottom left corner of the extent rectangle in the first plot:
transFigure = fig.transFigure.inverted()
coord1 = transFigure.transform(ax2.transAxes.transform([0, 0]))
coord2 = transFigure.transform(ax1.transData.transform([-45, -15]))
line = plt.Line2D((coord1[0], coord2[0]), (coord1[1], coord2[1]), transform=fig.transFigure)
fig.lines.append(line)

plt.show()

输出如下:

我认为这是因为我在调用 plt.axes() 时明确定义了轴的形状/方面,并且此形状与绘制的 cartopy 轴的形状不匹配宽高比旨在使 map 看起来正确。我可以在对 plt.axes() 的调用中调整坐标轴的形状,使纵横比与 map 的纵横比匹配,并在我期望的位置绘制线,但这并不容易!有没有一种方法可以在坐标变换中考虑到这一点?

最佳答案

AFAIK 并不容易,因为您本质上想在一个 CS 中定义一个点,而在另一个 CS 中定义另一个点(BlendedGenericTransform 允许您在一个 CS 中定义 xs,在另一个 CS 中定义 ys,但不能定义单个点)。

因此,我所知道的唯一解决方案是构造一个变换,该变换需要一定数量的点进行变换。我已经实现了一个 2 点变换类,它在给定第一个变换的情况下变换第一个点,并用另一个变换变换第二个点:

import matplotlib.transform as mtrans

class TwoPointTransformer(mtrans.Transform):
    is_affine = False
    has_inverse = False

    def __init__(self, first_point_transform, second_point_transform):
        self.first_point_transform = first_point_transform
        self.second_point_transform = second_point_transform
        return mtrans.Transform.__init__(self)

    def transform_non_affine(self, values):
        if values.shape != (2, 2):
            raise ValueError('The TwoPointTransformer can only handle '
                             'vectors of 2 points.')
        result = self.first_point_transform.transform_affine(values)
        second_values = self.second_point_transform.transform_affine(values)
        result[1, :] = second_values[1, :]
        return result

然后我可以添加一条用我关心的坐标表示的线:

line = plt.Line2D(xdata=(-45, 0), ydata=(-15, 0),
                  transform=TwoPointTransformer(ax1.transData, ax2.transAxes))

注意:我认为 matplotlib 对具有非仿射变换的行进行缓存存在问题,例如这样。当我们调整图形大小时,这个问题就会显现出来。因此,最简单的解决方案是同时添加以下行:

fig.canvas.mpl_connect('resize_event', lambda v: line.recache())

每次调整图形大小时都会重新计算直线。

这应该可以解决问题。

HTH

https://stackoverflow.com/questions/22543847/

相关文章:

ssis - 如何使用任何命令行、C# 或 T-SQL 导出部署在 "Integration Ser

sapui5 - 禁用诊断工具快捷键

python - 如何在 Django 中订购反向外键?

sql - 如何从 Rails 中的数据库中选择具有 ID 的不同记录?

version-control - Mercurial : Change root of named

pbs - 请求节点的所有处理器

google-maps-api-3 - 地理距离 : Wolfram Alpha not agree

indexing - MariaDB 中的索引键大小限制是多少?

jsf - 如何在 PrimeFaces DataTable 中设置自增列?

django - Django 中的弱实体