Skip to content

Spline ​

In mxcad, we can create splines by instantiating a McDbSpline() object. Depending on the data source, there are mainly two ways to create them: via Fit Points and via Control Vertices.

1. Drawing via Fit Points ​

This method generates a smooth curve by specifying a series of points that the curve must pass through. It is the most commonly used method in interactive drawing.

We can set the fit data for the spline by calling the setFitPoints() method on an instance of McDbSpline().

Click McDbSpline(), setFitPoints() to view detailed property and method descriptions.

setFitPoints() Parameter Description ​

The data object parameter for the setFitPoints() method contains the following properties:

  • degree: The degree of the spline curve, representing the mathematical order. Typically, splines in AutoCAD are cubic curves (degree is 3), meaning they are third-order polynomials.
  • fitTolerance: Fit tolerance, a numerical value representing the maximum allowed distance between the fit points and the actual generated spline curve. A smaller value means the spline will follow the fit points more closely, but may result in a more complex curve.
  • tangentsExist: A boolean value indicating whether start and end tangents are specified. If true, it indicates the existence of custom start and end tangent directions, which can control the direction of the curve at the endpoints.
  • startTangent: If tangentsExist is true, this parameter is a McGeVector3d object representing the tangent direction at the start of the curve. It determines the direction in which the curve begins.
  • endTangent: Similar to startTangent, but if tangentsExist is true, this parameter specifies the tangent direction at the end of the curve, affecting how the curve reaches its endpoint.
  • fitPoints: An array of type McGePoint3dArray containing a series of 3D points (McGePoint3d). These are the fit points that the spline curve will pass through. Based on the positions of these points, mxcad calculates a smooth curve passing through all of them.

The following code demonstrates how to respond to user clicks to dynamically preview and draw a fit spline.

typescript
import {
  MxCpp,
  MxCADUiPrPoint,
  McDbSpline,
  McGePoint3dArray,
  McGeVector3d,
} from "mxcad";

// Draw spline function
async function Mx_drawSpline() {
  const getPoint = new MxCADUiPrPoint();
  getPoint.setMessage("\nSpecify the first point:");
  let prvPoint = await getPoint.go();
  if (!prvPoint) return;

  getPoint.setMessage("\nSpecify the next point:");
  let fitPoints = new McGePoint3dArray();
  fitPoints.append(prvPoint);

  // Spline loop to get points
  while (true) {
    getPoint.setBasePt(prvPoint as any);
    if (fitPoints.length() == 1) {
      getPoint.setUseBasePt(true);
    } else {
      getPoint.setUseBasePt(false);
      // Dynamic drawing preview logic
      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;
  }

  // Final drawing entity
  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. Drawing via Control Vertices ​

This method provides lower-level control, allowing direct definition of NURBS (Non-Uniform Rational B-Spline) mathematical data. It precisely defines the curve through control points, knot vectors, and weights, suitable for scenarios requiring precise mathematical definitions or importing geometric data from other systems.

We can set this NURBS data by calling the setNurbsData() method on an instance of McDbSpline().

Click McDbSpline(), setNurbsData() to view detailed property and method descriptions.

setNurbsData() Parameter Description ​

The data object parameter for the setNurbsData() method contains the following properties:

  • degree: The degree of the curve (e.g., 3).
  • rational: Whether it is a rational spline. If false, weights are usually ignored or all set to 1.
  • closed: Whether the curve is closed.
  • periodic: Whether the curve is periodic.
  • controlPoints: An array of type McGePoint3dArray, which are the Control Vertices. These points define the control polygon of the curve. The curve usually does not pass through these points (except for the start and end), but is "attracted" by them.
  • knots: An array of type McGeDoubleArray, which is the Knot Vector. It defines the division of the parameter space, affecting the continuity of curve segments. The number of knots is usually equal to number of control points + degree + 1.
  • weights: An array of type McGeDoubleArray, which are the Weights. If it is a non-rational spline, this can be empty.
  • controlPtTol: Control point tolerance.
  • knotTol: Knot tolerance.

The following code demonstrates how to manually construct control points, knot vectors, and generate a NURBS spline.

typescript
import {
  MxCpp,
  McDbSpline,
  McGePoint3dArray,
  McGeDoubleArray,
  McGePoint3d,
} from "mxcad";

function Mx_DrawSpline() {
  const mxcad = MxCpp.getCurrentMxCAD();

  // 1. Create spline object
  const spline = new McDbSpline();

  // 2. Set 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. Set Knot Vector
  const knots = new McGeDoubleArray();
  knots.append(0);
  knots.append(0);
  knots.append(0);
  knots.append(0); // Start point multiplicity
  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); // End point multiplicity

  // 4. Set Weights
  // For non-rational splines, the weights array can be empty
  const weights = new McGeDoubleArray();

  // 5. Use setNurbsData to set data
  spline.setNurbsData({
    degree: 3,
    rational: false,
    closed: false,
    periodic: false,
    controlPoints: controlPoints,
    knots: knots,
    weights: weights,
    controlPtTol: 1e-9,
    knotTol: 1e-9,
  });

  // 6. Draw and verify
  mxcad.drawEntity(spline);
  mxcad.zoomAll();
  mxcad.updateDisplay();

  // Verify data reading
  const data = spline.getNurbsData();
  console.log("Spline data verification:");
  console.log("degree:", data.degree);
  console.log("controlPoints count:", data.controlPoints.length());
  console.log("knots count:", data.knots.length());
}