Advice on Bezier curve class implementation
-
Hello,
I am in the process of writing a framework for interactive curve editing in Qt, for use in developing an engineering design software. I would like the user to be able to create Bezier curves of varying order (quadratic, cubic, quartic, etc...). By the way, the order describes how many control points, or degrees of freedom, the user has to shape the curve. Given that the math is very similar between curves of varying order, I have decided to create a base class BezierCurve with virtual method computeBezier which each derived class implements slightly differently depending on the order of the curve.
In order for classes derived from BezierCurve to communicate the curve data to other classes or GUI elements, I wanted to use a struct defined in the BezierCurve class, with private members which the derived Bezier classes can write/read using public getters and setters. Other classes not derived from BezierCurve base class can only read the struct, not write to it. I think this is a pretty good way to enforce encapsulation in this system.
I have two questions:
-
Should I initialize the struct members in the constructor of BezierCurve via an initializer list? If so, how do I do this? I have heard that this is generally the idiomatic way to do things in C++, but I am not really sure how to go about doing it.
-
I would greatly appreciate constructive criticism of my current code from someone with more experience before moving forward with this implementation.
I am using QT 6 with C++, running on Windows 11.
Thank you in advance for any advice offered!
Here is my code for the base BezierCurve class, pasted below:
#ifndef BEZIERCURVE_H #define BEZIERCURVE_H #include <QObject> #include <QList> #include <QPointF> // BezierCurve class is the parent class for creating Bezier Curves // In order to use signals/slots, this class inherits QObject class BezierCurve : public QObject { private: // Set as private for encapsulation struct DataPort { // Data port that contains Bezier-related data to pass to other classes public: QList<QPointF> ctrlPts; // Contains control points QList<QPointF> bezierData; // Contains Bezier Curve data in coordinate space }; virtual QList<QPointF> computeBezier() = 0; // Declaration of pure virtual method to compute the curve DataPort DataPort_Bezier; public: // Put constructor here, use initializer list for struct members?? void getCtrlPts(); void getBezier(); void setCtrlPts(); void setBezier(); }; #endif // BEZIERCURVE_H -
-
Hi,
Can you show an example of class derived from that one ?
Maybe also a sample usage.
This would allow for better understanding what you want to implement and improved criticism. -
I don't currently have any implementation examples of derived classes because I wanted to try and establish the parent class beforehand. However, I will try to make as much sense as to what I want the derived classes to function/look like. Basically, the derived classes will override the computeBezier method, which will make use of this equation which calculates the x-y coordinates of the bezier curve based on control points P0, P1, P2, P3 (the curve is a cubic in this case, hence the highest degree of 3 in the equation)

The ctrlPts variable will be a list that stores points which represent the positions of each control point in graphics view space (i.e, pixel coordinates).
Ideally, derived classes will have a copy of the DataPort struct (that they inherit from base class) in which they store bezier curve data (control point locations and bezier curve coordinates) via the public setter method, which will look something like:
void setBezier() {
DataPort_Bezier.bezierData = computeBezier();
} // this setter will set the Bezier curve data in the struct using the computeBezier methodMy main question was, how do I initialize these struct variables (which are QLists) as empty lists each time a derived class is instantiated?
I apologize that I couldn't provide a coded example, and I understand if this hinders the ability to provide criticism on the code I have provided thus far. If I can figure out the first question, I will make a first-pass attempt at implementing a derived class so I can add it to this topic
-
The your first issue is: making DataPort private in your base class means that none of the derived class will know about it. See the cpp FAQ about access rules.