Создание новой ТП на трассе для трубопроводной сети в заданном пикете
С помощью инструментов пользовательского интерфейса редактирования трассы, мы легко можем добавить на нее точку пересечения (ТП). Однако в API Civil 3D 2013-2016 нет никакого готового метода, позволяющего выполнить то же самое программно. Мне же был крайне необходим такой метод для автоматизации работы с видами профилей трубопроводных сетей, поэтому пришлось разрабатывать его самостоятельно.
В общем случае, эта задача крайне непроста. Достаточно взглянуть на список возможных типов объектов, которые могут входить в состав трассы:
- 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», т.к. трубы можно создать только прямые или дуговые. Вдобавок, трасса для объектов трубопроводной сети не имеет «плавающих» составляющих. Значит, не придется рассматривать все эти варианты:
- public enum AlignmentEntityConstraintType
- {
- Fixed = 289,
- FloatOnPrev = 290,
- FloatOnNext = 291,
- Free = 292,
- }
Таким образом, у нас имеются ограничения:
• AlignmentEntityType – Line и Arc
• AlignmentEntityConstraintType – Fixed
Ниже представлен код, решающий поставленную задачу:
- 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;
- }
- }
- }
Обсуждение: http://adn-cis.org/forum/index.php?topic=3012
Опубликовано 12.09.2015