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:
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 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 :)