Most accurate line intersection ordinate computation with floats? - c++

I'm computing the ordinate y of a point on a line at a given abscissa x. The line is defined by its two end points coordinates (x0,y0)(x1,y1). End points coordinates are floats and the computation must be done in float precision for use in GPU.
The maths, and thus the naive implementation, are trivial.
Let t = (x - x0)/(x1 - x0), then y = (1 - t) * y0 + t * y1 = y0 + t * (y1 - y0).
The problem is when x1 - x0 is small. The result will introduce cancellation error. When combined with the one of x - x0, in the division I expect a significant error in t.
The question is if there exist another way to determine y with a better accuracy ?
i.e. should I compute (x - x0)*(y1 - y0) first, and divide by (x1 - x0) after ?
The difference y1 - y0 will always be big.

To a large degree, your underlying problem is fundamental. When (x1-x0) is small, it means there are only a few bits in the mantissa of x1 and x0 which differ. And by extension, there are only a limted number of floats between x0 and x1. E.g. if only the lower 4 bits of the mantissa differ, there are at most 14 values between them.
In your best algorithm, the t term represents these lower bits. And to continue or example, if x0 and x1 differ by 4 bits, then t can take on only 16 values either. The calculation of these possible values is fairly robust. Whether you're calculating 3E0/14E0 or 3E-12/14E-12, the result is going to be close to the mathematical value of 3/14.
Your formula has the additional advantage of having y0 <= y <= y1, since 0 <= t <= 1
(I'm assuming that you know enough about float representations, and therefore "(x1-x0) is small" really means "small, relative to the values of x1 and x0 themselves". A difference of 1E-1 is small when x0=1E3 but large if x0=1E-6 )

You may have a look at Qt's "QLine" (if I remember it right) sources; they have implemented an intersection determination algorithm taken from one the "Graphics Gems" books (the reference must be in the code comments, the book was on EDonkey a couple of years ago), which, in turn, has some guarantees on applicability for a given screen resolution when calculations are performed with given bit-width (they use fixed-point arithmetics if I'm not wrong).

If you have the possibility to do it, you can introduce two cases in your computation, depending on abs(x1-x0) < abs(y1-y0). In the vertical case abs(x1-x0) < abs(y1-y0), compute x from y instead of y from x.
EDIT. Another possibility would be to obtain the result bit by bit using a variant of dichotomic search. This will be slower, but may improve the result in extreme cases.
// Input is X
xmin = min(x0,x1);
xmax = max(x0,x1);
ymin = min(y0,y1);
ymax = max(y0,y1);
for (int i=0;i<20;i++) // get 20 bits in result
{
xmid = (xmin+xmax)*0.5;
ymid = (ymin+ymax)*0.5;
if ( x < xmid ) { xmax = xmid; ymax = ymid; } // first half
else { xmin = xmid; ymin = ymid; } // second half
}
// Output is some value in [ymin,ymax]
Y = ymin;

I have implemented a benchmark program to compare the effect of the different expression.
I computed y using double precision and then compute y using single precision with different expressions.
Here are the expression tested:
inline double getYDbl( double x, double x0, double y0, double x1, double y1 )
{
double const t = (x - x0)/(x1 - x0);
return y0 + t*(y1 - y0);
}
inline float getYFlt1( float x, float x0, float y0, float x1, float y1 )
{
double const t = (x - x0)/(x1 - x0);
return y0 + t*(y1 - y0);
}
inline float getYFlt2( float x, float x0, float y0, float x1, float y1 )
{
double const t = (x - x0)*(y1 - y0);
return y0 + t/(x1 - x0);
}
inline float getYFlt3( float x, float x0, float y0, float x1, float y1 )
{
double const t = (y1 - y0)/(x1 - x0);
return y0 + t*(x - x0);
}
inline float getYFlt4( float x, float x0, float y0, float x1, float y1 )
{
double const t = (x1 - x0)/(y1 - y0);
return y0 + (x - x0)/t;
}
I computed the average and stdDev of the difference between the double precision result and single precision result.
The result is that there is none on the average over 1000 and 10K random value sets. I used icc compiler with and without optimization as well as g++.
Note that I had to use the isnan() function to filter out bogus values. I suspect these result from underflow in the difference or division.
I don't know if the compilers rearrange the expression.
Anyway, the conclusion from this test is that the above rearrangements of the expression have no effect on the computation precision. The error remains the same (on average).

