Help for the mathematically challenged (trig question)
Greetings to all.
I'm in the process of writing a turtle graphics program. I've got the screen set up with panels and buttons etc - the problem I have now is with the x, y position once the turtle has turned 'n' degrees left or right, eg;-
// according to user commands translated by the program
penDown(dx, dy);// start drawing at this point
forward(100);// go forward 100 pixels up or right - whatever ...
turnRight(45);// 45 degrees added from previous angle - assume zero for this purpose
forward(50);// what is the dx, dy of the turtle now?
I hope this problem is easy enough to follow.
The starting point is known - the angle is known - the length of the travel along that angle is known - I just need help with the calculation of the new coordinate in math form, psuedocode or otherwise.
Many thanks in advance.
[1043 byte] By [
Petraa] at [2007-10-2 10:06:10]

If someone doesn't give you the answer maybe this will help. http://mathforum.org/library/drmath/sets/high_trigonometry.html-S
Probably best to follow the link given in the reply above.
As I too am "mathematically challenged"
Here is a clunky solution, that could be replaced with somtehing much better
probably using Matrices for transforms.....
At Start Of Turtle Session:
Store , Initial Position, as { 0, 0 }
Store Initial Angleas?{ 90 } for NoRth
Call the Initial Angle CURRENT_ANGLE
{ wherever the turtle starts - call that { 0, 0, ( 90 - North ) )
Any Move Order can be considered to be:
TURN ANGLE - ANGLE Can be Zero
MOVE DISTANCE
Now Make a New Value For CURRENT_ANGLE
So:turnLeft( 45 ), must equate to CURRENT_ANGLE += 45
turnRight( 30 ) - CURRENT_ANGLE -= 30
Make a note of What "Quadrant" the Turtle will be moving
e.g. if 0 <= CURRENT_ANGLE <= 90 : Set Quadrant = 1
{ 4 Quadrants ......}
Consider Any move The Turtle makes as Equivalent to:
MoveLeft or Righta distance ( ie parallel to X axis ) then
MoveForward or Back a distance ( ie Parralle to Y Axis )
Allowing For the Quadrants Above.
If The Turtle is told to MoveDISTANCE
We Know CURRENT_ANGLE
So: Parrallel to the X Axis it Moves:
DISTANCE XCOSINE ( CURRENT _ANGLE )
Parrallel to the Y Axis it Moves
DISTANCE X SINE( CURRENT_ANGLE )
Making sure to allow for Quadrants
Add those two Values to the:
CURRENT_POSITION( X, Y )
End this Move
{Position realative to Initial Position is updated.}
Just remember if the90 <= Angle <= 270any move decreases X
etc, which is what I meant about Quadrants
And that Java kinda uses Radians and not degrees
Hope this gives you some usable ideas........
Hi,-
I would rather explain this in plain English instead of pseudocode.
Let's first get the measures straight ?I will be using unit vectors (unit vector = vector with length 1) so I divide 100/100 = 1, and 50/100 = 0,5.
Imagine (to make things easier) that your originating point dx, dy is 0, 0, and it is placed at the center of a unit circle with the radius length = 1. Then the length of the vector in the direction of the x-axis is also 1 (it's a unit vector!). Let us call this vector r and it's coordinates are <1,0 >. The length |r| of your first move from dx, dy = 0, 0 is thus 1.
Now imagine that your second move is also a vector (with length 0,5 = |r|*1/2), called v. In a unit circle, the coordinates of a vector are cos p (x-axis) and sin p (y-axis) for some point p. As the angle between r and v is 45 degrees, the coordinates of v's endpoint are ? <-cos45, -sin45>. (The values are negative as v lies in the 4th quadrant ?as I assume we move from left to the right 100 units (the vector r), then turn 45 degrees right, then go another 50 units (vector v)).
The resulting value is <-0.352, -0.353> for cos and sin of v' endpoint, respectively; these are also the coordinates of v and it's length is the square root of (-0.353^2 + -0.353^2) = 0.5.
What I then do is to calculate the projection of v onto r:
(v*r / |r|^2)*r
(here |r| is the length of r, ie 1). That gives me the vector w = <-0.353, 0>. What I now need to do is to subtract the length of this vector from the length of r. The length of w: the square root of (-0.353^2) = 0.353.
1 - 0.353 = 0.646 gives the x-coordinate
0.646*100 = 64.64 (back to the original proportions)
The y-coordinate is just 0.353 itself (easy to see because of measurements of v).
Thus, the coordinates are: x = 64.64; y = 35.35.
I hope this helps ?I sure did enjoy answering ;-)
Your Turtle should have instance variables that remember its position
and heading. Each operation should be seen in terms of how it
changes those variables (as well as other stuff it might do like drawing).
Something like this might appear in the Turtle classprivate double x, y, h;
void penDown(double dx, double dy) {
x = dx;
y = dy;
}
void turnRight(double dh) {
h += dh;
if(h > 2 * Math.PI) h -= 2 * Math.PI;
if(h < 0) h += 2 * Math.PI;
}
void forward(double d) {
double newx = x + Math.cos(h * Math.PI / 360);
double newy = y + Math.sin(h * Math.PI / 360);
// draw line (x,y)->(newx,newy)
x = newx;
y = newy;
}
A more complex arrangement might use two classes - one for the
turtle with just position and heading, and another to store the list of
lines that has been drawn.
Sorry, - and this was the bit you were asking about -void forward(double d) {
double newx = x + d * Math.cos(h * Math.PI / 360);
double newy = y + d * Math.sin(h * Math.PI / 360);
// draw line (x,y)->(newx,newy)
x = newx;
y = newy;
}
Thanks all for the help. The answer was slightly different as values increase from the top left hand corner of the drawing area.
Here's the solution I've gotif(angle>=0 && angle<=90) {
angle=90-angle;
xx = dx + forward * (Math.cos(angle* (2*Math.PI /360)));
yy = dy - forward * (Math.sin(angle* (2*Math.PI /360)));
}
else if(angle>90 && angle<=180) {
angle=angle-90;
xx = dx + forward * (Math.cos(angle* (2*Math.PI /360)));
yy = dy + forward * (Math.sin(angle* (2*Math.PI /360)));
}
else if(angle>180 && angle<=270) {
angle=270-angle;
xx = dx - forward * (Math.cos(angle* (2*Math.PI /360)));
yy = dy + forward * (Math.sin(angle* (2*Math.PI /360)));
}
else {
angle=angle-270;
xx = dx - forward * (Math.cos(angle* (2*Math.PI /360)));
yy = dy - forward * (Math.sin(angle* (2*Math.PI /360)));
}
// draw the line dx dy to xx, yy
dx =xx;
dy =yy;
Just for the sake of correctness, I made 2 mistakes in my post above:
1) I turned 180 - 45 = 135 degrees instead of 45 - sorry!
2) No need to use projection of vector upon vector for this task - it's an overkill. Just use vector addition instead.
What you need is distance dist (here: 0.5) multiplied by coordinates, to get the second vector:
dist * cos45, dist * -sin45 = < 0.353, -0.353 > =vector v;
Then r + v:
< 1, 0 > + < 0.353, -0.353 > = < 1.353, -0353 > : this vector, multiplied by 100, should give the coordinates.
Regards, V
I'm glad you've got an answer.
> The answer was slightly different as values increase from the top left
> hand corner of the drawing area
The maths<->computer conversion baffles me every time: I usually
resort to guessing and swearing. Also I notice your angles increase
to the right (clockwise), rather than the mathematical anti-clockwise.
Taking both these transformations into account - but still following the
logic of Vahagn's argument - I get the following as equivalent to the
code you last posted:double d2r = 2 * Math.PI / 360;
xx = dx + forward * Math.sin(angle * d2r);
yy = dy - forward * Math.cos(angle * d2r);
// draw the line dx dy to xx, yy
dx =xx;
dy =yy;
This thread has some info about standard cartesian->computer conversion: http://forum.java.sun.com/thread.jspa?threadID=699269
@MLRon: Thanks, and for your pointer in another thread recently toLine2D (alas, this came a week after I had wrestled with orderinga bunch of points so they would draw correctly as a convex Polygon...)
> @MLRon: Thanks, and for your pointer in another thread recently to
> Line2D (alas, this came a week after I had wrestled with ordering
> a bunch of points so they would draw correctly as a convex Polygon...)
You're welcome. Glad to help!
I had to rewrite some code including scaling and changing the coordinate system for work from math coordinates to computer coordinates, and looked it up. I can find the full equations with scaling, if you need (not till Monday, of course).