/*-------------------------------------------------------------------------
* 功能描述: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
}
}