Like all Robocoders, I am frequently faced with trig challenges when implementing a new algorithm for my robot.
Sometimes i am able to solve them myself, but some remain unsolved.
I hope the latter categorie of challenges can be met by the trig guru's that visit this site :-)

btw, visit the Trigonometry page for more resources.

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'?

- a = arcd / r

2: how do i calculate the angle 'a' in a circle with radius 'r', given the chord 'd'?

- a = 2 * asin (d / (2 * r))

3: how do i calculate point p1(x1, y1), given angle 'a', center p0(x0, y0) and radius 'r'?

- x1 = x0 + (sin(a) * r)
- y1 = y0 + (cos(a) * 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)?

- the radius is the same as the distance between the two points. Use the law of pythagoras: a^2 + b^2 = c^2, where c is the radius. Therefore, c = square root of a^2 + b^2.
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)?

- first calculate the radius r (see 4) the use the inverse sine (arcsine or asine) to get the angle.
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)); } }

- It seems like an easier way to do this is to use the arc tangent:

double calcAbsoluteAngle(double x0, double y0, double x1, double y1) { return Math.atan2(x1-x0, y1-y0); }

- how do i calculate center (x0,y0), given angle a, radius r, point p1(x1,y1)? (if it is possible) --Starrynte
- Assuming that angle is from the robocode perspective (0 degrees is north), x0 = x1 - r*sin(a) and y0 = y1 - r*sin(a). It's just simply the reverse of how you find the point from a center, angle, and radius. Hope that helps. -- Rednaxela

how do i calculate the point p2 (x2,y2), given angle 'a', center(x0, y0) and point p1 (x1,y1)?

- first calculate the radius (see 4)
- then calculate the absolute angle a1 (see 5)
- the calculate the Point (see 3)
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); }

- Make sure you don't call all the functions on this page "calcPoint", because it could get confusing.

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)?

- ?? couldn't figure out this one

- lemme try:
- the corners:
- c1 = (x1 + w/2, y1 + w/2)
- c2 = (x1 - w/2, y1 - w/2)
- c3 = (x1 + w/2, y1 - w/2)
- c4 = (x1 - w/2, y1 + w/2)

- we also know (only one of those is correct (the one with the largest a))
- ll(p0, c1).(p0, c2)ll = ll(p0, c1)ll*ll(p0, c2)ll*cos(a)
- ll(p0, c3).(p0, c4)ll = ll(p0, c3)ll*ll(p0, c4)ll*cos(a)
- ll(p0, c1).(p0, c3)ll = ll(p0, c1)ll*ll(p0, c3)ll*cos(a)
- ll(p0, c1).(p0, c4)ll = ll(p0, c1)ll*ll(p0, c4)ll*cos(a)
- ll(p0, c2).(p0, c3)ll = ll(p0, c2)ll*ll(p0, c3)ll*cos(a)
- ll(p0, c2).(p0, c4)ll = ll(p0, c2)ll*ll(p0, c4)ll*cos(a)

- thus (for the first one)
- a = cos^-1(ll(p0, c1).(p0,c2)ll/(ll(p0, c1)ll*ll(p0,c2)ll))

- and if we transform the vectors into coordinates we get (also, only for the first one, you'll need to max it out yourself):
- a = cos^-1(((x1+w/2-x0)*(x1-w/2-x0)+(y1+w/2-y0)*(y1-w/2-y0)) / (sqrt((x0-x1-w/2)^2+(y0-y1-w/2)^2) * sqrt((x0-x1+w/2)^2+(y0-y1+w/2)^2)) )

- the corners:

- Didn't check for errors, but I think it's correct ...

-- FnH

A rough calculation is;

- BOT_SIZE = 40 unit;
- radius = distance(pt1, pt2);
- angleDegrees = (360.0 * BOT_SIZE)/2.0*PI* radius;

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)

- a = (20 - 3 * Bp) / vB; -- shouldn't this be vR/(20-3*Bp) ?
- (vB=8, Bp=0.1 => a=23.3 degrees)
- (vB=8, Bp=3.0 => a=41.6 degrees)

- Another significant question is the maximum angle if the opponent doesn't move in an arc, but rather continues in a direction perpendicular to your position at fire-time:

- a = asin(vR/vB). -- I think atan(vR/vB) is correct if moving in a tangent as in the drawing. Sanity check: intuitively I think the angles should be less than when moving in an arc. Using asin is correct if the robot is moving in a chord.

- (vB=8, Bp=0.1 => a=24 degrees)
- (vB=8, Bp=3.0 => a=46.7 degrees)

-- 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)

- x2 = x0 + (sin(a) * r)
- y2 = y0 + (cos(a) * r)

- first calculate the absolute angle(see 5)
- the calculate the Point using the new radius (see 3)
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

btw, visit the Trigonometry page for more resources.

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