Vector.AngleBetween in WinRT - c#

Currently i am converting a Desktop application to Windows 8 application. To get a angle between 2 points in desktop application they use Vector.AngleBetween(vector1, vector2). Using "Point" i got the vector values in WinRT. Like this,
var vectorX = point1.X - point2.X;
var vectorY = point1.Y - point2.Y;
Point vector = new Point(vectorX , vectorY);
But i don't find any way to get a angle between 2 points in WinRT. I got this function from online,
public double GetAngleOfLineBetweenTwoPoints(Point p1, Point p2)
{
var xDiff = p2.X - p1.X;
var yDiff = p2.Y - p1.Y;
return Math.Atan2(yDiff , xDiff) * (180 / Math.PI);
}
but it wont give the exact result like "Vector.AngleBetween". Is there any better way available to get a result like "Vector.AngleBetween" in WinRT...?

I don't think your math is right. You can calculate angle between vectors using dot product and arcus cosinus, pseudo-code below:
double vectorALength = sqrt(vectorA.x * vectorA.x + vectorA.y * vectorA.y);
double vectorBLength = sqrt(vectorB.x * vectorB.x + vectorB.y * vectorB.y);
double dotProduct = vectorA.x * vectorB.x + vectorA.y + vectorB.y
double cosAngle = dotProduct / (vectorALength * vectorBLength);
double angle = Math.Acos(cosAngle) * (180 / Math.PI);
If I'm correct this should give you roughly right answer. Details and better explenations can be found on internet, e.g. Dot product

Related

How to calculate coordinate X meters away from a point but towards another in C#

Let's say I have 2 coordinates that are ~222.33 meters away from each other :
A: 49.25818, -123.20626
B: 49.25813, -123.2032
Those 2 points makes a segment.
How can I calculate the coordinate of point Z that is X meters away from either A or B but towards the other point?
I already know the distance between my 2 points using System.Device.Location library.
GeoCoordinate A = new GeoCoordinate(49.25818, -123.20626);
GeoCoordinate B = new GeoCoordinate(49.25813, -123.2032);
var distanceInMeters = A.GetDistanceTo(B);
// distanceInMeters = 222.33039783713738
I'm looking for something like this:
GeoCoordinate GetPointTowards(GeoCoordinate fromPoint, GeoCoordinate towardPoint, double distanceInMeter) {
[???]
}
I think I may need the bearing or something to be able to get the new point location.
Most examples I've found are for iOS, Android or GMaps with specific libraries..
Here's an outline of how I would do it. With this approach, there is no need to explicitly deal with the difference in units between coordinates and distances because taking the ratio of target to total distance eliminates the unit.
totalDistance = distance in meters between point A and point B.
targetDistance = distance in meters to travel from point A to point B
ratio = targetDistance / totalDistance
diffX = B.X - A.X
diffY = B.Y - A.Y
targetX = A.X + (ratio * diffX)
targetY = A.Y + (ratio * diffY)
But this wouldn't handle the edge cases like being at 179 degrees longitude and adding 3 degrees which would put you at -178 longitude.
This is my code converted to C# from http://www.movable-type.co.uk/scripts/latlong.html. The fraction is from 0 to 1 and is the fraction along the distance from the first point to the second point the output position will be. You could always modify it to take a straight distance value.
public static (double Lat, double Lon) IntermediatePoint((double Lat, double Lon) StartPoint, (double Lat, double Lon) EndPoint, double fraction)
{
if (fraction < 0 || fraction > 1)
throw new ArgumentOutOfRangeException();
double angDist = Distance(StartPoint, EndPoint) / radius;
double lat1 = StartPoint.Lat * (Math.PI / 180);
double lon1 = StartPoint.Lon * (Math.PI / 180);
double lat2 = EndPoint.Lat * (Math.PI / 180);
double lon2 = EndPoint.Lon * (Math.PI / 180);
double a = Math.Sin((1 - fraction) * angDist) / Math.Sin(angDist);
double b = Math.Sin(fraction * angDist) / Math.Sin(angDist);
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(lat2);
double lat3 = Math.Atan2(z, Math.Sqrt(Math.Pow(x, 2) + Math.Pow(y, 2)));
double lon3 = Math.Atan2(y, x);
return (lat3 * (180 / Math.PI), lon3 * (180 / Math.PI));
}
public static double Distance((double Lat, double Lon) point1, (double Lat, double Lon) point2)
{
double φ1 = point1.Lat * (Math.PI / 180.0);
double φ2 = point2.Lat * (Math.PI / 180.0);
double Δφ = (point2.Lat - point1.Lat) * (Math.PI / 180.0);
double Δλ = (point2.Lon - point1.Lon) * (Math.PI / 180.0);
double a = Math.Sin(Δφ / 2) * Math.Sin(Δφ / 2) + Math.Cos(φ1) * Math.Cos(φ2) * Math.Sin(Δλ / 2) * Math.Sin(Δλ / 2);
double c = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a));
return radius * c;
}
radius is a constant representing the Earth's radius in meters.

