vcad.
Back to Rust API
Rust API

Sketch Operations

Create 3D solids from 2D sketches: extrude, revolve, sweep, loft

Sketch operations transform 2D profiles into 3D solids. They are essential for creating parts with complex geometry that cannot be achieved with primitives and booleans alone.

Overview

OperationDescriptionUse Case
ExtrudePush profile along a directionBrackets, plates, structural beams
RevolveSpin profile around an axisBottles, wheels, pulleys
SweepMove profile along a pathPipes, rails, springs
LoftBlend between multiple profilesTurbine blades, bottle necks

All sketch operations require a closed profile—a series of connected line and arc segments that form a closed loop.

Extrude

Sweeps a closed profile along a linear direction to create a prismatic solid.

Part::extrude(
    plane: SketchPlane,
    origin: Vec3,
    segments: &[SketchSegment2D],
    direction: Vec3,
) -> Part
planeSketchPlanerequired

The plane containing the sketch (XY, XZ, or YZ).

originVec3required

Origin point of the sketch in 3D space.

segments&[SketchSegment2D]required

Closed profile geometry (lines, arcs).

directionVec3required

Extrusion vector. The length determines the extrusion distance.

Creates:

  • 2 cap faces (start and end profiles)
  • N lateral faces (one per profile segment)
// L-shaped bracket profile
let profile = vec![
    SketchSegment2D::line([0.0, 0.0], [20.0, 0.0]),
    SketchSegment2D::line([20.0, 0.0], [20.0, 5.0]),
    SketchSegment2D::line([20.0, 5.0], [5.0, 5.0]),
    SketchSegment2D::line([5.0, 5.0], [5.0, 30.0]),
    SketchSegment2D::line([5.0, 30.0], [0.0, 30.0]),
    SketchSegment2D::line([0.0, 30.0], [0.0, 0.0]),
];

// Extrude 50mm along Z
let bracket = Part::extrude(
    SketchPlane::XY,
    Vec3::new(0.0, 0.0, 0.0),
    &profile,
    Vec3::new(0.0, 0.0, 50.0),
);

When to Use Extrude

  • Parts with constant cross-section
  • Plates, brackets, structural members
  • Features like bosses and ribs
  • Quick prototyping of mechanical parts

Extrusion direction does not need to be perpendicular to the sketch plane. Angled extrusions create sheared geometry.

Revolve

Rotates a closed profile around an axis to create a solid of revolution.

Part::revolve(
    plane: SketchPlane,
    origin: Vec3,
    segments: &[SketchSegment2D],
    axis_origin: Vec3,
    axis_dir: Vec3,
    angle_deg: f64,
) -> Part
planeSketchPlanerequired

The plane containing the sketch.

originVec3required

Origin point of the sketch.

segments&[SketchSegment2D]required

Closed profile geometry.

axis_originVec3required

A point on the rotation axis.

axis_dirVec3required

Direction of the rotation axis.

angle_degf64required

Rotation angle in degrees (0-360).

Creates:

  • Full 360-degree rotation: closed toroidal/cylindrical surfaces
  • Partial rotation: wedge with cap faces at start/end angles
// Wine glass profile (cross-section)
let profile = vec![
    SketchSegment2D::line([0.0, 0.0], [30.0, 0.0]),   // base
    SketchSegment2D::line([30.0, 0.0], [30.0, 5.0]),
    SketchSegment2D::line([30.0, 5.0], [5.0, 5.0]),
    SketchSegment2D::line([5.0, 5.0], [3.0, 50.0]),   // stem
    SketchSegment2D::line([3.0, 50.0], [20.0, 60.0]), // bowl
    SketchSegment2D::arc([20.0, 60.0], [25.0, 80.0], [22.0, 70.0]),
    SketchSegment2D::line([25.0, 80.0], [0.0, 80.0]),
    SketchSegment2D::line([0.0, 80.0], [0.0, 0.0]),
];

// Full revolution around Y axis
let glass = Part::revolve(
    SketchPlane::XY,
    Vec3::ZERO,
    &profile,
    Vec3::new(0.0, 0.0, 0.0),  // axis through origin
    Vec3::new(0.0, 1.0, 0.0),  // Y axis
    360.0,
);

Partial Revolve

