样条线
在 mxcad 中,我们可以通过实例化一个 McDbSpline() 对象来创建样条线。根据数据源的不同,主要有两种创建方式:通过拟合点 (Fit Points) 和通过控制点 (Control Vertices)。
1. 通过拟合点 (Fit Points) 绘制
这种方式通过指定一系列曲线必须经过的点来生成一条平滑的曲线,是交互式绘图中最常用的方法。
我们可以通过调用 McDbSpline() 实例对象的 setFitPoints() 方法来设置样条线的拟合数据。
点击 McDbSpline()、setFitPoints() 查看详细属性和方法说明。
setFitPoints() 参数说明
setFitPoints() 方法的参数 data 对象包含以下属性:
- degree: 样条曲线的次数(degree),表示曲线的数学阶次。通常,AutoCAD 中的样条曲线是三次曲线(degree 为 3),意味着它们是三阶多项式。
- fitTolerance: 拟合公差,这是一个数值,代表了拟合点到实际生成的样条曲线之间的最大允许距离。较小的值意味着样条曲线将更紧密地跟随拟合点,但可能会导致曲线更加复杂。
- tangentsExist: 一个布尔值,指示是否指定了起点切线和终点切线。如果为
true,则表示存在自定义的起始和结束切线方向,这可以控制曲线在端点处的方向。 - startTangent: 如果
tangentsExist为true,此参数是一个McGeVector3d对象,表示曲线起点的切线方向。它决定了曲线开始时的方向。 - endTangent: 类似于
startTangent,但如果tangentsExist为true,这个参数指定的是曲线结束时的切线方向,影响曲线如何到达其终点。 - fitPoints: 这是一个
McGePoint3dArray类型的数组,包含了一系列的三维点 (McGePoint3d),这些点是样条曲线要经过的拟合点。根据这些点的位置,mxcad会计算出一条平滑通过所有点的曲线。
以下代码演示了如何响应用户点击,动态预览并绘制一条拟合样条线。
typescript
import { MxCpp, MxCADUiPrPoint, McDbSpline, McGePoint3dArray, McGeVector3d } from "mxcad";
// 绘样条线函数
async function Mx_drawSpline() {
const getPoint = new MxCADUiPrPoint();
getPoint.setMessage("\n指定第一点:");
let prvPoint = await getPoint.go();
if (!prvPoint) return;
getPoint.setMessage("\n指定下一个点:");
let fitPoints = new McGePoint3dArray();
fitPoints.append(prvPoint);
// 样条线循环取点
while (true) {
getPoint.setBasePt(prvPoint as any);
if (fitPoints.length() == 1) {
getPoint.setUseBasePt(true);
} else {
getPoint.setUseBasePt(false);
// 动态绘制预览逻辑
getPoint.setUserDraw((pt, pw) => {
let tmpFitPoints = new McGePoint3dArray();
tmpFitPoints.copy(fitPoints);
tmpFitPoints.append(pt);
let tmpSPline = new McDbSpline();
tmpSPline.setFitPoints({
degree: 3,
fitTolerance: 0.000001,
tangentsExist: false,
startTangent: McGeVector3d.kIdentity,
endTangent: McGeVector3d.kIdentity,
fitPoints: tmpFitPoints,
});
pw.drawMcDbEntity(tmpSPline);
});
}
let pt = await getPoint.go();
if (!pt) break;
fitPoints.append(pt);
prvPoint = pt;
}
// 最终绘制实体
if (fitPoints.length() > 2) {
let sp = new McDbSpline();
sp.setFitPoints({
degree: 3,
fitTolerance: 0.000001,
tangentsExist: false,
startTangent: McGeVector3d.kIdentity,
endTangent: McGeVector3d.kIdentity,
fitPoints: fitPoints,
});
MxCpp.getCurrentMxCAD().drawEntity(sp);
}
}2. 通过控制点 (Control Vertices) 绘制
这种方式提供了更底层的控制,允许直接定义 NURBS(非均匀有理B样条)的数学数据。它通过控制点、节点向量和权重来精确定义曲线,适用于需要精确数学定义或从其他系统导入几何数据的场景。
我们可以通过调用 McDbSpline() 实例对象的 setNurbsData() 方法来设置这些 NURBS 数据。
点击 McDbSpline()、setNurbsData() 查看详细属性和方法说明。
setNurbsData() 参数说明
setNurbsData() 方法的参数 data 对象包含以下属性:
- degree: 曲线的次数(如 3 次)。
- rational: 是否为有理样条。若为
false,权重通常忽略或全为 1。 - closed: 曲线是否闭合。
- periodic: 曲线是否周期性。
- controlPoints:
McGePoint3dArray类型的数组,即控制点。这些点定义曲线的控制多边形,曲线通常不经过这些点(除首尾外),而是被它们“吸引”。 - knots:
McGeDoubleArray类型的数组,即节点向量。它定义了参数空间的划分,影响曲线段的连续性。节点数量通常等于控制点数量 + 次数 + 1。 - weights:
McGeDoubleArray类型的数组,即权重。若非有理样条,可为空。 - controlPtTol: 控制点容差。
- knotTol: 节点容差。
以下代码演示了如何手动构建控制点、节点向量并生成一条 NURBS 样条线。
typescript
import { MxCpp, McDbSpline, McGePoint3dArray, McGeDoubleArray, McGePoint3d } from "mxcad";
function Mx_DrawSpline() {
const mxcad = MxCpp.getCurrentMxCAD();
// 1. 创建样条线对象
const spline = new McDbSpline();
// 2. 设置控制点 (Control Vertices)
const controlPoints = new McGePoint3dArray();
controlPoints.append(new McGePoint3d(89.5, 174.5, 0));
controlPoints.append(new McGePoint3d(123.69, 226.98, 0));
controlPoints.append(new McGePoint3d(194.96, 336.35, 0));
controlPoints.append(new McGePoint3d(241.15, 63.93, 0));
controlPoints.append(new McGePoint3d(427.44, 306.12, 0));
controlPoints.append(new McGePoint3d(521.19, 159.27, 0));
controlPoints.append(new McGePoint3d(578.5, 69.5, 0));
// 3. 设置节点向量 (Knot Vector)
const knots = new McGeDoubleArray();
knots.append(0); knots.append(0); knots.append(0); knots.append(0); // 起点重复度
knots.append(130.82);
knots.append(272.65);
knots.append(424.77);
knots.append(664.03); knots.append(664.03); knots.append(664.03); knots.append(664.03); // 终点重复度
// 4. 设置权重 (Weights)
// 对于非有理样条,权重数组可以为空
const weights = new McGeDoubleArray();
// 5. 使用 setNurbsData 设置数据
spline.setNurbsData({
degree: 3,
rational: false,
closed: false,
periodic: false,
controlPoints: controlPoints,
knots: knots,
weights: weights,
controlPtTol: 1e-9,
knotTol: 1e-9
});
// 6. 绘制并验证
mxcad.drawEntity(spline);
mxcad.zoomAll();
mxcad.updateDisplay();
// 验证数据读取
const data = spline.getNurbsData();
console.log("样条线数据验证:");
console.log("degree:", data.degree);
console.log("controlPoints count:", data.controlPoints.length());
console.log("knots count:", data.knots.length());
}