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));
}
Related
I am aware that this question have been asked before, and I checked a lot of posts and I realize my math is not good enough to solve this problem.
I have a circle, which is the centerpoint at x = 0.0 & y = 0.0. Based on degree, 270 in this example, I want to place the x-box on x & y at the specified degree from the centerpoint. I just cannot get it right, not even with the examples I have found. Below is the current code I test as well as the result of 270 degree test, x-box is positioned wrongly as it is not 270 degree angle.
I would appreciate any help.
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class testscript : MonoBehaviour
{
public Image im1, im2;
public Text im1txt, im2txt, deg;
private float degree = 270f;
private float x, y;
void Start()
{
im1.rectTransform.anchoredPosition = new Vector2(0f, 0f);
im1txt.text = im1.rectTransform.anchoredPosition.ToString();
deg.text = degree + " degrees";
x = 0f + (100 * Mathf.Cos(degree * Mathf.PI / 360f));
y = 0f + (100 * Mathf.Sin(degree * Mathf.PI / 360f));
im2.rectTransform.anchoredPosition = new Vector2(x, y);
im2txt.text = im2.rectTransform.anchoredPosition.ToString();
}
}
I have tested the two suggestions below and basically get the same result as all the others. Let me visualize the result I get with the last test I done:
const float deg_to_rad = 2f * Mathf.PI / 360f;
var radians = degree * deg_to_rad;
x = 0 + Mathf.Cos(radians) * 100;
y = 0 + Mathf.Sin(radians) * 100;
Here is the result:
[![enter image description here][2]][2]
Solution is, Sin and Cos was swapped. Thanks J.Lengel:
float x = 1f + (100 * Mathf.Sin(angelDegree * Mathf.PI / 180));
float y = -14f + (100 * Mathf.Cos(angelDegree * Mathf.PI / 180));
In your Math.cos and Math.sin you are converting from degrees to radians by dividing by 360. This will not work as 360 degrees is the equivalent of 2pi in radians as opposed to pi. This means you have to divide by 180, or multiply degrees by 2. Hope that helps!
I've noticed that you take the cosine for x and the sin for y. Swap this; you want to go clockwise and the way you're doing it is for going counterclockwise.
x = x_origin + Math.sin(angle) * radius;
y = y_origin + Math.cos(angle) * radius;
A full circle (360 degrees) is 2*PI radians:
x = 0f + (100 * Mathf.Cos(degree * 2 * Mathf.PI / 360f));
y = 0f + (100 * Mathf.Sin(degree * 2 * Mathf.PI / 360f));
const float deg_to_rad = 2f * Mathf.PI / 360f
var radians = degrees * deg_to_rad;
x = x_orig + Mathf.Cos(radians) * radius;
y = y_orig + Mathf.Sin(radians) * radius;
Tried to add this to the original post but could not so I post here.
I have tested the above and get the same results as I have gotten with the majority of my previous tests. It seems to work on like 45 & 225 degree but not the 90, 180 & 270.
It is probably my math competence that fails and I guess it is a simple problem to solve.
The last test I did, with is represented in. the picture is:
const float deg_to_rad = 2f * Mathf.PI / 360f;
var radians = degree * deg_to_rad;
x = 0 + Mathf.Cos(radians) * 100;
y = 0 + Mathf.Sin(radians) * 100;
im2.rectTransform.anchoredPosition = new Vector2(x, y);
Here is the latest results from my tests with the above code:
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
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 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).
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