中国BDN社区-博客 - [CE C#]生成包络线(ConvexHull)
BMPCreated with Sketch.BMPZIPCreated with Sketch.ZIPXLSCreated with Sketch.XLSTXTCreated with Sketch.TXTPPTCreated with Sketch.PPTPNGCreated with Sketch.PNGPDFCreated with Sketch.PDFJPGCreated with Sketch.JPGGIFCreated with Sketch.GIFDOCCreated with Sketch.DOC Error Created with Sketch.
Blog

[CE C#]生成包络线(ConvexHull)

by
YongAn Fu
Expert
Created: (Edited: )

MicroStation CONNECT版带有基于.NET框架的一套几何库GeometryNET,里面含有很多有用的功能。虽然目前没有文档详细介绍这个几何库,但通过VS中带有的Object Browser(对象浏览器)功能完全可以查到DLL中所带的对象、方法和属性。

今天我们就给大家介绍一个很有趣的生成包络线的功能。所谓包络线就是能包含多个几何或点的最小包围多边线。如下图所示就是用我们将要介绍的程序对一些选择集中的点生成的包络线。

【注】:目前GeometryNET中所带的ConvexHull类仅能支持生成二维包络线,不支持生成三维包络体的功能。

image  image

要调用这个几何库,需要在您的C#项目中引用如下DLL文件:

  • Bentley.GeometryNET.DLL
  • Bentley.GeometryNET.Common.DLL
  • Bentley.GeometryNET.Strcuts.DLL

这三个DLL都位于默认的C:\Program Files\Bentley\MicroStation CONNECT Edition\MicroStation文件夹下。

要实现生成包络线,关键方法是Bentley.GeometryNET.ConvexHull.Calculate。给该方法传递一组二维点(DPoint2d结构),它就能返回一组包含这些点的最小包围多边线的各顶点。实现代码如下:

        public static void ConvexHullTest(string unparsed)
        {
            if (!Session.Instance.IsSelectionSetActive)
            {
                MessageCenter.Instance.ShowMessage(MessageType.Info, "No SelectionSet", "No SelectionSet", MessageAlert.Balloon);
                return;
            }
            DgnModelRef dgnModelRef = Session.Instance.GetActiveDgnModelRef();
            DgnModel dgnModel = Session.Instance.GetActiveDgnModel();
            LineElement line = new LineElement(dgnModel, null, new DSegment3d(0, 0, 0, 0));
            Element elem = line;

            List<DPoint2d> inPnts = new List<DPoint2d>();
            for (uint i = 0; i < SelectionSetManager.NumSelected(); i++)
            {
                SelectionSetManager.GetElement(i, ref elem, ref dgnModelRef);
                line = elem as LineElement;
                DPoint3d org;
                line.GetSnapOrigin(out org);
                inPnts.Add(new DPoint2d(org));
            }
            IReadOnlyList<DPoint2d> outPnts = ConvexHull.Calculate(inPnts);

            DPoint3d[] pts = new DPoint3d[outPnts.Count];
            for (int i = 0; i < outPnts.Count; i++)
            {
                pts[i].X = outPnts[i].X;
                pts[i].Y = outPnts[i].Y;
                pts[i].Z = 0;
            }
            ShapeElement shape = new ShapeElement(dgnModel, null, pts);
            shape.AddToModel();
        }

对以上代码做如下几点详细解释:

  1. 调用Bentley.MstnPlatformNET.Session.Instance.IsSelectionSetActive判断当前是否存在选择集,如果不存在,则提示出错后退出;
  2. 初始化dgnModelRef、dgnModel、elem为调用SelectionSetManager.GetElement做准备。GetElement的后两个参数都是ref参数传递,要求事先必须初始化这两个对象。又由于Bentley.DgnPlatformNET.Elements.Element没有默认的构造函数,在这里我们先创建了一个line(LineElement类),然后赋值给了elem(Element类);
  3. 对选择集中的每个元素做循环,取得每个元素后强行转换为线元素(这种做法仅适用于我们随后附带的DGN,其他更复杂的几何情况自己需要修改以上代码),调用GetSnapOrigin获得线元素的起点坐标,将这个坐标添加到一个二维点列表inPnts中;
  4. 调用ConvexHull.Calculate(inPnts)获得结果二维点列表outPnts;
  5. 调用ShapeElement将这些点构造成一个多边线并添加到模型中。

测试用DGN如下:

communities.bentley.com/.../ConvexHull.dgn

【注】:写本博客时使用的MicroStation CE版本为Update2(10.02.00.39),该版本中的ConvexHull.Calculate方法还不支持含有重复点的包络线生成,当具有重复点时,生成的包络线可能会出错。