首页 > 解决方案 > AutoCAD 如何计算仅由拟合点定义的样条曲线的端切线?

问题描述

AutoCAD 允许将 SPLINE 实体存储在仅由拟合点定义的 DXF 文件中,问题是,这样的样条定义具有无限的数值正确解,并且 Autodesk 没有提供必要的信息来根据给定的拟合点计算所需的参数。

tl;dr - 缺少的信息是全局 B 样条插值与末端导数的输入切线在方向和大小上的估计开始和结束切线,任何人都可以帮助计算这个值吗?

github上的完整源代码。

我使用 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:“The NURBS Book” - 第 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 是从拟合点推断出的方向和大小的端切线。

3. 情景

我需要控制顶点来渲染 B 样条,但开始和结束切线不像场景 1 那样存储在 DXF 文件中。需要估计开始和结束切线,最佳结果是:“5 点插值”来自“NURBS 书”,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')

现在样条线再次匹配:

现在样条线再次匹配

  1. 如果给定切线(存储在 DXF 中),则插值函数的输入切线的大小为“总弦长”。
  2. 没有给定切线,大小是不同的,在这个例子中:m1*1.3097943444804256,但它不是一个常数因子。

最大的问题是:对于仅由拟合点定义的样条曲线,如何估计方向和大小的起点和终点切线,如 AutoCAD 或 BricsCAD?

提前致谢,

曼弗雷德

标签: autocadsplinedxf

解决方案


第 3 种情况似乎已解决:没有给定端切线的拟合点的 SPLINE 实体。

应用三次贝塞尔曲线插值似乎是解决方案:

在此处输入图像描述

BricsCAD/AutoCAD 和 ezdxf SPLINE 之间没有视觉差异。

从三次贝塞尔曲线到三次样条曲线的转换在 math.stackexchange.com 上进行了描述,并在 ezdxf v0.16 中实现三次贝塞尔曲线插值的源代码这里

这仅适用于三次 B 样条(最常用的 B 样条),BricsCAD/AutoCAD 仅允许仅由拟合点定义的样条实体的度数为 2 或 3。唯一缺少的是将二次 B 样条插值作为二次贝塞尔曲线。

进一步的研究表明,由拟合点定义的二次 B 样条作为三次 B 样条加载到 BricsCAD/AutoCAD 中。除了上面的声明:

BricsCAD 和 AutoCAD 仅对仅由拟合点定义的 SPLINE 实体使用 3 阶。

没有给定端切线的 B 样条的解决方案是三次贝塞尔插值,不需要端切线计算。

更新:不是解决方案

可悲的是,这一切都只适用于小的简单 B 样条曲线:

复杂样条

  • 黄色:BricsCAD 的 SPLINE
  • 青色:贝塞尔曲线插值
  • 洋红色:全局曲线插值

全局曲线插值是比贝塞尔曲线插值更好的解决方案。它在 B 样条的开头发散,贝塞尔曲线插值完全失败。

继续搜索 AutoCAD 端切线...


推荐阅读