我正在尝试使用 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()
目前看起来像:
您可以简单地创建一个圆弧并将其添加到从两点开始的直线上,以在地图上创建抛物线。
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)
结果: