How can I retrieve the wall graph from the Revit API?
I am trying to retrieve the wall connections or wall graph from a Revit drawing using the API. In AutoCAD Architecture, this is exposed through the wall graph class. Is there any corresponding object that I can use in Revit to give me this information?
The LocationCurve ElementsAtJoin property returns all the connected walls that join a wall at its two end points. You can retrieve the wall's location curve though its Location property. Here is some sample code implementing a new external command class CmdWallNeighbours that demonstrates this:
public CmdResult Execute( ExternalCommandData commandData, ref string message, ElementSet elements ) { Application app = commandData.Application; Document doc = app.ActiveDocument; List<Element> walls = new List<Element>(); if( !Util.GetSelectedElementsOrAll( walls, doc, typeof( Wall ) ) ) { Selection sel = doc.Selection; message = ( 0 < sel.Elements.Size ) ? "Please select some wall elements." : "No wall elements found."; return CmdResult.Failed; } int i, n; string desc, s = null; List<Element> neighbours; foreach( Wall wall in walls ) { desc = Util.ElementDescription( wall ); LocationCurve c = wall.Location as LocationCurve; if( null == c ) { s = desc + ": No wall curve found."; } else { s = string.Empty; for( i = 0; i < 2; ++i ) { neighbours = c.get_ElementsAtJoin( i ); n = neighbours.Count; s += string.Format( "\n\n{0} {1} point has {2} neighbour{3}{4}", desc, (0 == i ? "start" : "end"), n, Util.PluralSuffix( n ), Util.DotOrColon( n ) ); foreach( Wall nb in neighbours ) { s += "\n " + Util.ElementDescription( nb ); } } } Util.InfoMsg( s ); } return CmdResult.Failed; }
Unfortunately, if two walls intersect in the middle of one of them, there is no API call to retrieve the connected wall.
Thanks to Chris Arps of Ameri-CAD Inc. for raising this issue, and Joe Ye of Autodesk for providing the answer.
Note that if a wall has at least one neighbour at one end, then the list of joined elements will include the wall itself as well, so that you get either zero neighbours or two or more, and one of them is the wall itself, which obviously can be filtered away from the list.
Here is the result of running this command on a small rectangular house with four walls:
Walls <127248 Jt> start point has 2 neighbours: Walls <127248 Jt> Walls <127251 Jt> Walls <127248 Jt> end point has 2 neighbours: Walls <127248 Jt> Walls <127249 Jt> Walls <127249 Jt> start point has 2 neighbours: Walls <127248 Jt> Walls <127249 Jt> Walls <127249 Jt> end point has 2 neighbours: Walls <127249 Jt> Walls <127250 Jt> Walls <127250 Jt> start point has 2 neighbours: Walls <127249 Jt> Walls <127250 Jt> Walls <127250 Jt> end point has 2 neighbours: Walls <127250 Jt> Walls <127251 Jt> Walls <127251 Jt> start point has 2 neighbours: Walls <127250 Jt> Walls <127251 Jt> Walls <127251 Jt> end point has 2 neighbours: Walls <127248 Jt> Walls <127251 Jt>
Here is the result of running it on a set of only two walls joined at their common end point:
Walls <127876 Jt> start point has 0 neighbours. Walls <127876 Jt> end point has 2 neighbours: Walls <127876 Jt> Walls <127933 Jt> Walls <127933 Jt> start point has 2 neighbours: Walls <127876 Jt> Walls <127933 Jt> Walls <127933 Jt> end point has 0 neighbours.
Here is an updated version 1.0.0.14 of the complete Visual Studio solution, including the new CmdWallNeighbours and all other commands discussed so far.
Note that this algorithm only reports the wall endpoint connections. If midpoint connections are required as well, some other algorithm will have to be used. The first idea that comes to mind is to retrieve all the wall center lines and treat is as a segment intersection problem in the plane: given a set S of n closed segments in the plane, report all intersection points among the segments in S. This doesn't seem like a challenging problem: one can take each pair of segments, compute whether they intersect, and, if so, report their intersection point. This brute force algorithm requires O(n^2) time. This is not a practical algorithm in real life. Wei Qian describes a more efficient sweep line algorithm for segment intersection which is O((n + i) log n), where i is the number of intersection points of segments in S. Obviously, one would have to sort the various wall center lines into different buckets for separate buildings and levels and possibly other relevant groupings before feeding them into such a algorithm.
Hi Jeremy,
I urgently need your help, I managed to get my ACA 2011 working with VS 2010 Express (thanks to your valuable posts), and started working on ACA.NET after watching your 2 last web-casts. I am facing a problem with the Graph class when running AecWallSystemSampleMgd (see code below)
Manager mgr = new Manager(db);
Graph theGraph = mgr.FindGraph(wall);
I am always getting null value for theGraph object, when I debug the mgr.GraphCount is always 0.
I need the Joints,Sections and Connections to develop automatic details generation of ICF system.
Any help in this regard will be highly appreciated and also if you have any resource regarding ICF wall system in ACA would be very helpful
Posted by: Ray Colins | December 21, 2010 at 11:55
Dear Ray,
Congratulations on getting it up and running in VS Express and thank you for the appreciation. I am glad that the posts were useful.
I am sorry to say that I currently don't do that much with ACA, and I have no idea why your call might be returning null.
I suggest that you log a query with ADN DevHelp Online, if you are a member, and otherwise try your luck on the other Autodesk and AUGI forums:
http://thebuildingcoder.typepad.com/blog/2009/10/revit-api-forums.html
Cheers, Jeremy.
Posted by: Jeremy Tammik | December 22, 2010 at 08:16
Hi Jeremy,
The issue of intersecting walls is problematic. The trick would be to insert a pre-processing step to identify intersecting walls and split the secondary wall (if it can be identified) into two walls--it makes sense to do so from a construction standpoint although from a drafting standpoint, it makes things more cumbersome since you now have to drag multiple walls instead of one when adjusting the design.
Posted by: Chuck Han | June 27, 2011 at 19:28
Dear Chuck,
Yes, sounds feasible to me. Also, please note that in Revit 2012, you have the option to allow and disallow wall end joins.
"The new WallUtils class methods DisallowWallJoinAtEnd, AllowWallJoinAtEnd and IsWallJoinAllowedAtEnd provide access to the setting for whether or not joining is allowed at a particular end of the wall. If joins exist at the end of a wall and joins are disallowed, the walls will become disjoint. If joins are disallowed for the end of the wall, and then the setting is toggled to allow the joins, the wall will automatically join to its neighbors if there are any."
Cheers, Jeremy.
Posted by: Jeremy Tammik | June 29, 2011 at 06:14
FYI, I've come across a couple of examples where walls are joined at a T, if I select one of the walls, neighbors.count is 2 (if I delete the wall that is reported as joined, neighbors.count is still 2, so the regenerated wall graph thinks the remaining wall is joined to the selected wall). Unfortunately, I can't show you the file as it is proprietary :-( Have you come across this situation?
Posted by: Chuck Han | July 26, 2011 at 12:32
Dear Chuck,
The ElementsAtJoin method will only report neighbours at the end points of the wall location curve; the Revit API help file states:
"Get all elements joining to the end of this element's location curve or change the order of elements participation in the end join with this location curve's end."
Therefore, if walls join in a T shape, the wall connecting at the midpoint will never be reported by this method.
To detect neighbour walls which do not connect at the endpoint of the location curve, you can use an intersection filter, e.g. as shown by the Geometry2012 sample demonstrating the new Boolean operations available in the Revit 2012 API and presented at the last DevDays conferences:
http://thebuildingcoder.typepad.com/blog/2011/04/devdays-2010-online-with-revit-2012-api-news.html#3
Cheers, Jeremy.
Posted by: Jeremy Tammik | July 27, 2011 at 19:12