Skip to main content

Applying 3D features

The outline becomes a leaf in seven features: the plate, one screw hole, the hole repeated into a row, rounded corners, one knuckle, the knuckle repeated along the pin axis, and the bore for the pin. Every feature is a dialog or a pick tool on the toolbar, and every one adds a row to the History panel and a statement to the file.

Extrude the plate

  1. Click Extrude. The dialog docks on the right; the Sketch slot is already filled with the outline because it is the last sketch in the file (click a sketch row in the History panel to pick a different one).
  2. Leave the Add tab selected, Direction on One direction, and type 3 in Distance. A translucent ghost shows the plate while you type.
  3. Click Apply.

Extrude dialog

The plate
The code behind it
hinge-leaf-fixed.part.js
import { origin, xAxis, yAxis, part, sketch, line, circle, extrude, cut, repeat, fillet, connector } from 'fluidcad/core';
import { coincident, horizontal, vertical, midpoint, distance, diameter, fix } from 'fluidcad/constraints';
import { edge } from 'fluidcad/filters';

// The part container: everything inside the callback belongs to the
// "Fixed leaf". Exporting it is what lets an assembly insert() it later.
export const fixedLeaf = part('Fixed leaf', () => {
// Leaf outline, drawn with the Rectangle tool on the XY plane: 30 mm wide,
// 60 mm along the pin axis (Y). The four lines are guesses; the constraints
// below are what the tool wrote to pin the rectangle down.
sketch('xy', () => {
const b = line([0, -28.96], [30, -28.96]);
const r = line([30, -28.96], [30, 31.04]);
const t = line([30, 31.04], [0, 31.04]);
const l = line([0, 31.04], [0, -28.96]);
// corners: each line ends where the next one starts
coincident(b.end(), r.start());
coincident(r.end(), t.start());
coincident(t.end(), l.start());
coincident(l.end(), b.start());
// square it up
horizontal(b);
vertical(r);
horizontal(t);
vertical(l);
// the two dimensions (double-click a label in the viewport to change them)
distance(b.start(), b.end(), 30);
distance(r.start(), r.end(), 60);
// centre the left edge on the origin: the pin axis runs through the
// middle of the leaf, and the outline cannot slide
midpoint(origin(), t.end(), b.start());
});
// Extrude dialog, Add tab, Distance 3: the leaf plate.
const leaf = extrude(3);
});

Cut a screw hole

Holes are a sketch on the top face and an extrude in Remove mode. The first hole goes near the front-right corner: 20 mm from the pin edge and 10 mm from the end of the plate.

  1. Click Sketch, then click the plate's top face in the viewport. The sketch opens on that face.
  2. Click Circle. Click a centre roughly where the hole goes, then type 4 for the diameter. Esc leaves the tool.
  3. Dimension the centre to the sketch axes: click the circle's centre and the X axis, then Dimension on the constraint toolbar, and type 20. Click the centre and the Y axis, Dimension, 20. The circle turns green. Finish sketch.
  4. Click Extrude, choose the Remove tab, and tick Through all. Click Apply.
One screw hole
The code behind it
hinge-leaf-fixed.part.js
import { origin, xAxis, yAxis, part, sketch, line, circle, extrude, cut, repeat, fillet, connector } from 'fluidcad/core';
import { coincident, horizontal, vertical, midpoint, distance, diameter, fix } from 'fluidcad/constraints';
import { edge } from 'fluidcad/filters';

// The part container: everything inside the callback belongs to the
// "Fixed leaf". Exporting it is what lets an assembly insert() it later.
export const fixedLeaf = part('Fixed leaf', () => {
// Leaf outline, drawn with the Rectangle tool on the XY plane: 30 mm wide,
// 60 mm along the pin axis (Y). The four lines are guesses; the constraints
// below are what the tool wrote to pin the rectangle down.
sketch('xy', () => {
const b = line([0, -28.96], [30, -28.96]);
const r = line([30, -28.96], [30, 31.04]);
const t = line([30, 31.04], [0, 31.04]);
const l = line([0, 31.04], [0, -28.96]);
// corners: each line ends where the next one starts
coincident(b.end(), r.start());
coincident(r.end(), t.start());
coincident(t.end(), l.start());
coincident(l.end(), b.start());
// square it up
horizontal(b);
vertical(r);
horizontal(t);
vertical(l);
// the two dimensions (double-click a label in the viewport to change them)
distance(b.start(), b.end(), 30);
distance(r.start(), r.end(), 60);
// centre the left edge on the origin: the pin axis runs through the
// middle of the leaf, and the outline cannot slide
midpoint(origin(), t.end(), b.start());
});
// Extrude dialog, Add tab, Distance 3: the leaf plate.
const leaf = extrude(3);
// One screw hole: a circle sketched on the plate's top face, then the
// Extrude dialog's Remove tab (a cut) with Through all. The circle is a
// guess; the two dimensions to the sketch axes place it 20 mm from the
// pin edge and 10 mm from the end of the plate.
sketch(leaf.endFaces(), () => {
const hole = circle([22.92, -25.08], 4);
diameter(hole, 4);
distance(hole.center(), xAxis(), 20);
distance(hole.center(), yAxis(), 20);
});
const hole = cut();
});