calculate Point by point, angle and distance on a map

I have a mission to calculate point on a Map. I have the start point, the angle and the distance from the point. How can I do it ? I search a lot I found something but it doesn't work good - I mean it it doesn't calculate the correct point. Thank's all.
My try :
public Point MesPoint(double x1, double x2, double y1, double y2, double distance, double x) // X is the angle
{
double xEndP, yEndP;
var angularDistance = distance / c_EarthRadiusInKilometers; // angular distance in radians
var lat = ToRadian(y2);
var lon = ToRadian(x2);
var angel = ToRadian(x);
double latRadians = Math.Asin((Math.Sin(lat) * Math.Cos(angularDistance)) + (Math.Cos(lat) * Math.Sin(angularDistance) * Math.Cos(angel)));
double lngRadians = Math.Atan2(
Math.Sin(angel) * Math.Sin(angularDistance) * Math.Cos(lat),
Math.Cos(angularDistance) - (Math.Sin(lat) * Math.Sin(latRadians)));
double lon1 = (lon + lngRadians + Math.PI) % (2 * Math.PI) - Math.PI; // normalise to -180..+180º
yEndP = ToDegrees(latRadians);
xEndP = ToDegrees(lon1);
return (new Point(xEndP, yEndP));
}

Calculate point on a Bézier curve according to t

I'm trying to create a bar that looks like this:
(source: hostingpics.net)
It's a bar containing buttons separated by a glowy separator. Those button have a non rectangular shape so I thought "I'll just put a transparent button and to draw the non-rectangular shape i'll use a path".
The problem I encounter is that I need to color the buttons depending on their state (enabled, disabled), so I need a path per button to change its color easily.
So I made a function to calculate a Bézier curve from the 4 points and a T value which represents the point on the curve between 0 and 1 (0 is the start point of the curve, 1 is the end point and 0.5 is the point at the middle of the curve).
public static Point CalculateBezierPoint(double t, Point p1, Point p2, Point p3, Point p4) {
Point p = new Point();
double tPower3 = t * t * t;
double tPower2 = t * t;
double oneMinusT = 1 - t;
double oneMinusTPower3 = oneMinusT * oneMinusT*oneMinusT;
double oneMinusTPower2 = oneMinusT * oneMinusT;
p.X = oneMinusTPower3 * p1.X + (3 * oneMinusTPower2 * t * p2.X) + (3 * oneMinusT * tPower2 * p3.X) + tPower3 * p4.X;
p.Y = oneMinusTPower3 * p1.Y + (3 * oneMinusTPower2 * t * p2.Y) + (3 * oneMinusT * tPower2 * p3.Y) + tPower3 * p4.Y;
return p;
}
This function is working well.
So I can draw the curve:
(source: hostingpics.net)
So this is pretty accurate. Except that button widths aren't equal (they should be delimited by the separators). So what I'd need is a function that can find the Y axis value of the point on the curve knowing its X axis value.
So knowing that the equation to find a point on a Bézier curve is:
(x coordinate)
Bx(t) = (1-t)^3 * P1.x + 3 * (1-t)^2 * t * P2.X + 3*(1-t)*t^2 * P3.X + t^3 * P4.X
(y coordinate)
By(t) = (1-t)^3 * P1.Y + 3 * (1-t)^2 * t * P2.Y + 3*(1-t)*t^2 * P3.Y + t^3 * P4.Y
Where:
Bx is the X axis value of the point on the curve, By is its Y axis value;
P1 is the start point of the curve
P2 is the first control point of the curve
P3 is the second control point of the curve
P4 is the end point of the curve
t is the position between 0 and 1 of the point we want to find on the curve
I thought that I could just resolve the Bx(t) equation according to t because I know at runtime the Bx, P1, P2, P3 and P4, only t is unknown. So I would like an equation which looks like:
t = ...
This was a good idea until I remembered that I'm terrible at math. I tried a lot of thing which didn't work and then tried to enter the equation in Wolframalpha, which gave me a ~50 long lines equation that doesn't work (here it is if you want to see) (I may have made mistakes recopying it in the function).
Anyway, here I am looking for help. Thank you for your help
Well, if your curve is really a function y=f(x), why not represent it that way, with X simply a linear parameter?
/// <summary>
/// Calculate a bezier height Y of a parameter in the range [start..end]
/// </summary>
public static double CalculateBezierHeightInInterval(double start, double end, double param, double y1, double y2, double y3, double y4)
{
return CalculateBezierHeight((param - start) / (end - start), y1, y2, y3, y4);
}
/// <summary>
/// Calculate a bezier height Y of a parameter in the range [0..1]
/// </summary>
public static double CalculateBezierHeight(double t, double y1, double y2, double y3, double y4)
{
double tPower3 = t * t * t;
double tPower2 = t * t;
double oneMinusT = 1 - t;
double oneMinusTPower3 = oneMinusT * oneMinusT * oneMinusT;
double oneMinusTPower2 = oneMinusT * oneMinusT;
double Y = oneMinusTPower3 * y1 + (3 * oneMinusTPower2 * t * y2) + (3 * oneMinusT * tPower2 * y3) + tPower3 * y4;
return Y;
}
In this formulation you no longer need to solve for X since X is an input for Y. On the other hand, your sample heights are assumed to occur at uniform X intervals, which might be undesirable for you.
If you need the extra shape control you can get from controlling the X locations of the control points, you can use the method here: y coordinate for a given x cubic bezier