Check if the distance between x0 and x1 is small, i.e. fabs(x1 - x0) < eps. Then the line is parallell to the y axis of the coordinate system, i.e. you can't calculuate the y values of that line depending on x. You have infinite many y values and therefore you have to treat this case differently.

If your source data is already a float then you already have fundamental inaccuracy.
To explain further, imagine if you were doing this graphically. You have a 2D sheet of graph paper, and 2 point marked.
Case 1: Those points are very accurate, and have been marked with a very sharp pencil. Its easy to draw the line joining them, and easy to then get y given x (or vice versa).
Case 2: These point have been marked with a big fat felt tip pen, like a bingo marker. Clearly the line you draw will be less accurate. Do you go through the centre of the spots? The top edge? The bottom edge? Top of one, bottom of the other? Clearly there are many different options. If the two dots are close to each other then the variation will be even greater.
Floats have a certain level of inaccuracy inherent in them, due to the way they represent numbers, ergo they correspond more to case 2 than case 1 (which one could suggest is the equivalent of using an arbitrary precision librray). No algorithm in the world can compensate for that. Imprecise data in, Imprecise data out

How about computing something like:
t = sign * power2 ( sqrt (abs(x - x0))/ sqrt (abs(x1 - x0)))
The idea is to use a mathematical equivalent formula in which low (x1-x0) has less effect.
(not sure if the one I wrote matches this criteria)

As MSalters said, the problem is already in the original data.
Interpolation / extrapolation requires the slope, which already has low accuracy in the given conditions (worst for very short line segments far away from the origin).
Choice of algorithm canot regain this accuracy loss. My gut feeling is that the different evaluation order will not change things, as the error is introduced by the subtractions, not the devision.
Idea:
If you have more accurate data when the lines are generated, you can change the representation from ((x0, y0), (x1, y1)) to (x0,y0, angle, length). You could store angle or slope, slope has a pole, but angle requires trig functions... ugly.
Of course that won't work if you need the end point frequently, and you have so many lines that you can't store additional data, I have no idea. But maybe there is another representation that works well for your needs.
doubles have enough resolution in most situations, but that would double the working set too.

Related

Trying to use functions in c++ to calculate if a 2D vector is perpendicular to another

enter image description here
The picture contains what I've tried...I assume something might be wrong in the normalize function but I'm not sure what.
Two vectors are perpendicular/orthogonal If their dot product is zero. You don't need to normalize anything. Here's a function that checks if two vectors are perpendicular:
int arePerpendicular(double x1, double y1, double x2, double y2)
{
double epsilon = 0.1;
double dot = x1 * x2 + y1 * y2;
if (abs(dot) < epsilon)
{
return 1;
}
return 0;
}
x1 and y1 are the first vector components, and x2 and y2 the second vector components. Also, epsilon is a threshold value, absolute values lesser than it are considered 0. This is necessary because an explicit == 0 check using floating point arithmetic is likely to fail due to the very nature of float and double. In fact, when comparing two floating point variables for equality you should find the absolute value of their difference and check if it's below a certain threshold.

Value type preventing calculation?

I am writing a program for class that simply calculates distance between two coordinate points (x,y).
differenceofx1 = x1 - x2;
differenceofy1 = y1 - y2;
squareofx1 = differenceofx1 * differenceofx1;
squareofy1 = differenceofy1 * differenceofy1;
distance1 = sqrt(squareofx1 - squareofy1);
When I calculate the distance, it works. However there are some situations such as the result being a square root of a non-square number, or the difference of x1 and x2 / y1 and y2 being negative due to the input order, that it just gives a distance of 0.00000 when the distance is clearly more than 0. I am using double for all the variables, should I use float instead for the negative possibility or does double do the same job? I set the precision to 8 as well but I don't understand why it wouldn't calculate properly?
I am sorry for the simplicity of the question, I am a bit more than a beginner.
You are using the distance formula wrong
it should be
distance1 = sqrt(squareofx1 + squareofy1);
instead of
distance1 = sqrt(squareofx1 - squareofy1);
due to the wrong formula if squareofx1 is less than squareofy1 you get an error as sqrt of a negative number is not possible in case of real coordinates.
Firstly, your formula is incorrect change it to distance1 = sqrt(squareofx1 + squareofy1) as #fefe mentioned. Btw All your calculation can be represented in one line of code:
distance1 = sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2));
No need for variables like differenceofx1, differenceofy1, squareofx1, squareofy1 unless you are using the results stored in these variables again in your program.
Secondly, Double give you more precision than float. If you need precision more than 6-7 places after decimal use Double else float works too. Read more about Float vs Double

