Как определить минимальное количество вершин для метода Spline.ToPolyline?

Автор Тема: Как определить минимальное количество вершин для метода Spline.ToPolyline?  (Прочитано 8520 раз)

0 Пользователей и 4 Гостей просматривают эту тему.

Оффлайн Дмитрий ЗагорулькинАвтор темы

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 737
Здравствуйте!
Конвертирую сплайны в полилинии с помощью метода Spline.ToPolyline. В нём первым параметром задаётся количество вершин для аппроксимации. Я полагал, что минимум можно задать 2 вершины - тогда сплайн преобразуется в отрезок. Но на практике оказалось, что с 2-мя вершинами выскакивает исключение eInvalidInput. Поэкспериментировал и выяснил, что корректно срабатывает, если количество вершин аппроксимации не меньше, чем значение Spline.NumControlPoints - 2. И я так подозреваю, что если сплайн будет построен по FitPoints, то надо будет вместо NumControlPoints опираться на количество NumFitPoints. Может, есть какая-то информация о том, как подбирать минимальное кол-во вершин аппроксимации для сплайна? В справке не нашёл такого.

Оффлайн Привалов Дмитрий

  • ADN Club
  • *****
  • Сообщений: 546
  • Карма: 119
В справке не нашёл такого.
Хм в arxdoc.chm вроде написано минимальное количество.

More polyline vertices make a more accurate apporximation, but too many vertices reduces the display performance of the polyline.

numOfVertices must be no smaller than the number of spline fit points.

максимальное скорее всего подобрать из соображений точности, например number of spline fit points * 8

Оффлайн Дмитрий ЗагорулькинАвтор темы

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 737
numOfVertices must be no smaller than the number of spline fit points.
максимальное скорее всего подобрать из соображений точности, например number of spline fit points * 8
Не годится, вот свойства моего сплайна:
Код - C# [Выбрать]
  1.  NumControlPoints = {int} 6
  2.  NumFitPoints = {int} 0
2 больше 0, но для метода требуется значение не менее 4.

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Дмитрий Загорулькин,
Кроме того, что нашел Привалов Дмитрий, никакой информации нет.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Привалов Дмитрий

  • ADN Club
  • *****
  • Сообщений: 546
  • Карма: 119
Не годится
Из справки AutoCAD очевидно, что с количеством управляющих и определяющих точек могут быть "нюансы":

Выполнение некоторых операций приводит к удалению определяющих точек. В этих случаях ручки располагаются в управляющих точках сплайна. К таким операциям относятся обрезка сплайна, перемещение контрольных точек и удаление определяющих данных.

Повысить точность сплайна можно, увеличив количество управляющих точек в какой-либо из его частей, или изменив весовые коэффициенты некоторых из управляющих точек. Повышение весового коэффициента управляющей точки заставляет сплайн проходить ближе к ней. Еще один способ увеличения точности сплайна - повышение его порядка. Порядком сплайна называется число, на единицу большее степени полинома, описывающего сплайн. Например, кубический сплайн имеет порядок 4. Чем выше порядок сплайна, тем больше у него управляющих точек.

Соответственно нужно анализировать больше параметров, ну или не париться и сделать как-то так:
int Points = Math.Max(NumControlPoints, NumFitPoints) *8;

Оффлайн Дмитрий ЗагорулькинАвтор темы

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 737
Выполнение некоторых операций приводит к удалению определяющих точек. В этих случаях ручки располагаются в управляющих точках сплайна. К таким операциям относятся обрезка сплайна, перемещение контрольных точек и удаление определяющих данных.

Повысить точность сплайна можно, увеличив количество управляющих точек в какой-либо из его частей, или изменив весовые коэффициенты некоторых из управляющих точек. Повышение весового коэффициента управляющей точки заставляет сплайн проходить ближе к ней. Еще один способ увеличения точности сплайна - повышение его порядка. Порядком сплайна называется число, на единицу большее степени полинома, описывающего сплайн. Например, кубический сплайн имеет порядок 4. Чем выше порядок сплайна, тем больше у него управляющих точек.
Что-то я не понял, что тут написано... Получается, что у сплайна есть:
- определяющие точки
- управляющие точки
- контрольные точки
Что из этого ControlPoints, а что FitPoints? Может ли ControlPoints быть меньше FitPoints?
ну или не париться и сделать как-то так:
int Points = Math.Max(NumControlPoints, NumFitPoints) *8;
Мне надо определить как можно меньшее число, но чтобы оно не вызывало исключения в методе. Например, мне попался сплайн, у которого NumControlPoints = 111. Если ещё на 8 умножить, то получится дикое количество в 888 вершин! Это нехорошо...
Вот ещё пример попался: длина сплайна 0.0003 ед. чертежа и у него NumControlPoints = 7. Если на 8 умножить, то у такой микроскопической полилинии получится 56 вершин!

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Дмитрий Загорулькин,
Может положится на AutoCAD и не задавать количество вершин?
- управляющие точки
- контрольные точки
Это одно и тоже - ControlPoints. В AutoCAD'е есть два вида сплайнов. В одних есть FitData, в других нет.
https://knowledge.autodesk.com/ru/support/autocad/learn-explore/caas/CloudHelp/cloudhelp/2016/RUS/AutoCAD-Core/files/GUID-58316136-30EB-499C-ACAD-31D0C653B2B2-htm.html
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Привалов Дмитрий

  • ADN Club
  • *****
  • Сообщений: 546
  • Карма: 119
