Статьи > Тестирование статей
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, но не уверен :)
Дмитрий Загорулькин:
Спасибо, принято :)
Версия в заголовок уже не вмещается.
Александр Ривилис:
Отлично! Статья принята и опубликована на сайте: Создание новой ТП на трассе для трубопроводной сети в заданном пикете
Навигация
Перейти к полной версии