Размер для линейного элемента

Автор Тема: Размер для линейного элемента  (Прочитано 6360 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Тема содержит сообщение с Решением. Нажмите здесь чтобы посмотреть его.

Оффлайн Илья ДрягинАвтор темы

  • ADN OPEN
  • Сообщений: 25
  • Карма: 2
  • Стройтэкпроект
Добрый день!

Столкнулся с задачей создания размера для арматурного стержня. По поводу размеров для стен было написано неоднократно, я думал, что для стержня (для простоты взят стержень стандартной формы без отгибов) это будет так же. Однако столкнулся с проблемой: для создания размера нам нужны как минимум 2 Reference, соответственно нам нужны ссылки на концы стержня.
Методом
Код - C# [Выбрать]
  1. var rebcc = (vertreb as Rebar).GetCenterlineCurves(false, false, false, MultiplanarOption.IncludeOnlyPlanarCurves).First();
мы получаем центральную линию стержня, но у этой линии нет возможности получить Reference концов.
Код - C# [Выбрать]
  1. Reference rebendref = ((vertreb as Rebar).GetCenterlineCurves(false, false, false, MultiplanarOption.IncludeOnlyPlanarCurves).First() as Line).GetEndPointReference(0);
выдает null. Это так же можно посмотреть через Revit LookUp, где в свойстве Rebar GetCenterlineCurves видно, что у Line нет EndReference (точнее они null)

В комментарии к свойству Reference класса Line я вычитал
Цитировать
This value is set for curve geometry obtained from Revit elements. a null reference ( Nothing in Visual Basic) if the curve was created via parameters, copying, transform, or other operations.
то есть построить параллельные линии по координатам конечных точек стержня и привязать к ним размер не получится. Поэтому я решил получить Line через геометрию стержня:

Код - C# [Выбрать]
  1.             Options ropt = new Options();
  2.             ropt.ComputeReferences = true;
  3.             ropt.IncludeNonVisibleObjects = false;
  4.             ropt.DetailLevel = ViewDetailLevel.Medium;
  5.             var rebg = vertreb.get_Geometry(ropt);
  6.  

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

но при добавлении полученных Reference в referenceArray для создания размера происходит непонятная штука - размер создается, но нулевой и не понятно куда привязанный.



Через Revit lookup я сравнил References созданного размера и References размера, поставленного вручную (правильного), отличий нет и в самих Reference нет указания на точку привязки, только на родительский элемент.

Может кто-то сталкивался с такой проблемой? как образмерить линейный элемент?

код создания размера:

Код - C# [Выбрать]
  1.            FilteredElementCollector rcollector = new FilteredElementCollector(doc,doc.ActiveView.Id).WhereElementIsNotElementType();
  2.             IList<Element> rebsonview =rcollector.OfCategory(BuiltInCategory.OST_Rebar).ToElements();
  3.              
  4.             var vertRebar = rebsonview.FirstOrDefault(x => ((x as Rebar).GetCenterlineCurves(false, false, false, MultiplanarOption.IncludeOnlyPlanarCurves).First() as Line).Direction.IsAlmostEqualTo(doc.ActiveView.UpDirection.Normalize()) ||
  5.                                                    ((x as Rebar).GetCenterlineCurves(false, false, false, MultiplanarOption.IncludeOnlyPlanarCurves).First() as Line).Direction.IsAlmostEqualTo(doc.ActiveView.UpDirection.Negate().Normalize()));
  6.              
  7.             ReferenceArray secrefarr = new ReferenceArray();
  8.              
  9.             Options ropt = new Options();
  10.             ropt.ComputeReferences = true;
  11.             ropt.View = doc.ActiveView;
  12.             ropt.IncludeNonVisibleObjects = false;
  13.  
  14.             GeometryElement rebg = vertRebar.get_Geometry(ropt);
  15.  
  16.             secRefarr.Append((rebg.First() as Line).GetEndPointReference(0));
  17.             secRefarr.Append((rebg.First() as Line).GetEndPointReference(1));
  18.  
  19.            Line dmmline1 = Line.CreateUnbound(dimmPoint1,doc.ActiveView.UpDirection);
  20.  
  21.            doc.Create.NewDimension(doc.ActiveView,dmmline2,secRefarr);
« Последнее редактирование: 05-04-2018, 15:00:05 от Илья Дрягин »

Оффлайн Александр Пекшев aka Modis

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Re: Размер для линейного элемента
« Ответ #1 : 05-04-2018, 14:59:44 »
У меня такое ощущение, что вопрос не дописан =))
Поэтому я решил получить Line через геометрию стержня:
ну а дальше что?

Оффлайн Илья ДрягинАвтор темы

  • ADN OPEN
  • Сообщений: 25
  • Карма: 2
  • Стройтэкпроект
Re: Размер для линейного элемента
« Ответ #2 : 05-04-2018, 15:01:26 »
У меня такое ощущение, что вопрос не дописан =))
Поэтому я решил получить Line через геометрию стержня:
ну а дальше что?

Отвлекся и случайно отправил незаконченное послание :)

Оффлайн Александр Пекшев aka Modis

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Re: Размер для линейного элемента
« Ответ #3 : 05-04-2018, 15:17:10 »
Вот вам волшебный метод:
Код - C# [Выбрать]
  1. public static Reference FixReference(this Reference reference, Element element)
  2. {
  3.     var stRepSplitted = reference.ConvertToStableRepresentation(element.Document).Split(':');
  4.     var elementUniqId = element.UniqueId;
  5.     if (stRepSplitted.Contains(elementUniqId))
  6.         return reference;
  7.     string fix;
  8.     if (element is FamilyInstance)
  9.     {
  10.         fix = elementUniqId + ":0:INSTANCE:";
  11.         foreach (string s in stRepSplitted)
  12.             fix += s + ":";
  13.     }
  14.     else
  15.     {
  16.         fix = elementUniqId + ":";
  17.         for (var i = 1; i < stRepSplitted.Length; i++)
  18.             fix += stRepSplitted[i] + ":";
  19.     }
  20.     fix = fix.TrimEnd(':');
  21.     return Reference.ParseFromStableRepresentation(element.Document, fix);
  22. }
Прежде чем добавлять референс в массив, "пропустите его" через этот метод

Оффлайн Александр Пекшев aka Modis

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Re: Размер для линейного элемента
« Ответ #4 : 05-04-2018, 15:27:46 »
Я вам неверно ответил. Но мой ответ тоже полезный и пригодится  ;)
А в вашем случае проблема в том, что вы неверно создаете линию для построения размера - она должна быть параллельна арматурному стержню, а вы ее создаете по UpDirection. вы уверены, что этот вектор "смотрит" куда надо?

Оффлайн Илья ДрягинАвтор темы

  • ADN OPEN
  • Сообщений: 25
  • Карма: 2
  • Стройтэкпроект
Re: Размер для линейного элемента
« Ответ #5 : 06-04-2018, 06:47:08 »
Я вам неверно ответил. Но мой ответ тоже полезный и пригодится  ;)
А в вашем случае проблема в том, что вы неверно создаете линию для построения размера - она должна быть параллельна арматурному стержню, а вы ее создаете по UpDirection. вы уверены, что этот вектор "смотрит" куда надо?

Все равно проверил ваш метод лечения Reference, ничего не изменилось.
А по поводу построения линии размера, это тестовый вариант в лабораторных условиях и я уверен, что UpDirection параллелен со стержнем во первых потому что так рисовал, во вторых потому что сделал проверку на вертикальность стержня на данном виде:

Код - C# [Выбрать]
  1.         var vertRebar = rebsonview.FirstOrDefault(x => ((x as Rebar).GetCenterlineCurves(false, false, false, MultiplanarOption.IncludeOnlyPlanarCurves).First() as Line).Direction.IsAlmostEqualTo(doc.ActiveView.UpDirection.Normalize()) ||
  2.                                                    ((x as Rebar).GetCenterlineCurves(false, false, false, MultiplanarOption.IncludeOnlyPlanarCurves).First() as Line).Direction.IsAlmostEqualTo(doc.ActiveView.UpDirection.Negate().Normalize()));

