using System; using System.Collections.Generic; using System.Linq; using Bentley.DgnPlatformNET; using Bentley.DgnPlatformNET.Elements; using Bentley.GeometryNET; using Bentley.MstnPlatformNET; namespace Mstn.Toolkit.Helpers { public class ElementSet : IElementSet { private readonly List _elements; private int _currentIndex; // 接受 IEnumerable,这是一个协变接口 public ElementSet(IEnumerable elements) { // 如果传入的 elements 不为 null,则转换为 List;否则创建一个空 List _elements = elements?.ToList() ?? new List(); _currentIndex = -1; } public uint GetCount() { return (uint)_elements.Count; } public Element GetFirst() { if (_elements.Count == 0) { return null; } _currentIndex = 0; return _elements[_currentIndex]; } public Element GetNext() { if (_currentIndex >= 0 && _currentIndex < _elements.Count - 1) { _currentIndex++; return _elements[_currentIndex]; } return null; } } public class SelectionSetHelper { /// /// 查询选择集中的元素 /// /// public static List QueryElements() { ElementAgenda agenda = new();//声明元素容器 SelectionSetManager.BuildAgenda(ref agenda);//从当前选择集中获得元素 List elems = []; for (uint i = 0; i < agenda.GetCount(); i++)//遍历选择集中的所有元素 { elems.Add(agenda.GetEntry(i)); } return elems; } public static void SetElements(List elements) { SelectionSetManager.EmptyAll();//清空选择集(主要为了防止因前期选择部分元素造成的选择集项目混乱) ElementSet set = new ElementSet(elements); SelectionSetManager.AddElementSet(set);//将筛选后的元素写入模型 } /// /// 设置选中元素 /// /// 选中条件 public static void SetElements(Func condition) { DgnModel dgnModel = Session.Instance.GetActiveDgnModel();//获得当前激活的模型控件 //ElementAgenda agenda = new();//声明元素容器 SelectionSetManager.EmptyAll();//清空选择集(主要为了防止因前期选择部分元素造成的选择集项目混乱) ModelElementsCollection elems = dgnModel.GetGraphicElements();//获得当前模型中的所有图形元素 foreach (Element elem in elems)//遍历模型中的所有元素 { if (condition(elem))//通过元素类型为Solid筛选出对应元素 { SelectionSetManager.AddElement(elem, dgnModel);//将筛选后的元素写入模型 } } } /// /// 过滤掉选择集中的内嵌元素 /// /// 过滤条件 public static void RemoveElements(Func condition) { DgnModel dgnModel = Session.Instance.GetActiveDgnModel();//获得当前激活的模型控件 ElementAgenda agenda = new();//声明元素容器 SelectionSetManager.BuildAgenda(ref agenda);//从当前选择集中获得元素 for (uint i = 0; i < agenda.GetCount(); i++)//遍历选择集中的所有元素 { var elem = agenda.GetEntry(i); if (condition(elem)) { SelectionSetManager.RemoveElement(agenda.GetEntry(i), dgnModel);//移除选择集中元素类型为Solid的元素 } } } /// /// 插入元素到选择集中 /// /// public static void InvertElements(Func condition) { DgnModel dgnModel = Session.Instance.GetActiveDgnModel();//获得当前激活的模型控件 ModelElementsCollection elems = dgnModel.GetGraphicElements();//获得当前模型中的所有图形元素 foreach (Element elem in elems)//遍历选择集中的所有元素 { if (condition(elem)) { SelectionSetManager.InvertElement(elem, dgnModel);//倒置元素类型为Solid的元素 } } } /// /// 替换选中元素 /// /// 替换的元素 /// public static BentleyStatus ReplaceElemsInSelection(Element elem) { DgnModel dgnModel = Session.Instance.GetActiveDgnModel();//获得当前激活的模型控件 double uorPerMas = Session.Instance.GetActiveDgnModel().GetModelInfo().UorPerMaster;//分辨率单位转换为主单位 ElementAgenda agenda = new();//声明元素容器 SelectionSetManager.BuildAgenda(ref agenda);//从当前选择集中获得元素 if (agenda.GetCount() > 0) { return SelectionSetManager.ReplaceWithElement(elem, dgnModel);//将该元素的选中状态替换为选中 //DisplayableElement displayableElem = agenda.GetEntry(0) as DisplayableElement;//获得选择集元素对应的父类元素 //displayableElem.GetTransformOrigin(out DPoint3d elemLoc);//从该父类中获得选中元素的定位坐标 //EllipseElement ellipse = new(dgnModel, null, elemLoc, 10 * uorPerMas, 5 * uorPerMas, DMatrix3d.Identity);//声明椭圆元素 //ellipse.AddToModel();//将椭圆元素添加到模型中 //BentleyStatus status = SelectionSetManager.ReplaceWithElement(ellipse, dgnModel);//将该元素的选中状态替换为椭圆选中 } return BentleyStatus.Error; } /// /// 扫描获取元素 /// /// 设置扫描部分 /// /// /// public static List FilterByScanCriteria(ScanRange range, DgnModelSections sections = DgnModelSections.GraphicElements, MSElementType elementType = MSElementType.Solid) { DgnModel dgnModel = Session.Instance.GetActiveDgnModel();//获得当前激活的模型控件 double uorPerMas = Session.Instance.GetActiveDgnModel().GetModelInfo().UorPerMaster;//分辨率单位转换为主单位 ScanCriteria sc = new();//声明扫描标准 sc.SetModelRef(dgnModel);//设置扫描目标模型 sc.SetModelSections(sections);//设置扫描部分(本案例中仅扫描图形元素) BitMask elemTypeMask = new(false) { Capacity = 128//设置数组容量 };//声明可变位数组 elemTypeMask.ClearAll(); // Element Type Number - 1 = BitMask Index elemTypeMask.SetBit((uint)elementType - 1, true);//设置筛选元素类型 sc.SetElementTypeTest(elemTypeMask);//将可变位数组应用于扫描标准 sc.SetRangeTest(range);//将扫描范围应用于扫描标准 注:若无范围要求不进行该项设置即可 List elements = []; sc.Scan((elem, modelRef) => { elements.Add(elem); return StatusInt.Success;//返回成功 });//执行扫描 return elements; } /// /// 通过点集创建围栅 /// /// 使用端点声明端点集 public static List CreateFenceByPoints(params DPoint3d[] points) { DgnModelRef dgnModelRef = Session.Instance.GetActiveDgnModelRef();//获得当前的模型空间/参照空间 注:DgnModelRef是一个基类,DgnModel和DgnAttachment都派生于这个基类 Viewport view = Session.GetActiveViewport();//获得当前视图信息 double uorPerMas = Session.Instance.GetActiveDgnModel().GetModelInfo().UorPerMaster;//分辨率单位转换为主单位 List result = []; var pos = points.Select(p => p * uorPerMas).ToArray(); if (StatusInt.Success == FenceManager.DefineByPoints(pos, view))//使用端点声明 { FenceParameters fenceParams = new(dgnModelRef, DTransform3d.Identity);//声明围栅信息 FenceManager.InitFromActiveFence(fenceParams, true, false, FenceClipMode.None);//使用围栅信息初始化围栅 //设置模型空间 DgnModelRef[] modelRefList = [dgnModelRef,];//设置需要声明围栅的模型空间 ElementAgenda eAgenda = new();//声明元素容器 FenceManager.BuildAgenda(fenceParams, eAgenda, modelRefList, false, false, false);//使用围栅信息获得符合要求的元素集 for (uint i = 0; i < eAgenda.GetCount(); i++)//遍历元素容器中的元素 { Element element = eAgenda.GetEntry(i);//获得元素容器中的元素 result.Add(element); } } return result; } /// /// 通过点集复制围栅 /// /// 使用端点声明端点集 public static void CopyFenceByPoints(params DPoint3d[] points) { DgnModelRef dgnModelRef = Session.Instance.GetActiveDgnModelRef();//获得当前的模型空间/参照空间 注:DgnModelRef是一个基类,DgnModel和DgnAttachment都派生于这个基类 Viewport view = Session.GetActiveViewport();//获得当前视图信息 double uorPerMas = Session.Instance.GetActiveDgnModel().GetModelInfo().UorPerMaster;//分辨率单位转换为主单位 var pos = points.Select(p => p * uorPerMas).ToArray(); if (StatusInt.Success == FenceManager.DefineByPoints(pos, view))//使用端点声明 { FenceParameters fenceParams = new(dgnModelRef, DTransform3d.Identity);//声明围栅信息 FenceManager.InitFromActiveFence(fenceParams, true, false, FenceClipMode.Copy);//使用围栅信息初始化围栅 ElementAgenda eAgenda = new();//声明元素容器 DgnModelRef[] modelRefList = [ dgnModelRef,//设置模型空间 ];//设置需要声明围栅的模型空间 FenceManager.BuildAgenda(fenceParams, eAgenda, modelRefList, false, false, false);//使用围栅信息获得符合要求的元素集 for (uint i = 0; i < eAgenda.GetCount(); i++)//遍历元素容器中的元素 { using (ElementCopyContext copyContext = new(dgnModelRef))//复制元素 { Element element = eAgenda.GetEntry(i);//获得元素容器中的元素 copyContext.DoCopy(element);//将元素复制到指定模型中 } } } } /// /// 通过围栅,拉伸元素 /// /// 移动的值 /// public static void StretchElementByFence(double distance, params DPoint3d[] points) { DgnModelRef dgnModelRef = Session.Instance.GetActiveDgnModelRef();//获得当前的模型空间/参照空间 注:DgnModelRef是一个基类,DgnModel和DgnAttachment都派生于这个基类 Viewport view = Session.GetActiveViewport();//获得当前视图信息 double uorPerMas = Session.Instance.GetActiveDgnModel().GetModelInfo().UorPerMaster;//分辨率单位转换为主单位 var pos = points.Select(p => p * uorPerMas).ToArray(); if (StatusInt.Success == FenceManager.DefineByPoints(pos, view))//使用端点声明 { FenceParameters fenceParams = new(dgnModelRef, DTransform3d.Identity);//声明围栅信息 FenceManager.InitFromActiveFence(fenceParams, true, false, FenceClipMode.None);//使用围栅信息初始化围栅 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++)//遍历元素容器中的元素 { Element element = eAgenda.GetEntry(i);//获得元素容器中的元素 DPoint3d po = new(distance * uorPerMas, 0, 0);//声明坐标点,在本文中用于表明移动的值,具体可参考元素变换课程相关内容 StatusInt status = FenceManager.StretchElement( fenceParams, element, DTransform3d.FromTranslation(po), FenceStretchFlags.None); /* * 使用围栅对元素拉伸 注:视图对拉伸结果也有影响 * fenceParameters:围栅信息 * element:围栅内拉伸的元素 * transform:变换信息 * stretchFlags:围栅拉伸风格。若为Cells,则可拉伸用户声明的单元组件 */ if (status == StatusInt.Success)//判断是否拉伸成功 { element.AddToModel();//将拉伸结果写入模型 } } } } } }