In the file, Remove mode is the cut() statement, and calling it with no distance is Through all. The two distance() constraints to xAxis() and yAxis() are the dimensions; the circle's own coordinates are only where you clicked.

Repeat the hole

  1. Click Repeat. Pick the Cut row in the History panel as the feature to repeat.
  2. Kind Linear, Axis Y, Count 3, Offset 20. Click Apply. The two copies land at 0 and 20 mm along Y, so the row is centred on the plate.
The row of holes
The code behind it
hinge-leaf-fixed.part.js
import { origin, xAxis, yAxis, part, sketch, line, circle, extrude, cut, repeat, fillet, connector } from 'fluidcad/core';
import { coincident, horizontal, vertical, midpoint, distance, diameter, fix } from 'fluidcad/constraints';
import { edge } from 'fluidcad/filters';

// The part container: everything inside the callback belongs to the
// "Fixed leaf". Exporting it is what lets an assembly insert() it later.
export const fixedLeaf = part('Fixed leaf', () => {
// Leaf outline, drawn with the Rectangle tool on the XY plane: 30 mm wide,
// 60 mm along the pin axis (Y). The four lines are guesses; the constraints
// below are what the tool wrote to pin the rectangle down.
sketch('xy', () => {
const b = line([0, -28.96], [30, -28.96]);
const r = line([30, -28.96], [30, 31.04]);
const t = line([30, 31.04], [0, 31.04]);
const l = line([0, 31.04], [0, -28.96]);
// corners: each line ends where the next one starts
coincident(b.end(), r.start());
coincident(r.end(), t.start());
coincident(t.end(), l.start());
coincident(l.end(), b.start());
// square it up
horizontal(b);
vertical(r);
horizontal(t);
vertical(l);
// the two dimensions (double-click a label in the viewport to change them)
distance(b.start(), b.end(), 30);
distance(r.start(), r.end(), 60);
// centre the left edge on the origin: the pin axis runs through the
// middle of the leaf, and the outline cannot slide
midpoint(origin(), t.end(), b.start());
});
// Extrude dialog, Add tab, Distance 3: the leaf plate.
const leaf = extrude(3);
// One screw hole: a circle sketched on the plate's top face, then the
// Extrude dialog's Remove tab (a cut) with Through all. The circle is a
// guess; the two dimensions to the sketch axes place it 20 mm from the
// pin edge and 10 mm from the end of the plate.
sketch(leaf.endFaces(), () => {
const hole = circle([22.92, -25.08], 4);
diameter(hole, 4);
distance(hole.center(), xAxis(), 20);
distance(hole.center(), yAxis(), 20);
});
const hole = cut();
// Repeat dialog: the same cut two more times, 20 mm apart along Y.
repeat('linear', 'y', { count: 3, offset: 20 }, hole);
});

repeat() re-applies the cut at each position, so the result is one solid with three holes. (copy() would have cloned the whole plate instead; see Patterns.)

