double mypercentslope = 1
With a calculator if I wanted to convert that to a degree, I'd simply do: arctan(0.01);
I've tried Math.Atan(0.01) and it's reporting an incorrect value. I've read that c# uses radians but not sure, based on that, how to accomplish what i need. Thanks all!
Yes, Math.Atan does give it's result in radians (from here). You could use this to convert to degrees:
private double RadianToDegree(double angle)
{
return angle * (180.0 / Math.PI);
}
(the above code snippet is taken from here)
so full working code might look like:
double myPercentSlope = 100;
double rads = Math.Atan(myPercentSlope/100);
double degrees = rads * (180.0 / Math.PI);
Related
I'm currently work on a certain program (in C# .NET - winforms), and among the things i came across the following problem:
I need to calculate the point (t, f(t)) given that:
f(t) = [Sin(t) / 16*Cos^4(t)]^(1/3), Such that: t: -89.995 -> 89.995. (t is real number).
Note: the value of t is ranges from -89.995 to 89.995.
I use the .NET functions Math.Sin(), Math.Cos(), Math.Pow() for the calculations, the converssions from radians to degrees are correct and all right.
The problem is that for every t < 0 that i put in f(t) i got NaN ( = not a number) from the above functions, and when i calculate it in a standard calculator i get standard correct values.
For examplae: t = -0.9165664, f(t) = -0.1000096, (Taht's the correct result).
but when i use the .NET functions in my program, the result i get for t = -0.9165664 is NaN (= Not a Number), why? it's not an exeption, not dividing by zero or something like that.
The code i use in the program:
float t = -0.9165664;
float numerator = Math.Sin(t * Math.PI / 180.0f);
float denominator = 16.0f * Math.Pow(Math.Cos(t * Math.PI / 180.0f), 4)
float ft = (float)Math.Pow(numerator / denominator, 1.0f / 3.0f));
Note: I can't cahnge the type of ft to double.
When i put any t > 0 in the above code it gives the correct result.
Can someone explain me what wrong or suggest a possible solution?
Thanks for help!!!
The problem is the definition of the Math.Pow function, see the documentation. Since your exponent is fixed and you're looking for the 3rd root as a real number, try something like
float t = -0.9165664;
float numerator = Math.Sin(t * Math.PI / 180.0f);
float denominator = 16.0f * Math.Pow(Math.Cos(t * Math.PI / 180.0f), 4)
float val = numerator / denominator;
float ft = Math.Sign(val) * (float)Math.Pow(Math.Abs(val), 1.0f / 3.0f));
I am trying to develop an algorithm that involves normalizing GPS coordinates (latitude/longitude). That means, that being given two points A (lat1,lon1) and B(lat2,lon2) I would like to insert a point C that is linear with AB (same arc) and is placed at a specific distance from A and B (eg: A to B distance is 0.5km and I want point C to be at 0.1 km from A, on the AB arc). How can I calculate the coordinates for point C?
For the purpose given, it is enough to approximate Earth as a perfect spherical object.
I have found this article, but it gives the formula for midpoint only (and I don't fully understand it, in order to adapt).
midpoint between two latitude and longitude
Thank you.
Edit: I tried this but it gives wrong answers
public static void normalizedPoint(double lat1, double lon1, double lat2, double lon2, double dist){
double constant=Math.PI/180;
double angular = dist/6371;
double a = Math.Sin( 0* angular )/Math.Sin(angular);
double b = Math.Sin(1*angular)/Math.Sin(angular);
double x = a * Math.Cos(lat1) * Math.Cos(lon1) + b * Math.Cos(lat2) * Math.Cos(lon2);
double y = a * Math.Cos(lat1) * Math.Sin(lon1) + b * Math.Cos(lat2) * Math.Sin(lon2);
double z = a * Math.Sin(lat1) + b * Math.Sin (lon2);
double lat3 = Math.Atan2(z, Math.Sqrt( x*x + y*y ));
double lon3 = Math.Atan2(y, x);
Console.WriteLine(lat3/constant + " " + lon3/constant );
}
As far as I understood the original formulas this should return one of the 2 original points, but it does not(because the fraction used is 1). Also the variable dist is the distance from the 2 points and is properly calculated (checked with the same website).
Edit 2: I am providing as inputs coordinates for 2 geographic points (lat1, lon1, lat2 lon2) and the distance between them. I'm trying to get an intermediary point (lat3,lon3).
As I point out in an answer on the linked to question, you need to change all of your inputs to use radians rather than degrees.
I believe you also had an error for z where you used lon2 rather than lat2.
With those corrections, I get the answer you're seeking:
public static void normalizedPoint(double lat1, double lon1,
double lat2, double lon2,
double dist)
{
double constant = Math.PI / 180;
double angular = dist / 6371;
double a = Math.Sin(0 * angular) / Math.Sin(angular);
double b = Math.Sin(1 * angular) / Math.Sin(angular);
double x = a * Math.Cos(lat1* constant) * Math.Cos(lon1* constant) +
b * Math.Cos(lat2* constant) * Math.Cos(lon2* constant);
double y = a * Math.Cos(lat1* constant) * Math.Sin(lon1* constant) +
b * Math.Cos(lat2* constant) * Math.Sin(lon2* constant);
double z = a * Math.Sin(lat1* constant) + b * Math.Sin(lat2* constant);
double lat3 = Math.Atan2(z, Math.Sqrt(x * x + y * y));
double lon3 = Math.Atan2(y, x);
Console.WriteLine(lat3 / constant + " " + lon3 / constant);
}
Of course, the above can be vastly simplified by only converting angles ones, avoiding repeated calculations of the same Sin/Cos values, etc.
Calling:
normalizedPoint(47.20761, 27.02185, 47.20754, 27.02177, 1);
I get the output:
47.20754 27.02177
Not sure if the original author found some answer, but since I had similar problem and developed working solution, I think it would be good to post it here.
The Problem
Having two geographical points, A and B, find intermediate point C which lies exactly on the direct way from A to B and is N kilometers far from A (where N is less than distance between A and B, otherwise C = B).
My Context
I was developing small pet project based on microservices architecture. The idea was to launch missile from given deployment platform (point A) to chosen target location (point B). I had to create some kind of simulator that sends some messages about current missile Geo location after it is launched, so I had to find those intermediate points between A and B somehow.
Solution Context
Eventually, I developed C# based solution based on this great web page - https://www.movable-type.co.uk/scripts/latlong.html.
That web page has all the explanations, formulas and JavaScript code at the bottom. If you are not familiar with the C#, you can use their JavaScript implementation.
My C# Implementation
Your input is Location A, Location B and the distance.
You need to find bearing from A to B (see 'Bearing' section on that site)
You need to find position C from A having bearing (see 'Destination point given distance and bearing from start point' on that site)
The Code
I have working solution as part of my pet project and it can be found here - https://github.com/kakarotto67/mlmc/blob/master/src/Services/MGCC.Api/ChipSimulation/CoordinatesHelper.cs.
(Since original class is subject to change in the future, you might need to refer to this gist - https://gist.github.com/kakarotto67/ef682bb5b3c8bd822c7f3cbce86ff372)
Usage
// 1. Find bearing between A and B
var bearing = CoordinatesHelper.FindInitialBearing(pointA, pointB);
// 2. Find intermediate point C having bearing (above) and any distance in km
var pointC = CoordinatesHelper.GetIntermediateLocation(pointA, bearing, distance);
I hope somebody will find this helpful.
def get_intermediate_point(lat1 , lon1 , lat2 , lon2 , d):
constant = np.pi / 180
R = 6371
φ1 = lat1 * constant
λ1 = lon1 * constant
φ2 = lat2 * constant
λ2 = lon2 * constant
y = np.sin(λ2-λ1) * np.cos(φ2);
x = np.cos(φ1)*np.sin(φ2) - np.sin(φ1)*np.cos(φ2)*np.cos(λ2-λ1)
θ = np.arctan2(y, x)
brng = (θ*180/np.pi + 360) % 360; #in degrees
brng = brng * constant
φ3 = np.arcsin( np.sin(φ1)*np.cos(d/R ) + np.cos(φ1)*np.sin(d/R )*np.cos(brng) )
λ3 = λ1 + np.arctan2(np.sin(brng)*np.sin(d/R )*np.cos(φ1), np.cos(d/R )-np.sin(φ1)*np.sin(φ2));
return φ3/constant , λ3/constant
Audio noob here and math challenged. I'm working with DirectSound which uses a -10000 to 0 range, converting that to a 0-100 scale.
I found this function here to obtain the millibels based on a percentage:
private int ConvertPercentageToMillibels(double value)
{
double attenuation = 1.0 / 1024.0 + value / 100.0 * 1023.0 / 1024.0;
double db = 10 * Math.Log10(attenuation) / Math.Log10(2);
return (int)(db * 100);
}
I need help getting the inverse of this function, basically to get the percentage based on millibels. Here is what I've got so far, which isn't working:
private double ConvertMillibelsToPercentage(int value)
{
double db = value / 100;
double attenuation = Math.Pow(10, db) / 10 * Math.Pow(10, 2);
double percentage = (1.0 * attenuation) - (1024.0 * 100.0 / 1023.0 * 1024.0);
return percentage;
}
Here you go!
private double ConvertMillibelsToPercentage(int value)
{
double exponent = ((value / 1000.0) + 10);
double numerator = 100.0 * (Math.Pow(2, exponent) - 1);
return numerator / 1023.0;
}
Answer will differ slightly due to obvious issues that arise from going between an int and a double.
EDIT: Per the teach how to fish request, here are the first mathematical steps toward arriving at the solution. I didn't show the whole thing because I didn't want to spoil allll the fun. All log functions should be considered Log base 10 unless otherwise noted:
millibels = db*100; // Beginning to work backward
millibels = 10*Log(attenuation)*(1/Log(2))*1000; // Substituting for db
millibels = 1000*Log(attenuation)/Log(2); // Simplifying
let millibels = m. Then:
m = 1000*Log(attenuation)/Log(2);
from here you can go two routes, you can either use properties of logs to find that:
m = 1000* Log_2(attenuation);// That is, log base 2 here
attenuation = 2^(m/1000);
OR you can ignore that particular property and realize:
attenuation = 10^(m*Log(2)/1000);
Try to work it out from one of the above options by plugging in the value that you know for attenuation:
attenuation = (1/1024)+(percentage/100)*(1023/1024);
And then solving for percentage. Good luck!
PS If you ever get stuck on things like this, I highly recommend going to the math stack exchange - there are some smart people there who love to solve math problems.
OR if you are particularly lazy and just want the answer, you can often simply type this stuff into Wolfram Alpha and it will "magically" give you the answer. Check this out
Here is some code I started writing, the Mercator projection is based on this answer.
using System;
using System.Drawing;
namespace CoordinatesTool
{
public class GeoPoint
{
public double Longitude { get; set; }
public double Latitude { get; set; }
public string ToString()
{
return Latitude + "," + Longitude;
}
public PointF ToMercator(int width, int height)
{
var x = (float)((Longitude + 180) * width / 360);
var latRadians = Latitude * Math.PI / 180;
var yTransformed = Math.Log(Math.Tan((latRadians / 2) + (Math.PI / 4)));
var yScaled = (float)((height / 2.0) - (width * yTransformed / (2 * Math.PI)));
return new PointF(x, yScaled);
}
public static GeoPoint FromMercator(PointF point, int width, int height)
{
return FromMercator(point.X, point.Y, width, height);
}
public static GeoPoint FromMercator(double x, double y, int width, int height)
{
// No clue what to do here
}
}
}
My goal is to use this utility class in a WinForms application. I'm using it with this map:
http://en.wikipedia.org/wiki/File:Mercator-projection.jpg (width: 2048, height: 1588).
The Mercator inversion is working quite well (however, I suspect it's not very accurate in the arctic/antarctic reagions).
But the inverse Mercator projection really leaves me puzzled. I played around with the solution proposed in another question, but couldn't get anywhere. Especially I don't understand the Gudermannian (and inverse) function, the DEGREES_PER_RADIAN and RADIANS_PER_DEGREE constants, and how I should convert the y value into a latitude to call the GudermannianInv() function with.
EDIT: Here is how I tried how to do the inverse projection:
Starting with yScaled (parameter y in FromMercator function):
var yTransformed = 2 * Math.PI * (height / 2.0 - yScaled) / width;
var latRadians = Math.Arctan(Math.Pow(Math.E, yTransformed) - Math.PI / 4) / 2;
// ...
Here are some bits of what you seek:
radians * degrees/radians == degrees : degrees_per_radian is just a way of expressing degrees/radians in 'English' rather than in 'maths'. radians_per_degree is left as an exercise for the reader. So these two constants represent the numbers you use when converting between angles in degrees and angles in radians.
Looking at the code you've posted, you have the lines to convert latRadians to y. It looks straightforward to implement code to invert those operations. You need to 'un'-scale and 'un'-transform 'yScaled'. For example, treating the line (part):
yScaled = ((height / 2.0) - (width * yTransformed / (2 * Math.PI)))
as a mathematical equation, you need to solve for yTransformed in terms of yScaled.
As for the Gudermannian, the question you refer to implements that in one line of code and the inverse Gudermannian in 3 lines. The Gudermannian is just a way of transforming a circular measurement (such as a measurement in degrees or radians) into a linear measurement (such as one in centimetres on a chart to be published on paper). In particular, and pertinent here, the Gudermannian will transform a latitude into a linear distance from 0.
EDIT
OK, so looking a bit closer, in your original code you transform the latitude from an angular measurement into a linear one with the line:
yTransformed = Math.Log(Math.Tan((latRadians / 2) + (Math.PI / 4)))
I think that you should probably replace this with a call to the inverse Gudermannian, as indicated in the answer to the question you link to. I suspect that your home-brewed transformation is stumbling over extreme points in the tan/arctan functions. You would then use the direct Gudermannian in the un-transformation of course.
There is another post here about Atan but I dont see any relevant answers:
C# - Why Math.Atan(Math.Tan(x)) != x?
Isn't Math.Atan the same as tan-1? On my calculator I do:
tan-1(1) and i get 45.
tan(45) = 1
In C#:
Math.Atan(1) = 0.78539816339744828 //
nowhere near the 45.
Math.Tan(45) = 1.6197751905438615 //1
dp over the < Piover2.
Whats happening here?
C# is treating the angles as radians; your calculator is using degrees.
Atan(1) is equal to π/4. This is the correct value when working in radians. The same can be said of the other calculations in the library.
Feel free to convert the values:
double DegreeToRadian(double angle) { return Math.PI * angle / 180.0; }
double RadianToDegree(double angle) { return angle * (180.0 / Math.PI); }
This means that 45 radians is equal to about 2578.31008 degrees, so the tangent you are looking for should be better expressed as tan(π/4) or if you don't mind "cheating": Math.Tan(Math.Atan(1)); // ~= 1. I'm fairly confident that had you tried that yourself, you'd have realized something reasonable was happening, and might have stumbled upon how radians relate to degrees.
Your calculator is in Degrees, C# is doing these calculations in Radians.
To get the correct values:
int angle = 45; //in degrees
int result = Math.Tan(45 * Math.PI/180);
int aTanResult = Math.Atan(result) *180/Math.PI;
Math.Atan returns a value in radians. Your calculator is using degrees. 0.7853... (pi/4) radians is 45 degrees. (And conversely Math.Tan(45) is telling you the tan of 45 radians.)