AutoCAD 允许将 SPLINE 实体存储在仅由以下定义的 DXF 文件中
拟合点,问题是,这样的样条定义有无限
数值正确的解决方案,Autodesk 不提供必要的
从给定的拟合点计算所需参数的信息。
tl;dr - 缺少的信息是估计的起点和终点切线
全局 B 样条输入切线的方向和大小
带有最终导数的插值,任何人都可以帮助计算这个值吗?
完整源代码在github上。 https://github.com/mozman/ezdxf/blob/master/exploration/spline_end_tangent_estimation.py
我使用 BricsCAD 进行测试,但“Trueview 2020”显示相同的结果。
1. 场景
仅给出拟合点,使用全局曲线插值,没有任何约束
获取由控制顶点定义的样条线:
# First spline defined by control vertices interpolated from given fit points
s = global_bspline_interpolation(points, degree=3)
msp.add_spline(dxfattribs={'color': 4, 'layer': 'Global Interpolation'}).apply_construction_tool(s)
# Second spline defined only by fit points as reference
spline = msp.add_spline(points, degree=3, dxfattribs={'layer': 'BricsCAD B-spline', 'color': 2})
doc.saveas(DIR / 'fit-points-only.dxf')
BricsCAD 从拟合点插值的样条曲线与插值定义的样条曲线不匹配
控制顶点:
2. 场景
除了拟合点之外,我还将起点和终点切线值存储在 DXF 文件中。
插值是通过带有末端导数的全局曲线插值来完成的
(Piegl & Tiller:“NURBS 书”- 第 9.2.2 章)。
我选择任意角度(100 度)作为起点和终点切线,即切线
震级是通过“总弦长”方法估计的。
m1, m2 = estimate_end_tangent_magnitude(points, method='chord')
start_tangent = Vector.from_deg_angle(100) * m1
end_tangent = Vector.from_deg_angle(-100) * m2
# First spline defined by control vertices interpolated from given fit points and end-tangents
s = global_bspline_interpolation(points, degree=3, tangents=(start_tangent, end_tangent))
msp.add_spline(dxfattribs={'color': 4, 'layer': 'Global Interpolation'}).apply_construction_tool(s)
# Result matches the BricsCAD interpolation if fit points, start- and end
# tangents are stored explicit in the DXF file.
# Second spline defined by fit points as reference
spline = msp.add_spline(points, degree=3, dxfattribs={'layer': 'BricsCAD B-spline', 'color': 2})
# set explicit start- and end tangent as unit vectors
spline.dxf.start_tangent = Vector.from_deg_angle(100)
spline.dxf.end_tangent = Vector.from_deg_angle(-100)
doc.saveas(DIR / 'fit-points-and-tangents.dxf')
BricsCAD 插值的样条曲线现在与由 BricsCAD 定义的样条曲线完全匹配
插值控制顶点:
现在我知道插值方法是正确的,我需要从拟合点渲染相同的样条线
因为 BricsCAD 是从拟合点推断出的方向和大小的端点切线。
3. 场景
我需要控制顶点来渲染 B 样条线,但是开始和
末端切线不像场景 1 那样存储在 DXF 文件中。
需要估计起点和终点切线,最佳结果如下:
“5 点插值”来自“The NURBS Book”,Piegl & Tiller
tangents = estimate_tangents(points, method='5-points')
# Estimated tangent angles: (108.43494882292201, -108.43494882292201) degree
m1, m2 = estimate_end_tangent_magnitude(points, method='chord')
start_tangent = tangents[0].normalize(m1)
end_tangent = tangents[-1].normalize(m2)
# First spline defined by control vertices interpolated from given fit points and end-tangents
s = global_bspline_interpolation(points, degree=3, tangents=(start_tangent, end_tangent))
msp.add_spline(dxfattribs={'color': 4, 'layer': 'Global Interpolation'}).apply_construction_tool(s)
# Second spline defined by fit points as reference, but without explicit start- and end
# tangents to see if my estimations are correct.
msp.add_spline(points, degree=3, dxfattribs={'layer': 'BricsCAD B-spline', 'color': 2})
doc.saveas(DIR / 'tangents-estimated.dxf')
令人惊讶的是,估计不正确,BricsCAD 样条线的切线角度为
101.0035408517495 和 -101.0035408517495 度。
真正烦人的部分是,如果我使用 BricsCAD 角度作为输入,
样条曲线仍然不匹配,所以我假设切线大小
估计与场景 2 不同。
4. 理论检验
以下值是根据 BricsCAD 保存的 DXF 文件计算得出的
SPLINE“方法”从“拟合点”切换为“控制顶点”。
根据这些数据,我计算了切线角度和大小,tangent vector = 2nd control vertex - 1st control vertex
required_angle = 101.0035408517495 # angle of tangent vector in degrees
required_magnitude = m1 * 1.3097943444804256 # magnitude of tangent vector
start_tangent = Vector.from_deg_angle(required_angle, required_magnitude)
end_tangent = Vector.from_deg_angle(-required_angle, required_magnitude)
s = global_bspline_interpolation(points, degree=3, tangents=(start_tangent, end_tangent))
msp.add_spline(dxfattribs={'color': 4, 'layer': 'Global Interpolation'}).apply_construction_tool(s)
msp.add_spline(points, degree=3, dxfattribs={'layer': 'BricsCAD B-spline', 'color': 2})
doc.saveas(DIR / 'theory-check.dxf')
现在样条线再次匹配:
- 如果给定切线(存储在 DXF 中),则输入切线的大小
插值函数是“总弦长”。
- 如果没有给定切线,则大小会有所不同,在此示例中:
m1*1.3097943444804256
,
但这不是一个恒定因素。
最大的问题是:如何估计起始切线和终止切线的方向和大小
像 AutoCAD 或 BricsCAD 那样仅由拟合点定义样条曲线?
提前致谢,
Manfred