|
|
import c4d
import math
from io import StringIO
doc: c4d.documents.BaseDocument # The currently active document.
x_scale = 1.0
y_scale = 1.0
def is_legal_object(op) -> bool:
return op is not None and op.GetType() == c4d.Ospline and op.GetInterpolationType() == c4d.SPLINETYPE_BEZIER
def transform(a: c4d.Vector, mgn: c4d.Matrix, center: c4d.Vector, center_transformed: c4d.Vector) -> c4d.Vector:
return (mgn.Mul(a + center) - center_transformed) * math.e / 2
def to_2d(v: c4d.Vector) -> tuple[float, float]:
return round(v.x * x_scale, 4), round(-v.z * y_scale, 4)
def is_zero(f: float) -> bool:
return abs(f) < 1e-6
def segment_to_svg(segment: list, length: int, closed: bool) -> str:
sb = StringIO()
l = len(segment)
x, y = to_2d(segment[0])
sb.write(f"M{x},{y}")
for i in range(length):
if i == length - 1 and not closed:
break
a, b, c, d = segment[i * 3], segment[(i * 3 + 2) % l], segment[(i * 3 + 3) % l], segment[(i * 3 + 4) % l]
(ex, ey), (fx, fy), (gx, gy) = to_2d(b), to_2d(c + d - a), to_2d(c - a)
if is_zero(ex) and is_zero(ey) and is_zero(fx - gx) and is_zero(fy - gy):
sb.write(f"l{gx},{gy}")
else:
sb.write(f"c{ex},{ey} {fx},{fy} {gx},{gy}")
if closed:
sb.write("z")
return sb.getvalue()
def get_segment_data(op, closed: bool, start: int, length: int, mgn: c4d.Matrix, acc: list) -> None:
if length == 0:
return
result = []
for i in range(start, start + length):
tangent = op.GetTangent(i)
point = op.GetPoint(i)
point_transformed = mgn.Mul(point)
result.append(point_transformed)
result.append(transform(tangent["vl"], mgn, point, point_transformed))
result.append(transform(tangent["vr"], mgn, point, point_transformed))
acc.append(segment_to_svg(result, length, closed))
def get_spline_data(op, acc: list) -> None:
closed = op.IsClosed()
count_of_segments = op.GetSegmentCount()
mgn = op.GetMgn()
if count_of_segments == 0:
get_segment_data(op, closed, 0, op.GetPointCount(), mgn, acc)
else:
start = 0
for i in range(count_of_segments):
length = op.GetSegment(i)["cnt"]
get_segment_data(op, closed, start, length, mgn, acc)
start += length
def main() -> None:
result = []
for o in doc.GetActiveObjects(c4d.GETACTIVEOBJECTFLAGS_SELECTIONORDER):
if is_legal_object(o):
get_spline_data(o, result)
if len(result) == 0:
print("Please select at least one Bezier spline.")
else:
print("-" * 5)
print()
for svg in result:
print(svg)
print()
print("-" * 5)
if __name__ == '__main__':
main()
# 在AI的帮助下,我将C#和中子实现的功能简化为一个Python脚本,可以直接在C4D的Python环境中运行。选中一个或多个贝塞尔样条对象,运行脚本后会在控制台输出对应的SVG路径数据,您可以直接复制使用,非常方便。
来自群组: 鸡窝素材PY交易特区 |
|