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

ADN Club => Revit API => Тема начата: shss от 12-12-2016, 16:19:48

Название: Получение всех объектов вокруг Room
Отправлено: shss от 12-12-2016, 16:19:48
Здравствуйте!
Столкнулся с интересной задачей, нужно получить все элементы окружающие Room.
Для стен написал так:
Код - C# [Выбрать]
  1. Room room = doc.GetElement(id) as Room;
  2. foreach (IList<Autodesk.Revit.DB.BoundarySegment> bsList in room.GetBoundarySegments(new SpatialElementBoundaryOptions())) {
  3. foreach (Autodesk.Revit.DB.BoundarySegment segments in bsList) {
  4.      Wall wall = segments.Element as Wall;
  5.      Curve curve = (LocationCurve)wall.Location as LocationCurve.Curve;
  6.      TaskDialog.Show("Bsegments", e.Name + " " + curve.Length * SCALE + "\n");
  7.      }
  8. }
  9.  
Далее пытался в стене найти окна или двери, но вся проблема в том, что одна стена может учавствовать в построении нескольких комнат, и если я нахожу в стене окно, то не факт что оно будет в выбранной комнате.
А также длины стен комнаты не являются корректными (потому что получен id всей стены, а не конкретно сегмента).
Есть ли возможность выбрать все элементы вокруг комнаты и получить корректные длины сегментов стены?

Спасибо

Название: Re: Получение всех объектов вокруг Room
Отправлено: Антон Останин от 12-12-2016, 18:05:29
Здравствуйте!
Попробуйте так:
Код - C# [Выбрать]
  1.                     SpatialElementGeometryCalculator calc = new SpatialElementGeometryCalculator(doc, new SpatialElementBoundaryOptions());
  2.                     SpatialElementGeometryResults results = calc.CalculateSpatialElementGeometry(room);
  3.                     var roomSolid = results.GetGeometry();
  4.                     foreach (Face face in roomSolid.Faces)
  5.                     {
  6.                         IList<SpatialElementBoundarySubface> subfaceList = results.GetBoundaryFaceInfo(face);
  7.                         foreach (SpatialElementBoundarySubface subface in subfaceList)                                              //Перебор всех прилегающих поверхностей к помещению
  8.                         {
  9.                            var area =  subface.GetSubface().Area;          //Площадь соприкосновения
  10.                         }
  11.                      }
  12.  
Название: Re: Получение всех объектов вокруг Room
Отправлено: shss от 13-12-2016, 09:46:15
Спасибо, этот код подойдет для получения длины сегментов стены, но правда не всегда отрабатывает если нет соприкосновения со стеной.
Название: Re: Получение всех объектов вокруг Room
Отправлено: Антон Останин от 13-12-2016, 09:52:31
Так это логично, если нет пересечения. :)
Название: Re: Получение всех объектов вокруг Room
Отправлено: Виктор Чекалин от 24-12-2016, 23:26:14
Далее пытался в стене найти окна или двери, но вся проблема в том, что одна стена может учавствовать в построении нескольких комнат, и если я нахожу в стене окно, то не факт что оно будет в выбранной комнате.
Сергей, окна, двери и любые другие элементы, находящиеся на стене, фактически не являются границами стен. Антон подсказал веерный метод для обнаружения границ помещения.
Ты верно отметил, что окно или дверь, находящееся на стене, может быть и за пределами конкретной комнаты. Самый простой способ понять, принадлежит ли окно/дверь  конкретному помещению - проверить свойства FamilyInstance.FromRoom и FamilyInstance.ToRoom
Название: Re: Получение всех объектов вокруг Room
Отправлено: shss от 18-04-2017, 13:27:33
Виктор, спасибо, за подсказку, с окнами и дверьми все получилось, обычным перебором и проверку свойства Room.
А как быть с потолком и полом, просто через соприкосновение с поверхностью я не могу определить тип объекта?
Название: Re: Получение всех объектов вокруг Room
Отправлено: Виктор Чекалин от 19-04-2017, 07:52:26
А как быть с потолком и полом, просто через соприкосновение с поверхностью я не могу определить тип объекта?
Разве? Я у себя применял подобное.
Вот метод для получения нижних границ помещения:
Код - C# [Выбрать]
  1.         IEnumerable<Element> GetRoomBottomBoundaElements(Document document,
  2.                 SpatialElementGeometryResults results,
  3.             Solid roomSolid)
  4.         {
  5.             foreach (Face face in roomSolid.Faces)
  6.             {
  7.                 var roomBoundaryFaceInfo =
  8.                     results.GetBoundaryFaceInfo(face);
  9.  
  10.                 Debug.Print("roomBoundaryFaceInfo: {0}", roomBoundaryFaceInfo.Count);
  11.  
  12.                 foreach (var info in roomBoundaryFaceInfo)
  13.                 {
  14.                     var type = info.SubfaceType;
  15.                     var linkedElementId = info.SpatialBoundaryElement;
  16.                     Element el = null;
  17.                     if (linkedElementId != null)
  18.                     {
  19.                         if (linkedElementId.HostElementId != ElementId.InvalidElementId)
  20.                         {
  21.                             el = document.GetElement(linkedElementId.HostElementId);
  22.                         }
  23.                     }
  24.                     if (el != null)
  25.                     {
  26.                         Debug.Print("{2} - [{0}] - {1}", el.Id.IntegerValue, el.Category.Name, type);
  27.                         if (info.SubfaceType == SubfaceType.Bottom)
  28.                         {
  29.                             yield return el;
  30.                         }
  31.                     }
  32.                     else
  33.                         Debug.Print("{0} - Not an element", type);
  34.                 }
  35.             }
  36.         }

