上一章和大家一起学习了Linear Geometry SDK的使用。本章我们将讲解Geometry Model SDK的使用。在上面所有章节我们获取路线Alignment对象的时候,都是通过DgnElementSetTool工具选取的。现在大家估计会有疑问,是不是获取Alignment对象都要进行交互式的选取操作才能获取,Alignment中除了能获取其Linear Geometry几何信息,我们还能获取哪些模型信息。那么这一章我们就用一个带有纵断面信息的Alignment为例,去探索一下Geometry Model SDK的世界。
一、构建程序框架
二、创建一条包含纵断面的Alignment
绘制结果如下图所示:
三、使用另外一种方式获取Alignment
⑴.ConsensusConnection类的使用
此类代表SDK与DgnModel的一个连接。SDK中任何对DgnModel的数据查询和提取,都需要直接或间接的透过此连接进行操作。所以,构造此对象始终是顺序遍历和解析DgnModel中数据的第一步。通过建立此对象,可以获取DgnModel中当前激活的GeometricModel对象。
我们先建立与当前DgnModel的连接,代码如下:
ConsensusConnection sdkCon = ConsensusConnection.Create(Bentley.MstnPlatformNET.Session.Instance.GetActiveDgnModelRef());
根据连接我们可获取DgnModel中当前激活的GeometricModel对象,代码如下:
GeometricModel gm = sdkCon.GetActive();
⑵. 获取Alignment:
从上一步可以看到,我们获取一个当前激活的GeometricModel对象。对象GeometricModel是一个包含ORD几何元素模型的集合。它包含的内容如下图所示:
对于GeometricModel这个类我们可以看到它有一个Alignments属性,它代表的是当前GeometricModel中包含的所有的Alignment集合。
在本章示例中我们创建的Dgn模型中,我们可以通过代码遍历属性Alignments,获取这个集合中的Alignment的个数为6。
为什么模型中只有一条复杂平面线形,而Alignment对象会有多个,是因为我们复杂线形中会包含多条直线、圆曲线等子元素,在ORD SDK中每个子元素也会成一个Alignment,所以本例遍历Alignments集合的时候就会发现多个Alignment对象。对于这一部分更进一步的讲解,我们会在后期有专门的文章去讲解。
我们获取最终的Alignment(可以理解为那个复杂线形的Alignment),可以使用Alignment的IsFinalElement属性去判断是否为一条最终(复杂线形)的Alignment,具体代码如下:
for (int i = 0; i < countAlg; i++)
{
Alignment al = Enumerable.ElementAt<Alignment>(Alignments, i);
if (al.IsFinalElement)
{
m_aligment = al;
}
}
四、创建一个动态标注Profile的光标
创建纵断面上的光标,我们需要在ORD软件中把Alignment的Profile模型打开,然后在我们在平面线模型中拖动鼠标,光标的十字最新正好落在纵断面线的对应桩号上。实现以上功能我们需要在动态拖动函数(OnDynamicFrame)中实现以下步骤。
我们可以先把当前鼠标转换成以米为单位的点,然后再使用函数ProjectPointOnPerpendicular求得这个点与平面线的投影处的垂足点pt_road,代码如下:
DPoint3d meter_pt = GetMeterPoint(ev.Point);
LinearPoint pt_road = m_aligment.LinearGeometry.ProjectPointOnPerpendicular(meter_pt);
此垂足处的桩号为:pt_road.DistanceAlong。
2. 获取当前纵断面元素。
获取当前Aligment的纵断面元素可以通过它的ActiveProfile属性获取。如果ActiveProfile这个纵断面元素是直线的话,它的类型为LineElement,如果断面元素是用复杂线形的话,它的类型为ComplexStringElement。我们要在代码里加以区分和判断。
3. 计算出当前桩号处的高程,从而绘制出光标。
我们需要从上一步中获取的纵断面线形里获取它的几何信息,从而获取纵断面线的起始位置。具体方法是,通过上面获取的纵断面线形的GetCurveVector方法获取CurveVector几何数据。然后调用CurveVector的GetStartPoint方法获取纵断面线在起始位置,也就是起始桩号处的坐标。另外起始位置坐标再加上垂足处的桩号(pt_road.DistanceAlong),就可以获取当前桩号处在纵断面线处的X坐标。
关于当前桩号处Y坐标的获取,我们可以先把当前激活的ActiveProfile转换成Geometry Model SDK中的 Profile对象,再利用Profile对象的 ProfileGeometry属性的 GetYAtX方法获取当前桩号的Y值(也就是高程值)。GetYAtX方法传入的X值为垂足处的桩号(pt_road.DistanceAlong)。
这样的话我们在平面线附近移动鼠标,在纵断面模型中对应的光标坐标值就计算出来。我们就可以按照上一章介绍的动态绘制线形元素的方法去绘制一个十字光标了。
效果如下图所示:
代码如下所示:
protected override void OnDynamicFrame(DgnButtonEvent ev)
{
if (!DynamicsStarted)
{
return;
}
DPoint3d meter_pt = GetMeterPoint(ev.Point);
LinearPoint pt_road = m_aligment.LinearGeometry.ProjectPointOnPerpendicular(meter_pt);
if (pt_road == null)
{
return;
}
if (m_aligment.ActiveProfile == null)
{
return;
}
CurveVector cvp;
LineElement lEle = m_aligment.ActiveProfile.Element as LineElement;
if (lEle == null)
{
ComplexStringElement cEle = m_aligment.ActiveProfile.Element as ComplexStringElement;
if(cEle == null)
return;
cvp = cEle.GetCurveVector();
}
else
{
cvp = lEle.GetCurveVector();
}
DPoint3d point;
cvp.GetStartPoint(out point);
Profile pp = Profile.CreateFromElement(m_aligment.ActiveProfile.Element);
double along = pt_road.DistanceAlong ;
double Y = pp.ProfileGeometry.GetYAtX(along);
DPoint3d dp_t = new DPoint3d((point.X + along) * UorPerMeter(), Y + 10000 * UorPerMeter());
DPoint3d dp_b = new DPoint3d((point.X + along) * UorPerMeter(), Y - 10000 * UorPerMeter());
DSegment3d segV = new DSegment3d(dp_t, dp_b);
DPoint3d dp_l = new DPoint3d(point.X - 10000 * UorPerMeter(), Y * UorPerMeter());
DPoint3d dp_r = new DPoint3d(point.X + 10000 * UorPerMeter(), Y * UorPerMeter());
DSegment3d segH = new DSegment3d(dp_l, dp_r);
DgnModel model = pp.DgnModel;
LineElement lineV = new LineElement(model, null, segV);
LineElement lineH = new LineElement(model, null, segH);
var redraw = new RedrawElems();
redraw.DrawMode = DgnDrawMode.TempDraw;
redraw.DrawPurpose = DrawPurpose.Dynamics;
redraw.SetDynamicsViewsFromActiveViewSet(ev.Viewport);
redraw.DoRedraw(lineV);
redraw.DoRedraw(lineH);
}
本章示例代码: