Части трубопроводной сети (трубы и колодцы) на виде профиля.

Автор Тема: Части трубопроводной сети (трубы и колодцы) на виде профиля.  (Прочитано 1488 раз)

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

Оффлайн Дмитрий ЗагорулькинАвтор темы

  • ADN
  • *
  • Сообщений: 1587
  • Карма: 363
  • LISP/C#, AutoCAD/Civil 3D
  • Skype: zagor_dmtr
Оригинал статьи: http://adndevblog.typepad.com/infrastructure/2014/07/pipe-network-parts-on-profile-view.html

На виде профиля, после добавления на него части трубопроводной сети (колодца или трубы), Civil 3D создает новый объект: ProfileViewPart. У этого объекта не много методов, но зато он является объектом базы данных чертежа (с ID и геометрией).
Итак, вопрос: как получить пикетаж и отметку части на виде профиля?
Используя габаритный контейнер части, мы можем получить доступ к координатам XY в модели. Тогда возможно получить среднюю точку (или какую-нибудь другую точку, например с максимальной и минимальной координатой Y). Используя эти координаты XY, мы можем вернуться обратно на вид профиля и запросить пикетаж и отметку для этой точки.
Пример кода ниже демонстрирует эту идею:
Код - C# [Выбрать]
  1. // выбор части сети на виде профиля
  2. Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
  3. PromptEntityOptions peo = new PromptEntityOptions(
  4.   "\nВыберите часть сети на виде профиля: ");
  5. peo.SetRejectMessage("\nТолько части сети на виде профиля!");
  6. peo.AddAllowedClass(typeof(ProfileViewPart), true);
  7. PromptEntityResult per = ed.GetEntity(peo);
  8. if (per.Status != PromptStatus.OK) return;
  9.  
  10. Database db = Application.DocumentManager.MdiActiveDocument.Database;
  11. using (Transaction trans = db.TransactionManager.StartTransaction())
  12. {
  13.   // получение части сети, отображенной на виде профиля
  14.   ProfileViewPart partPV = trans.GetObject(per.ObjectId,
  15.     OpenMode.ForRead) as ProfileViewPart;
  16.   Part part = trans.GetObject(partPV.ModelPartId,
  17.     OpenMode.ForRead) as Part;
  18.  
  19.   // может иметься несколько видов профилей, отображающих эту часть...
  20.   ObjectIdCollection pvIds = part.GetProfileViewsDisplayingMe();
  21.   foreach (ObjectId pvId in pvIds)
  22.   {
  23.     // получаем среднюю точку этого колодца на виде профиля (зам. пер. – это может быть и труба)
  24.     // вы можете изменить эти координаты X,Y для максимальных или минимальных значений...
  25.     Extents3d ext = partPV.GeometricExtents;
  26.     double x = (ext.MaxPoint.X - ext.MinPoint.X) / 2 + ext.MinPoint.X;
  27.     double y = (ext.MaxPoint.Y - ext.MinPoint.Y) / 2 + ext.MinPoint.Y;
  28.  
  29.     // получение вида профиля
  30.     ProfileView pv = trans.GetObject(pvId, OpenMode.ForRead) as ProfileView;
  31.  
  32.     // и пикетаж с отметкой на виде профиля
  33.     double station = 0.0;
  34.     double elevation = 0.0;
  35.     pv.FindStationAndElevationAtXY(x, y, ref station, ref elevation);
  36.  
  37.     ed.WriteMessage(
  38.       "\n{0} отображается на виде профиля {1} на пикете: {2:0.00} | Отметка: {3:0.00}",
  39.       part.Name, pv.Name, station, elevation);
  40.   }
  41. }
  42.  

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 8027
  • Карма: 949
  • Рыцарь ObjectARX
  • Skype: rivilis
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Дмитрий ЗагорулькинАвтор темы

  • ADN
  • *
  • Сообщений: 1587
  • Карма: 363
  • LISP/C#, AutoCAD/Civil 3D
  • Skype: zagor_dmtr
