Author Topic: A Little Trigonometry  (Read 29531 times)

Offline AGP

  • quad
  • ******
  • Posts: 1726
    • View Profile
A Little Trigonometry
« on: May 30, 2009, 06:32:34 pm »
I need to find the theta of the following triangle. The only trigonometry book I kept from school doesn't answer this very well. Can anyone help?


Offline EgonOlsen

  • Administrator
  • quad
  • *****
  • Posts: 12295
    • View Profile
    • http://www.jpct.net
Re: A Little Trigonometry
« Reply #1 on: May 30, 2009, 07:07:24 pm »
You have the vectors from center to direction (a) and from center to pointer (b). With that, you can do

cos(a,b)=a*b/(|a||b|)

(with * being the scala/dot product between of a and b). Calculate the arccos from this value you should have your angle.

Offline AGP

  • quad
  • ******
  • Posts: 1726
    • View Profile
Re: A Little Trigonometry
« Reply #2 on: May 30, 2009, 07:40:07 pm »
I don't think I got this right:
Code: [Select]
SimpleVector center = opponentCar.getTransformedCenter();
SimpleVector a =  new SimpleVector(center);
a.add(direction);
SimpleVector b = new SimpleVector(center);
b.add(opponentPointer.getTransformedCenter());
float cosine = a.calcDot(b)/(Math.abs(a.x*a.y)*Math.abs(b.x*b.y));
float arcCosine = (float)Math.acos(cosine);

Offline paulscode

  • double
  • *****
  • Posts: 863
    • View Profile
    • PaulsCode.Com
Re: A Little Trigonometry
« Reply #3 on: May 30, 2009, 08:18:01 pm »
Another method is to use normal vectors and the law of cosines.

Before I start, are vectors Direction and CarPointer world coordinates or are they direction vectors from CarCenter?

If they are world coordinates, get them into direction vectors first:
Code: [Select]
SimpleVector a = directionCoordinate.calcSub( carCenter ).normalize();
SimpleVector b = carPointerCoordinate.calcSub( carCenter ).normalize();

If they are already direction vectors from CarCenter, then just normalize them:
Code: [Select]
SimpleVector a = new SimpleVector( direction ).normalize();
SimpleVector b = newSimpleVector( carPointer ).normalize();

Now think of vectors "a" and "b" as two sides of a triangle, both with length=1 (since we normalized them).  To get the length of the third side:
Code: [Select]
float lengthC = b.calcSub( a ).length();
So now you have three sides of a triangle.  To calculate the angle between sides A and B, use the law of cosines (plugging in values A=1, B=1, and C=lengthC):
Code: [Select]
float theta = (float) Math.acos( (2.0f - (lengthC * lengthC) ) / 2.0f );
NOTE: I used acos in the above formula, so theta will never come out to be more than PI radians (if the actual angle is larger, the formula will return 2*PI - angle).
« Last Edit: May 30, 2009, 08:21:42 pm by paulscode »

Offline AGP

  • quad
  • ******
  • Posts: 1726
    • View Profile
Re: A Little Trigonometry
« Reply #4 on: May 30, 2009, 08:45:11 pm »
They're world coordinates. Pointer is taken from the center of the car's child (which is a lot like that target I made for my ship to follow in that other game, if you remember). Direction is a world coordinate that the car has to chase (it's pretty much on rails--I'll come up with a pathfinding algorithm later). So I did this, but the car still doesn't rotate right. Do you have any idea why? And thanks in advance, pal.
Code: [Select]
SimpleVector a = direction.calcSub(center).normalize();
SimpleVector b = opponentPointer.getTransformedCenter().calcSub(center).normalize();
float lengthC = b.calcSub( a ).length();
float theta = (float) Math.acos( (2.0f - (lengthC * lengthC) ) / 2.0f );

Offline paulscode

  • double
  • *****
  • Posts: 863
    • View Profile
    • PaulsCode.Com
Re: A Little Trigonometry
« Reply #5 on: May 30, 2009, 09:03:14 pm »
So I did this, but the car still doesn't rotate right. Do you have any idea why? And thanks in advance, pal.
Code: [Select]
SimpleVector a = direction.calcSub(center).normalize();
SimpleVector b = opponentPointer.getTransformedCenter().calcSub(center).normalize();
float lengthC = b.calcSub( a ).length();
float theta = (float) Math.acos( (2.0f - (lengthC * lengthC) ) / 2.0f );
Hmm.. this looks right to me.  What kind of behavior are you seeing?

Perhaps it is a problem with the rotation axis.  Are your car, pointer, and direction all aligned on the x/z plane (i.e. is -y up)?  If not, you should rotate around the following axis:
Code: [Select]
SimpleVector rotationAxis = a.calcCross( b ).normalize(); // may need to switch a and b here
However, if everything is on a flat surface (-y is up), you should be able to just rotate around the y-axis.  Does it help to reverse the sign of theta? (perhaps it is rotating the wrong direction)
Code: [Select]
theta = -theta

Offline EgonOlsen

  • Administrator
  • quad
  • *****
  • Posts: 12295
    • View Profile
    • http://www.jpct.net
Re: A Little Trigonometry
« Reply #6 on: May 30, 2009, 09:04:53 pm »
Using the dot product, it should be something like this...

Code: [Select]
SimpleVector a= new SimpleVector(direction);
SimpleVector b = new SimpleVector(opponentPointer.getTransformedCenter());
b=b.calcSub(opponentCar.getTransformedCenter());
float cosine = a.calcDot(b)/(a.length()*b.length());
float arcCosine = (float)Math.acos(cosine);

Offline AGP

  • quad
  • ******
  • Posts: 1726
    • View Profile
Re: A Little Trigonometry
« Reply #7 on: May 30, 2009, 09:18:36 pm »
I'm rotating around the Z axis (+Z is up, the car moves on the X/Y plane). I'm not sure what your rotationAxis is suppose to do or for that matter where to plug it.

Offline AGP

  • quad
  • ******
  • Posts: 1726
    • View Profile
Re: A Little Trigonometry
« Reply #8 on: May 30, 2009, 09:22:48 pm »
And Egon, yours also doesn't work. Both are turning the car in odd directions, and I think it might be because my +Z is up. Sorry for the mathematical ignorance, but you forget so much after ten years without looking at this stuff much. Now, I'm thinking I'll brush up later. :-)

But here's a question: which method should be faster (yours or paulscode's), even if trivially? Are their results equally reliable?

Offline paulscode

  • double
  • *****
  • Posts: 863
    • View Profile
    • PaulsCode.Com
Re: A Little Trigonometry
« Reply #9 on: May 30, 2009, 09:33:18 pm »
I'm rotating around the Z axis (+Z is up, the car moves on the X/Y plane). I'm not sure what your rotationAxis is suppose to do or for that matter where to plug it.
Using the X/Y plane should work the same as using the X/Z plane.  My point was, there might be a problem if "up" wasn't the same for all entities involved.  This doesn't sound like the case, though.

The rotationAxis would be for if the initial "up" for the car is different than the destination "up" (driving on a hill for example).  In that case you couldn't rotate the car around its Z axis or it wouldn't end up in the correct orientation.  So instead of a call to car.rotateZ( theta ); you would use car.rotateAxis( rotationAxis, theta );

Offline AGP

  • quad
  • ******
  • Posts: 1726
    • View Profile
Re: A Little Trigonometry
« Reply #10 on: May 30, 2009, 09:37:17 pm »
Got it, thanks. I'm going to turn this into an applet really fast and show you how it's turning with that code you posted (and I reposted!). But no, it's not a simple question of turning the opposite way unfortunately.

Offline paulscode

  • double
  • *****
  • Posts: 863
    • View Profile
    • PaulsCode.Com
Re: A Little Trigonometry
« Reply #11 on: May 30, 2009, 09:39:13 pm »
Ok, great.  I had many problems with strange rotation behavior when working on my ship navigation system recently, so maybe it will be something I recognize.

Offline AGP

  • quad
  • ******
  • Posts: 1726
    • View Profile
Re: A Little Trigonometry
« Reply #12 on: May 30, 2009, 10:47:47 pm »
Do you happen to know what lwjgl's AppletLoader's error 7 is? It doesn't print anything other than that it's error 7 in the Java console.

Offline paulscode

  • double
  • *****
  • Posts: 863
    • View Profile
    • PaulsCode.Com
Re: A Little Trigonometry
« Reply #13 on: May 30, 2009, 11:05:50 pm »
I've never received the AppletLoader Error 7 before myself, but Melssj5 had that problem before (this thread).  He never mentioned if he figured out what was causing the problem, though.  Have you used the AppletLoader before?

Offline paulscode

  • double
  • *****
  • Posts: 863
    • View Profile
    • PaulsCode.Com
Re: A Little Trigonometry
« Reply #14 on: May 30, 2009, 11:19:22 pm »
I searched the lwjgl forums a little.  Matzon stated that this indicates the AppletLoader failed in the STATE_SWITCHING_APPLET part (whatever that means).  Someone mentioned seeing this error when accidentally using an incorrect jar version.  You might check to make sure all the LWJGL jars are from the same version, and make sure any other jars you are linking to (i.e. jpct.jar) are the same versions you compiled with.

The other thing that was mentioned is signing issues, but I have never had any problem with this myself (using the LWJGL signed jars to load unsigned jars seems to work fine, and is really the whole point of the AppletLoader anyway).  Could you post the HTML you are using to launch the AppletLoader?