Collinear
collinear puts one line on the infinite extension of another. The two segments stay separate entities — they can have a gap, or overlap — but they share one line.
In the viewport
- Click two lines. A datum axis counts as a line.
- Click Collinear. The second line gets a
≡badge.

Before

The two lands are drawn at different heights, and the bottom edge sits just off the X axis.
After

collinear(leftLand, rightLand)Both lands share one line, and the bottom edge lies exactly on the revolve axis.
The code behind it
A half-profile to be revolved. collinear(leftLand, rightLand) removes 2 DOF from the right land so both lands share one surface across the snap-ring groove — one shaft diameter, dimensioned once. collinear(xAxis(), bottom) puts the profile's bottom edge exactly on the revolve axis: horizontal alone would only make it parallel.
shaft.part.js
import { sketch, line, xAxis, yAxis } from 'fluidcad/core';
import { collinear, coincident, horizontal, vertical, distance } from "fluidcad/constraints";
sketch("xy", () => {
// Half-profile of a shaft with a snap-ring groove, drawn to be
// revolved about the X axis. The two lands either side of the groove
// must share one surface.
const bottom = line([0, -3], [90, 2]);
const leftEnd = line([90, 1], [90, 26]);
const rightLand = line([90, 26], [46, 24]);
const grooveOut = line([46, 24], [46, 15]);
const grooveFloor = line([46, 15], [40, 15]);
const grooveIn = line([40, 15], [40, 19]);
const leftLand = line([40, 19], [0, 19]);
const rightEnd = line([0, 19], [0, 0]);
coincident(bottom.end(), leftEnd.start());
coincident(leftEnd.end(), rightLand.start());
coincident(rightLand.end(), grooveOut.start());
coincident(grooveOut.end(), grooveFloor.start());
coincident(grooveFloor.end(), grooveIn.start());
coincident(grooveIn.end(), leftLand.start());
coincident(leftLand.end(), rightEnd.start());
coincident(rightEnd.end(), bottom.start());
// The profile's bottom edge IS the revolve axis: on the X axis, not
// merely parallel to it.
collinear(xAxis(), bottom);
coincident(bottom.start(), yAxis());
vertical(leftEnd);
vertical(rightEnd);
vertical(grooveIn);
vertical(grooveOut);
horizontal(leftLand);
horizontal(grooveFloor);
// The right land lies on the left land's line: one shaft diameter,
// interrupted by the groove.
collinear(leftLand, rightLand);
distance(bottom.start(), bottom.end(), 90); // shaft length
distance(rightEnd.start(), rightEnd.end(), 20); // shaft radius
distance(leftLand.start(), leftLand.end(), 40); // groove position
distance(grooveIn, grooveOut, 6); // groove width
distance(leftLand, grooveFloor, 5); // groove depth
})
In code
collinear(a, b) // b lies on a's infinite line: 2 DOF
collinear(xAxis(), l) // l lies on the X axis
See also
- Horizontal, Vertical — direction only, no position
- Parallel