Draw line from point based on the angle between the 3 points - c++

How can I draw a line starting from one point in the direction of the angle between the points?
This is what I have for calculating the angle
double angle1 = atan2(point_1_y - point_2_y, point_3_x - point_2_x);
double angle2 = atan2(point_1_y - point_3_y, point_3_x - point_2_x);
double result = angle1 - angle2;

First write a function to normalise a vector:
double mag = sqrt(x*x + y*y);
x = x/mag;
y = y/mag;
(I don't know what language you use, so I don't know the syntax of a function.)
Then apply it to the two vectors:
double x1 = point_C_x - point_A_x;
double y1 = point_C_y - point_A_y;
normalise(x1, y1);
double x2 = point_B_x - point_A_x;
double y2 = point_B_y - point_A_y;
normalise(x2, y2);
Then add them to get a green vector, then use atan2:
double x_green = x1+x2;
double y_green = y1+y2;
double d = atan2(y_green, x_green);

Related

Given 2 point and a range from first point to the point that I have to find. How to find the point I have to find (on 3D Space)

I don't know how to find the third point that I have said.
However, I try to write code write this:
float extraX; // x of the third point
float extraY; // y of the third point
float extraZ; // z of the third point
void CalculateExtraPoint(float x1, float y1, float z1, float x2, float y2, float z2){
float range = extraRange; //range from the first point to third point
float d_x = x1-x2;
float d_y = y1-y2;
float d_z = z1-z2;
distance1_2 = sqrt(pow(d_x,2)+pow(d_y,2)+pow(d_z,2));
float temp = (range/distance1_2)+1;
extraX = x2 + (temp*d_x);
extraY = y2 + (temp*d_y);
extraZ = z2 + (temp*d_z);
}
It come from vector equation, r=(x2,y2,z2) + (lambda)[x1-x2,y1-y2,z1-z2]. r is any point.
Is it correct? Thanks in advance.
Yes, it is correct.
Slightly simpler, more convenient variant. Here it is more clear that we consider range from the first point:
float temp = range/distance1_2;
extraX = x1 + (temp*d_x);
extraY = y1 + (temp*d_y);
extraZ = z1 + (temp*d_z);

interior angles of irregular polygon with angles > 180

I'm trying to calculate the values shown in the picture in red i.e. the interior angles.
I've got an array of the points where lines intersect and have tried using the dot-product but it only returns the smallest angles. I need the full range of internal angles (0-359) but can't seem to find much that meets this criteria.
Assuming your angles are in standard counterclockwise format, the following should work:
void angles(double points[][2], double angles[], int npoints){
for(int i = 0; i < npoints; i++){
int last = (i - 1 + npoints) % npoints;
int next = (i + 1) % npoints;
double x1 = points[i][0] - points[last][0];
double y1 = points[i][1] - points[last][1];
double x2 = points[next][0] - points[i][0];
double y2 = points[next][1] - points[i][1];
double theta1 = atan2(y1, x1)*180/3.1415926358979323;
double theta2 = atan2(y2, x2)*180/3.1415926358979323;
angles[i] = (180 + theta1 - theta2 + 360);
while(angles[i]>360)angles[i]-=360;
}
}
Obviously, if you are using some sort of data structure for your points, you will want to replace double points[][2] and references to it with references to your data structure.
You can obtain full angle range (-Pi..Pi) with atan2 function:
atan2(crossproduct, dotproduct)

How to calculate the point of intersection between two lines

I am attempting to calculate the point of intersection between lines for a Optical Flow algorithm using a Hough Transform. However, I am not getting the points that I should be when I use my algorithm for calculating the intersections.
I save the Lines as an instance of a class that I created called ImageLine. Here is the code for my intersection method.
Point ImageLine::intersectionWith(ImageLine other)
{
float A2 = other.Y2() - other.Y1();
float B2 = other.X2() - other.X1();
float C2 = A2*other.X1() + B2*other.Y1();
float A1 = y2 - y1;
float B1 = x2 - x1;
float C1 = A1 * x1 + B1 * y1;
float det = A1*B2 - A2*B1;
if (det == 0)
{
return Point(-1,-1);
}
Point d = Point((B2 * C1 - B1 * C2) / det, -(A1 * C2 - A2 * C1) / det);
return d;
}
Is this method correct, or did I do something wrong? As far as I can tell, it should work, as it does for a single point that I hard-coded through, however, I have not been able to get a good intersection when using real data.
Considering the maths side: if we have two line equations:
y = m1 * x + c1
y = m2 * x + c2
The point of intersection: (X , Y), of two lines described by the following equations:
Y = m1 * X + c1
Y = m2 * X + c2
is the point which satisfies both equation, i.e.:
m1 * X + c1 = m2 * X + c2
(Y - c1) / m1 = (Y - c2) / m2
thus the point of intersection coordinates are:
intersectionX = (c2 - c1) / (m1 - m2)
intersectionY = (m1*c1 - c2*m2) / m1-m2 or intersectionY = m1 * intersectionX + c1
Note: c1, m1 and c2, m2 are calculated by getting any 2 points of a line and putting them in the line equations.
(det == 0) is unlikely to be true when you're using floating-point arithmetic, because it isn't precise.
Something like (fabs(det) < epsilon) is commonly used, for some suitable value of epsilon (say, 1e-6).
If that doesn't fix it, show some actual numbers, along with the expected result and the actual result.
For detailed formula, please go to this page.
But I love code so, here, check this code (I get it from github, so all credit goes to the author of that code):
///Calculate intersection of two lines.
///\return true if found, false if not found or error
bool LineLineIntersect(double x1, double y1, //Line 1 start
double x2, double y2, //Line 1 end
double x3, double y3, //Line 2 start
double x4, double y4, //Line 2 end
double &ixOut, double &iyOut) //Output
{
//http://mathworld.wolfram.com/Line-LineIntersection.html
double detL1 = Det(x1, y1, x2, y2);
double detL2 = Det(x3, y3, x4, y4);
double x1mx2 = x1 - x2;
double x3mx4 = x3 - x4;
double y1my2 = y1 - y2;
double y3my4 = y3 - y4;
double xnom = Det(detL1, x1mx2, detL2, x3mx4);
double ynom = Det(detL1, y1my2, detL2, y3my4);
double denom = Det(x1mx2, y1my2, x3mx4, y3my4);
if(denom == 0.0)//Lines don't seem to cross
{
ixOut = NAN;
iyOut = NAN;
return false;
}
ixOut = xnom / denom;
iyOut = ynom / denom;
if(!isfinite(ixOut) || !isfinite(iyOut)) //Probably a numerical issue
return false;
return true; //All OK
}
Assuming your formulas are correct, try declaring all your intermediate arguments as 'double'. Taking the difference of nearly parallel lines could result in your products being very close to each other, so 'float' may not preserve enough precision.

