spline
本文回答:
SplineEnt样条曲线 —— 拟合点 / 控制点、阶数、闭合、用法。
一、构造(位置参数)
// new SplineEnt(fitPts?, degree?) —— 拟合点是第一参
const spline = new vjmapext.SplineEnt(
[[0,0], [50,100], [150,80], [200,0], [250,100]],
3 // degree,默认 3(拟合点模式下不影响形状,见第四节)
);
spline.color = 0xff4488;
spline.lineWidth = 2;
mapcadLayer.addEntity(spline);
二、属性(d.ts 真实成员)
| 属性 | 类型 | 说明 |
|---|---|---|
fitPoints |
Point2D[] |
拟合点(曲线穿过;按 Catmull-Rom 插值) |
controlPoints |
Point2D[] |
B 样条控制点(多数不在曲线上;无权重/节点向量) |
degree |
number |
阶数,默认 3——只在控制点模式生效,拟合点模式忽略 |
isClosed |
boolean |
是否闭合(注意:不叫 closed) |
fillColor / fillOpacity / borderOpacity |
number | 闭合时填充 |
isFitMode |
getter | fitPoints.length >= 2 即为真——fitPoints 优先,controlPoints 有值也会被忽略(渲染/夹点/导出都走 activePoints) |
控制点模式:构造后改 spline.controlPoints = [...](d.ts 无 knots/weights 暴露)。要走控制点模式须保证 fitPoints.length < 2。
⚠️
controlPoints必须赋Point2D实例数组,不能赋裸[x,y]——clone()/move()/rotate()/scale()/mirror()对controlPoints无条件.map(p => p.clone()),裸数组会抛p.clone is not a function(addEntity的 undo 快照路径必触发)。而构造器new SplineEnt(fitPts)接受裸数组(内部Ut()转 Point2D)。赋值写法:s.controlPoints = pts.map(p => new Point2D(p[0], p[1]))。
三、闭合样条
const loop = new vjmapext.SplineEnt([[0,0],[100,80],[200,0],[150,-80],[50,-80]]);
loop.isClosed = true;
loop.fillColor = 0x4488ff;
mapcadLayer.addEntity(loop);
四、阶数(degree)何时生效
拟合点模式(构造传点,fitPoints.length >= 2)按 Catmull-Rom 插值渲染,degree 不参与——new SplineEnt(pts, 5) 与 new SplineEnt(pts) 画出来一样。degree 只在控制点模式(fitPoints.length < 2)下作 B 样条阶数(开口时自动夹到 控制点数 - 1):
const sp = new vjmapext.SplineEnt(); // 不传拟合点 → 控制点模式
sp.controlPoints = [[0,0],[50,200],[150,200],[200,0]].map(p => new vjmapext.Point2D(p[0], p[1]));
sp.degree = 2; // 此时 degree 才生效
mapcadLayer.addEntity(sp);
五、替代方案:贝塞尔
SplineEnt 不是严格 NURBS(拟合模式是 Catmull-Rom,控制点模式是无权重 B 样条);若只要光滑曲线,也可用辅助函数生成 PolylineEnt:
// polylineToBezierCurve 返回 BezierCurve 对象(控制点结构),
// 要再经 bezierCurveToPolyline 采样成点数组才能喂 PolylineEnt:
const curve = vjmap.polylineToBezierCurve([[0,0],[100,50],[200,0],[150,-50]]);
const smooth = new vjmapext.PolylineEnt(
vjmap.bezierCurveToPolyline(curve, 0.5) // precision?: number 采样精度
);
六、与 Polyline 的差别
| 特性 | SplineEnt | PolylineEnt |
|---|---|---|
| 光滑 | 拟合模式 Catmull-Rom(C1 连续) | 端点有折角 |
| bulge 弧 | 不需要 | 通过 bulgePoints 近似 |
| 交互夹点 | 拟合点 / 控制点 | 顶点 |
| 导出 DWG | 保留 SPLINE 类型 | 转 PLINE |
七、编辑
选中后夹点出现在拟合点(或控制点),拖动修改局部形状:
spline.fitPoints[1] = vjmapext.Point2D.fromArray([70, 150]);
spline.changed();
八、常见坑
- 构造是位置参数:
new SplineEnt(fitPts, degree)——options 对象不会生效(同 TextEnt)。 - 闭合属性是
isClosed,不是closed。 - 以为改 degree 能调平滑度:拟合点模式下 degree 被忽略(Catmull-Rom 固定);只有控制点模式才用,且开口样条会自动夹到
控制点数 - 1。 - 精确通过某点:必须用
fitPoints;controlPoints只决定形状。 - 大量 Spline 很慢:内部采样重建 Polyline;量大时直接生成 Polyline。