// Quarter pie slice
let pie_slice = Part::revolve(
    SketchPlane::XY,
    Vec3::ZERO,
    &profile,
    Vec3::ZERO,
    Vec3::new(0.0, 0.0, 1.0),  // Z axis
    90.0,  // 90-degree wedge
);

When to Use Revolve

  • Rotationally symmetric parts (wheels, pulleys, knobs)
  • Turned parts (lathe operations)
  • Bottles, vases, bowls
  • Pie-chart style wedges

Keep the profile entirely on one side of the rotation axis. If the profile crosses the axis, the resulting geometry may self-intersect.

Sweep

Moves a closed profile along a 3D path curve with optional twist and scale.

Part::sweep(
    plane: SketchPlane,
    origin: Vec3,
    segments: &[SketchSegment2D],
    path: &PathCurve,
    options: SweepOptions,
) -> Part
planeSketchPlanerequired

The plane containing the sketch.

originVec3required

Origin point of the sketch (start of path).

segments&[SketchSegment2D]required

Closed profile geometry.

path&PathCurverequired

3D path curve to sweep along (line, arc, spline, helix).

optionsSweepOptionsrequired

Optional twist and scale parameters.

SweepOptions

FieldTypeDefaultDescription
twist_anglef640.0Total twist in radians along path
scale_startf641.0Scale factor at path start
scale_endf641.0Scale factor at path end
// Curved pipe
let circle_profile = vec![
    SketchSegment2D::arc([5.0, 0.0], [-5.0, 0.0], [0.0, 5.0]),
    SketchSegment2D::arc([-5.0, 0.0], [5.0, 0.0], [0.0, -5.0]),
];

let curved_path = PathCurve::arc(
    Vec3::new(0.0, 0.0, 0.0),
    Vec3::new(50.0, 50.0, 0.0),
    Vec3::new(50.0, 0.0, 0.0),
);

let pipe = Part::sweep(
    SketchPlane::YZ,
    Vec3::ZERO,
    &circle_profile,
    &curved_path,
    SweepOptions::default(),
);

Sweep with Twist

// Twisted ribbon
let rect_profile = vec![
    SketchSegment2D::line([0.0, -1.0], [0.0, 1.0]),
    SketchSegment2D::line([0.0, 1.0], [10.0, 1.0]),
    SketchSegment2D::line([10.0, 1.0], [10.0, -1.0]),
    SketchSegment2D::line([10.0, -1.0], [0.0, -1.0]),
];

let straight_path = PathCurve::line(
    Vec3::new(0.0, 0.0, 0.0),
    Vec3::new(0.0, 0.0, 100.0),
);

let ribbon = Part::sweep(
    SketchPlane::XY,
    Vec3::ZERO,
    &rect_profile,
    &straight_path,
    SweepOptions {
        twist_angle: std::f64::consts::PI,  // 180-degree twist
        ..Default::default()
    },
);

Helix (Spring)

// Compression spring
let wire_profile = vec![
    SketchSegment2D::arc([1.5, 0.0], [-1.5, 0.0], [0.0, 1.5]),
    SketchSegment2D::arc([-1.5, 0.0], [1.5, 0.0], [0.0, -1.5]),
];

let helix = PathCurve::helix(
    radius: 10.0,
    pitch: 5.0,   // 5mm per revolution
    turns: 8.0,
);

let spring = Part::sweep(
    SketchPlane::XY,
    Vec3::new(10.0, 0.0, 0.0),
    &wire_profile,
    &helix,
    SweepOptions::default(),
);

When to Use Sweep

  • Pipes, tubes, and conduits
  • Rails and extrusions along curves
  • Springs and helical features
  • Handles and curved structural members
  • Wire/cable routing visualization

Sweep uses rotation-minimizing frames to maintain consistent profile orientation along the path, avoiding the twisting artifacts that can occur with simpler Frenet frames.

Loft

Interpolates between multiple profiles at different positions to create a smooth transition solid.

Part::loft(
    profiles: &[LoftProfile],
    closed: bool,
) -> Part
profiles&[LoftProfile]required

Two or more profile definitions at different positions.

closedboolrequired

If true, connects the last profile back to the first (creates a tube).

LoftProfile

Each profile contains:

FieldTypeDescription
planeSketchPlaneThe plane containing the sketch
originVec3Origin point in 3D space
segmentsVec<SketchSegment2D>Closed profile geometry

