Spline Entity (SplineEnt)
Spline Entity (SplineEnt)
SplineEnt represents a spline curve entity in CAD, used to create smooth free-form curves.
Overview
Spline curves (NURBS curves) support two creation modes:
- Control point mode: Control points "attract" the curve shape; the curve does not pass through control points (except endpoints)
- Fit point mode: The curve passes exactly through all specified fit points, ideal for scenarios requiring precise paths
Constructor
import { SplineEnt, SplineControlPoint, Point2D } from 'vjcad';
// Create spline curve
const spline = new SplineEnt();
// Traditional way: add control points
const cp1 = new SplineControlPoint();
cp1.point2d = new Point2D(0, 0);
cp1.weight = 1;
spline.controlPoints.items.push(cp1);
// ... add more control pointsSimplified Interface (Recommended)
A more concise array interface is provided to simplify spline creation and manipulation.
Setting and Adding Control Points
import { SplineEnt, Engine } from 'vjcad';
const spline = new SplineEnt();
// Method 1: Batch set control points (recommended)
// Format: [x, y] for coordinates (weight defaults to 1), [[x, y], weight] for weighted points
spline.setControlPoints([
[0, 0],
[50, 100],
[100, 50],
[[150, 100], 0.5], // with weight
[200, 0]
]);
// Method 2: Chain add single control points
spline.addControlPoint([0, 0])
.addControlPoint([50, 100])
.addControlPoint([100, 50], 0.5) // second parameter is weight
.addControlPoint([150, 0]);
// Method 3: Batch append control points
spline.addControlPoints([[200, 50], [[250, 100], 0.8], [300, 50]]);
spline.setDefaults();
Engine.addEntities(spline);Getting Control Points
const spline: SplineEnt = /* ... */;
// Get single control point coordinates
const [x, y] = spline.getControlPoint(0);
// Get single control point coordinates and weight
const [[px, py], weight] = spline.getControlPointWithWeight(3);
// Get all control point coordinates (without weights)
const coords = spline.getControlPoints(); // [[0,0], [50,100], [100,50], ...]
// Get all control points (with weights, format consistent with setControlPoints)
const full = spline.getControlPointsWithWeight();
// [[0,0], [50,100], [100,50], [[150,100], 0.5], ...]
// Copy to another spline
const spline2 = new SplineEnt();
spline2.setControlPoints(spline.getControlPointsWithWeight());Simplified Interface API Reference
| Method | Parameters | Returns | Description |
|---|---|---|---|
addControlPoint(coord, weight?) | [x, y], number | this | Add single control point, supports chaining |
addControlPoints(points) | see format below | this | Batch append control points |
setControlPoints(points) | see format below | this | Set all control points (replaces existing) |
getControlPoint(index) | number | [x, y] | Get control point coordinates at specified index |
getControlPoints() | - | [x, y][] | Get all control point coordinates |
getControlPointWithWeight(index) | number | [[x, y], weight] | Get control point coordinates and weight |
getControlPointsWithWeight() | - | see format below | Get all control points (with weights) |
Point array format:
- Without weight (default 1):
[x, y] - With weight:
[[x, y], weight] - Mixed:
[[0, 0], [50, 100], [[100, 50], 0.5], [150, 0]]
Recommended: Use Simplified Interface
The simplified interface is more concise than the traditional SplineControlPoint + Point2D approach, making code easier to read. The return format of getControlPointsWithWeight() is fully compatible with setControlPoints(), facilitating copy and serialization operations.
Fit Points Interface
In fit point mode, the curve passes exactly through all specified points. The algorithm automatically computes control points and knot vectors via global cubic B-spline interpolation.
Setting Fit Points
import { SplineEnt, Engine } from 'vjcad';
const spline = new SplineEnt();
// Set fit points — curve passes exactly through all points
spline.setFitPoints([
[0, 0],
[30, 60],
[70, 20],
[110, 80],
[150, 30]
]);
spline.setDefaults();
Engine.addEntities(spline);Parameterization Options
// Use centripetal parameterization (better for curves with sharp turns)
spline.setFitPoints(points, { parameterization: 'sqrtChord' });
// Specify endpoint tangent directions
spline.setFitPoints(points, {
startTangent: [1, 0], // start point tangent: horizontal right
endTangent: [1, 0] // end point tangent: horizontal right
});Fit Points API Reference
| Method | Parameters | Returns | Description |
|---|---|---|---|
setFitPoints(points, options?) | [x, y][], FitPointsOptions | this | Set fit points (replaces existing), auto-computes control points |
addFitPoint(coord, options?) | [x, y] | this | Append one fit point and recompute |
addFitPoints(points, options?) | [x, y][] | this | Batch append fit points and recompute |
getFitPoint(index) | number | [x, y] | Get fit point coordinates at index |
getFitPoints() | - | [x, y][] | Get all fit point coordinates |
Parameterization Options (FitPointsOptions):
| Option | Type | Default | Description |
|---|---|---|---|
parameterization | 'chord' | 'sqrtChord' | 'uniform' | 'chord' | Parameterization method |
startTangent | [number, number] | - | Start point tangent direction |
endTangent | [number, number] | - | End point tangent direction |
Control Points vs Fit Points
- Control points (
setControlPoints): Control points act like "magnets" pulling the curve; the curve does not pass through them. Best for direct shape manipulation. - Fit points (
setFitPoints): The curve must pass exactly through every fit point. Best when you know the exact path points.
Properties
Basic Properties
| Property | Type | Read/Write | Description |
|---|---|---|---|
controlPoints | SplineControlPoints | Read/Write | Control point collection |
fitPoints | SplineFitPoints | Read/Write | Fit point collection |
degree | number | Read/Write | Curve degree (usually 3) |
knots | SplineKnots | Read/Write | Knot vector |
Computed Properties (Read-only)
| Property | Type | Description |
|---|---|---|
length | number | Total spline length |
isClosed | boolean | Whether closed |
startPoint | Point2D | Start point |
endPoint | Point2D | End point |
numberOfControlPoints | number | Number of control points |
numberOfFitPoints | number | Number of fit points |
import { SplineEnt } from 'vjcad';
const spline = new SplineEnt();
spline.setControlPoints([
[0, 0], [50, 100], [100, 50], [150, 100], [200, 0]
]);
console.log('Control points:', spline.numberOfControlPoints); // 5
console.log('Degree:', spline.degree); // 3
console.log('Length:', spline.length);
console.log('Is closed:', spline.isClosed); // falseMethods
Geometric Transformations
move() - Move
import { SplineEnt, Point2D } from 'vjcad';
const spline: SplineEnt = /* ... */;
// Simplified syntax (recommended)
spline.move([0, 0], [50, 50]);rotate() - Rotate
import { SplineEnt, Point2D } from 'vjcad';
const spline: SplineEnt = /* ... */;
// Simplified syntax (recommended)
spline.rotate([0, 0], Math.PI / 4); // Rotate 45° around originscale() - Scale
import { SplineEnt, Point2D } from 'vjcad';
const spline: SplineEnt = /* ... */;
// Simplified syntax (recommended)
spline.scale([0, 0], 2); // Scale 2x with origin as centermirror() - Mirror
import { SplineEnt, Point2D } from 'vjcad';
const spline: SplineEnt = /* ... */;
// Simplified syntax (recommended)
spline.mirror([0, 0], [100, 0]); // Mirror along X axisSerialization
import { SplineEnt } from 'vjcad';
const spline = new SplineEnt();
spline.setControlPoints([[0, 0], [50, 100], [100, 50], [150, 0]]);
spline.setDefaults();
// Export
const dbData = spline.toDb();
console.log(dbData);
// Import
const newSpline = new SplineEnt();
newSpline.fromDb(dbData);Complete Examples
Create Simple Spline Curve
import { Engine, SplineEnt } from 'vjcad';
// Create spline using simplified interface
const spline = new SplineEnt();
spline.setControlPoints([
[0, 0],
[30, 80],
[70, 20],
[100, 100]
]);
spline.setDefaults();
Engine.addEntities(spline);
Engine.pcanvas.zoomExtents();Fit Points Spline Curve
import { Engine, SplineEnt } from 'vjcad';
// Fit point mode: curve passes exactly through all points
const fitSpline = new SplineEnt();
fitSpline.setFitPoints([
[0, 0], [30, 60], [70, 20], [110, 80], [150, 30], [200, 50]
]);
fitSpline.setDefaults();
fitSpline.color = 1;
// Comparison: control point mode with the same points
const ctrlSpline = new SplineEnt();
ctrlSpline.setControlPoints([
[0, 0], [30, 60], [70, 20], [110, 80], [150, 30], [200, 50]
]);
ctrlSpline.setDefaults();
ctrlSpline.color = 3;
Engine.addEntities(fitSpline, ctrlSpline);
// Red curve passes through all points, green curve is "pulled toward" but doesn't pass throughCreate Weighted Spline Curve
import { Engine, SplineEnt } from 'vjcad';
// Weights affect how strongly the curve is "attracted" to control points
const spline = new SplineEnt();
spline.setControlPoints([
[0, 0],
[[50, 100], 2], // weight 2, curve closer to this point
[100, 50],
[[150, 100], 0.5], // weight 0.5, curve farther from this point
[200, 0]
]);
spline.setDefaults();
Engine.addEntities(spline);Chain Call to Create Spline Curve
import { Engine, SplineEnt } from 'vjcad';
const spline = new SplineEnt();
// Chain add control points
spline.addControlPoint([0, 0])
.addControlPoint([25, 50])
.addControlPoint([50, 0])
.addControlPoint([75, 50])
.addControlPoint([100, 0]);
spline.setDefaults();
Engine.addEntities(spline);Draw Wave Line
import { Engine, SplineEnt } from 'vjcad';
function drawWave(startX: number, startY: number, amplitude: number, wavelength: number, cycles: number) {
const points: [number, number][] = [];
const pointsPerCycle = 4; // 4 control points per cycle
for (let i = 0; i <= cycles * pointsPerCycle; i++) {
const x = startX + (i / pointsPerCycle) * wavelength;
const phase = (i % pointsPerCycle) / pointsPerCycle;
const y = startY + amplitude * Math.sin(phase * 2 * Math.PI);
points.push([x, y]);
}
const spline = new SplineEnt();
spline.setControlPoints(points);
spline.setDefaults();
Engine.addEntities(spline);
return spline;
}
// Draw wave line with 3 cycles
drawWave(0, 100, 30, 50, 3);Copy and Modify Spline Curve
import { Engine, SplineEnt, Point2D } from 'vjcad';
// Create original spline
const original = new SplineEnt();
original.setControlPoints([[0, 0], [50, 100], [100, 0]]);
original.setDefaults();
// Copy using simplified interface
const copy = new SplineEnt();
copy.setControlPoints(original.getControlPointsWithWeight());
copy.setDefaults();
// Move copy
copy.move([0, 0], [0, 50]);
Engine.addEntities(original, copy);Next Steps
- Polyline (PolylineEnt) - Polyline entity details
- Arc Entity (ArcEnt) - Arc entity details
- Bezier Curve - Spline curve geometry calculation