AutoCAD 如何计算仅由拟合点定义的样条曲线的端切线? [英] How does AutoCAD calculate end tangents for splines defined only by fit points?

查看:39
本文介绍了AutoCAD 如何计算仅由拟合点定义的样条曲线的端切线?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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')

现在样条再次匹配:

  1. 如果给定切线(存储在 DXF 中),则输入切线的幅度插值函数是总弦长".
  2. 如果没有给定的切线,幅度是不同的,在这个例子中: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:

  1. If tangents are given (stored in DXF) the magnitude of the input tangents for the interpolation function is "total chord length".
  2. 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