目的:是为了将所有没有连接到一起的墙体进行连接,满足出图要求,刚开始采用深度遍历的方式发现会报错:堆栈溢出,原因是循环层数太多导致,之后优化了一下遍历方式使用广度遍历,问题解决。下面贴出两种获取墙体并连接的方式
Element.GetgeneratingElementIds这个方法可以获得连接墙体,但是没有试验过。
关于广度遍历与深度遍历可以参照下面这个博客:https://developer.51cto.com/art/202004/614590.htm
共用结构:
/// <summary>
/// 返回向外侧偏移后的新Solid
/// </summary>
/// <param name="curves"></param>
/// <param name="offset"></param>
/// <param name="extrusion"></param>
/// <returns></returns>
private Solid CreateNewSolid(List<CurveLoop> curves, double offset, double extrusion)
{
List<CurveLoop> nCurveLoops = new List<CurveLoop>();
foreach (var curve in curves)
{
var cp = CurveLoop.CreateViaOffset(curve, offset / 304.8, new XYZ(0, 0, -1));
nCurveLoops.Add(cp);
}
var solid = GeometryCreationUtilities.CreateExtrusionGeometry(nCurveLoops, new XYZ(0, 0, 1), extrusion);
return solid ?? null;
}
普通方式,遍历每个墙获取于墙相交的墙体
/*
* 普通方式连接墙体
*/
void UnionWall(Wall wall, List<Wall> walls)
{
try
{
var e = BIMTools.Geometry.GetFace(wall, BIMTools.Geometry.FaceNormal.Bottom);
var loops = e.GetEdgesAsCurveLoops();
var para = wall.get_Parameter(BuiltInParameter.HOST_AREA_COMPUTED);
var vPara = wall.get_Parameter(BuiltInParameter.HOST_VOLUME_COMPUTED);
var area = para.AsDouble();
var volume = vPara.AsDouble();
Solid ss = BIMTools.Geometry.GetSolid(wall);
var height = volume / area;
var solid = CreateNewSolid(loops.ToList(), 10, 2950 / 304.8); //偏移后的Solid
List<Wall> nWalls = new List<Wall>();
nWalls.AddRange(walls);
var bWall = nWalls.Remove(walls.FirstOrDefault(x => x.Id == wall.Id));
if (nWalls.Count > 1 && bWall)
{
foreach (var w in nWalls)
{
var s = BIMTools.Geometry.GetSolid(w);
if (s != null && solid != null)
{
Solid intersect =
BooleanOperationsUtils.ExecuteBooleanOperation(solid, s,
BooleanOperationsType.Intersect);
if (intersect.Volume > 0.0001)
{
try
{
if (!JoinGeometryUtils.AreElementsJoined(_document, wall, w))
{
JoinGeometryUtils.JoinGeometry(_document, wall, w);
wIds.Add(w.Id);
}
else
{
wIds.Add(w.Id);
}
wIds.Add(w.Id);
}
catch (ArgumentException)
{
}
}
}
}
}
}
catch (Exception)
{
// ignored
}
}
遍历方式获取墙体,这里参考了链表的方式,使用这种方式不仅可以获取墙体连接还可根据相应的对应关系进行更多的操作
public class BFS
{
public Wall _wall { get; private set; }
public bool _isIntersect { get; private set; }
private List<BFS> _next;
public BFS(Wall wall, bool isIntersect=false)
{
_wall = wall;
_isIntersect = isIntersect;
_next = new List<BFS>();
}
public void PutNode(BFS bfs)
{
if(bfs==null) throw new ArgumentNullException($"paramater:bfs is null");
if (_next.Count == 0) _next = new List<BFS>();
_next.Add(bfs);
}
public void PutNode(List<BFS> bfss)
{
_next.AddRange(bfss);
}
public void DeleteNode(BFS bfs)
{
if(_next.Count==0) throw new ArgumentException($"paramater:_next is null");
var b = _next.FirstOrDefault(x => x._wall.Id.Equals(bfs._wall.Id));
_next.Remove(b);
}
public List<BFS> GetNextNode() => _next;
}
public List<BFS> GetInsertWalls(Wall wall,List<Wall> walls)
{
if(wall==null) throw new ArgumentNullException($"paramater:wall is null");
if (walls.Count==0) throw new ArgumentNullException($"paramater:walls is null");
var f = BIMTools.Geometry.GetFace(wall, Geometry.FaceNormal.Bottom);
var loops = f.GetEdgesAsCurveLoops();
var solid = CreateNewSolid(loops.ToList(), 10, 3000 / 304.8);
List<BFS> intersectWalls = new List<BFS>();
foreach (var wall1 in walls)
{
if(wall1.Id.Equals(wall.Id)) continue;
var s = BIMTools.Geometry.GetSolid(wall1);
if (solid != null && s != null)
{
Solid intersect =
BooleanOperationsUtils.ExecuteBooleanOperation(solid, s, BooleanOperationsType.Intersect);
if (intersect.Volume > 0.0001)
{
BFS bfs = new BFS(wall1);
intersectWalls.Add(bfs);
}
}
}
return intersectWalls;
}