使用 Matplotlib 的抛物线连接图

问题描述 投票:0回答:1

我正在尝试使用 Python 创建连接图。我希望英国各地的一系列点会聚在一个目标上,并带有突出的抛物线弧。

我目前正在尝试绘制直线的代码。我想用参数增加这些线的曲率。

import numpy as np
import matplotlib.pyplot as plt
import geopandas as gpd
import contextily as ctx
import sympy as sm

def plot_connection(ax, start_point, end_point):
    x1, y1 = start_point[0], start_point[1]
    x3, y3 = end_point[0], end_point[1]
    
    x2 = (x1 + x3) / 2
    y2 = (y1 + y3) / 2
    
    x = np.array([x1, x2, x3])
    y = np.array([y1, y2, y3])

    a, b, c = sm.symbols('a b c', real=True)
    
    eq1 = sm.Eq((x[0]**2) * a + x[0] * b + c, y[0])
    eq2 = sm.Eq((x[1]**2) * a + x[1] * b + c, y[1])
    eq3 = sm.Eq((x[2]**2) * a + x[2] * b + c, y[2])

    sol = sm.solve([eq1, eq2, eq3], (a, b, c))

    def f(x):
        return sol[a] * (x**2) + sol[b] * x + sol[c]

    col = np.tan(np.linspace(-1, 1, 1500))
    plt.scatter(np.linspace(x[0], x[-1], 1500), f(np.linspace(x[0], x[-1], 1500)),
                c=col, zorder=-3, cmap='gray', s=0.005, alpha=0.6)

#london point 1, point 2
target = (-251467.639557, 7014473.211674)
london = (-23236.856599, 6713617.068344)
glasgow = (-472686.582916, 7534245.004013)
leeds = (-173664.928264, 7133714.975799)
brighton = (-14675.909431, 6599267.274029)
darmstadt = (88791.533909, 6672007.566294)
manchester = (-251095.637917, 7069851.838667)

fig, ax = plt.subplots(figsize=(15, 15))

#make a df of points across the uk
import pandas as pd

plot_connection(ax, target, london)
plot_connection(ax, target, glasgow)
plot_connection(ax, target, leeds)
plot_connection(ax, target, brighton)
plot_connection(ax, target, darmstadt)
plot_connection(ax, target, manchester)

#add xlim ylim over uk
# ax.set_xlim(-520000, 175000)
# ax.set_ylim(6500000, 8200000)

ctx.add_basemap(ax, source=ctx.providers.CartoDB.PositronNoLabels, zorder=-4, crs='EPSG:3857')
ax.axis('off')
plt.tight_layout()

目前看起来像:

我想要一个具有与此类似的弧线的图形,按英国境内的比例工作:

python matplotlib visualization geospatial
1个回答
0
投票

您可以简单地创建一个圆弧并将其添加到从两点开始的直线上,以在地图上创建抛物线。

distance
arc_ratio
变量用于使曲线更好。

def plot_connection(ax, start_point, end_point):
    
    x = np.linspace(start_point[0], end_point[0], 1500)
    y = np.linspace(start_point[1], end_point[1], 1500)
    distance = np.sqrt((start_point[0]-end_point[0])**2+(start_point[1]-end_point[1])**2)

    arc_ratio = 0.5 # 0 -> straight line; higher ratio creates bigger curve
    arc = (1-np.linspace(-1, 1, 1500)**2) * distance * arc_ratio
    y += arc

    col = np.tan(np.linspace(-1, 1, 1500))
    plt.scatter(x, y, c=col, zorder=-3, cmap='gray', s=0.005, alpha=0.6)

结果:

© www.soinside.com 2019 - 2024. All rights reserved.