Как AutoCAD рассчитывает конечные касательные для шлицев, определяемых только точками подгонки?

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 по точкам подгонки, не соответствует сплайну, заданному интерполированными контрольными вершинами:

«Сплайн

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, - это конечные касательные по направлению и величине, выведенные из точек подгонки.

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 градусов.

шлицы снова не совпадают

И действительно раздражает то, что если я использую углы 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')

Теперь шлицы снова совпадают:

теперь шлицы снова совпадают

  1. Если касательные заданы (сохранены в DXF), величина входных касательных для функции интерполяции равна «общей длине хорды».
  2. Без заданных касательных величина будет другой, в этом примере: m1*1.3097943444804256, но это не постоянный коэффициент.

Большой вопрос: Как оценить начальную и конечную касательные по направлению и величине, как в AutoCAD или BricsCAD для шлицев, определяемых только точками подгонки?

Заранее спасибо,

Манфред


person mozman    schedule 19.06.2020    source источник
comment
Время от времени я боролся с тем, как AutoCAD вычисляет некоторые из их значений, например, с дугами и эллипсами. Этот не из моей лиги. Похоже, это могло бы немного привлечь внимание к Math.SE, вы пробовали и там?   -  person Stewbob    schedule 23.06.2020


Ответы (2)


Объект SPLINE может иметь необязательные коды группы 12,22,32 для начальной касательной x, y, z и 13,23,33 для конечной касательной x, y, z. Я проверил исходный код проекта netDxf, и из этого следует, что если для определения сплайна используются только точки подгонки, то необходимо указать значения начала и конца касательной.

Из справочника AutoCAD 2012 DXF для объекта SPLINE:

12 Начальная касательная - можно не указывать (в WCS) DXF: значение X; ПРИЛОЖЕНИЕ: 3D-точка

22, 32 DXF: значения Y и Z начальной касательной - могут быть опущены (в WCS)

13 Конечная касательная - можно не указывать (в WCS) DXF: значение X; ПРИЛОЖЕНИЕ: 3D-точка

23, 33 DXF: значения Y и Z конечной касательной - могут быть опущены (в WCS)

Вчера мы с моим коллегой по Autocad 2020 создали несколько файлов DXF, включая шлицы с точками посадки. После экспорта в DXF шлицы определялись контрольными точками и узлами. Так что я предполагаю, что очки подгонки - это что-то устаревшее или предназначенное только для пользовательского интерфейса.

person Anatolijs Gorbunovs    schedule 02.09.2020
comment
Спасибо! Но причиной этого вопроса было воссоздание того же сплайна, что и в AutoCAD или BricsCAD, если конечные касательные не заданы / указаны. Задача решена для заданных касательных к концам. У вас будет такая же проблема, если вы получите файлы DXF из других источников, кроме AutoCAD (например, пользователей ezdxf ;-), и СПЛАЙН, определенный только точками подгонки без конечных касательных, является допустимой конструкцией DXF. - person mozman; 02.09.2020

Кажется, что третий сценарий решен: объекты СПЛАЙН из подходящих точек без заданных конечных касательных.

Решением может быть применение кубической интерполяции кривой Безье:

введите описание изображения здесь

Визуальной разницы между BricsCAD / AutoCAD и ezdxf SPLINE нет.

Преобразование кубической кривой Безье в кубический СПЛАЙН описывается здесь на math.stackexchange.com и реализованы здесь в ezdxf v0.16, а исходный код интерполяции кубической кривой Безье - здесь.

Это работает только для кубических B-сплайнов (наиболее часто используемых B-сплайнов), а BricsCAD / AutoCAD допускает только степень 2 или 3 для объектов SPLINE, определяемых только точками подгонки. Не хватает только интерполяции квадратичных B-сплайнов как квадратичных кривых Безье.

Дальнейшие исследования показали, что квадратичные B-сплайны, определяемые точками подгонки, загружаются в BricsCAD / AutoCAD как кубические B-сплайны. Дополнение к приведенному выше утверждению:

BricsCAD и AutoCAD используют степень 3 только для объектов СПЛАЙН, определяемых только точками подгонки.

Решением для B-сплайна без заданных конечных касательных является кубическая интерполяция Безье, вычисление конечных касательных не требуется.

ОБНОВЛЕНИЕ: не решение

К сожалению, все это работает только для небольших простых B-сплайнов:

Комплексный сплайн

  • желтый: SPLINE от BricsCAD
  • голубой: интерполяция кривой Безье
  • пурпурный: интерполяция глобальной кривой

Интерполяция глобальной кривой - гораздо лучшее решение, чем интерполяция кривой Безье. Он расходится в самом начале B-сплайна, где интерполяция кривой Безье полностью не выполняется.

Поиск касательных к концам AutoCAD продолжается ...

person mozman    schedule 25.02.2021