Skip to main content

Replicate

replicate() copies a mated part — or a mated sub-assembly — onto new mate targets. It is the "copy with mates" of other CAD systems, not a geometric pattern: every replica gets the seed's mates re-targeted to its own references, so the four standoffs on a plate each sit in their own hole and move on their own.

In the viewport​

  1. Mate the first instance the way every copy should be mated — the seed.
  2. Click Replicate on the assembly toolbar and pick the seed.
  3. The dialog lists the seed's outer mate sides — the connectors or faces on other parts its mates reference. For each replica, pick the replacement for each one.
  4. Or click Suggest copies. It fills one row per connector the seed could move to: when the connector the seed is mated to has copies, its other copies, in slot order; otherwise the part's other connectors. Connectors a mate already uses are skipped.
  5. Click Apply. The replicas appear as ordinary rows in the Parts panel, named after the seed with a suffix, marked as replicas.

Four standoffs replicated onto the plate's mounting holes

The code behind it

The plate declares one hole connector and copies it onto the other three holes, so the rows name hole.instance(1) to hole.instance(3) — the rows Suggest copies proposes for this seed.

standoff.part.js
standoff.part.js
import { part, sketch, circle, extrude, chamfer, color, connector } from 'fluidcad/core';

// A Ø8 × 15 standoff with a Ø4 through hole, chamfered on top.
export const standoff = part('Standoff', () => {
sketch('xy', () => {
circle([0, 0], 8);
circle([0, 0], 4);
});
const body = extrude(15);
chamfer(0.5, body.endEdges());
color('goldenrod');
// The foot: the face that sits on a mounting hole.
connector('foot', body.startFaces());
});
plate.part.js
plate.part.js
import { part, sketch, line, circle, extrude, fillet, select, connector, copy, expose } from 'fluidcad/core';
import { face } from 'fluidcad/filters';
import { coincident, distance, fix, horizontal, vertical } from 'fluidcad/constraints';

// The base plate every assembly example bolts onto: 80 × 50 × 10 mm, rounded
// corners, a Ø8 pivot bore in the middle and four Ø5 mounting holes.
export const plate = part('Base plate', () => {
sketch('xy', () => {
const b = line([-40, -25], [40, -25]);
const r = line([40, -25], [40, 25]);
const t = line([40, 25], [-40, 25]);
const l = line([-40, 25], [-40, -25]);
coincident(b.end(), r.start());
coincident(r.end(), t.start());
coincident(t.end(), l.start());
coincident(l.end(), b.start());
horizontal(b);
horizontal(t);
vertical(r);
vertical(l);
fix(b.start(), [-40, -25]);
distance(b.start(), b.end(), 80);
distance(r.start(), r.end(), 50);
// Round the four corners — a sketch fillet trims the lines and
// inserts tangent arcs.
fillet(6, b, r, t, l);
// The pivot bore, 20 mm right of centre …
circle([20, 0], 8);
// … and the mounting holes near each corner.
circle([-30, -17.5], 5);
circle([30, -17.5], 5);
circle([30, 17.5], 5);
circle([-30, 17.5], 5);
});
extrude(10);

// Mating frames. A face connector sits at the face centre with Z along
// the outward normal; .offset() then moves it along the frame's own
// X / Y / Z. Every frame here is the top face's, moved to where a part
// will mate — the top-face frame keeps X along world X and Y along
// world Y, so the offsets read like sketch coordinates.
connector('top', select(face().planar().onPlane('xy', 10)));
connector('bore', select(face().planar().onPlane('xy', 10))).offset(20, 0, 0);
// One connector on the front-left mounting hole, copied onto the other
// three: a 2 × 2 grid, 60 apart along X and 35 along Y, the same pitch
// as the hole circles. The copies are hole.instance(1) … hole.instance(3),
// numbered with X varying slowest: 1 is back left, 2 front right, 3 back
// right. An assembly mates them as base.connectors.hole.instance(k).
const hole = connector('hole', select(face().planar().onPlane('xy', 10))).offset(-30, -17.5, 0);
copy('linear', ['x', 'y'], { count: [2, 2], offset: [60, 35] }, hole);
// The top face as contact geometry for tangent mates.
expose('deck', select(face().planar().onPlane('xy', 10)));
});
standoffs.assembly.js
import { assembly, insert, mate, replicate } from 'fluidcad/core';
import { plate } from './asm-plate.part.js';
import { standoff } from './asm-standoff.part.js';

export const standoffs = assembly('standoffs', () => {
const base = insert(plate).grounded();

// The seed: one standoff fastened onto the first mounting hole.
const first = insert(standoff);
mate('fastened', base.connectors.hole, first.connectors.foot);

// replicate() re-inserts the seed once per row and re-targets its
// mates. The second argument lists the seed's OUTER mate sides that
// change per copy (one column: the plate connector); each row gives
// that column's replacement for one replica. The plate copies its
// `hole` connector onto the other three holes, so each row names one
// of those copies: hole.instance(1) is copy 1 of `hole`. Replicas take
// the seed's name with a suffix — "Standoff (2)", "Standoff (3)", … —
// and are ordinary instances from here on.
replicate(first, [base.connectors.hole], [
[base.connectors.hole.instance(1)],
[base.connectors.hole.instance(2)],
[base.connectors.hole.instance(3)],
]);
});

Signature​

replicate(seed, targets, rows)
ArgumentMeaning
seedThe handle insert() returned for the instance or sub-assembly to copy.
targetsThe seed's outer mate sides that change per replica — one column each. Any outer side not listed stays shared by every replica (a planar mate onto one common base).
rowsOne array per replica, one entry per target: rows[k][j] replaces targets[j] in replica k's mates. At least one row.

It returns the replica handles in row order, so const [b, c, d] = replicate(...) lets you name or mate them further.

Rules​

  • Only mates written before the statement replicate. Mate options (flip, rotate, offset, limits) are copied verbatim.
  • Replicas start at the seed's pose and are never grounded — their mates place them.
  • A target can be any mate side: instance.connectors.<name>, a copy of one (instance.connectors.<name>.instance(k)), an assembly connector or its copy (bay.instance(k)), or instance.features.<name> for a tangent mate.
  • Rows are always written out. Nothing follows the part's pattern: when the plate copies its hole connector onto six holes instead of four, add the rows (or run Suggest copies again).
  • Replicating a sub-assembly re-runs its body with the same parameters; its inner mates come along.