using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using Bentley.DgnPlatformNET; using Bentley.DgnPlatformNET.Elements; using Bentley.GeometryNET; using Bentley.MstnPlatformNET; using Mstn.Toolkit.Extensions; namespace Mstn.Toolkit.External { internal class SelectionExtensions { /// /// 围栅(临时组合) /// /// 只在当前操作期内有效,关闭DGN后再打开将不复存在,命名围栅则可以保存下来 /// public static void CreateFenceByElement(string unparsed)//Case:FenceClipByElement { DgnModelRef dgnModelRef = Session.Instance.GetActiveDgnModelRef();//获得当前的模型空间/参照空间 注:DgnModelRef是一个基类,DgnModel和DgnAttachment都派生于这个基类 DgnModel dgnModel = Session.Instance.GetActiveDgnModel();//获得当前激活的模型控件 Viewport view = Session.GetActiveViewport();//获得当前视图信息 double uorPerMas = Session.Instance.GetActiveDgnModel().GetModelInfo().UorPerMaster;//分辨率单位转换为主单位 #region Create complex shape element DPoint3d p1 = new(-10 * uorPerMas, 0, 0);//声明线串元素端点 DPoint3d p2 = new(-10 * uorPerMas, 260 * uorPerMas, 0); DPoint3d p3 = new(110 * uorPerMas, 260 * uorPerMas, 0); DPoint3d p4 = new(110 * uorPerMas, 110 * uorPerMas, 0); DPoint3d[] pos = { p1, p2, p3, p4 };//声明端点集 LineStringElement lineString = new(dgnModel, null, pos);//声明线串元素 DPoint3d centerPo = new(0, 100 * uorPerMas, 0);//声明弧元素的圆心 ArcElement arc = new( dgnModel, null, centerPo, 110 * uorPerMas, 110 * uorPerMas, DMatrix3d.Identity, 0, -Angle.PI.Radians / 2);//声明弧元素 ComplexShapeElement complexShape = new(dgnModel, null);//声明复杂形元素 complexShape.AddComponentElement(lineString);//将子构件添加到复杂元素中 complexShape.AddComponentElement(arc); complexShape.AddComponentComplete();//子构件添加完成 #endregion if (StatusInt.Success == FenceManager.DefineByElement(complexShape, view))//使用元素围成的区域声明围栅 { FenceParameters fenceParams = new(dgnModelRef, DTransform3d.Identity);//声明围栅信息 FenceManager.InitFromActiveFence(fenceParams, false, false, FenceClipMode.None); /* * 使用围栅信息初始化围栅 * fenceParameters:围栅信息 * overlap:若需囊括部分包含的元素则输入true * doClip:若需修剪操作则输入true * allowClipFlag:若需要在原始元素上剪切则输入FenceClipMode.Original,若需要在新声明的元素上剪切则输入FenceClipMode.Copy */ ElementAgenda eAgenda = new();//声明元素容器 DgnModelRef[] modelRefList = new DgnModelRef[1];//设置需要声明围栅的模型空间 modelRefList[0] = dgnModelRef;//设置模型空间 FenceManager.BuildAgenda(fenceParams, eAgenda, modelRefList, false, false, false); /* * 使用围栅信息获得符合要求的元素集 * fenceParameters:围栅信息 * elementAgenda:符合要求的元素集 * modelRefList:声明围栅的模型空间 * modifyOrig:是否修改原始元素 * allowLocked:是否允许锁定元素 * callAsynch:是否需要调用异步 */ string result = "Result:\n";//声明字符串 for (uint i = 0; i < eAgenda.GetCount(); i++)//遍历元素容器中的元素 { Element element = eAgenda.GetEntry(i);//获得元素容器中的元素 result = result + "ElementId = " + element.ElementId + '\n';//将元素ID写入模型 } result = result + "Total count: " + eAgenda.GetCount();//输出元素个数 MessageBox.Show(result);//将字符串输出到对话框中 } } public static void ClipElementByFence(string unparsed)//Case:FenceClipByPoints { DgnModelRef dgnModelRef = Session.Instance.GetActiveDgnModelRef();//获得当前的模型空间/参照空间 注:DgnModelRef是一个基类,DgnModel和DgnAttachment都派生于这个基类 DgnModel dgnModel = Session.Instance.GetActiveDgnModel();//获得当前激活的模型控件 Viewport view = Session.GetActiveViewport();//获得当前视图信息 double uorPerMas = Session.Instance.GetActiveDgnModel().GetModelInfo().UorPerMaster;//分辨率单位转换为主单位 DPoint3d p1 = new(-10 * uorPerMas, 0, -130 * uorPerMas);//声明围栅坐标点 DPoint3d p2 = new(-10 * uorPerMas, 0, 200 * uorPerMas); DPoint3d p3 = new(50 * uorPerMas, 0, 200 * uorPerMas); DPoint3d p4 = new(50 * uorPerMas, 0, -130 * uorPerMas); DPoint3d[] pos = { p1, p2, p3, p4 };//使用端点声明端点集 ShapeElement shape = new(dgnModel, null, pos);//声明形元素 if (StatusInt.Success == FenceManager.DefineByElement(shape, view))//使用图形建立围栅 { FenceParameters fenceParams = new(dgnModelRef, DTransform3d.Identity);//声明围栅信息 FenceManager.InitFromActiveFence(fenceParams, true, true, FenceClipMode.Copy);//使用围栅信息初始化围栅 ElementAgenda eAgenda = new();//声明元素容器 DgnModelRef[] modelRefList = new DgnModelRef[1];//设置需要声明围栅的模型空间 modelRefList[0] = dgnModelRef;//设置模型空间 FenceManager.BuildAgenda(fenceParams, eAgenda, modelRefList, false, false, false);//使用围栅信息获得符合要求的元素集 for (uint i = 0; i < eAgenda.GetCount(); i++)//遍历元素容器中的元素 { ElementAgenda insideElems = new();//声明元素容器 ElementAgenda outsideElems = new();//声明元素容器 Element element = eAgenda.GetEntry(i);//获得元素容器中的元素 FenceManager.ClipElement(fenceParams, insideElems, outsideElems, element, FenceClipFlags.Optimized);//对围栅内的元素进行剪切 for (uint j = 0; j < outsideElems.GetCount(); j++)//遍历围栅切割后生成的外围元素 { using (ElementCopyContext copyContext = new(dgnModelRef))//复制元素 { Element elemToCopy = outsideElems.GetEntry(j);//获得切割后生成的外围元素 copyContext.DoCopy(elemToCopy);//将元素复制到指定模型中 } } } } } //参考文章:https://communities.bentley.com/communities/other_communities/bdn_other_communities/b/bdn-blog/posts/mesh public static void BreakElementIntoPolyface(string unparsed)//Case:BreakSolidExample { DgnModel dgnModel = Session.Instance.GetActiveDgnModel();//获取当前的模型空间 double uorPerMas = Session.Instance.GetActiveDgnModel().GetModelInfo().UorPerMaster;//分辨率单位转换为主单位 #region Create Solid #region Create profile DPoint3d p1 = new(-uorPerMas, uorPerMas, 0);//声明体元素端点 DPoint3d p2 = new(uorPerMas, uorPerMas, 0); DPoint3d p3 = new(uorPerMas, -uorPerMas, 0); DPoint3d p4 = new(-uorPerMas, -uorPerMas, 0); DPoint3d[] pos = { p1, p2, p3, p4 };//将面元素端点添加到面元素端点数组中 ShapeElement shape = new(dgnModel, null, pos);//声明形元素 #endregion DPoint3d origin = DPoint3d.Zero;//声明拉伸基点 DVector3d extrudeVector = new(uorPerMas, uorPerMas, 10 * uorPerMas);//声明拉伸向量 SurfaceOrSolidElement solid = SurfaceOrSolidElement.CreateProjectionElement( dgnModel, null, shape, origin, extrudeVector, DTransform3d.Identity, true);//声明实体元素 solid.AddToModel();//将拉伸体写入模型 #endregion IList polyfaces = [];//声明多面体几何列表 FacetOptions facetOptions = new();//曲面属性,用于设置生成曲面或曲线弦的属性声明 facetOptions.SetDefaults();//属性设置为默认 PolyfaceProcessor polyfaceProcessor = new(ref polyfaces, facetOptions);//声明用于分解多面体几何的处理器 polyfaceProcessor.Process(solid); //将需要分解的元素输入处理器中 for (int i = 0; i < polyfaces.Count; i++)//遍历元素中分解后的多面体几何 { List colorIndex = [];//声明颜色索引 foreach (DPoint3d po in polyfaces[i].Point)//为了获得该多面体几何的端点个数,对端点进行遍历 { if (po.Z < 5 * uorPerMas)//Z坐标小于5为红色,否则则为蓝色 { colorIndex.Add(0x00ff0000);//红色 } else { colorIndex.Add(0x000000ff);//蓝色 } //关于16进制颜色对照请参考:http://each.sinaapp.com/tools/color.html 格式为:0x00+(去掉#)16进制颜色 } polyfaces[i].IntColor = colorIndex;//设置多面体几何的颜色索引值 polyfaces[i].ActivateVectorsForIndexing(polyfaces[i]);//设置为激活状态,以便携带所有的数据及索引信息 MeshHeaderElement meshElem = new(dgnModel, null, polyfaces[i]);//使用修改后的多面体几何建立网格元素 TransformInfo trans = new(DTransform3d.FromTranslation(new DPoint3d(5 * uorPerMas, 0, 0)));//声明变换信息 meshElem.ApplyTransform(trans);//对网格元素应用变换 meshElem.AddToModel();//将网格元素写入模型 } } public static void BreakElementIntoCurves(string unparsed)//Case:BreakSolidExample { DgnModel dgnModel = Session.Instance.GetActiveDgnModel();//获取当前的模型空间 double uorPerMas = Session.Instance.GetActiveDgnModel().GetModelInfo().UorPerMaster;//分辨率单位转换为主单位 #region Create Solid #region Create profile DPoint3d p1 = new(-uorPerMas, uorPerMas, 0);//声明体元素端点 DPoint3d p2 = new(uorPerMas, uorPerMas, 0); DPoint3d p3 = new(uorPerMas, -uorPerMas, 0); DPoint3d p4 = new(-uorPerMas, -uorPerMas, 0); DPoint3d[] pos = { p1, p2, p3, p4 };//将面元素端点添加到面元素端点数组中 ShapeElement shape = new(dgnModel, null, pos);//声明形元素 #endregion DPoint3d origin = DPoint3d.Zero;//声明拉伸基点 DVector3d extrudeVector = new(uorPerMas, uorPerMas, 10 * uorPerMas);//声明拉伸向量 SurfaceOrSolidElement solid = SurfaceOrSolidElement.CreateProjectionElement( dgnModel, null, shape, origin, extrudeVector, DTransform3d.Identity, true);//声明实体元素 solid.AddToModel();//将拉伸体写入模型 #endregion IList curves = [];//声明多面体几何列表 CurveProcessor curveProcessor = new(ref curves);//声明用于分解曲线几何的处理器 curveProcessor.Process(solid); //将需要分解的元素输入处理器中 List curvesList = [];//声明几何图元列表 for (int i = 0; i < curves.Count; i++)//遍历元素中分解后的曲线几何 { Element subElem = DraftingElementSchema.ToElement(dgnModel, curves[i], null);//将几何转换成对应的元素 subElem.AddToModel();//将元素写入模型 if (subElem.ElementType == MSElementType.LineString)//判断转换后的元素是否为线串 { ComplexShapeElement complexShape = new(dgnModel, null);//声明复杂形元素(因为对于线串元素不一定为闭合,有可能无法围城封闭图形,故使用建立shape的形式闭合几何图形) complexShape.AddComponentElement(subElem);//将线串元素添加到shape元素中 complexShape.AddComponentComplete();//添加元素完成 CurveVector shapeCurve = complexShape.GetCurveVector();//获得shape的封闭图形 CurveVector curveWithFillets = shapeCurve.CloneWithFillets(0.1 * uorPerMas);//对获得的几何图元做倒角处理 curvesList.Add(curveWithFillets);//将几何图元添加到列表中 } } BentleyStatus result = Create.BodyFromLoft( out SolidKernelEntity entityOut, curvesList.ToArray(), curvesList.Count, curvesList.ToArray(), 0, dgnModel, false, false);//声明扫掠体 Convert1.BodyToElement(out Element solidElem, entityOut, null, dgnModel);//将实体转换为元素 solidElem.AddToModel();//将元素写入模型空间 } #region PracticeWork public static void CmdPracticeWork(string unparsed) { DgnFile dgnFile = Session.Instance.GetActiveDgnFile();//获得当前激活的文件 DgnModel dgnModel = Session.Instance.GetActiveDgnModel();//获取当前的模型空间 double uorPerMeter = Session.Instance.GetActiveDgnModel().GetModelInfo().UorPerMeter;//分辨率单位转换为米 #region Create beam #region Create profile double H = 700 * uorPerMeter / 1000; double H1 = 125 * uorPerMeter / 1000, H2 = 125 * uorPerMeter / 1000; double H3 = 275 * uorPerMeter / 1000; double H4 = 75 * uorPerMeter / 1000, B4 = 75 * uorPerMeter / 1000; double H5 = 100 * uorPerMeter / 1000; double B3 = 125 * uorPerMeter / 1000; double B1 = 400 * uorPerMeter / 1000; double B2 = 300 * uorPerMeter / 1000; double B = 150 * uorPerMeter / 1000; DPoint3d p1 = new(-1 * 0.5 * B1, 0, 0);//声明体元素端点 DPoint3d p2 = new(-1 * 0.5 * B1, 0, H2); DPoint3d p3 = new(-0.5 * B, 0, H2 + H5); DPoint3d p4 = new(-0.5 * B, 0, H2 + H5 + H3); DPoint3d p5 = new(-0.5 * B2, 0, H2 + H5 + H3 + H4); DPoint3d p6 = new(-0.5 * B2, 0, H); DPoint3d p7 = new(0.5 * B2, 0, H); DPoint3d p8 = new(0.5 * B2, 0, H2 + H5 + H3 + H4); DPoint3d p9 = new(0.5 * B, 0, H2 + H5 + H3); DPoint3d p10 = new(0.5 * B, 0, H2 + H5); DPoint3d p11 = new(0.5 * B1, 0, H2); DPoint3d p12 = new(0.5 * B1, 0, 0); DPoint3d[] pos = { p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12 };//将面元素端点添加到面元素端点数组中 ShapeElement shape = new(dgnModel, null, pos);//声明形元素 #endregion DPoint3d origin = DPoint3d.Zero;//声明拉伸基点 DVector3d extrudeVector = new(0, 12 * uorPerMeter, 0);//声明拉伸向量 SurfaceOrSolidElement beamSolid = SurfaceOrSolidElement.CreateProjectionElement( dgnModel, null, shape, origin, extrudeVector, DTransform3d.Identity, true);//使用投影的方式声明拉伸体元素 #endregion #region Create dimension DPoint3d d1 = new(-0.5 * B1, 0, -50 * uorPerMeter / 1000);//声明标注点 DPoint3d d2 = new(0.5 * B1, 0, -50 * uorPerMeter / 1000);//声明标注点 DPoint3d[] dimensionPos1 = { d1, d2 };//声明标注点数组 DMatrix3d dMatrix1 = new(-1, 0, 0, 0, 0, 1, 0, -1, 0);//声明变换矩阵 DimensionElement dimEle1 = CreateDimensionElement(dgnFile, dgnModel, dimensionPos1, string.Empty, dMatrix1);//声明标注元素 dimEle1.AddToModel();//将标注元素写入模型 DPoint3d d3 = new(-0.5 * B1, 0, -10 * uorPerMeter / 1000); DPoint3d d4 = new(-0.5 * B, 0, -10 * uorPerMeter / 1000); DPoint3d d5 = new(0.5 * B, 0, -10 * uorPerMeter / 1000); DPoint3d d6 = new(0.5 * B1, 0, -10 * uorPerMeter / 1000); DPoint3d[] dimensionPos2 = { d3, d4, d5, d6 }; DimensionElement dimEle2 = CreateDimensionElement(dgnFile, dgnModel, dimensionPos2, string.Empty, dMatrix1); dimEle2.AddToModel();//将标注元素写入模型 DMatrix3d dMatrix2 = DMatrix3d.FromRows(new DVector3d(0, 1, 0), new DVector3d(-1, 0, 0), new DVector3d(0, 0, 1)); DMatrix3d dMatrix = DMatrix3d.Multiply(dMatrix1, dMatrix2); DPoint3d d7 = new(-0.5 * B1 - 50 * uorPerMeter / 1000, 0, 0); DPoint3d d8 = new(-0.5 * B1 - 50 * uorPerMeter / 1000, 0, H); DPoint3d[] dimensionPos3 = { d7, d8 }; DimensionElement dimEle3 = CreateDimensionElement(dgnFile, dgnModel, dimensionPos3, string.Empty, dMatrix); dimEle3.AddToModel();//将标注元素写入模型 DPoint3d d9 = new(-0.5 * B1 - 10 * uorPerMeter / 1000, 0, 0); DPoint3d d10 = new(-0.5 * B1 - 10 * uorPerMeter / 1000, 0, H2); DPoint3d d11 = new(-0.5 * B1 - 10 * uorPerMeter / 1000, 0, H2 + H5); DPoint3d d12 = new(-0.5 * B1 - 10 * uorPerMeter / 1000, 0, H2 + H5 + H3); DPoint3d d13 = new(-0.5 * B1 - 10 * uorPerMeter / 1000, 0, H2 + H5 + H3 + H4); DPoint3d d14 = new(-0.5 * B1 - 10 * uorPerMeter / 1000, 0, H); DPoint3d[] dimensionPos4 = { d9, d10, d11, d12, d13, d14 }; DimensionElement dimEle4 = CreateDimensionElement(dgnFile, dgnModel, dimensionPos4, string.Empty, dMatrix); dimEle4.AddToModel();//将标注元素写入模型 #endregion #region Create column EllipseElement ellipse = new( dgnModel, null, DPoint3d.Zero, 350 * uorPerMeter / 1000, 350 * uorPerMeter / 1000, DMatrix3d.Identity); DVector3d columnVector = new(0, 0, 3 * uorPerMeter);//声明拉伸向量 SurfaceOrSolidElement columnSolid = SurfaceOrSolidElement.CreateProjectionElement( dgnModel, null, ellipse, DPoint3d.Zero, columnVector, DTransform3d.Identity, true);//使用投影的方式声明拉伸体元素 DTransform3d dTransform3D = DTransform3d.FromTranslation(new DPoint3d(0, 12 * uorPerMeter, -1 * uorPerMeter));//声明变换几何,执行元素平移操作 TransformInfo trans = new(dTransform3D);//声明变换信息 columnSolid.ApplyTransform(trans);//对拉伸圆柱体施加变换信息 #endregion #region BooleanSubtract Convert1.ElementToBody(out SolidKernelEntity entity1, beamSolid, true, false, false);//将实体转成SolidKernelEntity Convert1.ElementToBody(out SolidKernelEntity entity2, columnSolid, true, false, false);//将圆台实体元素转成SolidKernelEntity SolidKernelEntity[] entities = { entity2 };//声明实核实体集 Modify.BooleanSubtract(ref entity1, ref entities, entities.Count());//用实核实体集中的实体与实体进行布尔减运算 Convert1.BodyToElement(out Element resultElem, entity1, null, dgnModel);//将结果转换为元素 #endregion #region Attach material MaterialId id = FindMaterial(dgnFile, dgnModel); AttachMaterialToElement(id, resultElem); AttachMaterialToElement(id, columnSolid); #endregion } private static void AttachMaterialToElement(MaterialId id, Element elem) { if (id != null) { MaterialPropertiesExtension propertiesExtension = MaterialPropertiesExtension.GetAsMaterialPropertiesExtension( (DisplayableElement)elem);//为拉伸实体元素设置材料属性 propertiesExtension.AddMaterialAttachment(id);//添加嵌入的材料信息 propertiesExtension.StoresAttachmentInfo(id);//保存拉伸实体元素的材料信息 propertiesExtension.AddToModel();//将拉伸实体写入模型 } } private static MaterialId FindMaterial(DgnFile dgnFile, DgnModel dgnModel) { MaterialTable matTbl = new(dgnFile) { Name = "MyMaterialTable"//声明材料表名称 };//声明材料表 PaletteInfo[] palInfo = MaterialManager.GetPalettesInSearchPath("MS_MATERIAL");//从MS_MATERIAL的环境变量声明路径下读取材料图表 if (palInfo.Length < 1)//判断是否获取到材料图表 { MessageCenter.Instance.ShowInfoMessage("Can't get palette", null, true);//输出错误信息 return null;//返回 } for (int i = 0; i < palInfo.Count(); i++)//遍历材料图表 { if (palInfo[i].Name == "Concrete&Pavers")//判断材料图表是否名为Concrete&Pavers { matTbl.AddPalette(palInfo[i]);//添加材料图表至材料表 break;//跳出循环 } else if (i == palInfo.Count() - 1)//若未找到名为lightwidgets的材料图表 { MessageCenter.Instance .ShowErrorMessage( "Can't find material lib named lightwidgets, please check", "Can't find material lib named lightwidgets, please check", true);//输出错误信息 } } MaterialManager.SetActiveTable(matTbl, dgnModel);//设置当前材料表为激活图表 MaterialManager.SaveTable(matTbl);//保存材料表 MaterialId id = new("Concrete_1");//查找名为Concrete_1的材料 return id; } #endregion /* * 参考论坛帖子: * https://communities.bentley.com/communities/other_communities/chinafirst/f/microstation-projectwise/158653/ms-ce-c * https://communities.bentley.com/communities/other_communities/chinafirst/f/microstation-projectwise/200717/thread/601140#601140 * https://communities.bentley.com/communities/other_communities/chinafirst/f/microstation-projectwise/221336/abd-ce-c/678991#678991 */ private static DimensionElement CreateDimensionElement( DgnFile dgnFile, DgnModel dgnModel, DPoint3d[] pos, string text, DMatrix3d dMatrix) { //获取当前dgn文件中名字为"DimStyle"的标注样式,尺寸标注元素的外貌由上百个属性控制,而标注样式是一组预先设置好的属性 //获取了预先订制好的标注样式之后,还可以调用DimensionStyle下的各种SetXXX成员函数修改设置的属性 DimensionStyle dimStyle = new("DimStyle", dgnFile);//声明标注样式 dimStyle.SetBooleanProp(true, DimStyleProp.Placement_UseStyleAnnotationScale_BOOLINT);//设置标注样式 dimStyle.SetDoubleProp(1, DimStyleProp.Placement_AnnotationScale_DOUBLE); dimStyle.SetBooleanProp(true, DimStyleProp.Text_OverrideHeight_BOOLINT); dimStyle.SetDistanceProp(200, DimStyleProp.Text_Height_DISTANCE, dgnModel); dimStyle.SetBooleanProp(true, DimStyleProp.Text_OverrideWidth_BOOLINT); dimStyle.SetDistanceProp(200, DimStyleProp.Text_Width_DISTANCE, dgnModel); dimStyle.SetBooleanProp(true, DimStyleProp.General_UseMinLeader_BOOLINT); dimStyle.SetDoubleProp(0.01, DimStyleProp.Terminator_MinLeader_DOUBLE); dimStyle.SetBooleanProp(true, DimStyleProp.Value_AngleMeasure_BOOLINT); dimStyle.SetAccuracyProp((byte)AnglePrecision.Use1Place, DimStyleProp.Value_AnglePrecision_INTEGER); int alignInt = (int)DimStyleProp_General_Alignment.True; StatusInt status = dimStyle.SetIntegerProp(alignInt, DimStyleProp.General_Alignment_INTEGER); dimStyle.GetIntegerProp(out int valueOut, DimStyleProp.General_Alignment_INTEGER); DgnTextStyle textStyle = new("TestStyle", dgnFile);//设置文字样式 LevelId lvlId = Settings.GetLevelIdFromName("Default");//设置图层 DimensionData callbacks = new(dimStyle, textStyle, new Symbology(), lvlId, null);//尺寸标注元素的构造函数会调用DimensionCreateData的各个成员函数去获取声明尺寸标注元素需要的各种参数 DimensionElement dimEle = new(dgnModel, callbacks, DimensionType.SizeStroke);//声明标注元素 if (dimEle.IsValid)//判断标注元素是否有效 { for (int i = 0; i < pos.Count(); i++) { dimEle.InsertPoint(pos[i], null, dimStyle, -1);//对标注元素设置插入点 } dimEle.SetHeight(500);//设置尺寸标注元素的高度 dimEle.SetRotationMatrix(dMatrix);//设置变换信息 } return dimEle; } } }