## Добавление и удаление геометрических объектов Основным предметом вычислений геометрического решателя являются геометрические объекты, поэтому формирование системы ограничений начинается с того, что приложение объявляет в системе ограничений геометрические объекты, которым предстоит стать аргументами ограничений. Каждый геометрический объект, объявленный в системе ограничений, получает свой уникальный идентификатор -- дескриптор типа GCM_geom, а его геометрический тип (GCM_g\_type) остается неизменным в течении жизни объекта. Ниже приведены вызовы API C3D Solver, добавляющие геометрические объекты в систему. Точка добавляется с помощью вызова ```cpp GCM_geom GCM_AddPoint(GCM_system gSys, const MbCartPoint3D & pVal) ``` Результатом функции является дескриптор геометрической точки с типом **GCM_POINT**, принадлежащей системе ограничений ***gSys*** .Параметр ***pVal*** задает начальные значения координат точки \. Для создания геометрических объектов других типов, включая и точку, необходимо заполнить структуру данных GCM_g\_record, представляющую собой унифицированную запись для геометрии любого типа, поддерживаемого решателем. Значение данной структуры принимает на вход функция ```cpp GCM_geom GCM_AddGeom(GCM_system gSys, const GCM_g_record & gRec) ``` Результатом вызова является дескриптор геометрического объекта, зарегистрированного в системе ***gSys**.* Параметры геометрического объекта задаются полями структуры GCM_g\_record: - **gRec.type** задает геометрический тип объекта (GCM_g\_type); - **gRec.origin** задает положение объекта, начало его ЛСК; - **gRec.axisZ** задает вектор оси Z ЛСК; - **gRec.axisX** задает вектор оси X ЛСК; - **gRec.axisY** задает вектор оси Y ЛСК; - **gRec.radiusA** и **gRec.radiusB** задают скалярные параметры радиусных объектов. Подробнее о представлении данных в структуре GCM_g\_record изложено в параграфе [Представление геометрических объектов](./Representation_of_geometric_objects.md). Для удобства и правильного заполнения структуры GCM_g\_record в API компонента GCM предусмотрены вспомогательные функции, приведенные ниже: Функция ```cpp GCM_g_record GCM_Point(const MbCartPoint3D &) ``` фактически конвертирует значение координат трехмерной точки из типа данных MbCartPoint3D в GCM_g\_record, воспринимаемой функцией GCM_AddGeom. ```cpp GCM_g_record GCM_Line(const MbCartPoint3D & org, const MbVector3D & axisZ) ``` возвращает запись прямой по точке и направляющему вектору. ```cpp GCM_g_record GCM_Plane(const MbCartPoint3D & org, const MbVector3D & axisZ) ``` возвращает запись о плоскости, заданной точкой и вектором нормали. Функция для получения записи конуса: ```cpp GCM_g_record GCM_Cone(const MbCartPoint3D & centre, const MbVector3D & axis , double radiusA , double radiusB) ``` Входные параметры: - **centre** -- центр окружности-основания конуса, - **axis** -- направляющий вектор оси конуса, - **radiusA** -- радиус основания конуса, - **radiusB** -- радиус сечения конуса (малый радиус). Предполагается, что параметры конуса описывают воображаемый усеченный конус, высота которого всегда равна единице длины, т.е. имеет единичное расстояние между поперечным сечением радиуса **radiusA** и сечением радиуса radiusB (см. иллюстрацию в таблице 1). Функция для получения записи цилиндра: ```cpp GCM_g_record GCM_Cylinder(const MbCartPoint3D & centre, const MbVector3D & axis , double radius) ``` Входные параметры: - **centre** -- точка на оси цилиндра; - **axis** -- направляющий вектор оси конуса; - **radius** -- радиус цилиндра. Функция для получения записи окружности: ```cpp GCM_g_record GCM_Circle(const MbCartPoint3D & centre, const MbVector3D & axis , double radius) ``` Входные параметры: - **centre** -- координаты центра окружности; - **axis** -- направляющий вектор оси окружности; - **radius** -- радиус окружности. Функция для получения записи тора: ```cpp GCM_g_record GCM_Torus(const MbCartPoint3D & centre, const MbVector3D & axis , double majorR , double minorR) ``` Входные параметры: - **centre** -- координаты центра тора; - **axis** -- направление оси вращения тора; - **majorR** -- расстояние от цента тора до центра образующей окружности тора; - **minorR** -- радиус образующей окружности тора. Функция для получения записи сферы: ```cpp GCM_g_record GCM_Sphere(const MbCartPoint3D & centre, double radius) ``` Входные параметры: - **centre** -- центр сферы; - **radius** -- радиус сферы. Функция для получения записи прямоугольной правой (right-handed) ЛСК: ```cpp GCM_g_record GCM_SolidLCS(const MbCartPoint3D & org, const MbVector3D & axisZ , const MbVector3D & axisX) ``` Входные параметры: - **org** -- начало системы координат; - **axisZ** -- орт Z; - **axisX** -- орт X. Результатом функции является запись ЛСК в виде четверки \, где ось Z ориентирована по векторному произведению X◦Y, что соответствует правосторонней ориентации тройки X-Y-Z (right-handed rule). Запись ЛСК имеет геометрический тип **GCM_LCS**. Другой метод создания записи ЛСК имеет тоже имя, но принимает в качестве аргумента значение MbPlacement3D: ```cpp GCM_g_record GCM_SolidLCS(const MbPlacement3D &) ``` Данный метод допускает создание как правосторонней, так и левосторонней СК. Результат, который возвращает функция **GCM_SolidLCS**, используется для задания в системе ограничений твердого тела (кластера) с помощью вызовов **GCM_AddGeom** или **GCM_SubGeom**. Для получения пустой записи GCM_g\_record, которая может быть использована для конструирования значения по умолчанию, можно применить вызов: ```cpp GCM_g_record GCM_NullGeom(void). ``` Ниже приведён фрагмент кода, демонстрирующий создание системы, включающей сферу **sph** с центром в начале координат и радиусом 10.0, а также цилиндр **cyl** с центром в точке \<10, 0, 0\>, ориентированный вдоль оси Z и имеющий тот же радиус. ```cpp GCM_system gSys = GCM_CreateSystem(); const MbCartPoint3D cylPos( 10.0, 0.0, 0.0 ); /* Register two geoms, sphere and cylinder. */ GCM_geom sph = GCM_AddGeom(gSys, GCM_Sphere(MbCartPoint3D::origin, 10.0)); GCM_geom cyl = GCM_AddGeom(gSys, GCM_Cylinder(cylPos, MbVector3D::zAxis, 10.0)); ... ... /* Finalize the constraint system to free its located memory. */ GCM_RemoveSystem(gSys); ``` Кроме вызова **GCM_AddGeom** в решателе предусмотрен другой метод для регистрации геометрических объектов, предусматривающий абстракцию твердого тела, а именно геометрически-жесткие множества, имеющие собственную ЛСК. Такие подмножество называется *кластером*. Для создания *кластера* необходимо объявить его ЛСК с помощью запроса: ```cpp GCM_geom lcs = GCM_AddGeom(gSys, GCM_SolidLCS(org, axisZ, axisX)) ``` Значения ***org**, **axisZ**, **axisX*** задают позицию и ориентацию кластера (его ЛСК). Полученный дескриптор **lcs** будет задавать ЛСК геометрически-жесткого множества, элементы которого объявляются с помощью вызова: ```cpp GCM_geom GCM_SubGeom(GCM_system gSys, GCM_geom lcs, const GCM_g_record & gRec) ``` Входные параметры: - **gSys** -- система геометрических ограничений; - **lcs** -- дескриптор ЛСК кластера; - **gRec** -- запись параметров геометрического объекта, заданного в ЛСК кластера. Функция возвращает дескриптор геометрического объекта, принадлежащего кластеру. Характерная особенность объекта, принадлежащего кластеру в том, что его положение в пространстве подчинено ЛСК кластера, таким образом подчиненный объект меняет свое положение вместе с ЛСК кластера. Это основное его отличие от геометрических объектов, созданных методом **GCM_AddGeom**. Более подробно о работе с кластерами рассмотрено в параграфе [Кластеризация геометрической сцены, моделирование сборок](./Geometric_scene_clustering_assembly_modeling.md). Геометрические объекты, возвращаемые функциями **GCM_SubGeom**, как и **GCM_AddGeom**, могут участвовать в ограничениях и размерах, т.е. могут быть аргументами ограничения. Удаление геометрических объектов осуществляется вызовом ```cpp void GCM_RemoveGeom(GCM_system gSys, GCM_geom g) ``` Данный метод удаляет геометрический объект из системы и делает его дескриптор **g** не действительным. Если геометрический объект на момент вызова является аргументом одного из ограничений, то он фактически остается в системе, но его неизбежное удаление откладывается до тех пор, пока не будет удалено последнее из ограничений, в которых он участвует. Таким образом, пользователь API GCM может освобождать геометрический объект, как только он стал не нужен для приложения, не заботясь о том есть ли ограничения, которые его удерживают.