class MyPipePartOverrule : DrawableOverrule
{
public override bool WorldDraw(
Drawable drawable, WorldDraw wd)
{
// Выводим базовое отображение объекта
bool ret = base.WorldDraw(drawable, wd);
ProfileViewPart viewPart = drawable as ProfileViewPart;
if (viewPart == null) return ret; // для безопасности
// получение типа объекта в модели
if (viewPart.ModelPartId.ObjectClass ==
RXClass.GetClass(typeof(Pipe)))
{
// Используем эмуляцию транзакции для работы с объектами
using (Transaction tr = viewPart.ModelPartId.Database
.TransactionManager.StartOpenCloseTransaction())
{
// Получаем объект трубы
Pipe pipe = tr.GetObject(viewPart.ModelPartId, OpenMode.ForRead) as Pipe;
// Проходим по всем видам профилей, которые отображают трубу
foreach (ObjectId pViewId in pipe.GetProfileViewsDisplayingMe())
{
// Проверяем существования вила профиля
if (pViewId.IsValid && !pViewId.IsErased && !pViewId.IsEffectivelyErased)
{
// Получаем вид профиля
ProfileView pView
= tr.GetObject(pViewId, OpenMode.ForRead) as ProfileView;
// Получаем трассу вида профиля
Alignment align
= tr.GetObject(pView.AlignmentId, OpenMode.ForRead) as Alignment;
// Точка пересечения трубы и плоскости вида профиля
Point3d intersPtAnPipe;
using (Point3dCollection ptsCol = new Point3dCollection())
{
pipe.IntersectWith
(align,
Intersect.OnBothOperands,
ptsCol, new IntPtr(0), new IntPtr(0));
// Если пересечений нет - переходим к следующему виду профиля
if (ptsCol.Count != 1) continue;
// Точка пересечения, найденная в методе IntersectWith
intersPtAnPipe = ptsCol[0];
}
// Найденная точка находится не на трубе,
// поэтому, требуется ее уточнить
#region Один из вариантов уточнения координаты Z для точки
// 2D точка пересечения
Point2d intersPt2D = new Point2d(intersPtAnPipe.X, intersPtAnPipe.Y);
// Начальная и конечная точки трубы
Point3d
startPt = pipe.StartPoint,
endPt = pipe.EndPoint;
// Если 2D точка пересечения трубы и трассы находится в начале трубы
if (intersPt2D.IsEqualTo(new Point2d(startPt.X, startPt.Y), Tolerance.Global))
// точка пересечения - начальная точка трубы
intersPtAnPipe = startPt;
// Если 2D точка пересечения трубы и трассы находится в конце трубы
if (intersPt2D.IsEqualTo(new Point2d(endPt.X, endPt.Y), Tolerance.Global))
// точка пересечения - конечная точка трубы
intersPtAnPipe = endPt;
else
{
// Математически определяем координату Z для точки
double
angleFactor = 0.0,
intersPtZ = 0.0;
if (!intersPt2D.X.Equals(startPt.X))
angleFactor = (endPt.X - startPt.X) / (intersPt2D.X - startPt.X);
else if (!intersPt2D.Y.Equals(startPt.Y))
angleFactor = (endPt.Y - startPt.Y) / (intersPt2D.Y - startPt.Y);
intersPtZ = ((endPt.Z - startPt.Z) / angleFactor) + startPt.Z;
intersPtAnPipe = new Point3d(intersPt2D.X, intersPt2D.Y, intersPtZ);
}
#endregion
// Ищем переопределение стиля трубы на виде профиля
ProfileOverride pipeStyleOverride =
pView.GraphOverrides.SingleOrDefault(item =>
item.ProfileId.IsValid
&& item.UseOverrideStyle
&& item.ProfileId.Equals(pipe.ProfileViewPartId));
ObjectId pipeStyleId;
// Если стиль переопределен
if (pipeStyleOverride != null)
{
// Получаем Id стиля переопределения
pipeStyleId = pipeStyleOverride.OverrideStyleId;
}
else
{
// Иначе - берем Id стиля трубы на плане
pipeStyleId = pipe.StyleId;
}
// Получаем стиль трубы
PipeStyle pipeStyle
= tr.GetObject(pipeStyleId, OpenMode.ForRead) as PipeStyle;
// Получаем настройки отображения элементов сечения
// пересекающей трубы на виде профиля из стиля трубы
// Штриховка перескающей трубы
DisplayStyle dispStyleCPH = pipeStyle.GetDisplayStyleProfile
(PipeDisplayStyleProfileType.CrossingPipeHatch);
// Внутренняя стенка пересекающей трубы
DisplayStyle dispStyleCPIW
= pipeStyle.GetDisplayStyleProfile
(PipeDisplayStyleProfileType.CrossingPipeInsideWall);
// Внешняя стенка пересекающей трубы
DisplayStyle dispStyleCPOW = pipeStyle.GetDisplayStyleProfile
(PipeDisplayStyleProfileType.CrossingPipeOutsideWall);
// Проверяем, показывается ли хоть один элемент сечения
bool showCrossing
= dispStyleCPH.Visible
|| dispStyleCPIW.Visible
|| dispStyleCPOW.Visible;
// Если пересекающая труба никак не отображается - переходим
// к следующему виду профиля
if (!showCrossing) continue;
// Находим пикетаж точки пересечения трубы и вида профиля
double station = 0.0, offset = 0.0;
align.StationOffset
(intersPtAnPipe.X, intersPtAnPipe.Y, ref station, ref offset);
// Получаем координаты точки пересечения на виде профиля
double x = 0.0, y = 0.0;
pView.FindXYAtStationAndElevation
(station, intersPtAnPipe.Z, ref x, ref y);
// Получаем стиль вида профиля
ProfileViewStyle pViewStyle
= tr.GetObject(pView.StyleId, OpenMode.ForRead) as ProfileViewStyle;
// Получаем вертикальный коэффициент масштабирования
GraphStyle graphStyle = pViewStyle.GraphStyle;
double verticalScaleFactor
= graphStyle.CurrentHorizontalScale / graphStyle.VerticalScale;
// Наружный радиус трубы по высоте в масштабе вида профиля
double outerRadInScale
= pipe.OuterDiameterOrWidth * verticalScaleFactor / 2.0;
// Рисуем крестик на пересекающей трубе
// pt1 pt3
// \ /
// / \
// pt4 pt2
Point3d
pt1 = new Point3d
(x - outerRadInScale, y + outerRadInScale, pView.Location.Z),
pt2 = new Point3d
(x + outerRadInScale, y - outerRadInScale, pView.Location.Z),
pt3 = new Point3d
(x + outerRadInScale, y + outerRadInScale, pView.Location.Z),
pt4 = new Point3d
(x - outerRadInScale, y - outerRadInScale, pView.Location.Z);
wd.Geometry.WorldLine(pt1, pt2);
wd.Geometry.WorldLine(pt3, pt4);
}
}
tr.Commit();
}
}
// если вам нужно обрабатывать колодцы
//else if (viewPart.ModelPartId.ObjectClass ==
// RXClass.GetClass(typeof(Structure)))
//{
//}
return ret;
}
}
public class MyCommads
{
[CommandMethod("MyProfilePartOverrule")]
public static void CmdProfilePartOverrule()
{
if (_overrule == null)
{
_overrule = new MyPipePartOverrule();
Overrule.AddOverrule(
RXClass.GetClass(typeof(ProfileViewPart)),
_overrule, false);
}
else
{
Overrule.RemoveOverrule(
RXClass.GetClass(typeof(ProfileViewPart)),
_overrule);
_overrule = null;
}
Application.DocumentManager.
MdiActiveDocument.Editor.Regen();
}
private static MyPipePartOverrule _overrule = null;
}