Переопределение частей трубопроводной сети на виде профиля
Используя эту простую заготовку переопределения, мы можем изменить отображение трубы или колодца на виде профиля. Нам нужно переопределить класс ProfileViewPart и добавить немного геометрии. Это простой пример:
- class PipePartOverrule : DrawableOverrule
- {
- public override bool WorldDraw(
- Drawable drawable, WorldDraw wd)
- {
- bool ret = base.WorldDraw(drawable, wd);
- ProfileViewPart viewPart = drawable as ProfileViewPart;
- if (viewPart == null) return ret; // для безопасности
- // получение базы данных
- // если объект является объектом базы данных,
- // получаем ее из свойства объекта
- // если нет, получаем активную базу данных
- Database db = (viewPart.Database != null ?
- viewPart.Database :
- Application.DocumentManager.
- MdiActiveDocument.Database);
- // получение типа объекта в модели
- if (viewPart.ModelPartId.ObjectClass ==
- RXClass.GetClass(typeof(Pipe)))
- {
- // хорошо, эта часть представляет собой трубу
- // нарисуем что-нибудь... пусть будет пересекающий отрезок
- wd.Geometry.WorldLine(
- viewPart.Bounds.Value.MinPoint,
- viewPart.Bounds.Value.MaxPoint);
- }
- // если вам нужно обрабатывать колодцы
- //else if (viewPart.ModelPartId.ObjectClass ==
- // RXClass.GetClass(typeof(Structure)))
- //{
- //}
- return ret;
- }
- }
- public class Commads
- {
- [CommandMethod("profilePartOverrule")]
- public static void CmdProfilePartOverrule()
- {
- if (_overrule == null)
- {
- _overrule = new PipePartOverrule();
- Overrule.AddOverrule(
- RXClass.GetClass(typeof(ProfileViewPart)),
- _overrule, false);
- }
- else
- {
- Overrule.RemoveOverrule(
- RXClass.GetClass(typeof(ProfileViewPart)),
- _overrule);
- _overrule = null;
- }
- Application.DocumentManager.
- MdiActiveDocument.Editor.Regen();
- }
- private static PipePartOverrule _overrule = null;
- }
От переводчика: Как мы уже видели ранее, метод работы с частями сети на виде профиля через габаритный контейнер очень груб и может применяться в ограниченных случаях – когда заранее известно, каким образом отображается часть и строго определено, что одна часть отображается только на одном виде профиля.
В коде ниже представлено, каким образом можно переопределять отображения частей трубопроводной сети более корректно:
- class MyPipePartOverrule : DrawableOverrule
- {
- public override bool WorldDraw(
- Drawable drawable, WorldDraw wd)
- {
- // Выводим базовое отображение объекта
- bool ret = base.WorldDraw(drawable, wd);
- ProfileViewPart viewPart = drawable as ProfileViewPart;
- if (viewPart == null) return ret; // для безопасности
- // получение типа объекта в модели
- if (viewPart.ModelPartId.ObjectClass ==
- RXClass.GetClass(typeof(Pipe)))
- {
- // Используем эмуляцию транзакции для работы с объектами
- using (Transaction tr = viewPart.ModelPartId.Database
- .TransactionManager.StartOpenCloseTransaction())
- {
- // Получаем объект трубы
- Pipe pipe = tr.GetObject(viewPart.ModelPartId, OpenMode.ForRead) as Pipe;
- // Проходим по всем видам профилей, которые отображают трубу
- foreach (ObjectId pViewId in pipe.GetProfileViewsDisplayingMe())
- {
- // Проверяем существования вила профиля
- if (pViewId.IsValid && !pViewId.IsErased && !pViewId.IsEffectivelyErased)
- {
- // Получаем вид профиля
- ProfileView pView
- = tr.GetObject(pViewId, OpenMode.ForRead) as ProfileView;
- // Получаем трассу вида профиля
- Alignment align
- = tr.GetObject(pView.AlignmentId, OpenMode.ForRead) as Alignment;
- // Точка пересечения трубы и плоскости вида профиля
- Point3d intersPtAnPipe;
- using (Point3dCollection ptsCol = new Point3dCollection())
- {
- pipe.IntersectWith
- (align,
- Intersect.OnBothOperands,
- ptsCol, new IntPtr(0), new IntPtr(0));
- // Если пересечений нет - переходим к следующему виду профиля
- if (ptsCol.Count != 1) continue;
- // Точка пересечения, найденная в методе IntersectWith
- intersPtAnPipe = ptsCol[0];
- }
- // Найденная точка находится не на трубе,
- // поэтому, требуется ее уточнить
- #region Один из вариантов уточнения координаты Z для точки
- // 2D точка пересечения
- Point2d intersPt2D = new Point2d(intersPtAnPipe.X, intersPtAnPipe.Y);
- // Начальная и конечная точки трубы
- Point3d
- startPt = pipe.StartPoint,
- endPt = pipe.EndPoint;
- // Если 2D точка пересечения трубы и трассы находится в начале трубы
- if (intersPt2D.IsEqualTo(new Point2d(startPt.X, startPt.Y), Tolerance.Global))
- // точка пересечения - начальная точка трубы
- intersPtAnPipe = startPt;
- // Если 2D точка пересечения трубы и трассы находится в конце трубы
- if (intersPt2D.IsEqualTo(new Point2d(endPt.X, endPt.Y), Tolerance.Global))
- // точка пересечения - конечная точка трубы
- intersPtAnPipe = endPt;
- else
- {
- // Математически определяем координату Z для точки
- double
- angleFactor = 0.0,
- intersPtZ = 0.0;
- if (!intersPt2D.X.Equals(startPt.X))
- angleFactor = (endPt.X - startPt.X) / (intersPt2D.X - startPt.X);
- else if (!intersPt2D.Y.Equals(startPt.Y))
- angleFactor = (endPt.Y - startPt.Y) / (intersPt2D.Y - startPt.Y);
- intersPtZ = ((endPt.Z - startPt.Z) / angleFactor) + startPt.Z;
- intersPtAnPipe = new Point3d(intersPt2D.X, intersPt2D.Y, intersPtZ);
- }
- #endregion
- // Ищем переопределение стиля трубы на виде профиля
- ProfileOverride pipeStyleOverride =
- pView.GraphOverrides.SingleOrDefault(item =>
- item.ProfileId.IsValid
- && item.UseOverrideStyle
- && item.ProfileId.Equals(pipe.ProfileViewPartId));
- ObjectId pipeStyleId;
- // Если стиль переопределен
- if (pipeStyleOverride != null)
- {
- // Получаем Id стиля переопределения
- pipeStyleId = pipeStyleOverride.OverrideStyleId;
- }
- else
- {
- // Иначе - берем Id стиля трубы на плане
- pipeStyleId = pipe.StyleId;
- }
- // Получаем стиль трубы
- PipeStyle pipeStyle
- = tr.GetObject(pipeStyleId, OpenMode.ForRead) as PipeStyle;
- // Получаем настройки отображения элементов сечения
- // пересекающей трубы на виде профиля из стиля трубы
- // Штриховка перескающей трубы
- DisplayStyle dispStyleCPH = pipeStyle.GetDisplayStyleProfile
- (PipeDisplayStyleProfileType.CrossingPipeHatch);
- // Внутренняя стенка пересекающей трубы
- DisplayStyle dispStyleCPIW
- = pipeStyle.GetDisplayStyleProfile
- (PipeDisplayStyleProfileType.CrossingPipeInsideWall);
- // Внешняя стенка пересекающей трубы
- DisplayStyle dispStyleCPOW = pipeStyle.GetDisplayStyleProfile
- (PipeDisplayStyleProfileType.CrossingPipeOutsideWall);
- // Проверяем, показывается ли хоть один элемент сечения
- bool showCrossing
- = dispStyleCPH.Visible
- || dispStyleCPIW.Visible
- || dispStyleCPOW.Visible;
- // Если пересекающая труба никак не отображается - переходим
- // к следующему виду профиля
- if (!showCrossing) continue;
- // Находим пикетаж точки пересечения трубы и вида профиля
- double station = 0.0, offset = 0.0;
- align.StationOffset
- (intersPtAnPipe.X, intersPtAnPipe.Y, ref station, ref offset);
- // Получаем координаты точки пересечения на виде профиля
- double x = 0.0, y = 0.0;
- pView.FindXYAtStationAndElevation
- (station, intersPtAnPipe.Z, ref x, ref y);
- // Получаем стиль вида профиля
- ProfileViewStyle pViewStyle
- = tr.GetObject(pView.StyleId, OpenMode.ForRead) as ProfileViewStyle;
- // Получаем вертикальный коэффициент масштабирования
- GraphStyle graphStyle = pViewStyle.GraphStyle;
- double verticalScaleFactor
- = graphStyle.CurrentHorizontalScale / graphStyle.VerticalScale;
- // Наружный радиус трубы по высоте в масштабе вида профиля
- double outerRadInScale
- = pipe.OuterDiameterOrWidth * verticalScaleFactor / 2.0;
- // Рисуем крестик на пересекающей трубе
- // pt1 pt3
- // \ /
- // / \
- // pt4 pt2
- Point3d
- pt1 = new Point3d
- (x - outerRadInScale, y + outerRadInScale, pView.Location.Z),
- pt2 = new Point3d
- (x + outerRadInScale, y - outerRadInScale, pView.Location.Z),
- pt3 = new Point3d
- (x + outerRadInScale, y + outerRadInScale, pView.Location.Z),
- pt4 = new Point3d
- (x - outerRadInScale, y - outerRadInScale, pView.Location.Z);
- wd.Geometry.WorldLine(pt1, pt2);
- wd.Geometry.WorldLine(pt3, pt4);
- }
- }
- tr.Commit();
- }
- }
- // если вам нужно обрабатывать колодцы
- //else if (viewPart.ModelPartId.ObjectClass ==
- // RXClass.GetClass(typeof(Structure)))
- //{
- //}
- return ret;
- }
- }
- public class MyCommads
- {
- [CommandMethod("MyProfilePartOverrule")]
- public static void CmdProfilePartOverrule()
- {
- if (_overrule == null)
- {
- _overrule = new MyPipePartOverrule();
- Overrule.AddOverrule(
- RXClass.GetClass(typeof(ProfileViewPart)),
- _overrule, false);
- }
- else
- {
- Overrule.RemoveOverrule(
- RXClass.GetClass(typeof(ProfileViewPart)),
- _overrule);
- _overrule = null;
- }
- Application.DocumentManager.
- MdiActiveDocument.Editor.Regen();
- }
- private static MyPipePartOverrule _overrule = null;
- }
В результате, на видах профилей все пересекающие трубы будут с крестиками, как на рисунке:
Источник: http://adndevblog.typepad.com/infrastructure/2015/04/overrule-pipe-network-part-in-profile-view.html
Автор перевода: Дмитрий Загорулькин
Обсуждение: http://adn-cis.org/forum/index.php?topic=2984
Опубликовано 05.09.2015