I tried to build the proposed shape using parametric equations.
There are some approximations, but if you get the exact geometry equations you could refine this to a better version.
In fact, the key is to define the correct equations ... the ideal case would be to ensure continuity.
This example has some caveats: approximations when joining the 2 circles due to geometrical simplification when drawing the small circle from pi
to 0
. Small circle start/end angles should be chosen as the interception of the 2 full circles for a more accurate shape continuity. But again, in the end it depends entirely on your shape specification
Heavly inspired from Plot equation showing a circle

import math
import numpy as np
import matplotlib.pyplot as plt
def compute_x_values(r, theta):
return r * np.cos(theta)
def compute_y_values(r, theta):
return r * np.sin(theta)
def compute_circle(r, theta):
return compute_x_values(r, theta), compute_y_values(r, theta)
def build_big_circle(crop_angle, offset, radius):
start_angle = offset + crop_angle
end_angle = offset + (2 * np.pi) - crop_angle
theta = np.linspace(start_angle, end_angle, 250)
# compute main circle vals
x, y = compute_circle(radius, theta)
return x, y
r = 1
offset = - np.pi / 2
crop_angle = np.pi / 20
x, y = build_big_circle(crop_angle, offset, r)
# now the other form:
# its a half circle from pi to 0
theta2 = np.linspace(np.pi, 0, 100)
# according our code above, angular space left on the circle for the notch is
missing_angle = crop_angle * 2
# the length between to points on a circle is given by the formula
# length = 2 * r * sin(angle/2)
l = math.sin(missing_angle / 2) * r * 2
# we want half the length for a future radius
r2 = l / 2
# the above lines could be optimized to this
# r2 = math.sin(crop_angle) * r
# but I kept intermediate steps for sake of geometric clarity
# equation is same of a circle
x1, y1 = compute_circle(r2, theta2)
# change center on y axis to - big circle radius
y1 = y1 - r
# merge the 2
x_total = np.append(x, x1)
y_total = np.append(y, y1)
# create the global figure
fig, ax = plt.subplots(1)
ax.plot(x_total, y_total)
ax.fill(x_total, y_total, facecolor='lightgrey', linewidth=1)
ax.set_aspect(1)
plt.show()
fig, ax = plt.subplots(1)
ax.plot(x, y)
ax.plot(x1, y1)
ax.set_aspect(1)
plt.show()