Skip to content

compas_tf.connectors ¤

Free-standing connector elements usable as boolean cutters or joiners.

Three light parametric solids that mirror the shapes already produced inside the floor model, but exposed as standalone, reusable elements:

  • :class:ConnectorBoxElement — a box (width x depth x height).
  • :class:ConnectorCylinderElement — a cylinder from an axis line + radius.
  • :class:ConnectorWedgeElement — a triangular wedge prism, like the contact wedges placed between the quarter slabs and the oculus.

Each one implements the standard :class:compas_model.elements.Element interface and additionally exposes boolean_geometry / boolean_geometries (the transformed cutter mesh), so it can drive a :class:compas_tf.solid_difference_modifier.SolidDifferenceModifier exactly like :class:compas_tf.wedge.WedgeElement and :class:compas_tf.joint_dowel.DowelElement do.

Classes¤

ConnectorBoxElement ¤

ConnectorBoxElement(width: float = 100.0, depth: float = 100.0, height: float = 100.0, transformation: Transformation | None = None, features: list | None = None, name: str | None = None)

A box-shaped connector centred on the element's local frame.

Parameters:

Name Type Description Default
width float

Box size along local X.

100.0
depth float

Box size along local Y.

100.0
height float

Box size along local Z.

100.0
transformation :class:`compas.geometry.Transformation`

Placement of the box in the model.

None
features list[:class:`ConnectorBoxFeature`]

Features of the connector.

None
name str

Name of the element.

None

Attributes¤

boolean_geometries property ¤
boolean_geometries: list

Cutter meshes contributed by the connector (one box).

boolean_geometry property ¤
boolean_geometry: Mesh

Cutter mesh with the element transformation applied.

box property ¤
box: Box

Box geometry in the element's local frame (centred on the origin).

ConnectorCylinderElement ¤

ConnectorCylinderElement(line: Line | None = None, radius: float = 50.0, sides: int = 16, transformation: Transformation | None = None, features: list | None = None, name: str | None = None)

A cylinder connector built from an axis line and a radius.

