Search code examples
mathgraphicsmodelbeziercurve

What is a generic data structure for bezier curves or b-splines?


I am wondering how you would model arbitrarily complex Bézier curves. I am not quite understanding the underlying abstraction yet of what a bezier curve is fundamentally composed of, as there are too many equations. I would like to have a generic struct that defines a bezier curve. The SVG path gives many examples of the types of curves you can create. They include linear, cubic, and quadratic bezier curves.

If a B-spline is a better generic model, then that would be fine to use too. I am not familiar with those yet tho. Difference between bezier segment and b-spline. I guess "a B-spline curve is a curve that consists of Bezier curves as segments", so that is what I am looking for.

SVG docs say:

Cubic Béziers take in two control points for each point.

<path d="M 10 10 C 20 20, 40 20, 50 10" stroke="black" fill="transparent"/>

Several Bézier curves can be stringed together to create extended, smooth shapes. Often, the control point on one side of a point will be a reflection of the control point used on the other side to keep the slope constant. In this case, a shortcut version of the cubic Bézier can be used, designated by the command S (or s).

<path d="M 10 80 C 40 10, 65 10, 95 80 S 150 150, 180 80" stroke="black" fill="transparent"/>

The other type of Bézier curve, the quadratic curve called with Q, is actually a simpler curve than the cubic one. It requires one control point which determines the slope of the curve at both the start point and the end point. It takes two parameters: the control point and the end point of the curve.

<path d="M 10 80 Q 95 10 180 80" stroke="black" fill="transparent"/>

Arcs and NURBS (non-uniform rational B-splines) are more complex than just plain bezier curves, but it would be nice if the model could be generalized enough to include these as well. Basically I would like a generic model of bezier curves/b-splines/nurbs to use in a drawing/graphics framework, and not sure what that would be.

  • Must each bezier class be implemented separately, or can they be combined into one generic class?
  • If separate, are they each basically just an array of control points?

So basically I start to think:

class CubicBezierCurve
  include ActiveModel::Model

  has_many :control_points
end

class ControlPoint
  include ActiveModel::Model

  attr_accessor :x, :y
end

But that doesn't quite seem right. A primitive cubic bezier curve, for instance, consists of 2 control points for each point. So perhaps (though, starting to get lost):

class CubicBezierCurve
  include ActiveModel::Model

  has_many :control_points, class_name: 'CubicBezierCurveControlPoint'
end

class CubicBezierCurveControlPoint
  include ActiveModel::Model

  attr_accessor :x, :y
end

class Point
  include ActiveModel::Model

  attr_accessor :x, :y
end

Basically, what is a good generic model for these 3 types of bezier curves (linear, cubic, and quadratic). If it's possible to make them all aspects of the same generic model that would be ideal (as it would mean the fewest number of classes), but if it requires class-specific other classes (like those specific to a cubic bezier curve), that would be fine too.

Implementation can be in any language, such as C structs, typescript, or Ruby models, Python classes, etc..

The reason for this question is so I can then build a DSL for creating curves on top of it, like the SVG path syntax. But the underlying data model will be the compile target.

For further reference, I will be researching these:

This is just for 2D graphics.


Solution

  • The most generic data structure for a Bezier curve is simply one that contains an array of control points. The degree of the Bezier curve is the number of control points - 1. So, linear, quadratic and cubic Bezier curves can all use the same data structure with difference in number of control points.

    For B-spline curve, the generic data structure will contain

    • Degree (D)
    • Number of control points (N)
    • Array of control points
    • Knot sequence.

    The knot sequence is simply a "double[ ]" of length = N+D+1. The knot values need to be in non-decreasing order.