Does anyone know how to calculate the medial axis for two given curves?
Medial axis: http://en.wikipedia.org/wiki/Medial_axis
Here is the shape I need to calculate it for:
I drew in the medial axis myself, the dark black line, but I need to be able to calculate it dynamically.
Here is the applet and code of what I have done so far:
http://www.prism.gatech.edu/~jstrauss6/3451/sample/
The known variables are:
-pt A, B, C, D
-radii of red, green, and black circles
-pt Q and R (just outside the picture), the black circles.
Let C1 and C2 be centers of circles with radii r1 and r2. The medial axis (minus the two center points) of the figure made of the two circles is the set of points M satisfying
|M - C1| - r1 = |M - C2| - r2
which implies
|M - C1| - |M - C2| = r1 - r2
|M - C1|^2 + |M - C2|^2 - (r1 - r2)^2 = 2 * |M - C1||M - C2|
(|M - C1|^2 + |M - C2|^2 - (r1 - r2)^2)^2 = 4 * |M - C1|^2 |M - C2|^2 (**)
so the medial axis is a fourth degree algebraic curve.
Let us say that C1 and C2 are on the y axis, and suppose that the point (0,0) lies on the medial axis (so C1 = (0, -r1 - x) and C2 = (0, r2 + x) for some x you can compute from your data). This is something you can always transform into.
Now, you want the curve y = f(x) which parametrizes the median axis. For this, pick the x of your choice, and solve equation (**) in y with Newton's method, with initial guess y = 0. This is a polynomial you can compute exactly, as well as its derivative (in y).
The medial axis is in this case a hyberbola.
For more information see this article, particularly the following excerpt:
The center of any circles externally tangent to two given circles lies on a hyperbola, whose foci are the centers of the given circles and where the vertex distance 2a equals the difference in radii of the two circles.
So the problem reduces to drawing a hyperbola, given its foci and vertex distance.
If you embed the circles on a rectangular grid (think image), then you can use the distance transform of this image to compute your medial axis. See this link.
Several O(nlogn) algorithms exist for computing the distance map on an image grid.
Related
Given a grid inclined at an angle θ (theta) with equal sized square-shaped cells with indices 00, 01, 02, ..., 55 (where first digit being x index and second being y index, for instance 00 means a cell at the intersection of row 0 and column 0), and a point p(x,y), how can we know that in which grid cell does the point lie without checking all the cells?
For instance, in the image below point p lies in the cell with index 23.
I found one answer at Checking if a point is inside a rotated rectangle that explains how to determine if a point lies inside a rotated rectangle, but with this approach I need to check all the grid cells.
Perhaps the simplest way - rotate point by the same angle (with negative sign) and check new coordinates in axis-aligned grid
nx = x * cos(theta) - y * sin(theta)
ny = x * sin(theta) + y * cos(theta)
row = (int) (ny / cellsize)
col = (int) (nx / cellsize)
I don't know if this question makes sense, but is there a formulaic way to calculate the height of a chord from a circle's edge in one of the circles from 3 tangent circles?
I have included a diagram to provide detail. Circles C1, C2 and C3 are connected at tangents and have equal radii (in this case 1 mm, but that is only for depiction). Triangle ABC is formed by connecting the centers of these circles. Line LM meets sides AB and AC and is tangential to Circle C1. Line PQ cuts through Circle C1 and triangle ABC and is tangential to both circles C2 and C3.
Diagram for question
What is the formula for the distance (x) between lines LM and PQ?
Given that the radii are equal (say, r), the total height of these 3 circles (line RS shown in diagram, which is my objective to calculate) is 4 times the radius minus the distance (x) between lines LM and PQ. In other words,
|RS| = {(4*r) - x}
variable x needs to be converted into a formula based exclusively on radius r so as to solve this equation.
It has been a while since I revisited my high school geometry lessons, so I hope this can be solved.
Distance A-LM is equal to r (circle center - tangent)
Distance BC-PQ is equal to r
If we add these distances and subtract distance PQ-LM (x), we'll get height of equilateral triangle ABC (with edge 2*r)
r + r - x = height of ABC = 2 * r * sqrt(3)/ 2
x = r * (2 - sqrt(3))
Given the following from the image below:
The green circle has a radius equal to B
The yellow line is tangent to the green circle
The vertical purple line is parallel to the green line and perpendicular to the yellow line.
The yellow line is perpendicular to both the green line and the vertical purple line
The purple point is centered on the green circle's edge
A and B are known values
I realize several of these constraints overlap, just trying to be thorough.
Pythagorean's theorem can provide the value of C, just to illustrate what I know we can determine already.
What is the formula/equation to determine D, where D is the perpendicular distance from the tangent yellow line to the arc/circle (at the purple point)?
Update
Replacing previous attempts to illustrate solution now with one that I can now visualize as the correct representation of the answer and comments provided by John
The distance D can be found by computing the lowest intersection between the vertical ray from the right endpoint of the yellow segment and the circle.
Some notations (x axis to the right, y axis to the bottom, origin at the center of the circle):
center of the circle: P_C = (0, 0)
origin of the vertical ray: P_O = (A, B)
direction of the vertical ray: v_d = (0, -1)
Points on the ray satisfy: P = P_O + t v_d = (A, B - t)
Points on the circle satisfy: |P P_O|^2 = B^2
Expanding the first equation into the second gives: A^2 + (B - t)^2 = B^2 = A^2 + B^2 - 2 B t + t^2
Solving t^2 - 2 B t + A^2 = 0 for t yields d = B^2 - A^2 > 0, so two solutions t_1 = B - sqrt(d), t_2 = B + sqrt(d) (one near the bottom of the circle, the other near the top as expected). But t actually gives the distance along the ray (since v_d is a unit vector), so what we are looking for is the smallest solution t_1. Hence D = B - sqrt(B^2 - A^2).
The final result can also be derived and / or verified geometrically (courtesy of John, see all the corresponding comments): D = B - B' and B'^2 + A^2 = B^2 (Pythagorus on the right triangle with the center of the circle and the purple point as two of its vertices and an edge sitting on the purple line).
As you mentioned C is the easy part. However with A,B,C and the cosine theorem you can work out the angel opposite to B (b):
cos(b) = (a^2 + c^2 -b^2)/(2ac)
knowing b and that A and D have a right angel you can work out the angle between C and D (b'):
b' = 90° - b
given that D lies on the circle you know that the distance from the center to D is B so you now have a triangle with sides B,D and C where you know two of the sides and one of the angles. With the cosine law again:
B^2 = C^2 + D^2 - 2CD cos(b')
so in one more step we can find:
B^2 - C^2 = D^2 - 2CD cos(b') + (C cos(b'))^2 -(C cos(b'))^2 <=>
B^2 - C^2 + (C cos(b'))^2 = (D - C cos(b'))^2 <=>
sqrt(B^2 - C^2 + (C cos(b'))^2) + C cos(b') = D
hope I didn't put stupid mistakes in there and this helps...
I have a square, for simplicity assume bottom left corner is on origin and width of the square is 1.
A ray divides the square into two parts. I have the coordinates of intersection points. I want to obtain the area that lies right of the vector from p1 to p2:
Right now I have 16 if statements checking every combination of 2 points and calculating the area accordingly. It looks awful. Is there a more clever way of doing this?
Call the points A and B instead of p1 and p2. I'll assume x increases to the right and y increases upward, as per convention.
The point A must have a coordinate (x or y) that is 0 or 1. Rotate the square (really just the two points) to make it x=0.
The point B might be at x=-1, in which case the area is 1-(Ay+By)/2.
Or B might be at y=0, area = 1+(AyBx)/2
Or B might be at y=1, area = (Ay-1)Bx/2
This solution assumes that p1 and p2 form a right-triangle as depicted in the shaded area:
Area to the right of the vector = (w * w) - (0.5 * p1 * p2)
where w is the width of the square, and 0 <= p1 <= w, and 0 <= p2 <= w.
For example if w = 1, p1 = 0.5, and p2 = 0.75
then Area = (1 * 1) - (0.5 * 0.5 * 0.75) = 0.8125
I'm working in flex, although I reckon this is a language independent problem. I'm trying to draw a curve using 3 points, using curveTo (a quadratic bezier function, I don't believe Flex has any other, if it does, please correct me!) Points 1 and 3 are "nodes", with point 2 being a drag handle.
What I want is not for the line to curve towards point 2 but in fact pass through it. I've managed to get this working by fluking it - by doubling the (distance between the midpoint of a line between Points 1 and 3) and Point 2.
This doesn't put it on the Apex of the line though, just somewhere close to it.
Anyone any ideas?
Andrew
the quadric bezier curve is calculate using the formula
B(t) = (1-t)(1-t)*P0 + 2(1-t)t*P1 + t*t*P2
where P0,P1 and P2 are the 3 points you specify. The curve starts in P0 and ends in P2
t ranges from 0 to 1
the apex should be reached at t = 0.5
so try to insert P0, P2 and t = 0.5 into the formula set it equal to the point where
you want the apex to be and extract P1 from the formula
Us this formula: B'(t) = 3 (1 - t) 2 (P1 - P0) + 6 (1 - t) t (P2 - P1) + 3 t2 (P3 - P2)
You can use the derivative to find maximums and minimums.
A Bezier spline will not pass through its control points, but a Catmull Rom spline will.
B(t) = ((2*P1)+(-P0+P2)*t + (2*P0-5*P1+4*P2-P3)*t*t + (-P0+3*P1-3*P2+P3)*t*t*t )) / 2
Although this is a cubic rather than quadratic spline. You could try making P1=P2