ADN Open CIS
Сообщество программистов Autodesk в СНГ

12/09/2015

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

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

Код - C#: [Выделить]
  1.     public enum AlignmentEntityType
  2.     {
  3.         Line = 257,
  4.         Arc = 258,
  5.         Spiral = 259,
  6.         SpiralCurveSpiral = 260,
  7.         SpiralLineSpiral = 261,
  8.         SpiralLine = 262,
  9.         LineSpiral = 263,
  10.         SpiralCurve = 264,
  11.         CurveSpiral = 265,
  12.         SpiralSpiralCurveSpiralSpiral = 266,
  13.         MultipleSegments = 267,
  14.         SpiralCurveSpiralCurveSpiral = 268,
  15.         SpiralCurveSpiralSpiralCurveSpiral = 269,
  16.         SpiralSpiral = 270,
  17.         SpiralSpiralCurve = 271,
  18.         CurveSpiralSpiral = 272,
  19.         CurveLineCurve = 273,
  20.         CurveReverseCurve = 274,
  21.         CurveCurveReverseCurve = 275,
  22.     }

Но в случае с трубопроводной сетью, нужно обработать только объекты типа «Line» и «Arc», т.к. трубы можно создать только прямые или дуговые. Вдобавок, трасса для объектов трубопроводной сети не имеет «плавающих» составляющих. Значит, не придется рассматривать все эти варианты:

Код - C#: [Выделить]
  1.     public enum AlignmentEntityConstraintType
  2.     {
  3.         Fixed = 289,
  4.         FloatOnPrev = 290,
  5.         FloatOnNext = 291,
  6.         Free = 292,
  7.     }

Таким образом, у нас имеются ограничения:

•   AlignmentEntityType – Line и Arc

•   AlignmentEntityConstraintType – Fixed

Ниже представлен код, решающий поставленную задачу:

Код - C#: [Выделить]
  1.     using Autodesk.AutoCAD.ApplicationServices;
  2.     using Autodesk.AutoCAD.DatabaseServices;
  3.     using Autodesk.AutoCAD.EditorInput;
  4.     using Autodesk.AutoCAD.Geometry;
  5.     using Autodesk.AutoCAD.Runtime;
  6.     using Autodesk.Civil.ApplicationServices;
  7.     using Autodesk.Civil.DatabaseServices;
  8.     using System;
  9.     using System.Linq;
  10.     
  11.     namespace DZagorulkin.CivilExtension
  12.     {
  13.         public class TestCommandClass
  14.         {
  15.             [CommandMethod("TestAddPI")]
  16.             public void AlignmentAddPITest()
  17.             {
  18.                 Document adoc = Application.DocumentManager.MdiActiveDocument;
  19.                 Database db = adoc.Database;
  20.                 Editor ed = adoc.Editor;
  21.     
  22.                 PromptEntityOptions alignOpt = new PromptEntityOptions("\nВыберите трассу: ");
  23.                 alignOpt.SetRejectMessage("\nЭто не трасса!");
  24.                 alignOpt.AddAllowedClass(typeof(Alignment), true);
  25.     
  26.                 PromptEntityResult alignRes = ed.GetEntity(alignOpt);
  27.                 if (alignRes.Status != PromptStatus.OK) return;
  28.     
  29.                 PromptDoubleResult newPiStationRes = ed.GetDouble("\nПикетаж для добавления ТП: ");
  30.                 if (newPiStationRes.Status != PromptStatus.OK) return;
  31.     
  32.                 bool ok;
  33.     
  34.                 using (Transaction tr = db.TransactionManager.StartTransaction())
  35.                 {
  36.                     Alignment align = tr.GetObject
  37.                         (alignRes.ObjectId, OpenMode.ForWrite, false, true) as Alignment;
  38.                     ok = align.AddPIToFixedSubEntity(newPiStationRes.Value);
  39.                     tr.Commit();
  40.                 }
  41.     
  42.                 ed.WriteMessage
  43.                     ("\nТП на пикете {0:0.00} {1}.",
  44.                     newPiStationRes.Value,
  45.                     ok ? "создана" : "создать не удалось");
  46.             }
  47.         }
  48.     
  49.         public static class AlignmentSupport
  50.         {
  51.             /// <summary>
  52.             /// Добавление точки пересечения (ТП)
  53.             /// на фиксированном участке трассы
  54.             /// </summary>
  55.             /// <param name="alignment">Трасса</param>
  56.             /// <param name="station">Пикет, в котором добавляем точку</param>
  57.             public static bool AddPIToFixedSubEntity(this Alignment alignment, double station)
  58.             {
  59.                 // Координаты точки - будущей ТП
  60.                 Point2d point;
  61.                 // Если трасса не содержит еще ТП в указаном пикете
  62.                 if (!alignment.GetStationSet(StationTypes.GeometryPoint)
  63.                     .Any(stat => stat.RawStation.Equals(station))
  64.                     // и точка находится на трассе
  65.                     && GetPointAtStation(alignment, station, out point))
  66.                 {
  67.                     // Проходим по всем объектам трассы, пока не найдем объект,
  68.                     // на котором наша точка
  69.                     for (int i = 0; i < alignment.Entities.Count; i++)
  70.                     {
  71.                         AlignmentEntity alignEnt = alignment.Entities[i];
  72.     
  73.                         // Если объект имеет нефиксированный тип - пропускаем его
  74.                         if (alignEnt.Constraint1 != AlignmentEntityConstraintType.Fixed) continue;
  75.     
  76.                         // Если объект - отрезок
  77.                         if (alignEnt.EntityType == AlignmentEntityType.Line)
  78.                         {
  79.                             // Приводим его к типу "отрезок трассы"
  80.                             AlignmentLine alignLine = alignEnt as AlignmentLine;
  81.                             // Получаем координаты начала и конца
  82.                             Point2d startPt = alignLine.StartPoint;
  83.                             Point2d endPt = alignLine.EndPoint;
  84.     
  85.                             // Если добавляемая точка находится на этом отрезке
  86.                             if (Math.Min(alignLine.StartStation, alignLine.EndStation) < station
  87.                                 && station < Math.Max(alignLine.StartStation, alignLine.EndStation))
  88.                             {
  89.                                 // Создаем вместо одного отрезка два
  90.                                 alignment.Entities.AddFixedLine
  91.                                     (new Point3d(startPt.X, startPt.Y, 0.0),
  92.                                     new Point3d(point.X, point.Y, 0.0));
  93.                                 alignment.Entities.AddFixedLine
  94.                                     (new Point3d(point.X, point.Y, 0.0),
  95.                                     new Point3d(endPt.X, endPt.Y, 0.0));
  96.                                 // Удаляем исходный отрезок
  97.                                 alignment.Entities.Remove(alignEnt);
  98.                                 return true;
  99.                             }
  100.                         }
  101.                         // Если объект - дуга
  102.                         else if (alignEnt.EntityType == AlignmentEntityType.Arc)
  103.                         {
  104.                             // Приводим его к типу "дуга трассы"
  105.                             AlignmentArc alignArc = alignEnt as AlignmentArc;
  106.     
  107.                             // Получаем среднюю точку дуги трассы
  108.                             Point2d midPoint;
  109.                             GetPointAtStation
  110.                                 (alignment,
  111.                                 (alignArc.EndStation + alignArc.StartStation) / 2,
  112.                                 out midPoint);
  113.     
  114.                             // Проверяем, находится ли наша точка на этой дуге.
  115.                             if (Math.Min(alignArc.StartStation, alignArc.EndStation) < station
  116.                                 && station < Math.Max(alignArc.StartStation, alignArc.EndStation))
  117.                             {
  118.                                 // Получаем средние точки будущих трасс
  119.                                 Point3d midFirstArc, midSecondArc;
  120.     
  121.                                 using (CircularArc2d arc
  122.                                     = new CircularArc2d(alignArc.StartPoint, midPoint, alignArc.EndPoint))
  123.                                 {
  124.     
  125.                                     double
  126.                                         paramStart = arc.GetParameterOf(alignArc.StartPoint),
  127.                                         paramEnd = arc.GetParameterOf(alignArc.EndPoint),
  128.                                         paramPt = arc.GetParameterOf(point);
  129.     
  130.                                     Point2d pt1 = arc.EvaluatePoint((paramPt + paramStart) * 0.5);
  131.                                     midFirstArc = new Point3d(pt1.X, pt1.Y, 0.0);
  132.     
  133.                                     Point2d pt2 = arc.EvaluatePoint((paramPt + paramEnd) * 0.5);
  134.                                     midSecondArc = new Point3d(pt2.X, pt2.Y, 0.0);
  135.                                 }                           
  136.     
  137.                                 // Создаем вместо одной дуги две
  138.                                 AlignmentArc newFirstArc = alignment.Entities.AddFixedCurve
  139.                                    (alignArc.EntityBefore,
  140.                                    new Point3d(alignArc.StartPoint.X, alignArc.StartPoint.Y, 0.0),
  141.                                    midFirstArc, new Point3d(point.X, point.Y, 0.0));
  142.                                 alignment.Entities.AddFixedCurve
  143.                                     (newFirstArc.EntityId, new Point3d(point.X, point.Y, 0.0), midSecondArc,
  144.                                     new Point3d(alignArc.EndPoint.X, alignArc.EndPoint.Y, 0.0));
  145.                                 // Удаляем исходную дугу
  146.                                 alignment.Entities.Remove(alignEnt);
  147.                                 return true;
  148.                             }
  149.                         }
  150.                     }
  151.                 }
  152.     
  153.                 return false;
  154.             }
  155.     
  156.             /// <summary>
  157.             /// Вспомогательный метод получения точки на трассе в указанном пикете
  158.             /// </summary>
  159.             /// <param name="alignment">Трасса</param>
  160.             /// <param name="station">Пикет</param>
  161.             /// <param name="stationPoint">Переменная для сохранения точки</param>
  162.             /// <returns>True - пикетаж задан верно, false - пикет вне трассы</returns>
  163.             static bool GetPointAtStation
  164.                 (Alignment alignment, double station, out Point2d stationPoint)
  165.             {
  166.                 // Если пикетаж в границах трассы
  167.                 if (alignment.StartingStation <= station
  168.                     && station <= alignment.EndingStation)
  169.                 {
  170.                     // Получаем 3D точку на пикете
  171.                     Point3d pt = alignment.GetPointAtDist
  172.                         (station - alignment.StartingStation);
  173.     
  174.                     // Конвертируем ее в 2D
  175.                     stationPoint = new Point2d(pt.X, pt.Y);
  176.     
  177.                     return true;
  178.                 }
  179.                 stationPoint = new Point2d();
  180.                 return false;
  181.             }
  182.         }
  183.     }

 

Автор: Дмитрий Загорулькин

Обсуждение: http://adn-cis.org/forum/index.php?topic=3012

Опубликовано 12.09.2015