using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Diagnostics; using System.Linq; using System.Text; using Bentley.DgnPlatformNET; using Bentley.DgnPlatformNET.DgnEC; using Bentley.DgnPlatformNET.Elements; using Bentley.ECObjects.Instance; using Bentley.ECObjects.Schema; using Bentley.MstnPlatformNET; using NCalc; namespace TunnelZYJSCSAddins { /// /// 自定义开项 /// /// var models = TunnelZYJSCSHelpers.GetDataByLevelName("JG_ZYJSCS"); public class TunnelZYJSCSHelpers { /// /// 公式计算结果 /// /// /// /// public static double EvaluateFormula(string formula, Dictionary parameters) { double result = default; try { Expression e = new Expression(formula); e.Parameters = parameters; var obj = e.Evaluate(); result = Convert.ToDouble(obj); } catch (Exception ex) { MessageCenter.Instance.ShowInfoMessage($"自定义公式计算出错", $"{ex.Message}", false); } return result; } /// /// 获取元素的图层,如果是一般单元,则按第一个子元素来获取 /// /// /// private static LevelHandle GetLevel(Element element) { ElementPropertiesGetter getter = new ElementPropertiesGetter(element); var lvlcache = Session.Instance.GetActiveDgnFile().GetLevelCache(); //一般单元 if (element.GetChildren().Count() > 0) { foreach (var elem in element.GetChildren()) { if (elem is DisplayableElement && !elem.IsInvisible) { return GetLevel(elem); } } } return lvlcache.GetLevel(getter.Level, true); } /// /// 按图层获取数据 /// /// 自定义开项的图层 /// 数据集合,Key是ID-100-名称 public static Dictionary GetDataByLevelName(string levelName) { //获取当前激活的模型 DgnModel dgnModel = Session.Instance.GetActiveDgnModel(); //获取图层 var layer = dgnModel.GetLevelCache().GetLevelByName(levelName); if (layer == null) { MessageCenter.Instance.ShowInfoMessage($"盾构专业技术措施开项出错", $"图层不存在", false); return new Dictionary(); } var elements = dgnModel.GetGraphicElements().Where(e => e.LevelId == layer.LevelId || GetLevel(e).LevelId == layer.LevelId); var items = AnalyzeElements(elements); //StringBuilder sb = new StringBuilder(); //sb.AppendLine("元素Id,元素类型,围岩等级,一级开项,二级开项,三级开项,支护类型,计量方式,单位,结果"); //foreach (var item in items) //{ // sb.AppendLine(item.ToString()); //} //对集合Items中的元素进行对比,如果有相同的元素,则合并,判断相同的元素通过Item的TypeOfSurrounding,Primary,Sub,Detail,Measurement,Unit,Formula来判断 //合并后的元素的Result为合并后的元素的Result之和 var mergedItems = new Dictionary(); foreach (var item in items) { var key = $"{item.Name}"; if (!mergedItems.ContainsKey(key)) { mergedItems[key] = new TunnelZYJSCSItem() { Name = item.Name, Unit = item.Unit, MeasurementStr = item.MeasurementStr, Formula = item.Formula, }; } mergedItems[key].Result += item.Result; mergedItems[key].Count++; } //foreach (var item in mergedItems) //{ // sb.AppendLine($",,{item.Key},{item.Value.Result}{item.Value.Unit}数量:{item.Value.Count}"); //} return mergedItems; //File.WriteAllText($"{Environment.GetFolderPath(Environment.SpecialFolder.Desktop)}\\ElementOpenItem.csv", sb.ToString(), Encoding.UTF8); } private static List AnalyzeElements(IEnumerable elements) { List items = new List(); foreach (var elem in elements) { items.Add(ToTunnelZYJSCSItem(elem)); } return items; } private static ZYJSCSElementItem ToTunnelZYJSCSItem(Element elem) { return new ZYJSCSElementItem() { MeasurementStr = GetPropertyValueByName(elem, "ID-100-计量方式")?.ToString().Trim(), Unit = GetPropertyValueByName(elem, "ID-100-单位")?.ToString().Trim(), Formula = GetPropertyValueByName(elem, "ID-100-公式")?.ToString().Trim(), AssociateElement = elem, Name = GetPropertyValueByName(elem, "ID-100-名称")?.ToString().Trim(), }; } /// /// 通过属性名获取属性值 /// /// 元素 /// 属性分组 /// 属性名 /// 属性值,可根据情况进行转换数据类型 public static Dictionary GetPropertyValueByClass(Element elem, string classDefinitionName) { var dict = new Dictionary(); if (elem == null) { return dict; } var instances = new CustomItemHost(elem, false).CustomItems; object value = default; foreach (var instance in instances) { if (instance.ClassDefinition.DisplayLabel.Contains(classDefinitionName) && instance.ContainsValues) { foreach (var propValue in instance) { if (propValue.TryGetNativeValue(out value)) { dict.Add(propValue.Property.DisplayLabel, value); } } } } return dict; } /// /// 通过属性名获取属性值 /// /// 元素 /// 属性名 /// 属性值,可根据情况进行转换数据类型 public static object GetPropertyValueByName(Element elem, string propName) { var instances = new CustomItemHost(elem, false).CustomItems; object value = default; foreach (var instance in instances) { if (instance.ContainsValues) { foreach (var propValue in instance) { if (propValue.Property.DisplayLabel == propName && propValue.TryGetNativeValue(out value)) { break; } } } } return value; } /// /// 获取元素的长度 /// /// 元素 /// 长度值,单位m public static double GetLength(Element elem) { var uorMeter = Session.Instance.GetActiveDgnModel().GetModelInfo().UorPerMeter; double length = default; if (elem is LineElement line) { length = line.GetCurveVector().SumOfLengths(); } if (elem is ComplexStringElement complexString) { length = complexString.GetCurveVector().SumOfLengths(); } if (elem is LineStringBaseElement lineStringBase) { length = lineStringBase.GetCurveVector().SumOfLengths(); } if (elem is EllipseElement ellipseElement) { length = ellipseElement.GetCurveVector().SumOfLengths(); } if (elem is ComplexShapeElement complexShape) { length = complexShape.GetCurveVector().SumOfLengths(); } if (elem is BSplineCurveElement bSplineCurve) { length = bSplineCurve.GetCurveVector().SumOfLengths(); } return length / uorMeter; } /// /// 获取属性 /// /// public static List GetPropertiesByName(Element element, string propName) { if (null == element) { MessageCenter.Instance.ShowInfoMessage("所提供Element无效", $"{nameof(element)}", false); return null; } 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.IsArray) { IECArrayValue arrayVal = propertyValue as IECArrayValue; if (arrayVal.Count >= 1) propertyValue = arrayVal[0]; } var prop = propertyEnum.Current.Name; ECNameValidation.DecodeFromValidName(ref prop); var displayLabel = propertyEnum.Current.DisplayLabel; ECNameValidation.DecodeFromValidName(ref displayLabel); if (propName == prop || displayLabel == propName) { eCProperties.Add(propertyValue); } } } return eCProperties; } } /// /// 盾构专项技术措施 /// public class TunnelZYJSCSItem { /// /// 开项名称 /// public string Name { get; set; } /// /// 计量单位 /// public string Unit { get; set; } /// /// 计量方式 /// public string MeasurementStr { get; set; } /// /// 公式 /// public string Formula { get; set; } /// /// 结果值 /// public virtual double Result { get; set; } /// /// 开项元素个数 /// public double Count { get; set; } public Measurement Measurement => GetMeasurement(MeasurementStr); private Measurement GetMeasurement(string measure) { if (string.IsNullOrEmpty(measure)) { return Measurement.Unknow; } else if (measure == "个数") { return Measurement.Count; } else if (measure == "长度") { return Measurement.Length; } else if (measure == "面积") { return Measurement.Area; } else if (measure == "体积") { return Measurement.Volume; } else if (measure == "公式") { return Measurement.Formula; } return Measurement.Unknow; } } /// /// 从模型属性读取的数据 /// public class ZYJSCSElementItem : TunnelZYJSCSItem { public Element AssociateElement { get; set; } private readonly double uorMeter = Session.Instance.GetActiveDgnModel().GetModelInfo().UorPerMeter; //public ElementOpenItem(string measure, List elements) //{ // MeasurementMode = GetMeasurement(measure); // AssociateElements = elements; //} public override string ToString() { return $"{AssociateElement.ElementId},{AssociateElement.Description},{MeasurementStr},{Unit},{Result}{Unit}"; } /// /// 信息 /// public StringBuilder Message { get; private set; } /// /// 平方米 /// /// private double GetArea() { //StringBuilder sb = new StringBuilder(); double area = default; var prop = TunnelZYJSCSHelpers.GetPropertiesByName(AssociateElement, "SurfaceArea").FirstOrDefault(); if (prop != null) { prop.TryGetNativeValue(out var value); double d = Convert.ToDouble(value) / (uorMeter * uorMeter); //sb.AppendLine($"父元素{AssociateElement.ElementId}:{AssociateElement.Description};面积:{d}"); area += d; } if (AssociateElement is CellHeaderElement cellElem) { foreach (var child in cellElem.GetChildren()) { var childProp = TunnelZYJSCSHelpers.GetPropertiesByName(child, "SurfaceArea").FirstOrDefault(); if (childProp != null) { childProp.TryGetNativeValue(out var value); double d = Convert.ToDouble(value) / (uorMeter * uorMeter); //sb.AppendLine($"父元素{AssociateElement.ElementId}:{AssociateElement.Description}中的子元素{child.ElementId}:{child.Description};面积:{d}"); area += d; } } } else if (AssociateElement is SharedCellElement sharedCell) { var definition = sharedCell.GetDefinition(Session.Instance.GetActiveDgnFile()); foreach (var child in definition.GetChildren()) { var childProp = TunnelZYJSCSHelpers.GetPropertiesByName(child, "SurfaceArea").FirstOrDefault(); if (childProp != null) { childProp.TryGetNativeValue(out var value); double d = Convert.ToDouble(value) / (uorMeter * uorMeter); //sb.AppendLine($"父元素{AssociateElement.ElementId}:{AssociateElement.Description}中的子元素{child.ElementId}:{child.Description};面积:{d}"); area += d; } } } return Math.Round(area, 3, MidpointRounding.AwayFromZero); } /// /// 米 /// /// private double GetLength() { double length = TunnelZYJSCSHelpers.GetLength(AssociateElement); //Message = sb; return Math.Round(length, 3, MidpointRounding.AwayFromZero); } private Measurement GetMeasurement(string measure) { if (string.IsNullOrEmpty(measure)) { return Measurement.Unknow; } else if (measure == "个数") { return Measurement.Count; } else if (measure == "长度") { return Measurement.Length; } else if (measure == "面积") { return Measurement.Area; } else if (measure == "体积") { return Measurement.Volume; } else if (measure == "公式") { return Measurement.Formula; } return Measurement.Unknow; } /// /// 立方米 /// /// private double GetVolume() { double volume = default; //StringBuilder sb = new StringBuilder(); //直接可以读取 var prop = TunnelZYJSCSHelpers.GetPropertiesByName(AssociateElement, "Volume").FirstOrDefault(); if (prop != null) { prop.TryGetNativeValue(out var value); double d = Convert.ToDouble(value) / (uorMeter * uorMeter * uorMeter); //sb.AppendLine($"父元素{AssociateElement.ElementId}:{AssociateElement.Description};体积:{d}"); volume += d; } //一般单元,能看到子元素 if (AssociateElement.GetChildren().Count() > 0) { foreach (var child in AssociateElement.GetChildren()) { var childProp = TunnelZYJSCSHelpers.GetPropertiesByName(child, "Volume").FirstOrDefault(); if (childProp != null) { childProp.TryGetNativeValue(out var value); double d = Convert.ToDouble(value) / (uorMeter * uorMeter * uorMeter); //sb.AppendLine($"父元素{AssociateElement.ElementId}:{AssociateElement.Description}中的子元素{child.ElementId}:{child.Description};体积:{d}"); volume += d; } } } //共享单元看不到子元素 if (AssociateElement is SharedCellElement sharedCell) { //var definition = sharedCell.GetDefinition(Session.Instance.GetActiveDgnFile()); DropGeometry geom = new DropGeometry(); geom.SetOptions(DropGeometry.Options.OPTION_SharedCells); geom.SetSharedCellOptions(DropGeometry.SharedCells.SHAREDCELL_Geometry); //ElementAgenda agenda = new ElementAgenda(); var status = MstnMixedAssistant.ElementOperation.DropElement(sharedCell, out var agenda, geom); if (status == StatusInt.Success) { for (uint i = 0; i < agenda.GetCount(); i++) { var child = agenda.GetEntry(i); var childProp = TunnelZYJSCSHelpers.GetPropertiesByName(child, "Volume").FirstOrDefault(); //第一次打散后,但是还是找不到体积属性,需要二次打散 if (childProp == null) { DropGeometry geomSub = new DropGeometry(); geomSub.SetOptions(DropGeometry.Options.OPTION_AppData); geomSub.SetSolidsOptions(DropGeometry.Solids.SOLID_Surfaces); var statusSub = MstnMixedAssistant.ElementOperation.DropElement(child, out var agendaSub, geomSub); if (statusSub == StatusInt.Success) { for (uint j = 0; j < agendaSub.GetCount(); j++) { var childSub = agendaSub.GetEntry(j); var childPropSub = TunnelZYJSCSHelpers.GetPropertiesByName(childSub, "Volume").FirstOrDefault(); if (childPropSub != null) { childPropSub.TryGetNativeValue(out var valueSub); double dSub = Convert.ToDouble(valueSub) / (uorMeter * uorMeter * uorMeter); volume += dSub; } } } } else { childProp.TryGetNativeValue(out var value); double d = Convert.ToDouble(value) / (uorMeter * uorMeter * uorMeter); volume += d; } //sb.AppendLine($"父元素{AssociateElement.ElementId}:{AssociateElement.Description}中的子元素{child.ElementId}:{child.Description};体积:{d}"); } } } //Message = sb; return Math.Round(volume, 3, MidpointRounding.AwayFromZero); } /// /// 通过公式计算结果 /// /// private double GetValueByFormula() { if (!string.IsNullOrEmpty(Formula) || !string.IsNullOrWhiteSpace(Formula)) { try { var parameters = TunnelZYJSCSHelpers.GetPropertyValueByClass(AssociateElement, "计算公式参数"); var result = TunnelZYJSCSHelpers.EvaluateFormula(Formula, parameters); return Math.Round(result, 3, MidpointRounding.AwayFromZero); } catch (Exception ex) { MessageCenter.Instance.ShowInfoMessage($"公式计算失败", $"{ex.Message}", false); } } return 0.0; } //private int GetCount() //{ // StringBuilder sb = new StringBuilder(); // foreach (var AssociateElement in AssociateElements) // { // sb.AppendLine($"父元素{AssociateElement.ElementId}:{AssociateElement.Description};个数:1"); // } // Message = sb; // return 1; //} /// /// 计量方式 /// public new Measurement Measurement => GetMeasurement(MeasurementStr); /// /// 计算结果 /// public override double Result { get { double result = 0.0; switch (Measurement) { case Measurement.Count: result = 1; break; case Measurement.Length: result = GetLength(); Unit = "m"; break; case Measurement.Area: result = GetArea(); Unit = "㎡"; break; case Measurement.Volume: result = GetVolume(); Unit = "m³"; break; case Measurement.Formula: result = GetValueByFormula(); break; case Measurement.Unknow: break; } return result; } } } /// /// 计量方式 /// public enum Measurement { [Description("未知")] Unknow, [Description("个数")] Count, [Description("长度")] Length, [Description("面积")] Area, [Description("体积")] Volume, [Description("公式")] Formula } }