Затем определить чем является элемент - не проблема. ПО категории например
Название: Re: Получение всех объектов вокруг Room
Отправлено: shss от 19-04-2017, 09:31:30
Спасибо, этот вариант мне нравится больше, чем который я реализовал, используя нижние и верхние границы стен комнаты :)
Название: Re: Получение всех объектов вокруг Room
Отправлено: Виктор Чекалин от 19-04-2017, 09:40:36
shss, Пожалуйста. Только есть один момент, о котором нужно помнить. Чтобы данный метод работал, нужно, чтобы в настройках было задано вычисление Площади и Объема помещения. Если будет только площадь, то не корректно будет работать.
Название: Re: Получение всех объектов вокруг Room
Отправлено: Антон Останин от 19-04-2017, 16:03:39
Либо можно самому включать это свойство и потом возвращать в исходное состояние.
Код - C# [Выбрать]
  1.        private void SetVolumesCompute(Document doc)
  2.         {
  3.             var settings = AreaVolumeSettings.GetAreaVolumeSettings(doc);
  4.             bool calcVolumes = settings.ComputeVolumes;                                     //состояние свойства
  5.             using (Transaction tr = new Transaction(doc, "Включение объемов"))
  6.             {
  7.                 tr.Start();
  8.                 settings.ComputeVolumes = true;  //включаем вычисление объемов
  9.                 tr.Commit();
  10.             }
  11.         }
  12.  
Название: Re: Получение всех объектов вокруг Room
Отправлено: shss от 25-04-2017, 10:44:55
А как быть в случае если потолком является пол следующего этажа?
Мне кажется, что нет соприкосновения поверхностей, между Solid комнаты и Floor следующего этажа, потому что когда получаю
Код - C# [Выбрать]
  1. var type = info.SubfaceType;
Типа "Top" не появлется вообще.
Название: Re: Получение всех объектов вокруг Room
Отправлено: shss от 25-04-2017, 11:12:24
Разобрался, необходимо выставить Upper Limit для Room, чтобы получить соприкосновение с Floor верхнего этажа.
Название: Re: Получение всех объектов вокруг Room
Отправлено: Agens от 31-01-2020, 09:29:42
Раз разобрались, могли бы скинуть код... Я понимаю, что прошло 3 года, и вы прошли долгий путь, новичкам как :)
Вообще в API странная реализация BoundarySegment...
----
Стены, пол, кровлю возвратить получилось, но с окнами пока беда FamilyInstance.FromRoom возвращает null...

Виктор, спасибо, за подсказку, с окнами и дверьми все получилось, обычным перебором и проверку свойства Room.

