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;
}
}
}