Векторная геометрия для разработчиков Revit API

|  Revit API

Класс XYZ представляет координаты в RevitAPI. А раз мы имеем дело с координатами, то следует рассмотреть азы векторной геометрии. Всего два действия: сложение и вычитание векторов, позволят сделать кучу полезной работы.

Для начала предлагаю ознакомиться со спецификацией класса XYZ здесь. Что такое векторы можно почитать в википедии.

Класс XYZ в RevitAPI в пространстве модели можно представить в виде вектора, начало которого находится в нулевой точке или базовой точке проекта (X =0, Y = 0, Z = 0), а конец вектора находится в точке, которую нам указывают координаты, например XYZ (-44.6464513504241, 82.7973662674829, 33.0782338854701). Все значения координат указываются в футах. Класс XYZ имеет методы, присущие векторам, которые ниже будут рассмотрены.

Рассмотрим векторы на примере линии детализации в Ревит. Базовую точку отметим как А. Тогда первая точка линии (с которой мы начали ее вести) будет В, завершающая точка линии будет С. Соответственно мы получим векторы АВ и ВС.

В Revit API предусмотрены методы для доступа к первой точке и последней точки линии. 

Показать код C# →

Reference r =  uiapp.ActiveUIDocument.Selection.PickObject(ObjectType.Element) 

Element line = doc.GetElement(r.ElementId); 

XYZ vectorAB = (line.Location as LocationCurve).Curve.GetEndPoint(0);

 XYZ vectorAC = (line.Location as LocationCurve).Curve.GetEndPoint(1);

 TaskDialog.Show("Векторы", vectorAB.ToString() + "\n" + vectorAC);

Для работы с линией детализации как с вектором нам нужен вектор ВС. Для получения вектора линии детализации ВС используем вычитание векторов.

ВС = АС - АВ

Все просто, в данном выражении конец вектора АС будет будет концом вектора ВС  (первое число в разности - конец). Конец вектора АВ будет началом вектора ВС (второе число в разности - начало).

XYZ vectorBC = vectorAC - vectorAB;

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

Показать код C# → 

XYZ vectorBC_1 = vectorBC * (-2) // удлиняется в сторону точки B

XYZ vectorBC_2 = vectorBC * 2; // удлиняется в сторону точки С

XYZ vectorBC_05 = vectorBC * .5 // середина вектора ВС 

 // код создания линии

 Line line = Line.CreateBound(vectorAB, vectorBC_2); // начальная и конечная точка, ведь класс XYZ - это координаты

 doc.Create.NewDetailCurve(doc.ActiveView, line);

Далее рассмотрим сложение векторов. 

Сложение векторов очень пригодится, если нужно разместить какой-либо объект на определенном расстоянии от уже известной точки. Для этого нужно будет воспользоваться координатами такой точки и нормализованным вектором (или единичным вектором). Нормализованный или единичный вектор - это вектор, длина которого равна единице. Подробнее читайте тут

Построим дубликат линии, расположенной горизонтально вправо на расстоянии 2000 мм от существующей. Для этого сначала я отображу графически необходимый результат. Сначала найдем необходимые координаты по правилу параллелограмма. Координаты новой линии детализации определяется так:

AF = AC + AF; AD = AB + BD;

По правилу параллелограмма, вместо векторов CF и BD мы можем воспользоваться вектором AX, который очень просто вычисляется. Воспользуемся нормализованным вектором, который в наше распоряжение предоставляет Revit API - это XYZ.BasisX. Длина этого вектора равна единице, и он, как все базисные векторы, расположен в начале координат. Поэтому умножим его на 2000мм, не забывая перевести миллиметры в футы.

Показать код C# →

XYZ vectorAX = XYZ.BasisX * (2000 / 304.8);

// Находим векторы AF и AD

XYZ vectorAF = vectorAC + vectorAX;

XYZ vectorAD = vectorAB +  vectorAX;

Найденные векторы vectorAF и vectorAD являются точными координатами для построения новой линии детализации. 

Посмотрим как можно, например удлинить нашу линию детализации на 1000 мм в сторону точки С или B.

Показать код C# →

// Удлиняем в сторону точки С 

XYZ directionToC = vectorBC.Normalize();

XYZ newC = vectorAC + (directionToC * (1000 / 304.8));

// Удлиняем в с сторону точки В

XYZ vectorCB = vectorAB - vectorAC;

XYZ directionToB = vectorCB.Normalize();

