Math.sin incorrect results even when converted to degrees - javascript

I'm trying to use sin on a variable and I saw you can convert it by using / (Math.PI / 180) but that seems contradictory if you want to convert it to degrees.. How do I properly convert and use sin in degree form? (On an iPhone calculator, for example it returns ~.707 from an input of 45, while this returns ~.806).
function click25() {
if (vi === 0) {
reactant = Math.sin(reactant / (Math.PI / 180))
}
}

You need to multiply the value in degree by (pi/180) to convert into the equivalent value in radians
var reactant = 45;
var vi = 0;
function click25() {
if (vi === 0) {
reactant = Math.sin(reactant * (Math.PI / 180))
}
console.log(reactant);
}
click25();

Related

Converting transform radian to degree value is not showing properly for few values using javascript

Radian to degree:
var Degrees = Radian * (180 / Math.PI)
Degree to transform
var bval=Math.sin(45*Math.PI / 180);
Transform to angle
var angle = Math.round(Math.asin(bval) * (180/Math.PI));
Degree to radian:
var Radians = Degree * Math.PI/180
The above steps tried with the below code with values "-3.17934" & "-0.9998"
"-3.17934" --> This value properly converted not closed to First Radian & Last radian
"-0.9998" --> This value properly converted & closed to First Radian & Last radian
`<script>
console.log("--------------------------------");
//var rad2="-3.17934";//-3.17934
var rad2="-0.9998";//-0.9998
console.log("First radian: "+rad2);
var rad2angle = rad2 * (180/Math.PI);
console.log("2 rad2angle: "+rad2angle);
var tt = Math.sin(rad2angle*Math.PI / 180);
console.log("3 To Transform: "+tt);
var t2angle = Math.round(Math.asin(tt) * (180/Math.PI));
console.log("2 t2angle: "+t2angle);
var angle2radian = t2angle * Math.PI/180;
console.log("Last radian: "+angle2radian);
</script>`
Thanks in Advance.
I tried with above code given in detail area.
While testing a script I realized that there was a problem for values ​​greater than PI/2 or less than -PI/2. So I modified the script accordingly and it works even for the value "-3.17934"
This is the script I use to test
<script>
var listeRadian = [-0.50,-1,-1.5,-2,0.50,1,1.5,2];
// For Each Value of Radian
for(i=0;i<listeRadian.length;i++)
{
// Extraction
let radianValue = listeRadian[i];
console.log("Radian Value : "+radianValue);
// Calculate Sinus
var sinus = Math.sin(radianValue);
console.log("Angle : "+radianValue*(180/Math.PI));
console.log("Sinus : "+sinus);
// Calculate Sinus Inv
var sinusInv = (Math.asin(sinus) * (180/Math.PI));
if(radianValue>Math.PI/2) sinusInv = 180-sinusInv;
if(radianValue<(Math.PI/2)*-1) sinusInv = (180+sinusInv)*-1;
console.log("Sinus Inv : "+sinusInv);
// Calculate Radian
var radianCalc = sinusInv * Math.PI/180;
console.log("Radian Calc : "+radianCalc);
console.log("\n");
}
// End - For Each Value of Radian
</script>
Hoping that my answer and my remark on PI/2 can help you.
Information about asin() function : Here
I have modified the code & i got the proper output.
Thanks everyone.
<script>
console.log("--------------------------------");
var rad2="-0.9998";
console.log("1- Radian Value: "+rad2);
var rad2angle = rad2 * (180/Math.PI);
console.log("2- Radian to Angle: "+rad2angle);
var cos=Math.cos(rad2angle*Math.PI / 180);
var sin=Math.sin(rad2angle*Math.PI / 180);
var catrans = [];
const trans = [cos, sin, -sin, cos, 0, 0];
console.log("3- Form Transform: "+trans.toString());
var tt= Math.atan2(sin,cos);
var angle2radian = tt * 180/Math.PI;
console.log("2- Transform to Angle: "+angle2radian);
console.log("1- Angle to radian: "+tt);
</script>

Convert distance between 2 points in a plane into distance between two point on Earth

