Tuesday, January 28, 2025

B-Spline curve in Javafx...

 A B-spline (Basis Spline) is a type of smooth, piecewise-defined curve commonly used in computer graphics, computer-aided design (CAD), and other computational fields. It generalizes Bézier curves by providing greater flexibility and control over the shape of the curve while maintaining important mathematical properties like smoothness and continuity.


Key Properties of B-Splines

  1. Piecewise Polynomial:

    • A B-spline curve is defined by connecting multiple polynomial segments, ensuring a smooth transition between them.
  2. Control Points:

    • A B-spline is influenced by a set of control points. These points do not necessarily lie on the curve, but they define its general shape.
  3. Degree (Order):

    • The degree of the B-spline determines the complexity of the curve segments (linear, quadratic, cubic, etc.).
    • Higher-degree B-splines produce smoother curves.
  4. Knots:

    • A knot vector is used to divide the curve into segments and determines how the control points influence the curve. Knots can be uniform (evenly spaced) or non-uniform (custom spacing).
  5. Continuity:

    • The continuity of a B-spline curve depends on its degree and the knot vector. It ensures smooth transitions between segments (e.g., C0,C1,C2C^0, C^1, C^2 continuity).
  6. Local Control:

    • Modifying a control point affects only a portion of the curve, making B-splines highly versatile for designing complex shapes.

Mathematical Definition

A B-spline curve is defined as:

C(t)=i=0nNi,k(t)PiC(t) = \sum_{i=0}^{n} N_{i,k}(t) \mathbf{P}_i
  • Pi\mathbf{P}_i: Control points.

  • Ni,k(t)N_{i,k}(t): Basis functions of degree kk, calculated recursively using the Cox-de Boor recursion formula:

    Ni,0(t)={1if tit<ti+10otherwiseN_{i,0}(t) = \begin{cases} 1 & \text{if } t_i \leq t < t_{i+1} \\ 0 & \text{otherwise} \end{cases} Ni,k(t)=ttiti+ktiNi,k1(t)+ti+k+1tti+k+1ti+1Ni+1,k1(t)N_{i,k}(t) = \frac{t - t_i}{t_{i+k} - t_i} N_{i,k-1}(t) + \frac{t_{i+k+1} - t}{t_{i+k+1} - t_{i+1}} N_{i+1,k-1}(t)
  • tt: Parametric value in the range of the knot vector.


Applications of B-Splines

  1. CAD and CAM:

    • Used for designing and manufacturing complex surfaces and shapes.
  2. Animation:

    • Smooth interpolation of motion paths or object deformation.
  3. Data Fitting:

    • Approximate noisy data points with smooth curves.
  4. Computer Graphics:

    • Modeling free-form curves and surfaces (e.g., NURBS, a special type of B-spline).
  5. Image Processing:

    • Resampling and interpolation of image data.

Advantages of B-Splines

  • Greater flexibility than Bézier curves.
  • Local control ensures efficiency in complex modeling tasks.
  • Customizable smoothness and continuity.
  • Can represent a Bézier curve or polynomial curve as a special case.



And here we go... the source code of B-Spline implemented in Javafx...

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Line;
import javafx.scene.shape.Path;
import javafx.scene.shape.MoveTo;
import javafx.scene.shape.CubicCurveTo;
import javafx.stage.Stage;

import java.util.ArrayList;
import java.util.List;

public class BSplineDemo extends Application {

private final List<Circle> controlPoints = new ArrayList<>();
private final Path bSplinePath = new Path();

@Override
public void start(Stage primaryStage) {
// Create the main pane
Pane pane = new Pane();
pane.setStyle("-fx-background-color: #f4f4f4");

// Add initial control points
addControlPoint(pane, 100, 200);
addControlPoint(pane, 200, 100);
addControlPoint(pane, 300, 250);
addControlPoint(pane, 400, 150);
addControlPoint(pane, 500, 200);

// Configure the B-spline path
bSplinePath.setStroke(Color.BLACK);
bSplinePath.setStrokeWidth(2);
bSplinePath.setFill(null);

// Add path and points to the pane
pane.getChildren().add(bSplinePath);
updateBSpline();

// Create the scene
Scene scene = new Scene(pane, 600, 400);
primaryStage.setTitle("B-Spline Demo");
primaryStage.setScene(scene);
primaryStage.show();
}

// Adds a draggable control point
private void addControlPoint(Pane pane, double x, double y) {
Circle point = new Circle(x, y, 8, Color.RED);
point.setStroke(Color.BLACK);
point.setStrokeWidth(1);
point.setOnMouseDragged(event -> {
point.setCenterX(event.getX());
point.setCenterY(event.getY());
updateBSpline();
});
controlPoints.add(point);
pane.getChildren().add(point);
}

// Updates the B-spline path
private void updateBSpline() {
if (controlPoints.size() < 4) {
bSplinePath.getElements().clear(); // Clear path if not enough points
return;
}

bSplinePath.getElements().clear();

// Use the de Boor algorithm for cubic B-spline interpolation
for (int i = 1; i < controlPoints.size() - 2; i++) {
Circle p0 = controlPoints.get(i - 1);
Circle p1 = controlPoints.get(i);
Circle p2 = controlPoints.get(i + 1);
Circle p3 = controlPoints.get(i + 2);

// Define cubic curve control points
double x1 = (p0.getCenterX() + 4 * p1.getCenterX() + p2.getCenterX()) / 6;
double y1 = (p0.getCenterY() + 4 * p1.getCenterY() + p2.getCenterY()) / 6;

double x2 = (p1.getCenterX() + 4 * p2.getCenterX() + p3.getCenterX()) / 6;
double y2 = (p1.getCenterY() + 4 * p2.getCenterY() + p3.getCenterY()) / 6;

double xControl1 = (2 * p1.getCenterX() + p2.getCenterX()) / 3;
double yControl1 = (2 * p1.getCenterY() + p2.getCenterY()) / 3;

double xControl2 = (p1.getCenterX() + 2 * p2.getCenterX()) / 3;
double yControl2 = (p1.getCenterY() + 2 * p2.getCenterY()) / 3;

// First point
if (i == 1) {
bSplinePath.getElements().add(new MoveTo(x1, y1));
}

// Add cubic segment
bSplinePath.getElements().add(new CubicCurveTo(xControl1, yControl1, xControl2, yControl2, x2, y2));
}
}

public static void main(String[] args) {
launch(args);
}
}

No comments: