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 共享单元 /// /// 包围盒中心点 /// /// private static HashSet GetBoundingBoxCentroid(HashSet cellElements) { var hashSet = new HashSet(); 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; } /// /// 判断元素是否是曲线 /// /// 元素 /// 是否是曲线 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; } /// /// 通过点分布获取中心线 /// /// /// /// private static Element GetCenterLine(List listLineMilGeoData, HashSet 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; } /// /// 获取共享单元在最近的中线投影长度 /// /// 同一个类型的Cell实体 /// 中心线所在图层,起始字符,如DG-ZZX /// private static double GetCellsProjectLength(HashSet 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; } /// /// 根据元素类型名称,获取对应元素在中心线上的投影长度 /// /// 中心线图层起始字符串,中线可能在两个图层上DG-ZZX /// 共享单元所在图层 /// 网格元素和投影长度的集合 /// 如果是 public static Dictionary GetSharedCellProjectLength(string centerLineLevel, string modelLevel) { Dictionary cellLengthDictionary = new Dictionary(); 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().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; } /// /// 获取所有属性 /// /// private static List GetProperyValues(Element element, string propName) { if (null == element) { throw new ArgumentNullException(nameof(element), "所提供ElemId无效"); } List eCProperties = new List(); DgnECManager ecManager = DgnECManager.Manager; int count = 0; DgnECInstanceCollection instCol = ecManager.GetElementProperties(element, ECQueryProcessFlags.SearchAllClasses); foreach (IDgnECInstance inst in instCol) { count++; IEnumerator 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 } }