See if a point lies on a line(vector)

I have currently the following line in my program. I have two other whole number variables, x and y.
I wish to see if this new point(x, y) is on this line. I have been looking at the following thread:
Given a start and end point, and a distance, calculate a point along a line
I've come up with the following:
if(x >= x1 && x <= x2 && (y >= y1 && y <= y2 || y <= y1 && y >= y2))
{
float vx = x2 - x1;
float vy = y2 - y1;
float mag = sqrt(vx*vx + vy*vy);
// need to get the unit vector (direction)
float dvx = vx/mag; // this would be the unit vector (direction) x for the line
float dvy = vy/mag; // this would be the unit vector (direction) y for the line
float vcx = x - x1;
float vcy = y - y1;
float magc = sqrt(vcx*vcx + vcy*vcy);
// need to get the unit vector (direction)
float dvcx = vcx/magc; // this would be the unit vector (direction) x for the point
float dvcy = vcy/magc; // this would be the unit vector (direction) y for the point
// I was thinking of comparing the direction of the two vectors, if they are the same then the point must lie on the line?
if(dvcx == dvx && dvcy == dvy)
{
// the point is on the line!
}
}
It doesn't seem to be working, or is this idea whack?
Floating point numbers have a limited precision, so you'll get rounding errors from the calculations, with the result that values that should mathematically be equal will end up slightly different.
You'll need to compare with a small tolerance for error:
if (std::abs(dvcx-dvx) < tolerance && std::abs(dvcy-dvy) < tolerance)
{
// the point is (more or less) on the line!
}
The hard part is choosing that tolerance. If you can't accept any errors, then you'll need to use something other than fixed-precision floating point values - perhaps integers, with the calculations rearranged to avoid division and other inexact operations.
In any case, you can do this more simply, without anything like a square root. You want to find out if the two vectors are parallel; they are if the vector product is zero or, equivalently, if they have equal tangents. So you just need
if (vx * vcy == vy * vcx) // might still need a tolerance for floating-point
{
// the point is on the line!
}
If your inputs are integers, small enough that the multiplication won't overflow, then there's no need for floating-point arithmetic at all.
An efficient way to solve this problem is to use the signed area of a triangle. When the signed area of the triangle created by points {x1,y1}, {x2,y2}, and {x,y} is near-zero, you can consider {x,y} to be on the line. As others have mentioned, picking a good tolerance value is an important part of this if you are using floating point values.
bool isPointOnLine (xy p1, xy p2, xy p3) // returns true if p3 is on line p1, p2
{
xy va = p1 - p2;
xy vb = p3 - p2;
area = va.x * vb.y - va.y * vb.x;
if (abs (area) < tolerance)
return true;
return false;
}
This will let you know if {x,y} lies on the line, but it will not determine if {x,y} is contained by the line segment. To do that, you would also need to check {x,y} against the bounds of the line segment.
First you need to calculate the equation of your line. Then see if this equation holds true for the values of x and y that you have. To calculate the equation of your line, you need to work out where it croses the y-axis and what its gradient is. The equation will be of the form y=mx+c where m is the gradient and c is the 'intercept' (where the line crosses the y-axis).
For float values, don't use == but instead test for small difference:
if (fabs(dvcx-dvx) < delta && fabs(dvcy-dvy) < delta)
Also, you don't really need the unit vector, just the tangent:
float originalTangent = (y2 - y1) / (x2 - x1);
float newTangent = (y - y1) / (x - x1);
if (fabs(newTangent - originalTangent) < delta) { ... }
(delta should be some small number that depends on the accuracy you are expecting.)
Given that (x, y) is actually a point, the job seems a bit simpler than you're making it.
You probably want to start by checking for a perfectly horizontal or vertical line. In those cases, you just check whether x falls between x1 and x2 (or y between y1 and y2 for vertical).
Otherwise you can use linear interpolation on x and see if it gives you the correct value for y (within some possible tolerance for rounding). For this, you'd do something like:
slope = (y2-y1)/(x2-x1);
if (abs(slope * (x - x1) - y) < tolerance)
// (x,y) is on the line
else
// (x,y) isn't on the line

