|
@@ -9,14 +9,37 @@
|
|
|
using System;
|
|
|
using System.Collections.Generic;
|
|
|
using System.Linq;
|
|
|
+using System.Text.RegularExpressions;
|
|
|
using Autodesk.Revit.DB;
|
|
|
using Autodesk.Revit.DB.Mechanical;
|
|
|
using FWindSoft.Data;
|
|
|
using SAGA.DotNetUtils.Extend;
|
|
|
+using SAGA.MBI.DataArrange;
|
|
|
+using SAGA.MBI.Model;
|
|
|
+using SAGA.Models;
|
|
|
+using SAGA.RevitUtils;
|
|
|
using SAGA.RevitUtils.Extends;
|
|
|
|
|
|
-namespace SAGA.GplotRelationComputerManage.SpaceRelation
|
|
|
+namespace SAGA.GplotRelationComputerManage
|
|
|
{
|
|
|
+ [Flags]
|
|
|
+ public enum AdjanceElementType
|
|
|
+ {
|
|
|
+ None=0,
|
|
|
+ Wall=1,
|
|
|
+ VirtualWall=1<<1,
|
|
|
+ Door=1<<2,
|
|
|
+ Window=1<<3,
|
|
|
+ /// <summary>
|
|
|
+ /// 垂直邻接
|
|
|
+ /// </summary>
|
|
|
+ Vertical=1<<4,
|
|
|
+ /// <summary>
|
|
|
+ /// 垂直洞口,交通
|
|
|
+ /// </summary>
|
|
|
+ VerticalOpening = 1 << 5,
|
|
|
+ }
|
|
|
+
|
|
|
/// <summary>
|
|
|
///模型解析对应的楼层空间数据
|
|
|
/// </summary>
|
|
@@ -30,9 +53,11 @@ namespace SAGA.GplotRelationComputerManage.SpaceRelation
|
|
|
public FloorSpaceItems(Document doc)
|
|
|
{
|
|
|
Document = doc;
|
|
|
- Doors = new List<FamilyInstance>();
|
|
|
- Windows = new List<FamilyInstance>();
|
|
|
+ Doors = new Dictionary<string, List<FamilyInstance>>();
|
|
|
+ Windows = new Dictionary<string, List<FamilyInstance>>();
|
|
|
Spaces = new List<Space>();
|
|
|
+ ComputerSpaceItems = new List<ComputerSpaceItem>();
|
|
|
+ InitData();
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
@@ -44,30 +69,214 @@ namespace SAGA.GplotRelationComputerManage.SpaceRelation
|
|
|
/// <summary>
|
|
|
/// 关联门信息
|
|
|
/// </summary>
|
|
|
- public List<FamilyInstance> Doors { get; private set; }
|
|
|
+ public Dictionary<string,List<FamilyInstance>> Doors { get; private set; }
|
|
|
/// <summary>
|
|
|
/// 关联窗体信息
|
|
|
/// </summary>
|
|
|
- public List<FamilyInstance> Windows { get; private set; }
|
|
|
+ public Dictionary<string, List<FamilyInstance>> Windows { get; private set; }
|
|
|
/// <summary>
|
|
|
/// 关联空间信息
|
|
|
/// </summary>
|
|
|
- public List<Space> Spaces { get; private set; }
|
|
|
+ public List<Space> Spaces { get; private set; }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 空间计算数据
|
|
|
+ /// </summary>
|
|
|
+ public List<ComputerSpaceItem> ComputerSpaceItems { get; private set; }
|
|
|
#endregion
|
|
|
|
|
|
+ private bool m_IsInited;
|
|
|
+ public void InitData()
|
|
|
+ {
|
|
|
+ if (!m_IsInited)
|
|
|
+ {
|
|
|
+ var doc = Document;
|
|
|
+ Doors = doc.GetElements<FamilyInstance>(BuiltInCategory.OST_Doors).GroupBy(e =>
|
|
|
+ {
|
|
|
+ var host = e.Host;
|
|
|
+ if (host == null)
|
|
|
+ return "-1";
|
|
|
+ return host.Id.IntegerValue.ToString();
|
|
|
+ }).ToDictionary(g => g.Key, g => g.ToList());
|
|
|
+ Windows = doc.GetElements<FamilyInstance>(BuiltInCategory.OST_Windows).GroupBy(e =>
|
|
|
+ {
|
|
|
+ var host = e.Host;
|
|
|
+ if (host == null)
|
|
|
+ return "-1";
|
|
|
+ return host.Id.IntegerValue.ToString();
|
|
|
+ }).ToDictionary(g => g.Key, g => g.ToList());
|
|
|
+ Spaces = doc.GetElements<SpatialElement>(BuiltInCategory.OST_MEPSpaces).OfType<Space>().Where(s=>s.Area>0.001).ToList();
|
|
|
+ ComputerSpaceItems = Spaces.Select(s => new ComputerSpaceItem(s)).ToList();
|
|
|
+ m_IsInited = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ #region 持久缓存数据
|
|
|
+ private Dictionary<string, SgSpace> m_SaveSpaces = new Dictionary<string, SgSpace>();
|
|
|
+
|
|
|
/// <summary>
|
|
|
- /// 解析
|
|
|
+ /// 获取空间持久数据【缓存没有的话,创建新对象,并加入缓存】
|
|
|
/// </summary>
|
|
|
- public void Parse()
|
|
|
+ /// <param name="space"></param>
|
|
|
+ /// <param name="context"></param>
|
|
|
+ /// <returns></returns>
|
|
|
+ public SgSpace GetSpace(Space space,SpaceComputerContext context)
|
|
|
{
|
|
|
+ string key = space.GetBimId();
|
|
|
+ if (m_SaveSpaces.TryGetValue(key, out SgSpace useSpace))
|
|
|
+ {
|
|
|
+ return useSpace;
|
|
|
+ }
|
|
|
+ useSpace = context.NewSpace(space);
|
|
|
+ m_SaveSpaces[key] = useSpace;
|
|
|
+ return useSpace;
|
|
|
+ }
|
|
|
+ #endregion
|
|
|
+ /// <summary>
|
|
|
+ /// 解析空间关系
|
|
|
+ /// </summary>
|
|
|
+ public void Parse(SpaceComputerContext context)
|
|
|
+ {
|
|
|
+ //初始化空间信息
|
|
|
+ Spaces.ForEach(s => GetSpace(s, context));
|
|
|
+
|
|
|
+ CurrentFloorParse(context);
|
|
|
+ UpFloorParse(context);
|
|
|
+ #region 保存缓存数据
|
|
|
var doc = Document;
|
|
|
- Doors = doc.GetElements<FamilyInstance>(BuiltInCategory.OST_Doors);
|
|
|
- Windows = doc.GetElements<FamilyInstance>(BuiltInCategory.OST_Windows);
|
|
|
- Spaces = doc.GetElements<SpatialElement>(BuiltInCategory.OST_MEPSpaces).OfType<Space>().ToList();
|
|
|
+ var id = Regex.Replace(doc.PathName, @".+\\(\w+)\\(\w+).rvt$", "$1-$2");
|
|
|
+ var saveName = DalProjectTree.GetFloorNameByFloorId(id.Split('-')[1]);
|
|
|
+ var levels = doc.GetLevels();
|
|
|
+ string levelName = saveName;
|
|
|
+ var currLevels = levels.FirstOrDefault(t => t.Name.IndexOf("-saga") > -1);
|
|
|
+ if (currLevels != null) levelName = currLevels.Name;
|
|
|
+ FloorSpaceData floorData = new FloorSpaceData
|
|
|
+ {
|
|
|
+ Name = saveName,
|
|
|
+ Id = id,
|
|
|
+ LevelName = levelName.Replace("-saga", "")
|
|
|
+ };
|
|
|
+ m_SaveSpaces.Values.ToList().ForEach(s => floorData.EndPoints.Add(s));
|
|
|
+ //获取标高名称,并按高度排序
|
|
|
+ List<string> levelNames = levels.OrderBy(t => t.Elevation).Where(t => Regex.IsMatch(t.Name, "[F|B]")).Select(t => t.Name.Replace("-saga", "")).ToList();
|
|
|
+ DrawDataServer.SaveSpaceFloorData(new List<FloorSpaceData>() { floorData }, levelNames);
|
|
|
+ #endregion
|
|
|
+ }
|
|
|
+ /// <summary>
|
|
|
+ /// 本层空间关系解析
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="context"></param>
|
|
|
+ private void CurrentFloorParse(SpaceComputerContext context)
|
|
|
+ {
|
|
|
+ BinaryRelationCollection<Space, AdjanceElementType> spaceRelations =
|
|
|
+ new BinaryRelationCollection<Space, AdjanceElementType>(false,space=>space.Id.IntegerValue.ToString());
|
|
|
+ spaceRelations.SetSetting(new BinaryCollectionSetting<Space, AdjanceElementType>()
|
|
|
+ {UpdateAction = (o, n) => o.Value | n.Value});
|
|
|
+ #region 本层关系处理
|
|
|
//展开空间关系数据
|
|
|
var flatSpaceItems = FlatSpaceEdges(Spaces);
|
|
|
var groupSpaces = flatSpaceItems.GroupBy(t => t.EdgeElement.Id.IntegerValue).ToList();
|
|
|
- var relation = CalcCombineRelations(groupSpaces.ToList().Select(g=>g.Key).ToList());
|
|
|
+ var relations = CalcCombineRelations(groupSpaces.ToList().Select(g => g.Key).ToList());
|
|
|
+ for (int i = 0; i < groupSpaces.Count; i++)
|
|
|
+ {
|
|
|
+ var baseSpace = groupSpaces[i];
|
|
|
+ var rels = relations.Where(c => !c.IsHandled && c.Contains(baseSpace.Key)).ToList();
|
|
|
+ List<SpaceEdgeInfo> refEdgeInfos = new List<SpaceEdgeInfo>(baseSpace.ToList());
|
|
|
+ foreach (var rel in rels)
|
|
|
+ {
|
|
|
+ rel.IsHandled = true;
|
|
|
+ var anotherId = rel.GetAnother(baseSpace.Key);
|
|
|
+ if (anotherId == baseSpace.Key)
|
|
|
+ {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ var anSpace = groupSpaces.FirstOrDefault(g => g.Key == anotherId);
|
|
|
+ if (anSpace != null)
|
|
|
+ {
|
|
|
+ refEdgeInfos.AddRange(anSpace.ToList());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ for (int j = 0; j < refEdgeInfos.Count; j++)
|
|
|
+ {
|
|
|
+ var baseEdge = refEdgeInfos[j];
|
|
|
+ for (int k =j + 1; k < refEdgeInfos.Count; k++)
|
|
|
+ {
|
|
|
+ var refEdge = refEdgeInfos[k];
|
|
|
+ var type = JudgeAdjancentSpace(baseEdge, refEdge);
|
|
|
+ if (type != AdjanceElementType.None)
|
|
|
+ {
|
|
|
+ BinaryRelationItem<Space, AdjanceElementType> item =
|
|
|
+ new BinaryRelationItem<Space, AdjanceElementType>(baseEdge.Space, refEdge.Space)
|
|
|
+ { Value = type };
|
|
|
+ spaceRelations.Update(item);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ #endregion
|
|
|
+
|
|
|
+ #region 整理关联数据
|
|
|
+ foreach (var binaryItem in spaceRelations)
|
|
|
+ {
|
|
|
+ SpaceRelatedEnum relationType= SpaceComputerManager.GetRelationEnum(binaryItem.Value);
|
|
|
+ var space1 = GetSpace(binaryItem.First, context);
|
|
|
+ space1.AdjacentSpaces.Add(new AdjacentSpace() {Space = context.NewSpace(binaryItem.Second),RelatedEnum= relationType });
|
|
|
+ var space2 = GetSpace(binaryItem.Second, context);
|
|
|
+ space2.AdjacentSpaces.Add(new AdjacentSpace() { Space = context.NewSpace(binaryItem.First), RelatedEnum = relationType });
|
|
|
+ }
|
|
|
+ #endregion
|
|
|
+ }
|
|
|
+ /// <summary>
|
|
|
+ /// 上下层空间关系解析
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="context"></param>
|
|
|
+ private void UpFloorParse(SpaceComputerContext context)
|
|
|
+ {
|
|
|
+ #region 上下层关系处理
|
|
|
+ /*1、从下往上计算,则可以利用现有缓存
|
|
|
+ 2、如果上一层是夹层,则继续找夹层的上一层,。处理这层中没有分配上下关系的空间
|
|
|
+ */
|
|
|
+ var currentDoc = Document;
|
|
|
+ var currentSpaces = this.ComputerSpaceItems;
|
|
|
+ currentSpaces.ForEach(c => c.IsHandled = false);
|
|
|
+ do
|
|
|
+ {
|
|
|
+ var floorId = currentDoc.PathName.GetFileName();
|
|
|
+ var upFloor = DalProjectTree.GetUpperFloor(floorId);
|
|
|
+ if (upFloor == null)
|
|
|
+ break;
|
|
|
+ var upFloorItems = context.GetFloorItems(upFloor.FullPath);
|
|
|
+ if (upFloorItems == null)
|
|
|
+ return;
|
|
|
+
|
|
|
+ var upSpaces = upFloorItems.ComputerSpaceItems;
|
|
|
+ foreach (var currentSpace in currentSpaces)
|
|
|
+ {
|
|
|
+ if (currentSpace.IsHandled)
|
|
|
+ continue;
|
|
|
+ var space1 = GetSpace(currentSpace.Space, context);
|
|
|
+ foreach (var upSpace in upSpaces)
|
|
|
+ {
|
|
|
+ var type= JudgeUpAdjancentSpace(currentSpace, upSpace);
|
|
|
+ if (type != AdjanceElementType.None)
|
|
|
+ {
|
|
|
+ currentSpace.IsHandled = true;
|
|
|
+ SpaceRelatedEnum relationType = SpaceComputerManager.GetRelationEnum(type);
|
|
|
+ var refSpace = context.NewSpace(upSpace.Space);
|
|
|
+ space1.UpElements.Add(new AdjacentSpace() { Space = refSpace, RelatedEnum = relationType });
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ if (upFloor.FloorType == "4") //夹层为4
|
|
|
+ {
|
|
|
+ currentDoc = upFloorItems.Document;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ } while (true);
|
|
|
+ #endregion
|
|
|
}
|
|
|
|
|
|
#region 展开空间与边界的关联关系
|
|
@@ -145,6 +354,7 @@ namespace SAGA.GplotRelationComputerManage.SpaceRelation
|
|
|
var doc = Document;
|
|
|
FilteredElementCollector collectors =
|
|
|
new FilteredElementCollector(doc, ids.Select(id => new ElementId(id)).ToList());
|
|
|
+ collectors.WhereElementIsNotElementType();
|
|
|
var calcElements = collectors.ToElements();
|
|
|
Dictionary<int, ElementGraphicItem> tempItems = new Dictionary<int, ElementGraphicItem>();
|
|
|
for (int i = 0; i < calcElements.Count; i++)
|
|
@@ -173,7 +383,7 @@ namespace SAGA.GplotRelationComputerManage.SpaceRelation
|
|
|
if (((outItem.Width + inItem.Width) / 2.0d).IsThanEq(length))
|
|
|
{
|
|
|
relations.Add(new BinaryRelationItem<int>(outElement.Id.IntegerValue,
|
|
|
- outElement.Id.IntegerValue));
|
|
|
+ inElement.Id.IntegerValue));
|
|
|
}
|
|
|
}
|
|
|
#endregion
|
|
@@ -234,5 +444,146 @@ namespace SAGA.GplotRelationComputerManage.SpaceRelation
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
+
|
|
|
+ #region 邻接关系判断
|
|
|
+ /// <summary>
|
|
|
+ /// 判断两个空间,在指定边上的相交关系
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="space1"></param>
|
|
|
+ /// <param name="space2"></param>
|
|
|
+ /// <returns></returns>
|
|
|
+ public AdjanceElementType JudgeAdjancentSpace(SpaceEdgeInfo space1, SpaceEdgeInfo space2)
|
|
|
+ {
|
|
|
+ var result=AdjanceElementType.None;
|
|
|
+ if(space1.Space.Id.IntegerValue==space2.Space.Id.IntegerValue)
|
|
|
+ return result;
|
|
|
+ /*先判断是否是虚拟墙。如果是实体墙,则进一步判断是否所有门窗之间的关系;
|
|
|
+ 两个space,可能不是公用一个Eelment,而是通过关联产生的
|
|
|
+ */
|
|
|
+ //平行直线和弧线的投影
|
|
|
+ var baseCurve = space1.Edge;//spac1的edge和space2的edge平行
|
|
|
+ Curve curve1 = GetProjectCurve(baseCurve, space1.SegEdge);
|
|
|
+ Curve curve2 = GetProjectCurve(baseCurve, space2.SegEdge);
|
|
|
+ IntersectionResultArray ira;
|
|
|
+ var isConn = curve2.Intersect(curve1, out ira) != SetComparisonResult.Disjoint;
|
|
|
+ if (!isConn||(ira != null && ira.Size == 1))
|
|
|
+ {
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+ #region 虚拟墙判断
|
|
|
+ var virType = typeof(ModelCurve);
|
|
|
+ if (space1.EType == virType && space2.EType == virType)
|
|
|
+ {
|
|
|
+ return AdjanceElementType.VirtualWall;
|
|
|
+ }
|
|
|
+ #endregion
|
|
|
+ result = AdjanceElementType.Wall;//必然墙相连
|
|
|
+ #region 门窗判断
|
|
|
+ List<Wall> walls = new List<Wall>();
|
|
|
+ foreach (var spaceEdgeInfo in new []{space1,space2})
|
|
|
+ {
|
|
|
+ if (spaceEdgeInfo.EType == typeof(Wall))
|
|
|
+ {
|
|
|
+ if (walls.Any(w => w.Id == spaceEdgeInfo.EdgeElement.Id))
|
|
|
+ {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ walls.Add(spaceEdgeInfo.EdgeElement as Wall);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (walls.Any())
|
|
|
+ {
|
|
|
+ result = result | AdjanceElementType.Wall;
|
|
|
+ var doors = new List<FamilyInstance>();
|
|
|
+ var windows = new List<FamilyInstance>();
|
|
|
+ foreach (var wall in walls)
|
|
|
+ {
|
|
|
+ List<FamilyInstance> tempDoors = new List<FamilyInstance>();
|
|
|
+ if (Doors.TryGetValue(wall.Id.IntegerValue.ToString(), out tempDoors))
|
|
|
+ {
|
|
|
+ doors.AddRange(tempDoors);
|
|
|
+ }
|
|
|
+ List<FamilyInstance> tempWindows = new List<FamilyInstance>();
|
|
|
+ if (Windows.TryGetValue(wall.Id.IntegerValue.ToString(), out tempWindows))
|
|
|
+ {
|
|
|
+ windows.AddRange(tempWindows);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ List<Curve> edgeCurves = new List<Curve>() {space1.SegEdge, space2.SegEdge};
|
|
|
+ if (doors.Any(d => edgeCurves.All(c => c.IsContain(c.GetProjectPt(d.GetLocationPoint())))))
|
|
|
+ {
|
|
|
+ result = result | AdjanceElementType.Door;
|
|
|
+ }
|
|
|
+ if (windows.Any(w => edgeCurves.All(c => c.IsContain(c.GetProjectPt(w.GetLocationPoint())))))
|
|
|
+ {
|
|
|
+ result = result | AdjanceElementType.Window;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ #endregion
|
|
|
+
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+ /// <summary>
|
|
|
+ /// 获取Curve1在Curve2上的投影【两线为平行关系的直线和弧线】【可简化】
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="projectCurve"></param>
|
|
|
+ /// <param name="curve"></param>
|
|
|
+ /// <returns></returns>
|
|
|
+ private Curve GetProjectCurve(Curve projectCurve, Curve curve)
|
|
|
+ {
|
|
|
+ var startPoint = projectCurve.GetProjectPt(curve.StartPoint());
|
|
|
+ var endPoint = projectCurve.GetProjectPt(curve.EndPoint());
|
|
|
+ if (projectCurve is Arc)
|
|
|
+ {
|
|
|
+ //弧形应该是法向投影
|
|
|
+ var middle = projectCurve.GetProjectPt((startPoint + endPoint) / 2);
|
|
|
+ return Arc.Create(startPoint, endPoint, middle);
|
|
|
+ }
|
|
|
+ return Line.CreateBound(startPoint, endPoint);
|
|
|
+ }
|
|
|
+ #endregion
|
|
|
+
|
|
|
+ #region 上下层关系判断
|
|
|
+ /// <summary>
|
|
|
+ /// 判断两个空间是否是上下相交关系
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="aFSpace"></param>
|
|
|
+ /// <param name="bSpace"></param>
|
|
|
+ /// <returns></returns>
|
|
|
+ public AdjanceElementType JudgeUpAdjancentSpace(ComputerSpaceItem aFSpace, ComputerSpaceItem bSpace)
|
|
|
+ {
|
|
|
+ AdjanceElementType result = AdjanceElementType.None;
|
|
|
+ if (!aFSpace.Box.Intersects(bSpace.Box, 0))
|
|
|
+ {
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+ if (ClosedIntersect(aFSpace.ZeroCurves, bSpace.ZeroCurves))
|
|
|
+ {
|
|
|
+ result = AdjanceElementType.Vertical;
|
|
|
+ if (SpaceComputerManager.IsCrossFunType(aFSpace.FuncType) && SpaceComputerManager.IsCrossFunType(bSpace.FuncType))
|
|
|
+ {
|
|
|
+ result = result | AdjanceElementType.VerticalOpening;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+ public bool ClosedIntersect(List<Curve> closed1, List<Curve> closed2)
|
|
|
+ {
|
|
|
+ //判断所有的线是否有相交
|
|
|
+ foreach (var curve1 in closed1)
|
|
|
+ {
|
|
|
+ if (curve1.IsIntersectPoly(closed2)) return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ //判断是否包含
|
|
|
+ foreach (var curve in closed1)
|
|
|
+ {
|
|
|
+ if (curve.StartPoint().PointInPolygon(closed2)) return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ return closed2.Any(curve => curve.StartPoint().PointInPolygon(closed1));
|
|
|
+ }
|
|
|
+ #endregion
|
|
|
}
|
|
|
}
|