Algorithm for finding new points of rotating a vector - c#

I am trying to programmatically find the point created from rotating a vector around it's origin point (could be anywhere in 2D space).
We see that we have our line (or vector for the math) A at some point of (x, y) that might be anywhere in 2D space. It runs to point B at some (x, y). We rotate it by Theta which then moves to some point C at an (x, y). The problem for me comes with trying to programmatically use math to solve for such.
Originally the thought was to form a triangle and use trig but this angle could be exactly 180 (unlikely but possible) which obviously no triangle can work. Would anyone have ideas?
I am using C# and my own vector object (below) to test out the creation of lines. Any help is appreciated!
struct Vector2D {
double x, y, theta;
Vector2D(double x, double y) {
(this.x, this.y) = (x, y);
theta = x != 0 ? Math.Atan(y / x) : 0;
}
double Magnitude() {
return Math.Sqrt(Math.Pow(x, 2) + Math.Pow(y, 2));
}
(double,double) PointFromRotation(double angle) {
// This is where I need some help...
return (0,0); // hopefully a point of x and y from the angle argument
}
}

I think it would be best to use the following code.
I've made some minor modifications and supplements to your code.
The calculation part of 'theta' was slightly modified.
And, you can refer to the rotation algorithm from the following URL.
Rotation (mathematics)
struct Vector2D
{
public double x;
public double y;
public double theta;
public Vector2D(double x, double y)
{
(this.x, this.y) = (x, y);
theta = x != 0 ? Math.Atan(y / x) : Math.Sign(y) * Math.PI / 2.0;
}
public double Magnitude()
{
return Math.Sqrt(Math.Pow(x, 2) + Math.Pow(y, 2));
}
public (double x, double y) PointFromRotation(double angle)
{
double Sint = Math.Sin(angle);
double Cost = Math.Cos(angle);
double rX = x * Cost - y * Sint;
double rY = x * Sint + y * Cost;
return (rX, rY);
}
}

You can convert cartesian coordinates (x, y) into polar ones (R, fi),
add theta to fi and then convert back to cartesian:
// Rotate B around A by angle theta
private static (double x, double y) Rotate(
(double x, double y) A,
(double x, double y) B,
double theta) {
double fi = Math.Atan2(B.y - A.y, B.x - A.x) + theta;
double R = Math.Sqrt((A.y - B.y) * (A.y - B.y) + (A.x - B.x) * (A.x - B.x));
return (A.x + R * Math.Cos(fi), A.y + R * Math.Sin(fi));
}
the only possible difficulty is to compute fi which can be done with a help of Math.Atan2 method.

Another option:
// Rotate B around A by angle theta clockwise
private static (double x, double y) Rotate(
(double x, double y) A,
(double x, double y) B,
double theta)
{
double s = Math.Sin(theta);
double c = Math.Cos(theta);
// translate point back to origin:
B.x -= A.x;
B.y -= A.y;
// rotate point clockwise
double xnew = B.x * c - B.y * s;
double ynew = B.x * s + B.y * c;
// translate point back:
B.x = xnew + A.x;
B.y = ynew + A.y;
return B;
}
inspired by this answer

Related

Formula to compute an arcuate segment length

Considering the class:
public class Point3D
{
public double X;
public double Y;
public double Z;
public Point3D(double x, double y, double z)
{
X = x;
Y = y;
Z = z;
}
public double DistanceTo(Point3D to)
{
double dX = Math.Abs(to.X - X);
double dY = Math.Abs(to.Y - Y);
double dZ = Math.Abs(to.Z - Z);
return Math.Sqrt(dX * dX + dY * dY + dZ * dZ);
}
}
And the class:
public class Segment
{
public Point3D From;
public Point3D To;
public double? Radius;
public Segment(Point3D from, Point3D to, double? radius)
{
From = from;
To = to;
Radius = radius;
}
public double Length
{
get
{
double straightLength = From.DistanceTo(To);
if (Radius == null)
return straightLength;
if (Radius < straightLength/ 2d)
throw new Exception();
// Compute the arcuate segment length
}
}
}
I would like to compute the length of the arc (with Radius) passing through From and To 3D points.
Some help will be welcome!
According to http://mathworld.wolfram.com/IsoscelesTriangle.html
straightLength / 2 = Radius * sin( 1/2 * angle)
Therefore:
angle = 2 * arcsin( straightLength / 2 / Radius)
and
arcLength = Radius * angle;
One more reference:
from math.stackexchange
S=length of the arc = r*theta,
where r= radius and Cos(theta)=(dotproduct of 2 vectors)/(product of the modulus of those vectors)

Calculating temporary coordinate if distance exceeds 100

I have a problem with coding a function that will do the following:
Function will take 2 sets of coordinates (x,y,z). First set is starting point and second one is end point.
Now first i will have to determine distance between those two points. If distance will be greater than lets say 100 then i will have to calculate a temporary point. I will then calculate distance between first set of coordinates and this temporary point. Please check illustration below i am sure things will be much more understandable.
Function that calculates new point between points A,B:
x = (x1+x2/2)
y = (y1+y2/2)
z = (z1+z2/2)
Function that calculates distance is:
public float DistanceTo(float x, float y, float z, float x2, float y2, float z2)
{
float a = x - x2;
float b = y - y2;
float c = z - z2;
return Math.Sqrt(a * a + b * b + c * c);
}
Link to illustration:
Perhaps my approach will be CPU heavy and perhaps slow (?) but currently i am out of ideas how to approach the problem.
Basically i need a function that will go from A to B in increments if (distance < 100).
Thank you for reading and thanks for any solution posted!
PS please dont make fun of my paint skills :)
Compute the distance d from (xb,yb,zb) (begin) to (xe,ye,ze) (end). Compute the number of parts N=(int)((d-1)/100)+1. Compute
xk = xb + (k*(xe-xb))/N
yk = yb + (k*(ye-yb))/N
zk = zb + (k*(ze-zb))/N
for k=1,...,N-1 to get equally spaced points on the segment with a distance not surpassing 100.
You can do it recursively
create a Point struct that represent a point in R3, with 2 utility methods to calculate the distance and midpoint.
struct Point
{
public double x;
public double y;
public double z;
public double Distance(Point b)
{
return Math.Sqrt(Math.Pow(b.x - this.x, 2) +
Math.Pow(b.y - this.y, 2) +
Math.Pow(b.z - this.z, 2));
}
public Point MidPoint(Point b)
{
return new Point()
{
x = (this.x + b.x) / 2,
y = (this.y + b.y) / 2,
z = (this.z + b.z) / 2
};
}
}
and write a simple recursive function that will calculate the distance and call itself recursively until the distance between point a and the temp point is less than maxSegmentLength which is 100 in your case:
public static Point GetPoint(Point a, Point b, double maxSegmentLength)
{
var distance = a.Distance(b);
if (distance < maxSegmentLength)
return b;
else
return GetPoint(a, a.MidPoint(b),maxSegmentLength);
}
Or more efficiently with vectors:
struct Vector
{
public double Vx;
public double Vy;
public double Vz;
public double R;
public Vector(Point a,Point b)
{
R = a.Distance(b);
Vx = (b.x - a.x)/R;
Vy = (b.y - a.y)/R;
Vz = (b.z - a.z)/R;
}
}
public static Point GetPoint(Point a, Point b,double maxSegmentLength)
{
var Vab = new Vector(a, b);
var dAC = Vab.R;
while (dAC > maxSegmentLength) { dAC /= 2; } //or replace this line and the one above it with var dAC=Math.Pow(0.5,(int)(-(Math.Log(maxSegmentLength / Vab.R) / Math.Log(2))) + 1)*Vab.R;
return new Point() {
x = a.x + Vab.Vx * dAC ,
y = a.y + Vab.Vy * dAC ,
z = a.z + Vab.Vz * dAC
};
}
If the point is always at a midpoint then its distance is always half of the original
public double Calc(Point A, Point B)
{
double d = Distance(A,B);
while(d>100)
{
d/=2;
}
return d;
}

calculate Point by point, angle and distance on a map

I have a mission to calculate point on a Map. I have the start point, the angle and the distance from the point. How can I do it ? I search a lot I found something but it doesn't work good - I mean it it doesn't calculate the correct point. Thank's all.
My try :
public Point MesPoint(double x1, double x2, double y1, double y2, double distance, double x) // X is the angle
{
double xEndP, yEndP;
var angularDistance = distance / c_EarthRadiusInKilometers; // angular distance in radians
var lat = ToRadian(y2);
var lon = ToRadian(x2);
var angel = ToRadian(x);
double latRadians = Math.Asin((Math.Sin(lat) * Math.Cos(angularDistance)) + (Math.Cos(lat) * Math.Sin(angularDistance) * Math.Cos(angel)));
double lngRadians = Math.Atan2(
Math.Sin(angel) * Math.Sin(angularDistance) * Math.Cos(lat),
Math.Cos(angularDistance) - (Math.Sin(lat) * Math.Sin(latRadians)));
double lon1 = (lon + lngRadians + Math.PI) % (2 * Math.PI) - Math.PI; // normalise to -180..+180ยบ
yEndP = ToDegrees(latRadians);
xEndP = ToDegrees(lon1);
return (new Point(xEndP, yEndP));
}

Rotating 3D scatter plot data in WPF not working as expected

I have followed the model presented in this article for displaying scatter plot data in WPF. I can easily rotate the image in the view matrix but I need to rotate the raw data points and do a least squares fit of the z-axis values to the z=0 plane. I only need to rotate the data 5-20 degrees so I don't think I need quaternions to avoid gimble lock. I have tried the following methods and have also tried translating the data to the origin before rotating but it has not worked as expected. The RotateX method seems to work but the other 2 methods seem to squish all the data together either in the y axis or the z axis. I've checked the formulas with about 10 different sites and can't find any errors but the results still don't make sense.
public static Point3D RotateAboutX(Point3D pt1, double aX)
{
double angleX = 3.1415926 * aX / 180;
double x2 = pt1.X;
double y2 = (pt1.Y * Math.Cos(angleX)) - (pt1.Z * Math.Sin(angleX));
double z2 = (pt1.Y * Math.Sin(angleX)) + (pt1.Z * Math.Cos(angleX));
return new Point3D(x2, y2, z2);
}
public static Point3D RotateAboutY(Point3D pt1, double aY)
{
double angleY = 3.1415926 * aY / 180;
double x2 = (pt1.X * Math.Cos(angleY)) - (pt1.Z * Math.Sin(angleY));
double y2 = pt1.Y;
double z2 = (pt1.X * Math.Sin(angleY)) + (pt1.Z * Math.Cos(angleY));
return new Point3D(x2, y2, z2);
}
public static Point3D RotateAboutZ(Point3D pt1, double aZ)
{
double angleZ = 3.1415926 * aZ / 180;
double x2 = (pt1.X * Math.Cos(angleZ)) - (pt1.Y * Math.Sin(angleZ));
double y2 = (pt1.X * Math.Sin(angleZ)) + (pt1.Y * Math.Cos(angleZ));
double z2 = pt1.Z;
return new Point3D(x2, y2, z2);
}
I found my own error. The mistake is in the RotateAboutY() method above. The correct method is like this...
public static Point3D RotateAboutY(Point3D pt1, double aY)
{
double angleY = 3.1415926 * aY / 180;
double x2 = (pt1.Z * Math.Sin(angleY)) + (pt1.X * Math.Cos(angleY));
double y2 = pt1.Y;
double z2 = (pt1.Z * Math.Cos(angleY)) - (pt1.X * Math.Sin(angleY));
return new Point3D(x2, y2, z2);
}
The short treatment of this topic can be found here with the correct formulas. There is a more detailed explanation of this topic on Kirupa.com where the correct formulas are also included.

Retrieve a positive or a negative angle from 3 points

I am rotating points around a center point in 2D space. The points are the center point, the old mouse position, and the new mouse position. My rotation function works fine, and I can calculate the angle perfectly. But I want to calculate a negative angle if the user is moving their mouse in a direction which should be interpreted as counter-clockwise.
For example, moving the mouse toward the right (positive x-axis) should rotate clockwise if you are above (less than) the y value of the center point, but it should rotate counter-clockwise if you are actually below (greater than) the y value of the center point.
Here's what I have:
PointF centerPoint;
PointF oldPoint;
PointF newPoint;
double Xc = centerPoint.X;
double Yc = centerPoint.Y;
double Xb = oldPoint.X;
double Yb = oldPoint.Y;
double Xa = newPoint.X;
double Ya = newPoint.Y;
double c2 = (Math.Pow(Xb - Xa, 2) + Math.Pow(Yb - Ya, 2));
double a2 = (Math.Pow(Xb - Xc, 2) + Math.Pow(Yb - Yc, 2));
double b2 = (Math.Pow(Xa - Xc, 2) + Math.Pow(Ya - Yc, 2));
double a = Math.Sqrt(a2);
double b = Math.Sqrt(b2);
double val = (a2 + b2 - c2) / (2 * a * b);
double angle = Math.Acos(val);
So I need a way to make angle negative when it needs to be, so the points rotate clockwise or counter-clockwise to follow the mouse position.
Try this, but I'm not sure:
double v1x = Xb - Xc;
double v1y = Yb - Yc;
double v2x = Xa - Xc;
double v2y = Ya - Yc;
double angle = Math.Atan2(v1x, v1y) - Math.Atan2(v2x, v2y);
private double AngleFrom3PointsInDegrees(double x1, double y1, double x2, double y2, double x3, double y3)
{
double a = x2 - x1;
double b = y2 - y1;
double c = x3 - x2;
double d = y3 - y2;
double atanA = Math.Atan2(a, b);
double atanB = Math.Atan2(c, d);
return (atanA - atanB) * (-180 / Math.PI);
// if Second line is counterclockwise from 1st line angle is
// positive, else negative
}
It seems like all you need to do is
angle = angle > Math.PI ? angle - 2*Math.PI : angle;
at the end of your code. That will give you a clockwise rotation to the right of the line defined by centerPoint and oldPoint, and counter-clockwise to the left of it, regardless of orientation.
Given vectors (x1,y1) and (x2,y2), I would suggest computing the cross product and dot product, and then using Atan2() on them. That will work in all cases where both vectors are non-zero and vector lengths are "reasonable".

Categories