note: i am not a trig expert and some of my calculations may be wrong :-) So, it would be useful if some of you trig guru's could check my solutions.
Feel free to add more challenges (with solution or open) to this page. good luck! -- Vic
1: how do i calculate the angle 'a' in a circle with radius 'r', given the arc length 'arcd'?
2: how do i calculate the angle 'a' in a circle with radius 'r', given the chord 'd'?
3: how do i calculate point p1(x1, y1), given angle 'a', center p0(x0, y0) and radius 'r'?
Point calcPoint(double a, double x0, double y0, double r) { x1 = x0 + (Math.sin(a) * r); y1 = y0 + (Math.cos(a) * r); return Point(x1, y1); }
4: how do i calculate radius r, given point p1(x1, y1) and center p0(x0, y0)?
double calcRadius(double x0, double y0, double x1, double y1) { return (Math.sqrt(Math.pow((x1 - x0), 2) + Math.pow((y1 - y0), 2))); }
5: how do i calculate angle 'a', given point p1(x1, y1) and center(x0, y0)?
double calcAbsoluteAngle(double x0, double y0, double x1, double y1) { double r = calcRadius(x0,y0,x1,y1); if(y1 < y0) { return (Math.asin ((x1 - x0) / r)); } else { return ( Math.PI - Math.asin ((x1 - x0) / r)); } }
double calcAbsoluteAngle(double x0, double y0, double x1, double y1) { return Math.atan2(x1-x0, y1-y0); }
how do i calculate the point p2 (x2,y2), given angle 'a', center(x0, y0) and point p1 (x1,y1)?
Point calcPoint(double a, double x0, double y0, double x1, double y1) { double r = calcRadius(x0,y0,x1,y1); double a1 = calcAbsoluteAngle(x0,y0,x1,y1); return calcPoint(a+a1, x0, y0, r); }
how do i calculate angle 'a', given a non rotating square B1 defined by center P1 (x1, y1) and width 'w', and center(x0,x1)?
-- FnH
A rough calculation is;
Solving exactly would require you first select which two points on the square are deciding the angle -- there are 6 possibilities. That part is easy. Then, it just becomes a law of cosines problem. Alternatively, you could calculate the angle for all 6 possible combinations and choose the largest one. -- nano
ok got it.. FnH took a shot at nano's second option so i'll take one at the first:
/////////////////////////////// // first of all, determine which two corners define the projected angle: ////////////////////////////// xmin = x1 - w/2; xmax = x1 + w/2; ymin = y1 - w/2; ymax = y1 + w/2; if(y0 >= ymin && y0 <= ymax) //if p0 in horizontal bar defined by B1 { if (x0 < xmin) //choose left or right corners" { corner_1.set(xmin, ymin); corner_2.set(xmin, ymax); } else { corner_1.set(xmax, ymin); corner_2.set(xmax, ymax); } } else if(x0 >= xmin && x0 <= xmax) //else if p0 in vertical bar defined by B1 { if (y0 < ymin) //choose top or bottom corners" { corner_1.set(xmin, ymin); corner_2.set(xmax, ymin); } else { corner_1.set(xmin, ymax); corner_2.set(xmax, ymax); } } else //or else opposing corners define the angle" { if(x0 < xmin) { furthest_x = xmax; closest_x = xmin; } else { furthest_x = xmin; closest_x = xmax; } if(y0 < ymin) { furthest_y = ymax; closest_y = ymin; } else { furthest_y = ymin; closest_y = ymax; } corner_1.set = (furthest_x, closest_y); corner_2.set = ( closest_x, furthest_y); }
/////////////////////////////// // then, using the law of cosine, calculate the angle: ////////////////////////////// La = distance(p0, corner_1); Lb = distance(p0, corner_2); Lc = distance(corner_1, corner_2); //law of cosine: Lc^2 = La^2 + Lb^2 ? 2 * La * Lb * cos(angle). //therefore: cos(angle) = (Lc^2 - (La^2 + Lb^2)) / (- 2 * La * Lb) //therefore: angle = acos ((Lc^2 - (La^2 + Lb^2)) / (- 2 * La * Lb)) a = Math.acos ((Lc * Lc - (La * La + Lb * Lb)) / (- 2 * La * Lb));
-- Vic Stewart
6. how do i calculate the maximum angle 'a' given bullet power 'Bp' and Robot velocity 'vR' (assuming instantaneous max speed and direction of the robot)
-- I don't get the same results here, Kawigi. if I do atan(8/11) I get a=36 degrees. What am I doing wrong? How do I get this 46.7 degrees result? anyone? --Vic
-- It's not the atan(8/11), because the bullet trajectory is the hypotenuse of the triangle, not the line between you and the target (because that line would miss :-p), so it's the asin(8/11). The point being that they can get that far still before the bullet has traveled long enough to hit them. -- Kawigi
-- Ok, thanx. --Vic
7. how do i calculate the point p2 defined as the intersection of circle C and Line L given radius r, center p0(x0,y0) and point p1(x1,y1)
Point calcPointFromRadius(double r, double x0, double y0, double x1, double y1) { double a = calcAbsoluteAngle(x0,y0,x1,y1); return calcPoint(a, x0, y0, r); }
Given a origin point and a bearing from the point (Robocode style - 0 up, +ve clockwise) to generate a line that extends both sides of the origin point how do you calculate the perpendicular distance from the line of any other point so that you get positive distances for points to the right of the line (facing in the direction of the bearing) and negative distances for those points on the left of the line. Thanks Paul Evans.
I'm not sure I fully understand the question. But maybe this?
relativeBearing = normalRelativeAngle(bearingFromOriginToAnyPoint - lineBearing);-- PEZ
Good approach to it - if you want the actual distance, it would be the sine of the above times the distance to the other point. -- Kawigi
Thanks - it's so obvious (but I could not sort it out) Paul Evans
Making a left/right stat segmenter? -- Kuuran
Nah - just trying to rate different points for Melee movement. -- Paul Evans
Seems like you'd do that with LateralVelocity instead. -- Kawigi
Isn't that basically what this is, just relative to a different system? -- Kuuran
Nah, it's distance, velocity needs a time component. If it's a left/right segmenter I'd rather use LateralVelocity or
bearingDelta = normalRelativeAngle(newBearing - oldBearing)-- PEZ
You're right, of course. -- Kuuran
It seems like lateral velocity would be better than bearingDelta in a few cases, when your movement influences the bearingDelta more (and in the opposite direction) than the opponent's movement. But they'd have the same sign about 90% of the time. -- Kawigi
Any examination of magnitude is automatically wrong, though. -- Kuuran
(Refering to Kawigis' alert about bearingDelta.) Yes, if you just go with the bearings as reported by your radar. (That's why my very first attempts with AngularTargeting failed so brutally.) But done right I think it maybe better removes your own movement than lateralVelocity. If you check some of my bot code published here on the wiki you'll find that I calculate it like so:
oldBearing = bearing(myOldPosition, enemyOldPosition); newBearing = bearing(myOldPosition, enemyNewPosition);Which, of course, could be exactly what Pauls more general description is about. It also serves to illustrate that, if you're like me and don't know much trig at all, using coordinates for about everything is the way to go. -- PEZ
Quick note: All of the trig being done is using robocode trigonometry, or at least should be. Not all of this is applicable in normal unit circle trig, though often replacing instances of 'sin' with 'cos' would fix it, and some of the trig being done isn't dependent on robocode trig as it analyzes smaller sub-portions, and normal laws hold. Just a caution before extending experience between the two. -- Kuuran