Speed of quadratic curve

I'm writing a 2d game and I have birds in a camera-space. I want to make them fly. So, I generate 3 ~random points. First one is left-upper side, second: middle-bottom, third: right-upper.
As a result I have 180deg rotated triangle.
To move a bird through the curve's path I have a t-parameter which is increased in each frame (render loop) by some delta.
The problem is that in different curves birds have different speed. If the triangle is "wide" (1) they are more slowly, if it's stretched by Y-coordinate (2), the speed is very fast.
But I want to make speed equal at different curves. It's logically, that I have to change delta which is appended each frame for each curve.
I've tried to solve it like this:
Find the ~length of the curve by summing length of 2 vectors: P1P2 and P2P3.
Than I've defined the speed for 1 virtual meter per frame. A little pseudocode:
float pixelsInMeter = 92.f; // One virtual meter equals to this number of pixels
float length = len(P1P2) + len(P2P3)
float speed = 0.0003f; // m/frame
// (length * speed) / etalon_length
float speedForTheCurve = toPixels( (toMeters(length) * speed) / 1.f);
// ...
// Each frame code:
t += speedForTheCurve;
Vector2 newPos = BezierQuadratic(t, P1, P2, P3);
But birds anyway have different speed. What's wrong? Or maybe there is a better way.
The Bezier function you're using is a parametrized function with bounds [0...1]. You're mucking with the step-size, which is why you're getting crazy speeds. Generally speaking, the distance d is the dependent variable in the equation, which says to me that their speeds will be different based on the length of the curve.
Since speed is your dependent variable, we're going to vectorize your function by computing the step-size.
Check out this pseudocode:
P1 = (x1, y1)
P2 = (x2, y2)
P3 = (x3, y3)
int vec[100][2]
int getPoint(int p1, int p2, float stepSize) {
return p1 + (p2 - p1)*stepSize;
}
for (float i = 0.0; i < 1.0; i += 0.01 ) {
int newX = getPoint(getPoint(x1, x2, i), getPoint(x2, x3, i), i);
int newY = getPoint(getPoint(y1, y2, i), getPoint(y2, y3, i), i);
vec[iter++][0] = newX;
vec[iter][1] = newY;
}
You can get the delta values by performing a first difference but I don't think that's necessary. As long as you move all the birds the appropriate distance based on the step iteration they will all move different distances but they will start and end their trajectories identically.
From your equation, we can compute the pixel delta step size:
int pixelsToMove = toMeter(sqrt((x2 - x1)^2 + (y2 - y1)^2))/pixelsInMeter;
Which will give you the appropriate amount of pixels to move the bird. That way they'll all move different step sizes, but their speeds will be different. Does that make sense?
Or, try something like this (much harder):
Obtain the actual quadratic function of the three points you chose.
Integrate the quadratic between two xy rectangular coordinate
Convert computed length into pixels or whatever you're using
Obtain dependent variable speed so all curves finish at the same time.
Let's start with quadratic stuff:
y = Ax^2 + Bx + C where A != 0, so since you have three points, you will need three equations. Using algebra, you can solve for the contants:
A = (y3 - y2)/((x3 - x2)(x3 - x1)) - (y1 - y2)/((x1 - x2)(x3 - x1))
B = (y1 - y2 + A(x2^2 - x1^2))/(x1 - x2)
C = y1 - Ax1^2 - Bx1
Then you can use the formula above to obtain a closed-form arc length. Check this website out, wolfram will integrate it for you and you just have to type it:
Closed form solution for quadradic integration
Now that you've computed the arc length, convert actualArcLength to the speed or whatever unit you're using:
float speedForTheCurve = toPixels( (toMeters(actualArcLength) * speed) / 1.f);

Direct way of computing clockwise angle between 2 vectors

