Reputation: 5040
I know how to calculate the X/Y position of a point on a circle given a radius and distance. That's not what I need to calculate.
I need to calculate the X/Y position on one circle, but based on a point and angle that is not the center of that circle.
The known values are:
What I'm doing is calculating lines on a curved scale for a meter display. The lines need to be parallel to the needle of the meter, but it's pivot point may not be the same as the radius point of the scale's arc.
It will need to be in Javascript and is used in drawing on an HTML5 canvas object.
Here's an image to help explain what I'm looking for:
(source: sloansweb.com)
Referring to the drawing, CP1 will always be within the inner radius of the circle with CP2.
EDIT: I've updated the drawing to simplify it showing just one circle around CP2. Note that the angle to the crossing point relative to CP2 is unknown. Also, the distance to the crossing point relative to CP1 is unknown.
Thanks in advance!!
Upvotes: 1
Views: 1643
Reputation: 824
Maybe it's possible in this way: if you have the radius and the center of the circle, you can write your equation for that (say Cr(x) ). Now, if you have only CP2 and A1_angle, you can write the equation of a line starting at CP2 with angular coefficient=A1_angle so you will be able to, geometrically, intercept the "Crossing Point 1 " and " Crossing Point 2 " somewhere, finding out coordinates with the line-equation or also with Cr(x).
More pratically:
1) Cr(x) := (x-CP2.x)^2+(y-CP2.y)^2=radius1^2
with x,y, variables and CP2.x, CP2.y the x-coordinate and y-coordinate of CP2.
2) Then you have to find out what is the function of the line starting at CP1 and going on with slope=A1: y=tan(A1)*x+b
, with b = CP1.y-tan(A1)*CP1.x
3) Make these two functions intercept each other in order to find how many points they have in common (no more than 2!):
{ Cr(x) AND y=tan(A1)*x+b }
. Here you have to substitute the y variable ( I think this way is more simple than substituting the x variable... you choose) and make the equation equals to 0.
((x-CP2.x)^2+(tan(A1)*x+b-CP2.y)^2 - radius1^2=0
If you have done rights, you must have at the end 2 points (because the line intercepts the circle twice), nothing more to say just to select the rights ones and do what you need.
The same happens with radius2 for the 2nd circle, just get the Cr(x) function for circle with radius2 (line remains the same!) and find out the coordinates :)
I know it's a way more mathematically, and complex maybe, than what you need for drawing a canvas, but this is what came in my mind at first.
Hope i was clear :)
EDIT:
Try this in your javascript code, hope it works correctly:
function GetPoints(Center_x, Center_y, Radius, CP1_x, CP1_y, angle){
var a=Center_x;
var b=Center_y;
var c=CP1_x;
var d=CP1_y;
var TAN=Math.tan((2*Math.PI*angle) / 360);
var res_x= [];
var res_y= [];
if(angle!=90 && angle!=180 && angle!=270 && angle!=360){
res_x[0]= ((2*TAN*TAN*c+2*b*TAN-2*d*TAN+2*a) +
Math.sqrt(
-2*c*TAN*TAN-2*b*TAN+2*d*TAN-2*a - (4*TAN*TAN + 4)*(c*c*TAN*TAN-2*c*d*TAN+2*c*b*TAN-2*d*b+d*d+b*b-Radius*Radius+a*a)
)
) / (2*TAN*TAN+2);
res_x[1]= ((2*TAN*TAN*c+2*b*TAN-2*d*TAN+2*a) -
Math.sqrt(
-2*c*TAN*TAN-2*b*TAN+2*d*TAN-2*a - 4*(TAN*TAN + 1)*(c*c*TAN*TAN-2*c*d*TAN+2*c*b*TAN-2*d*b+d*d+b*b-Radius*Radius+a*a)
)
) / (2*TAN*TAN+2);
res_y[0]= TAN*res_x[0]+d-TAN*c;
res_y[1]= TAN*res_x[1]+d-TAN*c;
}
else{
res_y[0]= b +
Math.sqrt(
-c*c+2*c*a-a*a+Radius*Radius
);
res_y[1]= b -
Math.sqrt(
-c*c+2*c*a-a*a+Radius*Radius
);
}
res_x[0]=res_x[1]=c;
console.log("x0= "+res_x[0]+ "\nx1= "+res_x[1]+"\n");
console.log("y0= "+res_y[0]+ "\ny1= "+res_y[1]+"\n");
}
Those console.logs should be useful when debugging, so I left them.
Angle is in degrees, I have implemented an implicit switch to grads, and is calculated in the default way (in respect of grads). I didn't know how much your A1
angle has to vary, so I preferred this way, but I think it's not very complicated to make this change. In res_x[] are stored the x-values of your crossing points and in res_y[] the y-values. I saw that eventually it could make some approximations caused of the maths I suppose. One more thing, the function as you can see doesn't handle exception.
2 EDIT:
I came up with a second solution. For knowing all of a triangle, we need at least 3 datas. And we have already 3 datas of our triangle ABC!
We know where are A and B, and so their distance, we know the alpha-angle, and so all the entire angle of B (90° + alpha) and we know AC. Definitely, we know 2 sides and one angle ... perhaps we don't need anything else.
From theory, we know that in a whatever triangle, one side over sin of the opposite angle is a constant with every side and every angle. In this case, we know AC ( it is the radius) and B_angle (it is 90 degrees plus your value alpha), so AC/sin(alpha+pi/2)
is equals to AB/sin(C_angle)
that is equals once more to BC/sin(A_angle)
.
Making some equation:
AC/sin(alpha+90°)=AB/sin(C_angle)
so
sin(C_angle)=AB*sin(alpha+90°)/AC
and
C_angle= arcsin ( AB*sin(alpha+90°)/AC )
Now, if we know C_angle and alpha, we can compute A_angle because sum of all 3 angles in a triangle makes 180°. So A_angle=180°-alpha-C_angle. Now we know all angles, and 2 sides. For the last one we can apply the same formula as above:
BC/sin(A_angle)=AC/sin(alpha+90°)=AB/sin(C_angle)
Choose what you prefer and retrieve BC. Now we have:
AC=radius;
AB= known with coordinates;
BC= retrieved from previous relations
B_angle= alpha + 90°
A_angle and C_angle= retrieved from previous relations as for BC.
We know everything now, in particular BC.
For retrieving coordinates of C point from knowing its distance from B, we could do a trick:
Make line(x) equation starting from B and going with slope of tan(alpha) and, knowing distance from B to C, we can retrieve X/Y coordinates of C in such a way:
C.x= BC*cos(alpha)
C.y= line(x+BC*cos(alpha))
And there you go.
I found this process much more simple than the other one I suggested you, and maybe coding it in JS could be pretty much easier.
This works until B point stands on the same axis of A. In case B point shoudl be moved around, the B_angle coudl change a lot, and instead of adding 90° you should add the angle between A and B.
Upvotes: 2