So finding the distance between two points in a plane and between two points on Earth is a pretty easy google search away, but converting one to the other I couldn't find how to do.
Using these two functions
function dist = (lat1: number, lng1: number, lat2: number, lng2: number) => {
return Math.sqrt((lat1 - lat2) * (lat1 - lat2) + (lng1 - lng2) * (lng1 - lng2))
}
function distOnEarthInMeters = (lat1: number, lng1: number, lat2: number, lng2: number) => {
if (lat1 === lat2 && lng1 === lng2) return 0
const radianLat1 = lat1 * (Math.PI / 180)
const radianLng1 = lng1 * (Math.PI / 180)
const radianLat2 = lat2 * (Math.PI / 180)
const radianLng2 = lng2 * (Math.PI / 180)
const earthRadius = 6378137
const diffLat = radianLat1 - radianLat2
const diffLng = radianLng1 - radianLng2
const sinLat = Math.sin(diffLat / 2)
const sinLng = Math.sin(diffLng / 2)
const a = Math.pow(sinLat, 2.0) + Math.cos(radianLat1) * Math.cos(radianLat2) * Math.pow(sinLng, 2.0)
return Math.floor(earthRadius * 2 * Math.asin(Math.min(1, Math.sqrt(a))))
}
I get these:
dist(-27, -42, -26, -41) === 1.4142135623730951
distOnEarthInMeters(-27, -42, -26, -41) === 149386
But can can I turn one into the other without knowing the coordinates?
make 1.4142135623730951 become 149386 and 1.4142135623730951 become 149386
(copied to https://math.stackexchange.com/questions/4489148)
As others said this is a math problem. But the answer is no you can't find it. Every map projection changes some distances on the globe. Some projections can conserve some distances, but never all.

Sorting by distance with Titanium alloy models

I recently used Titanium and Alloy to develop an android application. Now I'm trying (for the first time) to sort a bound backbone collection by distance with a comparator function, but it doesn't work.
comparator: function(game) {
var lon1, lat1, lat2, lon2;
if (Ti.Geolocation.locationServicesEnabled) {
Ti.Geolocation.getCurrentPosition(function(e) {
if (e.error) {
Ti.API.error('Error:' + e.error);
return 0;
} else {
Ti.API.info(e.coords);
lon1 = e.coords.longitude;
lat1 = e.coords.latitude;
Titanium.Geolocation.forwardGeocoder(game.get("camp"), function(e) {
if (e.success) {
lat2 = e.latitude;
lon2 = e.longitude;
var R = 6371; // km
var dLat = (lat2 - lat1) * Math.PI / 180;
var dLon = (lon2 - lon1) * Math.PI / 180;
var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
Math.cos(lat1 * Math.PI / 180) * Math.cos(lat2 * Math.PI / 180) *
Math.sin(dLon / 2) * Math.sin(dLon / 2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
var d = R * c;
console.log("KM: " + parseInt(d));
return parseInt(d);
} else {
console.log("Unable to find address");
return 0;
}
});
}
});
} else {
console.log('please enable location services')
return 0;
}
}
In my controller, I use:
var games = Alloy.Collections.allGames;
games.sort();
games.fetch();
Can you tell me what is wrong?
I don't use neither Titanium or Alloy, but I can see why your comparator function won't work.
Backbone collection's comparator property
First, to see why it doesn't work, you need to understand what's the collection's comparator property, what's available and how to implement one.
There are (at least) 3 types of value a collection's comparator property can take.
The name of an attribute as a string
comparator: 'fieldName'
A sortBy function which takes a single argument
comparator: function(model) {
// return a numeric or string value by which the model
// should be ordered relative to others.
return Math.sin(model.get('myNumber'));
}
A sort function that expects two arguments
comparator: compare(modelA, modelB) {
var field = 'myNumber',
numA = modelA.get(field),
numB = modelB.get(field);
if (numA < numB) {
return -1;
}
if (numA > numB) {
return 1;
}
// a must be equal to b
return 0;
}
Why yours fails?
The short answer: It only ever returns undefined or 0 depending on the value of Ti.Geolocation.locationServicesEnabled.
You have made a convoluted function to sort your models in which you use asynchronous functions (getCurrentPosition, forwardGeocoder) and you put all the logic inside callbacks which are evaluated when the collection has already finished sorting.

Have javascript assume degrees instead of radians? [duplicate]

This question already has answers here:
What is the method for converting radians to degrees?
(12 answers)
Closed 7 years ago.
My problem is that I have an input field where you type in some degrees and a velocity ( like 44 degrees and 10m/s). Then that runs through some javascript, and it spits out a trajectory.
A jsfiddle showing my problem a little better.
http://jsfiddle.net/3ahhf1xL/1/
How do i input it as degrees? or convert radians to the exact same amount of degrees?
Edit: I want to convert it to the same amount of degrees. an example of 44 radians would result in 2521 degrees if I straight up convert them instead of 44 degrees (amount of radians = amount of degrees).
You just need to multiply the degree by PI/180. In JavaScript, it looks like this:
var rads = degrees * (Math.PI / 180);
Like this:
function toRadians(degrees) {
return degrees * (Math.PI / 180);
}
function toDegrees(radians) {
return radians * (180 / Math.PI);
}
1 degree equals 0.0174532925 radians..
So you can change your code into this:
function submit() {
var a = document.getElementById('var1').value * 0.0174532925;
var b = document.getElementById('var2').value * 0.0174532925;
alert(a);
myGraph.drawEquation(function(x) {
return x*Math.tan(a)-((9.80665*(x*x))/(2*b^2*Math.cos(a)^2));
}, 'red', 3);
}

Mercator longitude and latitude calculations to x and y on a cropped map (of the UK)

I have this image. It's a map of the UK (not including Southern Ireland):
I have successfully managed to get a latitude and longitude and plot it onto this map by taking the leftmost longitude and rightmost longitude of the UK and using them to work out where to put the point on the map.
This is the code (for use in Processing.js but could be used as js or anything):
// Size of the map
int width = 538;
int height = 811;
// X and Y boundaries
float westLong = -8.166667;
float eastLong = 1.762833;
float northLat = 58.666667;
float southLat = 49.95;
void drawPoint(float latitude, float longitude){
fill(#000000);
x = width * ((westLong-longitude)/(westLong-eastLong));
y = (height * ((northLat-latitude)/(northLat-southLat)));
console.log(x + ", " + y);
ellipseMode(RADIUS);
ellipse(x, y, 2, 2);
}
However, I haven't been able to implement a Mercator projection on these values. The plots are reasonably accurate but they are not good enough and this projection would solve it.
I can't figure out how to do it. All the examples I find are explaining how to do it for the whole world. This is a good resource of examples explaining how to implement the projection but I haven't been able to get it to work.
Another resource is the Extreme points of the United Kingdom where I got the latitude and longitude values of the bounding box around the UK. They are also here:
northLat = 58.666667;
northLong = -3.366667;
eastLat = 52.481167;
eastLong = 1.762833;
southLat = 49.95;
southLong = -5.2;
westLat = 54.45;
westLong = -8.166667;
If anyone could help me with this, I would greatly appreciate it!
Thanks
I wrote a function which does exactly what you were looking for. I know it's a bit late, but maybe there are some other people interested in.
You need a map which is a mercator projection and you need to know the lat / lon positions of your map.
You get great customized mercator maps with perfect matching lat / lon positions from TileMill which is a free software from MapBox!
I'm using this script and tested it with some google earth positions. It worked perfect on a pixel level. Actually I didnt test this on different or larger maps. I hope it helps you!
Raphael ;)
<?php
$mapWidth = 1500;
$mapHeight = 1577;
$mapLonLeft = 9.8;
$mapLonRight = 10.2;
$mapLonDelta = $mapLonRight - $mapLonLeft;
$mapLatBottom = 53.45;
$mapLatBottomDegree = $mapLatBottom * M_PI / 180;
function convertGeoToPixel($lat, $lon)
{
global $mapWidth, $mapHeight, $mapLonLeft, $mapLonDelta, $mapLatBottom, $mapLatBottomDegree;
$x = ($lon - $mapLonLeft) * ($mapWidth / $mapLonDelta);
$lat = $lat * M_PI / 180;
$worldMapWidth = (($mapWidth / $mapLonDelta) * 360) / (2 * M_PI);
$mapOffsetY = ($worldMapWidth / 2 * log((1 + sin($mapLatBottomDegree)) / (1 - sin($mapLatBottomDegree))));
$y = $mapHeight - (($worldMapWidth / 2 * log((1 + sin($lat)) / (1 - sin($lat)))) - $mapOffsetY);
return array($x, $y);
}
$position = convertGeoToPixel(53.7, 9.95);
echo "x: ".$position[0]." / ".$position[1];
?>
Here is the image I created with TileMill and which I used in this example:
In addition to what Raphael Wichmann has posted (Thanks, by the way!),
here is the reverse function, in actionscript :
function convertPixelToGeo(tx:Number, ty:Number):Point
{
/* called worldMapWidth in Raphael's Code, but I think that's the radius since it's the map width or circumference divided by 2*PI */
var worldMapRadius:Number = mapWidth / mapLonDelta * 360/(2 * Math.PI);
var mapOffsetY:Number = ( worldMapRadius / 2 * Math.log( (1 + Math.sin(mapLatBottomRadian) ) / (1 - Math.sin(mapLatBottomRadian)) ));
var equatorY:Number = mapHeight + mapOffsetY;
var a:Number = (equatorY-ty)/worldMapRadius;
var lat:Number = 180/Math.PI * (2 * Math.atan(Math.exp(a)) - Math.PI/2);
var long:Number = mapLonLeft+tx/mapWidth*mapLonDelta;
return new Point(lat,long);
}
Here's another Javascript implementation. This is a simplification of #Rob Willet's solution above. Instead of requiring computed values as parameters to the function, it only requires essential values and computes everything from them:
function convertGeoToPixel(latitude, longitude,
mapWidth, // in pixels
mapHeight, // in pixels
mapLngLeft, // in degrees. the longitude of the left side of the map (i.e. the longitude of whatever is depicted on the left-most part of the map image)
mapLngRight, // in degrees. the longitude of the right side of the map
mapLatBottom) // in degrees. the latitude of the bottom of the map
{
const mapLatBottomRad = mapLatBottom * Math.PI / 180
const latitudeRad = latitude * Math.PI / 180
const mapLngDelta = (mapLngRight - mapLngLeft)
const worldMapWidth = ((mapWidth / mapLngDelta) * 360) / (2 * Math.PI)
const mapOffsetY = (worldMapWidth / 2 * Math.log((1 + Math.sin(mapLatBottomRad)) / (1 - Math.sin(mapLatBottomRad))))
const x = (longitude - mapLngLeft) * (mapWidth / mapLngDelta)
const y = mapHeight - ((worldMapWidth / 2 * Math.log((1 + Math.sin(latitudeRad)) / (1 - Math.sin(latitudeRad)))) - mapOffsetY)
return {x, y} // the pixel x,y value of this point on the map image
}
I've converted the PHP code provided by Raphael to JavaScript and can confirm it worked and this code works myself. All credit to Raphael.
/*
var mapWidth = 1500;
var mapHeight = 1577;
var mapLonLeft = 9.8;
var mapLonRight = 10.2;
var mapLonDelta = mapLonRight - mapLonLeft;
var mapLatBottom = 53.45;
var mapLatBottomDegree = mapLatBottom * Math.PI / 180;
*/
function convertGeoToPixel(latitude, longitude ,
mapWidth , // in pixels
mapHeight , // in pixels
mapLonLeft , // in degrees
mapLonDelta , // in degrees (mapLonRight - mapLonLeft);
mapLatBottom , // in degrees
mapLatBottomDegree) // in Radians
{
var x = (longitude - mapLonLeft) * (mapWidth / mapLonDelta);
latitude = latitude * Math.PI / 180;
var worldMapWidth = ((mapWidth / mapLonDelta) * 360) / (2 * Math.PI);
var mapOffsetY = (worldMapWidth / 2 * Math.log((1 + Math.sin(mapLatBottomDegree)) / (1 - Math.sin(mapLatBottomDegree))));
var y = mapHeight - ((worldMapWidth / 2 * Math.log((1 + Math.sin(latitude)) / (1 - Math.sin(latitude)))) - mapOffsetY);
return { "x": x , "y": y};
}
I think it's worthwhile to keep in mind that not all flat maps are Mercator projections. Without knowing more about that map in particular, it's hard to be sure. You may find that most maps of a small area of the world are more likely to be a conical type projection, where the area of interest on the map is "flatter" than would be on a global Mercator projection. This is especially more important the further you get away from the equator (and the UK is far enough away for it to matter).
You may be able to get "close enough" using the calculations you're trying, but for best accuracy you may want to either use a map with a well-defined projection, or create your own map.
I know the question was asked a while ago, but the Proj4JS library is ideal for transforming between different map projections in JavaScript.
UK maps tend to use the OSGB's National Grid which is based on a Transverse Mercator projection. Ie. like a conventional Mercator but turned 90 degrees, so that the "equator" becomes a meridian.
#Xarinko Actionscript snippet in Javascript (with some testing values)
var mapWidth = 1500;
var mapHeight = 1577;
var mapLonLeft = 9.8;
var mapLonRight = 10.2;
var mapLonDelta = mapLonRight - mapLonLeft;
var mapLatBottom = 53.45;
var mapLatBottomRadian = mapLatBottom * Math.PI / 180;
function convertPixelToGeo(tx, ty)
{
/* called worldMapWidth in Raphael's Code, but I think that's the radius since it's the map width or circumference divided by 2*PI */
var worldMapRadius = mapWidth / mapLonDelta * 360/(2 * Math.PI);
var mapOffsetY = ( worldMapRadius / 2 * Math.log( (1 + Math.sin(mapLatBottomRadian) ) / (1 - Math.sin(mapLatBottomRadian)) ));
var equatorY = mapHeight + mapOffsetY;
var a = (equatorY-ty)/worldMapRadius;
var lat = 180/Math.PI * (2 * Math.atan(Math.exp(a)) - Math.PI/2);
var long = mapLonLeft+tx/mapWidth*mapLonDelta;
return [lat,long];
}
convertPixelToGeo(241,444)
C# implementation:
private Point ConvertGeoToPixel(
double latitude, double longitude, // The coordinate to translate
int imageWidth, int imageHeight, // The dimensions of the target space (in pixels)
double mapLonLeft, double mapLonRight, double mapLatBottom // The bounds of the target space (in geo coordinates)
) {
double mapLatBottomRad = mapLatBottom * Math.PI / 180;
double latitudeRad = latitude * Math.PI / 180;
double mapLonDelta = mapLonRight - mapLonLeft;
double worldMapWidth = (imageWidth / mapLonDelta * 360) / (2 * Math.PI);
double mapOffsetY = worldMapWidth / 2 * Math.Log((1 + Math.Sin(mapLatBottomRad)) / (1 - Math.Sin(mapLatBottomRad)));
double x = (longitude - mapLonLeft) * (imageWidth / mapLonDelta);
double y = imageHeight - ((worldMapWidth / 2 * Math.Log((1 + Math.Sin(latitudeRad)) / (1 - Math.Sin(latitudeRad)))) - mapOffsetY);
return new Point()
{
X = Convert.ToInt32(x),
Y = Convert.ToInt32(y)
};
}
If you want to avoid some of the messier aspects of lat/lng projections intrinsic to Proj4JS, you can use D3, which offers many baked-in projections and renders beautifully. Here's an interactive example of several flavors of Azimuthal projections. I prefer Albers for USA maps.
If D3 is not an end-user option -- say, you need to support IE 7/8 -- you can render in D3 and then snag the xy coordinates from the resultant SVG file that D3 generates. You can then render those xy coordinates in Raphael.
This function works great for me because I want to define the mapHeight based on the map I want to plot. I'm generating PDF maps. All I need to do is pass in the map's max Lat , min Lon and it returns the pixels size for the map as [height,width].
convertGeoToPixel(maxlatitude, maxlongitude)
One note in the final step where $y is set, do not subtract the calculation from the mapHeight if your coordinate system 'xy' starts at the bottom/left , like with PDFs, this will invert the map.
$y = (($worldMapWidth / 2 * log((1 + sin($lat)) / (1 - sin($lat)))) - $mapOffsetY);

Categories