Angles to decimal conversion - language-agnostic

I'm trying to understand some flash animation, and am having difficulty working out the following. Can anyone help?
I want to convert a degree range of 0 to 90, to a value between 0 and 1
These is an existing function to convert from the range 0 to 1 to degrees, eg:
function convertToDegrees(Int:Pos)
{
var rot = (45 * pos);
var degrees = (90 - ( rot * 2 ));
return degrees;
}
Now to convert backwards, from degrees to 0 to 1 value, I am trying:
(WHICH IS WRONG)
function convertFromDegrees(Int:currentDegreeValue )
{
var rot = (currentDegreeValue / 2) + 90;
var Pos = rot / 45;
return Pos;
}
Can anyone help me as to where I am going wrong?

The first function could be simplified to 90 * (1 - pos), so the reverse function would be 1 - (degrees / 90).

I want to convert a degree range of 0 to 90, to a value between 0 and 1
How about:
x / 90.0

rot = (90 - degrees) / 2

Related

as3 getting the "hours" in milliseconds in mp3

In As3 the code below gets the minutes and the seconds:
var minutes:uint = Math.floor(PrayPrayer.position / 1000 / 60);
var seconds:uint = Math.floor(PrayPrayer.position / 1000) % 60;
But what if your listening to an audio talk that goes over the hour mark?
What is the math needed to get the hours from an mp3 talk?
var hours:uint = Math.floor(PrayPrayer.position / 1000) % 60 & (((???????)));
this is my conversion method:
public static var MINUTE:Number = 60;
public static var HOUR:Number = 60 * MINUTE;
public static var DAY:Number = 24 * HOUR;
/**
* returns string created from seconds value in following format hours:minutes:seconds, i.e. 121 seconds will be displayed as 00:02:01
* #param seconds <i>Number</i>
* #return <i>String</i>
*/
public static function secondsToHMS(seconds:Number, doNotRound:Boolean = false):String
{
var _bNegative:Boolean = seconds < 0;
seconds = Math.abs(seconds);
var time:Number = (doNotRound) ? seconds:Math.round(seconds);
var ms:Number;
var msec:String;
if (doNotRound)
{
ms = seconds - (seconds | 0);
msec = prependZeros((ms * 1000) | 0, 3);
}
var sec:Number = (time | 0) % MINUTE;
var min:Number = Math.floor((time / MINUTE) % MINUTE);
var hrs:Number = Math.floor(time / HOUR);
//
return (_bNegative ? "-":"") +
((hrs > 9) ? "":"0") + hrs + ":" +
((min > 9) ? "":"0") + min + ":" +
((sec > 9) ? "":"0") + sec +
(doNotRound ? "." + msec:"");
}
prependZeros is another utility to add "0" in front of given string.
So PrayPrayer.position is in milliseconds. Your minutes line is dividing by 1000 to get seconds, then dividing by 60 to go from seconds to minutes. Your seconds line is looking at the remainder.
What you started in your hours line is using %, so will look at the remainder - you're using seconds there. % is the modulo operator. It gives you the remainder of integer division. So your line
var seconds:uint = Math.floor(PrayPrayer.position / 1000) % 60;
is finding the number of seconds (PrayPrayer.position / 1000), which could be something big like 2337, dividing by 60 and just keeping the remainder. 2337/60 = 38 remainder 57, so 2337%60 will be 57.
An easy way to find hours is to use the same trick with your minutes.
var minutes:uint = Math.floor(PrayPrayer.position / 1000 / 60);
var seconds:uint = Math.floor(PrayPrayer.position / 1000) % 60;
var hours:uint = Math.floor(minutes / 60);
minutes %= 60; // same as minutes = minutes % 60. Forces minutes to be between 0 and 59.

Decimals to one decimal place in as3?

I randomly generate a decimal using:
private function randomNumber(min:Number, max:Number):Number
{
return Math.random() * (max - min) + min;
}
It comes out with something like 1.34235346435.
How can I convert it so that its 1.3.
You can round to one decimal place like this;
var newValue:Number = Math.round(oldValue * 10)/10
Or an arbitrary number of decimal places like this:
function round2(num:Number, decimals:int):Number
{
var m:int = Math.pow(10, decimals);
return Math.round(num * m) / m;
}
trace(round2(1.3231321321, 3)); //1.323
Just use the .toFixed or .toPrecision method, it doesn't have to be complicated (note that the number will become a string so you'll need to assign it to such or convert it back).
eg.
var numb:Number = 4.3265891;
var newnumb;
newnumb=numb.toFixed(2);//rounds to two decimal places, can be any number up to 20
trace(newnumb);//traces 4.33
newnumb=numb.toPrecision(3);//the 3 means round to the first 3 numbers, can be any number from 1 to 20
trace(newnumb);//traces 4.33
If you need Number as result and performance, I would say this solution is more efficient than the Math.pow()/Math.round() one. If you need 3 decimals just change 100 by 1000.
var myNumber:Number = 3.553366582;
myNumber = (( myNumber * 100 + 0.5) >> 0) / 100;
//trace = 3.55
demonstrating the rounding :
var myNumber:Number = 3.557366582;
myNumber = (( myNumber * 100 + 0.5) >> 0) / 100;
//trace = 3.56
use this instead
return Math.Round((Math.random() * (max - min) + min),1);
,1 will round up till 1 place
for 2 places of decimal you can use
return Math.Round((Math.random() * (max - min) + min),2);
I hope this helps now.

strange rotation values

