So I'm trying to use the haversine formula in Unity to get the distance between two different points (latitude and longitud given). The code is working (no errors) but I keep gettting a wrong result. I followed the entire formula so I don't really know where the math/code problem is. Any idea?
Here's the code:
public float lat1 = 42.239616f;
public float lat2 = -8.72304f;
public float lon1 = 42.239659f;
public float lon2 = -8.722305f;
void operacion(){
float R = 6371000; // metres
float omega1 = ((lat1/180)*Mathf.PI);
float omega2 = ((lat2/180)*Mathf.PI);
float variacionomega1 = (((lat2 - lat1)/180)*Mathf.PI);
float variacionomega2 = (((lon2 - lon1) / 180) * Mathf.PI);
float a = Mathf.Sin(variacionomega1/2) * Mathf.Sin(variacionomega1/2) +
Mathf.Cos(omega1) * Mathf.Cos(omega2) *
Mathf.Sin(variacionomega2/2) * Mathf.Sin(variacionomega2/2);
float c = 2 * Mathf.Atan2(Mathf.Sqrt(a), Mathf.Sqrt(1-a));
float d = R * c;
}
I think this line is incorrect:
float c = 2 * Mathf.Atan2(Mathf.Sqrt(a), Mathf.Sqrt(1-a));
UPDATED:
The correct way would be:
float c = 2 * Mathf.Asin(Mathf.Sqrt(a));
Related
Hello I am trying to visualize an Aizawa attractor and it's seems to work at first but then just stabilizes at zero/stops moving. I have looked at several implementations online and mine seems to be the same but I don't know why it stops moving.
Here's the code which takes in a point and returns the new point:
public class Aizawa
{
private const float a = 0.95f;
private const float b = 0.7f;
private const float c = 0.6f;
private const float d = 3.5f;
private const float e = 0.25f;
private const float f = 0.1f;
public static void Iterate(float x, float y, float z, out float dX, out float dY, out float dZ)
{
dX = ((z - b) * x - d * y);
dY = (d * x + (z - b) * y);
dZ = (c + a * z - ((z * z * z) / 3f) - (x * x + y * y) * (1f + e * z) + f * z * x * x * x);
}
}
After this I just set the point as follows:
_xPos += dX * time;
_yPos += dY * time;
_zPos += dZ * time;
I'm using unity to visualize it and here is the result so far:
screenshot
I have no idea where to go from here! Any help would be appreciated
Cheers
I am trying to figure math for getting all longitudes and latitudes in a specific distance between each other. I have math for getting distance between geographic coords but I would like to get an array of all geo coords from the standard plane earthmap in the specific distance. Can you help me, please?
Here is example link of earthmap picture. I have earth heightmap in resolution 43200x21600 and I would like to get heights/pixels indexed from bottom left to top right in exact distance 100km. If I can get longitudes and latitudes in distance 100km then I can read these heights.
Here is math for distance between geographic points:
public static float GetGeographicDistance(float latitudeA, float longitudeA, float latitudeB, float longitudeB, float earthRadius = 6371.007f)
{
float phi1 = latitudeA * Mathf.Deg2Rad;
float phi2 = latitudeB * Mathf.Deg2Rad;
float deltaPhi = (latitudeB - latitudeA) * Mathf.Deg2Rad;
float deltaLambda = (longitudeB - longitudeA) * Mathf.Deg2Rad;
float a = Mathf.Sin(deltaPhi / 2) * Mathf.Sin(deltaPhi / 2) +
Mathf.Cos(phi1) * Mathf.Cos(phi2) *
Mathf.Sin(deltaLambda / 2) * Mathf.Sin(deltaLambda / 2);
float c = 2.0f * Mathf.Atan2(Mathf.Sqrt(a), Mathf.Sqrt(1.0f - a));
return earthRadius * c;
}
Got it. If somebody needs it, here is the function in C#.
public static TGeographicCoordinate DestinationPointFromStartPoint(TGeographicCoordinate start, double distance = 100f, double bearing = 90f, double earthRadius = 6371.009d)
{
TGeographicCoordinate result = new TGeographicCoordinate();
double angularDistanceRdn = distance / earthRadius;
double bearingRad = Mathf.Deg2Rad * bearing;
double startLatRad = start.Latitude * Mathf.Deg2Rad;
double startLonRad = start.Longitude * Mathf.Deg2Rad;
result.Latitude = Math.Asin((Math.Sin(startLatRad) * Math.Cos(angularDistanceRdn)) +
(Math.Cos(startLatRad) * Math.Sin(angularDistanceRdn) * Math.Cos(bearingRad)));
result.Longitude = startLonRad + Math.Atan2(Math.Sin(bearingRad) * Math.Sin(angularDistanceRdn) * Math.Cos(startLatRad),
Math.Cos(angularDistanceRdn) - (Math.Sin(startLatRad)) * Math.Sin(result.Latitude));
result.Latitude *= Mathf.Rad2Deg;
result.Longitude *= Mathf.Rad2Deg;
return result;
}
I'm creating a small game in Unity with C#, I'm not allowed to use any of the built in physics or colliders. What I have is a platform with a weight object on it. With the arrow keys you can tilt the platforms angle. The weight on top should then react accordingly to the given tilt angle. I have calculated everything with the friction, max friction, normal force a.s.o. The thing that doesn't work is when you press a key to change the tilt, the force on the object should change accordingly, and if the force on the weight is greater that the maximum friction force, then the weight should move. Here is a simplified example of my code.
public float m = 35;
public float µ = 0.15f;
public float g = 9.82f; //(N/kg)
public float N;
public double deg = 0;
Fmax = m * g * µ;
if (Input.GetKeyDown(KeyCode.UpArrow)) {
deg++;
N = m * g * µ * (Math.Cos(deg) * (180.0 / Math.PI));
platform.transform.Rotate(0, 0, deg, Space.Self);
} else if (Input.GetKeyDown(KeyCode.DownArrow)) {
deg--;
N = m * g * µ * (Math.Cos(deg) * (180.0 / Math.PI));
platform.transform.Rotate(0, 0, deg, Space.Self);
}
if(N > Fmax) {
// Do the rest of the code
}
I think that the problem has to do with that Math.Cos(deg) turns the deg into a radian, but I tried to then covert back the reg to a deg with: (180.0 / Math.PI). I can get everything to work on my calculator but not in the code.
This is incorrect:
N = m * g * µ * (Math.Cos(deg) * (180.0 / Math.PI));
If the angle is in degrees you have to convert it to radians and pass that the cosine function:
double rad = deg*Math.PI/180.0;
N = m*g*mu*Math.Cos(rad);
You can easily convert from radians to degrees and from degrees to radians using the Mathf.Deg2Rad and Mathf.Rad2Deg constants
using UnityEngine;
public class Example : MonoBehaviour
{
// convert 1 radian to degrees
float rad = 10.0f;
void Start()
{
float deg = rad * Mathf.Rad2Deg;
Debug.Log(rad + " radians are equal to " + deg + " degrees.");
}
}
There is a super handy function called Mathf.Rad2Deg and Mathf.Deg2Rad. They convert radians to degrees and degrees to radians.
So unlike everyone here, I'm trying to find the intersections from circle-line collision.
The points are taken from the user input.
float cx; //circle center x
float cy; //circle center y
float px; //point x
float py; //point y
float vx; //vector x
float vy; //vector y
float vySq = vy * vy;
float vxSq = vx * vx;
float cxSq = cx * cx;
float rSq = r * r;
float thatPart = ( ( (vy * px) / vx) + py - cy); //so I don't have to re-type it 3 different times
float a = 1 + (vySq/vxSq);
float b = (2 * cx) + ( (2 * vy) * thatPart / vx);
float c = cxSq + ( thatPart * thatPart ) - rSq;
float x1 = QUADRATIC(a, b, c, true);
float x2 = QUADRATIC(a, b, c, false);
float y1 = ((vy * x1) - (vy * px) + (vx * py)) / vx;
float y2 = ((vy * x2) - (vy * px) + (vx * py)) / vx;
My QUADRATIC function 100% works, so I am not worried about that.
It's a, b, and c. I receive the wrong values for them. And all this math is based on a pdf given in math class. (here)
So... what am I doing wrong?
Thanks.
The equations in both the PDF and the source code seem unnecessarily complicated, so I will re-establish them in a clenear way (or at least one that pleases me).
The vector from the center of the circle to any point S on the line can be written as
CS = CP + t V
where t is an arbitrary parameter.
S belongs to the circle when
CS² = R² = (CP + t V)²
giving the quadratic equation in t:
V² t² + 2 CP.V t + CP² - R² = 0
When you have the values of t, plug in the first equation.
Math Treatment
You have a line with coordinates (x,y) = (px + vx*t, py + vy*t) where t is an arbitrary parameter.
The line intersects the circle when its coordinates solve x^2 + y^2 = r^2.
This leads to the following quadratic equation, to be solved for t.
t^2 + 2*t*b + a = 0
a = (px^2+py^2-r^2)/(vx^2+vy^2)
b = (px*vx+py*vy)/(vx^2+vy^2)
The two solutions are:
t = -b ± sqrt(b^2-a)
Use the two t values into (x,y) to get the coordinates.
Sample Code
static class Program
{
static void Main(string[] args)
{
var ray = new Ray() {
Point = new Vector2(-3, 1),
Direction = new Vector2(2, 0.5f)
};
var circle = new Circle
{
Center = new Vector2(1, 1),
Radius = 4
};
var points = Geometry.Intersect(circle, ray);
if(points.Length>0)
{
foreach(var point in points)
{
Console.WriteLine(point.ToString());
}
}
else
{
Console.WriteLine("Circle and Ray do not intersect");
}
}
}
Object Oriented Models
public class Circle
{
public Vector2 Center { get; set; }
public float Radius { get; set; }
}
public class Ray
{
public Vector2 Point { get; set; }
public Vector2 Direction { get; set; }
public Vector2 Along(float t)
{
return Point + t*Direction;
}
}
public static class Geometry
{
public static Vector2[] Intersect(Circle circle, Ray ray)
{
float a = (ray.Point.LengthSquared()-circle.Radius*circle.Radius)/ray.Direction.LengthSquared();
float b = Vector2.Dot(ray.Point, ray.Direction)/ray.Direction.LengthSquared();
if(b*b-a>0)
{
// two intersection points
float t1 = -b-(float)Math.Sqrt(b*b-a);
float t2 = -b+(float)Math.Sqrt(b*b-a);
return new Vector2[] {
ray.Along(t1),
ray.Along(t2),
};
}
else if(b*b-a==0)
{
// one intersection point
float t = -b;
return new Vector2[] { ray.Along(t) };
}
else
{
// no intersection, return empty array
return new Vector2[0];
}
}
}
NOTE: Code uses System.Numerics library
I don't quite understand this code so I am having difficulty modifying it.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SunScript : MonoBehaviour {
public float duration = 1.0F;
public Light lt;
void Start() {
lt = GetComponent<Light>();
}
void Update() {
float phi = Time.time / duration * 0.1f * Mathf.PI;
float amplitude = Mathf.Cos(phi) * 0.5F + 0.5F;
lt.intensity = amplitude;
}
}
This moves the light's intensity up and down in a cycle. However, I would like to have it stay at its brightest and its dimmest for a while before it starts to move back the other direction. How should I do this?
What about replacing Mathf.Cos(phi) one of these functions instead of just a cosine?
Using the equation at the bottom of that page:
float amplitude = Mathf.Sin(Mathf.PI / 2f * Mathf.Cos(phi)) * 0.5f + 0.5f;
For the formula with the b term, you could do this (using extra temp variables to make it a little more readable).
float b = // whatever your b parameter is or have this declared as a class field that you can set in the Unity editor
float cosine = Mathf.Cos(phi);
float numerator = 1f + (b * b);
float denominator = 1f + (b * b * cosine * cosine);
float amplitude = (Mathf.Sqrt(numerator / denominator) * cosine) * 0.5f + 0.5f;
You can also use the Unity AnimationCurve to achieve this:
public class SunScript : MonoBehaviour
{
public float duration = 1.0F;
public AnimationCurve curve;
private Light lt;
void Start()
{
lt = GetComponent<Light>();
}
void Update()
{
lt.intensity = curve.Evaluate((Time.time % duration) / duration);
}
}
Simply make sure your curve is from 0 to 1 following X axis and make it the values you want on the Y axis.
Hope this helps,