post-and-beam housing, and I have been driving Archicad entirely from
Python to build our structural models.
I would like to share the result and, more usefully for this board,
the places where I got stuck.
Video (23 min, uncut, English subtitles):
■ What it does
Input is an IFC exported from Japanese structural-calculation software.
The tools read coordinates and attributes straight out of that IFC - it is
never imported into Archicad as a model - and build the entire frame:
foundation, sills, girders, packers, anchor bolts, hold-downs, floor posts
and sheathing, 51 columns, 37 studs, window sills and lintels, braces,
shear panels, roof beams, purlins, sloped beams, dovetail joints, splices,
34 roof struts and their connectors, 54 rafters, 60 roof panels, barge and
fascia boards, 270 rafter notches, 70 screws and 200 nails.
54 steps, about 23 minutes, 1,549 elements and operations, no manual input.
The 2D symbols and section representations are built into the GDL objects,
so the structural framing plans and structural sections come out at the same
time as the model. There is no separate documentation pass.
■ Stack
- Archicad 29
- Tapir add-on - I use its JSON commands from its Python execution
environment (so this is Tapir's API rather than the official Python API;
mentioning it because the two get conflated)
- Python for all the layout logic
- A small in-house C++ add-on for a handful of things I could not reach
from Python (details below)
■ Structure of the tools
Every element a tool creates gets a custom property acting as a managed
link, roughly ACSYNC:<tool>:<key>. The tool owns exactly the elements
carrying its own links and nothing else.
That one decision made the rest work:
- re-running a tool queries existing links first, then creates only what is
missing, removes what is no longer planned, and leaves unchanged elements
alone. When the structural calculation is revised, you swap the IFC and
run again.
- anything without a link - hand-placed elements, hotlinked existing
buildings - is never touched.
Once built, the tools need no AI and no network. The video is a single
runner executing 54 steps in order, deterministically.
■ The traps that cost me the most time
1. New elements inherit the tool's current defaults.
This was the single biggest source of bugs, and it took a while to see that
several unrelated symptoms had one cause. Placement angle, beam profile
dimensions, building material, GDL A/B values, even stale custom property
values are inherited from whatever the tool defaults happen to be at that
moment.
Concretely: I ran the foundation step, then the sill step, and the sills
came out 150 x 700 - the cross section of the foundation stem wall. Width
and height passed to the beam creation call were silently ignored because
the beams carried a profile.
The fix that generalises: clean up a favorite for each element type and
apply it to the defaults before creating anything.
2. GDL A/B are multipliers, not sizes.
Sending 0.910 to a brace gave me 828.1 mm. The value is applied against the
object's nominal dimension. My tools now send 1.0 first, read back the
resulting nominal, and then send target/nominal. ZZYZX behaves normally, for
what it is worth.
3. Reading a value back does not mean you verified it.
The one that really got me. A beam's anchor point decides where the body
sits relative to the reference line. I had it wrong, and every coordinate
read-back matched my expected values perfectly - because the coordinate
returned IS the reference line. The body was half a beam width off and no
positional check could see it.
Rafters run +X on the west face and -X on the east, so left and right
flipped and the two faces ended up 45 mm apart - exactly one rafter width.
I only found it by measuring the actual solid with Get3DBoundingBoxes and
comparing the real centre against the reference line.
Since then every tool verifies by measuring geometry, not by re-reading the
value it just wrote.
One caveat on that: bounding boxes can return stale values until the 3D is
rebuilt. I lost time chasing a panel that reported the wrong length and was
in fact correct.
■ What I could not do from Python
I ended up adding a small C++ add-on for these:
- read and write a beam's anchor point
- read how a beam end is cut (square to the run, vertical, horizontal)
- strip a profile off a beam and set plain width / depth / building material
- change an element's layer
- switch the active story
All of them are cases where a value existed but was not reachable, and
therefore could not be verified. My rule became: if I cannot read it,
I add a way to read it.
■ Note
This is in-house work for our own projects, not a product, and it carries
conventions specific to how we build. Sharing it as a data point on how far
Python-driven Archicad can be taken.
■ Questions for this board
- Has anyone else hit the inherited-defaults behaviour, and is there a
cleaner way to neutralise it than applying a favorite?
- For those doing large batch creation: what do you use as your verification
strategy? I would like to hear approaches other than measuring geometry.