找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 76|回复: 0

[python]把c4d的样条转换成svg

[复制链接]
发表于 2026-4-6 11:50:57 | 显示全部楼层 |阅读模式
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交易特区
您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|Archiver|手机版|管理员邮箱|红警DIY论坛 |网站地图

GMT+8, 2026-4-19 19:23 , Processed in 0.155907 second(s), 16 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表