|
@@ -10,8 +10,11 @@ using System.Text;
|
|
|
using System.Threading.Tasks;
|
|
|
using Autodesk.Revit.DB;
|
|
|
using Autodesk.Revit.DB.Mechanical;
|
|
|
+using JBIM.Definition;
|
|
|
+using RevitToJBim.Common;
|
|
|
using SAGA.RevitUtils;
|
|
|
using SAGA.RevitUtils.Extends;
|
|
|
+using XYZ = Autodesk.Revit.DB.XYZ;
|
|
|
|
|
|
namespace RevitToJBim.Extension
|
|
|
{
|
|
@@ -85,5 +88,215 @@ namespace RevitToJBim.Extension
|
|
|
}
|
|
|
return space.Level?.Id == useViewId.GenLevel?.Id;
|
|
|
}
|
|
|
+
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 获取空间的外轮廓
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="space"></param>
|
|
|
+ /// <returns></returns>
|
|
|
+ public static List<Polygon> GetSpaceOutline(this Space space)
|
|
|
+ {
|
|
|
+ List<Polygon> outlines=new List<Polygon>();
|
|
|
+ try
|
|
|
+ {
|
|
|
+ SpatialElementBoundaryOptions options = new SpatialElementBoundaryOptions();
|
|
|
+ //options.SpatialElementBoundaryLocation = SpatialElementBoundaryLocation.Finish;
|
|
|
+ var segments = space.GetBoundarySegments(options);
|
|
|
+ double tolerance = space.Document.Application.ShortCurveTolerance;
|
|
|
+ foreach (var segment in segments)
|
|
|
+ {
|
|
|
+ #region 取外轮廓的点
|
|
|
+
|
|
|
+ List<XYZ> xyzs = new List<XYZ>();
|
|
|
+ foreach (BoundarySegment boundarySegment in segment)
|
|
|
+ {
|
|
|
+ var segmentElement = space.Document.GetElement(boundarySegment.ElementId);
|
|
|
+ if (segmentElement is Wall wall)
|
|
|
+ {
|
|
|
+ var wallCurve = wall.GetLocationCurve();
|
|
|
+ var parallelWalls = GetParallelWalls(wall);
|
|
|
+ var segmentCurve = boundarySegment.GetCurve();
|
|
|
+ var tessellates = segmentCurve.Tessellate();
|
|
|
+ foreach (XYZ tessellate in tessellates)
|
|
|
+ {
|
|
|
+ var project = wallCurve.GetProjectPt(tessellate);
|
|
|
+ var verticalVector = (project - tessellate).Normalize();
|
|
|
+ var tempXyz = GetOuterXYZ(tessellate, verticalVector, segmentCurve, parallelWalls);
|
|
|
+ if (tempXyz != null)
|
|
|
+ xyzs.Add(tempXyz);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ foreach (XYZ tessellate in boundarySegment.GetCurve().Tessellate())
|
|
|
+ {
|
|
|
+ xyzs.Add(tessellate);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ #endregion
|
|
|
+
|
|
|
+ #region 处理内拐角
|
|
|
+
|
|
|
+ int count = xyzs.Count;
|
|
|
+ /*
|
|
|
+ * 相邻两条线求交点
|
|
|
+ * 处理内拐角
|
|
|
+ */
|
|
|
+ for (int i = 0; i < count; i++)
|
|
|
+ {
|
|
|
+ if (count < 4) continue;
|
|
|
+ var p1 = xyzs[i];
|
|
|
+ int j2 = i + 1 >= xyzs.Count ? i + 1 - count : i + 1;
|
|
|
+ var p2 = xyzs[j2];
|
|
|
+ int j3 = i + 2 >= xyzs.Count ? i + 2 - count : i + 2;
|
|
|
+ var p3 = xyzs[j3];
|
|
|
+ int j4 = i + 3 >= xyzs.Count ? i + 3 - count : i + 3;
|
|
|
+ var p4 = xyzs[j4];
|
|
|
+ if (p2.IsEqual(p3) || p1.DistanceTo(p2) < tolerance || p3.DistanceTo(p4) < tolerance)
|
|
|
+ continue;
|
|
|
+ Curve curve1 = Line.CreateBound(p1, p2);
|
|
|
+ Curve curve2 = Line.CreateBound(p3, p4);
|
|
|
+ XYZ intersection = curve1.GetIntersection(curve2);
|
|
|
+ if (intersection == null) continue;
|
|
|
+ xyzs[j2] = intersection;
|
|
|
+ xyzs[j3] = intersection;
|
|
|
+ }
|
|
|
+
|
|
|
+ #endregion
|
|
|
+
|
|
|
+ //添加起始点,形成闭合区域
|
|
|
+ if (xyzs.Any())
|
|
|
+ xyzs.Add(xyzs[0]);
|
|
|
+
|
|
|
+ //整理数据
|
|
|
+ Polygon outLine = new Polygon();
|
|
|
+ var usePoints = xyzs.Select(xyz => BimConvert.ConvertToXYZ(xyz)).ToList();
|
|
|
+ outLine.AddRange(usePoints.GetRange(0, usePoints.Count - 1));
|
|
|
+ StandardUtil.ArrangeLoop(outLine);
|
|
|
+ outlines.Add(outLine);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ catch (Exception e)
|
|
|
+ {
|
|
|
+ Console.WriteLine(e);
|
|
|
+ throw;
|
|
|
+ }
|
|
|
+
|
|
|
+ return outlines;
|
|
|
+ }
|
|
|
+
|
|
|
+ private static double m_RedundancySpace = 10d;
|
|
|
+ /// <summary>
|
|
|
+ /// 获取平行墙,平行且投影有重叠部分
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="wall"></param>
|
|
|
+ /// <returns></returns>
|
|
|
+ public static List<Wall> GetParallelWalls(Wall wall)
|
|
|
+ {
|
|
|
+ List<Wall> walls = new List<Wall>();
|
|
|
+ walls.Add(wall);
|
|
|
+ var doc = wall.Document;
|
|
|
+ var allWalls = doc.GetElements<Wall>();
|
|
|
+ var curve = wall.GetLocationCurve();
|
|
|
+ var parallelWalls = allWalls.Where(t => t.GetLocationCurve().IsParallel(curve));
|
|
|
+
|
|
|
+ int len = walls.Count;
|
|
|
+ do
|
|
|
+ {
|
|
|
+ len = walls.Count;
|
|
|
+ foreach (Wall parallelWall in parallelWalls)
|
|
|
+ {
|
|
|
+ var curve1 = parallelWall.GetLocationCurve();
|
|
|
+ var startP11 = CurveExtend.StartPoint(curve1);
|
|
|
+ var endP11 = CurveExtend.EndPoint(curve1);
|
|
|
+ double width1 = parallelWall.Width.FromApi();
|
|
|
+ for (int i = 0; i < walls.Count; i++)
|
|
|
+ {
|
|
|
+ Wall referenceWall = walls[i];
|
|
|
+ if (walls.Contains(parallelWall)) continue;
|
|
|
+ var curve2 = referenceWall.GetLocationCurve();
|
|
|
+ var startP12 = CurveExtend.GetProjectPt(curve2, startP11);
|
|
|
+ var endP12 = CurveExtend.GetProjectPt(curve2, endP11);
|
|
|
+ var startP21 = CurveExtend.StartPoint(curve2);
|
|
|
+ var endP21 = CurveExtend.EndPoint(curve2);
|
|
|
+ var startP22 = CurveExtend.GetProjectPt(curve1, startP21);
|
|
|
+ var endP22 = CurveExtend.GetProjectPt(curve1, endP21);
|
|
|
+ //判断是否有重叠部分
|
|
|
+ if (startP12.IsOnCurve(curve2) || endP12.IsOnCurve(curve2) || startP22.IsOnCurve(curve1) ||
|
|
|
+ endP22.IsOnCurve(curve1))
|
|
|
+ {
|
|
|
+ double width2 = referenceWall.Width.FromApi();
|
|
|
+ double distacne = curve1.Distance(curve2).FromApi();
|
|
|
+ if (distacne < (width1 + width2) / 2.0 + m_RedundancySpace)
|
|
|
+ walls.Add(parallelWall);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } while (len != walls.Count);
|
|
|
+
|
|
|
+ return walls;
|
|
|
+ }
|
|
|
+ /// <summary>
|
|
|
+ /// 获取外廓后的点
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="xyz">外廓点</param>
|
|
|
+ /// <param name="verticalVector">外廓向量</param>
|
|
|
+ /// <param name="segmentCurve">参考Curve</param>
|
|
|
+ /// <param name="walls">平行墙集合</param>
|
|
|
+ /// <returns></returns>
|
|
|
+ public static XYZ GetOuterXYZ(XYZ xyz, XYZ verticalVector, Curve segmentCurve, List<Wall> walls)
|
|
|
+ {
|
|
|
+ XYZ outerXyz = xyz;
|
|
|
+ double distance = 0;
|
|
|
+ foreach (Wall wall in walls)
|
|
|
+ {
|
|
|
+ /*
|
|
|
+ * 注意幕墙,没有底面,直接取原始点xyz
|
|
|
+ */
|
|
|
+ List<PlanarFace> faces = wall.GetBottomFaces();
|
|
|
+ foreach (PlanarFace face in faces)
|
|
|
+ {
|
|
|
+ foreach (CurveLoop curveLoop in face.GetEdgesAsCurveLoops())
|
|
|
+ {
|
|
|
+ foreach (Curve curve in curveLoop)
|
|
|
+ {
|
|
|
+ /*
|
|
|
+ * 1. 获取平行边
|
|
|
+ * 2. 平行边求投影,投影点形成向量为向外
|
|
|
+ * 3. 投影点在线上
|
|
|
+ */
|
|
|
+ if (!segmentCurve.IsParallel(curve))
|
|
|
+ continue;
|
|
|
+ var projectPt = curve.GetProjectPt(xyz);
|
|
|
+ var tempVector = (projectPt - xyz).Normalize();
|
|
|
+ if (projectPt.IsOnCurve(curve) && !projectPt.IsEqual(xyz) && tempVector.IsEqual(verticalVector))
|
|
|
+ {
|
|
|
+ var tempDistance = xyz.DistanceTo(projectPt);
|
|
|
+ if (tempDistance >= distance)
|
|
|
+ {
|
|
|
+ distance = tempDistance;
|
|
|
+ outerXyz = projectPt;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ /*
|
|
|
+ * 无投影点,给个默认投影点的情况
|
|
|
+ * 处理斜边投影不到的情况边上的情况,
|
|
|
+ * 目前任意取了一个,多个取最近的??
|
|
|
+ */
|
|
|
+ if (outerXyz == null || outerXyz.IsEqual(xyz))
|
|
|
+ outerXyz = projectPt;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return outerXyz;
|
|
|
+ }
|
|
|
}
|
|
|
}
|