BMesh script

Using methods from https://blender.stackexchange.com/a/132928/15543 re making an ellipse from the eccentricity.
Here is a test script, result image above using values as below. The inner radius is the radius of hole, the outer radius the maximum radius of ellipse, and an angle of eccentricity as explained in link.
Have added a height to keep the "ribs" too, whereas could also use the eccentricity. Am not sure if a scaled circle in 1D, and rotated and projected are same ellipse.
Anyway, the method uses the points created by scribing the hole, and the ellipse as reference points to create ribs and skin them.
Left as a long chain of transforms, instead could make a you-beaut chain matrix, but ...
import bpy
import bmesh
from bpy import context
from mathutils import Matrix, Vector
from math import asin, radians
inner_radius = 0.5
outer_radius = 1.5 # maximum
height = 0.5
eccentricity_angle = radians(45)
number_segments = 32
number_rings = 64
Re = Matrix.Rotation(eccentricity_angle, 3, 'X')
Se = Matrix.Scale(0, 3, (0, 0, 1))
Me = Se @ Re
me = bpy.data.meshes.new("Ell_Toro")
bm = bmesh.new()
Te = Matrix.Translation((1, 0, 0))
def new_rib(angle):
x = Vector((1, 0))
R = Matrix.Rotation(angle, 4, 'Z')
p1 = R @ Vector((inner_radius, 0, 0))
p2 = Me @ (R @ Vector((outer_radius, 0, 0)))
rib = bmesh.ops.create_circle(
bm,
radius=1,
segments=number_segments,
matrix= Matrix.Rotation(radians(-90), 4, 'X') @ Matrix.Translation((1, 0, 0)),
)
Q = Matrix.Rotation(
(p2 - p1).xy.angle_signed(x),
4, 'Z')
bmesh.ops.transform(
bm,
verts=rib["verts"],
matrix = Q,
)
bmesh.ops.transform(
bm,
verts=rib["verts"],
matrix = (0.5 * (p2 - p1).length * Matrix()),
)
bmesh.ops.transform(
bm,
verts=rib["verts"],
matrix=Matrix.Scale(height /(p2 - p1).length, 3, (0, 0, 1)),
)
bmesh.ops.transform(
bm,
verts=rib["verts"],
matrix= Matrix.Translation(p1),
)
return bm.edges[-number_segments:]
angle = radians(360) / number_rings
ribs = [new_rib(i * angle) for i in range(number_rings)]
ribs.append(ribs[0])
while len(ribs) > 1:
rib = ribs.pop()
bmesh.ops.bridge_loops(
bm,
use_pairs=True,
edges=rib + ribs[-1],
)
ob = bpy.data.objects.new("Ell_Toro", me)
bm.to_mesh(me)
context.collection.objects.link(ob)
p2 - p1
, not the one that determines them. Which is giving the oval look. Will fix later. $\endgroup$