Мне надо определить как можно меньшее число
Это аппроксимация и по идее, чтобы повторить геометрию сплайна полилинией без  сглаживания нужно большее количество точек.

мне попался сплайн, у которого NumControlPoints = 111. Если ещё на 8 умножить, то получится дикое количество в 888 вершин! Это нехорошо...
Возможно это не аргумент. Для раздумья:
1. Возможно полилиния с 888 вершинами пострится быстрее, чем сплайн с 111.
2. Изыскатели как правило все рисуют полилиниями без дуг с большим количеством вершин(заборы, границы, горизонтали и т.д.). Т.к. заказчики могут перекидывать в другие САПРы и простые полилинии перекидываются без проблем. 1000 вершин на полилинию не так уж и много.
3. А может вершин сплайна изначально много, можно оптимизировать, а потом аппроксимировать.
4. Попробовать аппроксимировать другим способом. Александр вроде приводил на форуме пример аппроксимации Curve на примере Polyline.

Оффлайн Привалов Дмитрий

  • ADN Club
  • *****
  • Сообщений: 546
  • Карма: 119
Вот ещё пример попался: длина сплайна 0.0003 ед. чертежа и у него NumControlPoints = 7. Если на 8 умножить, то у такой микроскопической полилинии получится 56 вершин!
Такое в автокаде сплошь и рядом. Выбери свою стратегию для таких объектов:
1. Не обращать внимания, делать единообразно как для всех
2. Не аппроксимировать сплайны, длина которых меньше допуска.
3. Перед аппроксимацией удалить, как объект "нулевой длины" не попадающий в допуск.
4. Нужен для целостности контура? Упростить, можно заменить например на отрезок, начало и конец известны. Или удалить промежуточные точки сплайна.

Оффлайн Дмитрий ЗагорулькинАвтор темы

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 737
Может положиться на AutoCAD и не задавать количество вершин?
Вы про метод ToPolyline без параметра numOfVertices? Я его пробовал, но мне не понравилось, что он по умолчанию очень много вершин создаёт даже для довольно простых кривых. На примере во вложении для этой кривой создалось 222 вершины!
В AutoCAD'е есть два вида сплайнов. В одних есть FitData, в других нет.
Да, и если я всё правильно понимаю, один в другой можно переключать ручкой на сплайне.
1. Возможно полилиния с 888 вершинами пострится быстрее, чем сплайн с 111.
2. Изыскатели как правило все рисуют полилиниями без дуг с большим количеством вершин(заборы, границы, горизонтали и т.д.). Т.к. заказчики могут перекидывать в другие САПРы и простые полилинии перекидываются без проблем. 1000 вершин на полилинию не так уж и много.
Лишние вершины полилиний очень сильно увеличивают размер чертежа и уменьшают быстродействие. Я помню чистил такие чертежи с диким количеством вершин с помощью "прополки" из PLTools и за счёт этого уменьшал вес файла чертежа на десятки мегабайт.
3. А может вершин сплайна изначально много, можно оптимизировать, а потом аппроксимировать.
4. Попробовать аппроксимировать другим способом. Александр вроде приводил на форуме пример аппроксимации Curve на примере Polyline.
Я затем извлекаю вершины из полилинии и выполняю оптимизацию. Поэтому, очень хочется, чтобы изначально в эту оптимизацию приходило как можно меньше вершин. Особенно, на микроскопических сплайнах.
Я пока остановился на таком варианте:
Код - C# [Выбрать]
  1. var splinePointsCount = (uint)Math.Max(spline.NumFitPoints, spline.NumControlPoints);
Использую его для сплайнов, длина которых меньше значимой величины.



Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Я пока остановился на таком варианте:
Это правильно для достаточно гладких сплайнов с достаточно большим количеством вершин. А вот если у него Fit/Knot-точек мало, а он достаточно большой, то точность аппроксимации может быть неудовлетворительной. Аппроксимацию лучше делать, задавшись максимальной высотой хорды. Мне так кажется...
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Дмитрий ЗагорулькинАвтор темы

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 737
Я проводил опыты и пришёл к выводу, что в большинстве случаев 100 точек на сплайн достаточно для первоначальной аппроксимации. Это, конечно, много для простых кривых, но это в среднем меньше, чем использует стандартная аппроксимация. Поэтому, я изначально по умолчанию поставил такую величину как константу. Но сегодня, когда тестировал большой чертёж с кучей сплайнов, среди которых оказалось много крошечных, решил что для них 100 точек многовато. Потому и озадачился минимально допустимым значением.
В итоге, у меня получилось так:
Код - C# [Выбрать]
  1. uint approxVerticesCount = 100;
  2. var splinePointsCount = (uint)Math.Max(spline.NumFitPoints, spline.NumControlPoints);
  3. if (approxVerticesCount < splinePointsCount || (spline.TryGetLength(out var length) && length < tolerance))
  4. {
  5.    approxVerticesCount = splinePointsCount;
  6. }