Переопределение частей трубопроводной сети на виде профиля.

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

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

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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Оригинал статьи: http://adndevblog.typepad.com/infrastructure/2015/04/overrule-pipe-network-part-in-profile-view.html
Используя эту простую заготовку переопределения, мы можем изменить отображение трубы или колодца на виде профиля. Нам нужно переопределить класс ProfileViewPart и добавить немного геометрии. Это простой пример:
Код - C# [Выбрать]
  1. class PipePartOverrule : DrawableOverrule
  2. {
  3.     public override bool WorldDraw(
  4.       Drawable drawable, WorldDraw wd)
  5.     {
  6.         bool ret = base.WorldDraw(drawable, wd);
  7.  
  8.         ProfileViewPart viewPart = drawable as ProfileViewPart;
  9.         if (viewPart == null) return ret; // для безопасности
  10.  
  11.         // получение базы данных
  12.         // если объект является объектом базы данных,
  13.         // получаем ее из свойства объекта
  14.         // если нет, получаем активную базу данных
  15.         Database db = (viewPart.Database != null ?
  16.           viewPart.Database :
  17.           Application.DocumentManager.
  18.           MdiActiveDocument.Database);
  19.  
  20.         // получение типа объекта в модели
  21.         if (viewPart.ModelPartId.ObjectClass ==
  22.           RXClass.GetClass(typeof(Pipe)))
  23.         {
  24.             // хорошо, эта часть представляет собой трубу
  25.             // нарисуем что-нибудь... пусть будет пересекающий отрезок
  26.             wd.Geometry.WorldLine(
  27.               viewPart.Bounds.Value.MinPoint,
  28.               viewPart.Bounds.Value.MaxPoint);
  29.         }
  30.  
  31.         // если вам нужно обрабатывать колодцы
  32.         //else if (viewPart.ModelPartId.ObjectClass ==
  33.         //  RXClass.GetClass(typeof(Structure)))
  34.         //{
  35.         //}
  36.  
  37.         return ret;
  38.     }
  39. }
  40.  
  41. public class Commads
  42. {
  43.     [CommandMethod("profilePartOverrule")]
  44.     public static void CmdProfilePartOverrule()
  45.     {
  46.         if (_overrule == null)
  47.         {
  48.             _overrule = new PipePartOverrule();
  49.             Overrule.AddOverrule(
  50.               RXClass.GetClass(typeof(ProfileViewPart)),
  51.               _overrule, false);
  52.         }
  53.         else
  54.         {
  55.             Overrule.RemoveOverrule(
  56.               RXClass.GetClass(typeof(ProfileViewPart)),
  57.               _overrule);
  58.             _overrule = null;
  59.         }
  60.         Application.DocumentManager.
  61.           MdiActiveDocument.Editor.Regen();
  62.     }
  63.  
  64.     private static PipePartOverrule _overrule = null;
  65. }
  66.  

От переводчика.

