Algorithm for the Winding Number of a Closed Contour - algorithm

Let's say I have a contour shape defined by two functions x(p) and y(p), where p is the distance traveled along the perimeter of the shape, normalized between 0 and 1. For example, a unit circle about the origin would be defined as x(p) = sin(2 * pi * p) and y(p) = cos(2 * pi * p).
A simple test to determine if a point is within that circle would be to calculate the point's distance from the origin, and then detect if that distance is less than or equal to 1.
But what if my shape has multiple crossings, and is much more complicated than a circle?
There exists a point in polygon test for a discrete shape defined by a set of points. That algorithm is pretty easy to find, since it's used in a lot of places. But if I don't want to use a discrete definition of my shape, what algorithm can I use to determine the winding number, with the assumption that the shape is defined at compile time?

Generalizing the point in polygon test, you can find all solutions of y(p)=0 such that x(p)>0 and use the parity of their numbers.
In the case of the circle, cos(2πp)=0 for p=(k+1/2)π, and only one value of p in range [0,1) makes sin(2πp)>0.
So far so good if you can solve the y equation analytically. Otherwise you will need a reliable numerical solver, able to spot all roots. An alternative is to flatten the curve (draw it as a polyline, ensuring a maximum deviation tolerance), and apply the polygon algorithm.
For the sake of a second example, let us consider Pascal's limaçon with equation r = 0.5 + cos Θ, and some test point along X.
y = (0.5 + cos Θ) sin Θ = 0
for Θ=0, 2π/3, π, 4π/3. The corresponding abscissas are 1.5, 0, 0.5 and 0.
You can conclude that the interior points on the X axis are between 0.5 and 1.5 (also at 0, in a degenerate way).

If you know a point that is inside (or outside) the shape and the shape is smooth and non-intersecting, then you can connect the known point to any other point and count the number of times it crosses the boundary. An even number of times means the unknown point is similarly inside (or outside). An odd number means the opposite.
This is based on the Jordan Curve Theorem. As I recall, winding number is needed for the proof of the theorem, but the application is quite easy.

How about computing the total curvature of the closed curve (assuming it is everywhere differentiable), then dividing it by 2PI? See Wiki's Total Curvature page here.

Related

Fast algorithm to calculate 3D ray / triangle edge intersections for a large number of triangles

I have a triangle ABC in 3D space and a ray in plane of the triangle given by starting point E (always inside or on the triangle's edge) and direction vector d.
The vertices A, B and C as well as E and d are given in 3D coordinates {x,y,z}.
I am looking for an algorithm to calculate the intersection of the ray with the triangle's edge P.
I can do 3 ray / line segment intersection tests for the 3 edges of the triangle but since I have to do this for a large number of triangles I am looking for a more efficient and faster algorithm.
What is the best way to do this?
Could Barycentric Coordinates help?
Could Barycentric Coordinates help?
It may. It depends a bit on how highly optimized your non-barycentric code is, but I'd say that using barycentric coordinates it's at least easier to write code which is both maintainable and performant.
As far as I can tell, your whole setup is essentially 2d, with both the point E and the direction d contained within the plane spanned by A,B,C. So you have
E = aE*A + bE*B + cE*C with aE+bE+cE=1
d = ad*A + bd*B + cd*C with ad+bd+cd=0
Now you have two subproblems:
How to obtain the barycentric coordinates efficiently
How to find the point of intersection
Let's start with the latter. You simply add to E as many multiples of d until the c coordinate becomes zero.
P = E - (cE/cd)*d
Depending on your setup, you might also be fine using homogeneous coordinates, in which case you could write this as P = cd*E - cE*d.
How do you turn x,y,z coordinates of d and E into barycentric a,b,c? Well, that's just a system of linear equations. You could use the inverse of the matrix formed by the vectors A,B,C. Again, if you are dealing with homogeneous coordinates, you can use the adjunct instead of the inverse.
Here is the homogeneous approach spelled out:
aE = (By*Cz-Bz*Cy)*Ex + (Bz*Cx-Bx*Cz)*Ey + (Bx*Cy-By*Cx)*Ez
bE = (Cy*Az-Cz*Ay)*Ex + (Cz*Ax-Cx*Az)*Ey + (Cx*Ay-Cy*Ax)*Ez
cE = (Ay*Bz-Az*By)*Ex + (Az*Bx-Ax*Bz)*Ey + (Ax*By-Ay*Bx)*Ez
ad = (By*Cz-Bz*Cy)*dx + (Bz*Cx-Bx*Cz)*dy + (Bx*Cy-By*Cx)*dz
bd = (Cy*Az-Cz*Ay)*dx + (Cz*Ax-Cx*Az)*dy + (Cx*Ay-Cy*Ax)*dz
cd = (Ay*Bz-Az*By)*dx + (Az*Bx-Ax*Bz)*dy + (Ax*By-Ay*Bx)*dz
aP = cd*aE - cE*ad
bP = cd*bE - cE*bd
Px = aP/(aP+bP)*Ax + bP/(aP+bP)*Bx
Py = aP/(aP+bP)*Ay + bP/(aP+bP)*By
Pz = aP/(aP+bP)*Az + bP/(aP+bP)*Bz
The first three lines convert E to barycentric coordinates, the next three lines d. Then we compute the barycentric coordinates of P, and turn these back into Cartesian coordinates. In that step we also dehomogenize them, i.e. divide by the sum of the barycentric coordinates.
On the whole, there is a considerable amount of code here. You can reduce the number of operations by moving common expressions to dedicated variables, particularly if your compiler doesn't do that for you. One benefit is that you won't need any divisions except for the final dehomogenization, i.e. the division by (a+b). If you compute 1/(a+b) once, you can make do with but a single division, which is good for performance.
The real benefit of the above code however is likely that you can do many nice things with the barycentric coordinates that you couldn't easily do with other coordinate systems. For example, if you want to check whether the ray hits the line AB on the line segment or somewhere outside the triangle, just check whether aP*bP > 0.
Time complexity is O(1)
It could potentially help.
In case we are talking about 3D and all your points lie on one plane. In cartesian coordinates you need to solve three linear systems to find intersection with three lines, and then determinate whether intersections lies on edge or not.
Or you need to find barycentric coordinates of two points on line. Point A(a1,a2,a3) = E and B(b1,b2,b3) = E+d. Equation of line is
Now you still need to solve three linear systems (where one of the mu = 0 and sum of the others = 1). But it will be 2x2 systems that easer to solve. And then check signes of found roots to detrerminate whether found point lies on edge or not.
Temporarily ignore the axis for which d has the smallest component, and treat the resulting 2D problem, just as we see on your illustration.
You can precompute the equation of the line of support of the ray, in the form ax + by + c = 0 (assuming z was ignored). Plug the coordinates of the three vertices in this expression, and the signs will tell you on what side of the line the vertices are.
The two intersections with the line occur on the edges having different signs at the endpoints.
Then, to determine which is the right edge, the sign of the angle between the ray and the third egde will do (if I am right);
When you know which edge, you can compute the parameter of the parametric equation of the side, which you can deduce from the previously computed signs. For instance, along the edge AB, t = Sb / (Sb - Sa). Also compute 1 - t;
Finally, use the t value to interpolate between the endpoints, this time in 3D.
The computational cost is
evalutation of the three signs Sa, Sb, Sc, taking 6 + and 6 x;
selection of the two edge candidates, taking two or three comparisons;
selection of the single candidate, taking a 2D cross product, 3 + and 2 x and a comparison;
computation of the interpolation parameter, 2 +, 1 /;
final 3D interpolation, 3 +, 6 x.
Will be hard to do shorter.
See the paper
Fast, minimum storage ray-triangle intersection,
by Tomas Möller and Ben Trombone,
in
Journal of Graphics Tools, 2(1):21–28, 1997.
See also this page.
The authors say:
One advantage of this method is that the plane equation need not be computed on the fly nor be stored, which can amount to significant memory savings for triangle meshes. As we found our method to be comparable in speed to previous methods, we believe it is the fastest ray-triangle intersection routine for triangles that do not have precomputed plane equations.

How to efficiently sample y in intervals of Δx in an “ascending” cubic Bézier curve?

For a cubic Bézier curve defined by control points P0, P1, P2 and P3 with the formula
B(t)=(1−t)^3*P0 + 3(1−t)^2t*P1 + 3(1−t)t^2*P2 + t^3*P3
we can get a point corresponding to any t ∈ [0,1]. However, from what I've gathered, algebraically solving for either one of the coordinates becomes very tedious and costly, at least for a general solution.
Now, suppose we have a two-dimensional curve B(t)=(x,y) with the specific constraint that dx/dt > 0 for all 0 ≤ t ≤ 1, i.e. the curve can progress to the positive x direction, but never "straight up/down" or "backwards", is there an efficient algorithm (/algebraic manipulation trick) to sort of "sample" the y of the curve with respect to a constant interval Δx that can leverage this property?
I'm going to answer what I think you're asking, rather than what you're actually asking, so if this doesn't cover it (and even if it does) you will want to update your post to clarify what you really mean.
Now, suppose we have a two-dimensional curve B(t)=(x,y) with the specific constraint that dx/dt > 0 for all 0 ≤ t ≤ 1, i.e. the curve can progress to the positive x direction, but never "straight up/down" or "backwards", is there an efficient algorithm (/algebraic manipulation trick) to sort of "sample" the y of the curve with respect to a constant interval Δx that can leverage this property?
Bezier curves are affine transform invariant, so any curve that does fit this definition can be rotated to no longer fit that definition. Let's assume you are referring to some canonical form, where you preprocess the curve by applying a rotation/translate to it such that the first point is at (0,0), and the last point is some coordinate (>0,R) (that is, x coordinate greater than 0, and y coordinate "any real number").
Given that, your constraints mean that the first control point (which determines the tangent at the curve at t=0) must lie strictly to the right of (0,0). The y coordinate is irrelevant (it just needs to be a real number), and the x coordinate can be any real number greater than 0 (even something as close to zero as IEEE floating point numbers allow).
Conversely, the end coordinate needs to be similarly approached, so for any end coordinate (ex,ey), the associated control point (which determines the curve tangent at t=1) needs to lie strictly to the left of (ex,ey); that is, the y coordinate can be anything, and the x coordinate must be to less than ex, but again it can be as close as possible without being ex.
Done, we now have a curve that fits your needs, which leaves the sampling at fixed x interval: you have three options.
The mathematically true way to do this is to reparameterise your curve such that y becomes and expression of x and that is ludicrously hard.
You know the tangent at each point, and Cubic Bezier curves that conform to your needs do not oscillat, so you can compute a guess for "the next x" and then use the Newtonian approach to find the true next x value you need. Or,
solve this the programming way: you're going to be drawing this curve anyway, so during the draw routine, build the LUT for the curve points that need to be drawn to the screen: you now have a list of x values with associated y values and you just need to do a simple lookup.
Obviously, unless you need absolute scientific precision, option 3 is going to be by far the best choice.

Parabola fitting with two given points and a cost function

Suppose that there is a parabola Y = aX^2 + bX + c, and it might be rotated as follow:
X = x.sin(phi) + y.cos(phi)
Y = x.cos(phi) - y.sin(phi)
phi = rotation angle
We wish to fit it on a border (e.g. inner border of an eyelid, figure below). The problem is that how we can change the parabola in each iteration such that it minimizes a cost function. We know that the parabola can be in different rotation and its origin may vary in the search region. Note that the there are two given points which the fitted parabola should passes through them (e.g. the white squares in fig below). So, In each iteration we can compute a, b and c by the two given points and the origin point (three equations and three variables).
The question is how we can reach the goal in minimum iteration (not to test all the possibilities, i.e. all angles and all positions in the search region).
Any idea will be appreciated.
#woodchips: I think this is a programming problem, and he asked a solution for the implementation.I definitely disagree with you.
A possible solution would be to first search along the vertical line which is orthogonal to the line between the two given points. And also you can vary the angle in this interval. As the nature of your problem (the border of eyelid), you can limit the angle variation between -pi/4 and pi/4. After you find the minimum cost for a position in this vertical line, you can search along the horizontal line and do similar tasks.
Why not use regression to fit a parabola to several points in the target shape? Then you could use which ever algorithm you wanted to get an approximate solution. Newton's method converges pretty fast. The optimization here is on the coefficients in the approximate parabolas.

finding saddle points in 3d heightmap

Given a 3d heightmap (from a laser scanner), how do I find the saddle points?
I.e. given something like this:
I am looking for all points where the curvature is positive in one direction and negative in the other.
(These directions should not need to be aligned with the X and Y axis.
I know how to check whether the curvature in X direction has the opposite sign as the curvature in Y direction, but that does not cover all cases. To make matters worse, the resolution in X is different from the resolution in Y)
Ideally I am looking for an algorithm that can tolerate some amount of noise and only mark "significant" saddle points.
I've been exploring a similar problem for a computational topology class and have had some success with the method outlined below.
First you will need a comparison function that will evaluate the height at two input points and will return < or > (not equal) for any input. One way to do this is that if the points are equal height you use some position-based or random index to find the greater point. You can think of this as adding an infinitesimal perturbation to the height.
Now, for each point, you will compare the height at all the surrounding neighbors (there will be 8 neighbors on a 2D rectangular grid). The lower link for a point will be the set of all neighbors for which the height is less than the point.
If all the neighboring values are in the lower link, you are at a local maximum. If none of the points are in the lower link you are at a local minimum. Otherwise, if the lower link is a single connected set, you are at a regular point on a slope. But if the lower link is two unconnected sets, you are at a saddle.
In 2D you can construct a list of the 8 neighboring point in cyclic order around the point you are checking. You assign a value of +/-1 for each neighbor depending on your comparison function. You can then step through that list (remember to compare the two end points) and count how many times the sign changes to determine the number of connected components in the lower link.
Determining which saddles are "important" is a more difficult analysis. You may wish to look at this: http://www.cs.jhu.edu/~misha/ReadingSeminar/Papers/Gyulassy08.pdf for some guidance.
-Michael
(From a guess at the maths rather than practical experience)
Fit a quadratic to the surface in a small patch around each candidate point, e.g. with least squares. How big the patch is is one way of controlling noise, and you might gain by weighting points depending on their distance from the candidate point. In matrix notation, you can represent the quadratic as x'Ax + b'x + c, where A is symmetric.
The quadratic will have zero gradient at x = (A^-1)b/2. If this not within the patch, discard it.
If A has both +ve and -ve eigenvalues you have a saddle point at x. Since A is only 2x2 and so has at most two eigenvalues, you can ignore the case when it as a zero eigenvalue and so you couldn't invert it at the previous stage.

Envelope Algorithm Optimization -- Best Place to Put a Circle

I have to solve the following problem in an optimal way.
Input data is:
N points in a plane given as a (x, y) pair of integer coordinates
M points in the same plane given as a (x, y) pair of integer coordinates representing the center of a circle. All this circles have (0, 0) on their edge.
I need to find a way of isolating a number of circles that have the property than for any "good" circle no point from the first N points lays in the chosen circle or at the edge of the chosen circle.
The number of points and circles is in the order of 100,000. The obvious solution of checking every circle with every point has the complexity O(N * M) and with 100,000 circles and 100,000 points it takes about 15 seconds on a Core 2 Duo with 64 bit SSE3 single precision code. The reference implementation I compete against takes only about 0.1 seconds with the same data. I know the reference implementation is O(Nlog N + Mlog M).
I have thought of optimizing my algorithm in the following way. Make 2 copies of the point data and sort the copies in respect to x coordinate, respectively the y coordinate. Then use only points that lay in the square defined by [(xc - r, yc - r); (xc + r, yc + r)], where (xc, yc) is the center of the "current" circle, with radius r. I can find points in that interval using binary search because now I work with sorted data. The complexity of this approach should be O(Nlog N + Mlog^2 N), and indeed it is faster but still significantly slower than the reference.
I know more or less how the reference implementation works, but there are some steps that I don't understand. I will try to explain what I know so far:
The radius of a circle with coordinates (Xc, Yc) is:
Rc = sqrt(Xc * Xc + Yc * Yc) (1)
That's because (0, 0) is on the edge of a circle.
For a point P(x, y) to be outside of a circle, the following inegality must be true:
sqrt((Xc - x)^2 + (Yc - y)^2) > Rc (2)
Now if we substitute Rc from (1) into (2), then square the inegality after we make some simple calculations we get:
Yc < 1/2y * (x^2 + y^2) - Xc * x/y (3.1) for y > 0
Yc > 1/2y * (x^2 + y^2) - Xc * x/y (3.2) for y < 0
(3.1) and (3.2) must be true for a given circle C(Xc, Yc) for any (x, y) chosen from the input data.
For simplicity, let's make a few notations:
A(x, y) = 1/2y * (x^2 + y^2) (4.1)
B(x, y) = -x/y (4.2)
E(Xc) = 1/2y * (x^2 + y^2) - Xc * x/y = A(x, y) + Xc * B(x, y) (4.3)
We can see that for a given circle C(Xc, Yc), we can write (3) as:
Yc < MIN(E(Xc)) (5.1) for all points with y > 0
Yc > MAX(E(Xc)) (5.2) for all points with y < 0
We can see that E(Xc) is a linear function in respect to Xc with 2 paramaters -- A(x, y) and B(x, y). That means that basically E(Xc) represents in the Euclidean space a family of lines with 2 parameters.
Now here comes the part I don't understand. They say that because of the property stated in the above paragraph we can calculate MIN() and MAX() in O(1) amortized time instead of O(N) time using an Envelope algorithm. I don't know how the Envelope algorithm might work.
Any hints on how to implement the Envelope algorithm?
Thanks in advance!
Edit:
The question is not about what an envelope in the mathematical sense is -- I already know that. The question is how to determine the envelope in better time then O(n), apparently it could be done in amortized O(1).
I have the family of functions I need to calculate the envelope, and I have an array of all posible parameters. How do I solve the maximization problem in an optimal way?
Thanks again!
Here is the Wikipedia entry on envelopes. Here is a tutorial about the envelope theorem in optimization.
I don't have the mathematical background, but I would approach this problem in three steps:
Throw away most points in N. This is the tricky part. Every pair of points "shadows" an area "behind" it when seen from the origin. This area is delimited by two beams starting from the points outward, pointing to the origin, and a circle intersection between the points. The calculation of this might be much simpler in polar coordinates. Start off with a random pair, then look at one new point at a time: if it is shadowed, throw it away; if not, find out if it shadows any point already in your set, then rebuild the enveloping set of curves. The tests for rebuilding the enveloping curve part should take almost constant time because the shadow set is unlikely to grow beyond a certain small number. The worst case for this seems to be O(NlogN). I cannot imagine any solution can be better than O(N) because you have to look at each point in any case.
Throw away most points in M. This is rather easy: if the point from M is farther from the origin than half the distance to the farthest point from the enveloping set, then it can be thrown out. This takes O(M)
Filter the remaining points in M through the actual check. It depends on the distribution of N and M how long this takes, but I think it is almost O(1) if both numbers are big and the distributions similar.
Overall, it seems to be possible in O(N log(N) + M). No guarantees, though ;)
Construct an R-Tree of all the points in the first set.
For each point in the second set, compute the bounding box of its circle and look up all the points in the R-Tree that fall inside that bounding box (O(n log n) with respect to number of points returned).
Check the distance between each returned point and the point currently under consideration; discard any that lie within the bounding box but outside the circle.
I think you can do it with Voronoi diagram:
Make a Voronoi Diagram of the {N points} union {[0,0]}
The centres of circles not touching the N points are exactly these lying inside the Voronoi cell of the point [0,0], which is a convex polygon
Filter the M points, one test should take O(log C)=O(log N) [where C is the number of vertices in the cell [0,0]
Overall complexity should be O(N log N+M log N)
Consider some other aspects of your computations.
For instance, you apparently compare a lot of distances. Each takes a call to SQRT. Why not compare the "squares of the distances" instead. SQRT is a costly computation.
Never take sqrt. Leave all distances as their squares. Doing so, you can compare them as well, but the time is 2-3-fold less.

Resources