Вопрос: "Как вручную повернуть объект IFC-модели?"
Ответ я не буду делить на части, хотя информации много. Мы поступим по-другому. Сейчас мы разберем техническую сторону вопроса - как в IFC описывается модель относительного размещения и ориентации объекта в 3D-пространстве. А в следующем посте я покажу вам один способ как в реальном проекте повращать любой необходимый нам объект.
Итак, знакомьтесь, это кубоид. Его особенностью является то, что размер его ребер (осей) = 1. С его помощью можно указать направление вектора, относительно которого можно сориентировать любой объект в 3D-пространстве:

Поясню как. Допустим нам надо создать 3D-вектор, исходящий из начала координат (0,0,0) под углом 30° в плоскости XOY и наклоненный к этой плоскости под 45°:

Построим его и спроецируем конечную точку вектора на оси нашего кубоида. В таком случае, координаты точки будут равны:
- ось X = cos (30°) = 0,866025403784438
- ось Y = sin (30°) = 0,5
- ось Z = 1

По такому принципу указывается направление в классе IfcDirection (соотношение по оси X, соотношение по оси Y, соотношение по оси Z). На языке EXPRESS направление указанного нами вектора будет записано так:
#1= IFCDIRECTION((0.866025403784438, 0.5, 1.))
Чтобы сориентировать объект в 3D-пространстве таких векторов необходимо указать два. Первый указывает ориентацию оси Z объекта, второй - куда будет направлена ось X объекта. Посмотрите на пример ниже, как ориентированы локальная ось Z объекта (голубая) и ось X (красная):

В дополнение к этому надо указать точку начала осей (декартова точка) - IfcCartesianPoint . В нашем примере она имеет координаты (300,200,0). Запишем эту информацию на языке EXPRESS:
/* локальная ось Z */
#1= IFCDIRECTION((0., -0.5, 0.866025403784438))
/* локальная ось X */
#2= IFCDIRECTION((0.755967731484218, 0.654608882428740, 0.353474843779257))
/* начало осей */
#3= IFCCARTESIANPOINT((300., 200., 0.))
В совокупности эти три параметра и определяют относительное размещение и ориентацию объекта в 3D-пространстве. Она объединяется в классе IfcAxis2Placement3D, который состоит из 3-х атрибутов:
- Location.
- Axis (optional).
- RefDirection (optional).
В Location мы ссылаемся на начало осей - декартову точку (#3), в Axis - на направление локальной оси Z объекта (#1), а в RefDirection - на направление локальной оси X объекта (#2).
#4= IFCAXIS2PLACEMENT3D(#3,#1,#2)
ВАЖНО! Атрибуты Axis и RefDirection являются опциональными, т.е. мы можем их не определять. В таком случае, ориентация осей принимается по умолчанию для X (1,0,0), для Y (0,1,0), для Z (0,0,1).
Прежде, чем мы перейдём к практике и начнём вращать объекты в каком-нибудь проекте, нам осталось понять ещё одну важную вещь - Относительно чего указывается начало осей объекта (декартова точка)?
Относительное размещение объекта
В IFC существует правило - Все объекты модели должны быть размещены в одной системе координат. Как правило, мы работаем в относительной системе координат (или локальной, ЛСК), потому что так удобнее. Второй вариант - работать в абсолютной системе координат (или мировой, МСК). Это чревато проблемами с математикой. Наши координаты могут быть удалены от центра МСК на тысячи километров.
На схеме ниже показано, относительно чего определяется размещения различных сущностей проекта в IFC:

Гораздо удобнее указывать координаты, например, здания относительно центра ЛСК участка, или объекта относительно центра ЛСК этажа здания, на котором он размещен.
Класс IfcLocalPlacement определяет относительное размещение объекта (или другой пространственной сущности) по отношению к размещению другого объекта (или другой пространственной сущности) или его абсолютное размещение в контексте геометрического представления проекта. Он определяется двумя атрибутами:
- PlacementRelTo (optional).
- RelativePlacement.
Атрибут PlacementRelTo ссылается на LocalPlacement сущности (например, этажа), относительно которой будет размещаться объект.
ВАЖНО! Если PlacementRelTo не задан, то объект размещается абсолютно в пределах мировой системы координат (МСК).
Атрибут RelativePlacement ссылается на относительное размещение и ориентацию самого объекта, которое определяется классом IfcAxis2Placement3D (#4). На языке EXPRESS это будет примерно так:
#5= IFCLOCALPLACEMENT($,#4)
На этом теория закончилась, а практика будет в следующем посту. Там мы еще раз коснемся всего того, о чём было написано здесь, но уже на конкретном примере. Если возникли вопросы по теории, то пишите в комментариях.