Reputation: 155
I'm writing a G-Code interpreter and am having difficulties determining the center of a circle when given (X, Y) for two Points on the circle and the radius. I can plot a circle from 2 Points when given the center coint, but if a radius value is given instead, I can't use that to the a center point.
I've looked up multiple examples that are written in different forms of math (calculus, geometry, trig, etc.) but can't translate any of them to code. My understanding is that the values given generate two different center/intersecting points. Those are what I need to figure out.
The interpreter is running on an Arduino and written in C. If someone could just walk me through it in pseudo code even, I would be very grateful.
Thanks!
Upvotes: 13
Views: 18349
Reputation: 14086
You can't necessarily always find a unique center point give two points and a radius. In fact there are three distinct cases:
happens when the given diameter is smaller than the distance between the given points. In this case there are no solutions.
happens when the given diameter is exactly equal ot the distance between two points. In this case there is a trivial solution of
happens when the given diameter is more than the distance between the two points. In this case there are two solutions from the equations:
which you can find solutions for example from this page:
where q
is the distance between the two points and [x3, y3]
is the middle point.
Here in this Gist I'm trying to implement these in C, however not finished yet. feel free to continue from where I have left.
Upvotes: 5
Reputation: 352
Given the equation of a circle and the equations of the midpoints:
q = sqrt((x2-x1)^2 + (y2-y1)^2)
y3 = (y1+y2)/2
x3 = (x1+x2)/2
One answer will be:
x = x3 + sqrt(r^2-(q/2)^2)*(y1-y2)/q
y = y3 + sqrt(r^2-(q/2)^2)*(x2-x1)/q
The other will be:
x = x3 - sqrt(r^2-(q/2)^2)*(y1-y2)/q
y = y3 - sqrt(r^2-(q/2)^2)*(x2-x1)/q
Assuming the variables for the points have been declared already, your code should look like this:
double q = Math.Sqrt(Math.Pow((x2-x1),2) + Math.Pow((y2-y1),2));
double y3 = (y1+y2)/2;
double x3 = (x1+x2)/2;
double basex = Math.Sqrt(Math.Pow(r,2)-Math.Pow((q/2),2))*(y1-y2)/q; //calculate once
double basey = Math.Sqrt(Math.Pow(r,2)-Math.Pow((q/2),2))*(x2-x1)/q; //calculate once
double centerx1 = x3 + basex; //center x of circle 1
double centery1 = y3 + basey; //center y of circle 1
double centerx2 = x3 - basex; //center x of circle 2
double centery2 = y3 - basey; //center y of circle 2
source: Link
Upvotes: 14
Reputation: 1002
This will return one center point. You will need to alter it for the other.
In c#:
private double CenterX(double x1,double y1, double x2, double y2,double radius)
{
double radsq = radius * radius;
double q = Math.Sqrt(((x2 - x1) * (x2 - x1)) + ((y2 - y1) * (y2 - y1)));
double x3 = (x1 + x2) / 2;
return x3 + Math.Sqrt(radsq - ((q / 2) * (q / 2))) * ((y1 - y2) / q);
}
private double CenterY(double x1, double y1, double x2, double y2, double radius)
{
double radsq = radius * radius;
double q = Math.Sqrt(((x2 - x1) * (x2 - x1)) + ((y2 - y1) * (y2 - y1)));
double y3 = (y1 + y2) / 2;
return y3 + Math.Sqrt(radsq - ((q / 2) * (q / 2))) * ((x2-x1) / q);
}
Upvotes: 6
Reputation: 427
This the ruby version of the same code, should someone need it, (thanks to C# code by rookie1024)
def chord
@chord ||= begin
a = (point_1.x.to_f - point_2.x.to_f).abs ** 2
b = (point_1.y.to_f - point_2.y.to_f).abs ** 2
Math.sqrt(a + b)
end
end
def radius
@radius ||= begin
s = (chord / 2) * bulge
((chord/2) ** 2 + (s ** 2))/(2*s)
end.to_f
end
def center
x1 = point_1.x
y1 = point_1.y
x2 = point_2.x
y2 = point_2.y
x3 = (x1+x2)/2
y3 = (y1+y2)/2
basex = Math.sqrt((radius ** 2) - ((chord/2) ** 2)) * (y1-y2)/chord
basey = Math.sqrt((radius ** 2) - ((chord/2) ** 2)) * (x2-x1)/chord
centerx1 = x3 + basex
centery1 = y3 + basey
centerx2 = x3 - basex
centery2 = y3 - basey
bulge > 0 ? [centerx1, centery1] : [centerx2, centery2]
end
Upvotes: 0