import matplotlib.pyplot as plt
import numpy as np
from io import StringIO

# Left: the "unit circle" (all points at distance 1 from the origin) under three metrics.
# Right: one pair of points, a = (1, 2) and b = (4, 6), measured three ways.
plt.rcParams.update({'text.color': 'gray', 'axes.labelcolor': 'gray', 'axes.edgecolor': 'gray',
                     'xtick.color': 'gray', 'ytick.color': 'gray'})
BLUE, ORANGE, GREEN = '#58a6ff', '#f0883e', '#3fb950'

fig, (left, right) = plt.subplots(1, 2, figsize=(9.5, 4.4))

t = np.linspace(0, 2 * np.pi, 400)
left.plot(np.cos(t), np.sin(t), color=BLUE, lw=2, label='p = 2, Euclidean')
left.plot([1, 0, -1, 0, 1], [0, 1, 0, -1, 0], color=ORANGE, lw=2, label='p = 1, Manhattan')
left.plot([1, -1, -1, 1, 1], [1, 1, -1, -1, 1], color=GREEN, lw=2, label='p = ∞, Chebyshev')
left.scatter([0], [0], color='gray', s=15)
left.set_xlim(-1.6, 1.6)
left.set_ylim(-1.6, 1.9)
left.set_aspect('equal')
left.legend(fontsize=8, loc='upper center', ncol=1, frameon=False)
left.set_title('All points at distance 1 from the origin', fontsize=10)
left.tick_params(labelsize=8)

a, b = np.array([1, 2]), np.array([4, 6])
right.plot([a[0], b[0], b[0]], [a[1], a[1], b[1]], color=ORANGE, lw=2.2,
           label='Manhattan: |4−1| + |6−2| = 3 + 4 = 7')
right.plot([a[0], b[0]], [a[1], b[1]], color=BLUE, lw=2.2,
           label='Euclidean: √(3² + 4²) = 5')
right.plot([a[0] - 0.25, a[0] - 0.25], [a[1], b[1]], color=GREEN, lw=2.2,
           label='Chebyshev: max(3, 4) = 4')
right.scatter(*zip(a, b), color='gray', s=40, zorder=3)
right.annotate('a = (1, 2)', a, xytext=(6, -14), textcoords='offset points', fontsize=9)
right.annotate('b = (4, 6)', b, xytext=(6, 4), textcoords='offset points', fontsize=9)
right.set_xlim(0, 6.5)
right.set_ylim(0.5, 8.3)
right.set_aspect('equal')
right.legend(fontsize=8, loc='upper left', frameon=False)
right.set_title('One pair of points, three distances', fontsize=10)
right.tick_params(labelsize=8)

plt.tight_layout()

buffer = StringIO()
plt.savefig(buffer, format="svg", transparent=True)
print(buffer.getvalue())

plt.close()
