Сообщество программистов Autodesk в СНГ

ADN Club => Revit API => Тема начата: Александр Пекшев aka Modis от 19-02-2018, 15:20:58

Название: Проекция CurveLoop на плоскость
Отправлено: Александр Пекшев aka Modis от 19-02-2018, 15:20:58
Всем привет. Ищу способы решения. Мне кажется, что решатся должно просто (нужно только нужные методы найти), но пока не нахожу решения.
Задача - подсчитать площадь проёма. Решение я придумал и вполне "красивое" и точное (даже с учётом стороны стены), но в процессе тестов сам себе придумал проблему. А именно - полукруглая стена!
Имеется вот такой пример:

(https://s18.postimg.org/fgtomt1qt/Screenshot_13.png) (https://postimg.org/image/fgtomt1qt/)

Стена хоть и полукруглая, но окно в ней все-равно плоское. После некоторых манипуляций я получаю CurveLoop по внешней стороне проема:

(https://s18.postimg.org/upjm0pl6d/Screenshot_14.png) (https://postimg.org/image/upjm0pl6d/)

Тут красные - это Curve проема. Фиолетовая - это прямая, добавленная в коде, чтобы замкнуть контур. А вот зеленые - это Curve, которые дуговые ввиду того, что стена полукруглая. Так вот если я посмотрю на все это "Спереди" (т.е. со стороны окна), то "увижу" плоский замкнутый контур. Скажем так - проекцию:

(https://s18.postimg.org/45r0y8s91/Screenshot_15.png) (https://postimg.org/image/45r0y8s91/)

Вот задача теперь в том, чтобы получить этот "плоский" контур, но программно. По сути мне нужно спроецировать мой контур на плоскость окна.

Есть идеи?
Название: Re: Проекция CurveLoop на плоскость
Отправлено: Александр Пекшев aka Modis от 20-02-2018, 10:09:07
Что ж... Сам спросил - сам отвечу =)
В RevitAPI каких-либо методов проекции нет. Однако есть нужная тема у Таммика (http://thebuildingcoder.typepad.com/blog/2014/09/planes-projections-and-picking-points.html). Правда у него там ошибка в методе ProjectOnto - смотрите в комментариях.
Из его поста беру нужные мне методы:
Извините, вам запрещён просмотр содержимого спойлеров.

Теперь в коде плагина, получив нужные мне кривые, я их проецирую на плоскость. Для построения плоскости использую свойство семейства (окна или двери) FacingOrientation:
Код - C# [Выбрать]
  1. Plane plane = new Plane(familyInstance.FacingOrientation, new XYZ(0,0,0));
Методы у меня проецируют на плоскость точки. И если для отрезков это не вызовет проблем - там всего две точки (начало и конец), то для дуговых сегментов не подходит. На выручку приходит метод Curve.Tessellate() (http://www.revitapidocs.com/2018.1/f95f3199-3251-c708-c5a3-a0e9ef95ecfa.htm), который дуговые сегменты апроксимирует. Остается только соединить полученные точки в новые отрезки (и только отрезки). Это делается тоже легко:
Код - C# [Выбрать]
  1. List<Curve> projectedCurves = new List<Curve>();
  2. foreach (Curve curve in curves)
  3. {
  4.     XYZ previosPoint = null;
  5.     for (var i = 0; i < curve.Tessellate().Count; i++)
  6.     {
  7.         XYZ xyzProjected = plane.ProjectOnto(curve.Tessellate()[i]);
  8.         if (i == 0)
  9.             previosPoint = plane.ProjectOnto(xyzProjected);
  10.         else
  11.         {
  12.             projectedCurves.Add(Line.CreateBound(previosPoint, xyzProjected));
  13.             previosPoint = xyzProjected;
  14.         }
  15.     }
  16. }

В итоге получаю нужный мне контур окна, спроецированный на плоскость:


(https://s17.postimg.org/xv2ke9qkb/Screenshot_16.png) (https://postimg.org/image/xv2ke9qkb/)

Для тех, у кого вдруг возник вопрос "Зачем это нужно?" - дело в том, что дальше я кривые собираю в CurveLoop и используя метод ExporterIFCUtils.ComputeAreaOfCurveLoops() (http://www.revitapidocs.com/2018.1/57f85e13-8ea8-01af-2660-94f1ff5cf7ea.htm) считаю площадь. Однако, в ходе тестов, выяснилось, что метод возвращает 0.0, если CurveLoop не лежит в одной плоскости. В справке этого не написано, к сожалению, хотя это логичное поведение
Название: Re: Проекция CurveLoop на плоскость
Отправлено: Алексей Кузин от 20-02-2018, 12:32:00
Цитировать
И если для отрезков это не вызовет проблем - там всего две точки (начало и конец), то для дуговых сегментов не подходит

В вашем примере видно что в результате проецирования дуги получается прямая. То есть плоскость дуги перпендикулярна плоскости проецирования. То достаточно проецировать концевые точки. Для Задачи подсчета площади проема я полагаю это будет всегда.
Название: Re: Проекция CurveLoop на плоскость
Отправлено: Александр Пекшев aka Modis от 20-02-2018, 12:36:12
То достаточно проецировать концевые точки. Для Задачи подсчета площади проема я полагаю это будет всегда
Вы сейчас мне моего коллегу напомнили, который мне подобное сказал =) Отвечу Вам также, как и ему:
А если у меня круглое окно? Что тогда?
Мой вариант решения универсален и позволяет проецировать геометрию любой формы. А то, что из одной дуги (которая чисто в этом примере получилась перпендикулярно плоскости) получится 5-6 отрезков - вообще ни на что не повлияет )
Название: Re: Проекция CurveLoop на плоскость
Отправлено: Алексей Кузин от 20-02-2018, 12:38:46
Да! Про круглые не подумал)