288 lines
14 KiB
C#
288 lines
14 KiB
C#
|
||
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();//将拉伸结果写入模型
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|