Александр Максименко, руководитель отдела разработки C3D Solver, C3D Labs, показывает, какие возможности открываются для параметрического черчения и моделирования в 3D, если задействовать новый инструментарий решения и диагностики модуля C3D Solver.
Разработка математического ядра — это сложный квест с большим числом нюансов. И хотелось бы рассказать о многих тонкостях, но в данном обзоре я выделил четыре темы. Первая посвящена диагностике при параметрическом черчении, другие три — отрезкам нулевой длины, опции касания и многопоточности.
C3D Solver как модуль состоит из двух компонентов. Первый предназначен для обслуживания параметрических чертежей и выступает в качестве чертежного процессора. Второй — трехмерный компонент — решает задачи сопряжения деталей сборки, кинематического анализа и каркасного моделирования.
Оба компонента реализуют декларативный подход. Что это значит? Пользователь описывает желаемое решение в терминах ограничений, параметров и размеров, солвер исполняет поставленную задачу. Основная задача C3D Solver звучит просто — найти такое положение геометрическим объектам, при котором все геометрические и размерные ограничения будут удовлетворены. Кроме основной, есть сопутствующие задачи, среди которых выделим диагностическую.
C3D Solver снабжает инженера информацией о том, на какой стадии его чертеж и есть ли в нем потенциальные проблемы. В связи с этим различаем следующие состояния эскиза.
- Недоопределенное состояние, когда существуют объекты с ненулевой степенью свободы. Именно с этим состоянием инженер имеет дело большую часть времени, задавая одно ограничение за другим, пока не достигнет следующего состояния — полной определенности геометрии.
- Полностью определенное состояние, означающее, что все объекты заняли свои места в соответствии с задумкой пользователя и не имеют свободы движения при заданной (означенной) конфигурации управляющих размеров.
- Этим двум состояниям может сопутствовать третье, переопределенное, означающее, что в эскизе имеются лишние уравнения. Переопределенности могут быть двух родов. Первый — с противоречием, подразумевающим невозможность решить эскиз. Системы ограничений в состоянии такого рода называются несовместными. Второй род — переопределенности без противоречий, то есть просто лишние уравнения, удаление которых не меняет множества возможных решений.
В одной модели могут соседствовать и недо-, и пере-, и полноопределенные участки чертежа. Тут надо заметить, что всякая переопределенность распространяется не на чертеж целиком, а на какой-то его участок, имеющий по меньшей мере какие-то два ограничения, избыточные по отношению друг другу. Забегая вперед, скажу, что не всякая избыточность приводит к проблеме. Некоторые избыточности не создают помех для работоспособности параметрического чертежа, C3D Solver хорошо с ними справляется.
О недоопределенных участках чертежа пользователь узнает с помощью вызовов API, в рамках которых он может запросить контрольные точки объектов, и каждая точка выдаст степень свободы от нуля до двух и вектор возможного движения. Для скалярных параметров есть функция GCE_CoordDOF, благодаря которой можно узнать, например, свободен ли радиус окружности.
О существовании переопределений или противоречий в чертеже можно узнать, если опросить каждое ограничение с помощью вызова API GCE_ConstraintStatus. Эта функция говорит о том, к какому подмножеству C3D Solver отнес ограничение. Допустим, есть хорошо обусловленная часть ограничений со статусами Well-treated и Well-conditioned. Ограничения, отмеченные Well-treated, относятся к хорошо обрабатываемой части системы, не вовлеченной ни в какие переопределения. Оба статуса образуют хорошо обусловленную часть системы, но Well-conditioned также может попасть в подмножество избыточных ограничений, образованное тремя статусами: Well-conditioned, Ill-conditioned и Redundant. Статус Redundant означает доказанную избыточность, а это определенно положительный результат, в то время как Ill-conditioned служит предварительной оценкой, при которой C3D Solver не дает точного вывода. Однако он обращает внимание пользователя на существующую систему ограничений.
Типы переопределений
Предположительно избыточные
C3D Solver способен справляться с подобными классами случаев. Предварительный анализ осуществляется методами линейной алгебры применительно к линейному приближению системы уравнений (прошедшей линеаризацию). Линеаризованная система уравнений «подсказывает», в каких местах могут быть лишние уравнения, а C3D Solver делает предположения об избыточности, и если предположение подтверждается доказательными методами, то ограничение получает статус Redundant, в противном случае — статус Ill-conditioned.
Случаи доказанной избыточности
Важность выявления лишних уравнений напрямую связана с точностью и адекватностью вывода степеней свободы, чтобы пользователь знал, какая геометрия чертежа все еще недоопределена. Поэтому при разработке алгоритмов диагностики C3D Solver мы фокусируемся на том, чтобы научиться выявлять новые случаи Redundant и оставлять все меньше случаев с недоказанной избыточностью типа Ill-conditioned.
Например, с чем хорошо справляется C3D Solver, — это всякого рода комбинации с параллельностью, перпендикулярностью, горизонтальностью, вертикальностью, коллинеарностью, фиксацией углов и т. д. Вдоль этих цепочек он эффективно выявляет избыточности, образно говоря, «выбрасывает» их, чтобы они не мешали решению.
Другой класс доказательной избыточности выявляют алгебро-геометрические методы, позволяющие найти в системе нелинейные уравнения, которые могут быть заменены на линейные с сохранением множества решений. Подсистемы, состоящие из линейно-приведенных уравнений, позволяют легко доказывать избыточность.
Методы дискретной математики также помогают найти ограничения со статусом Redundant. Самое очевидное — это вытеснение избыточных ограничений по переполнению графа распределения степеней свободы и ограничений.
Избыточность инвариантных ограничений кластера
Новый интересный случай, который мы научились обрабатывать, — это алгоритм поиска кластеров. Кластеры — это подмножества чертежа, которые характеризуются преобразованиями переноса, поворота и масштаба. То есть группами преобразований, в случае которых все ограничения остаются удовлетворенными (инвариантными). При обнаружении такого кластера на нем хорошо выявляются лишние ограничения. На иллюстрации справа представлен пример прямоугольного треугольника ABC с избыточным набором ограничений, инвариантных к переносу. Это значит, что у кластера должно быть 2 степени свободы переноса (TDOF = 2) и 0 степеней свободы вращения (RDOF=0). Для кластера с такой конфигурацией степеней свободы должно оставаться не более 6-2=4 уравнений. Пятое ограничение, например «перпендикулярность», вытесняется как лишнее. Оно уже обеспечено четверкой других.
Слева на иллюстрации продемонстрирован нередкий случай в инженерных чертежах — паз. Именно на нем мы улучшили вывод избыточности. На дуге AB радиуса R выявляется, например, лишнее расстояние. Это важно, так как повышает результативность дальнейшего анализа. При этом кластер этой дуги вместе с его радиусами и distance-ограничениями представляет собой не только жесткий поворотно-переносный объект, но еще и масштабируемый, который может растягиваться.
Если суммировать все эти методы выявления классов инвариантности, обнаружится, что мы достигли улучшения в тех ситуациях, в которых наблюдалось ложное занижение степени свободы. Это характерно для чертежей, в которых пользователь находится в одном шаге до полной определенности, но из-за наличия лишних уравнений система информирует его о том, что у нее все определено, а значит, вводит в заблуждение. Фактически мы избавились от подобных проблем.
Как следствие, появился драггинг. Драггинг — изменение геометрии чертежа в рамках степеней свободы с помощью переноса контрольных точек чертежа «мышкой».
Другое достижение заключается в том, что во многих случаях нечеткий статус Ill-conditioned заменился на доказательный статус Redundant. Избыточность ограничений со статусом Redundant можно смело игнорировать и даже не показывать пользователю, если они не создают противоречий.
Приятная неожиданность, обнаруженная в ходе тестирования, — это быстрая отсечка бесперспективных попыток решения, когда решения не существует. C3D Solver исключает из вычислений избыточное ограничение, которое невозможно удовлетворить.
Итак, речь шла о том, как C3D Solver справляется с переопределенными системами ограничений, их диагностикой и решением. С другой стороны, неоспорима важность качественных формулировок на стороне САПР.
Особенно это касается типовых фрагментов чертежа в машиностроительных САПР. Их подсистема ограничений формируется не человеком, а приложением. На иллюстрации изображен «паз прямой», который характеризуется некоторыми параметрами. Если параметр L не зафиксирован, то в процессе боковые дуги паза даже могут заставить перевернуться, как видно внизу на картинке. Этого можно избежать, если добавить неравенство L > 0 с помощью вызова API GCE_AddBound, которое создаст интервальное ограничение.
Похожий пример наблюдается с дуговым пазом. Он также «выворачивается», если не применить к нему неравенство, согласно которому Rb должен быть больше, чем Ra. Для этого нужно использовать вызов GCE_AddLinearEquation, добавить линейное уравнение и сделать его линейным неравенством, добавив к одной из его переменных интервальное ограничение.
Отрезки нулевой длины
Следующая тема, которая получила продвижение в C3D Solver, — это поддержка вырожденной геометрии.
Понятие «вырожденные объекты» не несет никакого отрицательного смысла — наоборот, состояние вырожденности является вполне валидным и даже нужным. На чертеже, представленном на иллюстрации, видно, что если приравнять два вертикальных размера — на 30 и 50, то возникнет необходимость, чтобы исчезли отрезок и дуга. Они превращаются в точку. Для того чтобы решать такие задачи, нами были сделаны соответствующие доработки. Еще одно преимущество состоит в том, что, когда на основе 2D-эскиза создается трехмерная модель, она получает переменную топологию.
Востребованность и интересное применение эта доработка обрела в процессе построения поверхностей переменного сечения по траектории. В этом случае каждое сечение рассчитывается с помощью C3D Solver согласно некоторой зависимости геометрии профиля от положения на траектории. На иллюстрации — прямоугольник со скруглением. Желаемая цель — квадрат. На практике это могла бы быть модель воздуховода с переходом от одного сечения на другое. Для подобных ситуаций можно применять опцию вырожденности. Аналогичен пример, когда L-образное сечение превращается в прямоугольное последовательным преобразованием.
Для обеспечения этой опции в API обратных вызовов (callbacks) предусмотрены две функции, которые реализуются на стороне приложения. Они разрешают или запрещают каждому объекту в отдельности быть вырожденным. Например, ось симметрии в чертеже должна всегда демонстрировать пунктурную линию, разделяющую чертеж на две зеркально-симметричные части. Очевидно, такая ось, имеющая начало и конец (отрезок), потеряла бы смысл в состоянии нулевой длины. Чтобы этого избежать, приложению САПР следует вернуть false при вызове allowZeroLength для отрезка, моделирующего ось симметрии.
Другая немаловажная функция — это getLSegDirection. Она востребована, когда возникает вопрос, что делать с отрезком, который превратился в 0, для того чтобы он приобрел ненулевую длину, поскольку у такого отрезка теряется направление. Чтобы «помнить» это направление, приложению рекомендуется реализовать эту функцию, за счет которой C3D Solver будет хранить данные о том, куда направлен вектор этого отрезка.
Опция касания
Новую опцию получило ограничение касания кривых.
Существует два варианта его исполнения, когда ориентации направляющих векторов в точке касания совпадают или смотрят в противоположные стороны. Раньше ориентация касания запоминалась непосредственно текущим состоянием геометрии. Это было приемлемым вариантом до тех пор, пока не возникли случаи, когда геометрию меняли на стороне САПР еще до того, как она оказывалась под управлением C3D Solver. Соответственно, терялась информация о том, с какой стороны одна кривая касается другой.
Требовалось явно указать сторону касания. Теперь с помощью новых опций GCE_COORIENTED и GCE_OPPOSITE можно информировать C3D Solver о том, как следует исполнять касание, а САПР может «запомнить» сторону касания. Рассмотрим пример: пользователь намеревался вписать окружность в неподвижный шестиугольник. Если шестиугольник поменяет положение еще до того, как будет добавлен в C3D Solver, то окружность может найти нежелательное решение.
Вызов API для этого также предусмотрен.
Потокобезопасность C3D Solver
Помимо прочего, была произведена доработка, связанная с потокобезопасностью.
От заказчика мы получили запрос об аварийной завершении работы. Это сложно было вообразить, ведь решатель работает как швейцарские часы, он никогда не «вылетает». В ходе тестирования мы обнаружили, что в этом кейсе используется многопоточность. На подходе к исправлению мы выписали следующую шкалу требований, в которой 0 приравнивается к полной небезопасности для многопоточности. Показатель A означает, что C3D Solver можно «вызывать» из разных потоков, но только в случае, когда системы ограничений изолированы по потокам. Далее — по мере усложнения, B — это полная потокобезопасность, но при этом нет никакого распараллеливания. C1 и C2 означают, что распараллеливание уже присутствует.
Для 3D Solver мы можем решать изолированные системы в каждом потоке, он соответствует потокобезопасности по типу A.
2D Solver уже достиг уровня потокобезовасности C1.
Большая часть вызовов 2D Solver добавляет в него какие-то данные. В их названии присутствует глагол add (см.диаграмму на рис. 18), например GCE_AddLine, GCE_AddCircle, GCE_AddDistance и т. д. С их помощью САПР загружает в решатель систему ограничений и делает это обычно сразу после чтения файла с чертежами или эскизами. У разработчиков САПР имеется возможность существенно ускорить процесс загрузки насыщенных чертежей, вызывая эти функции из разных потоков.
Этим список усовершенствований не ограничивается, но это повод для подготовки отдельного материала.

Александр Максименко,
руководитель отдела разработки C3D Solver,
C3D Labs