NURBS 表面到水密 stl

问题描述

我一直在使用 Python 中的 NURBS 实现 geomdl 进行参数化设计。问题是它是空心的,不能用 cgal 或 3dprinted 处理。我正在寻找一种通过关闭顶部和底部来使其防水的方法。我已经尝试使用 trimesh.covex.convex_hull 库中的 trimesh 函数,但它搞砸了设计。

example image

示例代码

import os
from geomdl import NURBS
from geomdl import construct
from geomdl import exchange
from geomdl.visualization import VisMPL as vis
from geomdl import knotvector

os.chdir(os.path.dirname(os.path.realpath(__file__)))

# Create a NURBS surface instance
surf = NURBS.Surface()

# Set degrees
surf.degree_u = 2
surf.degree_v = 2

# Set control points from a template file
surf.set_ctrlpts(*exchange.import_txt("ctrlpts.cptw",two_dimensional=True,jinja2=True))

# Set knot vectors
surf.knotvector_u = knotvector.generate(surf.degree_u,surf.ctrlpts_size_u)
surf.knotvector_v = knotvector.generate(surf.degree_v,surf.ctrlpts_size_v)#[0,0.25,0.5,0.75,1,1]

# Set evaluation delta
surf.delta = 0.05

exchange.export_stl(surf,"test2.stl")
os.system('fstl ./test2.stl')

和控制点:

4.00,0.00,1.00;2.83,2.83,1.00;0.00,4.00,1.00;-2.83,1.00;-4.00,-2.83,-4.00,1.00;4.00,1.00
4.00,10.00,20.00,30.00,40.00,1.00
4.30,50.00,1.00;3.04,3.04,4.30,1.00;-3.04,1.00;-4.30,-3.04,-4.30,1.00;4.30,1.00
4.60,60.00,1.00;3.25,3.25,4.60,1.00;-3.25,1.00;-4.60,-3.25,-4.60,1.00;4.60,1.00
0.30,70.00,1.00;-0.96,1.00;-7.04,1.00;-8.30,1.00;0.30,1.00
-3.70,80.00,1.00;-4.96,1.00;-8.00,1.00;-11.04,1.00;-12.30,1.00;-3.70,1.00
-7.70,90.00,1.00;-8.96,1.00;-12.00,1.00;-15.04,1.00;-16.30,1.00;-7.70,1.00
-11.70,100.00,1.00;-12.96,1.00;-16.00,1.00;-19.04,1.00;-20.30,1.00;-11.70,1.00
-15.70,110.00,1.00;-16.96,1.00;-20.00,1.00;-23.04,1.00;-24.30,1.00;-15.70,1.00

解决方法

对您来说一个简单易行的方法是使用 3D alpha-shape(也称为凹壳)。您可以对您的 NURBS 曲面进行采样(可能会在“上限”上添加额外的点,但从您问题中的数字我相信在您的上下文中即使这不是必需的),然后构建 3D alpha 形状的曲面,这应该给出您正在寻找的防水网格。

参见 my previous answer 示例,在一组 3D 点上构造(和绘制)alpha 形状的调用的 Python 代码以及进一步的解释。答案基于在这个漂亮的 answer 中找到的 3D alpha 形状代码。

如果您不想使用 alpha 形状,您可以通过对 NURBS 曲面的 uv 域进行均匀采样并从样本索引获取用于创建三角形的连接信息来自己构建防水曲面网格(例如,来自 (u[i],v[j]) 的样本点将创建一个带有 (u[i+1],v[j+1])(u[i],v[j+1]) 的三角形,其他邻居也类似)。 要关闭“盖子”,您可以在管端的中间添加一个附加点(例如在 (u[0],v[:]) 处的点的平均点处,类似地,对于另一端 {{1} 处的平均点})。并从这个附加点到管表面边界圆上的点添加三角形。