Click to See Complete Forum and Search --> : angle coordinate function
In conjunction with my timeangle function (http://phpbuilder.com/board/showthread.php?t=10339328) I wanted to create a function that would find the coordinates of the endpoint of a radius based on a specified angle and length. I created this so I could hopefully create an analog clock using PHP's image functions and in order to do this i need to have the start coordinates and ending coordinates of the line segment (used for hands on clock). I'm fairly new to PHP and this code took a while to figure out. It works, but the mathematics and efficiency seem kind of lacking. If someone could look at this and tell me if there's a better or easier way of accomplishing this it would be great.
Thanks!
// Function angle_point
// This function takes degrees and length and finds endpoint coordinates of radius
// Used for drawing out a clock with php
//
// Parameters are $angle (in degrees) and length of segment
function angle_point($angle, $length)
{
// Set default quadrant to 1
$q = 1;
// Find correct quardrant and adjust angle for computation
if ($angle > 90 && $angle <= 180)
{
$angle = $angle - 90;
$q = 2;
}
elseif ($angle > 180 && $angle <= 270)
{
$angle = $angle - 180;
$q = 3;
}
elseif ($angle > 270 && $angle < 360)
{
$angle = $angle - 270;
$q = 4;
}
elseif ($angle == 360)
{
$angle = 0;
$q = 1;
}
// Set angle depending on size
if ($angle > 45)
{
$new_angle = 90 - $angle;
}
else
{
$new_angle = $angle;
}
// Find side of right triangle
$s = abs((sin(deg2rad($new_angle))) * $length);
$c = abs((cos(deg2rad($new_angle))) * $length);
// Set coordinates based on location and original angle size
if ($q == 1 && $angle <= 45)
{
$point["x"] = $s;
$point["y"] = $c;
}
elseif ($q == 1 && $angle > 45)
{
$point["x"] = $c;
$point["y"] = $s;
}
elseif ($q == 2 && $angle <= 45)
{
$point["x"] = $c;
$point["y"] = -($s) ;
}
elseif ($q == 2 && $angle > 45)
{
$point["x"] = $s;
$point["y"] = -($c);
}
elseif ($q == 3 && $angle <= 45)
{
$point["x"] = -($s);
$point["y"] = -($c);
}
elseif ($q == 3 && $angle > 45)
{
$point["x"] = -($c);
$point["y"] = -($s);
}
elseif ($q == 4 && $angle <= 45)
{
$point["x"] = -($c);
$point["y"] = $s;
}
elseif ($q == 4 && $angle > 45)
{
$point["x"] = -($s);
$point["y"] = $c;
}
// Return an associative array with "x" and "y" with found coordinates
return ($point);
}
Weedpacket
04-24-2007, 04:46 AM
$x = $s;
$y = $c;
if($angle>45)
{
$t = $x;
$x = $y;
$y = $t;
}
if($q==2 || $q==4)
{
$t = $x;
$x = $y;
$y = $t;
}
if($q==2 || $q==3)
{
$y = -$y;
}
if($q==3 || $q==4)
{
$x = -$x;
}
$point['x'] = $x;
$point['y'] = $y;
severeheadache
04-24-2007, 11:30 AM
Ok, I am not sure I understand your problem, but it sounds like you want to find the x and y coordinates of a point on a circle? Since you are passing in the length (radius) of the circle, then it is a really simple geometry/trig problem (if I understand your request).
Assumptions:
1) Cartesian coordinate system (obvious since you want x and y)
2) the (0,0) point exists at the axis of the second and hour hands (so for instance, 11 o'clock would be negative x but positive y. Or 7 o'clock would be negative x and negative y)
equation of a circle (geometry):
eq1: radius^2 = x^2 + y^2
since we only know the radius, then we need another equation for the second unknown (trig):
eq2: sin( angle ) = ( x/radius )
so we solve for x in eq2:
x = radius * sin( angle )
NOTE: angle must be in radians. If it is in degrees (90 or 180, etc then you need to devide the angle by 2*Pi
So now we solve eq1 for y in terms of x:
y = sqrt( radius^2 - x^2 )
sooooo ... you can reduce all your code to:
// Function angle_point
// This function takes degrees and length and finds endpoint coordinates of radius
// Used for drawing out a clock with php
//
// Parameters are $angle (in degrees) and length of segment
function angle_point( $angleInDegrees, $length )
{
// Convert degrees To Radians
$angleInRadians = $angleInDegrees / ( 2 * pi() );
$point['x'] = $length * sin( $angleInRadians );
$point['y'] = sqrt( $length^2 - $point['x']^2;
return $point;
}
I think this is right, I was an engineer long time ago.
Hope this helps,
Michael
Thanks for the suggestions! I wish my math skills were a bit better.
I think I understand the math, but for some reason when I put values into the two variations I get two different results. For example, if I have an angle of 45 degrees and a radius of 5. My original function would give the following, which seems right:
x = 3.53553390593
y = 3.53553390593
When running the same parameters through the smaller function I receive this:
x = 3.84982765965
y = NAN
Since a 45 degree angle has a slope of 1, the values should be equal. I looked through the new function to try to figure out if i'm not interpreting it right or not so I can avoid using all my messy code.
This is my updated function (still a mess, but works with negative values and angles > 360)
function angle_point($angle, $length, $round = FALSE)
{
// Set default quadrant to 1
$q = 1;
// Checks if angle is negative, converts to positive and sets flag
if ($angle < 0)
{
$n = 1;
$angle = abs($angle);
}
// Find correct quardrant and adjust angle for computation
if ($angle > 360)
{
$angle = $angle % 360;
}
if (isset($n)) // Sets correct angle if negative
{
$angle = 360 - $angle;
}
if ($angle > 90 && $angle <= 180)
{
$angle = $angle - 90;
$q = 2;
}
if ($angle > 180 && $angle <= 270)
{
$angle = $angle - 180;
$q = 3;
}
if ($angle > 270 && $angle < 360)
{
$angle = $angle - 270;
$q = 4;
}
if ($angle == 360)
{
$angle = 0;
$q = 1;
}
// Set angle depending on size
if ($angle > 45)
{
$new_angle = 90 - $angle;
$ag = 1;
}
else
{
$new_angle = $angle;
}
// Find side of right triangle
$x = sin(deg2rad($new_angle)) * $length;
$y = cos(deg2rad($new_angle)) * $length;
// Set correct x and y values based on angle and quadrant
if ($angle > 45)
{
$t = $x;
$x = $y;
$y = $t;
}
if ($q == 2 || $q == 4)
{
$t = $x;
$x = $y;
$y = $t;
}
if ($q == 2 || $q == 3)
{
$y = -$y;
}
if ($q == 3 || $q == 4)
{
$x = -$x;
}
$point['x'] = $x;
$point['y'] = $y;
// Rounding
if ($round !== FALSE)
{
$point['x'] = round($point['x'], $round);
$point['y'] = round($point['y'], $round);
}
// Return an associative array with "x" and "y" with found coordinates
return ($point);
}
kilo dB
04-24-2007, 06:37 PM
It should be asin(deg2rad($angle_in_degrees))
this is the inverse function to sin, also known as arc sin. And note that php has a fn to do the conversion to radians, no need to writre one.
(I still am an engineer).
severeheadache
04-25-2007, 01:31 PM
Kilo Db, Uh, nope. asin is not correct. arc sin is used when you have a ratio and want to determine the angle. Not here. sin() is correct. What was not correct was my degree to rad conversion. It should have been multiply by 2Pi and devide by 360 (or multiply by Pi and devide by 180).
Sorry about that art6. this is the corrected code. And yes, you can use the built-in function, forgot that existed (thanks Kilo Db).
// Function angle_point
// This function takes degrees and length and finds endpoint coordinates of radius
// Used for drawing out a clock with php
//
// Parameters are $angle (in degrees) and length of segment
function angle_point( $angleInDegrees, $length )
{
// Convert degrees To Radians
$angleInRadians = deg2rad( $angleInDegrees );
// that function does this in case you were wondering about the math
// now that I remembered correctly :-)
// $angleInRadians = $angleInDegrees * ( pi() / 180 );
$point['x'] = $length * sin( $angleInRadians );
$point['y'] = sqrt( $length^2 - $point['x']^2 );
return $point;
}
kilo dB
04-25-2007, 01:46 PM
er..consider my face red.
I should know better, and I should know better than to suggest a fix without checking it!
Of course, you can combine the function calls:
$point['x'] = $length * sin(deg2rad( $angleInDegrees ) );
$point['y'] = sqrt( $length^2 - $point['x']^2 );
laserlight
04-25-2007, 06:15 PM
Just a moment. In your mathematical notation, ^ denotes exponentiation, right? If so, the simplified versions are incorrect as they perform bitwise XOR instead of exponentiation. Assuming severeheadache's most recent code snippet is correct, and incorporating kilo dB's changes, the code should actually be:
// Function angle_point
// This function takes degrees and length and finds endpoint coordinates of radius
// Used for drawing out a clock with php
//
// Parameters are $angle (in degrees) and length of segment
function angle_point( $angleInDegrees, $length )
{
// Note: Convert degrees To Radians
$point['x'] = $length * sin( deg2rad( $angleInDegrees ) );
$point['y'] = sqrt( $length * $length - $point['x'] * $point['x'] );
return $point;
}
kilo dB
04-25-2007, 06:59 PM
Very good, laserlight!
Gee, how many ways can we mess this up? Perhaps a better approach would be to use:
$point['y'] = $length * sin( deg2rad(90 - $angleInDegrees ) );
It is the same in JavaScript, no simple power operator. One either uses pow($x,2) or
$x * $x for squaring. I suspect the latter is best when only squaring, right?
severeheadache
04-25-2007, 10:52 PM
wow, yeah good catch. It has been literally years since I have had to raise anything to a power, If I was working on this problem I would have been scratching my head for hours, until I came the the sad realization that that was a bitwise operator. Good one laserlight.
O'well, the math was right, and collectively, we all solved his problem. Good work team!
Thanks for all your help! I feel sort of incompetent looking back at my orginal code. It achieved the right results, it was just unnecessarily long and clumsy. I learned a lot from this.
Anyway, I finished the basic script which will draw a clock based on the current or inputted time. Here's what I came up with. The image script could be reworked quite a bit, but since there are better alternatives already out, I don't think i'm going to keep working on it. I just wanted to work on the math and see if i could get the correct result.
I attached the script in a text file, by simply running it as a php file it should draw a png clock with the default time (current) and size (200 pixels).
Mgccl
04-26-2007, 08:24 PM
In PHP, if you want the most efficient usage of all resources, try think in radian and think the image not as 8 triangles but 1 circle(...of course it is not circle.. but think it that way)
When I do 2D programing, I found angle is a very boring scalar and usually I use a 2D vector(x velocity and y velocity) to describe an angle
btw art6 got a MSN, Yahoo IM or any other IM so I can contact you real time? I'm interested in your clock thing? Can't PM you >.<
PHP Builder
Copyright WebMediaBrands Inc. All Rights Reserved.