AutoCAD позволяет сохранять объекты СПЛАЙН в файлах 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 из подходящих точек, не соответствует сплайн, определяемый интерполированными управляющими вершинами:
![Spline without constraints](https://i.stack.imgur.com/0y986.png)
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, теперь точно соответствует сплайну, заданному интерполированными контрольными вершинами:
![matching splines](https://i.stack.imgur.com/bes5c.png)
Теперь я знаю, что метод интерполяции правильный, все, что мне нужно для рендеринга одного и того же сплайна из точек подгонки, так как BricsCAD, - это касательные на концах в направлении и величине, полученные из точек подгонки.
3. Сценарий
Мне нужны контрольные вершины для рендеринга B-сплайна, но начальные и конечные касательные не сохраняются в файле DXF, как в сценарии 1. Требуется оценка начальных и конечных касательных, лучший результат по : "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 градусов.
![splines do not match again](https://i.stack.imgur.com/cvgma.png)
И действительно раздражает то, что если я использую углы BricsCAD в качестве входных данных, сплайны все равно не совпадают, поэтому я предположил, что оценка тангенциальной величины отличается от сценарий 2.
4. Проверка теории
Следующие значения вычисляются из файла DXF, сохраненного BricsCAD, и 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')
Теперь шлицы снова совпадают:
![now the splines match again](https://i.stack.imgur.com/1BMLm.png)
- Если касательные заданы (сохранены в DXF), величина входных касательных для функции интерполяции равна «общей длине хорды».
- Без заданных касательных величина отличается, в этом примере:
m1*1.3097943444804256
, но это не постоянный коэффициент.
Большой вопрос: Как оценить начальную и конечную касательные по направлению и величине, как в AutoCAD или BricsCAD для сплайнов, определяемых только подходят точки?
Заранее спасибо,
Манфред