/*------------------------------------------------------------------------- * 功能描述:FloorSystemItems * 作者:xulisong * 创建时间: 2019/1/4 17:50:04 * 版本号:v1.0 * -------------------------------------------------------------------------*/ using System.Collections.Generic; using System.Linq; using System.Text.RegularExpressions; using Autodesk.Revit.DB; using Autodesk.Revit.DB.Mechanical; using Autodesk.Revit.DB.Plumbing; using SAGA.DotNetUtils.Data; using SAGA.Models; using SAGA.RevitUtils; using SAGA.RevitUtils.Extends; using SAGA.RevitUtils.MEP; namespace SAGA.GplotRelationComputerManage { public class FloorSystemItem { #region 构造函数 /// /// 初始化解析类 /// /// public FloorSystemItem(Document doc) { Document = doc; InitData(); } #endregion #region 属性相关 /// /// 关联模型信息 /// public Document Document { get; private set; } /// /// 使用关联标高 /// public Level UseLevel { get; private set; } private bool m_IsInited; /// /// 初始化数据 /// private void InitData() { if (m_IsInited) return; UseLevel = Document.GetUseView()?.GenLevel; m_IsInited = true; } #endregion #region 开始节点获取 /// /// 缓存信息 /// private List> m_StartNodes; /// /// 按系统获取开始节点 /// /// private List> GetStartNodes() { if (m_StartNodes != null) { //返回没有处理过的节点信息 return m_StartNodes.Where(s=>!s.Handled).ToList(); } List> startNodes = new List>(); var doc = Document; #region 立管处理 /* * 暂时认定,一个立管之关联一个系统 */ var verticalPipes = doc.GetElements().Where(p => SystemCalcUtil.IsStart(p) && p.IsVerticalPipe()); foreach (var verticalPipe in verticalPipes) { ElementTreeNode node = new ElementTreeNode(); node.Current = verticalPipe; var systemTypeName = verticalPipe.GetSystemTypeName(); startNodes.Add(new StringFlag(systemTypeName, node)); } #endregion #region 特殊阀门处理 ElementCategoryFilter pipeFilter = new ElementCategoryFilter(BuiltInCategory.OST_PipeAccessory); ElementCategoryFilter ductFilter = new ElementCategoryFilter(BuiltInCategory.OST_DuctAccessory); ElementFilter filter = new LogicalOrFilter(pipeFilter, ductFilter); var specialValves = doc.FilterElements(filter).Where(f => SystemCalcUtil.IsStart(f)); foreach (var familyInstance in specialValves) { var connector = familyInstance.GetAllConnectors().FirstOrDefault(c => Regex.IsMatch(c.Description, AppSetting.EndFlag)); if (connector == null) continue; var node = SystemParseManager.CreateTreeNode(familyInstance, connector, e => e is MEPCurve); var useMepCurve = node.GetLeaves().FirstOrDefault()?.Current as MEPCurve; if (useMepCurve == null) continue; var systemTypeName = useMepCurve.GetSystemTypeName(); startNodes.Add(new StringFlag(systemTypeName, node)); } #endregion return m_StartNodes = startNodes; } #endregion #region 设备节点获取 /// /// 模型中包含的设备 /// public Dictionary> RevitEquipments { get; private set; } /// /// 通过设备类型获取相关设备 /// /// private List GetEquipments(string category) { if (RevitEquipments == null) { var doc = Document; var fies = doc.FilterElements(); List> original = new List>(); foreach (var familyInstance in fies) { var familyName = familyInstance.GetFamily().Name; if (string.IsNullOrEmpty(familyName)) continue; var match=Regex.Match(familyName, @"^(?:((?:[A-Z][A-Z]){2,3})\s*-\s*\S*)"); if (match.Success) { original.Add(new StringFlag(match.Groups[1].ToString(), familyInstance)); } } RevitEquipments= original.GroupBy(f => f.Flag).ToDictionary(g=>g.Key,g=>g.ToList().Select(f=>f.Instance).ToList()); } RevitEquipments.TryGetValue(category, out List result); return result??new List(); } #endregion #region 数据解析方法 /// /// 解析当前楼层系统数据 /// /// public void Parse(SystemComputerContext context) { var doc = Document; var relations = context.Relations; foreach (var relation in relations) { var shell = context.RelationShells.GetItem(relation); if (shell.IsPipeSystem()) { ParsePipe(context, shell); } else { ParseDuct(context, shell); } } } #region 水系统解析 public void ParsePipe(SystemComputerContext context,RelationTypeShell relationSetting) { List drawRecords = new List(); List relationRecords = new List(); #region 计算拓扑树形结构 /* * 1、遍历开始点的限制:特殊阀门,指定标注的Connector;立管,已连接连接件;空间,相交风管元素; * 2、根据拓扑图关联的对象信息,找到系统关联的设备生成节点。如果没有遍历到要独立生成 * 3、要不要显示端头管所在空间的位置 */ var startNodes = GetStartNodes(); List useIds = new List(); for (int i = 0; i < startNodes.Count; i++) { var startNode = startNodes[i]; if (!relationSetting.IsMatchSystem(startNode.Flag)) { continue; } if (useIds.Any(id => id == startNode.Instance.Current.Id.IntegerValue)) { continue; } var tempIds=SystemParseManager.BuildSystemNode(startNode.Instance, Domain.DomainPiping, (m => !relationSetting.IsMatchSystem(m.GetSystemTypeName()))); useIds.AddRange(tempIds); startNode.Handled = true; //可以清空Leaves的子节点 #region 整理原始数据 //判断是否有设备节点,不进行数据处理 var useNode = startNode.Instance; var firstEquipment = useNode.FirstOrDefault(t => MBIInfoUtil.IsEquipment(t.Current)); //要不要以这个为判定条件,图形可以画出,关系肯定是没有的 if (firstEquipment != null) { //存在设备则保存信息 var drawRecord = BuildFloorDrawRecord(relationSetting, useNode); drawRecord.SystemName = startNode.Flag; drawRecords.Add(drawRecord); var relationRecord = BuildFloorRelationRecord(relationSetting, useNode); relationRecords.Add(relationRecord); } #endregion } //获取没有使用过的对象节点 List singleInstances = relationSetting.RelationItem.Objects.SelectMany(o => GetEquipments(o.Type)).ToList(); for (int i = 0; i < singleInstances.Count; i++) { var useInstance = singleInstances[i]; if (useIds.Any(id => id == useInstance.Id.IntegerValue)) { continue; } var startNode = new ElementTreeNode() {Current = useInstance}; var tempIds = SystemParseManager.BuildSystemNode(startNode, Domain.DomainPiping, (m => !relationSetting.IsMatchSystem(m.GetSystemTypeName()))); useIds.AddRange(tempIds); #region 生成绘图,计算数据 //解析数据,找管道定系统,管道找不到,系统名为"关联类型-未知" var firstMepCurve = startNode.FirstOrDefault(t => t.Current is MEPCurve); if (firstMepCurve == null) continue; var useSystemName = (firstMepCurve.Current as MEPCurve)?.GetSystemTypeName() ?? GetUnknownSystemName(relationSetting); //存在设备则保存信息 var drawRecord = BuildFloorDrawRecord(relationSetting, startNode); drawRecord.SystemName = useSystemName; drawRecords.Add(drawRecord); var relationRecord = BuildFloorRelationRecord(relationSetting, startNode); relationRecords.Add(relationRecord); #endregion } #endregion context.DrawRecords.AddRange(drawRecords); context.RelationRecords.AddRange(relationRecords); } #endregion #region 风系统解析 public void ParseDuct(SystemComputerContext context, RelationTypeShell relationSetting) { } #endregion #endregion #region 解析立管 private void ComputerVerticalPipes(Level refLevel, List pipes, SystemComputerContext context) { var result = new List(); var spaces = Document.GetElements(BuiltInCategory.OST_MEPSpaces).OfType(); var level = refLevel; var currentLevelName = MBIInfoUtil.GetFloorNameByLevel(level.Name); foreach (var pipe in pipes) { if (pipe == null) continue; var vp = new VerticalPipe { Id = pipe.Id.IntegerValue.ToString(), LevelName = currentLevelName, LevelElevation = level.Elevation, UpPoint3D = PointConverter.XYZToPoint3D(pipe.GetVerticalTopPoint()), DownPoint3D = PointConverter.XYZToPoint3D(pipe.GetVerticalBottomPoint()), PipeSytemType = pipe.GetSystemTypeName() }; #region 获取立管关联空间 var locationCurve = pipe.GetLocationCurve(); var midPoint = (locationCurve.StartPoint() + locationCurve.EndPoint()) / 2; Space refSpace = spaces.FirstOrDefault(s => s.IsPointInSpace(midPoint));//关联 var display = context.GetSpaceDisplay(refSpace, out string tip); vp.Display = $"{display}:{pipe.Id.IntegerValue.ToString()}"; vp.DisplayTip = tip ?? string.Empty; #endregion result.Add(vp); } LevelData levelData = new LevelData() { Id = refLevel.Id.ToString(), Name = MBIInfoUtil.GetFloorNameByLevel(refLevel.Name) }; context.VerticalPipes.AddRange(result); context.Levels.Add(levelData); } #endregion #region 保存数据类对象创建 private string GetUnknownSystemName(RelationTypeShell relationShell) { return relationShell.RelationItem?.Name + "---未知"; } private FloorDrawRecord BuildFloorDrawRecord(RelationTypeShell relationShell,ElementTreeNode node) { var floorDraw = new FloorDrawRecord(); floorDraw.SetFloorLevel(UseLevel); floorDraw.RelationType = relationShell.RelationItem.Type; floorDraw.DrawIems = SystemParseManager.CreateDrawing(node)??new SystemDrawItems(); return floorDraw; } private FloorRelationRecord BuildFloorRelationRecord(RelationTypeShell relationShell, ElementTreeNode node) { var floorRelation = new FloorRelationRecord(); floorRelation.SetFloorLevel(UseLevel); floorRelation.RelationType = relationShell.RelationItem.Type; floorRelation.EquipmentItems = SystemParseManager.CreateRelation(node)??new List(); return floorRelation; } #endregion } }