AutoCAD 如何计算仅由拟合点定义的样条曲线的端切线? [英] How does AutoCAD calculate end tangents for splines defined only by fit points?
问题描述
AutoCAD 允许将 SPLINE 实体存储在仅由定义的 DXF 文件中拟合点,问题是,这样的样条定义有无限数值正确的解决方案,Autodesk 不提供必要的根据给定的拟合点计算所需参数的信息.
tl;dr - 缺失的信息是估计的起点和终点切线全局 B 样条输入切线的方向和幅度使用末端导数进行插值,有人可以帮助计算这个值吗?
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) * m1end_tangent = Vector.from_deg_angle(-100) * m2# 由从给定拟合点和端切线插值的控制顶点定义的第一个样条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)# 结果与 BricsCAD 插值匹配,如果拟合点、起点和终点# 切线显式存储在 DXF 文件中.# 由拟合点定义的第二个样条作为参考spline = msp.add_spline(points, degree=3, dxfattribs={'layer': 'BricsCAD B-spline', 'color': 2})# 将显式起点和终点切线设置为单位向量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 文件中.需要估计起点和终点切线,最佳结果为:来自The NURBS Book"的5 Point Interpolation",Piegl &分蘖
tangents =estimate_tangents(points, method='5-points')# 估计切线角度:(108.43494882292201, -108.43494882292201) 度m1, m2 =estimate_end_tangent_magnitude(points, method='chord')start_tangent = tangents[0].normalize(m1)end_tangent = tangents[-1].normalize(m2)# 由从给定拟合点和端切线插值的控制顶点定义的第一个样条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/'tangents-estimated.dxf')
令人惊讶的估计是不正确的,BricsCAD 样条的切线角为101.0035408517495 和 -101.0035408517495 度.
真正令人讨厌的部分是,如果我使用 BricsCAD 角度作为输入,样条仍然不匹配,所以我假设切线幅度估计与场景 2 不同.
4.理论检查
以下值是根据 BricsCAD 保存的 DXF 文件计算得出的和 SPLINE方法"从拟合点"切换到控制顶点".根据这些数据,我计算了切线角度和大小,切线向量 = 第二个控制顶点 - 第一个控制顶点
required_angle = 101.0035408517495 # 切向量的角度(度)required_magnitude = m1 * 1.3097943444804256 # 切向量的大小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 的样条曲线仅由拟合点定义?
提前致谢,
曼弗雷德
第三个场景似乎已经解决:没有给定端切线的拟合点的 SPLINE 实体.
应用
在 BricsCAD/AutoCAD 和 ezdxf SPLINE 之间没有视觉差异.
描述了从三次贝塞尔曲线到三次样条曲线的转换
- 黄色:BricsCAD 的 SPLINE
- 青色:贝塞尔曲线插值
- 洋红色:全局曲线插值
全局曲线插值是比贝塞尔曲线插值更好的解决方案.它在 B 样条的开始处发散,此时贝塞尔曲线插值完全失败.
继续搜索 AutoCAD 端切线...
AutoCAD allows to store SPLINE entities in the DXF files defined only by fit points, the problem is, that such a spline definition has infinite numerical correct solutions and Autodesk does not provide the necessary information to calculate the required parameters from the given fit points.
tl;dr - The missing information are the estimated start- and end tangents in direction and magnitude for the input tangents to the global B-spline interpolation with end derivatives, can anyone help to calculate this values?
Complete source code on github.
I use BricsCAD for testing, but "Trueview 2020" shows the same results.
1. Scenario
Only fit points are given, using the global curve interpolation without any constraints to get a spline defined by control vertices:
# 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')
The Spline interpolated by BricsCAD from fit points does not match the spline defined by the interpolated control vertices:
2. Scenario
Beside the fit points I store also the start- and end tangent values in the DXF file. The interpolation is done by global curve interpolation with end derivatives (Piegl & Tiller: "The NURBS Book" - chapter 9.2.2).
I chose an arbitrary angle (100 degrees) as start- and end tangents, the tangent magnitude is estimated by the "Total chord length" method.
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')
The Spline interpolated by BricsCAD now matches exactly the spline defined by the interpolated control vertices:
Now I know the interpolation method is correct, all I need to render the same spline from fit points as BricsCAD are the end-tangents in direction and magnitude inferred from the fit points.
3. Scenario
I need the control vertices to render the B-spline, but start- and end tangents are not stored in the DXF file like in scenario 1. Estimation of start- and end tangents is required, best result by: "5 Point Interpolation" from "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')
And surprise the estimations are not correct, BricsCAD spline has tangent angles of 101.0035408517495 and -101.0035408517495 degrees.
And the really annoying part is, if I use the BricsCAD angles as input, the splines still does not match, so I assumed that the tangent magnitude estimation is different from scenario 2.
4. Theory Check
Following values are calculated from a DXF file saved by BricsCAD
and SPLINE "Method" switched from "fit points" to "control vertices".
From this data I calculated the tangent angles and also the magnitudes,
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')
Now the splines match again:
- If tangents are given (stored in DXF) the magnitude of the input tangents for the interpolation function is "total chord length".
- Without given tangents the magnitude is different, in this example:
m1*1.3097943444804256
, but it is not a constant factor.
The big question is: How to estimate the start- and end tangents in direction and magnitude like AutoCAD or BricsCAD for splines defined only by fit points?
Thanks in advance,
Manfred
The 3rd Scenario seems to be solved: SPLINE entities from fit points without given end tangents.
Applying a cubic Bézier curve interpolation seems to be the solution:
There is no visual difference between the BricsCAD/AutoCAD and the ezdxf SPLINE.
The conversion from cubic Bèzier curve to a cubic SPLINE is described here on math.stackexchange.com, and implemented here in ezdxf v0.16 and the source code for the cubic Bézier curve interpolation is here.
This works only for cubic B-splines (the most common used B-spline), and BricsCAD/AutoCAD allow only a degree of 2 or 3 for SPLINE entities defined only by fit points. The only thing missing is an interpolation of quadratic B-splines as quadratic Bézier curves.
Further research showed that quadratic B-splines defined by fit points are loaded into BricsCAD/AutoCAD as cubic B-splines. Addition to the statement above:
BricsCAD and AutoCAD only use a degree of 3 for SPLINE entities defined only by fit points.
The solution for a B-spline without given end tangents is a cubic Bèzier interpolation, no end tangent calculation is needed.
UPDATE: not a solution
Sadly this all works just for small simple B-splines:
- yellow: SPLINE by BricsCAD
- cyan: Bèzier curve interpolation
- magenta: global curve interpolation
The global curve interpolation is the much better solution than the Bèzier curve interpolation. It diverges just at the beginning of the B-spline, where the Bèzier curve interpolation totally fails.
The search for the AutoCAD end tangents continues ...
这篇关于AutoCAD 如何计算仅由拟合点定义的样条曲线的端切线?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!