来自我在BSE 这里 的回答。
我将其添加到stackoverflow中,因为它是一种不依赖于固定迭代步骤而依赖于点之间距离收敛到平均距离的不同方法。
因此,计算时间更短,只取决于所需顶点数量和要达到的精度(小于0.01%需要约6次迭代)。
原理如下:
0/ 第一步:使用a * cos(t)和b * sin(t)正常计算点
1/ 计算顶点之间的长度
2/ 根据每个距离与平均距离之间的差距调整角度变化
3/ 重新定位点
4/ 当达到所需精度时退出或返回1/
import bpy, bmesh
from math import radians, sqrt, cos, sin
rad90 = radians( 90.0 )
rad180 = radians( 180.0 )
def createVertex( bm, x, y ):
return bm.verts.new( [x, y, 0] )
def listSum( list, index ):
sum = 0
for i in list:
sum = sum + i[index]
return sum
def calcLength( points ):
prevPoint = points[0]
for point in points :
dx = point[0] - prevPoint[0]
dy = point[1] - prevPoint[1]
dist = sqrt( dx * dx + dy *dy )
point[3] = dist
prevPoint = point
def calcPos( points, a, b ):
angle = 0
for i in range( 1, len(points) - 1 ):
point = points[i]
angle += point[2]
point[0] = a * cos( angle )
point[1] = b * sin( angle )
def adjust( points ):
totalLength = listSum( points, 3 )
averageLength = totalLength / (len(points) - 1)
maxRatio = 0
for i in range( 1, len(points) ):
point = points[i]
ratio = (averageLength - point[3]) / averageLength
point[2] = (1.0 + ratio) * point[2]
absRatio = abs( ratio )
if absRatio > maxRatio:
maxRatio = absRatio
return maxRatio
def ellipse( bm, a, b, steps, limit ):
delta = rad90 / steps
angle = 0.0
points = []
for step in range( steps + 1 ) :
x = a * cos( angle )
y = b * sin( angle )
points.append( [x, y, delta, 0.0] )
angle += delta
print( 'start' )
doContinue = True
while doContinue:
calcLength( points )
maxRatio = adjust( points )
calcPos( points, a, b )
doContinue = maxRatio > limit
print( maxRatio )
verts = []
for point in points:
verts.append( createVertex( bm, point[0], point[1] ) )
for i in range( 1, len(verts) ):
bm.edges.new( [verts[i - 1], verts[i]] )
A = 4
B = 6
bm = bmesh.new()
ellipse( bm, A, B, 32, 0.00001 )
mesh = bpy.context.object.data
bm.to_mesh(mesh)
mesh.update()