В результате проверки работы кода, обнаружилось, что в алгоритме имеется ошибка. Автор кода учел, что часть может отображаться на нескольких видах профилей. Однако, в этом случае, габаритный контейнер для части на виде профиля будет вычисляться охватыванием всех отображений части на всех видах профилей, т.к. это не несколько разных объектов, а один! Координаты габаритного контейнера получаются несколько иными, чем ожидается, и практического смысла от них мало. Подробно я показал это на видео: https://screencast.autodesk.com/main/details/4fba5135-8cd6-4949-988d-e3e6c239d99c.
В общем-то, использование габаритного контейнера для получения точек части сети на виде профиля – это довольно грубый способ. В конце-концов, это же BIM-продукт! Мы имеем дело с интеллектуальными объектами! Почему бы не получать нужные свойства напрямую? Приведенный ниже код использует как раз такой, цивилизованный подход:
Код - C# [Выбрать]
  1. // выбор части сети на виде профиля
  2. Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
  3. PromptEntityOptions peo = new PromptEntityOptions(
  4.   "\nВыберите часть сети на виде профиля: ");
  5. peo.SetRejectMessage("\nТолько части сети на виде профиля!");
  6. peo.AddAllowedClass(typeof(ProfileViewPart), true);
  7. PromptEntityResult per = ed.GetEntity(peo);
  8. if (per.Status != PromptStatus.OK) return;
  9.  
  10. Database db = Application.DocumentManager.MdiActiveDocument.Database;
  11. using (Transaction trans = db.TransactionManager.StartTransaction())
  12. {
  13.     // получение части сети, отображенной на виде профиля
  14.     ProfileViewPart partPV = trans.GetObject(per.ObjectId,
  15.       OpenMode.ForRead) as ProfileViewPart;
  16.     Part part = trans.GetObject(partPV.ModelPartId,
  17.       OpenMode.ForRead) as Part;
  18.  
  19.     // может иметься несколько видов профилей, отображающих эту часть...
  20.     ObjectIdCollection pvIds = part.GetProfileViewsDisplayingMe();
  21.     foreach (ObjectId pvId in pvIds)
  22.     {
  23.         // получение вида профиля
  24.         ProfileView pv = trans.GetObject(pvId, OpenMode.ForRead) as ProfileView;
  25.  
  26.         // получение трассы вида профиля
  27.         Alignment align = trans.GetObject(pv.AlignmentId, OpenMode.ForRead) as Alignment;
  28.  
  29.         // если объект - колодец
  30.         if (part is Structure)
  31.         {
  32.             // получение колодца
  33.             Structure structure = part as Structure;
  34.  
  35.             // получение точки вставки колодца в модели
  36.             Point3d strLoc = structure.Location;
  37.  
  38.             // получение пикетажа колодца по трассе вида профиля
  39.             // как побочные данные, будет получено еще смещение
  40.             // колодца от трассы вида профиля в плане
  41.             double
  42.                 station = 0.0,
  43.                 offset = 0.0;                        
  44.             align.StationOffset(strLoc.X, strLoc.Y, ref station, ref offset);                
  45.  
  46.             // вывод сообщения о положении колодца
  47.             ed.WriteMessage(
  48.               "\nКолодец '{0}' отображается на виде профиля '{1}' на пикете: {2:0.00}",
  49.               part.Name, pv.Name, station);
  50.  
  51.             // если колодец соединительный - вывод отметки его крышки и дна
  52.             if (structure.PartType == PartType.StructJunction)
  53.             {
  54.                 ed.WriteMessage
  55.                     ("\nОтметка крышки колодца: {0:0.00}, дна: {1:0.00}",
  56.                     structure.RimElevation, structure.SumpElevation);
  57.             }
  58.         }
  59.         // если объект - труба
  60.         else if (part is Pipe)
  61.         {
  62.             // получение трубы
  63.             Pipe pipe = part as Pipe;
  64.  
  65.             // ... и ее начальной и конечной точек (на оси трубы)
  66.             Point3d
  67.                 startPt = pipe.StartPoint,
  68.                 endPt = pipe.EndPoint;
  69.                        
  70.             // получение пикетажей и смещений начальной и конечной точек
  71.             double
  72.                 startStation = 0.0,
  73.                 startOffset = 0.0,
  74.                 endStation = 0.0,
  75.                 endOffset = 0.0;
  76.  
  77.             align.StationOffset(startPt.X, startPt.Y, ref startStation, ref startOffset);
  78.             align.StationOffset(endPt.X, endPt.Y, ref endStation, ref endOffset);
  79.  
  80.             // вывод значения пикетажей и отметок начальной и конечной точек
  81.             ed.WriteMessage(
  82.               "\nТруба '{0}' отображается на виде профиля '{1}'."
  83.               + "\nНачало - пикет: {2:0.00}, отметка: {3:0.00}"
  84.               + "\nКонец - пикет: {4:0.00}, отметка: {5:0.00}",
  85.               part.Name, pv.Name, startStation, startPt.Z, endStation, endPt.Z);
  86.         }
  87.     }
  88. }
  89.  
« Последнее редактирование: 30-08-2015, 13:01:37 от Дмитрий Загорулькин »

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 8027
  • Карма: 949
  • Рыцарь ObjectARX
  • Skype: rivilis
Отлично! Я исправил статью на сайте согласно с твоими исправлениям и дополнениями.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение