Connecting Catmull-Rom splines together and calculating its length? - c++

I'm trying to create a class which takes in any number of points (position and control) and creates a catmull-rom spline based on the information given.
What I'm doing - and I'm really unsure if this is the right way to do it - is storing each individual point in a class like so:
class Point
{
public:
Vector3 position;
Vector3 control;
}
Where obviously position is the position of the point and control is the control point.
My issue is connecting up the splines - obviously given the above class holding a point in the spline array indicates that any given position can only have one control point. So when having three or more points in a catmull rom spline the various individual catmull-rom splines which are being connected share one position and one control with another such spline.
Now with position being the same is required - since I want to create splines which are continuous between themselves. However I really wonder, should the control points also be the same between the two splines? With a bit of fiddling of the control points I can make it appear to be transitioning smoothly from one spline to another however I must emphasize that I'm not sure if the way they are transitioning is consistent with how catmull-rom splines form their shape. I'd much rather do it correctly than sit on my hands and rationalize that it's good enough.
Obviously the second part of my question is self explanatory: Given two control and position points how do I calculate the length of a catmull-rom spline?

To define the spline between two control points, the Catmull-Rom spline needs the control points and the tangent vector at each control point. However, the tangent vector at internal (i.e. non-endpoint) control points is defined by the control points on either side of it:
T(Pn) = (Pn+1 - Pn-1) / 2. For closed curves, the spline is completely defined by the set of control points. For non-closed curves, you need to also supply the tangent vector at the first and last control point. This is commonly done: T(P0) = P1 - P0 and T(Pn) = Pn - Pn-1.
Thus, for closed curves, your data structure is just a list of control points. For general splines, it's a list of points plus the first and last normal vector.
If you want to have a cardinal spline, then you can add a weighting factor to the tangent vector calculation as in the Wikipedia article.
To calculate the length of such a spline, one approach would be to approximate it by evaluating the spline at many points and then calculating the linear distance between each neighboring pair of points.

With regards to measuring the lengths, you can do this with calculus since its a polynomial spline. You need to do integrate the distance function across the line. Its described quite well on Wikipedia...

Related

Duplicate points along NURBS curve

in my current project I have implemented NURBS curves and at the beginning of the curve I have some 3D points, which are all located in the normal plane of the point (u = 0.0). Now I want to copy these points to other locations of the curve (e.g. u = 0.5) to create some kind of extrude / sweep mechanism. My theoretical approach is to create a local coordinate system in point 0.0 and to calculate the coordinates of every point in relation to this system. Then I can create local coordinate systems at the desired points and place the points there. My problem is that with the first derivation of the NURBS curve I can get the tangent and therefore the normal plane of the point / system (local X direction) but I don't know how to orient the system. My first idea was to take the second derivative of the NURBS curve and use this to calculate the local Y and Z axis of the system but the results of the second derivatives does not seem to be suitable for this approach.
Is there a common approach to solve this problem?
As an additional question I am wondering how to dictate the tangent vector of a given control point, for example the tangent of the first control point. Currently I solve this by dictating the position of the second control point, which seems to be not very elegant.
We solved the same problem using this approach:
https://www.microsoft.com/en-us/research/wp-content/uploads/2016/12/Computation-of-rotation-minimizing-frames.pdf
Look like you would like to find a local coordinate system at any given point on the NURBS curve. If this is the case, Frenet frame is the typical choice. See this link for more details.
As for the issue of "tangent vector of a given control point", since control points in general do not lie on the NURBS curve, it does not have a tangent vector. If you really need one for some special reason, you can use the tangent vector at the point on the curve that is closest to the control point.

Draw a bezier curve(s) with a set of points from a vector

I was wondering what would be the best and less complicated way of drawing a bezier curve in c++ with a set of points (roughly 100+ points) that are stored inside a vector
From my understanding:
-Bezier curves consist of 4 control points, the points in the middle dictate the direction/tangent of the curve
Would one possible method be to breakdown the points into different segments and from each segment determine the control points and tangents?
It is called a cubic spline and if you search you might find some C++ code for it. I used the free Fortran code from Numerical Recipes Online and ported it to C# with no problems.
Would one possible method be to
breakdown the points into different
segments and from each segment
determine the control points and
tangents?
Yes, basically one connects the line segments end-to-end such that the slope approaching the end of the line segment is equal on both sides of the connection point. This is called a cubic spline. You can find algorithms for this here.

how to interpret a freetype glyph outline when the first point on the contour is off curve