Проблема не в этом. Вообще у Reference есть свойство GlobalPoint (The position on which the reference is hit), но у полученных Reference (так же как и у References правильного размера,, построенного вручную через интерфейс) это свойство почему то null

Для чистоты эксперимента я все равно пересоздал линию для разреза:

Код - C# [Выбрать]
  1.            XYZ dimmPoint2 = (rebGeometry.First() as Line).GetEndPoint(0).Add(doc.ActiveView.RightDirection.Negate().Multiply(5));
  2.            Line dmmline2 = Line.CreateUnbound(dimmPoint2,((vertRebar as Rebar).GetCenterlineCurves(false, false, false, MultiplanarOption.IncludeOnlyPlanarCurves).First() as Line).Direction);

Оффлайн Александр Пекшев aka Modis

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Re: Размер для линейного элемента
« Ответ #6 : 06-04-2018, 16:38:17 »
Совсем забыл про тему =))
Можете сделать тестовый проект? Я бы потестировал и возможно подсказал бы. Самому некогда делать  ::)

Оффлайн Илья ДрягинАвтор темы

  • ADN OPEN
  • Сообщений: 25
  • Карма: 2
  • Стройтэкпроект
Re: Размер для линейного элемента
« Ответ #7 : 09-04-2018, 06:56:59 »
Совсем забыл про тему =))
Можете сделать тестовый проект? Я бы потестировал и возможно подсказал бы. Самому некогда делать  ::)

Вот, сделал тестовый проект, макрос с кодом в него вложил. Макрос запускается на разрезе без ошибок, на других видах запуск не гарантирован, проверки не проводятся.

Отмечено как Решение Илья Дрягин 09-04-2018, 13:42:34

Оффлайн Александр Пекшев aka Modis

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Re: Размер для линейного элемента
« Ответ #8 : 09-04-2018, 10:38:56 »
В общем, заставил я работать Ваш код) Точнее - от вашего ничего не осталось  ;D
И даже мой волшебный метод в случае арматуры не нужен.

Для начала пару пояснений:
Итак, я открываю ваш проект, вызываю команду "Параллельный размер" (именно его мы создаем программно) и пытаюсь поставить размер именно на концевые точки арматуры (используя Тab) - и у меня это не получается ну вот никак. Это уже должно навести на мысль, что подход Ваш неверный!