I got an object (called tempEnemy) which is flying around and shooting.
The problem is that I can't keep the value tempEnemy.rotateTo positive, i.e.
it shall be between 0 and 359 degrees. Currently rotateTo ranges from:
rotateTo < 0 (bug) && rotateTo > 0 && rotateTo > 359 (bug).
tempEnemy.dX = tempEnemy.destX - tempEnemy.x;
tempEnemy.dY = tempEnemy.destY - tempEnemy.y;
//I added 180 because my tempEnemy object was looking and shooting to the wrong direction
tempEnemy.rotateTo = (toDegrees(getRadians(tempEnemy.dX, tempEnemy.dY))) + 180;
if (tempEnemy.rotateTo > tempEnemy.frame + 180) tempEnemy.rotateTo -= 360;
if (tempEnemy.rotateTo < tempEnemy.frame - 180) tempEnemy.rotateTo += 360;
tempEnemy.incFrame = int((tempEnemy.rotateTo - tempEnemy.frame) / tempEnemy.rotateSpeed);
You can always use the modulo operator (%) to keep a value positive. The module calculates the rest of a division.
E.g. (example works with integers there for a division always has a left over.)
19 % 5 = 4
Because in the number 19 5 only fits 3 times (3 * 5 = 15,, 4 * 5 = 20,, 20 is too high) the left over is 4 (19 - 15). That is the modulo.
Extra examples:
7 % 3 = 1
15 % 4 = 3
21 % 9 = 3
The output of a modulo operation is never higher then the right hand operator - 1 There for it is perfect for your problem.
If your object is rotated 1234 degrees,, then operate it with a modulo 360 to get the respective number between 0 and 360 for it.
1234 % 360 = 154
Other more easier examples:
720 % 360 = 0
360 % 360 = 0
540 % 360 = 180
-180 % 360 = 180
-720 % 360 = 0
-540 % 360 = 180
Sounds like a classic angle averaging issue. Here's a formula that works for averaging angles
private function averageNums($a:Number, $b:Number):Number {
return = (Math.atan2( Math.sin($a) + Math.sin($b) , Math.cos($a) + Math.cos($b) ));
}

Generating random number from 0 to 10 including both

I heard of some Math.random() but I'm not sure about using it correctly. Number must be whole, so I suppose I'll need some rounding function.
Math.random produces a pseudo random number between [0;1[ (0 included, but 1 excluded)
To have an evenly distributed probability for all numbers between 0 and 10, you need to:
var a : int = Math.floor( Math.random() * 11 )
Math.random() returns a number between 0 - 1. Multiply it with 10 an round it using an int.
// random number between 1- 10
var randomRounded : int = Math.round(Math.random() * 10);
Edit: more accurate version
// more accurate
var randomRounded : int = Math.floor(Math.random() * 11);
Math.round(Math.random()*10); maybe?

Draw polygon x meters around a point

How can I create a polygon(only a square in my case) around a given point(lat/lang) x meters around the given point. It's just a visual representation of a geofence but I dont need all the calculations whether a point is outside a geofence or not. I tried using the code below but its creating a rectangle instead of a square and I'm not even sure if the 1000 meter boudaries are being rendered correctly.
var map = new GMap2(document.getElementById("map_canvas"));
map.setCenter(new GLatLng(37.4419, -122.1419), 13);
map.addControl(new GSmallMapControl());
GEvent.addListener(map, 'click', function(overlay, latlng) {
var lat = latlng.lat();
var lng = latlng.lng();
var height = 1000; //meters
var width = 1000; //meters
var polygon = new GPolygon(
[
new GLatLng(lat + height / 2 * 90 / 10000000, lng + width / 2 * 90 / 10000000 / Math.cos(lat)),
new GLatLng(lat - height / 2 * 90 / 10000000, lng + width / 2 * 90 / 10000000 / Math.cos(lat)),
new GLatLng(lat - height / 2 * 90 / 10000000, lng - width / 2 * 90 / 10000000 / Math.cos(lat)),
new GLatLng(lat + height / 2 * 90 / 10000000, lng - width / 2 * 90 / 10000000 / Math.cos(lat)),
new GLatLng(lat + height / 2 * 90 / 10000000, lng + width / 2 * 90 / 10000000 / Math.cos(lat))
], "#f33f00", 2, 1, "#ff0000", 0.2);
map.addOverlay(polygon);
});
I ported this PHP function to calculate the location an arbitrary distance and bearing from a known location, to Javascript:
var EARTH_RADIUS_EQUATOR = 6378140.0;
var RADIAN = 180 / Math.PI;
function calcLatLong(longitude, lat, distance, bearing)
{
var b = bearing / RADIAN;
var lon = longitude / RADIAN;
var lat = lat / RADIAN;
var f = 1/298.257;
var e = 0.08181922;
var R = EARTH_RADIUS_EQUATOR * (1 - e * e) / Math.pow( (1 - e*e * Math.pow(Math.sin(lat),2)), 1.5);
var psi = distance/R;
var phi = Math.PI/2 - lat;
var arccos = Math.cos(psi) * Math.cos(phi) + Math.sin(psi) * Math.sin(phi) * Math.cos(b);
var latA = (Math.PI/2 - Math.acos(arccos)) * RADIAN;
var arcsin = Math.sin(b) * Math.sin(psi) / Math.sin(phi);
var longA = (lon - Math.asin(arcsin)) * RADIAN;
return new GLatLng (latA, longA);
}
I have written a working example of this function that you can check out (source).
I use the Pythagorean Theorem to translate from a width of a square to a radius, if you want to use a simple 1000 meter radius from the center you can do that instead:
// this
var radius = 1000;
// instead of this
var radius = (Math.sqrt (2 * (width * width))) / 2;