I want to find out the clockwise angle between 2 vectors(2D, 3D).
The clasic way with the dot product gives me the inner angle(0-180 degrees) and I need to use some if statements to determine if the result is the angle I need or its complement.
Do you know a direct way of computing clockwise angle?
2D case
Just like the dot product is proportional to the cosine of the angle, the determinant is proprortional to its sine. So you can compute the angle like this:
dot = x1*x2 + y1*y2 # dot product between [x1, y1] and [x2, y2]
det = x1*y2 - y1*x2 # determinant
angle = atan2(det, dot) # atan2(y, x) or atan2(sin, cos)
The orientation of this angle matches that of the coordinate system. In a left-handed coordinate system, i.e. x pointing right and y down as is common for computer graphics, this will mean you get a positive sign for clockwise angles. If the orientation of the coordinate system is mathematical with y up, you get counter-clockwise angles as is the convention in mathematics. Changing the order of the inputs will change the sign, so if you are unhappy with the signs just swap the inputs.
3D case
In 3D, two arbitrarily placed vectors define their own axis of rotation, perpendicular to both. That axis of rotation does not come with a fixed orientation, which means that you cannot uniquely fix the direction of the angle of rotation either. One common convention is to let angles be always positive, and to orient the axis in such a way that it fits a positive angle. In this case, the dot product of the normalized vectors is enough to compute angles.
dot = x1*x2 + y1*y2 + z1*z2 #between [x1, y1, z1] and [x2, y2, z2]
lenSq1 = x1*x1 + y1*y1 + z1*z1
lenSq2 = x2*x2 + y2*y2 + z2*z2
angle = acos(dot/sqrt(lenSq1 * lenSq2))
Edit: Note that some comments and alternate answers advise against the use of acos for numeric reasons, in particular if the angles to be measured are small.
Plane embedded in 3D
One special case is the case where your vectors are not placed arbitrarily, but lie within a plane with a known normal vector n. Then the axis of rotation will be in direction n as well, and the orientation of n will fix an orientation for that axis. In this case, you can adapt the 2D computation above, including n into the determinant to make its size 3×3.
dot = x1*x2 + y1*y2 + z1*z2
det = x1*y2*zn + x2*yn*z1 + xn*y1*z2 - z1*y2*xn - z2*yn*x1 - zn*y1*x2
angle = atan2(det, dot)
One condition for this to work is that the normal vector n has unit length. If not, you'll have to normalize it.
As triple product
This determinant could also be expressed as the triple product, as #Excrubulent pointed out in a suggested edit.
det = n · (v1 × v2)
This might be easier to implement in some APIs, and gives a different perspective on what's going on here: The cross product is proportional to the sine of the angle, and will lie perpendicular to the plane, hence be a multiple of n. The dot product will therefore basically measure the length of that vector, but with the correct sign attached to it.
To compute angle you just need to call atan2(v1.s_cross(v2), v1.dot(v2)) for 2D case.
Where s_cross is scalar analogue of cross production (signed area of parallelogram).
For 2D case that would be wedge production.
For 3D case you need to define clockwise rotation because from one side of plane clockwise is one direction, from other side of plane is another direction =)
Edit: this is counter clockwise angle, clockwise angle is just opposite
This answer is the same as MvG's, but explains it differently (it's the result of my efforts in trying to understand why MvG's solution works). I'm posting it on the off chance that others find it helpful.
The anti-clockwise angle theta from x to y, with respect to the viewpoint of their given normal n (||n|| = 1), is given by
atan2( dot(n, cross(x,y)), dot(x,y) )
(1) = atan2( ||x|| ||y|| sin(theta),  ||x|| ||y|| cos(theta) )
(2) = atan2( sin(theta), cos(theta) )
(3) = anti-clockwise angle between x axis and the vector (cos(theta), sin(theta))
(4) = theta
where ||x|| denotes the magnitude of x.
Step (1) follows by noting that
cross(x,y) = ||x|| ||y|| sin(theta) n,
and so
dot(n, cross(x,y))
= dot(n, ||x|| ||y|| sin(theta) n)
= ||x|| ||y|| sin(theta) dot(n, n)
which equals
||x|| ||y|| sin(theta)
if ||n|| = 1.
Step (2) follows from the definition of atan2, noting that atan2(cy, cx) = atan2(y,x), where c is a scalar. Step (3) follows from the definition of atan2. Step (4) follows from the geometric definitions of cos and sin.
Since one of the simplest and most elegant solutions is hidden in one the comments, I think it might be useful to post it as a separate answer.
acos can cause inaccuracies for very small angles, so atan2 is usually preferred. For the 3D case:
dot = x1 * x2 + y1 * y2 + z1 * z2
cross_x = (y1 * z2 – z1 * y2)
cross_y = (z1 * x2 – x1 * z2)
cross_z = (x1 * y2 – y1 * x2)
det = sqrt(cross_x * cross_x + cross_y * cross_y + cross_z * cross_z)
angle = atan2(det, dot)
Scalar (dot) product of two vectors lets you get the cosinus of the angle between them.
To get the 'direction' of the angle, you should also calculate the cross product, it will let you check (via z coordinate) is angle is clockwise or not (i.e. should you extract it from 360 degrees or not).
For a 2D method, you could use the law of
cosines and the "direction" method.
To calculate the angle of segment P3:P1
sweeping clockwise to segment P3:P2.
P1 P2
P3
double d = direction(x3, y3, x2, y2, x1, y1);
// c
int d1d3 = distanceSqEucl(x1, y1, x3, y3);
// b
int d2d3 = distanceSqEucl(x2, y2, x3, y3);
// a
int d1d2 = distanceSqEucl(x1, y1, x2, y2);
//cosine A = (b^2 + c^2 - a^2)/2bc
double cosA = (d1d3 + d2d3 - d1d2)
/ (2 * Math.sqrt(d1d3 * d2d3));
double angleA = Math.acos(cosA);
if (d > 0) {
angleA = 2.*Math.PI - angleA;
}
This has the same number of transcendental
operations as suggestions above and only one
more or so floating point operation.
the methods it uses are:
public int distanceSqEucl(int x1, int y1,
int x2, int y2) {
int diffX = x1 - x2;
int diffY = y1 - y2;
return (diffX * diffX + diffY * diffY);
}
public int direction(int x1, int y1, int x2, int y2,
int x3, int y3) {
int d = ((x2 - x1)*(y3 - y1)) - ((y2 - y1)*(x3 - x1));
return d;
}
If by "direct way" you mean avoiding the if statement, then I don't think there is a really general solution.
However, if your specific problem would allow loosing some precision in angle discretization and you are ok with loosing some time in type conversions, you can map the [-pi,pi) allowed range of phi angle onto the allowed range of some signed integer type. Then you would get the complementarity for free. However, I didn't really use this trick in practice. Most likely, the expense of float-to-integer and integer-to-float conversions would outweigh any benefit of the directness. It's better to set your priorities on writing autovectorizable or parallelizable code when this angle computation is done a lot.
Also, if your problem details are such that there is a definite more likely outcome for the angle direction, then you can use compilers' builtin functions to supply this information to the compiler, so it can optimize the branching more efficiently. E.g., in case of gcc, that's __builtin_expect function. It's somewhat more handy to use when you wrap it into such likely and unlikely macros (like in linux kernel):
#define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)
For 2D case atan2 can easily calculate angle between (1, 0) vector (X-axis) and one of your vectors.
Formula is:
Atan2(y, x)
So you can easily calculate difference of two angles relatively X-axis
angle = -(atan2(y2, x2) - atan2(y1, x1))
Why is it not used as default solution? atan2 is not efficient enough. Solution from the top answer is better. Tests on C# showed that this method has 19.6% less performance (100 000 000 iterations). It's not critical but unpleasant.
So, another info that can be useful:
The smallest angle between outer and inner in degrees:
abs(angle * 180 / PI)
Full angle in degrees:
angle = angle * 180 / PI
angle = angle > 0 ? angle : 360 - angle
or
angle = angle * 180 / PI
if (angle < 0) angle = 360 - angle;
A formula for clockwise angle,2D case, between 2 vectors, xa,ya and xb,yb.
Angle(vec.a-vec,b)=
pi()/2*((1+sign(ya))*
(1-sign(xa^2))-(1+sign(yb))*
(1-sign(xb^2))) +pi()/4*
((2+sign(ya))*sign(xa)-(2+sign(yb))*
sign(xb)) +sign(xa*ya)*
atan((abs(ya)-abs(xa))/(abs(ya)+abs(xa)))-sign(xb*yb)*
atan((abs(yb)-abs(xb))/(abs(yb)+abs(xb)))
just copy & paste this.
angle = (acos((v1.x * v2.x + v1.y * v2.y)/((sqrt(v1.x*v1.x + v1.y*v1.y) * sqrt(v2.x*v2.x + v2.y*v2.y))))/pi*180);
you're welcome ;-)