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
|
|||
|
|
}
|
|||
|
|
}
|