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);
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));
I wrote this extension method for an IPoint.
public static IPoint Offset(this IPoint point, double angle, double distanceInMeters)
{
var radians = Math.PI * angle / 180;
var distanceX = distanceInMeters * Math.Cos(radians);
var distanceY = distanceInMeters * Math.Sin(radians);
var earthRadius = 6371000;
var y = point.Y + ((distanceY / earthRadius) * 180 / Math.PI);
var x = point.X + ((distanceX / (earthRadius * Math.Cos(y * 180 / Math.PI))) * 180 / Math.PI);
return new Point(x, y);
}
It works fine when I am putting in an angle of 0, 90, 180 and 270, then it return a coordinate at the given distance away from the starting point. But when I am starting to go in an angle that do not point exactly North, East etc. Iam getting wrong distances.
Where do I go wrong ?
Alternative is there some libraries to use?
Try this formula. As I consider you should transfer latitude and longitude to radians and then back to degrees.
public static Point Offset(this Point point, double angle, double distanceInMeters)
{
double rad = Math.PI * angle / 180;
double xRad = Math.PI * point.X / 180; // convert to radians
double yRad = Math.PI * point.Y / 180;
double R = 6378100; //Radius of the Earth in meters
double x = Math.Asin(Math.Sin(xRad) * Math.Cos(distanceInMeters/ R)
+ Math.Cos(xRad) * Math.Sin(distanceInMeters/ R) * Math.Cos(rad));
double y = yRad + Math.Atan2(Math.Sin(rad) * Math.Sin(distanceInMeters/ R) * Math.Cos(xRad), Math.Cos(distanceInMeters/ R) - Math.Sin(xRad) * Math.Sin(x));
x = x * 180 / Math.PI; // convert back to degrees
y = y * 180 / Math.PI;
return new Point(x, y);
}
Im using Microsoft visual studio 2010, with the refernce dynamic data display.
I would like to draw a circle on a map, i have 2 points, one of them is the center of the circle and the other is the point on the circle, the distance between them is the radius of the circle.
the result should look like this :
http://sizmedia.com/my.php?i=mjmynzim2nhy.png
my result when I draw a circle with one point and const distance is like this (distance = radius = 15):
http://sizmedia.com/my.php?i=hm2zuv5yyenj.png
***** I don't care if the circle will look like my result(the ellipse)
because as I understood the earth is circle and its type of reasonable. ****
but when I draw circle with distance between 2 point (distance = 3400 +) I can't see the circle that I draw.
I would love to get some help, there is my code to find distance between 2 points.
// Calculating the distance between the two points
double dLat = (ps.X - centerPoint.X) / 180 * Math.PI;
double dLong = (
double.Parse(this.plotter.Viewport.Transform.DataTransform.ViewportToData(ps).Y.ToString()) -
double.Parse(this.plotter.Viewport.Transform.DataTransform.ViewportToData(centerPoint).Y.ToString())) / 180 * Math.PI;
double a = Math.Sin(dLat / 2) * Math.Sin(dLat / 2)
+ Math.Cos(ps.X / 180 * Math.PI) * Math.Cos(pointLine1.X / 180 * Math.PI)
* Math.Sin(dLong / 2) * Math.Sin(dLong / 2);
double c = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a));
//Calculate radius of earth
double radiusE = 6378135; // Equatorial radius, in metres
double radiusP = 6356750; // Polar Radius
//Numerator part of function
double nr = Math.Pow(radiusE * radiusP * Math.Cos(ps.X / 180 * Math.PI), 2);
//Denominator part of the function
double dr = Math.Pow(radiusE * Math.Cos(ps.X / 180 * Math.PI), 2)
+ Math.Pow(radiusP * Math.Sin(ps.X / 180 * Math.PI), 2);
double radius = Math.Sqrt(nr / dr);
//Calculate distance in meters.
distance = (radius * c); // resualt in meters
distance /= 1000; // resualt in KM
And there is my code to add the circle :
while (a < 360) // Doing one round around the point (The angels)
{
// Get the X position of the pointClicked
cx = (double)prePs.X;
// Get the Y position of the pointClicked
cy = double.Parse(this.plotter.Viewport.Transform.DataTransform.ViewportToData(prePs).Y.ToString());
// Get the new X position of the pointClicked by the angel with math calculation
xEndP = (float)(distance * Math.Cos(a * Math.PI / 180F)) + cx;
// Get the new Y position of the pointClicked by the angel with math calculation
yEndP = (float)(distance * Math.Sin(a * Math.PI / 180F)) + cy;
// Creating the new point
globalPoint = new DraggablePoint(new Point(xEndP, yEndP));
globalPoint.Position = new Point(xEndP, yEndP);
globalPoint.Visibility = Visibility.Visible;
// Increas the angel
a++;
//Creat new point on the circle with new angel
xEndPNext = (float)(distance * Math.Cos(a * Math.PI / 180F)) + cx;
yEndPNext = (float)(distance * Math.Sin(a * Math.PI / 180F)) + cy;
// Creat line between the two new points that we creat now
segmentHelper = new Segment(new Point(xEndP, yEndP), new Point(xEndPNext, yEndPNext));
// Brush between the points by line
SolidColorBrush mySolidColorBrush = new SolidColorBrush();
mySolidColorBrush.Color = Color.FromArgb(255, 47, 79, 49);
segmentHelper.Stroke = mySolidColorBrush;
// Add the line to the chartplotter
plotter.Children.Add(segmentHelper);
// Add the angel
a++;
}
My algorithm is take one point, and the next point and to draw line between them ( when the points are visiblty false) and then i get a nice circle.
Thank you very much :)
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
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