Статьи > Тестирование статей

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

(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

Навигация

[0] Главная страница сообщений

Перейти к полной версии