Может кто подскажет направление?
----
BoundarySegment даст окно, которое может выходить за пределы помещения... (ерунду написал, окно не может принадлежать двум помещениям)... или нет? опять же вернутся все окна стены, которая принадлежит нескольким помещениям...
Просто считал теплопотери в Sancom, там такое возможно (окно делится стеной)...
----
(https://i.postimg.cc/mPHdM5Bt/6.png) (https://postimg.cc/mPHdM5Bt)
Название: Re: Получение всех объектов вокруг Room
Отправлено: Agens от 01-02-2020, 17:30:17
Оказалось все проще:
Код - C# [Выбрать]
  1. Room room = window.get_Room(phase);
Название: Re: Получение всех объектов вокруг Room
Отправлено: Agens от 01-02-2020, 19:56:23
Странно, дверь не обрабатывает!?
Код - C# [Выбрать]
  1. Room room = door.get_Room(phase);
возвращает nulll...
Название: Re: Получение всех объектов вокруг Room
Отправлено: Agens от 01-02-2020, 21:38:33
Я в шоке от ревита :)
Если дверь открывается наружу, то она не определяется (null), а если внутрь, то Room возвращается...
---
Дверь справа не обрабатывается, слева все ОК. Тоже самое и с окном, если его отзеркалить маркером...
---
(https://i.postimg.cc/Js6d1ggb/7.png) (https://postimg.cc/Js6d1ggb)
---
Вижу два решения для себя:
1. если Family возвращается null отзеркалить его и снова взять Room.
2.искать пренадлежность двери через Face...
Название: Re: Получение всех объектов вокруг Room
Отправлено: Александр Игнатович от 05-02-2020, 10:04:43
Попробуй по аналогии:

Код - C# [Выбрать]
  1. door.get_FromRoom(phase)
и
Код - C# [Выбрать]
  1. door.get_ToRoom(phase)

А вообще тут всё сильно зависит от аккуратности моделирования. Попробуй ещё с SpatialElementGeometryCalculator поковыряться, получая все граничные элементы по конкретному помещению
Название: Re: Получение всех объектов вокруг Room
Отправлено: Agens от 05-02-2020, 11:31:06
Код - C# [Выбрать]
  1. door.get_FromRoom(phase);
- выдает Room в обоих случая, пока подходит больше всего...
Код - C# [Выбрать]
  1. .flipFacing()
- менять не нужно...
Название: Re: Получение всех объектов вокруг Room
Отправлено: Agens от 05-02-2020, 11:36:48
А вообще тут всё сильно зависит от аккуратности моделирования. Попробуй ещё с SpatialElementGeometryCalculator поковыряться, получая все граничные элементы по конкретному помещению
Да, "ковыряю"... Можно вопрос тут задам:
Код - C# [Выбрать]
  1.         private IList<SpatialElementBoundarySubface> GetAllSubfacefSpase(Space space)
  2.         {
  3.             Room room = space.Room;
  4.             List<SpatialElementBoundarySubface> allsubfacelist = new List<SpatialElementBoundarySubface>();
  5.  
  6.             SpatialElementGeometryCalculator calc = new SpatialElementGeometryCalculator(m_doc, new SpatialElementBoundaryOptions());
  7.             SpatialElementGeometryResults results = calc.CalculateSpatialElementGeometry(room);
  8.  
  9.             Solid roomSolid = results.GetGeometry(); // Получаем солиды
  10.  
  11.             foreach (Face face in roomSolid.Faces) // Перебираем поверхности
  12.             {
  13.                 IList<SpatialElementBoundarySubface> subfaceList = results.GetBoundaryFaceInfo(face); // Перебираем субповерхности
  14.                 foreach (SpatialElementBoundarySubface subface in subfaceList)
  15.                 {
  16.                     allsubfacelist.Add(subface);
  17.                 }
  18.             }
  19.             return allsubfacelist;
  20.         }
Room состоит из Solid, Solid состоит из Face (+ Edge), зачем мы лезем в subFace? Почему не достаточно работать с Face?
Название: Re: Получение всех объектов вокруг Room
Отправлено: Александр Игнатович от 05-02-2020, 11:42:26
одна поверхность solid-а помещения может быть фактически ограничена несколькими элементами
Название: Re: Получение всех объектов вокруг Room
Отправлено: Agens от 05-02-2020, 11:53:32
а где про Face почитать? Face состоит из SpatialElementBoundarySubface? Что-то я в этом месте не понимаю :) Природу/геометрию SpatialElementBoundarySubface.
Название: Re: Получение всех объектов вокруг Room
Отправлено: Александр Игнатович от 05-02-2020, 12:11:26
Как всегда, в SDK.

Во-первых, собственно, в описаниях классов и методов, во-вторых, есть Samples\RoofsRooms - пример использования, в третьих собственные исследования с помощью, например, Revit pyhon shell + RevitLookup
Название: Re: Получение всех объектов вокруг Room
Отправлено: Agens от 05-02-2020, 12:25:07
Вроде разобрался...
Как получить наружный Face стены?
Как получить стены, имеющие общую поверхность к стене?
---
тема: https://adn-cis.org/forum/index.php?topic=3006.msg11532#quickreply
---
День добрый! то есть из файла не понятно, что некая точка А - это одна поверхность стены, а точка Б - это другая поверхность той же стены?
А что если сделать так:
для каждой стены берем LocationCurve, делаем её копию (метод Clone), затем вызываем MakeUnbound() - получили бесконечную прямую.
Затем попарно их пересекаем метод Intersect(), если пересечений нет (метод возвращает SetComparisonResult.Disjoint - There is no intersection found between the two curves), значит стенки параллельны, мы можем у LocationCurve второй стены взять GetEndPoint(0), вызвать curve(первой стены).Project() - в результате определить расстояние между двумя параллельными стенами, точнее между их осевыми, а дальше можно уже просто сравнить значения и сделать нужные телодвижения
У двух стен Edge будет одинковый, как их сравнить? По точкам?