Implement closed B-Spline interpolation of datapoints - computational-geometry

I have a set of 3D points which I am trying to interpolate using a pth-degree B-Spline. I have implemented the algorithm described here https://pages.mtu.edu/~shene/COURSES/cs3621/NOTES/INT-APP/CURVE-INT-global.html so that the curve passes through the datapoints. Also, the curve I have has the 1st point equal to the last points, since it is a closed curve.
Now, I have implemented the interpolation algorithm for the clamped case, where the 1st p and last p knots are 0 and 1, respectively, and have p+1 multiplicity. However, I am struggling to do the same for the closed case, where I want the curve to be periodic.
I have successfully transformed the clamped (or open) curve representation I obtained into a closed representation by modifying the knots, according to the Control Point Wrapping algorithm described here: https://pages.mtu.edu/~shene/COURSES/cs3621/NOTES/spline/B-spline/bspline-curve-closed.html
However, I have tried to do the same with the Knot Wrapping algorithm, but with no success. They say to wrap the last knots with the first ones, but the knot vector is supposed to be a sequence of nondecreasing real numbers, so that can't be. I have also tried to do the wrapping by extending the knot vector past 1 for the knots corresponding to the wrapped control points, while keeping the knot deltas in the beginning of the knot vector, but that didn't work either.
Now I am wondering if I should solve the system of equations already knowing the final curve has to be closed, instead of trying to transform the clamped curve into a closed one. Would anyone know how to correctly implement this, or know where to point me in the right direction?
Any help would be appreciated.

In my opinion, it adds a new b-spline, instead of moving one part of the old to make it closed.

Related

deCasteljau algorithm on bezier surfaces

Hi people i have 2 question related to Decasteljau algorithm,they are more of a general questions,but if im right it could help solving many problems.Here it is:
We have some sufrace: Ʃ(i=0,n) Ʃ(j=o,m) Bi,n(U),Bi,m(v) Pi,j analysis that i have found says that first we take some value for one parameter u=uo,then we itterate other parametar v -> 1 get a set of points,then increment u by one etc....for loop inside for loop in code language.My question is can we fix one parameter U=Uo for what ever value,and then just compute points on for parameter v?Because all points that are on one curve are also on the surface,and if distance between curves approaches to zero (which itteration really is) we can apply DeCasteljau algorithm only to one set of curves itterating only one parameter.Or i got something wrong?:)
Second question is i havent really figured out what do we really need DeCasteljau algorithm for,unless we are drawing curves by hand?If we know order of the curve we can easily form Bernstain polynoms for that curve order and compute point for given value of parametar.Because when you unwrap Decasteljau what you get is Bernstain polynom?
So like i said,please help have i got i wrong?
Yes you can fix one parameter (say U) and change the other (V) to generate an iso-U curve.
You can see the things as if you had an NxM array of control points. If you perform a first interpolation on U (actually M interpolations involving N control points), you get M new control points that define a Bezier curve. and by varying U, the curve moves in space.
The De Casteljau's algorithm is used for convenience: it computes the interpolant by using a cascade of linear interpolations between the control points. Direct evaluation of the Bernstein polynomials would require the precomputation of the coefficients, and would not be faster, even when implemented by Horner's scheme, and can be numerically less stable.
The De Casteljau's algorithm is also appreciated for its geometrical interpretation, and for its connection with the subdivision process: if you want to build the control points for just a part of a Bezier curve, De Calsteljau's provides them.

Checking convexity from outside [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
Is there any method or algorithm to determine convex (or non-convexity) property of a region from outside (perimeter) ?
One way is plotting tangent line in each point of perimeter and discuss how many times this line intersect the perimeter points. If no intersect shown (for all points of perimeter ) we can conclude region is convex. In otherwise region is non-convex.
Second way is determine interior angel of each point of perimeter and discuss if it's bigger than 180 or not. The region is non-convex if at least one point in perimeter exist it's interior angel bigger than 180.
Are there another simpler ways?
Any ideas or solution would be appreciated, thanks.
One thing to observe when doing this is that as you traverse the sides of a convex polygon, all the turns will be to the same side. That is, if you are traversing around the vertices in a counter-clockwise direction, all of the turns will be to the left; if you are traversing around the vertices in a clockwise direction, all of the turns will be to the right. If you ever observe a turn to the opposite side of any others observed, then you know you're dealing with a non-convex polygon. If all of the turns are to one side, then it is a convex polygon.
So, all you need to do is take look three vertices at a time, call them vn, vn+1 and vn+2. You can then determine which side of the line segment connecting vn and vn+2 the vertex vn+1 sits on. For CCW, vn+1 should be on the right of the line segment, and for CW it should be on the left. There is an answer to another question which provides a method for determining this.
There are additional implementation details you should work out (like how to deal with n=N, the number of points in your polygon, but this should provide you with a place to start.
An implementation based on this approach will run in O(N) time and space.
UPDATE: In response to the question below, "how about non-polygonal regions"? In general this is much harder. Mathematically, a region can be shown to be non-convex by finding a line segment with endpoints in the interior of the region but which has some portion of the line segment exterior to the region. I suspect you're looking for a way of implementing this using a digital computer, and so the pure mathematical approach is not practical.
So, you're going to have to offer some sort of constraints as to the types regions before the problem becomes intractable. That is, you have to constrain your problem space so that things like Nyquist sampling of the perimeter of the boundary do not incorrectly identify a non-convex region as being convex.
Assuming you can properly constrain the problem, any solution you can come up with, which can be implemented on a digital computer will have to approximate the region. You can either generate a piece-wise linear approximation of the region in question and run the algorithm above, or pick the proper set of points along the boundary of the region and calculate their derivative. Each successive sample should rotate the angle of the tangent line by some increment in the same direction. But again, it gets downs to sampling.
If you have other information about the nature of any nonlinearities which comprise the boundary of your region, you may be able to symbolically demonstrate whether a segment of the boundary is convex. The problem then reduces to showing that it remains convex when joined to the adjacent sections, which again is going to be problem specific.
So, my suggestion is, for digital computer implementation, approximate as needed the boundary of the region by a polygon and run the method defined above on that approximation.
An algorithm I've used (in pseudo code):
function isConvex(vertices[Count] V):
convex = true
if Count <= 3 return convex
for N = 0 to Count while convex:
// line segment between previous and subsequent vertices
LineSegment segment1 = new LineSegment(
V[(N + Count - 1) % Count], V[(N + 1) % Count]);
// line segment between the point and any other point
LineSegment segment2 = new LineSegment((V[N], V[N+2 % Count]);
if not segment1.intersects(segment2) then convex = false;
return convex
I don't know if this is optimal or simpler than the algorithms you've already tried.
The LineSegment.intersects() method already existed making this really easy to write.
The actual code used segment2 from the previous iteration as segment 1 of the current iteration making it faster but more complex to write even in pseudo code.
And also, for what it's worth, the original of this algorithm was written in assembly language on a processor that no longer exists, so I won't be providing actual code ;-).

Catmull-Rom interpolation in Ruby

I have a list of points that I want to draw a smooth line between. I am using the RVG library for drawing so if i could get a SVG string from my points I would be happy. Searched around and found that Catmull-Rom probably is the algorithm to use.
Found some implementations in the Kamelopard and Rubyvis libraries, but couldn't understand how to use them from my list of points.
So, the question is, how can I take my array of (x,y) points and get a Catmull-Rom interpolated SVG curve from them?
Catmull-Rom is probably a good place to start. I recently re-implemented the Kamelopard version, and found this helpful: http://www.cs.cmu.edu/~462/projects/assn2/assn2/catmullRom.pdf
It's fairly straightforward, provided you understand the matrix multiplication. You'll end up with a matrix equation you'll need to evaluate a bunch of times, once per point on the path you're drawing. If you have control points A, B, C, and D, and you want to draw the curve between B and C, make a matrix where A, B, C, and D are the rows, and plug it into the equation at the top of the paper I linked to. It will be the last matrix in the list. The other values you'll need to know are "u", which ranges from 0 to 1, and "T", the "tension" of the spline. You'll evaluate the equation multiple times, incrementing u across its domain each time. You can set the tension to whatever you want, between 0 and 1, and it will affect how sharply the spline curves. 0.5 is a common value.
If you're trying to evaluate the curve between, for instance, the first two control points on your list, or the last two, you'll find you have problems making your matrix, because you need the two control points on either side of the point you're evaluating. In these cases, just duplicate the first or last control point, as necessary.

Generating random tunnels

What methods could we use to generate a random tunnel, similar to the one in this classic helicopter game? Other than that it should be smooth and allow you to navigate through it, while looking as natural as possible (not too symmetric but not overly distorted either), it should also:
Most importantly - be infinite and allow me to control its thickness in time - make it narrower or wider as I see fit, when I see fit;
Ideally, it should be possible to efficiently generate it with smooth curves, not rectangles as in the above game;
I should be able to know in advance what its bounds are, so I can detect collisions and generate powerups inside the tunnel;
Any other properties that let you have more control over it or offer optimization possibilities are welcome.
Note:
I'm not asking for which is best or what that game uses, which could spark extended discussion and would be subjective, I'm just asking for some methods that others know about or have used before or even think they might work. That is all, I can take it from there.
Also asked on gamedev. I think it fits in both places, since it's as much an algorithm question as it is a gamedev question, IMO.
I think you could use Bézier curves for the tunnel walls, because they have the property that each end of the curve is tangent to the line segment between the last two control points at that end. This means it's possible to generate curves lazily, appending them as you go, without creating sharp corners. You only ever need to buffer one off-screen segment. As soon as its leftmost edge appears on-screen, create the next off-screen segment.
If you use cubic Béziers, you need 4 control points. The 1st will necessarily be the same as the last control point of the previous segment; to preserve smoothness at the junction, the 2nd will need to be somewhere on the line containing the previous segment's last 2 control points; the 4th will be where you want this curve to end; and the 3rd can probably be chosen freely. (You may want to keep it horizontally between the 1st and 4th points, to avoid the possibility of the curve "doubling back".)
Béziers have 2 other properties that will simplify your implementation:
The curve is completely contained within the convex hull defined by the control points, so it's easy to ensure there's a gap between the top and the bottom curves.
You can split a Bézier at any point to produce 2 sub-Béziers. This is handy for rasterising/linearising.
EDIT: Replaced "bounding box" with "convex hull".
Decide on the width of the tunnel (it will probably reduce with distance), and then put 2 control points at a random height, but make sure that the vertical offset from the previous pair or points is small enough for the helicopter to make a manoeuvre. Continue adding control points at equal distances:
_
_ _ _
_ _
_ _
Next you need to find intermediate points. I'd use monotone cubic interpolation, which guarantees that all intermediate points are always between the control points, never lower or higher. Here's a demo I made in JavaScript: http://explored.tk/experiments/monotone/
UPD: or you can generate one such curve, and then draw the tunnel boundaries symmetrically around it.

Looking for a "closing curves connecting with respect to points" algorithm

I am looking for an algorithm that can connect points together with a continuous curve line. Imagine drawing from point a to b to c until the last point, and when you draw from point to point, the line must be a curve and is continuous with respect to the previous point and next point, as if the given points are just samples of a closed loop. Please see figure below for illustration.
Are there such algorithm for something like this?
*The circles in the figure are my list of points.
Given that your points are ordered, spline interpolation is definitely the best way to go here. (As indicated by by bo1024's comment) I highly recommend the following notes:
http://www.cs.mtu.edu/~shene/COURSES/cs3621/NOTES/
And specifically the section here would be most relevant to getting a closed loop like you asked for:
http://www.cs.mtu.edu/~shene/COURSES/cs3621/NOTES/spline/B-spline/bspline-curve-closed.html
EDIT: If the curve has to pass through the points, then the unique degree n solution is the Lagrange interpolating polynomial. You can just make one polynomial for each component of your points vectors using the formula on the wiki page:
http://en.wikipedia.org/wiki/Lagrange_polynomial
Unfortunately Lagrange interpolation can be pretty noisy if you have too many points. As a result, I would still recommend using some fixed degree spline interpolation. Instead of B-splines, another option are Hermite polynomials:
http://en.wikipedia.org/wiki/Cubic_Hermite_spline
These will guarantee that the curve passes through the points. To get a closed curve, you need to repeat the the first d points of your curve when solving for the coefficients, where d is the degree of the Hermite spline you are using to approximate your points.
The problem is very similar to the travelling salesman problem, you may be able to extend some of the algorithms used to solve it to suit your case.
For instance, evolutionary algorithms are easy to adapt and you will find lot of references about using them to solve the TSP.

Resources