Untitled

mail@pastecode.io avatar
unknown
python
a year ago
2.5 kB
3
Indexable
Never
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.path import Path
from matplotlib.patches import PathPatch

def linear_interpolation(p1, p2, t):
    return tuple(a + t * (b - a) for a, b in zip(p1, p2))

def normalize_vector(v):
    return v / np.linalg.norm(v)

def absolute_padding(p1, p2, padding):
    direction = normalize_vector(np.array(p2) - np.array(p1))
    return tuple(np.array(p1) + padding * direction)

def interpolate_points(ax, x, y, pad, open=False, absolute_pad=False, **kwargs):
    verts = []
    codes = []

    points = list(zip(x, y))
    n = len(points)

    for i, (prev_pt, curr_pt, next_pt) in enumerate(zip(points[-1:] + points[:-1], points, points[1:] + points[:1])):
        if i == 0:
            if open:
                codes.append(Path.MOVETO)
                verts.append(curr_pt)
            else:
                if absolute_pad:
                    smoothed_pt = absolute_padding(curr_pt, prev_pt, pad)
                else:
                    smoothed_pt = linear_interpolation(prev_pt, curr_pt, 1 - pad)
                codes.append(Path.MOVETO)
                verts.append(smoothed_pt)

        else:
            if absolute_pad:
                if open and i == n - 1:
                    smoothed_pt = curr_pt
                else:
                    smoothed_pt = absolute_padding(curr_pt, prev_pt, pad)
            else:
                if open and i == n - 1:
                    smoothed_pt = curr_pt
                else:
                    smoothed_pt = linear_interpolation(prev_pt, curr_pt, 1 - pad)
            codes.append(Path.LINETO)
            verts.append(smoothed_pt)

        if not open or i < n - 1:
            if absolute_pad:
                smoothed_pt = absolute_padding(curr_pt, next_pt, pad)
            else:
                smoothed_pt = linear_interpolation(curr_pt, next_pt, pad)
            
            codes.extend([Path.CURVE3, Path.CURVE3])
            verts.extend([curr_pt, smoothed_pt])

    if not open:
        codes.append(Path.LINETO)
        verts.append(verts[0])

    rounded_path = Path(verts, codes)
    rounded_patch = PathPatch(rounded_path, **kwargs)
    ax.add_patch(rounded_patch)

fig, ax = plt.subplots(dpi=220, figsize=(1.5, 1.5))
x = np.array([0.25, 0.25, 0.75, 0.75]) 
y = np.array([0, 1, 1, 0])
ax.plot(x, y, 'o:', 'k', mfc='r', zorder=2)
ax.set_xlim(-0.5, 1.5)
ax.set_ylim(-0.5, 1.5)
interpolate_points(ax, x, y, 0.25, open=True, absolute_pad=True, facecolor='red', edgecolor='k', alpha=1/3)
plt.show()