Files
MsAddIns/Mstn.Toolkit/Helpers/SelectionSetHelper.cs

288 lines
14 KiB
C#
Raw Permalink Normal View History

2026-02-28 21:01:57 +08:00

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<Element> _elements;
private int _currentIndex;
// 接受 IEnumerable<Element>,这是一个协变接口
public ElementSet(IEnumerable<Element> elements)
{
// 如果传入的 elements 不为 null则转换为 List否则创建一个空 List
_elements = elements?.ToList() ?? new List<Element>();
_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
{
/// <summary>
/// 查询选择集中的元素
/// </summary>
/// <returns></returns>
public static List<Element> QueryElements()
{
ElementAgenda agenda = new();//声明元素容器
SelectionSetManager.BuildAgenda(ref agenda);//从当前选择集中获得元素
List<Element> elems = [];
for (uint i = 0; i < agenda.GetCount(); i++)//遍历选择集中的所有元素
{
elems.Add(agenda.GetEntry(i));
}
return elems;
}
public static void SetElements(List<Element> elements)
{
SelectionSetManager.EmptyAll();//清空选择集(主要为了防止因前期选择部分元素造成的选择集项目混乱)
ElementSet set = new ElementSet(elements);
SelectionSetManager.AddElementSet(set);//将筛选后的元素写入模型
}
/// <summary>
/// 设置选中元素
/// </summary>
/// <param name="condition">选中条件</param>
public static void SetElements(Func<Element, bool> 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);//将筛选后的元素写入模型
}
}
}
/// <summary>
/// 过滤掉选择集中的内嵌元素
/// </summary>
/// <param name="condition">过滤条件</param>
public static void RemoveElements(Func<Element, bool> 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的元素
}
}
}
/// <summary>
/// 插入元素到选择集中
/// </summary>
/// <param name="condition"></param>
public static void InvertElements(Func<Element, bool> condition)
{
DgnModel dgnModel = Session.Instance.GetActiveDgnModel();//获得当前激活的模型控件
ModelElementsCollection elems = dgnModel.GetGraphicElements();//获得当前模型中的所有图形元素
foreach (Element elem in elems)//遍历选择集中的所有元素
{
if (condition(elem))
{
SelectionSetManager.InvertElement(elem, dgnModel);//倒置元素类型为Solid的元素
}
}
}
/// <summary>
/// 替换选中元素
/// </summary>
/// <param name="elem">替换的元素</param>
/// <returns></returns>
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;
}
/// <summary>
/// 扫描获取元素
/// </summary>
/// <param name="sections">设置扫描部分</param>
/// <param name="elementType"></param>
/// <param name="range"></param>
/// <returns></returns>
public static List<Element> 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<Element> elements = [];
sc.Scan((elem, modelRef) =>
{
elements.Add(elem);
return StatusInt.Success;//返回成功
});//执行扫描
return elements;
}
/// <summary>
/// 通过点集创建围栅
/// </summary>
/// <param name="points">使用端点声明端点集</param>
public static List<Element> CreateFenceByPoints(params DPoint3d[] points)
{
DgnModelRef dgnModelRef = Session.Instance.GetActiveDgnModelRef();//获得当前的模型空间/参照空间 注DgnModelRef是一个基类DgnModel和DgnAttachment都派生于这个基类
Viewport view = Session.GetActiveViewport();//获得当前视图信息
double uorPerMas = Session.Instance.GetActiveDgnModel().GetModelInfo().UorPerMaster;//分辨率单位转换为主单位
List<Element> 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;
}
/// <summary>
/// 通过点集复制围栅
/// </summary>
/// <param name="points">使用端点声明端点集</param>
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);//将元素复制到指定模型中
}
}
}
}
/// <summary>
/// 通过围栅,拉伸元素
/// </summary>
/// <param name="distance">移动的值</param>
/// <param name="points"></param>
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
* stretchFlagsCells
*/
if (status == StatusInt.Success)//判断是否拉伸成功
{
element.AddToModel();//将拉伸结果写入模型
}
}
}
}
}
}