I'm writing a drawing program. I'm trying to take an ordered list mouse positions, and approximate a smooth Quadratic BSpline Curve. Does anyone know how to accomplish this?
Thanks!
"B-spline curve fitting based on adaptive curve refinement using dominant points" by Park & Lee and "Fair interpolation and approximation of B-splines by energy minimization and points insertion" by Vassilev seem to be solving this problem. Also there look like a few references on the first link that should help you.
Converting data points to control points in areas of high curvature and removing data points in areas of little curvature is a general approach.
Related
Let's define a curve as set of 2D points which can be computed to arbitrary precision. For instance, this is a curve:
A set of N intersecting curves is given (N can be arbitrarily large), like in the following image:
How to find the perimeter of the connected area (a bounding box is given if necessary) which is delimited by the set of curves; or, given the example above, the red curve? Note that the perimeter can be concave and it has no obvious parametrization.
A starting point of the red curve can be given
I am interested in efficient ideas to build up a generic algorithm however...
I am coding in C++ and I can use any opensource library to help with this
I do not know if this problem has a name or if there is a ready-made solution, in case please let me know and I will edit the title and the tags.
Additional notes:
The solution is unique as in the region of interest there is only a single connected area which is free from any curve, but of course I can only compute a finite number of curves.
The curves are originally parametrized (and then affine transformations are applied), so I can add as many point as I want. I can compute distances, lengths and go along with them. Intersections are also feasible. Basically any geometric operation that can be built up from point coordinates is acceptable.
I have found that a similar problem is encountered when "cutting" gears eg. https://scialert.net/fulltext/?doi=jas.2014.362.367, but still I do not see how to solve it in a decently efficient way.
If the curves are given in order, you can find the pairwise intersections between successive curves. Depending on their nature, an analytical or numerical solution will do.
Then a first approximation of the envelope is the polyline through these points.
Another approximation can be obtained by drawing the common tangent to successive curves, and by intersecting those tangents pairwise. The common tangent problem is more difficult, anyway.
If the equations of the curves are known in terms of a single parameter, you can find the envelope curve by solving a differential equation, obtained by eliminating the parameter between the implicit equation of the curve and this equation differentiated wrt the parameter. You can integrate this equation numerically.
When I have got such problems (maths are not enough or are terribly tricky) I decompose each curve into segments.
Then, I search segment-segment intersections. For example, a segment in curve Ci with all of segments in curve Cj. Even you can replace a segment with its bounding box and do box-box intersection for quick discard, focusing in those boxes that have intersection.
This gives a rough aproximation of curve-curve intersections.
Apart from intersections you can search for max/min coordinates, aproximated also with segments or boxes.
Once you get a decent aproximation, you can refine it by reducing the length/size of segments and boxes and repeating the intersection (or max/min) checks.
You can have an approximate solution using the grids. First, find a bounding box for the curves. And then griding inside the bounding box. and then search over the cells to find the specified area. And finally using the number of cells over the perimeter approximate the value of the perimeter (as the size of the cells is known).
I am currently working on a soft body system using numeric spring physics and I have finally got that working. My issue is that everything is currently in straight lines.
I am aiming to replicate something similar to the game "The floor is Jelly" and everything work except the smooth corners and deformation which currently are straight and angular.
I have tried using Cubic Bezier equations but that just means every 3 nodes I have a new curve. Is there an equation for Bezier splines that take in n number of control points that will work with loop of vec2's (so node[0] is the first and last control point).
Sorry I don't any code to show for this but i'm completely stumped and googling is bringing up nothing.
Simply google "B-spline library" will give you many references. Having said this, B-spline is not your only choice. You can use cubic Hermite spline (which is defined by a series of points and derivatives) (see link for details) as well.
On the other hand, you can also continue using straight lines in your system and create a curve interpolating the straight line vertices just for display purpose. To create an interpolating curve thru a series of data points, Catmull-Rom spline is a good choice for easy implementation. This approach is likely to have a better performance than really using a B-spline curve in your system.
I would use B-splines for this problem since they can represent smooth curves with minimal number of control points. In addition finding the approximate smooth surface for a given data set is a simple linear algebra problem.
I have written a simple B-spline C++ library (includes Bezier curves as well) that I am using for scientific computations, here:
https://github.com/feevos/bsplines
it can accept arbitrary number of control points / multiplicities and give you back a basis. However, creating the B-spline curve that fits your data is something you have to do.
A great implementation of B-splines (but no Bezier curves) exists also in GNU GSL (
https://www.gnu.org/software/gsl/manual/html_node/Basis-Splines.html). Again here you have to implement the control points to be 2/3D for the given basis, and fix the boundary conditions to fit your data.
More information on open/closed curves and B-splines here:
https://www.cs.mtu.edu/~shene/COURSES/cs3621/NOTES/index.html
I am trying to extract the curvature of a pulse along its profile (see the picture below). The pulse is calculated on a grid of length and height: 150 x 100 cells by using Finite Differences, implemented in C++.
I extracted all the points with the same value (contour/ level set) and marked them as the red continuous line in the picture below. The other colors are negligible.
Then I tried to find the curvature from this already noisy (due to grid discretization) contour line by the following means:
(moving average already applied)
1) Curvature via Tangents
The curvature of the line at point P is defined by:
So the curvature is the limes of angle delta over the arclength between P and N. Since my points have a certain distance between them, I could not approximate the limes enough, so that the curvature was not calculated correctly. I tested it with a circle, which naturally has a constant curvature. But I could not reproduce this (only 1 significant digit was correct).
2) Second derivative of the line parametrized by arclength
I calculated the first derivative of the line with respect to arclength, smoothed with a moving average and then took the derivative again (2nd derivative). But here I also got only 1 significant digit correct.
Unfortunately taking a derivative multiplies the already inherent noise to larger levels.
3) Approximating the line locally with a circle
Since the reciprocal of the circle radius is the curvature I used the following approach:
This worked best so far (2 correct significant digits), but I need to refine even further. So my new idea is the following:
Instead of using the values at the discrete points to determine the curvature, I want to approximate the pulse profile with a 3 dimensional spline surface. Then I extract the level set of a certain value from it to gain a smooth line of points, which I can find a nice curvature from.
So far I could not find a C++ library which can generate such a Bezier spline surface. Could you maybe point me to any?
Also do you think this approach is worth giving a shot, or will I lose too much accuracy in my curvature?
Do you know of any other approach?
With very kind regards,
Jan
edit: It seems I can not post pictures as a new user, so I removed all of them from my question, even though I find them important to explain my issue. Is there any way I can still show them?
edit2: ok, done :)
There is ALGLIB that supports various flavours of interpolation:
Polynomial interpolation
Rational interpolation
Spline interpolation
Least squares fitting (linear/nonlinear)
Bilinear and bicubic spline interpolation
Fast RBF interpolation/fitting
I don't know whether it meets all of your requirements. I personally have not worked with this library yet, but I believe cubic spline interpolation could be what you are looking for (two times differentiable).
In order to prevent an overfitting to your noisy input points you should apply some sort of smoothing mechanism, e.g. you could try if things like Moving Window Average/Gaussian/FIR filters are applicable. Also have a look at (Cubic) Smoothing Splines.
I have some 3D Points that roughly, but clearly form a segment of a circle. I now have to determine the circle that fits best all the points. I think there has to be some sort of least squares best fit but I cant figure out how to start.
The points are sorted the way they would be situated on the circle. I also have an estimated curvature at each point.
I need the radius and the plane of the circle.
I have to work in c/c++ or use an extern script.
You could use a Principal Component Analysis (PCA) to map your coordinates from three dimensions down to two dimensions.
Compute the PCA and project your data onto the first to principal components. You can then use any 2D algorithm to find the centre of the circle and its radius. Once these have been found/fitted, you can project the centre back into 3D coordinates.
Since your data is noisy, there will still be some data in the third dimension you squeezed out, but bear in mind that the PCA chooses this dimension such as to minimize the amount of data lost, i.e. by maximizing the amount of data that is represented in the first two components, so you should be safe.
A good algorithm for such data fitting is RANSAC (Random sample consensus). You can find a good description in the link so this is just a short outline of the important parts:
In your special case the model would be the 3D circle. To build this up pick three random non-colinear points from your set, compute the hyperplane they are embedded in (cross product), project the random points to the plane and then apply the usual 2D circle fitting. With this you get the circle center, radius and the hyperplane equation. Now it's easy to check the support by each of the remaining points. The support may be expressed as the distance from the circle that consists of two parts: The orthogonal distance from the plane and the distance from the circle boundary inside the plane.
Edit:
The reason because i would prefer RANSAC over ordinary Least-Squares(LS) is its superior stability in the case of heavy outliers. The following image is showing an example comparision of LS vs. RANSAC. While the ideal model line is created by RANSAC the dashed line is created by LS.
The arguably easiest algorithm is called Least-Square Curve Fitting.
You may want to check the math,
or look at similar questions, such as polynomial least squares for image curve fitting
However I'd rather use a library for doing it.
I have tiles that are in random spots, and they wind up at x',y' (to make a nice 2d array) by doing :
Xt = (((X′-X)/T)*t)+X ,
Yt = (((Y′-Y)/T)*t)+Y
This works well, but it is linear. I'm looking for something curvier. A little bit like a parabola works. Basically instead of getting to X' in a straight line, I'm looking for an algorithm that will curve out and end up at X' and the amount of curvature is base on a variable.
Thanks
*EDIT
I think Bezier curve look to be what I want, but I'm not sure how to implement it. Could someone please explain the quadratic bezier formula. I'm also unsure what the 'E' - like symbol does. I think it relates to a range but I'm not sure, Thanks
You're looking for Bezier Curves, or some other similar parametric curve. These are programatically quite easy to code and have the advantage of being intuitively straightforward to manipulate. The best treatise I know of is in the classic book Mathematical Elements of Computer Graphics, but any textbook on computer graphics will probably include a basic introduction.
What you're looking for is a Catmul-Rom spline, it's a type of Hermite spline that passes though the control points. Bezier curves are not the way to go, they are difficult to control in this situation.
Have a look at this page about Perlin Noise, in particular the "Interpolation" section. The general idea is that instead of a linear transfer function over t in [0, 1], you can apply something to result in smoother curves. The "smoothest" noise is a cos(t) function, but cubic or quintic polynomials can be used to approximate a cosine.