Files
MsAddIns/Mstn.Toolkit/Helpers/SelectionSetHelper.cs
2026-02-28 21:01:57 +08:00

288 lines
14 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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变换信息
* stretchFlags围栅拉伸风格。若为Cells则可拉伸用户声明的单元组件
*/
if (status == StatusInt.Success)//判断是否拉伸成功
{
element.AddToModel();//将拉伸结果写入模型
}
}
}
}
}
}