XYZ newB = vectorAB + (directionToB * (1000 / 304.8));

Пару слов о методе Normalize класса XYZ. Normalize возвращает нормализованный вектор BC или CB. То есть это вектор BC или CB, укороченный до длины равной 1 и помещенный в начало координат с сохранением направления.

Для увлекательного путешествия по трехмерному миру при разработке программ для Ревит нам нужна только опорная точка с известными координатами и указатель движения в виде нормализованного (единичного) вектора, и расстояние. Произведение указателя с расстоянием, и прибавленная к ним опорная точка дадут новые координаты. Пространство проекта в Ревит просто наполнено указателями, которые можно  получать из многих элементов. Мы можем вычислять свои указатели как в примере выше.

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

Ниже можно посмотреть листинг макроса для Ревит, который сдвигает выбранную линию детализации на 2000мм вправо и удлиняет ее на 1000мм в обе стороны.

Показать макрос для Revit C# →

/*
;* Created by SharpDevelop.
 * User: Akunets Aleksandr
 * Date: 27.08.2017
 * Time: 20:37
 * 
 * To change this template use Tools | Options | Coding | Edit Standard Headers.
 */
using System;
using Autodesk.Revit.UI;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI.Selection;
using System.Collections.Generic;
using System.Linq;

namespace Vector
{
    [Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
    [Autodesk.Revit.DB.Macros.AddInId("17333FA7-9C10-4B4E-A179-7B56E33FC6B3")]
    public partial class ThisApplication
    {
        private void Module_Startup(object sender, EventArgs e)
        {

        }

        private void Module_Shutdown(object sender, EventArgs e)
        {

        }
        
        public void Vector() {
            
            UIDocument uidoc = this.ActiveUIDocument; 
            
            Document doc = uidoc.Document; //получаем документ
    
            Selection selection = uidoc.Selection; 
            
            Reference r    = selection.PickObject(ObjectType.Element, "Выделите линию детализации"); // получаем линию
            
            Element line = doc.GetElement(r.ElementId); // получаем линию как элемент
            
            XYZ vectorAB = (line.Location as LocationCurve).Curve.GetEndPoint(0); // получаем вектор к первой точке
            
             XYZ vectorAC = (line.Location as LocationCurve).Curve.GetEndPoint(1); // получаем вектор ко второй точке
             
             XYZ vectorBC = vectorAC - vectorAB; // получаем вектор, определяющий линию детализации
             
             XYZ vectorAX = XYZ.BasisX * (2000 / 304.8); // получаем вектор сдвига на 2000мм вправо (от нулевой точки 2000мм вправо)
            
             XYZ vectorAF = vectorAC + vectorAX; // получаем вектор (координаты) новой точки
            
            XYZ vectorAD = vectorAB +  vectorAX; // получаем вектор (координаты) новой точки
            
            XYZ directionToC = vectorBC.Normalize(); // получаем направление (единичный вектор) в сторону точки С,
            // и используем его для любых параллельных ему векторов
            
            XYZ newC = vectorAF + (directionToC * (1000 / 304.8)); // получаем вектор (координаты) новой точки для новой линии
            
            // Удлиняем в с сторону точки В
            XYZ vectorCB = vectorAB - vectorAC; // получаем вектор, зеркальный вектору BC
            
            XYZ directionToB = vectorCB.Normalize(); // получаем направление (единичный вектор) в сторону точки B,
            // и используем его для любых параллельных ему векторов
            
            XYZ newB = vectorAD + (directionToB * (1000 / 304.8)); // получаем вектор (координаты) новой точки для новой линии

            
            Transaction t = new Transaction(doc, "Create Detail Line");
            {
                t.Start();
                
                Line geomLine = Line.CreateBound(newB, newC);
                
                DetailLine detailline = doc.Create.NewDetailCurve(doc.ActiveView, geomLine ) as DetailLine;
                
                t.Commit();
            }
        }

        #region Revit Macros generated code
        private void InternalStartup()
        {
            this.Startup += new System.EventHandler(Module_Startup);
            this.Shutdown += new System.EventHandler(Module_Shutdown);
        }
        #endregion         
    }
}

Поддержите мои бесплатные приложения для Revit. Нажмайте "Нравится"!

Узнавайте о новых расширениях для Revit подписавшись на страницу BIM3D в Твиттере!

Извините за предствленные неудобства. Всплывающее окно больше не побеспокоит Вас!

Назад
Архив новостей блога