Announcements
Notice: Upload of PDF documents is currently unavailable across the Community due to an ongoing issue.

Revit API: Automatically Resolving Wall Reinforcement Misalignment Between Floors

Revit API: Automatically Resolving Wall Reinforcement Misalignment Between Floors

tiezerqieutyune
Observer Observer
190 Views
4 Replies
Message 1 of 5

Revit API: Automatically Resolving Wall Reinforcement Misalignment Between Floors

tiezerqieutyune
Observer
Observer

Hi everyone,

I have been developing a Revit API / C# system for automated reinforced-concrete wall reinforcement.

The system is considerably larger than the particular example below, but I wanted to share one relatively small problem that I found interesting from an algorithmic point of view.

A deliberately difficult test case

For testing, I created two walls with different reinforcement layouts.

The lower wall uses vertical reinforcement at 100 mm spacing, while the walls above use 200 mm spacing.

I also deliberately shifted the upper walls so that the offset between the reinforcement grids is not a multiple of 100 mm.

In other words, the reinforcement grids between the floors do not simply line up.

wall1.jpg

 

Lower wall: 100 mm spacing

 

wall2.jpg

Upper walls: 200 mm spacing, with a deliberate offset

A simple approach would be to generate the reinforcement independently on each floor. But for a real structural system, this is not sufficient.

The reinforcement on one floor is related to the reinforcement on the floor below.

The algorithm therefore has to determine how the reinforcement from the lower floor can be connected to the reinforcement layout required on the floor above, despite the different spacing and the geometric offset.

The problem becomes more interesting when the wall geometry also changes between floors.

There may be:

  • different wall lengths or positions;

  • openings in different locations;

  • intersections with other walls;

  • slabs and beams crossing the wall;

  • different reinforcement requirements on different floors;

  • reinforcement already placed manually by the engineer.

So the task is not simply:

Wall → generate rebar

It is closer to:

Structural context → determine engineering constraints → find a compatible reinforcement layout → generate the Revit elements

In this particular test case, the program determines the required relationships between the reinforcement layouts rather than relying on the reinforcement grids being aligned.

This is only a small part of the overall wall reinforcement system, but I found it to be a good example of the kind of problems that appear when engineering logic is translated into automation.

I would be interested to hear how other Revit API developers approach similar problems.

When reinforcement layouts on adjacent floors have different spacing and their grids do not align, how do you model and resolve the relationship between the two reinforcement systems?

Do you approach this primarily as a geometric problem, as a rule-based engineering problem, or as a combination of both?

I would be especially interested in approaches that remain deterministic when the geometry becomes more complicated.

0 Likes
191 Views
4 Replies
Replies (4)
Message 2 of 5

sharafutdinov_di_dev
Enthusiast
Enthusiast

@tiezerqieutyune, interesting case. I haven't built this for walls, so below is how I would structure it rather than a tested solution. I'd treat it as a combination: geometry produces the candidates, rules choose between them, and the choice is made in a fixed order so the result is reproducible.

1. Give the joint its own bars. I wouldn't try to extend the lower wall's verticals into the upper wall or the other way round. Each wall keeps its own layout (100 mm below, 200 mm above, whatever offset), and the continuity is a separate set of starter/lap bars that belongs to the joint between the two walls. Then the joint is the only place that has to know about both layouts, and changing one floor doesn't ripple through the other.

2. Work in one coordinate along the wall. At the joint, project the vertical bars of both walls (per face) onto a single axis s, measured from a fixed origin, for example the start of the lower wall's location line. Everything after that is 1D:

  • the usable interval is the overlap of both walls minus covers;
  • openings near the joint, crossing beams and wall intersections just remove sub-intervals;
  • a change of wall length or position only changes the interval, not the algorithm.

3. Match upper bars to lower bars by rule. For every upper bar inside the interval, look for the nearest lower bar within a maximum lap offset. Under Eurocode 2 (8.7.2), for example, lapped bars should be no more than 4φ or 50 mm apart, otherwise the lap length grows by the excess. Then:

  • partner found: lap with it;
  • no partner: add a starter bar at the upper bar's position, anchored into the lower wall;
  • lower bars left without a partner stop below the joint with their own anchorage.

In your test case the upper spacing is a multiple of the lower one, so whatever the offset, every upper bar has a lower bar within 50 mm. Whether that counts as a lap or needs a starter bar is then purely a tolerance decision, which is exactly what you want to keep in the rules and not in the geometry code.

4. Make it deterministic on purpose.

  • Sort by s and break ties by a fixed rule (for example, always prefer the smaller s). Never rely on collector order or ElementId order.
  • Round coordinates to a fixed grid (1 mm, say) before any comparison, so floating point noise can't flip a match.
  • Bars placed manually by the engineer go into the lower set as fixed partners: the algorithm can lap onto them but never moves them.
  • Tag what you generate (Extensible Storage works well) so a rerun can compare against the previous result and update it, instead of deleting and recreating. Same input should give the same bars and the same ids.

5. Check what Revit actually placed. In a recent thread on beam rebar (Stacking rebars issue within intersected beams) I measured that Rebar.CreateFromCurves gives the bar default constraints, and after regeneration Revit moved longitudinal bars to the stirrup, ignoring the coordinates the script passed in. I haven't checked walls, but I'd assume the same can happen: compute the layout in your own model, then after Regenerate read the bars back and compare with what you asked for, and set explicit constraints where they drift.

How do you currently handle bars the engineer placed by hand: as fixed input like above, or do you regenerate around them?

Dinar Sharafutdinov · BIM coordinator · Revit API · Belgrade
Revit Model MCP   GitHub   LinkedIn   sharafutdinov.online
0 Likes
Message 3 of 5

tiezerqieutyune
Observer
Observer

Thank you for the detailed breakdown — this is exactly the kind of exchange I was hoping for.

I think we're describing the same logic from different angles. In my system, I don't physically extend a bar from the lower wall into the upper wall. Instead, I generate new bars in the upper wall and match them with the lower ones by rule: if a lower bar is within 50 mm of the upper bar, they're lapped. If there's no lower bar to connect to, the upper bar is anchored into the wall or slab. The lower bars stay where they are unless their anchorage length needs to change — in that case I recreate them with the new length and track their IDs to avoid conflicts.

Your point about working in one coordinate along the wall (point 2) — I do that too, but only in certain cases. The pictures above show one case where the two wall layouts are different and the offset is not a multiple of the spacing. That's the harder case. The simpler case — projecting upper walls onto lower walls and matching bars at intersections — I also handle, and that's what you see in the additional pictures below.

walls1.png

 

 

walls2.jpg
So both approaches exist in the system: the simple one for straightforward joints, and the more complex one for when the layouts don't line up.

On point 4 — I already treat manually placed bars as fixed input. The algorithm can lap onto them but never moves them. I also tag the bars I generate so a rerun can compare and update rather than delete and recreate.

But there's one thing I should explain better, because it's the core of how my system works. It has two stages:

Stage 1 — analysis and framework. The algorithm reads the entire building: all walls, floors, openings, beams, slabs, existing reinforcement, manually placed bars, everything. It computes the full structural context — how each wall relates to the next, how reinforcement from the floor below affects the floor above, where openings and intersections remove usable intervals. This is like planning a chess game several moves ahead: the system works out the whole configuration before placing a single bar.

Stage 2 — generation. Only after the full framework is computed does the system start placing bars. Each zone is built separately, but always with the pre-computed conditions and the already-placed elements in mind. Nothing is moved after this. Nothing is regenerated around. The bars are placed once, correctly, based on the full analysis.

That's why I don't see bars drifting after Regenerate — because I don't regenerate around them. I analyze first, then place. The only place I've had issues was with hooks on stirrups, and even that wasn't consistent.

My main rule in all my plugins has always been: maximum economy within the construction rules.

How do you handle the case where the wall layouts themselves don't line up — for example, when the upper wall is shifted and its reinforcement spacing is different, so there is no simple one-to-one correspondence between the bars?

0 Likes
Message 4 of 5

sharafutdinov_di_dev
Enthusiast
Enthusiast

@tiezerqieutyune , thanks, the two-stage split makes sense. On the shifted layout with a different spacing: I wouldn't look for a one-to-one correspondence at all. At the joint it is a 1D problem: two sorted lists of bar positions along the wall, lower and upper. What you need is an order-preserving matching between them with a cost, and that is solvable exactly with dynamic programming in O(n·m), so it stays deterministic.

For each upper bar there are two options, and a lower bar may also stay unused:

  • lap with a lower bar at clear distance d: cost is the extra lap length, 0 up to 4φ / 50 mm, then the excess (EC2 8.7.2(3));
  • starter bar at the upper bar's position: cost is its full length (lap + anchorage);
  • an unused lower bar stops below the joint with its own anchorage.
f[i][j] = min( f[i-1][j] + starter, f[i][j-1], f[i-1][j-1] + lap(|u_i - l_j|) )

With cost in kg of steel this is directly your "maximum economy within the rules". Rules like the share of bars lapped in one section go in as constraints or penalties, not into the geometry.

I checked it on synthetic layouts only (plain Python, not in Revit; φ12, lap 600 mm, starter 1100 mm), against "nearest free lower bar" with the same rules:

Lower / upper spacing, offsetUpper barsGreedy: starters, extra lapDP: starters, extra lap
100 / 200, 37 mm150, 0 mm0, 0 mm
200 / 150, 37 mm204, 2314 mm4, 56 mm
250 / 200, 80 mm152, 1548 mm2, 136 mm

Your test case (100 below, 200 above) is the easy one: every upper bar has a lower bar within 50 mm whatever the offset. It gets interesting when the lower grid is sparser than the upper one. Then the nearest-bar choice takes a lower bar a neighbour needs more, and the neighbour pays with a long lap.

Dinar Sharafutdinov · BIM coordinator · Revit API · Belgrade
Revit Model MCP   GitHub   LinkedIn   sharafutdinov.online
0 Likes
Message 5 of 5

tiezerqieutyune
Observer
Observer

Thanks for the suggestion, Dinar. I think the key issue is the problem formulation.

In actual RC detailing, the upper reinforcement layout is not an independent set of coordinates that can be matched to the lower bars. It must first be constructed according to the wall geometry, the positions of the boundary bars and the required uniform spacing. The first bar's position is determined by the geometry and the specified offsets; it is not a free optimization variable.

The objective is also different. I'm not minimizing lap length or the cost of matching two given sets of bars. I'm generating a constructible reinforcement layout while minimizing additional anchorage, subject to the applicable detailing rules and the constraints imposed by the reinforcement already present.

Your DP formulation may solve the matching problem you defined, but I don't see how it addresses the actual reinforcement design problem described in my post. In particular, it doesn't generate the upper layout or enforce uniform spacing.

My algorithm implements the detailing logic used by structural engineers; the challenge is formalizing the interdependent decisions involved, not simply matching two sets of coordinates.

If you've seen this generation problem solved in a different way, I'd be glad to hear it — but I think the starting point has to be the engineering logic, not the matching algorithm.

0 Likes