Finding the distance between 2 3D points

I'm running into a problem where my square of X is always becoming infinite leading to the resulting distance also being infinite, however I can't see anything wrong with my own maths:
// Claculate distance
xSqr = (x1 - x2) * (x1 - x2);
ySqr = (y1 - y2) * (y1 - y2);
zSqr = (z1 - z2) * (z1 - z2);
double mySqr = xSqr + ySqr + zSqr;
double myDistance = sqrt(mySqr);
When I run my program I get user input for each of the co-ordinates and then display the distance after I have run the calulation.
If your inputs are single-precision float, then you should be fine if you force double-precision arithmetic:
xSqr = double(x1 - x2) * (x1 - x2);
// ^^^^^^
If the inputs are already double-precision, and you don't have a larger floating-point type available, then you'll need to rearrange the Euclidean distance calculation to avoid overflow:
r = sqrt(x^2 + y^2 + z^2)
= abs(x) * sqrt(1 + (y/x)^2 + (z/x)^2)
where x is the largest of the three coordinate distances.
In code, that might look something like:
double d[] = {abs(x1-x2), abs(y1-y2), abs(z1-z2)};
if (d[0] < d[1]) swap(d[0],d[1]);
if (d[0] < d[2]) swap(d[0],d[2]);
double distance = d[0] * sqrt(1.0 + d[1]/d[0] + d[2]/d[0]);
or alternatively, use hypot, which uses similar techniques to avoid overflow:
double distance = hypot(hypot(x1-x2,y1-y2),z1-z2);
although this may not be available in pre-2011 C++ libraries.
Try this:
long double myDistance=sqrt(pow(x1-x2,2.0)+pow(y1-y2,2.0)+pow(z1-z2,2.0));
I figured out what was going on, I had copied and pasted the code for setting x1, y1 and z1 and forgot to change it to x2 y2 and z2, It's always the silliest of things with me :P thanks for the help anyway guys

Given a start and end point, and a distance, calculate a point along a line

Looking for the quickest way to calculate a point that lies on a line
a given distance away from the end point of the line:
void calculate_line_point(int x1, int y1, int x2, int y2, int distance, int *px, int *py)
{
//calculate a point on the line x1-y1 to x2-y2 that is distance from x2-y2
*px = ???
*py = ???
}
Thanks for the responses, no this is not homework, just some hacking out of
my normal area of expertise.
This is the function suggested below. It's not close to working. If I
calculate points every 5 degrees on the upper right 90 degree portion of
a circle as starting points and call the function below with the center of the circle as x2,y2 with a distance of 4 the end points are totally wrong. They lie below and to the right of the center and the length is as long as the center point. Anyone have any suggestions?
void calculate_line_point(int x1, int y1, int x2, int y2, int distance)
{
//calculate a point on the line x1-y1 to x2-y2 that is distance from x2-y2
double vx = x2 - x1; // x vector
double vy = y2 - y1; // y vector
double mag = sqrt(vx*vx + vy*vy); // length
vx /= mag;
vy /= mag;
// calculate the new vector, which is x2y2 + vxvy * (mag + distance).
px = (int) ( (double) x2 + vx * (mag + (double)distance) );
py = (int) ( (double) y2 + vy * (mag + (double)distance) );
}
I've found this solution on stackoverflow but don't understand it completely, can anyone clarify?
I think this belongs on MathOverflow, but I'll answer since this is your first post.
First you calculate the vector from x1y1 to x2y2:
float vx = x2 - x1;
float vy = y2 - y1;
Then calculate the length:
float mag = sqrt(vx*vx + vy*vy);
Normalize the vector to unit length:
vx /= mag;
vy /= mag;
Finally calculate the new vector, which is x2y2 + vxvy * (mag + distance).
*px = (int)((float)x1 + vx * (mag + distance));
*py = (int)((float)y1 + vy * (mag + distance));
You can omit some of the calculations multiplying with distance / mag instead.
These equations are wrong:
px = (int) ( (double) x2 + vx * (mag + (double)distance) );
py = (int) ( (double) y2 + vy * (mag + (double)distance) );
The correct equations are:
px = (int) ( (double) x2 + vx * (double)distance );
py = (int) ( (double) y2 + vy * (double)distance );
Tom