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
Related
I have tried to adapt some code I came across to draw an equilateral triangle in c#
public void drawTriangle(PaintEventArgs e, int x, int y, int distance)
{
float angle = 0;
SolidBrush brs = new SolidBrush(Color.Green);
PointF[] p = new PointF[3];
p[0].X = x;
p[0].Y = y;
p[1].Y = (float)( x + distance * Math.Cos(angle + Math.PI / 3));
p[1].X = (float)( y + distance * Math.Sin(angle + Math.PI / 3));
p[2].Y = (float)( x + distance * Math.Cos(angle - Math.PI / 3));
p[2].X = (float)( y + distance * Math.Sin(angle - Math.PI / 3));
e.Graphics.FillPolygon(brs, p);
}
Unfortunately, this doesn't even come close. I have drawn equilateral triangles, but the points were always based on the centers of congruent circles. I am trying to find a simpler way. I am sure there must be an obvious problem with this code, but I am trying to learn the math needed as I go, so I don't know what it is. Thanks for your time.
Try this approach. I assume that for zero angle p[0] is left bottom vertex, p[1] is right bottom (the same horizontal).
(BTW, you have got strange mangling of Y/X)
p[0].X = x;
p[0].Y = y;
p[1].X = (float)( x + distance * Math.Cos(angle));
p[1].Y = (float)( y + distance * Math.Sin(angle));
p[2].X = (float)( x + distance * Math.Cos(angle + Math.PI / 3));
p[2].Y = (float)( y + distance * Math.Sin(angle + Math.PI / 3));
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
I am using the following function.
private static Location CoordinateAtADistance(double latOrigin, double lonOrigin, double radius, double angle)
{
double lonDestination;
double R = 6371.0;
double d = radius / R; // d = angular distance covered on earth's surface
double lat1 = ToRadian(latOrigin);
double lon1 = ToRadian(lonOrigin);
double brng = ToRadian(angle);
double latDestination = lat1 + d * Math.Cos(brng);
double dLat = d * Math.Cos(brng);
double dPhi = Math.Log(Math.Tan(latDestination / 2 + Math.PI / 4) / Math.Tan(lat1 / 2 + Math.PI / 4));
double q = (double.IsNaN(dLat / dPhi)) ? dLat / dPhi : Math.Cos(lat1); // E-W line gives dPhi=0
double dLon = d * Math.Sin(brng) / q;
// check for some daft bugger going past the pole
if (Math.Abs(latDestination) > Math.PI / 2)
latDestination = latDestination > 0 ? Math.PI - latDestination : -(Math.PI - latDestination);
lonDestination = (lon1 + dLon +3* Math.PI) % (2 * Math.PI) - Math.PI;
Location nextPoint = new Location();
if (angle == 0)
{
nextPoint.Latitude = ToDegree(latDestination);
nextPoint.Longitude = lonOrigin;
}
if (angle == 90)
{
nextPoint.Latitude = latOrigin;
nextPoint.Longitude = ToDegree(lonDestination);
}
return nextPoint;
}
Here radius is the distance.
Now the problem is when I calculate short distances e.g. a few hundreds kilometers it works perfectly. But for large distances say 11,000 kilometers it gives in correct longitude.
Please not I only move either along latitude or longitude so one of them will not change in any case. While moving for latitude I get correct answer but for longitude values are not even closer.
Please post comments if any thing is unclear.
double latDestination = lat1 + d * Math.Cos(brng);
double dLat = d * Math.Cos(brng);
double dPhi = Math.Log(Math.Tan(latDestination / 2 + Math.PI / 4) / Math.Tan(lat1 / 2 + Math.PI / 4));
double q = (double.IsNaN(dLat / dPhi)) ? dLat / dPhi : Math.Cos(lat1); // E-W line gives dPhi=0
double dLon = d * Math.Sin(brng) / q;
// check for some daft bugger going past the pole
if (Math.Abs(latDestination) > Math.PI / 2)
latDestination = latDestination > 0 ? Math.PI - latDestination : -(Math.PI - latDestination);
lonDestination = (lon1 + dLon + 3 * Math.PI) % (2 * Math.PI) - Math.PI;
A little correction was needed and the above formula works fine.
I have 2 lines that i draw like this:
float Alpha = RotDegrees;
PointF PitCenter = new Point(picBoxZoomMap.Width / 2, picBoxZoomMap.Height / 2);
PointF p = new PointF(PitCenter.X - 20, PitCenter.Y - 250);
PointF p2 = new PointF(PitCenter.X + 20, PitCenter.Y - 250);
zoomgfx.DrawLine(Pens.Red, PitCenter, new PointF(
(float)((p.Y - PitCenter.Y) * Math.Sin(Alpha * Math.PI / 180) + p.X),
(float)(PitCenter.Y + (p.Y - PitCenter.Y) * Math.Cos(Alpha * Math.PI / 180))));
zoomgfx.DrawLine(Pens.Red, PitCenter, new PointF(
(float)((p2.Y - PitCenter.Y) * Math.Sin(Alpha * Math.PI / 180) + p2.X),
(float)(PitCenter.Y + (p2.Y - PitCenter.Y) * Math.Cos(Alpha * Math.PI / 180))));
Here are the lines when Alpha = 0;
And here are the lines after 90 degrees rotation..
As you see the lines somehow meets.. i really cant understand why..
Any ideas?
Your formula for the rotation is incorrect, have a look here --> Rotate a point by another point in 2D
Change your code to this, and you will get the right effect:
PointF PitCenter = new Point(picBoxZoomMap.Width / 2, picBoxZoomMap.Height / 2);
PointF p = new PointF(PitCenter.X - 20, PitCenter.Y - 250);
PointF p2 = new PointF(PitCenter.X + 20, PitCenter.Y - 250);
var AlphaRad = RotDegrees * Math.PI / 180;
zoomgfx.DrawLine(Pens.Red, PitCenter, new PointF(
(float)(Math.Cos(AlphaRad) * (p.X - PitCenter.X) - Math.Sin(AlphaRad) * (p.Y - PitCenter.Y) + PitCenter.X),
(float)(Math.Sin(AlphaRad) * (p.X - PitCenter.X) + Math.Cos(AlphaRad) * (p.Y - PitCenter.Y) + PitCenter.Y)));
zoomgfx.DrawLine(Pens.Red, PitCenter, new PointF(
(float)(Math.Cos(AlphaRad) * (p2.X - PitCenter.X) - Math.Sin(AlphaRad) * (p2.Y - PitCenter.Y) + PitCenter.X),
(float)(Math.Sin(AlphaRad) * (p2.X - PitCenter.X) + Math.Cos(AlphaRad) * (p2.Y - PitCenter.Y) + PitCenter.Y)));
You take the difference between the Y-coordinates and multiply with Sin to get the X-coordinates. This is correct.
However, you also take the difference between the Y-coordinates when you construct the new Y-coordinates. For this, you should take the difference between the X-coordinates and multiply by Cos.
E.g. your line 8 and line 12 produces the same Y-coordinates for the new point because p.Y - PitCenter.Y is the same as p2.Y - PitCenter.Y since p.Y = p2.Y.
Makes sense?
I find it easier to understand things if I break it down a bit more. It looks to me like you're trying to do too many things all at once. I think this will do what you're looking for (I'm not sure if the radius definition is exactly what you want) but it's hopefully clear enough that you understand what I'm suggesting.
float RotDegrees = 90.0; // Centerline angle for wedge
float width = 10.0; // Assume a 10 degree wedge
// Center of view
PointF PitCenter = new PointF(picBoxZoomMap.Width / 2,
picBoxZoomMap.Height / 2);
// Determine the angle for the wedges in radians
float theta0 = (RotDegrees - width / 2.0) * Math.PI / 180.0;
float theta1 = (RotDegrees + width / 2.0) * Math.PI / 180.0;
// May need to adjust this to satisfy your needs
float radius = 100.0;
// Determine the endpoints of the new wedge ... Assumes (0,0) is in the upper
// left corner rather than the lower left (where it belongs ;). If it's in the
// lower left after all, change the subtraction in the Y components to an
// addition
PointF p0 = new PointF( PitCenter.X + radius * Math.Cos(theta0),
PitCenter.Y - radius * Math.Sin(theta0) );
PointF p1 = new PointF( PitCenter.X + radius * Math.Cos(theta1),
PitCenter.Y - radius * Math.Sin(theta1));
// Draw the lines
zoomgfx.DrawLine(Pens.Red, PitCenter, p0);
zoomgfx.DrawLine(Pens.Red, PitCenter, p1);
I want to know how to get an angle of a line A-B from horizontal axis X. Other questions in SO do that only between two lines. I'm aware I can always draw second line A-C and calculate but I'm wondering if there's a faster method.
EDIT: I'm very sure I'm not doing a premature optimization.
You can use atan for that.
angle = atan((By-Ay)/(Bx-Ax))
private double Angulo(int x1, int y1, int x2, int y2)
{
double degrees;
// Avoid divide by zero run values.
if (x2 - x1 == 0)
{
if (y2 > y1)
degrees = 90;
else
degrees = 270;
}
else
{
// Calculate angle from offset.
double riseoverrun = (double)(y2 - y1) / (double)(x2 - x1);
double radians = Math.Atan(riseoverrun);
degrees = radians * ((double)180 / Math.PI);
// Handle quadrant specific transformations.
if ((x2 - x1) < 0 || (y2 - y1) < 0)
degrees += 180;
if ((x2 - x1) > 0 && (y2 - y1) < 0)
degrees -= 180;
if (degrees < 0)
degrees += 360;
}
return degrees;
}
If you need all four quadrants, Atan2 is more suitable than Atan.
public static int GetAngleBetweenPoints(PointF pt1, PointF pt2)
{
float dx = pt2.X - pt1.X;
float dy = pt2.Y - pt1.Y;
int deg = Convert.ToInt32(Math.Atan2(dy, dx) * (180 / Math.PI));
if (deg < 0) { deg += 360; }
return deg;
}
If
The angle is small,
you can live with small inaccuracies, and
You can use the angle in radians and not degrees,
then there is a fast solution: Under these conditions, you can assume that tan(a) = a = atan(a), and hence just omit the atan() call.
You could also use arccosine, if your line is in the form [r_x,r_y], where r_x is the change in x and r_y is the change in y.
angle = arccos( r_x/( r_x*r_x + r_y*r_y ) )
It's slightly more opaque, but it's basically the dot product law:
angle = arccos (r . v)
Where r and v are both unit vectors (vectors of length 1). In our case, v is the vector [1,0], and r is
[r_x,r_y] / (r_x^2+r_y^2)
in order to make it a unit vector.
The x-axis is actually a line with equation
y = 0
so you could use the solution you have already.