Finding the closest point on a line to another point - java

I have a affine equation y = ax + b where a is the coefficient (coeff).
Let D be a line that goes through axis and described by the previous equation.
I'm trying with this piece of code to find the coordinates of the closest point on D to position (ignoring the y coordinate, because 2D in 3D)
double a = coeff;
double b = position.getZ();
double c = axis.getZ() - axis.getX() * coeff;
double x0 = position.getX();
double y0 = position.getZ();
return new Vector((b * (b * x0 - a * y0) - a * c) / (a * a + b * b), position.getY(),
(a * (-b * x0 + a * y0) - b * c) / (a * a + b * b));
Using this as a refernece
However, this does not work and return weird results

If you stay in vector representation it may be easier.
I have an example code but only in C++ (and Direct3D):
D3DXVECTOR3 ProjectOnLine (const D3DXVECTOR3 &point,
const D3DXVECTOR3 &linePoint,
const D3DXVECTOR3 &lineUnityDir)
{
float t = D3DXVec3Dot(&(point-linePoint), &lineUnityDir);
return linePoint + lineUnityDir*t;
}
If I understand you then your parameters can be used like this:
D3DXVECTOR3 point = position;
D3DXVECTOR3 linePoint = axis;
D3DXVECTOR3 lineUnityDir = D3DXVECTOR3(1, a, 0)/sqrt(1+a*a);

Related

Adaptive Quadrature Algorithm - Recursive to Iterative

I would like to know if it is possible to make this algorithm iterative instead of recursive, and if its posible, could someone help me?.
public static double adaptiveQuadrature(double a, double b) {
double h = b - a;
double c = (a + b) / 2.0;
double d = (a + c) / 2.0;
double e = (b + c) / 2.0;
double Q1 = h / 6 * (f(a) + 4 * f(c) + f(b));
double Q2 = h / 12 * (f(a) + 4 * f(d) + 2 * f(c) + 4 * f(e) + f(b));
if (Math.abs(Q2 - Q1) <= EPSILON)
return Q2 + (Q2 - Q1) / 15;
else
return adaptiveQuadrature(a, c) + adaptiveQuadrature(c, b);
}
static double f(double x) {
return Math.exp( - x * x / 2) / Math.sqrt(2 * Math.PI);
}
Thank you so much for your help!
I don't think so. The size of the steps is depending on function evaluations made at the endpoints of the initial interval, then at the endpoints of subintervals. The pattern is not progressive and you can't organize a single loop that will "guess" the step ahead of time.
Of course you can derecursivate by means of an explicit stack, but that won't essentially change the nature of the process.

How do I get the endpoints of a line in Java knowing angle, midpoint, and length

I need to find the endpoints of a line knowing its midpoint, angle, and length. First, I tried this:
public Point getEndpointA(Point midpoint, double angle, double length) {
Point a = new Point(0, 0);
a.x = midpoint.x + (int) length * Math.cos(angle);
a.y = midpoint.y + (int) length * Math.sin(angle);
return a;
}
public Point getEnpointB(Point midpoint, double angle, double length) {
Point b = new Point(0, 0);
b.x = midpoint.x + (int) length * Math.cos(-angle);
b.y = midpoint.y + (int) length * Math.sin(-angle);
return b;
}
and then I called these functions to get the enpoints of the lines. However, this was inaccurate, and the points weren't placed quite where I hoped. Then, I tried experimenting with the distance formula, but that didn't work because I am only just starting Algebra I and I was having trouble getting rid of exponents and radical signs, which is not covered in Algebra I. (I looked up the functions sin and cos, and I understand what they mean now, so that's how I know about them) So, can somebody write a function that would return the endpoints of a line based of its midpoint, angle, and length, and explain to me how it works?
You want to specify the angle in degrees like followings?
public Point getEndpointA(Point midpoint, double angleDegee, double length) {
Point a = new Point(0, 0);
// convert degrees=>radians
final double angleRad = Math.toRadians(angleDegee);
a.x = (int) (midpoint.x + (int) length * Math.cos(angleRad));
a.y = (int) (midpoint.y + (int) length * Math.sin(angleRad));
return a;
}
public Point getEndpointB(Point midpoint, double angleDeg, double length) {
Point b = new Point(0, 0);
final double angleRad = Math.toRadians(angleDeg + 180d);
b.x = (int) (midpoint.x + (int) length * Math.cos(angleRad));
b.y = (int) (midpoint.y + (int) length * Math.sin(angleRad));
return b;
}

X and Y with coordinate - algorithm

I have many object with coordinate (like 600-1000) for example:
coordX - 16.88799654
coordY - 53.452535636
coordX - 16.78799652
coordY - 53.1436346423
coordX - 17.06546333
coordY - 52.96543332
.....
user add his own coordinates X and Y for example:
userX = 12.4669945
userY = 52.234534536
Someone have idea, how to write an algorithm, to get the nearest in straight line object for list of all object?
I assume that the coordinates are geodetic (lat/lon), so a simple Euclidian distance won't be correct. The following is in C#, I hope you can translate to Java. You can also simplify to a single function if desired.
private const double EARTH_RADIUS_MI = 3959; //In statute miles
public static float Radians(double degrees)
{
return (float)(degrees * (Math.PI / 180));
}
public static double CalculateDistance(Coordinates fromPoint, Coordinates toPoint)
{
double dLat = Radians(toPoint.Latitude - fromPoint.Latitude);
double dLon = Radians(toPoint.Longitude - fromPoint.Longitude);
double a = Math.Sin(dLat / 2) * Math.Sin(dLat / 2) +
Math.Cos(Radians(fromPoint.Latitude)) * Math.Cos(Radians(toPoint.Latitude)) *
Math.Sin(dLon / 2) * Math.Sin(dLon / 2);
double c = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a));
return EARTH_RADIUS_MI * c;
}

Angle between two 3D vectors

I have a series of vertices (pink) that I want to rotate so that one edge of the pattern of vertices matches with the edge of the triangle (white).
To do this, I first create two vectors to represent the edges: floretAB and triangleAB (green). I then find the cross product of the two to get an axis around which I can rotate the vertices (red).
I then get the angle between the two vectors, and use that, with the rotation axis to create a quaternion. Finally, I rotate all the vertices around the quaternion.
Before rotation
_
What rotation should produce
_
However, although the vertices correctly rotate around the quaternion, the angle is not coming out correct, as illustrated here:
This is the code I'm using to get the angle between the two vectors. I don't understand what I'm doing wrong:
double[] cross = new double[3];
crossProduct(floretAB.mX, floretAB.mY, floretAB.mZ, triangleAB.mX, triangleAB.mY, triangleAB.mZ, cross);
double dot = dotProduct(floretAB.mX, floretAB.mY, floretAB.mZ, triangleAB.mX, triangleAB.mY, triangleAB.mZ);
double crossMag = Math.sqrt(cross[0]*cross[0] + cross[1]*cross[1] + cross[2]*cross[2]);
double angle = Math.atan2(crossMag, dot);
public static double dotProduct(double vector1X,double vector1Y,double vector1Z,double vector2X,double vector2Y,double vector2Z){
return vector1X*vector2X + vector1Y*vector2Y + vector1Z*vector2Z;
}
public static void crossProduct(double vector1X,double vector1Y,double vector1Z,double vector2X,double vector2Y,double vector2Z, double[] outputArray){
outputArray[0] = vector1Y*vector2Z - vector1Z*vector2Y;
outputArray[1] = vector1Z*vector2X - vector1X*vector2Z;
outputArray[2] = vector1X*vector2Y - vector1Y*vector2X;
}
Any help with this would be most appreciated as it is really bugging me.
Thanks, James
Edit: Here is the rest of the code:
// get floret p1,p2 vector
// get triangle p1,p2 vector
Vector3D floretAB = new Vector3D(florets3D[0], florets3D[7]);
// get triangle p1,p2 vector
Vector3D triangleAB = new Vector3D(triangle[0], triangle[1]);
// get rotation axis (cross) and angle (dot)
/*
double[] cross = new double[3];
crossProduct(floretAB.mX, floretAB.mY, floretAB.mZ, triangleAB.mX, triangleAB.mY, triangleAB.mZ, cross);
double dotMag = floretAB.getMagnitude() * triangleAB.getMagnitude();
double dot = dotProduct(floretAB.mX, floretAB.mY, floretAB.mZ, triangleAB.mX, triangleAB.mY, triangleAB.mZ) / dotMag;
double angle = Math.acos(dot);
*/
double[] cross = new double[3];
crossProduct(floretAB.mX, floretAB.mY, floretAB.mZ, triangleAB.mX, triangleAB.mY, triangleAB.mZ, cross);
double dot = dotProduct(floretAB.mX, floretAB.mY, floretAB.mZ, triangleAB.mX, triangleAB.mY, triangleAB.mZ);
double crossMag = Math.sqrt(cross[0]*cross[0] + cross[1]*cross[1] + cross[2]*cross[2]);
double angle = Math.atan2(crossMag, dot);
// rotate floret so p1,p2 vector matches with triangle p1,p2 vector
double[] newVerts = new double[3];
Quaternion quat = new Quaternion(cross[0], cross[1], cross[2], angle);
for(int i = 0;i<numfloretVerts;i++){
Vertex3D vert = florets3D[i];
quat.RotateVector(vert.getmX(), vert.getmY(), vert.getmZ(), newVerts);
vert.setmX(newVerts[0]);
vert.setmY(newVerts[1]);
vert.setmZ(newVerts[2]);
}
_
public class Vector3D {
public double mX;
public double mY;
public double mZ;
public Vertex3D point;
/**
* Constructs a vector from two points. The new vector is normalised
*
* #param point1
* #param point2
*/
public Vector3D(Vertex3D point1, Vertex3D point2){
mX = point2.getmX() - point1.getmX();
mY = point2.getmY() - point1.getmY();
mZ = point2.getmZ() - point1.getmZ();
normalise();
point = point1;
}
/**
* Normalises the vector
*/
public void normalise(){
double magnitude = Math.sqrt(mX*mX + mY*mY + mZ*mZ);
if(magnitude!=0){
mX /= magnitude;
mY /= magnitude;
mZ /= magnitude;
}
}
/**
*
* #return the magnitude of the vector
*/
public double getMagnitude(){
return Math.sqrt(mX*mX + mY*mY + mZ*mZ);
}
}
_
public class Quaternion {
private static final double TOLERANCE = 0.00001f;
double w;
double x;
double y;
double z;
public Quaternion(double axisX, double axisY, double axisZ, double angleInRadians){
setAxisAngle(axisX, axisY, axisZ, angleInRadians);
}
public void Normalise(){
// Don't normalize if we don't have to
double mag2 = w * w + x * x + y * y + z * z;
if (Math.abs(mag2) > TOLERANCE && Math.abs(mag2 - 1.0f) > TOLERANCE) {
double mag = (double) Math.sqrt(mag2);
w /= mag;
x /= mag;
y /= mag;
z /= mag;
}
}
public void getConjugate(double[] outputArray){
outputArray[0] = w;
outputArray[1] = -x;
outputArray[2] = -y;
outputArray[3] = -z;
}
public void Multiply(double[] aq, double[] rq, double[] outputArray){
outputArray[0] = aq[0] * rq[0] - aq[1] * rq[1] - aq[2] * rq[2] - aq[3] * rq[3];
outputArray[1] = aq[0] * rq[1] + aq[1] * rq[0] + aq[2] * rq[3] - aq[3] * rq[2];
outputArray[2] = aq[0] * rq[2] + aq[2] * rq[0] + aq[3] * rq[1] - aq[1] * rq[3];
outputArray[3] = aq[0] * rq[3] + aq[3] * rq[0] + aq[1] * rq[2] - aq[2] * rq[1];
}
private double[] vecQuat = new double[4];
private double[] resQuat = new double[4];
private double[] thisQuat = new double[4];
private double[] conj = new double[4];
/**
* Rotates a vector (or point) around this axis-angle
*
* #param vectorX the x component of the vector (or point)
* #param vectorY the y component of the vector (or point)
* #param vectorZ the z component of the vector (or point)
* #param outputArray the array in which the results will be stored
*/
public void RotateVector(double vectorX, double vectorY, double vectorZ, double[] outputArray){
vecQuat[0] = 0.0f;
vecQuat[1] = vectorX;
vecQuat[2] = vectorY;
vecQuat[3] = vectorZ;
thisQuat[0] = w;
thisQuat[1] = x;
thisQuat[2] = y;
thisQuat[3] = z;
getConjugate(conj);
Multiply(vecQuat,conj,resQuat);
Multiply(thisQuat,resQuat,vecQuat);
outputArray[0] = vecQuat[1];
outputArray[1] = vecQuat[2];
outputArray[2] = vecQuat[3];
}
/**
* set Quaternion by providing axis-angle form
*/
public void setAxisAngle(double axisX, double axisY, double axisZ, double angleInRadians){
w = (double) Math.cos( angleInRadians/2);
x = (double) (axisX * Math.sin( angleInRadians/2 ));
y = (double) (axisY * Math.sin( angleInRadians/2 ));
z = (double) (axisZ * Math.sin( angleInRadians/2 ));
Normalise();
}
}
I think you've overcomplicated your maths.
Given two unit vectors (you did say they were normalised) then the magnitude of the cross product is equal to sin(theta). There shouldn't be any need to invoke the dot product or atan2.
You possibly also need to normalise the cross product vector result too before you create the quaternion - it depends on your implementation of new Quaternion(x, y, z, theta) and whether it requires [x, y, z] to be normalised or not.
I think the problem is that you evaluate the angle in the wrong way.
If I understand correctly what are you trying to achieve, then you need the angle between 2 green lines. You correctly evaluate the dot product between 2 green lines using the definition:
(a, b) = a1*b1 + a2*b2 + a3*b3.
But dot product can also be evaluated like this:
(a, b) = |a|*|b|*cos(theta)
So you can evaluate cos(theta) - the cosine of angle between 2 green lines - like this:
cos(theta) = (a1*b1 + a2*b2 + a3*b3) / (|a|*|b|)
But I would use yet another approach. I would normalize both vectors at first (i.e. converted them to unit-vectors). You can do this by dividing each vector's component by the vector's length (sqrt(x1*x1 + y1*y1 + z1*z1)) Then you will have the following:
(aa, bb) = cos(theta)
where aa is normalized a and bb is normalized b.
I hope this helps.
The stated answers are correct for real numbers but can loose accuracy near certain angles when computed with floating point numbers. For arcos() when the angle is near zero or PI, and for arcsin() near pi/2 and –pi/2, as many a half the significant figures can be lost. A method that is more robust and only suffers a few rounding errors uniformly over the whole range from and including zero to and including PI, assuming the input vectors are unit length is:
public double AngleBetween(Vector3D a, Vector3D b)
{
return 2.0d * Math.atan((a-b).Length/(a+b).Length);
}
Note, this gives the unoriented angle between the two vectors. A reference for this and attributed to Kahan may be found at: http://www.cs.berkeley.edu/~wkahan/MathH110/Cross.pdf

Point to Line distance (2D) and Coordintates of intersection

So I need to know the Distance from a point to a line (in 2D space), given two coordinates of the line (AB).
Here is what I have so far:
public double pointToLineDistance(Point A, Point B, Point P)
{
double normalLength = Math.sqrt((B.x - A.x) * (B.x - A.x) + (B.y - A.y) * (B.y - A.y));
return Math.abs((P.x - A.x) * (B.y - A.y) - (P.y - A.y) * (B.x - A.x)) / normalLength;
}
But I also need to get the coordinates of the point where the perpendicular line intersects with the AB line (it's ok if it's outside this segment).
Any ideas?
Observe that AB can just be expressed as
ab = A + (B - A) * s
So, the direction of AB is B - A, or (B.x - A.x, B.y - A.y). A line whose direction is (A.y - B.y, B.x - A.x) will be perpendicular. (We just swap the x and y and negate one of them.)
We specifically want a line which is perpendicular to AB and also passes through P, so we do
perp = P + (A.y - B.y, B.x - A.x) * t;
perp = (P.x + A.y - B.y, P.y + B.x - A.x) * t;
Now just find the intersection between this perpendicular line and AB. You have two equations (for the x and y components of the intersection point) and two unknowns (s and t). Once you find s and t, plug them in to either of the lines' equations to get the intersection point.
Here is some working code:
static Vect2 getIntersection(Vect2 A, Vect2 B, Vect2 P) {
Vect2 abDir = B.minus(A);
Vect2 perpDir = new Vect2(-abDir.y, abDir.x);
Vect2 apDir = P.minus(A);
double s = (perpDir.y * apDir.x - perpDir.x * apDir.y)
/ (abDir.x * perpDir.y - abDir.y * perpDir.x);
return A.plus(abDir.scale(s));
}
class Vect2 {
final double x, y;
Vect2(double x, double y) {
this.x = x;
this.y = y;
}
Vect2 scale(double k) {
return new Vect2(x * k, y * k);
}
Vect2 plus(Vect2 that) {
return new Vect2(x + that.x, y + that.y);
}
Vect2 minus(Vect2 that) {
return this.plus(that.scale(-1));
}
}
The idea is to construct an equation of the line going through the points A and B. When you have constructed that equation, you construct an equation of a line that goes through P and is perpendicular to AB. The equation for the perpendicular has coefficients that are easily derived from the equation for the AB-line. Once you have two equations, solving them will give you the coordinate of the intersection.
Is this for homework?
This would help
http://paulbourke.net/geometry/pointline/

Categories