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

12/11/2018

Маркировка пространств на разрезах

Сегодня мы поговорим о маркировке пространств на разрезах.

Для создания марок пространств в Revit API предназначен метод NewSpaceTag класса Autodesk.Revit.Creation.Document. Сигнатура метода следующая:

Код - C#: [Выделить]
  1. public SpaceTag NewSpaceTag(Space space, UV point, View view)

В контексте рассматриваемого в этой статье вопроса нас больше всего интересует второй параметр метода. SDK нам говорит следующее:

Type: Autodesk.Revit.DB.UV

A 2D point that dictates the location on the level of the space.

Т.е. это точка на плоскости уровня, на котором расположено пространство. Действительно, нет никаких проблем создать марку пространства на плане используя следующий код:

Код - C#: [Выделить]
  1.  
  2. ...
  3. var spaceLocation = (LocationPoint) space.Location;
  4. doc.Create
  5.                 .NewSpaceTag(space, new UV(spaceLocation.Point.X, spaceLocation.Point.Y), doc.ActiveView);
  6. ...
  7.  

Location пространства задается пользователем, на виде в плане он показывается пересечением линий с крестиком. Именно в этом месте и создается марка с помощью кода, показанного выше.

 

А что же насчет разрезов? А здесь возникают проблемы. Во-первых, за счет того, что метод принимает аргументом точку на плоскости, то в свойстве TagHeadPosition координата Z будет нулевой, и марка в общем случае появится далеко от маркируемого пространства. Во-вторых пространство на разрезе имеет собственный "прицел", который в общем случае не совпадает со Space.Location, а марку хотелось бы привязать именно к пересечению этих линий.

Свойство TagHeadPosition имеет сеттер, т.е. после создания марки мы можем переместить её в нужную позицию. Осталось понять, как получить линии, образующие "прицел".

Для этого нужно получить геометрию текущего вида, в т.ч. невидимую (установив IncludeNonVisibleObjects = true), из этой геометрии получить линии и проверить категорию линии в графическом стиле как показано на этой схеме с помощью утилиты Revit Lookup:

 

Код - C#: [Выделить]
  1.  
  2. private static XYZ GetSpaceTagPositionOnSectionView(Space space, ViewSection viewSection)
  3. {
  4.                 var spaceReferenceLines = space.get_Geometry(new Options { View = viewSection, IncludeNonVisibleObjects = true })
  5.                                .OfType<Line>()
  6.                                .Where(x => IsSpaceReferenceLine(x, space.Document))
  7.                                .ToList();
  8.  
  9.                 if (spaceReferenceLines.Count != 2)
  10.                                throw new InvalidOperationException("Что-то пошло не так");
  11.  
  12.                 IntersectionResultArray intersectionResult;
  13.  
  14.                 if (spaceReferenceLines[0].Intersect(spaceReferenceLines[1], out intersectionResult) != SetComparisonResult.Overlap)
  15.                                throw new InvalidOperationException("Что-то пошло не так");
  16.  
  17.                 return intersectionResult.get_Item(0).XYZPoint;
  18. }
  19.  
  20. private static bool IsSpaceReferenceLine(Line line, Document document)
  21. {
  22.                 var referenceLineStyleCategoryId = new ElementId(BuiltInCategory.OST_MEPSpaceReference);
  23.  
  24.                 var graphicsStyle = document.GetElement(line.GraphicsStyleId) as GraphicsStyle;
  25.  
  26.                 return graphicsStyle?.GraphicsStyleCategory.Id == referenceLineStyleCategoryId;
  27. }
  28.  

Теперь осталось только присвоить рассчитанное значение свойству TagHeadPosition после создания марки:

Код - C#: [Выделить]
  1.  
  2. ...
  3.  
  4. var tag = doc.Create
  5.                 .NewSpaceTag(space, UV.Zero, doc.ActiveView);
  6.  
  7. tag.TagHeadPosition = GetSpaceTagPositionOnSectionView(space, (ViewSection) doc.ActiveView);
  8.  
  9. ...
  10.  

Обсуждение: http://adn-cis.org/forum/index.php?topic=

Опубликовано 12.11.2018