Requirements:

  • Minimum 2 profiles
  • All profiles must have the same number of segments
  • Profiles should be at different positions in 3D space
// Transition from square to circle
let square_profile = vec![
    SketchSegment2D::line([-10.0, -10.0], [10.0, -10.0]),
    SketchSegment2D::line([10.0, -10.0], [10.0, 10.0]),
    SketchSegment2D::line([10.0, 10.0], [-10.0, 10.0]),
    SketchSegment2D::line([-10.0, 10.0], [-10.0, -10.0]),
];

// Approximate circle with 4 arcs to match segment count
let circle_profile = vec![
    SketchSegment2D::arc([-10.0, 0.0], [0.0, -10.0], [-7.0, -7.0]),
    SketchSegment2D::arc([0.0, -10.0], [10.0, 0.0], [7.0, -7.0]),
    SketchSegment2D::arc([10.0, 0.0], [0.0, 10.0], [7.0, 7.0]),
    SketchSegment2D::arc([0.0, 10.0], [-10.0, 0.0], [-7.0, 7.0]),
];

let adapter = Part::loft(
    &[
        LoftProfile {
            plane: SketchPlane::XY,
            origin: Vec3::new(0.0, 0.0, 0.0),
            segments: square_profile,
        },
        LoftProfile {
            plane: SketchPlane::XY,
            origin: Vec3::new(0.0, 0.0, 50.0),
            segments: circle_profile,
        },
    ],
    false,
);

Multi-Profile Loft

// Airfoil transitioning along span
let profiles = vec![
    LoftProfile {
        plane: SketchPlane::XZ,
        origin: Vec3::new(0.0, 0.0, 0.0),
        segments: root_airfoil.clone(),
    },
    LoftProfile {
        plane: SketchPlane::XZ,
        origin: Vec3::new(0.0, 100.0, 5.0),
        segments: mid_airfoil.clone(),
    },
    LoftProfile {
        plane: SketchPlane::XZ,
        origin: Vec3::new(0.0, 200.0, 10.0),
        segments: tip_airfoil.clone(),
    },
];

let wing = Part::loft(&profiles, false);

Closed Loft (Tube)

// Torus-like shape
let profile = create_circle_profile(5.0);

let ring = Part::loft(
    &[
        LoftProfile {
            plane: SketchPlane::YZ,
            origin: Vec3::new(30.0, 0.0, 0.0),
            segments: profile.clone(),
        },
        LoftProfile {
            plane: SketchPlane::XZ,
            origin: Vec3::new(0.0, 30.0, 0.0),
            segments: profile.clone(),
        },
        LoftProfile {
            plane: SketchPlane::YZ,
            origin: Vec3::new(-30.0, 0.0, 0.0),
            segments: profile.clone(),
        },
        LoftProfile {
            plane: SketchPlane::XZ,
            origin: Vec3::new(0.0, -30.0, 0.0),
            segments: profile.clone(),
        },
    ],
    true,  // Connect last to first
);

When to Use Loft

  • Transitioning between different shapes
  • Organic forms (bottles, vases, aerodynamic shapes)
  • Turbine and propeller blades
  • Ductwork and HVAC transitions
  • Ergonomic handles and grips

All profiles must have the same segment count. If transitioning between shapes with different numbers of sides, approximate one shape to match the other's segment count.

Sketch Segments

Profile geometry is defined using 2D segments:

Line Segment

SketchSegment2D::line(start: [f64; 2], end: [f64; 2])

Arc Segment

SketchSegment2D::arc(start: [f64; 2], end: [f64; 2], mid: [f64; 2])

The mid point lies on the arc between start and end, defining the curve direction and radius.

Edge Cases

SituationBehavior
Empty profileOperation rejected with error
Open profileWarning displayed, may produce invalid geometry
Self-intersecting profileMay produce invalid or unexpected geometry
Zero-length extrusionPrevented by validation
Revolve axis through profileCreates hollow geometry
Mismatched loft segment countsError with specific mismatch info

Operation Comparison

FeatureExtrudeRevolveSweepLoft
Profile count1112+
Path requiredNo (linear)No (circular)YesNo
Twist supportNoNoYesNo
Scale variationNoNoYesImplicit
Profiles at different positionsNoNoNoYes