Purpose: To connect all unconnected walls together to meet drawing requirements. At first adopted depth traversal method found error: stack overflow, reason is too many loop layers. Later optimized traversal method using breadth traversal, problem solved. Below paste two ways to get walls and connect

Element.GetgeneratingElementIds This method can get connected walls, but haven’t experimented yet.

Regarding breadth traversal and depth traversal can refer to this blog: https://developer.51cto.com/art/202004/614590.htm


Common Structure:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/// <summary>
/// Return new Solid after offset to outside
/// </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;
}

Normal way, traverse each wall to get walls intersecting with wall

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
/*
* Connect walls in normal way
*/
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 after offset
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
}
}

Traverse way to get walls, here referred to linked list method. Using this method not only can get wall connection but also perform more operations according to corresponding relationship

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
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;
}