Как мы уже видели ранее, метод работы с частями сети на виде профиля через габаритный контейнер очень груб и может применяться в ограниченных случаях – когда заранее известно, каким образом отображается часть и строго определено, что одна часть отображается только на одном виде профиля.
В коде ниже представлено, каким образом можно переопределять отображения частей трубопроводной сети более корректно:
Код - C# [Выбрать]
  1. class MyPipePartOverrule : DrawableOverrule
  2. {
  3.     public override bool WorldDraw(
  4.      Drawable drawable, WorldDraw wd)
  5.     {
  6.         // Выводим базовое отображение объекта
  7.         bool ret = base.WorldDraw(drawable, wd);
  8.  
  9.         ProfileViewPart viewPart = drawable as ProfileViewPart;
  10.         if (viewPart == null) return ret; // для безопасности
  11.  
  12.         // получение типа объекта в модели
  13.         if (viewPart.ModelPartId.ObjectClass ==
  14.           RXClass.GetClass(typeof(Pipe)))
  15.         {
  16.             // Используем эмуляцию транзакции для работы с объектами
  17.             using (Transaction tr = viewPart.ModelPartId.Database
  18.                 .TransactionManager.StartOpenCloseTransaction())
  19.             {
  20.                 // Получаем объект трубы
  21.                 Pipe pipe = tr.GetObject(viewPart.ModelPartId, OpenMode.ForRead) as Pipe;
  22.  
  23.                 // Проходим по всем видам профилей, которые отображают трубу
  24.                 foreach (ObjectId pViewId in pipe.GetProfileViewsDisplayingMe())
  25.                 {
  26.                     // Проверяем существования вила профиля
  27.                     if (pViewId.IsValid && !pViewId.IsErased && !pViewId.IsEffectivelyErased)
  28.                     {
  29.                         // Получаем вид профиля
  30.                         ProfileView pView
  31.                             = tr.GetObject(pViewId, OpenMode.ForRead) as ProfileView;
  32.  
  33.                         // Получаем трассу вида профиля
  34.                         Alignment align
  35.                             = tr.GetObject(pView.AlignmentId, OpenMode.ForRead) as Alignment;
  36.  
  37.                         // Точка пересечения трубы и плоскости вида профиля
  38.                         Point3d intersPtAnPipe;
  39.  
  40.                         using (Point3dCollection ptsCol = new Point3dCollection())
  41.                         {
  42.                             pipe.IntersectWith
  43.                                 (align,
  44.                                 Intersect.OnBothOperands,
  45.                                 ptsCol, new IntPtr(0), new IntPtr(0));
  46.  
  47.                             // Если пересечений нет - переходим к следующему виду профиля
  48.                             if (ptsCol.Count != 1) continue;
  49.  
  50.                             // Точка пересечения, найденная в методе IntersectWith                                
  51.                             intersPtAnPipe = ptsCol[0];
  52.                         }
  53.  
  54.                         // Найденная точка находится не на трубе,
  55.                         // поэтому, требуется ее уточнить                              
  56.  
  57.                         #region Один из вариантов уточнения координаты Z для точки
  58.  
  59.                         // 2D точка пересечения
  60.                         Point2d intersPt2D = new Point2d(intersPtAnPipe.X, intersPtAnPipe.Y);
  61.  
  62.                         // Начальная и конечная точки трубы
  63.                         Point3d
  64.                             startPt = pipe.StartPoint,
  65.                             endPt = pipe.EndPoint;
  66.  
  67.                         // Если 2D точка пересечения трубы и трассы находится в начале трубы
  68.                         if (intersPt2D.IsEqualTo(new Point2d(startPt.X, startPt.Y), Tolerance.Global))
  69.                             // точка пересечения - начальная точка трубы
  70.                             intersPtAnPipe = startPt;
  71.                         // Если 2D точка пересечения трубы и трассы находится в конце трубы
  72.                         if (intersPt2D.IsEqualTo(new Point2d(endPt.X, endPt.Y), Tolerance.Global))
  73.                             // точка пересечения - конечная точка трубы
  74.                             intersPtAnPipe = endPt;
  75.                         else
  76.                         {
  77.                             // Математически определяем координату Z для точки
  78.                             double
  79.                                 angleFactor = 0.0,
  80.                                 intersPtZ = 0.0;
  81.  
  82.                             if (!intersPt2D.X.Equals(startPt.X))
  83.                                 angleFactor = (endPt.X - startPt.X) / (intersPt2D.X - startPt.X);
  84.  
  85.                             else if (!intersPt2D.Y.Equals(startPt.Y))
  86.                                 angleFactor = (endPt.Y - startPt.Y) / (intersPt2D.Y - startPt.Y);
  87.  
  88.                             intersPtZ = ((endPt.Z - startPt.Z) / angleFactor) + startPt.Z;
  89.  
  90.                             intersPtAnPipe = new Point3d(intersPt2D.X, intersPt2D.Y, intersPtZ);
  91.                         }
  92.  
  93.                         #endregion
  94.                        
  95.                         // Ищем переопределение стиля трубы на виде профиля
  96.                         ProfileOverride pipeStyleOverride =
  97.                             pView.GraphOverrides.SingleOrDefault(item =>
  98.                                 item.ProfileId.IsValid
  99.                                 && item.UseOverrideStyle
  100.                                 && item.ProfileId.Equals(pipe.ProfileViewPartId));
  101.  
  102.                         ObjectId pipeStyleId;
  103.  
  104.                         // Если стиль переопределен
  105.                         if (pipeStyleOverride != null)
  106.                         {
  107.                             // Получаем Id стиля переопределения
  108.                             pipeStyleId = pipeStyleOverride.OverrideStyleId;
  109.                         }
  110.                         else
  111.                         {
  112.                             // Иначе - берем Id стиля трубы на плане
  113.                             pipeStyleId = pipe.StyleId;
  114.                         }
  115.  
  116.                         // Получаем стиль трубы
  117.                         PipeStyle pipeStyle
  118.                             = tr.GetObject(pipeStyleId, OpenMode.ForRead) as PipeStyle;
  119.  
  120.                         // Получаем настройки отображения элементов сечения
  121.                         // пересекающей трубы на виде профиля из стиля трубы
  122.  
  123.                         // Штриховка перескающей трубы
  124.                         DisplayStyle dispStyleCPH = pipeStyle.GetDisplayStyleProfile
  125.                             (PipeDisplayStyleProfileType.CrossingPipeHatch);
  126.                         // Внутренняя стенка пересекающей трубы
  127.                         DisplayStyle dispStyleCPIW
  128.                             = pipeStyle.GetDisplayStyleProfile
  129.                             (PipeDisplayStyleProfileType.CrossingPipeInsideWall);
  130.                         // Внешняя стенка пересекающей трубы
  131.                         DisplayStyle dispStyleCPOW = pipeStyle.GetDisplayStyleProfile
  132.                             (PipeDisplayStyleProfileType.CrossingPipeOutsideWall);
  133.  
  134.                         // Проверяем, показывается ли хоть один элемент сечения
  135.                         bool showCrossing
  136.                             = dispStyleCPH.Visible
  137.                             || dispStyleCPIW.Visible
  138.                             || dispStyleCPOW.Visible;
  139.  
  140.                         // Если пересекающая труба никак не отображается - переходим
  141.                         // к следующему виду профиля
  142.                         if (!showCrossing) continue;
  143.  
  144.                         // Находим пикетаж точки пересечения трубы и вида профиля
  145.                         double station = 0.0, offset = 0.0;
  146.                         align.StationOffset
  147.                             (intersPtAnPipe.X, intersPtAnPipe.Y, ref station, ref offset);
  148.  
  149.                         // Получаем координаты точки пересечения на виде профиля
  150.                         double x = 0.0, y = 0.0;
  151.                         pView.FindXYAtStationAndElevation
  152.                             (station, intersPtAnPipe.Z, ref x, ref y);
  153.  
  154.                         // Получаем стиль вида профиля
  155.                         ProfileViewStyle pViewStyle
  156.                             = tr.GetObject(pView.StyleId, OpenMode.ForRead) as ProfileViewStyle;
  157.  
  158.                         // Получаем вертикальный коэффициент масштабирования
  159.                         GraphStyle graphStyle = pViewStyle.GraphStyle;
  160.                         double verticalScaleFactor
  161.                             = graphStyle.CurrentHorizontalScale / graphStyle.VerticalScale;
  162.  
  163.                         // Наружный радиус трубы по высоте в масштабе вида профиля
  164.                         double outerRadInScale
  165.                             = pipe.OuterDiameterOrWidth * verticalScaleFactor / 2.0;
  166.  
  167.                         // Рисуем крестик на пересекающей трубе
  168.                         // pt1   pt3
  169.                         //    \ /
  170.                         //    / \
  171.                         // pt4   pt2
  172.  
  173.                         Point3d
  174.                             pt1 = new Point3d
  175.                                 (x - outerRadInScale, y + outerRadInScale, pView.Location.Z),
  176.                             pt2 = new Point3d
  177.                                 (x + outerRadInScale, y - outerRadInScale, pView.Location.Z),
  178.                             pt3 = new Point3d
  179.                                 (x + outerRadInScale, y + outerRadInScale, pView.Location.Z),
  180.                             pt4 = new Point3d
  181.                                 (x - outerRadInScale, y - outerRadInScale, pView.Location.Z);
  182.  
  183.                         wd.Geometry.WorldLine(pt1, pt2);
  184.                         wd.Geometry.WorldLine(pt3, pt4);
  185.                     }
  186.                 }
  187.  
  188.                 tr.Commit();
  189.             }
  190.         }
  191.  
  192.         // если вам нужно обрабатывать колодцы
  193.         //else if (viewPart.ModelPartId.ObjectClass ==
  194.         //  RXClass.GetClass(typeof(Structure)))
  195.         //{
  196.         //}
  197.  
  198.         return ret;
  199.     }
  200. }
  201.  
  202. public class MyCommads
  203. {
  204.     [CommandMethod("MyProfilePartOverrule")]
  205.     public static void CmdProfilePartOverrule()
  206.     {
  207.         if (_overrule == null)
  208.         {
  209.             _overrule = new MyPipePartOverrule();
  210.             Overrule.AddOverrule(
  211.               RXClass.GetClass(typeof(ProfileViewPart)),
  212.               _overrule, false);
  213.         }
  214.         else
  215.         {
  216.             Overrule.RemoveOverrule(
  217.               RXClass.GetClass(typeof(ProfileViewPart)),
  218.               _overrule);
  219.             _overrule = null;
  220.         }
  221.         Application.DocumentManager.
  222.           MdiActiveDocument.Editor.Regen();
  223.     }
  224.  
  225.     private static MyPipePartOverrule _overrule = null;
  226. }
  227.  
В результате, на видах профилей все пересекающие трубы будут с крестиками, как на рисунке.

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

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