Drawing a square around a lat-long point

I'm trying to draw a square around a given point on the earth's surface.
I'm using information I retrieved from here and here and ultimately came up with this:-
// Converting degrees to radians
double latInDecimals = (Math.PI / 180) * latitude;
double longInDecimals = (Math.PI / 180) * longitude;
List<string> lstStrCoords = new List<string>();
double changeInLat;
double changeInLong;
double lineOfLat;
// Calculating change in latitude for square of side
changeInLong = (side / 1000) * (360.0 / 40075);
// Calculating length of longitude at that point of latitude
lineOfLat = Math.Cos(longitude) * 40075;
// Calculating change in longitude for square of side 'side'
changeInLat = (side / 1000) * (360.0 / lineOfLat);
// Converting changes into radians
changeInLat = changeInLat * (Math.PI / 180);
changeInLong = changeInLong * (Math.PI / 180);
double nLat = changeInLat * (Math.Sqrt(2) / 2);
double nLong = changeInLong * (Math.Sqrt(2) / 2);
double coordLat1 = latInDecimals + nLat;
double coordLong1 = longInDecimals + nLong;
double coordLat2 = latInDecimals + nLat;
double coordLong2 = longInDecimals - nLong;
double coordLat3 = latInDecimals - nLat;
double coordLong3 = longInDecimals - nLong;
double coordLat4 = latInDecimals - nLat;
double coordLong4 = longInDecimals + nLong;
// Converting coords back to degrees
coordLat1 = coordLat1 * (180 / Math.PI);
coordLat2 = coordLat2 * (180 / Math.PI);
coordLat3 = coordLat3 * (180 / Math.PI);
coordLat4 = coordLat4 * (180 / Math.PI);
coordLong1 = coordLong1 * (180 / Math.PI);
coordLong2 = coordLong2 * (180 / Math.PI);
coordLong3 = coordLong3 * (180 / Math.PI);
coordLong4 = coordLong4 * (180 / Math.PI);
Now even though this works, the polygon that I get from joining these is a rectangle.
I'm confused as to what's wrong with my code.
A rectangle of one degree of latitude and longitude on the sphere has not the same length in km unless it is situated on the equator. It gets narrower towards the poles. If you want to make both sides the same size you have to make a correction
longitudinal_length = latitudinal_length / cos(latitude)
So you will need to divide your longitudinal length of your square by cos(latitude).
Now, your square might still be crooked, but this depends on how the map is projected and this is a completely different story. You would need to know the projection formulas used by Google to make a correction.
You may find more complicated formulas that take account of the fact that the earth is not a perfect sphere, but I think that this should be sufficient for your position marker. Note also that you will get a division by zero at +/-90 degree. So placing a rectangle on a pole requires another approach.
From: IBM Knowledge Center / Geographic coordinate system / Figure 4. Different dimensions between locations on the graticule

Trig triangles angle

i have a start point and a end point. I want to work out the angle i have this formula that seems to work
double dx = end.X - start.X;
double dy = end.Y - start.Y;
double degrees = Math.Acos((-Math.Pow(dy, 2) + Math.Pow(dx, 2) + Math.Pow(dx, 2)) / (2 * Math.Pow(dx, 2)));
degrees = degrees * 180 / Math.PI;
Then i want to take the angle and extend the line's length. i have this so far
end.Y = (start.Y + (len * Math.Sin(angle)));
end.X = (start.X + (len * Math.Cos(angle)));
now this does not give me the right value.
white is original line and red is the extending
what am i doing wro
This is what I meant in code:
double dx = end.X - start.X;
double dy = end.Y - start.Y;
double dlen = Math.Sqrt(dx * dx + dy * dy);
dx = dx / dlen;
dy = dy / dlen;
end.X = start.X + (dx * len);
end.Y = start.Y + (dy * len);
If you just want to continue your line, first you'll have to find the function which defines your line.
this is a "simple" line ... it's function is f(x)=ax+b. Find a and b.
To find a :
a = (start.y - end.y) / (start.x - end.x)
// easy, isn't it ?
To find b :
b = (start.y) - (a * start.x)
// you can check switching "start" by "end"
No deal with angles, cosinus or sinus ...
Bye
if you don't have the hypotenuse (which you don't need) you should use a tangent trig function
Like
double rads = Math.Atan(dy/dx);
Your degree calc is quite convoluted although my way involves keeping track of quadrants. See: http://www.mathwizz.com/algebra/help/help29.htm

Categories