Round the outer corners

  1. Click Fillet. A small panel shows the Radius; set it to 4.
  2. Click the two vertical edges on the side away from the pin. Each click adds the edge; right-clicking an edge opens a menu with related edges (the tangent chain, edges of the same type, the feature's other edge groups) if you want several at once.
  3. Click Apply.
Rounded corners
The code behind it
hinge-leaf-fixed.part.js
import { origin, xAxis, yAxis, part, sketch, line, circle, extrude, cut, repeat, fillet, connector } from 'fluidcad/core';
import { coincident, horizontal, vertical, midpoint, distance, diameter, fix } from 'fluidcad/constraints';
import { edge } from 'fluidcad/filters';

// The part container: everything inside the callback belongs to the
// "Fixed leaf". Exporting it is what lets an assembly insert() it later.
export const fixedLeaf = part('Fixed leaf', () => {
// Leaf outline, drawn with the Rectangle tool on the XY plane: 30 mm wide,
// 60 mm along the pin axis (Y). The four lines are guesses; the constraints
// below are what the tool wrote to pin the rectangle down.
sketch('xy', () => {
const b = line([0, -28.96], [30, -28.96]);
const r = line([30, -28.96], [30, 31.04]);
const t = line([30, 31.04], [0, 31.04]);
const l = line([0, 31.04], [0, -28.96]);
// corners: each line ends where the next one starts
coincident(b.end(), r.start());
coincident(r.end(), t.start());
coincident(t.end(), l.start());
coincident(l.end(), b.start());
// square it up
horizontal(b);
vertical(r);
horizontal(t);
vertical(l);
// the two dimensions (double-click a label in the viewport to change them)
distance(b.start(), b.end(), 30);
distance(r.start(), r.end(), 60);
// centre the left edge on the origin: the pin axis runs through the
// middle of the leaf, and the outline cannot slide
midpoint(origin(), t.end(), b.start());
});
// Extrude dialog, Add tab, Distance 3: the leaf plate.
const leaf = extrude(3);
// One screw hole: a circle sketched on the plate's top face, then the
// Extrude dialog's Remove tab (a cut) with Through all. The circle is a
// guess; the two dimensions to the sketch axes place it 20 mm from the
// pin edge and 10 mm from the end of the plate.
sketch(leaf.endFaces(), () => {
const hole = circle([22.92, -25.08], 4);
diameter(hole, 4);
distance(hole.center(), xAxis(), 20);
distance(hole.center(), yAxis(), 20);
});
const hole = cut();
// Repeat dialog: the same cut two more times, 20 mm apart along Y.
repeat('linear', 'y', { count: 3, offset: 20 }, hole);
// Fillet tool, radius 4, on the two corners away from the pin — the
// vertical edges that lie on the plane x = 30.
fillet(4, leaf.sideEdges(edge().onPlane('yz', 30)));
});

The tool picked the edges by where they are: the vertical edges of the plate that lie on the plane x = 30. That reference survives changes to the plate's size, which a stored edge index would not.

One knuckle

The knuckle is a tube along the pin axis. It is sketched on the front plane (XZ) as a circle and extruded along Y, both ways from the plane, so the tube is centred on the middle of the leaf like the outline is.

  1. Click Sketch, then click the XZ origin plane.
  2. Circle: centre 0, 4 (the axis sits 4 mm above the leaf, so the tube rests on the plate's edge), diameter 8. Typing the centre in the coordinate pill writes those coordinates into the statement; the centre stays free until you constrain it. Finish sketch.
  3. Extrude, Add tab, Direction Symmetric, Distance 12. The ghost shows the tube growing 6 mm to each side of the front plane. Apply.
The first knuckle
The code behind it
hinge-leaf-fixed.part.js
import { origin, xAxis, yAxis, part, sketch, line, circle, extrude, cut, repeat, fillet, connector } from 'fluidcad/core';
import { coincident, horizontal, vertical, midpoint, distance, diameter, fix } from 'fluidcad/constraints';
import { edge } from 'fluidcad/filters';

// The part container: everything inside the callback belongs to the
// "Fixed leaf". Exporting it is what lets an assembly insert() it later.
export const fixedLeaf = part('Fixed leaf', () => {
// Leaf outline, drawn with the Rectangle tool on the XY plane: 30 mm wide,
// 60 mm along the pin axis (Y). The four lines are guesses; the constraints
// below are what the tool wrote to pin the rectangle down.
sketch('xy', () => {
const b = line([0, -28.96], [30, -28.96]);
const r = line([30, -28.96], [30, 31.04]);
const t = line([30, 31.04], [0, 31.04]);
const l = line([0, 31.04], [0, -28.96]);
// corners: each line ends where the next one starts
coincident(b.end(), r.start());
coincident(r.end(), t.start());
coincident(t.end(), l.start());
coincident(l.end(), b.start());
// square it up
horizontal(b);
vertical(r);
horizontal(t);
vertical(l);
// the two dimensions (double-click a label in the viewport to change them)
distance(b.start(), b.end(), 30);
distance(r.start(), r.end(), 60);
// centre the left edge on the origin: the pin axis runs through the
// middle of the leaf, and the outline cannot slide
midpoint(origin(), t.end(), b.start());
});
// Extrude dialog, Add tab, Distance 3: the leaf plate.
const leaf = extrude(3);
// One screw hole: a circle sketched on the plate's top face, then the
// Extrude dialog's Remove tab (a cut) with Through all. The circle is a
// guess; the two dimensions to the sketch axes place it 20 mm from the
// pin edge and 10 mm from the end of the plate.
sketch(leaf.endFaces(), () => {
const hole = circle([22.92, -25.08], 4);
diameter(hole, 4);
distance(hole.center(), xAxis(), 20);
distance(hole.center(), yAxis(), 20);
});
const hole = cut();
// Repeat dialog: the same cut two more times, 20 mm apart along Y.
repeat('linear', 'y', { count: 3, offset: 20 }, hole);
// Fillet tool, radius 4, on the two corners away from the pin — the
// vertical edges that lie on the plane x = 30.
fillet(4, leaf.sideEdges(edge().onPlane('yz', 30)));
// One knuckle: an 8 mm ring sketched on the front plane, centred 4 mm
// above the leaf so the tube sits on the plate's edge, then extruded 12 mm
// along the pin axis, symmetric about the sketch plane (6 mm each way).
sketch('xz', () => {
const outer = circle([0, 4], 8);
diameter(outer, 8);
fix(outer.center(), [0, 4]);
});
const knuckle = extrude(12).symmetric();
});

The tube is solid for now; the bore comes last, once all three knuckles are in place. The extrude fuses with the plate where they touch.

Repeat the knuckle

  1. Repeat again: pick the knuckle's Extrude row, Linear along Y, Count 3, Offset 24, and tick Centered. Apply.
Three knuckles
The code behind it
hinge-leaf-fixed.part.js
import { origin, xAxis, yAxis, part, sketch, line, circle, extrude, cut, repeat, fillet, connector } from 'fluidcad/core';
import { coincident, horizontal, vertical, midpoint, distance, diameter, fix } from 'fluidcad/constraints';
import { edge } from 'fluidcad/filters';

// The part container: everything inside the callback belongs to the
// "Fixed leaf". Exporting it is what lets an assembly insert() it later.
export const fixedLeaf = part('Fixed leaf', () => {
// Leaf outline, drawn with the Rectangle tool on the XY plane: 30 mm wide,
// 60 mm along the pin axis (Y). The four lines are guesses; the constraints
// below are what the tool wrote to pin the rectangle down.
sketch('xy', () => {
const b = line([0, -28.96], [30, -28.96]);
const r = line([30, -28.96], [30, 31.04]);
const t = line([30, 31.04], [0, 31.04]);
const l = line([0, 31.04], [0, -28.96]);
// corners: each line ends where the next one starts
coincident(b.end(), r.start());
coincident(r.end(), t.start());
coincident(t.end(), l.start());
coincident(l.end(), b.start());
// square it up
horizontal(b);
vertical(r);
horizontal(t);
vertical(l);
// the two dimensions (double-click a label in the viewport to change them)
distance(b.start(), b.end(), 30);
distance(r.start(), r.end(), 60);
// centre the left edge on the origin: the pin axis runs through the
// middle of the leaf, and the outline cannot slide
midpoint(origin(), t.end(), b.start());
});
// Extrude dialog, Add tab, Distance 3: the leaf plate.
const leaf = extrude(3);
// One screw hole: a circle sketched on the plate's top face, then the
// Extrude dialog's Remove tab (a cut) with Through all. The circle is a
// guess; the two dimensions to the sketch axes place it 20 mm from the
// pin edge and 10 mm from the end of the plate.
sketch(leaf.endFaces(), () => {
const hole = circle([22.92, -25.08], 4);
diameter(hole, 4);
distance(hole.center(), xAxis(), 20);
distance(hole.center(), yAxis(), 20);
});
const hole = cut();
// Repeat dialog: the same cut two more times, 20 mm apart along Y.
repeat('linear', 'y', { count: 3, offset: 20 }, hole);
// Fillet tool, radius 4, on the two corners away from the pin — the
// vertical edges that lie on the plane x = 30.
fillet(4, leaf.sideEdges(edge().onPlane('yz', 30)));
// One knuckle: an 8 mm ring sketched on the front plane, centred 4 mm
// above the leaf so the tube sits on the plate's edge, then extruded 12 mm
// along the pin axis, symmetric about the sketch plane (6 mm each way).
sketch('xz', () => {
const outer = circle([0, 4], 8);
diameter(outer, 8);
fix(outer.center(), [0, 4]);
});
const knuckle = extrude(12).symmetric();
// Three knuckles on this leaf, 24 mm apart and centred on the first one:
// the other leaf's two knuckles fill the gaps between them.
repeat('linear', 'y', { count: 3, offset: 24, centered: true }, knuckle);
});

Centered spreads the copies to both sides of the original instead of stacking them one way, so the knuckles sit at −24, 0 and 24 mm and the outer two end flush with the plate. The 12 mm gaps between them are where the other leaf's two knuckles go.

Bore the pin hole

One more Remove extrude drills the 4 mm bore through all three knuckles at once.

  1. Sketch on the XZ plane again. Circle: centre 0, 4, diameter 4. Finish sketch.
  2. Extrude, Remove tab, Direction Symmetric, tick Through all. Apply.
The bore through the knuckles
The code behind it
hinge-leaf-fixed.part.js
import { origin, xAxis, yAxis, part, sketch, line, circle, extrude, cut, repeat, fillet, connector } from 'fluidcad/core';
import { coincident, horizontal, vertical, midpoint, distance, diameter, fix } from 'fluidcad/constraints';
import { edge } from 'fluidcad/filters';

// The part container: everything inside the callback belongs to the
// "Fixed leaf". Exporting it is what lets an assembly insert() it later.
export const fixedLeaf = part('Fixed leaf', () => {
// Leaf outline, drawn with the Rectangle tool on the XY plane: 30 mm wide,
// 60 mm along the pin axis (Y). The four lines are guesses; the constraints
// below are what the tool wrote to pin the rectangle down.
sketch('xy', () => {
const b = line([0, -28.96], [30, -28.96]);
const r = line([30, -28.96], [30, 31.04]);
const t = line([30, 31.04], [0, 31.04]);
const l = line([0, 31.04], [0, -28.96]);
// corners: each line ends where the next one starts
coincident(b.end(), r.start());
coincident(r.end(), t.start());
coincident(t.end(), l.start());
coincident(l.end(), b.start());
// square it up
horizontal(b);
vertical(r);
horizontal(t);
vertical(l);
// the two dimensions (double-click a label in the viewport to change them)
distance(b.start(), b.end(), 30);
distance(r.start(), r.end(), 60);
// centre the left edge on the origin: the pin axis runs through the
// middle of the leaf, and the outline cannot slide
midpoint(origin(), t.end(), b.start());
});
// Extrude dialog, Add tab, Distance 3: the leaf plate.
const leaf = extrude(3);
// One screw hole: a circle sketched on the plate's top face, then the
// Extrude dialog's Remove tab (a cut) with Through all. The circle is a
// guess; the two dimensions to the sketch axes place it 20 mm from the
// pin edge and 10 mm from the end of the plate.
sketch(leaf.endFaces(), () => {
const hole = circle([22.92, -25.08], 4);
diameter(hole, 4);
distance(hole.center(), xAxis(), 20);
distance(hole.center(), yAxis(), 20);
});
const hole = cut();
// Repeat dialog: the same cut two more times, 20 mm apart along Y.
repeat('linear', 'y', { count: 3, offset: 20 }, hole);
// Fillet tool, radius 4, on the two corners away from the pin — the
// vertical edges that lie on the plane x = 30.
fillet(4, leaf.sideEdges(edge().onPlane('yz', 30)));
// One knuckle: an 8 mm ring sketched on the front plane, centred 4 mm
// above the leaf so the tube sits on the plate's edge, then extruded 12 mm
// along the pin axis, symmetric about the sketch plane (6 mm each way).
sketch('xz', () => {
const outer = circle([0, 4], 8);
diameter(outer, 8);
fix(outer.center(), [0, 4]);
});
const knuckle = extrude(12).symmetric();
// Three knuckles on this leaf, 24 mm apart and centred on the first one:
// the other leaf's two knuckles fill the gaps between them.
repeat('linear', 'y', { count: 3, offset: 24, centered: true }, knuckle);
// The 4 mm bore for the pin: a circle on the front plane, cut Through all
// in both directions so one cut drills all three knuckles.
sketch('xz', () => {
const bore = circle([0, 4], 4);
diameter(bore, 4);
fix(bore.center(), [0, 4]);
});
cut().symmetric();
});

Through all with Symmetric reaches from the sketch plane to the ends of the solid in both directions, so one cut from the middle knuckle drills the outer two as well. (Drawing the bore as a second circle inside the ring sketch would have worked for one knuckle too; a separate cut keeps the knuckle a plain tube that other features, like the connectors, can refer to.)

Next: Defining connectors.