|
Author |
Topic: weird trig problem (Read 370 times) |
|
wilson
|
weird trig problem
« on: Apr 12th, 2004, 4:32am » |
|
hi. So I'm doing this bigger project, but am trying to test this bit of code to make sure it works before I move on. Basically, I want to have individual nodes reposition themselves according to the perspective of a single entity - in the project, this will be a user, in the test code, it's a rectangle. For example, there are a bunch of nodes positioned around a center point. When the user moves forward or backward, these nodes move closer / farther away along the y-axis. When the user turns (using the A or D keys, the nodes move closer / farther away from the user's vision -- which means they are basically just rotating around a circle with the center point the x,y of the user (which in this case happens to be the center of the stage). But I'm having a slight problem making this work. A quick test of the below code should make clear what I want to have happen. And everything is working as long as the angle of the node is between 0-180 degrees. However, if you try and position a node in front of you (180-360 degrees, assuming 270 degrees is right in front of the you) by moving it along the y axis (with w and s keys), then it seems to flip the axis. This seems like it should be a simple problem, but I'm having a really difficult go at it. If there is someone out there who sees a solution, I'd be ever so appreciative of a reply. Code is below. Thanks for any help in advance. _Will float i; //angle color c; //color of circle float x, y, track_x, track_y; // x, y are stage locations, //track_x, track_y are locations relative to the center of the circle (the square) boolean moveY; // true when user is moving along the y axis (using w and s keys) float radius, convert; //radius is the radius between circle and the center square String direction; // to tell showDirections which kind of arrow to draw void setup() { size(400, 400); i=90; //start w/ radius of 90 degrees c=color(0, 0, 0); background(255); moveY = true; //assume we are moving forward initially convert = radians(i); //convert i degrees to radians to work with radius = 50; //initial radius of 50 px track_x = radius * cos(convert); //grab x position from center track_y = radius * sin(convert); //y position from center x = width/2+track_x; //x position on stage y = height/2+track_y; //y position on stage } void loop() { //static stuff background(255); stroke(0); fill(0); rectMode(CENTER_RADIUS); ellipseMode(CENTER_RADIUS); rect(200, 200, 5, 5); //draw out a rectangle at center -- represents the user showDirection(direction); // pass direction to a function // that draws out the appropriate arrow //trig stuff noStroke(); fill(c); radius = dist(width/2, height/2, x, y); // calculate radius if (moveY) { //if we are moving forwards or backwards along the y axis //use cosA=b/c float temp = track_x/radius; //grab updated angle i = degrees(float(Math.acos(temp))); //update ellipse data in relation to center point convert = radians(i); track_x = radius * cos(convert); track_y = radius * sin(convert); //draw out ellipse ellipse(x, y, 5, 5); } else { //reposition the ellipse according to the current radius and angle convert = radians(i); track_x = radius * cos(convert); track_y = radius * sin(convert); //update stage position x = width/2+track_x; y = height/2+track_y; ellipse(x, y, 5, 5); } keyPressed(); } void mousePressed() { println(i); } //handles the key stuff, moving forward, backward, or turning left or right void keyPressed() { if (key == 'a') { if (i<=0) { i=360; } else { i-=1; } direction="LEFT"; moveY=false; } if (key == 'd') { if (i>=360) { i=0; } else { i+=1; } direction="RIGHT"; moveY=false; } if (key == 'w') { y+=2; direction="FORWARDS"; moveY=true; } if (key == 's') { y-=2; direction="BACKWARDS"; moveY=true; } } //draws out helper arrows that signal current direction / rotation void showDirection(String dir) { if (dir=="NONE") { rect(10, 10, 10, 10); } if (dir=="LEFT") { line(10, 20, 50, 20); line(40, 10, 50, 20); line(40, 30, 50, 20); } if (dir=="RIGHT") { line(10, 20, 50, 20); line(20, 10, 10, 20); line(20, 30, 10, 20); } if (dir=="FORWARDS") { line(10, 20, 20, 10); line(20, 10, 30, 20); line(20, 10, 20, 50); } if (dir=="BACKWARDS") { line(20, 10, 20, 50); line(10, 40, 20, 50); line(30, 40, 20, 50); } }
|
|
|
|
arielm
|
Re: weird trig problem
« Reply #1 on: Apr 12th, 2004, 10:27am » |
|
not tested, just an intuition: try to use atan2() instead of acos() or asin()
|
Ariel Malka | www.chronotext.org
|
|
|
wilson
|
Re: weird trig problem
« Reply #2 on: Apr 12th, 2004, 4:56pm » |
|
hm. atan2 doesn't seem to work, although I'm not sure exactly why.
|
|
|
|
wilson
|
Re: weird trig problem
« Reply #3 on: Apr 12th, 2004, 5:11pm » |
|
also... the var track_x (which holds the x position of the ellipse relative to the center point of the stage) seems to be inconsistently positive or negative... not sure why that is, but it may be a problem -- and abs(track_x) is giving me a NaN at certain points...
|
|
|
|
arielm
|
Re: weird trig problem
« Reply #4 on: Apr 12th, 2004, 5:56pm » |
|
i didn't meant to replace acos() as it is with atan2(), rather: you use the "cosA=b/c" pattern to find out an angle, so i meant that you have to adapt this pattern to "tanA=a/b" and then: A = atan2(b, a) all this because acos() and asin() are well-known trouble makers (i.e. producing NaN, aka errors, at some angles), also atan2() is always returning a "full angle" (i.e. no headache with signs, directions, etc...) another tip: you don't have to convert to degrees() and then back to radians()... just keep everything in radians...
|
Ariel Malka | www.chronotext.org
|
|
|
wilson
|
Re: weird trig problem
« Reply #5 on: Apr 12th, 2004, 7:07pm » |
|
thanks. I changed the angle calculation to: i = atan2(y-(height/2), x-(width/2)); (substracting height/2, width/2 to position according to the 0, 0 position of the coordinate origin -- could also prob. just use translate) so this works in most cases, but also, by what I can tell, yeilds random errors at some points... thanks for all your help -- any other suggestions would be much appreciated. code now looks like: //not yeilding a negative track_y if (moveY) { //if we are moving forwards or backwards along the y axis //use tanA=a/b //grab updated angle i = atan2(y-(height/2), x-(width/2)); //update ellipse data in relation to center point track_x = radius * cos(i); track_y = -(radius * sin(i)); //draw out ellipse ellipse(x, y, 5, 5); } else { //reposition the ellipse according to the current radius and angle track_x = radius * cos(i); track_y = radius * sin(i); //update stage position x = width/2+track_x; y = height/2+track_y; ellipse(x, y, 5, 5); }
|
|
|
|
wilson
|
Re: weird trig problem
« Reply #6 on: Apr 12th, 2004, 7:15pm » |
|
update: the above code seems to work, above 180 degrees, when the user is rotating clockwise... but counterclockwise rotation resets angle (i) to 0 degrees. ugh.
|
|
|
|
|