样条曲线实体 (SplineEnt)
大约 5 分钟
样条曲线实体 (SplineEnt)
SplineEnt 表示 CAD 中的样条曲线实体,用于创建光滑的自由曲线。
概述
样条曲线(NURBS曲线)通过一组控制点定义,可以创建任意形状的光滑曲线。每个控制点可以有一个权重值来影响曲线的形状。
构造函数
import { SplineEnt, SplineControlPoint, Point2D } from 'vjcad';
// 创建样条曲线
const spline = new SplineEnt();
// 传统方式:添加控制点
const cp1 = new SplineControlPoint();
cp1.point2d = new Point2D(0, 0);
cp1.weight = 1;
spline.controlPoints.items.push(cp1);
// ... 添加更多控制点简化接口(推荐)
为了简化样条曲线的创建和操作,提供了更简洁的数组接口。
设置和添加控制点
import { SplineEnt, Engine } from 'vjcad';
const spline = new SplineEnt();
// 方式1: 批量设置控制点(推荐)
// 格式: [x, y] 表示坐标(权重默认为1),[[x, y], weight] 表示带权重的点
spline.setControlPoints([
[0, 0],
[50, 100],
[100, 50],
[[150, 100], 0.5], // 带权重
[200, 0]
]);
// 方式2: 链式添加单个控制点
spline.addControlPoint([0, 0])
.addControlPoint([50, 100])
.addControlPoint([100, 50], 0.5) // 第二参数是权重
.addControlPoint([150, 0]);
// 方式3: 批量追加控制点
spline.addControlPoints([[200, 50], [[250, 100], 0.8], [300, 50]]);
spline.setDefaults();
Engine.addEntities(spline);获取控制点
const spline: SplineEnt = /* ... */;
// 获取单个控制点坐标
const [x, y] = spline.getControlPoint(0);
// 获取单个控制点坐标和权重
const [[px, py], weight] = spline.getControlPointWithWeight(3);
// 获取所有控制点坐标(不含权重)
const coords = spline.getControlPoints(); // [[0,0], [50,100], [100,50], ...]
// 获取所有控制点(含权重,与 setControlPoints 格式一致)
const full = spline.getControlPointsWithWeight();
// [[0,0], [50,100], [100,50], [[150,100], 0.5], ...]
// 复制到另一个样条曲线
const spline2 = new SplineEnt();
spline2.setControlPoints(spline.getControlPointsWithWeight());简化接口 API 参考
| 方法 | 参数 | 返回值 | 说明 |
|---|---|---|---|
addControlPoint(coord, weight?) | [x, y], number | this | 添加单个控制点,支持链式调用 |
addControlPoints(points) | 见下方格式 | this | 批量追加控制点 |
setControlPoints(points) | 见下方格式 | this | 设置所有控制点(替换现有) |
getControlPoint(index) | number | [x, y] | 获取指定索引的控制点坐标 |
getControlPoints() | - | [x, y][] | 获取所有控制点坐标 |
getControlPointWithWeight(index) | number | [[x, y], weight] | 获取控制点坐标和权重 |
getControlPointsWithWeight() | - | 见下方格式 | 获取所有控制点(含权重) |
点数组格式:
- 无权重(默认为1):
[x, y] - 有权重:
[[x, y], weight] - 混合:
[[0, 0], [50, 100], [[100, 50], 0.5], [150, 0]]
推荐使用简化接口
简化接口比传统的 SplineControlPoint + Point2D 方式更简洁,代码更易读。getControlPointsWithWeight() 的返回格式与 setControlPoints() 完全兼容,方便复制和序列化操作。
属性
基本属性
| 属性 | 类型 | 读写 | 说明 |
|---|---|---|---|
controlPoints | SplineControlPoints | 读写 | 控制点集合 |
fitPoints | SplineFitPoints | 读写 | 拟合点集合 |
degree | number | 读写 | 曲线阶数(通常为3) |
knots | SplineKnots | 读写 | 节点向量 |
计算属性(只读)
| 属性 | 类型 | 说明 |
|---|---|---|
length | number | 样条曲线总长度 |
isClosed | boolean | 是否闭合 |
startPoint | Point2D | 起始点 |
endPoint | Point2D | 结束点 |
numberOfControlPoints | number | 控制点数量 |
import { SplineEnt } from 'vjcad';
const spline = new SplineEnt();
spline.setControlPoints([
[0, 0], [50, 100], [100, 50], [150, 100], [200, 0]
]);
console.log('控制点数:', spline.numberOfControlPoints); // 5
console.log('阶数:', spline.degree); // 3
console.log('长度:', spline.length);
console.log('是否闭合:', spline.isClosed); // false方法
几何变换
move() - 移动
import { SplineEnt, Point2D } from 'vjcad';
const spline: SplineEnt = /* ... */;
// 简化写法(推荐)
spline.move([0, 0], [50, 50]);rotate() - 旋转
import { SplineEnt, Point2D } from 'vjcad';
const spline: SplineEnt = /* ... */;
// 简化写法(推荐)
spline.rotate([0, 0], Math.PI / 4); // 绕原点旋转 45°scale() - 缩放
import { SplineEnt, Point2D } from 'vjcad';
const spline: SplineEnt = /* ... */;
// 简化写法(推荐)
spline.scale([0, 0], 2); // 以原点为中心放大 2 倍mirror() - 镜像
import { SplineEnt, Point2D } from 'vjcad';
const spline: SplineEnt = /* ... */;
// 简化写法(推荐)
spline.mirror([0, 0], [100, 0]); // 沿 X 轴镜像序列化
import { SplineEnt } from 'vjcad';
const spline = new SplineEnt();
spline.setControlPoints([[0, 0], [50, 100], [100, 50], [150, 0]]);
spline.setDefaults();
// 导出
const dbData = spline.toDb();
console.log(dbData);
// 导入
const newSpline = new SplineEnt();
newSpline.fromDb(dbData);完整示例
创建简单样条曲线
import { Engine, SplineEnt } from 'vjcad';
// 使用简化接口创建样条曲线
const spline = new SplineEnt();
spline.setControlPoints([
[0, 0],
[30, 80],
[70, 20],
[100, 100]
]);
spline.setDefaults();
Engine.addEntities(spline);
Engine.pcanvas.zoomExtents();创建带权重的样条曲线
import { Engine, SplineEnt } from 'vjcad';
// 权重可以影响曲线对控制点的"吸引力"
const spline = new SplineEnt();
spline.setControlPoints([
[0, 0],
[[50, 100], 2], // 权重为2,曲线更靠近此点
[100, 50],
[[150, 100], 0.5], // 权重为0.5,曲线远离此点
[200, 0]
]);
spline.setDefaults();
Engine.addEntities(spline);链式调用创建样条曲线
import { Engine, SplineEnt } from 'vjcad';
const spline = new SplineEnt();
// 链式添加控制点
spline.addControlPoint([0, 0])
.addControlPoint([25, 50])
.addControlPoint([50, 0])
.addControlPoint([75, 50])
.addControlPoint([100, 0]);
spline.setDefaults();
Engine.addEntities(spline);绘制波浪线
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个控制点
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;
}
// 绘制3个周期的波浪线
drawWave(0, 100, 30, 50, 3);复制和修改样条曲线
import { Engine, SplineEnt, Point2D } from 'vjcad';
// 创建原始样条曲线
const original = new SplineEnt();
original.setControlPoints([[0, 0], [50, 100], [100, 0]]);
original.setDefaults();
// 使用简化接口复制
const copy = new SplineEnt();
copy.setControlPoints(original.getControlPointsWithWeight());
copy.setDefaults();
// 移动副本
copy.move([0, 0], [0, 50]);
Engine.addEntities(original, copy);下一步
- 多段线 (PolylineEnt) - 多段线实体详解
- 圆弧实体 (ArcEnt) - 圆弧实体详解
- 贝塞尔曲线 - 样条曲线几何计算