Статьи > Тестирование статей
Переопределение частей трубопроводной сети на виде профиля.
(1/1)
Дмитрий Загорулькин:
Оригинал статьи: http://adndevblog.typepad.com/infrastructure/2015/04/overrule-pipe-network-part-in-profile-view.html
Используя эту простую заготовку переопределения, мы можем изменить отображение трубы или колодца на виде профиля. Нам нужно переопределить класс ProfileViewPart и добавить немного геометрии. Это простой пример:
--- Код - C# [Выбрать] ---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;}
От переводчика.
Как мы уже видели ранее, метод работы с частями сети на виде профиля через габаритный контейнер очень груб и может применяться в ограниченных случаях – когда заранее известно, каким образом отображается часть и строго определено, что одна часть отображается только на одном виде профиля.
В коде ниже представлено, каким образом можно переопределять отображения частей трубопроводной сети более корректно:
--- Код - C# [Выбрать] ---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://adn-cis.org/pereopredelenie-chastej-truboprovodnoj-seti-na-vide-profilya.html
Навигация
Перейти к полной версии