Files
MsAddIns/ShrlAlgo.MsAddIns/TunnelZYJSCSHelpers.cs
2026-02-28 21:01:57 +08:00

649 lines
24 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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
{
/// <summary>
/// 自定义开项
/// </summary>
/// <example>var models = TunnelZYJSCSHelpers.GetDataByLevelName("JG_ZYJSCS");</example>
public class TunnelZYJSCSHelpers
{
/// <summary>
/// 公式计算结果
/// </summary>
/// <param name="formula"></param>
/// <param name="parameters"></param>
/// <returns></returns>
public static double EvaluateFormula(string formula, Dictionary<string, object> 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;
}
/// <summary>
/// 获取元素的图层,如果是一般单元,则按第一个子元素来获取
/// </summary>
/// <param name="element"></param>
/// <returns></returns>
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);
}
/// <summary>
/// 按图层获取数据
/// </summary>
/// <param name="levelName">自定义开项的图层</param>
/// <returns>数据集合,Key是ID-100-名称</returns>
public static Dictionary<string, TunnelZYJSCSItem> GetDataByLevelName(string levelName)
{
//获取当前激活的模型
DgnModel dgnModel = Session.Instance.GetActiveDgnModel();
//获取图层
var layer = dgnModel.GetLevelCache().GetLevelByName(levelName);
if (layer == null)
{
MessageCenter.Instance.ShowInfoMessage($"盾构专业技术措施开项出错", $"图层不存在", false);
return new Dictionary<string, TunnelZYJSCSItem>();
}
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的TypeOfSurroundingPrimarySubDetailMeasurementUnitFormula来判断
//合并后的元素的Result为合并后的元素的Result之和
var mergedItems = new Dictionary<string, TunnelZYJSCSItem>();
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<ZYJSCSElementItem> AnalyzeElements(IEnumerable<Element> elements)
{
List<ZYJSCSElementItem> items = new List<ZYJSCSElementItem>();
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(),
};
}
/// <summary>
/// 通过属性名获取属性值
/// </summary>
/// <param name="elem">元素</param>
/// <param name="classDefinitionName">属性分组</param>
/// <param name="propName">属性名</param>
/// <returns>属性值,可根据情况进行转换数据类型</returns>
public static Dictionary<string, object> GetPropertyValueByClass(Element elem, string classDefinitionName)
{
var dict = new Dictionary<string, object>();
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;
}
/// <summary>
/// 通过属性名获取属性值
/// </summary>
/// <param name="elem">元素</param>
/// <param name="propName">属性名</param>
/// <returns>属性值,可根据情况进行转换数据类型</returns>
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;
}
/// <summary>
/// 获取元素的长度
/// </summary>
/// <param name="elem">元素</param>
/// <returns>长度值单位m</returns>
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;
}
/// <summary>
/// 获取属性
/// </summary>
/// <param name="element"></param>
public static List<IECPropertyValue> GetPropertiesByName(Element element, string propName)
{
if (null == element)
{
MessageCenter.Instance.ShowInfoMessage("所提供Element无效", $"{nameof(element)}", false);
return null;
}
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.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;
}
}
/// <summary>
/// 盾构专项技术措施
/// </summary>
public class TunnelZYJSCSItem
{
/// <summary>
/// 开项名称
/// </summary>
public string Name { get; set; }
/// <summary>
/// 计量单位
/// </summary>
public string Unit { get; set; }
/// <summary>
/// 计量方式
/// </summary>
public string MeasurementStr { get; set; }
/// <summary>
/// 公式
/// </summary>
public string Formula { get; set; }
/// <summary>
/// 结果值
/// </summary>
public virtual double Result { get; set; }
/// <summary>
/// 开项元素个数
/// </summary>
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;
}
}
/// <summary>
/// 从模型属性读取的数据
/// </summary>
public class ZYJSCSElementItem : TunnelZYJSCSItem
{
public Element AssociateElement { get; set; }
private readonly double uorMeter = Session.Instance.GetActiveDgnModel().GetModelInfo().UorPerMeter;
//public ElementOpenItem(string measure, List<Element> elements)
//{
// MeasurementMode = GetMeasurement(measure);
// AssociateElements = elements;
//}
public override string ToString()
{
return $"{AssociateElement.ElementId},{AssociateElement.Description},{MeasurementStr},{Unit},{Result}{Unit}";
}
/// <summary>
/// 信息
/// </summary>
public StringBuilder Message { get; private set; }
/// <summary>
/// 平方米
/// </summary>
/// <returns></returns>
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);
}
/// <summary>
/// 米
/// </summary>
/// <returns></returns>
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;
}
/// <summary>
/// 立方米
/// </summary>
/// <returns></returns>
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);
}
/// <summary>
/// 通过公式计算结果
/// </summary>
/// <returns></returns>
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;
//}
/// <summary>
/// 计量方式
/// </summary>
public new Measurement Measurement => GetMeasurement(MeasurementStr);
/// <summary>
/// 计算结果
/// </summary>
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;
}
}
}
/// <summary>
/// 计量方式
/// </summary>
public enum Measurement
{
[Description("未知")]
Unknow,
[Description("个数")]
Count,
[Description("长度")]
Length,
[Description("面积")]
Area,
[Description("体积")]
Volume,
[Description("公式")]
Formula
}
}