Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Getting Started

Install and initialize the WebAssembly package:

npm install ishape_wasm

Boolean operation

The builder uses familiar Canvas-style path methods. Every contour must be closed before build() is called.

import init, {
    CurveBuilder,
    CurveOverlay,
    FillRule,
    OverlayRule,
} from 'ishape_wasm';

await init();

const subjectBuilder = new CurveBuilder();
subjectBuilder.moveTo(0, 0);
subjectBuilder.bezierCurveTo(25, -30, 75, -30, 100, 0);
subjectBuilder.lineTo(100, 80);
subjectBuilder.lineTo(0, 80);
subjectBuilder.closeContour();
const subject = subjectBuilder.build();

const clipBuilder = new CurveBuilder();
clipBuilder.addEllipse(65, 35, 45, 30, 0, false);
const clip = clipBuilder.build();

const operation = new CurveOverlay(subject, clip);
const result = operation.overlay(
    OverlayRule.Intersect,
    FillRule.NonZero,
);

console.log(result.shapeCount);
console.log(result.contourCount);
console.log(result.segmentCount);
console.log(result.toData());

CurveOverlay is a single-use operation object: overlay() consumes it. The input and result CurveGeometry objects remain reusable.

Building contours

Available segment methods are:

const builder = new CurveBuilder();

builder.moveTo(10, 10);
builder.lineTo(60, 10);
builder.quadraticCurveTo(90, 40, 60, 70);
builder.bezierCurveTo(40, 90, 20, 90, 10, 70);
builder.lineTo(10, 10);
builder.closeContour();

// Angles and ellipse rotation are expressed in radians.
builder.ellipticArcTo(
    120, 60, // center
    30, 20,  // radii
    0,       // rotation
    0,       // start angle
    Math.PI, // sweep angle
);
builder.closeContour();

// A complete ellipse is added as a new closed contour.
builder.addEllipse(200, 60, 30, 20, 0, false);

const geometry = builder.build();

Call moveTo() only after the previous contour has been closed. After a successful build(), the builder is reset and can be used for another shape.

Resolving self-intersections

When there is no clip geometry, create a subject-only operation:

const operation = CurveOverlay.fromSubject(subject);
const resolved = operation.resolveSubject(FillRule.EvenOdd);

The fill rule determines which regions of overlapping or self-intersecting contours belong to the result.

Precision controls

For most inputs, automatic scaling and the default approximation are sufficient. Advanced callers can inspect or override them before running the operation:

const operation = new CurveOverlay(subject, clip);

operation.setApproximation({
    minChordLength: 0.001,
    angleTolerance: 0.125,
    maxDepth: 16,
});

console.log(operation.scale());
console.log(operation.conversionReport());

const result = operation.overlay(
    OverlayRule.Union,
    FillRule.NonZero,
);

Use CurveOverlay.withScale(subject, clip, scale) only when the application needs an explicit float-to-integer conversion scale. A conversion report with hasDegeneracies: true indicates that some input geometry collapsed or an arc had to be linearized during conversion.