123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445 |
- /*-------------------------------------------------------------------------
- * 功能描述: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 构造函数
- /// <summary>
- /// 初始化解析类
- /// </summary>
- /// <param name="doc"></param>
- public FloorSystemItem(Document doc)
- {
- Document = doc;
- InitData();
- }
- #endregion
- #region 属性相关
- /// <summary>
- /// 关联模型信息
- /// </summary>
- public Document Document { get; private set; }
- /// <summary>
- /// 使用关联标高
- /// </summary>
- public Level UseLevel { get; private set; }
- private bool m_IsInited;
- /// <summary>
- /// 初始化数据
- /// </summary>
- private void InitData()
- {
- if (m_IsInited)
- return;
- UseLevel = Document.GetUseView()?.GenLevel;
- m_IsInited = true;
- }
- #endregion
- #region 开始节点获取
- /// <summary>
- /// 缓存信息
- /// </summary>
- private List<StringFlag<ElementTreeNode>> m_StartNodes;
- /// <summary>
- /// 按系统获取开始节点
- /// </summary>
- /// <returns></returns>
- private List<StringFlag<ElementTreeNode>> GetStartNodes()
- {
- if (m_StartNodes != null)
- {
- //返回没有处理过的节点信息
- return m_StartNodes.Where(s=>!s.Handled).ToList();
- }
- List<StringFlag<ElementTreeNode>> startNodes = new List<StringFlag<ElementTreeNode>>();
- var doc = Document;
- #region 立管处理
- /*
- * 暂时认定,一个立管之关联一个系统
- */
- var verticalPipes = doc.GetElements<MEPCurve>().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<ElementTreeNode>(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<ElementTreeNode>(systemTypeName, node));
- }
- #endregion
- return m_StartNodes = startNodes;
- }
- #endregion
- #region 设备节点获取
- /// <summary>
- /// 模型中包含的设备
- /// </summary>
- public Dictionary<string, List<FamilyInstance>> RevitEquipments { get; private set; }
- /// <summary>
- /// 通过设备类型获取相关设备
- /// </summary>
- /// <returns></returns>
- private List<FamilyInstance> GetEquipments(string category)
- {
- if (RevitEquipments == null)
- {
- var doc = Document;
- var fies = doc.FilterElements<FamilyInstance>();
- List<StringFlag<FamilyInstance>> original = new List<StringFlag<FamilyInstance>>();
- 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<FamilyInstance>(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<FamilyInstance> result);
- return result??new List<FamilyInstance>();
- }
- #endregion
- #region 数据解析方法
- /// <summary>
- /// 解析当前楼层系统数据
- /// </summary>
- /// <param name="context"></param>
- public void Parse(SystemComputerContext context)
- {
- if (UseLevel == null)
- return;
- 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)
- {
- Domain useDomain = Domain.DomainPiping;
- List<FloorDrawRecord> drawRecords = new List<FloorDrawRecord>();
- List<FloorRelationRecord> relationRecords = new List<FloorRelationRecord>();
- #region 计算拓扑树形结构
- /*
- * 1、遍历开始点的限制:特殊阀门,指定标注的Connector;立管,已连接连接件;空间,相交风管元素;
- * 2、根据拓扑图关联的对象信息,找到系统关联的设备生成节点。如果没有遍历到要独立生成
- * 3、要不要显示端头管所在空间的位置
- */
- var startNodes = GetStartNodes();
- List<int> useIds = new List<int>();
- List<MEPCurve> verticalMepCurves = new List<MEPCurve>();
- for (int i = 0; i < startNodes.Count; i++)
- {
- var startNode = startNodes[i];
- var useRelation = relationSetting.GetFirstMatchSystem(startNode.Flag);
- if (useRelation == null)
- continue;
-
- if (useIds.Any(id => id == startNode.Instance.Current.Id.IntegerValue))
- {
- continue;
- }
- if (startNode.Instance.Current is MEPCurve mepCurve)
- {
- verticalMepCurves.Add(mepCurve);
- }
- var tempIds=SystemParseManager.BuildSystemNode(startNode.Instance, useDomain,
- (m => !startNode.Flag.Equals(m.GetSystemTypeName())));
- startNode.Instance.PipeSystemTypeName = startNode.Flag;
- BuildElementNodeData(context, startNode.Instance);
- useIds.AddRange(tempIds);
- startNode.Handled = true;
- //可以清空Leaves的子节点
- #region 整理原始数据
- //判断是否有设备节点,不进行数据处理
- var useNode = startNode.Instance;
- //var firstEquipment = useNode.FirstOrDefault(t => MBIInfoUtil.IsEquipment(t.Current));
- //要不要以这个为判定条件,图形可以画出,关系肯定是没有的
- //if (firstEquipment != null)
- if (useNode.Nodes.Any())
- {
- //存在设备则保存信息
- var drawRecord = BuildFloorDrawRecord(relationSetting, useNode);
- drawRecord.SystemName = startNode.Flag;
- drawRecords.Add(drawRecord);
- var relationRecord = BuildFloorRelationRecord(relationSetting, useNode);
- relationRecords.Add(relationRecord);
- }
- #endregion
- }
-
- //获取没有使用过的对象节点
- List<FamilyInstance> 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 connectors = useInstance.GetAllConnectors();
- foreach (var connector in connectors)
- {
- if (connector.Domain != useDomain)
- {
- continue;
- }
- var startNode = SystemParseManager.CreateTreeNode(useInstance, connector, e => e is MEPCurve);
- var useMepCurve = startNode.GetLeaves().FirstOrDefault()?.Current as MEPCurve;
- if (useMepCurve == null)
- continue;
- var systemTypeName = useMepCurve.GetSystemTypeName();
- if (!relationSetting.IsMatchSystem(systemTypeName))
- {
- continue;
- }
- //var startNode = new ElementTreeNode() { Current = useInstance };
- var tempIds = SystemParseManager.BuildSystemNode(startNode, useDomain,
- (m => !systemTypeName.Equals(m.GetSystemTypeName())));
- startNode.PipeSystemTypeName = systemTypeName;
- BuildElementNodeData(context, startNode);
- useIds.AddRange(tempIds);
- #region 生成绘图,计算数据
- //解析数据,找管道定系统,管道找不到,系统名为"关联类型-未知"
- var drawRecord = BuildFloorDrawRecord(relationSetting, startNode);
- drawRecord.SystemName = systemTypeName;
- drawRecords.Add(drawRecord);
- var relationRecord = BuildFloorRelationRecord(relationSetting, startNode);
- relationRecords.Add(relationRecord);
- #endregion
- }
- }
- #endregion
- //增加立管数据
- ComputerVerticalPipes(UseLevel, verticalMepCurves, context);
- context.FloorDrawRecords.AddRange(drawRecords);
- context.FloorRelationRecords.AddRange(relationRecords);
- }
- #endregion
- #region 风系统解析
- public void ParseDuct(SystemComputerContext context, RelationTypeShell relationSetting)
- { }
- #endregion
- #endregion
- #region 解析立管
- /*
- * 1、解析立管需要考虑,竖直风管,水管,空间的情况;
- *2、将各层数据汇总,才能统一计算立管的相关关系数据
- */
- private void ComputerVerticalPipes(Level refLevel, List<MEPCurve> mepCurves, SystemComputerContext context)
- {
- var result = new List<VerticalPipe>();
- var spaces = Document.GetElements<SpatialElement>(BuiltInCategory.OST_MEPSpaces).OfType<Space>();
- var level = refLevel;
- var currentLevelName = MBIInfoUtil.GetFloorNameByLevel(level.Name);
- foreach (var pipe in mepCurves)
- {
- 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.RelationItems = SystemParseManager.CreateRelation(node)??new List<BinaryRelationItem>();
- return floorRelation;
- }
- #endregion
- #region 初始化名称,分类
- /// <summary>
- /// 初始化节点扩展数据
- /// </summary>
- /// <param name="context"></param>
- /// <param name="node"></param>
- private void BuildElementNodeData(SystemComputerContext context, ElementTreeNode node)
- {
- Queue<ElementTreeNode> nodeQueue = new Queue<ElementTreeNode>();
- nodeQueue.Enqueue(node);
- while (nodeQueue.Any())
- {
- #region 控制验证
- var currentNode = nodeQueue.Dequeue();
- if (currentNode == null)
- continue;
- var element = currentNode.Current;
- if (element == null)
- continue;
- #endregion
- if (element is FamilyInstance fiEq)
- {
- #region 判断是否是设备
- if (MBIInfoUtil.IsEquipment(fiEq))
- {
- var equipItem = context.EquipmentItems.GetItem(fiEq.GetBimId());
- NodeExtendData data = new NodeExtendData();
- if (equipItem != null)
- {
- data.Name = equipItem.GetDisplay();
- data.Category = equipItem.Category;
- }
- else
- {
- data.Name = fiEq.GetFamily()?.Name;
- }
- data.SystemType = node.PipeSystemTypeName;
- currentNode.Tag = data;
- }
- #endregion
- }
- else if (element is Space revitSpace)
- {
- var space = context.Rooms.GetItem(element.GetBimId());
- NodeExtendData data = new NodeExtendData();
- if (space != null)
- {
- data.Name = space.GetDisplay();
- }
- else
- {
- data.Name = revitSpace.Name;
- }
- data.SystemType = node.PipeSystemTypeName;
- currentNode.Tag = data;
- }
- currentNode.Nodes.ForEach(e => nodeQueue.Enqueue(e));
- }
- }
- #endregion
- #region 解析机房数据
- private void ParseMachineRoomData()
- {
- //GplotOptions options = new GplotOptions();
- //options.BaseOnDefinition(Definition);
- //SystemParse parse = new SystemParse(new SystemParseSetting(options));
- //StartElementsManager startManager = new StartElementsManager(options);
- ////所有项目中所有文档
- //List<Element> startElements = new List<Element>();
- //startElements.AddRange(startManager.GetStartElements(Document));
- //var arrays = parse.Execute(startElements);
- ////arrays.ForEach(a => parse.LoadEquipmentItem(a));
- ////去除不包含真实设备的拓扑
- //arrays.RemoveAll(c => c.GetAvailableVertexes(null).All(v => !v.IsRealEquipment()));
- ////GplotParseData data = new GplotParseData();
- //data.OriginalData = arrays;
- }
- #endregion
- }
- }
|