You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将文本渲染为多填充多边形并转直线段以挤出3D三角网格?

将文本挤出为3D三角网格的解决方案

核心思路

利用fontTools提取字体轮廓,借助其内置的贝塞尔曲线细分工具将曲线自动转为直线段,再用trimesh完成挤出操作,无需自行实现曲线转直线的核心逻辑。

步骤1:提取并转换字体轮廓为直线段

通过fontTools加载字体,记录字形路径后,用自带工具将曲线转为满足精度要求的直线段:

from fontTools.ttLib import TTFont
from fontTools.pens.recordingPen import RecordingPen
from fontTools.misc.bezierTools import splitCubicAtT

def convert_curve_to_lines(commands, tolerance=0.1):
    """将路径命令中的曲线转为直线段,tolerance控制近似精度"""
    line_commands = []
    current_point = None
    for cmd, args in commands:
        if cmd == "moveTo":
            current_point = args[0]
            line_commands.append(("moveTo", current_point))
        elif cmd == "lineTo":
            line_commands.append(("lineTo", args[0]))
            current_point = args[0]
        elif cmd == "curveTo":
            # 递归细分三次贝塞尔曲线,直到线段足够短
            pt1, pt2, pt3 = args
            _subdivide_cubic_segment(current_point, pt1, pt2, pt3, tolerance, line_commands)
            current_point = pt3
        elif cmd == "closePath":
            line_commands.append(("closePath",))
    return line_commands

def _subdivide_cubic_segment(p0, p1, p2, p3, tolerance, line_list):
    """递归细分贝塞尔曲线生成直线段"""
    dx, dy = p3[0] - p0[0], p3[1] - p0[1]
    if dx*dx + dy*dy <= tolerance*tolerance:
        line_list.append(("lineTo", p3))
        return
    # 拆分曲线为两段,递归处理
    t = 0.5
    _, _, _, mid_point = splitCubicAtT(p0, p1, p2, p3, t)
    p0a, p1a, p2a, _ = splitCubicAtT(p0, p1, p2, p3, t)
    _, p1b, p2b, p3b = splitCubicAtT(p0, p1, p2, p3, 1-t)
    _subdivide_cubic_segment(p0a, p1a, p2a, mid_point, tolerance, line_list)
    _subdivide_cubic_segment(mid_point, p1b, p2b, p3b, tolerance, line_list)

# 加载目标字体(替换为你的字体路径)
font = TTFont("arial.ttf")
glyph_set = font.getGlyphSet()
# 获取目标字符的字形(这里以字符"A"为例)
target_glyph = glyph_set["A"]

# 记录字形路径
pen = RecordingPen()
target_glyph.draw(pen)

# 转换为纯直线段路径
line_path = convert_curve_to_lines(pen.value, tolerance=0.5)

步骤2:用trimesh挤出为3D网格

将转换后的直线段路径转为trimesh可识别的多边形,执行挤出操作:

import trimesh

def lines_to_polygons(line_commands):
    """将直线段命令转为多边形列表"""
    polygons = []
    current_poly = []
    for cmd, *args in line_commands:
        if cmd == "moveTo":
            if current_poly:
                polygons.append(current_poly)
                current_poly = []
            current_poly.append(args[0])
        elif cmd == "lineTo":
            current_poly.append(args[0])
        elif cmd == "closePath":
            current_poly.append(current_poly[0])
            polygons.append(current_poly)
            current_poly = []
    return polygons

# 生成多边形
text_polygons = lines_to_polygons(line_path)
# 转为trimesh的2D路径
path_2d = trimesh.load_path(text_polygons)
# 挤出为3D网格(height为挤出高度)
extruded_mesh = path_2d.extrude(height=2.0)

# 保存为STL文件或显示
extruded_mesh.export("text_3d.stl")
extruded_mesh.show()

替代方案:基于图像提取轮廓

如果不想处理字体曲线,也可以用PIL生成文本图像,再提取轮廓转3D:

from PIL import Image, ImageDraw
import trimesh
import numpy as np

# 生成文本图像
img = Image.new("L", (200, 100), 0)
draw = ImageDraw.Draw(img)
draw.text((20, 20), "A", fill=255)  # 可指定font参数自定义字体
img_np = np.array(img)

# 提取轮廓并挤出
contours = trimesh.util.extract_contours(img_np)
mesh = trimesh.extrude(contours[0], height=2.0)
mesh.show()

内容的提问来源于stack exchange,提问作者cube

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 14:18:27