The cylinder is lofted between two sides-gon circles centred on the ends of line (given in the element's local frame), perpendicular to it.

Parameters:

Name Type Description Default
line :class:`compas.geometry.Line`

Cylinder axis in the element's local frame. Defaults to a 100 mm long axis along local Z.

None
radius float

Cylinder radius.

50.0
sides int

Number of polygon sides approximating the circle.

16
transformation :class:`compas.geometry.Transformation`

Placement of the cylinder in the model.

None
features list[:class:`ConnectorCylinderFeature`]

Features of the connector.

None
name str

Name of the element.

None

Attributes¤

axis property ¤
axis: Line

Axis line with the element transformation applied.

boolean_geometries property ¤
boolean_geometries: list

Cutter meshes contributed by the connector (one cylinder).

boolean_geometry property ¤
boolean_geometry: Mesh

Cutter mesh with the element transformation applied.

Methods:¤

compute_mesh ¤
compute_mesh() -> Mesh

Loft two circles along the axis line into a closed cylinder mesh.

ConnectorElement ¤

ConnectorElement(transformation: Transformation | None = None, features: list | None = None, name: str | None = None)

Rectangular connector box straddling the contact between two elements.

Local frame (before transformation):

  • +X runs across the joint, toward the rib. The box spans [-BACK, +FRONT] = [-140, +265] along X (140 into the column, 265 into the rib), split at the contact plane (local x = 0). The total length (405) is the longest dimension, so it points toward the rib.
  • +Y is horizontal along the contact face; the box is WIDTH = 21 wide, centred on the placement point.
  • +Z is up; the box top face is at local z = 0 and the body hangs down to z = -HEIGHT = -350.

Build one oriented to a contact with :meth:from_contact: the placement frame sits at the contact polygon's topmost point, with +X along the horizontal contact normal (flipped to point toward the rib) and +Z along world up.

Parameters:

Name Type Description Default
transformation :class:`compas.geometry.Transformation`

Places the local box in the model (typically a world frame).

None
features list[:class:`ConnectorFeature`]
None
name str
None

Methods:¤

add_cutters ¤
add_cutters(meshes: list, name: str = 'connector_cutters')

Store cutter solids (e.g. the dowel cylinders) as a difference feature.

The meshes must be in the connector's local frame. Stored as a :class:compas_tf.solid_difference_modifier.MeshCutFeature so the holes travel with the connector through copy/serialization.

cutter_mesh ¤
cutter_mesh(overshoot: float = 0.0) -> Mesh

The connector box in world coordinates (for boolean cutting).

overshoot grows the box ONLY at the top (local +Z, above z = 0) by that amount. The box top sits at the contact's top edge, which is coplanar with the column/rib top face - a cutter cap exactly coplanar with a target face makes the mesh boolean difference unreliable (the same reason the dowel cylinders overshoot, see :meth:cylinder_cutters), so the top is pushed past that surface. The bottom (z = -HEIGHT) is a BLIND pocket floor buried inside the material - extending it there would only cut the pocket deeper than the connector, so it is left flush. The in-plane (X/Y) footprint is unchanged. overshoot=0 returns the exact box (legacy behaviour).

Parameters:

Name Type Description Default
overshoot float

Extra length added at the TOP cap so the cut clears the coplanar top face cleanly (e.g. 25). The bottom is not extended.

0.0

Returns:

Type Description
class:`compas.datastructures.Mesh`
cylinder_cutters ¤
cylinder_cutters(length: float, overshoot: float = 25.0)

Cylindrical dowel cutters: two per side (column and rib).

A cylinder sits at each of the four positions from :meth:_dowel_grid (two sides x two rows), each held in from the box boundaries by EDGE_MARGIN_X * RADIUS horizontally and EDGE_MARGIN_Z * RADIUS vertically - column side near x = -BACK, rib side near x = +FRONT. Each cylinder's axis runs along the connector width (local Y), with the given length and radius :attr:RADIUS. The two sides carry the same vertical rows, just on opposite sides (so the female/male distinction does not change the geometry).

Each cutter is extended by overshoot at both ends so its flat caps clear the element surfaces: a cap exactly flush (coplanar) with a face makes the boolean difference unreliable. The clipped hole still spans the element; only the cutter overshoots, the nominal dowel length is length.

Parameters:

Name Type Description Default
length float

Cylinder length (e.g. the rib thickness).

required
overshoot float

Extra length added at each cap so the cut passes cleanly through.

25.0

Returns:

Type Description
tuple[list[:class:`compas.datastructures.Mesh`], list[:class:`compas.datastructures.Mesh`]]

(column_cutters, rib_cutters) as closed meshes in world coordinates - to subtract from the column and the rib respectively.

cylinder_elements ¤
cylinder_elements(length: float)

The four dowel cylinders as placed model elements (nominal length).

Same positions as :meth:cylinder_cutters - the shared :meth:_dowel_grid (a margin in from the box boundaries, axis along local Y) - but at the nominal length (no cutter overshoot); these are the real dowels, added to the model like the wedge components.

Parameters:

Name Type Description Default
length float

Cylinder length (e.g. the rib thickness).

required

Returns:

Type Description
list[:class:`DowelCylinderElement`]
from_contact classmethod ¤
from_contact(contact, toward, name: str | None = None) -> ConnectorElement

Create a connector oriented to a contact polygon.

Parameters:

Name Type Description Default
contact :class:`compas_model.interactions.Contact`

The contact whose polygon defines the placement.

required
toward :class:`compas.geometry.Point`

A point on the rib side (e.g. the rib element's centroid). The local +X axis (the contact normal, projected horizontal) is flipped to point toward it, so the longer 265 mm extent goes into the rib.

required
name str
None

Returns:

Type Description
class:`ConnectorElement`

ConnectorWedgeElement ¤

ConnectorWedgeElement(length: float = 160.0, cylinder_radius: float = 10.0, cylinder_spacing: float = 320.0, cylinder_sides: int = 12, transformation: Transformation | None = None, features: list | None = None, name: str | None = None)

The floor contact wedge (copied from :class:compas_tf.wedge.WedgeElement), exposed as a free connector that is sized and placed from an interface line.

The fixed triangular PROFILE (local YZ plane) is copied to x = -length/2 and x = +length/2 and lofted into a closed triangular prism — the exact wedge geometry used in example_2_floor_model_booleans.py. The dowel axis (DOWEL_START -> DOWEL_END) runs along local Y, and :meth:create_cylinders distributes :class:ConnectorCylinderElement dowels along the wedge length.

Parameters:

Name Type Description Default
length float

Prism length along local X (the wedge "target_length"). Usually set from the interface edge via :meth:from_interface / :meth:from_contact.

160.0
cylinder_radius float

Radius of the dowel cylinders.

10.0
cylinder_spacing float

Approximate spacing between dowels along the wedge length.

320.0
cylinder_sides int

Polygon resolution of the dowel cylinders.

12
transformation :class:`compas.geometry.Transformation`

Placement of the wedge in the model.

None
features list[:class:`ConnectorWedgeFeature`]

Features of the connector.

None
name str

Name of the element.

None

Attributes¤

boolean_geometries property ¤
boolean_geometries: list

Cutter meshes contributed by the connector (the wedge solid).

boolean_geometry property ¤
boolean_geometry: Mesh

Cutting geometry of the wedge — the wedge solid itself (model space), so a plate carved by it is identical to the WedgeElement cut in example_2. Use :meth:cutter_box instead for a box-shaped slot.

Methods:¤

build_mesh ¤
build_mesh() -> Mesh

Loft the fixed PROFILE between x = -length/2 and +length/2 (WedgeElement).

create_cylinders ¤
create_cylinders(horizontal: bool = True)

Distribute :class:ConnectorCylinderElement dowels along the wedge.

Mirrors WedgeElement.dowel_lines: the DOWEL axis (local Y) is copied to max(int(length / spacing), 1) evenly-spaced stations along local X.

By default the dowels are kept PARALLEL TO THE GROUND (world XY). The raw dowel direction is the wedge's local Y = the contact normal, so on an inclined wall (e.g. the oculus) the bolts would come out inclined with the face. With horizontal=True each dowel's world axis is projected onto the horizontal plane through its own centre - the faces stay inclined as they are, only the bolt direction is flattened - and the centre and nominal dowel length are preserved. On a vertical wall the contact normal is already horizontal, so this is a no-op. Pass horizontal=False for the perpendicular-to-face behaviour.

Parameters:

Name Type Description Default
horizontal bool

Flatten the dowel axes parallel to the world XY plane (default).

True

Returns:

Type Description
list[:class:`ConnectorCylinderElement`]
cutter_box ¤
cutter_box(through: float = 400.0, margin: float = 0.0) -> Mesh

Oriented BOX cutter aligned to the wedge — its cutting geometry.

The box is built in the wedge's local frame so its biggest face (local X-Z, length x profile-depth) coincides with the wedge's biggest side. It is made massive along local Y (through, the joint normal) so it slices clean through both plates, producing a straight rectangular slot rather than a triangular one. Size is intentionally generous — the boolean only removes the intersection.

Parameters:

Name Type Description Default
through float

Box extent along local Y (the cut-through direction).

400.0
margin float

Extra added to the X (length) and Z (depth) extents.

0.0

Returns:

Type Description
class:`compas.datastructures.Mesh`

The box cutter, with the wedge transformation applied (model space).

end_polylines ¤
end_polylines()

The wedge's two triangular end faces as co-wound closed polylines.

The prism is the PROFILE copied to x = -length/2 (bottom) and x = +length/2 (top); both use the same PROFILE order, so vertex i of the bottom matches vertex i of the top (same winding), exactly the (bottom, top) representation a plate uses. Returned in model space (the wedge transformation applied), to match :attr:boolean_geometry.

Returns:

Type Description
tuple(:class:`compas.geometry.Polyline`, :class:`compas.geometry.Polyline`)

The (bottom, top) end-face polylines.

from_contact classmethod ¤
from_contact(contact, length_margin=0.0, **kwargs)

Create a wedge from a contact's longest top edge (see :meth:interface_line).

from_interface classmethod ¤
from_interface(start, end, normal, length_margin=0.0, **kwargs)

Create a wedge centred on an interface edge.

The wedge frame is X = edge direction, Y = normal, Z = X cross Y, placed at the edge midpoint. The wedge length is the edge length minus 2 * length_margin (e.g. plate thickness), so it is driven by the interface line length.

Parameters:

Name Type Description Default
start point - like

Endpoints of the interface edge.

required
end point - like

Endpoints of the interface edge.

required
normal vector - like

Contact normal (becomes the wedge's local Y / cylinder axis).

required
length_margin float

Amount trimmed off each end of the edge to size the wedge length.

0.0
**kwargs

Forwarded to __init__ (cross-section + cylinder parameters).

{}
inclined_face_box_outlines ¤
inclined_face_box_outlines(depth=100.0, margin=0.0)

The (bottom, top) rectangle outlines of each inclined-face box.

Same boxes as :meth:inclined_face_boxes, but as their two large-face rectangles - bottom lying ON the incline, top depth into the plate - returned co-wound (vertex i of bottom matches vertex i of top), in model space. This is the minimal, parametric drilling / fabrication form: feed a pair to a :class:compas_tf.solid_difference_modifier.PrismCutFeature to get both the box cutter (the loft) and the outlines (its minimal). One pair per inclined face, in order [A-B, A-C].

inclined_face_boxes ¤
inclined_face_boxes(depth=100.0, margin=0.0)

One oriented box per INCLINED wedge face (the two slants A-B, A-C).

Each box's large face lies on the incline (box X = wedge length, box Y = the slant edge), and the box extends depth along that face's OUTWARD normal - into the plate the face meets. Returned in model space (wedge transform applied), so the box follows the inclined face exactly, with no extra transform needed. The two boxes are returned in face order [A-B, A-C] - one for each neighbour the wedge joins.

interface_line staticmethod ¤
interface_line(contact)

Return (start, end, normal) for a contact's longest top edge.

Mirrors the floor model's pick: collinear vertices are merged, edges whose midpoint is at/above the polygon centroid count as "top", and the longest such edge wins. normal is the contact polygon normal.

Parameters:

Name Type Description Default
contact :class:`compas_model.interactions.Contact`
required

Returns:

Type Description
tuple(:class:`compas.geometry.Point`, :class:`compas.geometry.Point`, :class:`compas.geometry.Vector`)

DowelCylinderElement ¤

DowelCylinderElement(radius=25.0, length=100.0, transformation=None, features=None, name=None)

A cylindrical dowel connector.

Like the wedge components, this is a real model element (visible, serialized) that is also used as a boolean cutter against the elements it joins. The cylinder is built along the local Y axis, centred at the origin, and placed by transformation.

Parameters:

Name Type Description Default
radius float

Cylinder radius.

25.0
length float

Cylinder length (the nominal dowel length, e.g. the rib thickness).

100.0
transformation :class:`compas.geometry.Transformation`
None
features list[:class:`Feature`]
None
name str
None

OuterRibConnectorElement ¤

OuterRibConnectorElement(transformation: Transformation | None = None, features: list | None = None, name: str | None = None)

Connector joining two quarters' outer ribs at a seam, from OBJ templates.

Unlike the parametric connectors above, this is a fixed fabrication shape modelled in Rhino and shipped as three OBJ files in data/OuterRibConnector/:

  • OuterRibConnector.obj — the connector body (the visible element);
  • OuterRibConnector_cut0.obj — the MALE boolean cutter, to subtract from the rib on the local -Y side;
  • OuterRibConnector_cut1.obj — the FEMALE boolean cutter, to subtract from the rib on the local +Y side.

The OBJs are modelled in the connector's LOCAL frame, deliberately offset so placement needs no further shifting:

  • local y = 0 is the rib-rib interface plane. The body spans y in [-400, +400] (one half into each rib) and each cutter overshoots the interface by 10, so no cutter cap is coplanar with a rib end face (a flush cap makes the boolean difference unreliable);
  • local +X points from the placement origin DOWN the rib end face; the body spans x in [138.5, 208.9], i.e. it hangs below the seam's top edge by that built-in offset;
  • local Z spans the rib thickness (z in [-15, +15]).

:meth:from_contact builds the matching placement frame: origin at the middle of the contact polygon's TOP edge, +X = world down, +Y = the horizontal contact normal.

Parameters:

Name Type Description Default
transformation :class:`compas.geometry.Transformation`

Places the local template in the model (see :meth:from_contact).

None
features list[:class:`compas_model.elements.element.Feature`]
None
name str
None

Methods:¤

cutter_for ¤
cutter_for(point) -> Mesh

The cutter (world coordinates) for the rib on point's side of the seam.

Parameters:

Name Type Description Default
point point - like

A world point identifying the rib, e.g. its centroid. On the connector's local -Y side it gets the MALE cutter, on the +Y side the FEMALE one.

required

Returns:

Type Description
class:`compas.datastructures.Mesh`
cutter_meshes ¤
cutter_meshes() -> tuple

The (male, female) boolean cutters in WORLD coordinates.

The male cutter carves the rib on the connector's local -Y side, the female cutter the rib on the +Y side. Use :meth:cutter_for to pick the right one for a given rib automatically.

from_contact classmethod ¤
from_contact(contact, name: str | None = None) -> OuterRibConnectorElement

Create a connector oriented to a rib-rib seam contact.

The placement frame: origin at the middle of the contact polygon's TOP edge, +X = world down (into the seam face), +Y = the horizontal contact normal — matching the local frame the OBJ templates are modelled in, so the templates land on the seam with no extra offsets.

Parameters:

Name Type Description Default
contact :class:`compas_model.interactions.Contact`

The seam contact between two outer ribs.

required
name str
None

Returns:

Type Description
class:`OuterRibConnectorElement`
template classmethod ¤
template(filename: str) -> Mesh

A fresh copy of one of the OBJ templates, in the connector's local frame.

The file is read once and cached at class level; every call returns an independent copy, so callers can transform it freely.