Дальше, я выбираю размер на разрезе (тот, на котором написано "То, что надо") и снупаю его через Revit Lookup. В одном из последних коммитов к нему мной было добавлено отображение результата метода ConvertToStableRepresentation. Посмотрев референсы вижу, что результат примерно такой:
Цитировать
9a071010-f77d-4fdb-a7d9-00b061a1fd39-000859ad:2000000:1003000
9a071010-f77d-4fdb-a7d9-00b061a1fd39-000859ad:2000000:1004000
Но если получить StableRepresentation для GetEndPointReference (как в вашем случае), то результат будет далек от указанного выше. Живого примера под рукой уже нет - будет интересно - посмотрите сами.
И из всего этого мы можем сделать только один вывод - размер ставится на линии, перпендикулярные средней линии арматуры.
Так что вот вам код, который точно ставит размер на арматуре в вашем примере. Конечно нужно будет учесть множество нюансов, которые могут быть (гнутая там арматура, с крюками и т.п.) - но это уже ваша работа =)
Код - C# [Выбрать]
  1. public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
  2. {
  3.     Document doc = commandData.Application.ActiveUIDocument.Document;
  4.  
  5.     FilteredElementCollector rcollector = new FilteredElementCollector(doc, doc.ActiveView.Id).WhereElementIsNotElementType();
  6.     IList<Element> rebsonview = rcollector.OfCategory(BuiltInCategory.OST_Rebar).ToElements();
  7.  
  8.     Options opt = new Options()
  9.     {
  10.         ComputeReferences = true,
  11.         View = doc.ActiveView,
  12.         IncludeNonVisibleObjects = true
  13.     };
  14.    
  15.     foreach (Element element in rebsonview)
  16.     {
  17.         if (element is Rebar rebar)
  18.         {
  19.             var rebarCenterCurve = rebar.GetCenterlineCurves(false, false, false, MultiplanarOption.IncludeOnlyPlanarCurves,0).FirstOrDefault();
  20.             if (rebarCenterCurve != null && rebarCenterCurve is Line rebarCenterLine &&
  21.                 (rebarCenterLine.Direction.IsAlmostEqualTo(doc.ActiveView.UpDirection.Normalize()) ||
  22.                 rebarCenterLine.Direction.IsAlmostEqualTo(doc.ActiveView.UpDirection.Negate().Normalize())))
  23.             {
  24.                 ReferenceArray refArr = new ReferenceArray();
  25.                 foreach (GeometryObject geometryObject in rebar.get_Geometry(opt))
  26.                 {
  27.                     if (geometryObject is Line line)
  28.                     {
  29.                         if (rebarCenterLine.Intersect(line, out var intersectionResult) == SetComparisonResult.Overlap &&
  30.                             intersectionResult.Size == 1)
  31.                         {
  32.                             var intersectPt = intersectionResult.get_Item(0).XYZPoint;
  33.                             if (intersectPt.IsAlmostEqualTo(rebarCenterLine.GetEndPoint(0)) ||
  34.                                 intersectPt.IsAlmostEqualTo(rebarCenterLine.GetEndPoint(1)))
  35.                             {
  36.                                 refArr.Append(line.Reference);
  37.                             }
  38.                         }
  39.                     }
  40.                 }
  41.                 if (refArr.Size >= 2)
  42.                 {
  43.                     XYZ dimmPoint = rebarCenterLine.GetEndPoint(0).Add(doc.ActiveView.RightDirection.Negate().Multiply(5));
  44.                     Line dimmLine = Line.CreateUnbound(dimmPoint, rebarCenterLine.Direction);
  45.                     using (Transaction tr = new Transaction(doc, "Dimm"))
  46.                     {
  47.                         tr.Start();
  48.  
  49.                         doc.Create.NewDimension(doc.ActiveView, dimmLine, refArr);
  50.  
  51.                         tr.Commit();
  52.                     }
  53.                 }
  54.             }
  55.         }
  56.     }
  57.  
  58.     return Result.Succeeded;
  59. }

Оффлайн Илья ДрягинАвтор темы

  • ADN OPEN
  • Сообщений: 25
  • Карма: 2
  • Стройтэкпроект
Re: Размер для линейного элемента
« Ответ #9 : 09-04-2018, 12:42:20 »
вызываю команду "Параллельный размер" (именно его мы создаем программно) и пытаюсь поставить размер именно на концевые точки арматуры (используя Тab) - и у меня это не получается ну вот никак. Это уже должно навести на мысль, что подход Ваш неверный!

У меня получается, в приложений скриншот. Конечная точка выделяется и в строке помощи отображается как "Несущая арматура:Арматурный стержень...:Ручка формы"


По поводу кода: Пока я не понял что это за линии геометрии, к которым цепляется размер, буду анализировать и разбираться. Решение через поиск пересечения объектов геометрии внутри элемента для меня совсем не очевидное :) однако оно работает, спасибо!

Оффлайн Александр Пекшев aka Modis

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Re: Размер для линейного элемента
« Ответ #10 : 09-04-2018, 12:45:32 »
У меня получается, в приложений скриншот. Конечная точка выделяется и в строке помощи отображается как "Несущая арматура:Арматурный стержень...:Ручка формы"
Только вот это не ТОЧКА! Точка подсвечивается именно как точка - закрашенный синий кружок.