Issue
I am trying to create a connection graph using Python. I'd like a series of points across the UK converging on a target, with accentuated parabolic arcs.
I have a code attempt that is plotting straight lines at the moment. I'd like to increase the curvature of these lines with a parameter.
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()
Currently looks like:
I'd like a figure with arcs similar to this, working on the scale of within the UK:
Solution
You can simply create an arc and add it to your line from two points to create a parabolic curve on the map. The distance
and arc_ratio
variables are used to make the curve better.
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)
The result:
Answered By - Ali Ent
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.