C#实现Mesh布尔运算


Mstn SDKC/C++接口中有mdlMesh_booleanXXX系列函数以及mdlPop_elementDescrFromElementDescrXXX系列函数可以得到Mesh元素之间的布尔运算结果,目前在Mstn C#的编程框架中未对此类函数进行封装,所以在使用C#语言开发Mstn插件时,如果想要对Mesh元素做布尔运算的话会比较麻烦。一种选择是通过将Mesh元素转换为Parasolid数据结构,通过调用Bentley.DgnPlatformNET.SolidUtil以及其子类Bentley.DgnPlatformNET.Modify等(这些类是对C/C++接口中的SolidUtilModify等的封装,不同的是在C/C++Modify等类是作为SolidUtil的类中类定义的,而非派生继承关系)对ParaSolid数据结构进行操作,最后将得到的结果再转换为Mesh(转换Mesh参考:元素图形处理器—IElementGraphicsProcessor)。由于Parasolid技术对于Solid有严格的要求(具体参考这篇wiki:三维实体建模的限制),所以被操做的Mesh也要满足这些要求。另外一种选择就是封装C/C++接口在C#中调用,好在mdlPop_elementDescrFromElementDescrXXX系列函数原型并不是很复杂,所以我们可以直接通过PInvoke调用这些函数。例如对于mdlPop_elementDescrFromElementDescrBoolOp函数,其在C/C++ SDK的头文件中的定义如下所示:

MSCORE_EXPORT MSElementDescrP    mdlPop_elementDescrFromElementDescrBoolOp
(
MSElementDescrCP    pDescr0,
MSElementDescrCP    pDescr1,
MSElementCP         pTemplate,
int                 boolType,
bool                removeCoplanarEdges,
bool                removeColinearVertices,
bool                setCookieCutter,
bool                imprintOnly,
bool                separateShells
);

我们可以在C#中通过如下的方式声明一个对应的函数:

[System.Runtime.InteropServices.DllImport("ustation.dll", EntryPoint = "mdlPop_elementDescrFromElementDescrBoolOp")]
        public static extern long mdlPop_elementDescrFromElementDescrBoolOp(long pDescr0, long pDescr1, long pTemplate,int boolType,
  bool removeCoplanarEdges,bool removeColinearVertices, bool setCookieCutter,  bool imprintOnly,bool separateShells);

如下代码演示了如何调用此函数:

public static void MeshUnion()
        {
            long eleid = 233536;
            Bentley.Interop.MicroStationDGN.Element mesh1 = Bentley.MstnPlatformNET.InteropServices.Utilities.ComApp.ActiveModelReference.GetElementByID(ref eleid);
            long elmdscrp1 = mesh1.MdlElementDescrP(false);
            eleid = 233535;
            Bentley.Interop.MicroStationDGN.Element mesh2 = Bentley.MstnPlatformNET.InteropServices.Utilities.ComApp.ActiveModelReference.GetElementByID(ref eleid);
            long elmdscrp2 = mesh2.MdlElementDescrP(false);
            if (0 != elmdscrp1 && 0 != elmdscrp2)
            {
                long elmdscrp = ImportNativeCode.mdlPop_elementDescrFromElementDescrBoolOp(mesh1.MdlElementDescrP(false),
                    mesh2.MdlElementDescrP(false), 0, 0, true, true, false, false, false);
                if (0 != elmdscrp)
                {
                    Bentley.Interop.MicroStationDGN.Element mesh3 = Bentley.MstnPlatformNET.InteropServices.Utilities.ComApp.MdlCreateElementFromElementDescrP(elmdscrp);
                    Bentley.MstnPlatformNET.InteropServices.Utilities.ComApp.ActiveModelReference.AddElement(mesh3);
                }
            }
        }