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]
# 1
If someone doesn't give you the answer maybe this will help. http://mathforum.org/library/drmath/sets/high_trigonometry.html-S
slenzia at 2007-7-13 1:22:29 > top of Java-index,Java Essentials,New To Java...
# 2

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

WIlfred_Deatha at 2007-7-13 1:22:29 > top of Java-index,Java Essentials,New To Java...
# 3

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

Vahagna at 2007-7-13 1:22:29 > top of Java-index,Java Essentials,New To Java...
# 4

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.

pbrockway2a at 2007-7-13 1:22:29 > top of Java-index,Java Essentials,New To Java...
# 5

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;

}

pbrockway2a at 2007-7-13 1:22:30 > top of Java-index,Java Essentials,New To Java...
# 6

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;

Petraa at 2007-7-13 1:22:30 > top of Java-index,Java Essentials,New To Java...
# 7

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

Vahagna at 2007-7-13 1:22:30 > top of Java-index,Java Essentials,New To Java...
# 8

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;

pbrockway2a at 2007-7-13 1:22:30 > top of Java-index,Java Essentials,New To Java...
# 9
This thread has some info about standard cartesian->computer conversion: http://forum.java.sun.com/thread.jspa?threadID=699269
MLRona at 2007-7-13 1:22:30 > top of Java-index,Java Essentials,New To Java...
# 10
@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...)
pbrockway2a at 2007-7-13 1:22:30 > top of Java-index,Java Essentials,New To Java...
# 11

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

MLRona at 2007-7-13 1:22:30 > top of Java-index,Java Essentials,New To Java...