243 lines
10 KiB
C#
243 lines
10 KiB
C#
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.DgnEC;
|
||
using Bentley.DgnPlatformNET.Elements;
|
||
using Bentley.ECObjects.Instance;
|
||
using Bentley.ECObjects.Schema;
|
||
using Bentley.GeometryNET;
|
||
using Bentley.MstnPlatformNET;
|
||
|
||
namespace CenterCurveAddins
|
||
{
|
||
internal class SharedCellTunnelLengthHelper
|
||
{
|
||
#region 共享单元
|
||
/// <summary>
|
||
/// 包围盒中心点
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
private static HashSet<DPoint3d> GetBoundingBoxCentroid(HashSet<SharedCellElement> cellElements)
|
||
{
|
||
var hashSet = new HashSet<DPoint3d>();
|
||
|
||
foreach (var element in cellElements)
|
||
{
|
||
// 获取元素的范围,使用单位矩阵获取模型坐标系中的范围
|
||
var status = element.CalcElementRange(out var range);
|
||
if (!range.IsNull() && status == StatusInt.Success)
|
||
{
|
||
var center = (range.Low + range.High) * 0.5;
|
||
hashSet.Add(center);
|
||
}
|
||
}
|
||
return hashSet;
|
||
}
|
||
/// <summary>
|
||
/// 判断元素是否是曲线
|
||
/// </summary>
|
||
/// <param name="elem">元素</param>
|
||
/// <returns>是否是曲线</returns>
|
||
private static bool IsCurve(Element elem)
|
||
{
|
||
return elem is LineElement ||
|
||
elem is ComplexStringElement ||
|
||
elem is LineStringBaseElement ||
|
||
elem is EllipseElement ||
|
||
elem is ComplexShapeElement ||
|
||
elem is BSplineCurveElement;
|
||
}
|
||
/// <summary>
|
||
/// 通过点分布获取中心线
|
||
/// </summary>
|
||
/// <param name="listLineMilGeoData"></param>
|
||
/// <param name="listPtAll"></param>
|
||
/// <returns></returns>
|
||
private static Element GetCenterLine(List<Element> listLineMilGeoData, HashSet<DPoint3d> listPtAll)
|
||
{
|
||
Element targetLine = null;
|
||
//随机取点
|
||
var pt3dMid = listPtAll.FirstOrDefault();
|
||
if (listPtAll == null || listPtAll.Count == 0)
|
||
{
|
||
return targetLine;
|
||
}
|
||
|
||
double dDisMin = double.MaxValue;
|
||
//找到距离点最近的线元素
|
||
foreach (var item in listLineMilGeoData)
|
||
{
|
||
CurveVector cv = CurvePathQuery.ElementToCurveVector(item);
|
||
if (cv == null)
|
||
{
|
||
continue;
|
||
}
|
||
|
||
CurveLocationDetail curLocDetail = cv.ClosestPointBounded(pt3dMid);
|
||
if (curLocDetail == null)
|
||
{
|
||
continue;
|
||
}
|
||
|
||
double dDis = pt3dMid.DistanceXY(curLocDetail.Point);
|
||
if (dDis < dDisMin)
|
||
{
|
||
dDisMin = dDis;
|
||
targetLine = item;
|
||
}
|
||
}
|
||
return targetLine;
|
||
}
|
||
/// <summary>
|
||
/// 获取共享单元在最近的中线投影长度
|
||
/// </summary>
|
||
/// <param name="cellElements">同一个类型的Cell实体</param>
|
||
/// <param name="centerLineLevel">中心线所在图层,起始字符,如DG-ZZX</param>
|
||
/// <returns></returns>
|
||
private static double GetCellsProjectLength(HashSet<SharedCellElement> cellElements, string centerLineLevel)
|
||
{
|
||
if (cellElements.Count == 0)
|
||
{
|
||
return 0.0;
|
||
}
|
||
DgnModel dgnModel = Session.Instance.GetActiveDgnModel();
|
||
var levelCache = dgnModel.GetLevelCache();
|
||
|
||
//过滤获取线条元素,即所有中心线
|
||
var listLineMilGeoData = dgnModel.GetElements()
|
||
.Where(
|
||
e => e.IsValid &&
|
||
!e.IsInvisible &&
|
||
levelCache.GetLevel(e.LevelId)?.DisplayName.Trim().StartsWith(centerLineLevel) == true &&
|
||
IsCurve(e))
|
||
.ToList();
|
||
//曲面拍平的所有点
|
||
var listPtAll = GetBoundingBoxCentroid(cellElements);
|
||
//通过点分布获取中心线
|
||
var targetLine = GetCenterLine(listLineMilGeoData, listPtAll);
|
||
if (targetLine != null)
|
||
{
|
||
CurveVector curveVector = CurvePathQuery.ElementToCurveVector(targetLine);
|
||
//找到曲面拍平的 所有点 到 平面距离最近中心线上的点
|
||
var locs = listPtAll.Select(curveVector.ClosestPointBoundedXY);
|
||
|
||
var ordered = locs.OrderBy(loc => curveVector.CurveLocationDetailIndex(loc)).ThenBy(loc => loc.Fraction);
|
||
var min = ordered.FirstOrDefault();
|
||
var max = ordered.LastOrDefault();
|
||
|
||
var minIndex = curveVector.CurveLocationDetailIndex(min);
|
||
var maxIndex = curveVector.CurveLocationDetailIndex(max);
|
||
|
||
var minCurve = curveVector.GetPrimitive((int)minIndex);
|
||
var maxCurve = curveVector.GetPrimitive((int)maxIndex);
|
||
//拿到最大最小线段距离
|
||
minCurve.SignedDistanceBetweenFractions(0, min.Fraction, out var dist);
|
||
maxCurve.SignedDistanceBetweenFractions(0, max.Fraction, out var dist1);
|
||
//var l = (dist1 - dist) / Session.Instance.GetActiveDgnModel().GetModelInfo().UorPerMeter > 5000;
|
||
|
||
if (minIndex == maxIndex) //是否在同一条线上
|
||
{
|
||
return (dist1 - dist) / Session.Instance.GetActiveDgnModel().GetModelInfo().UorPerMeter;
|
||
}
|
||
else if (maxIndex > minIndex)
|
||
{
|
||
minCurve.Length(out var minLength);
|
||
//maxCurve.Length(out var maxlength);
|
||
var minDis = minLength - dist;//前置曲线的后半段
|
||
//var maxDis = max.Fraction * maxlength;//后置曲线的前半段
|
||
var length = minDis + dist1;
|
||
|
||
if (maxIndex - minIndex > 1)//不连续,中间还有其他的线
|
||
{
|
||
for (var i = minIndex + 1; i < maxIndex; i++)
|
||
{
|
||
curveVector.GetPrimitive((int)i).Length(out var l);
|
||
length += l;
|
||
}
|
||
}
|
||
return length / Session.Instance.GetActiveDgnModel().GetModelInfo().UorPerMeter;
|
||
}
|
||
}
|
||
return 0.0;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 根据元素类型名称,获取对应元素在中心线上的投影长度
|
||
/// </summary>
|
||
/// <param name="centerLineLevel">中心线图层起始字符串,中线可能在两个图层上DG-ZZX</param>
|
||
/// <param name="modelLevel">共享单元所在图层</param>
|
||
/// <returns>网格元素和投影长度的集合</returns>
|
||
/// <remarks>如果是</remarks>
|
||
public static Dictionary<string, double> GetSharedCellProjectLength(string centerLineLevel, string modelLevel)
|
||
{
|
||
Dictionary<string, double> cellLengthDictionary = new Dictionary<string, double>();
|
||
DgnModel dgnModel = Session.Instance.GetActiveDgnModel();
|
||
var levelCache = dgnModel.GetLevelCache();
|
||
|
||
try
|
||
{
|
||
var sharedCellElements = dgnModel.GetElements()
|
||
.Where(e => e.IsValid && !e.IsInvisible && (levelCache.GetLevel(e.LevelId)?.DisplayName.Trim().ToUpper() == modelLevel) && e is SharedCellElement).Cast<SharedCellElement>().ToHashSet();
|
||
var groups = sharedCellElements.GroupBy(cell => GetProperyValues(cell, "ID-100-名称").FirstOrDefault().NativeValue.ToString());
|
||
foreach (var group in groups)
|
||
{
|
||
var length = GetCellsProjectLength(sharedCellElements, centerLineLevel);
|
||
cellLengthDictionary.Add(group.Key, length);
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
MessageBox.Show(ex.Message);
|
||
}
|
||
return cellLengthDictionary;
|
||
}
|
||
/// <summary>
|
||
/// 获取所有属性
|
||
/// </summary>
|
||
/// <param name="element"></param>
|
||
private static List<IECPropertyValue> GetProperyValues(Element element, string propName)
|
||
{
|
||
if (null == element)
|
||
{
|
||
throw new ArgumentNullException(nameof(element), "所提供ElemId无效");
|
||
}
|
||
List<IECPropertyValue> eCProperties = new List<IECPropertyValue>();
|
||
DgnECManager ecManager = DgnECManager.Manager;
|
||
int count = 0;
|
||
DgnECInstanceCollection instCol = ecManager.GetElementProperties(element, ECQueryProcessFlags.SearchAllClasses);
|
||
foreach (IDgnECInstance inst in instCol)
|
||
{
|
||
count++;
|
||
IEnumerator<IECProperty> propertyEnum = inst.ClassDefinition.GetEnumerator();
|
||
while (propertyEnum.MoveNext())
|
||
{
|
||
IECPropertyValue propertyValue = inst.GetPropertyValue(propertyEnum.Current.Name);
|
||
if (propertyValue == null)
|
||
{
|
||
continue;
|
||
}
|
||
if (propertyValue.IsArray)
|
||
{
|
||
IECArrayValue arrayVal = propertyValue as IECArrayValue;
|
||
if (arrayVal.Count >= 1)
|
||
propertyValue = arrayVal[0];
|
||
}
|
||
var prop = propertyEnum.Current.Name;
|
||
ECNameValidation.DecodeFromValidName(ref prop);
|
||
if (propName == prop)
|
||
{
|
||
eCProperties.Add(propertyValue);
|
||
}
|
||
}
|
||
}
|
||
return eCProperties;
|
||
}
|
||
#endregion
|
||
}
|
||
}
|