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 :)
Related
I'm trying to place some icons equally on the upper half of a circle.
I managed to place them around a whole circle with the following formula/code
for(int i=0;i<numberOfItems;i++)
{
float x = (float)(center.X + radius * Math.Cos(2 * Math.PI * i / numberOfItems))-iconBmp.Width/2;
float y = (float)(center.Y + radius * Math.Sin(2 * Math.PI * i/ numberOfItems))-iconBmp.Height/2;
canvas.DrawBitmap(iconBmp, new SKPoint(x, y));
}
But I can't figure how to do it for just the upper half of the circle?
Is there a formula for that as well?
I have the feeling that the one I have for the whole circle just needs some adjustment to achieve that...but can't figure what.
Thank you already!
This is more a math question than a programming question.
2pi radians = 360 degrees
So if you want all of the items shown, but the shape to be a half circle, then use:
Math.PI * i / numberOfItems instead of 2 * Math.PI * i / numberOfItems
Also because screen coordinates start in the top-left corner. That will make it the bottom half of the circle with the first item on the right. If you want the top half of the circle with the first item on the left, then just add pi:
Math.PI + (Math.PI * i / numberOfItems)
Whole code:
for(int i=0;i<numberOfItems;i++)
{
float x = (float)(center.X + radius * Math.Cos(Math.PI + (Math.PI * i / numberOfItems)))-iconBmp.Width/2;
float y = (float)(center.Y + radius * Math.Sin(Math.PI + (Math.PI * i / numberOfItems)))-iconBmp.Height/2;
canvas.DrawBitmap(iconBmp, new SKPoint(x, y));
}
I've been trying to get this code to work properly for the past hour and I almost got it complete. Everything works, but the float verticalDegrees.
In Detail Question: How do I get this code working so it returns XYZ from horizontal degrees, vertical degrees, radius and origin?
This link helped me, but it's missing Z coordinate
This is what I have so far:
private float[] DegreesToXYZ(float horizonalDegrees, float verticalDegrees, float radius, float[] origin)
{
float[] xyz = new float[3];
double radiansH = horizonalDegrees * Math.PI / 180.0;
double radiansV = verticalDegrees * Math.PI / 180.0;
xyz[1] = (float)Math.Cos(radiansH) * radius + origin[1];
xyz[0] = (float)Math.Sin(-radiansH) * radius + origin[0];
double deltaXY = Math.Sqrt(origin[0] * origin[0] + origin[1] * origin[1]);
xyz[2] = (float)Math.Atan2(origin[2], deltaXY);
return xyz;
}
This method converts spherical coordinates into cartesian coordinates:
private static double[] DegreesToXYZ(double radius, double theta, double phi, double[] originXYZ)
{
theta *= Math.PI / 180;//converting degress into radians
phi *= Math.PI / 180;//converting degress into radians
double[] xyz = new double[3];
xyz[0] = originXYZ[0] + radius * Math.Cos(theta) * Math.Sin(phi);//x
xyz[1] = originXYZ[1] + radius * Math.Sin(theta) * Math.Sin(phi);//y
xyz[2] = originXYZ[2] + radius * Math.Cos(phi);//z
return xyz;
}
Where theta is the 'horizontal' or 'azimuth' angle (angle from the x-axis in the x-y plane), and phi is the 'inclination' (angle from the positive
z axis) or 'vertical' angle.The radius is the distance to a given point (x,y,z) in cartesian coordinates.
Seems you have spherical coordinates and want to get Cartesian coordinates. In this case
x = x0 + r * Cos(fi) * Sin(theta)
y = y0 + r * Sin(fi) * Sin(theta)
z = z0 + r * Cos(theta)
Here fi is your "horizontal angle", theta is "vertical angle", x0..z0 are origin coordinates
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);
}
I have a line (DrawLine-Event) with the points (a,b) (c,d) and now I want to calculate the angle of it but I don't know how.
I tried it like this:
double atan = ((d - b) / c - a)) * Math.PI / 180;
double solution = Math.Atan(atan);
int angle = Convert.ToInt32(Math.Round(solution * 180 / Math.PI));
You can use Vector.AngleBetween Method to get the angle
private Double angleBetweenExample()
{
Vector vector1 = new Vector(20, 30);
Vector vector2 = new Vector(45, 70);
Double angleBetween;
// angleBetween is approximately equal to 0.9548
angleBetween = Vector.AngleBetween(vector1, vector2);
return angleBetween;
}
I know that the theory of rotating a point by an angle is on the internet a million times, but I don't get my code to work properly.
I have a line with 2 points, when you click on 1 of the 2 points, you will rotate the point relative to the other point. In my testcase I have a upper left point and a bottom right point, so a diagonal line.
I want to make sure the line snaps to a 90 degrees rotation so It will always be a straight line (either vertically or horizontally). So I first get the current angle, then get the angle that It should be, and calculate the difference.
Point startPoint = obj2.Location;
Point currentEndPoint = new Point(obj2.Location.X + obj2.Size.Width, obj2.Location.Y + obj2.Size.Height);
Point newEndPoint = e.Location;
double angle = MathHelper.GetAngleOfVerticalLine(startPoint, newEndPoint);
double angleToBe = MathHelper.GetClosestNumber(angle, new double[] { 0, 90, 180, 270, 360 });
double angleToDo = 0.0; // -5
if (angle < angleToBe)
{
angleToDo = Math.Abs(angle - angleToBe);
}
else
{
angleToDo = angleToBe - angle;
}
angleToDo %= 360;
Point newSize = MathHelper.RotatePoint(newEndPoint, startPoint, angleToDo);
obj.Size = (Size)newSize;
public static Point RotatePoint(Point pointToRotate, Point centerPoint, double angleInDegrees)
{
double angleInRadians = angleInDegrees * (Math.PI / 180);
double cosTheta = Math.Cos(angleInRadians);
double sinTheta = Math.Sin(angleInRadians);
return new Point
{
X =
(int)
(cosTheta * (pointToRotate.X - centerPoint.X) -
sinTheta * (pointToRotate.Y - centerPoint.Y) + centerPoint.X),
Y =
(int)
(sinTheta * (pointToRotate.X - centerPoint.X) +
cosTheta * (pointToRotate.Y - centerPoint.Y) + centerPoint.Y)
};
}
But the results that I get, are not straight lines but they are kind of random. The angle, angleToBe and angleToDo work properly. The RotatePoint method should be the problem then, but I'm not 100% sure about that.
Can't you use the Matrix.Rotate class to do the heavy lifting? Source: http://msdn.microsoft.com/en-us/library/s0s56wcf.aspx (Of course the math is half the fun).