I'm actually working on a renderer that converts freetype glyphs into polylines to control a laser marking system. The problem I have is that I don't know how to handle correctly a contour beginning with an off curve point (99.9% begin with on curve points!). I've searched quite a while now for informations but I couldn't find anything useful.
Thanks for your help
FreeType uses three types of points: on-curve, quadratic control points (also known as 'conic') and cubic control points. The quadratic control points are grouped with on-curve points on either side of them to form the three points needed to define a quadratic Bézier spline. The cubic control points must occur in pairs, and are grouped with on-curve points on either side to make up the four points needed for a cubic Bézier spline.
However, there is a short-hand notation for quadratic points only. Where quadratic points occur next to each other, an on-curve control point is interpolated between them. And there is another convention, that if a closed path starts with a quadratic point, the last point of the path is examined, and if it is quadratic, an on-curve point is interpolated between them, and the path is taken to start with that on-curve point; if the last point is not a quadratic control point, it is itself used for the start point.
If you want to see exactly how this is done, please look at the FreeType source code. The function FT_Outline_Decompose traverses a path and converts it into a series of lines and curves of both types. It's in this file:
http://git.savannah.gnu.org/cgit/freetype/freetype2.git/tree/src/base/ftoutln.c
The part of especial interest starts with this comment (note again that 'conic' means the same as 'quadratic' in this context):
/* first point is conic control. Yes, this happens. */

How do bezier handles work?

On Wikipedia I found information about bezier curves and made a function to generate the inbetween points for a bezier polygon. I noticed that Expression Design uses bezier handles. This allows a circle to be made with 4 points each with a bezier handle.
I'm just not sure mathematically how this works in relation with the formula for bezier point at time T. How do these handle vectors work to modify the shape? Basically what's there relation to the bezier formula?
Thanks
Basically, the 4 points used in the cubic bezier formula are the 2 points the curve is between, plus the two points of the handles on that "side" of the first two points (1 handle from each of the first points). If there are double handles on each point, the handles on the "opposite" side of the points from the curve currently being calculated are ignored (they're used for generating the curve that comes out of the opposite side).
The actual generation method used for cubic bezier curves is outlined on the Wikipedia page you linked in your question.
The 4 points of a Bezier segment are the two endpoints of the segment and two handles, one per endpoint. The handles determine the initial direction of the line as it leaves the endpoint. The distance from the handle to the endpoint determines the amount of "pull" that the handle exerts on the path.
Often you will find multiple Beziers connected end to end, with the endpoint of one being shared as the starting point of the next. This guarantees an unbroken curve. If the handles on either side of a point are directly across from each other, the angle at the joint will match up; if the handles are also the same distance from the point, the angle will be completely smooth and there will not be a visible discontinuity at the point.
An interesting property of Bezier segments is that the curve will fit entirely within the parallelogram defined by the 4 points.
What I have been describing is the most common form of Bezier, the cubic. There is also a quadratic which only has a single handle between the two endpoints; the most common application is TrueType fonts.

Area of a irregular shape

I have set of points which lies on the image. These set of points form a irregular closed shape. I need to find the area of this shape. Does any body which is the normal algorithm used for calculating the area ? Or is there any support available in libraries such as boost? I am using C++.
If you polygon is simple (it doesn't have any point in common except for the pairs of consecutive segments) then wikipedia comes to help you:
The formula for the area is
(it assumes that the last point is the same of the first one)
You can easily implement it as
float area = 0.0f;
for (int i = 0; i < numVertices - 1; ++i)
area += point[i].x * point[i+1].y - point[i+1].x * point[i].y;
area += point[numVertices-1].x * point[0].y - point[0].x * point[numVertices-1].y;
area = abs(area) / 2.0f;
Of course vertices must be ordered according to their natural following in the polygon..
There's a summation formula for that.
You might want to be more precise, possibly even providing a graphical example.
For instance, if the points you have are merely pixels, then the number of pixels equals the area. But if the points are the corners of a polygon, then the area of the polygon isn't that easily determined. You'd use polygon triangulation, and sum the areas of the triangles obtained.
Note: If you don't know the order of the points and cannot guarantee that your polygon is convex, it is not possible to determine the ordering of the shape, since there may be more than one possible order the points which produces a polygon. If you do know that the polygon is convex, determining the ordering of the points is easy. Merely sort the points by angle from one particular point., with the first point being the one that forms a line between itself and the initial point such that all the other points are on the same side of the line. The triangles formed by this process can also be used to calculate the area.
There is support for area calculation of polygons in Boost.Geometry (which isn't yet accepted into boost and which is very confusing to use).
Otherwise you would have to determine the polygon that is defined by your points first. From the looks of it all of your points are vertices of the polygon so this is a simply a matter of ordering your point sets correctly. Another possibility is that you are looking for the convex hull of your point set (see http://en.wikipedia.org/wiki/Convex_hull_algorithms).
Without modesty, I refer you to my answer to another question Combined area of overlapping circles. Monte Carlo is robust, easy-to-parallelise and will, eventually, give you an answer to the accuracy you require.
The simplest way to do this is probably to triangulate your shape and calculate the area of the triangles. Dave Eberly has a library called (Boost license) that may help with the triangulation; there is more information here. Look for TriangulateEC, for example.