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

Civil 3D. Создание новой ТП на трассе для трубопроводной сети в заданном пикете.

(1/1)

Дмитрий Загорулькин:
С помощью инструментов пользовательского интерфейса редактирования трассы, мы легко можем добавить на нее точку пересечения (ТП). Однако в API Civil 3D 2013-2016 нет никакого готового метода, позволяющего выполнить то же самое программно. Мне же был крайне необходим такой метод для автоматизации работы с видами профилей трубопроводных сетей, поэтому пришлось разрабатывать его самостоятельно.
В общем случае, эта задача крайне непроста. Достаточно взглянуть на список возможных типов объектов, которые могут входить в состав трассы:

--- Код - C# [Выбрать] ---public enum AlignmentEntityType{    Line = 257,    Arc = 258,    Spiral = 259,    SpiralCurveSpiral = 260,    SpiralLineSpiral = 261,    SpiralLine = 262,    LineSpiral = 263,    SpiralCurve = 264,    CurveSpiral = 265,    SpiralSpiralCurveSpiralSpiral = 266,    MultipleSegments = 267,    SpiralCurveSpiralCurveSpiral = 268,    SpiralCurveSpiralSpiralCurveSpiral = 269,    SpiralSpiral = 270,    SpiralSpiralCurve = 271,    CurveSpiralSpiral = 272,    CurveLineCurve = 273,    CurveReverseCurve = 274,    CurveCurveReverseCurve = 275,}
Но в случае с трубопроводной сетью, нужно обработать только объекты типа «Line» и «Arc», т.к. трубы можно создать только прямые или дуговые. Вдобавок, трасса для объектов трубопроводной сети не имеет «плавающих» составляющих. Значит, не придется рассматривать все эти варианты:

--- Код - C# [Выбрать] ---public enum AlignmentEntityConstraintType{    Fixed = 289,    FloatOnPrev = 290,    FloatOnNext = 291,    Free = 292,}Таким образом, у нас имеются ограничения:
•   AlignmentEntityType – Line и Arc
•   AlignmentEntityConstraintType – Fixed
Ниже представлен код, решающий поставленную задачу:

--- Код - C# [Выбрать] ---using Autodesk.AutoCAD.ApplicationServices;using Autodesk.AutoCAD.DatabaseServices;using Autodesk.AutoCAD.EditorInput;using Autodesk.AutoCAD.Geometry;using Autodesk.AutoCAD.Runtime;using Autodesk.Civil.ApplicationServices;using Autodesk.Civil.DatabaseServices;using System;using System.Linq; namespace DZagorulkin.CivilExtension{    public class TestCommandClass    {        [CommandMethod("TestAddPI")]        public void AlignmentAddPITest()        {            Document adoc = Application.DocumentManager.MdiActiveDocument;            Database db = adoc.Database;            Editor ed = adoc.Editor;             PromptEntityOptions alignOpt = new PromptEntityOptions("\nВыберите трассу: ");            alignOpt.SetRejectMessage("\nЭто не трасса!");            alignOpt.AddAllowedClass(typeof(Alignment), true);             PromptEntityResult alignRes = ed.GetEntity(alignOpt);            if (alignRes.Status != PromptStatus.OK) return;             PromptDoubleResult newPiStationRes = ed.GetDouble("\nПикетаж для добавления ТП: ");            if (newPiStationRes.Status != PromptStatus.OK) return;             bool ok;             using (Transaction tr = db.TransactionManager.StartTransaction())            {                Alignment align = tr.GetObject                    (alignRes.ObjectId, OpenMode.ForWrite, false, true) as Alignment;                ok = align.AddPIToFixedSubEntity(newPiStationRes.Value);                tr.Commit();            }             ed.WriteMessage                ("\nТП на пикете {0:0.00} {1}.",                newPiStationRes.Value,                ok ? "создана" : "создать не удалось");        }    }     public static class AlignmentSupport    {        /// <summary>        /// Добавление точки пересечения (ТП)        /// на фиксированном участке трассы        /// </summary>        /// <param name="alignment">Трасса</param>        /// <param name="station">Пикет, в котором добавляем точку</param>        public static bool AddPIToFixedSubEntity(this Alignment alignment, double station)        {            // Координаты точки - будущей ТП            Point2d point;            // Если трасса не содержит еще ТП в указаном пикете            if (!alignment.GetStationSet(StationTypes.GeometryPoint)                .Any(stat => stat.RawStation.Equals(station))                // и точка находится на трассе                && GetPointAtStation(alignment, station, out point))            {                // Проходим по всем объектам трассы, пока не найдем объект,                // на котором наша точка                for (int i = 0; i < alignment.Entities.Count; i++)                {                    AlignmentEntity alignEnt = alignment.Entities[i];                     // Если объект имеет нефиксированный тип - пропускаем его                    if (alignEnt.Constraint1 != AlignmentEntityConstraintType.Fixed) continue;                     // Если объект - отрезок                    if (alignEnt.EntityType == AlignmentEntityType.Line)                    {                        // Приводим его к типу "отрезок трассы"                        AlignmentLine alignLine = alignEnt as AlignmentLine;                        // Получаем координаты начала и конца                        Point2d startPt = alignLine.StartPoint;                        Point2d endPt = alignLine.EndPoint;                         // Если добавляемая точка находится на этом отрезке                        if (Math.Min(alignLine.StartStation, alignLine.EndStation) < station                            && station < Math.Max(alignLine.StartStation, alignLine.EndStation))                        {                            // Создаем вместо одного отрезка два                            alignment.Entities.AddFixedLine                                (new Point3d(startPt.X, startPt.Y, 0.0),                                new Point3d(point.X, point.Y, 0.0));                            alignment.Entities.AddFixedLine                                (new Point3d(point.X, point.Y, 0.0),                                new Point3d(endPt.X, endPt.Y, 0.0));                            // Удаляем исходный отрезок                            alignment.Entities.Remove(alignEnt);                            return true;                        }                    }                    // Если объект - дуга                    else if (alignEnt.EntityType == AlignmentEntityType.Arc)                    {                        // Приводим его к типу "дуга трассы"                        AlignmentArc alignArc = alignEnt as AlignmentArc;                         // Получаем среднюю точку дуги трассы                        Point2d midPoint;                        GetPointAtStation                            (alignment,                            (alignArc.EndStation + alignArc.StartStation) / 2,                            out midPoint);                         // Проверяем, находится ли наша точка на этой дуге.                        if (Math.Min(alignArc.StartStation, alignArc.EndStation) < station                            && station < Math.Max(alignArc.StartStation, alignArc.EndStation))                        {                            // Получаем средние точки будущих трасс                            Point3d midFirstArc, midSecondArc;                             using (CircularArc2d arc                                = new CircularArc2d(alignArc.StartPoint, midPoint, alignArc.EndPoint))                            {                                 double                                    paramStart = arc.GetParameterOf(alignArc.StartPoint),                                    paramEnd = arc.GetParameterOf(alignArc.EndPoint),                                    paramPt = arc.GetParameterOf(point);                                 Point2d pt1 = arc.EvaluatePoint((paramPt + paramStart) * 0.5);                                midFirstArc = new Point3d(pt1.X, pt1.Y, 0.0);                                 Point2d pt2 = arc.EvaluatePoint((paramPt + paramEnd) * 0.5);                                midSecondArc = new Point3d(pt2.X, pt2.Y, 0.0);                            }                                                         // Создаем вместо одной дуги две                            AlignmentArc newFirstArc = alignment.Entities.AddFixedCurve                               (alignArc.EntityBefore,                               new Point3d(alignArc.StartPoint.X, alignArc.StartPoint.Y, 0.0),                               midFirstArc, new Point3d(point.X, point.Y, 0.0));                            alignment.Entities.AddFixedCurve                                (newFirstArc.EntityId, new Point3d(point.X, point.Y, 0.0), midSecondArc,                                new Point3d(alignArc.EndPoint.X, alignArc.EndPoint.Y, 0.0));                            // Удаляем исходную дугу                            alignment.Entities.Remove(alignEnt);                            return true;                        }                    }                }            }             return false;        }         /// <summary>        /// Вспомогательный метод получения точки на трассе в указанном пикете        /// </summary>        /// <param name="alignment">Трасса</param>        /// <param name="station">Пикет</param>        /// <param name="stationPoint">Переменная для сохранения точки</param>        /// <returns>True - пикетаж задан верно, false - пикет вне трассы</returns>        static bool GetPointAtStation            (Alignment alignment, double station, out Point2d stationPoint)        {            // Если пикетаж в границах трассы            if (alignment.StartingStation <= station                && station <= alignment.EndingStation)            {                // Получаем 3D точку на пикете                Point3d pt = alignment.GetPointAtDist                    (station - alignment.StartingStation);                 // Конвертируем ее в 2D                stationPoint = new Point2d(pt.X, pt.Y);                 return true;            }            stationPoint = new Point2d();            return false;        }    }} 

Алексей Кулик:
Off-Topic: показатьНа всякий случай: в заголовке статьи укажи полное название и версию ПО, для которого выполняешь разработку. Я, например, могу только подозревать, что разговор ведется про Civil3D 2014-2016, но не уверен :)

Дмитрий Загорулькин:
Спасибо, принято :)
Версия в заголовок уже не вмещается.

Александр Ривилис:
Отлично! Статья принята и опубликована на сайте: Создание новой ТП на трассе для трубопроводной сети в заданном пикете

Навигация

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

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