Suppose that I have the following chart -- https://www.desmos.com/calculator/eabskyo0hk
I need to do the following:
Determine whether apex (endpoint1), dest (newvertex) and endpoint1
are collinear.
If they are not collinear, find their intersection point.
I wrote the following code to do that -- http://coliru.stacked-crooked.com/a/c08cbe113e706a9c
Unfortunately, it doesn't work properly. It says that those points are not collinear but then it says that their intersection point is dest (newvertex) so that invalidates the first statement.
I suppose that this must be due to the floating point-related issues but I wonder how can I fix it w/o changing the coordinates?
Thanks in advance.
Your coordinate values have very large magnitude, so comparison of cross-product magnitude with std::numeric_limits<T>::epsilon() gives false result.
Edit: std::numeric_limits<T>::epsilon() is not suitable as "small value here".
You can try to scale "small value" accordingly to coordinates. Example:
my_eps = 1.0E-9;
eps = my_eps * Max(abs(x1), abs(y1)....
Note that small difference of two big values already contains large relative error, so next approach is wrong:
eps = my_eps * Max(abs(y1 - y2), abs(x1 - x3), abs(y1 - y3), abs(x1 - x2));
Described method should improve result, but won't provide "silver bullet" - there are special computational methods for robust, error-prone intersection calculations (problem is global). Example - orientation test
Related
I am trying to make a sprite walk towards another sprite,
movement_angle = (atan2((y - target->y),(x - target->x)));
if(isWalkable(game,delta))
{
y -= ((int)(movementspeed)*delta)*sin(((movement_angle)));
x -= ((int)(movementspeed)*delta)*cos(((movement_angle)));
}
I am calculating the angle and adding the values to my x and y cords.
But the movement is not perfect, it does not really follow as I wish, takes weird turns and so on.
It's hard to say exactly what's going wrong from your code, but here are some things you could look at:
To get a vector from a point to target you'll need to subtract target->x by the point's x and target->y by the point's y
At least movement_angle needs to be a floating point number, though you'll likely want to use doubles for all your 3D geometry values
Why bother with trigonometric functions? You want to walk directly from point x, y to target->x, target->y, why not just use a vector, normalize it, and multiply by your movementspeed and delta?
Well you are casting an algebraic result to an int. I think that may be causing your problem.
I'm struggling to make sense of the spectral clustering documentation here.
Specifically.
If you have an affinity matrix, such as a distance matrix, for which 0 means identical elements, and high values means very dissimilar elements, it can be transformed in a similarity matrix that is well suited for the algorithm by applying the Gaussian (RBF, heat) kernel:
np.exp(- X ** 2 / (2. * delta ** 2))
For my data, I have a complete distance matrix of size (n_samples, n_samples) where large entries represent dissimilar pairs, small values represent similar pairs and zero represents identical entries. (I.e. the only zeros are along the diagonal).
So all I need to do is build the SpectralClustering object with affinity = "precomputed" and then pass the transformed distance matrix to fit_predict.
I'm stuck on the suggested transformation equation. np.exp(- X ** 2 / (2. * delta ** 2)).
What is X here? The (n_samples, n_samples) distance matrix?
If so, what is delta. Is it just X.max()-X.min()?
Calling np.exp(- X ** 2 / (2. * (X.max()-X.min()) ** 2)) seems to do the right thing. I.e. big entries become relatively small, and small entries relatively big, with all the entries between 0 and 1. The diagonal is all 1's, which makes sense, since each point is most affine with itself.
But I'm worried. I think if the author had wanted me to use np.exp(- X ** 2 / (2. * (X.max()-X.min()) ** 2)) he would have told me to use just that, instead of throwing delta in there.
So I guess my question is just this. What's delta?
Yes, X in this case is the matrix of distances. delta is a scale parameter that you can tune as you wish. It controls the "tightness", so to speak, of the distance/similarity relation, in the sense that a small delta increases the relative dissimmilarity of faraway points.
Notice that delta is proportional to the inverse of the gamma parameter of the RBF kernel, mentioned earlier in the doc link you give: both are free parameters which can be used to tune the clustering results.
In GLSL (specifically 3.00 that I'm using), there are two versions of
atan(): atan(y_over_x) can only return angles between -PI/2, PI/2, while atan(y/x) can take all 4 quadrants into account so the angle range covers everything from -PI, PI, much like atan2() in C++.
I would like to use the second atan to convert XY coordinates to angle.
However, atan() in GLSL, besides not able to handle when x = 0, is not very stable. Especially where x is close to zero, the division can overflow resulting in an opposite resulting angle (you get something close to -PI/2 where you suppose to get approximately PI/2).
What is a good, simple implementation that we can build on top of GLSL atan(y,x) to make it more robust?
I'm going to answer my own question to share my knowledge. We first notice that the instability happens when x is near zero. However, we can also translate that as abs(x) << abs(y). So first we divide the plane (assuming we are on a unit circle) into two regions: one where |x| <= |y| and another where |x| > |y|, as shown below:
We know that atan(x,y) is much more stable in the green region -- when x is close to zero we simply have something close to atan(0.0) which is very stable numerically, while the usual atan(y,x) is more stable in the orange region. You can also convince yourself that this relationship:
atan(x,y) = PI/2 - atan(y,x)
holds for all non-origin (x,y), where it is undefined, and we are talking about atan(y,x) that is able to return angle value in the entire range of -PI,PI, not atan(y_over_x) which only returns angle between -PI/2, PI/2. Therefore, our robust atan2() routine for GLSL is quite simple:
float atan2(in float y, in float x)
{
bool s = (abs(x) > abs(y));
return mix(PI/2.0 - atan(x,y), atan(y,x), s);
}
As a side note, the identity for mathematical function atan(x) is actually:
atan(x) + atan(1/x) = sgn(x) * PI/2
which is true because its range is (-PI/2, PI/2).
Depending on your targeted platform, this might be a solved problem. The OpenGL spec for atan(y, x) specifies that it should work in all quadrants, leaving behavior undefined only when x and y are both 0.
So one would expect any decent implementation to be stable near all axes, as this is the whole purpose behind 2-argument atan (or atan2).
The questioner/answerer is correct in that some implementations do take shortcuts. However, the accepted solution makes the assumption that a bad implementation will always be unstable when x is near zero: on some hardware (my Galaxy S4 for example) the value is stable when x is near zero, but unstable when y is near zero.
To test your GLSL renderer's implementation of atan(y,x), here's a WebGL test pattern. Follow the link below and as long as your OpenGL implementation is decent, you should see something like this:
Test pattern using native atan(y,x): http://glslsandbox.com/e#26563.2
If all is well, you should see 8 distinct colors (ignoring the center).
The linked demo samples atan(y,x) for several values of x and y, including 0, very large, and very small values. The central box is atan(0.,0.)--undefined mathematically, and implementations vary. I've seen 0 (red), PI/2 (green), and NaN (black) on hardware I've tested.
Here's a test page for the accepted solution. Note: the host's WebGL version lacks mix(float,float,bool), so I added an implementation that matches the spec.
Test pattern using atan2(y,x) from accepted answer: http://glslsandbox.com/e#26666.0
Your proposed solution still fails in the case x=y=0. Here both of the atan() functions return NaN.
Further I would not rely on mix to switch between the two cases. I am not sure how this is implemented/compiled, but IEEE float rules for x*NaN and x+NaN result again in NaN. So if your compiler really used mix/interpolation the result should be NaN for x=0 or y=0.
Here is another fix which solved the problem for me:
float atan2(in float y, in float x)
{
return x == 0.0 ? sign(y)*PI/2 : atan(y, x);
}
When x=0 the angle can be ±π/2. Which of the two depends on y only. If y=0 too, the angle can be arbitrary (vector has length 0). sign(y) returns 0 in that case which is just ok.
Sometimes the best way to improve the performance of a piece of code is to avoid calling it in the first place. For example, one of the reasons you might want to determine the angle of a vector is so that you can use this angle to construct a rotation matrix using combinations of the angle's sine and cosine. However, the sine and cosine of a vector (relative to the origin) are already hidden in plain sight inside the vector itself. All you need to do is to create a normalized version of the vector by dividing each vector coordinate by the total length of the vector. Here's the two-dimensional example to calculate the sine and cosine of the angle of vector [ x y ]:
double length = sqrt(x*x + y*y);
double cos = x / length;
double sin = y / length;
Once you have the sine and cosine values, you can now directly populate a rotation matrix with these values to perform a clockwise or counterclockwise rotation of arbitrary vectors by the same angle, or you can concatenate a second rotation matrix to rotate to an angle other than zero. In this case, you can think of the rotation matrix as "normalizing" the angle to zero for an arbitrary vector. This approach is extensible to the three-dimensional (or N-dimensional) case as well, although for example you will have three angles and six sin/cos pairs to calculate (one angle per plane) for 3D rotation.
In situations where you can use this approach, you get a big win by bypassing the atan calculation completely, which is possible since the only reason you wanted to determine the angle was to calculate the sine and cosine values. By skipping the conversion to angle space and back, you not only avoid worrying about division by zero, but you also improve precision for angles which are near the poles and would otherwise suffer from being multiplied/divided by large numbers. I've successfully used this approach in a GLSL program which rotates a scene to zero degrees to simplify a computation.
It can be easy to get so caught up in an immediate problem that you can lose sight of why you need this information in the first place. Not that this works in every case, but sometimes it helps to think out of the box...
A formula that gives an angle in the four quadrants for any value
of coordinates x and y. For x=y=0 the result is undefined.
f(x,y)=pi()-pi()/2*(1+sign(x))* (1-sign(y^2))-pi()/4*(2+sign(x))*sign(y)
-sign(x*y)*atan((abs(x)-abs(y))/(abs(x)+abs(y)))
hell-o guys!
well, I'm playing with random walks. Midpoint displacement gives some nice results, but I would like a random walk without walk loops, like the ones (in yellow) on this screen-hot :
My first idea to deal with that problem is to check for each segment if there is an intersection with all others segments, then to delete the walk loop between the both segments and bind at the interesection point. But for some walks, it would give a strange result, like that one :
where the yellow part is a loop, and we can see that a big part of the walk would be deleted if I do what I said.
Maybe another method would be to check, when the displacement of the midpoint is made, if the segments are interesecting. In case of there is an intersection, get another displacment. But it looks to become very time consuming quickly when the number of subdivisions rises...
So I would like to know if there is a way to avoid these loops
so... it's seems playing with the amplitudes of the random numbers is a good way to avoid overlaps :
the path without displacement is drawn in cyan. I didn't get overlaps with these displacments :
do{
dx = (D>0)? 0.5*sqrt((double)(rand()%D)) - sqrt((double)D)/2. : 0 ;
dz = (D>0)? 0.5*sqrt((double)(rand()%D)) - sqrt((double)D)/2. : 0 ;
}while(dx*dx+dz*dz>D);
where D is the squared distance between the two neibourers of the point we want to displace. The (D>0)? is needed to avoid some Floating Point Exception.
I am trying to find the 2D vector in a set that is closest to the provided angle from another vector.
So if I have v(10, 10) and I would like to find the closest other vector along an angle of 90 degrees it should find v(20, 10), for example. I have written a method that I think returns the correct bearing between two vectors.
float getBearing(
const sf::Vector2f& a, const sf::Vector2f& b)
{
float degs = atan2f(b.y - a.y, b.x - a.x) * (180 / M_PI);
return (degs > 0.0f ? degs : (360.0f + degs)) + 90.0f;
}
This seems to work okay although if I place one above another it returns 180, which is fine, and 360, which is just odd. Shouldn't it return 0 if it is directly above it? The best way to do that would be to check for 360 and return 0 I guess.
My problem is that I can't work out the difference between the passed angle, 90 degrees for example, and the one returned from getBearing. I'm not even sure if the returned bearing is correct in all situations.
Can anyone help correct any glaringly obvious mistakes in my bearing method and suggest a way to get the difference between two bearings? I have been hunting through the internet but there are so many ways to do it, most of which are shown in other languages.
Thanks.
If what you need is just to find the vectors nearest to a certain angle, you can follow #swtdrgn method; if, instead, you actually need to compute the angle difference between two vectors, you can exploit a simple property of the dot product:
where theta is the angle between the two vectors; thus, inverting the formula, you get:
I would suggest to take the two vectors that are being compared and do an unit dot product. The closest bearing should be greatest, 1 being the maximum (meaning the vectors are pointing to the same direction) and -1 being the minimum (meaning the vectors are pointing to opposite directions).
I have found a solution for now. I have spent a good few hours trying to solve this and I finally do it minutes after asking SO, typical. There may be a much better way of doing this, so I am still open to suggestions from other answers.
I am still using my bearing method from the question at the moment, which will always return a value between 0 and 360. I then get the difference between the returned value and a specified angle like so.
fabs(fmodf(getBearing(vectorA, vectorB) + 180 - angle, 360) - 180);
This will return a positive float that measures the distance in degrees between the bearing between two vectors. #swtdrgn's answer suggests using the dot product of the two vectors, this may be much simpler than my bearing method because I don't actually need the angle, I just need the difference.