I have been working on Unigine and been trying to code a flight program for weeks, I need to find the direction between two dummy nodes so I can use this direction to rotate the wings of the aircraft. Any explanation would be appreciated.
First you have to calculate the length of the distance between P1 and P2.
distance = abs(P2(y) - P1(y))
Then you can use the angular functions to calculate the angle.
a = sin(distance / length(P12))
As already stated in the comments, the vector from P1 to P2 is given by P = P2 - P1.
The direction can be attained in two ways.
1. Directly compute angle = tan_inverse( P.y() / P.x() ).
In this method however, 1st quadrant and 3rd quadrant are treated in the same way as the signs cancel out.
2.You can normalize this vector to get a unit vector. This is the preferred way since it alleviates the quadrant issues.
P(normalized) = P / (mod(p))
Now you can get the projection of any vector in this direction by just calculating the dot-product by this unit vector.
I just randomly came across this question and therefore it might be useful for someone else to read some more useful information here, regardless of the fact that this question has been asked years ago.
Currently, there is no accepted answer, which could mean that it wasn't very clear what the OP was asking so I'll confront two problems here.
Finding the direction of a vector
I am not very fluent in C++ so I'll
go one abstraction below and write C. Consider the following function
double get_vector_direction (vector v)
{
return atan2(v.q.y - v.p.y, v.q.x - v.p.x); /* atan(ratio) */
}
As simple as this! Also, I like to define vectors this way:
typedef struct POINT { double x, y; } point;
typedef struct VECTOR { point p, q; } vector;
the atan family of functions returns the inverse tangent and this function returns the direction of a vector, which is the measure of the angle it makes with a horizontal line (in radians).
There is a diagram in the answers here that shows the horizontal line as the x component of a vector. It's a simplistic implementation of a Cartesian to Polar coordinates conversion.
Finding the distance between the initial and terminal point
You may also want to know the magnitude of the vector, which could be obtained using the distance formula: sqrt(pow(v.q.x-v.p.x, 2)+pow(v.q.y-v.p.y, 2));
The two functions make up direction() and distance() which are the two most essential functions when dealing with algebra during game development. I would also recommend vectoradd and maybe even vectorsub and of course, radtodeg to convert radians to degrees if the angle is to be showed to the player.
If under the direction you mean angle w.r.t. an arbitrary vector (let it be (p1,p3)), then you can calculate the angle using:
angle = arcos( (p1,p2) * (p1,p3) / (modulus((p1,p2)) * modulus((p1,p3)) ))
where * is the dot product. The angle will be in radians. To change it to degrees you can multiply it by 180/PI (PI=3.1415926...). Modulus is length of vector:
modulus((p1,p2))=square root((p1,p2) * (p1,p2)).
The answer is rather about math than C++ but the implementation of the simple formula is straightforward.
Related
I do not know how to approach this math problem. Any hint would be much appreciated. Before I could solve such problem using Atan2 method to get two vector angles, when axes c and a are orthogonal.
Problem: there are two non orthogonal to each other vectors c and a. I need to rotate one time around vector c then around vector a to obtain vector v orientation.
Question: how can I get c and a vector rotations, when I only know vector v orientation?
In the image below, c and a vector rotations are both 0.
I was using atan2 for orthogonal system to get two rotations, but in this cases axis A is not perpendicular to C.
double RotationC = Math.Atan2(V_.X, V_.Y);
double RotationA = Math.Atan2(Math.Sqrt(V_.X * V_.X + V_.Y * V_.Y), V_.Z);
I am creating a Discrete Element Method simulation program and I am using CGAL to describe the polyhedrons. From reading literature I was planning to do my differential equations for rotation with Quaternions due to the better numerical stability and lack of gimbal lock. However CGAL does not seem to support rotation based on quaternions. (Please tell me if I am incorrect here) I find it a bit surprising that this seems to be missing, certainly since CGAL likes to be absolute in its accuracy which seems to fit well with the numerical stability of quaternions.
Question: Can I somehow combine Boost Quaternions with CGAL or is there any easy way to implement this. And if so, would this be a logical idea to try?
The other options I think I have are:
writing my differential equations for the affine rotation used is CGAL and deal with the downsides there.
store the orientation as an affine rotation matrix and convert it to Quaternions and use this in the diff. equations. Obviously I am worried about the needed conversion step here every timestep.
Any suggestions or other options that I might think of are greatly appreciated.
First Option: Use the Aff_transformation_3 class
CGAL does not provide a quaternion class, it does provide the Aff_transformation_3 class though. Which you could easily use like this:
CGAL::Surface_mesh<Kernel> P;
std::transform( P.points_begin(), P.points_end(), P.points_begin(), yourAffineTransformation);
for defining the transformation matrix see this.
Second Option: Use Quaternions
If you want to use quaternions you would need to construct one with an external library. For example you could use Eigen:
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h> //or whichever kernel suits your needs
#include <CGAL/Surface_mesh.h>
#include <Eigen/Geometry>
using Kernel = CGAL::Exact_predicates_inexact_constructions_kernel;
using Polyhedron = CGAL::Surface_mesh<Kernel>;
using Point = CGAL::Point_3<Kernel>;
// define the function that rotates your mesh
template <typename Vect, typename Quaternion>
void rotateCGALPolyhedron(Polyhedron P, Vect to_rotation_center,
Quaternion quat) {
for (auto vi : P.vertices()) {
Point p = P.point(vi);
// translate your point to the rotation center. In your case this would be
// the center of mass of the Polyhderon
Vect V(p[0] - to_rotation_center[0], p[1] - to_rotation_center[1],
p[2] - to_rotation_center[2]);
// construct the translation vector that moves your point to the rotated
// position
Vect v = quat * V; //the Vect operator*(Quaternion, Vect) must be implemented!! If you use Eigen::Quaternion you could use Eigen::Vector3d
// retranslate the point back to its initial position and translate it using
// the previously created translation vector
P.point(size_t(vi)) =
Point(to_rotation_center[0] + v[0], to_rotation_center[1] + v[1],
to_rotation_center[2] + v[2]);
}
}
int main() {
// define your rotation using eigen's quaternion class
Eigen::Quaternion<double> quad(..);
Eigen::Vector_3d centerOfMass; //find the center of mass of the mesh you want to rotate
rotateCGALPolyhedron(P.vertices.begin(), P.vertices.end(), centerOfMass,
quad);
return 0;
}
As you can see since cgal does not have an implementation for quaternions if you want to use quaternions the code is lengthy compared to the Aff_transformation_3 case.
I got a vector with n rows with xy coordinates of points. These points form a conture of an given CAD model. Now I want to restore the conture of the model. So I tried to sort the point with the atan2 function.
This is the code I use to sort the points.
std::sort(matrix.begin(), matrix.end(), sort1);
matrix.erase(std::unique(matrix.begin(), matrix.end(), compare2),matrix.end());
matrix.push_back(std::vector<double>(3, 0));
So first I sort the points in the vector matrix. As compare function i use this code
bool sort1(vector<double> const& s1, vector<double> const& s2)
{
return atan2(s1[1],s1[0])<atan2(s2[1],s2[0]);
}
After the vector has been sorted, I just delete duplicates to reduce the size of the vector. The last step is to push back the first point to the end of the vector to close the conture.
For standard models like a cube, or a ball this works fine, but for more complicate models the atan2 function is note working fine.
So this image show the unsorted points.
When I sort the vector I get this conture as result
My first approach was to check the atan2 function but it's working fine. The problem seem to be the result of the atan2 function. So this list shows the actual coordinates and the result of the atan2 function
x y z atan2
-5.44283 -1.94995 0 -2.79758
-5.36969 -1.93228 0 -2.79617
-5.33637 -1.92454 0 -2.79547
-13.15 -4.76500 0 -2.79395
-5.26308 -1.90750 0 -2.79389
-5.22970 -1.90005 0 -2.7931
-5.15626 -1.88364 0 -2.79134
As you can see while the x and y coordinate change the atan2 stays in the same range as the other values. For me that's the problem, why my conture isn't correct. Do I have to add something to my sort function to get the correct results?
One idea i had was to sort the coordinates not just by the atan2, but also by the length of the vector between the point, with the lowest atan2, and all other points. But here's my problem. I would first sort by atan2, and then sort again by the length. But the second sort process would destroy the hole result of the first sort function.
atan2 obviously won't help in generic case. It is mostly good for convex figures. Consider a narrow rectangle with (0,0) inside and an adjacent rectangle and try to sort their points by their atan2.
Have you tried painting a point in the set and then looking for the closest not yet painted point as an iteration step?
If you're dealing with curves only then I'd suggest to use following algorithm:
Define angle range R
Take initial point A, mark it as visited
Find closest to A point B, mark it as visited
Calculate the direction formed by vector [A, B]
Find closest to B unvisited point C in angle range R and mark it visited
Go to step 4 with B as A and C as B
This is not an ultimate solution but it should be able to find basic curves and some polygons. With wider angle range R you can approximate more curved lines.
I am in a lost. I have been trying to implement this code at:http://www.blackpawn.com/texts/pointinpoly/default.html
However, I don't know how is it possible that the cross-product present there between two 2D vectors can result also in a 2D vector. It does not make sense to me. That is also present in some examples of intersection between polygons and lines, in the fine book "Realtime Collision Detection" - where even scalar triples between 2D vectors appear in the codes (see page 189, for instance).
The issue is that, as far as I can think of it, the pseudo cross-product of two 2D vectors can only result in a scalar (v1.xv2.y-v1.yv2.x) or at most in a 3D vector if one adds two zeros, since that scalar represents the Z dimension. But how can it result in a 2D vector?
I am not the first one to ask this and, coincidently, when trying to use the same code example: Cross product of 2 2D vectors However, as can be easily seen, the answer, the original question when updated and the comments in that thread ended up being quite a mess, if I dare say so.
Does anyone know how should I get these 2D vectors from the cross-product of two 2D vectors? If code is to be provided, I can handle C#, JavaScript and some C++.
EDIT - here is a piece of the code in the book as I mentioned above:
int IntersectLineQuad(Point p, Point q, Point a, Point b, Point c, Point d, Point &r)
{
Vector pq = q - p;
Vector pa = a - p;
Vector pb = b - p;
Vector pc = c - p;
// Determine which triangle to test against by testing against diagonal first
Vector m = Cross(pc, pq);
float v = Dot(pa, m); // ScalarTriple(pq, pa, pc);
if (v >= 0.0f) {
// Test intersection against triangle abc
float u = -Dot(pb, m); // ScalarTriple(pq, pc, pb);
if (u < 0.0f) return 0;
float w = ScalarTriple(pq, pb, pa);
....
For the page you linked, it seems that they talk about a triangle in a 3d space:
Because the triangle can be oriented in any way in 3d-space, ...
Hence all the vectors they talk about are 3d vectors, and all the text and code makes perfect sense. Note that even for a 2d vectors everything also makes sense, if you consider a cross product to be a 3d vector pointing out of screen. And they mention it on the page too:
If you take the cross product of [B-A] and [p-A], you'll get a vector pointing out of the screen.
Their code is correct too, both for 2d and 3d cases:
function SameSide(p1,p2, a,b)
cp1 = CrossProduct(b-a, p1-a)
cp2 = CrossProduct(b-a, p2-a)
if DotProduct(cp1, cp2) >= 0 then return true
else return false
For 2d, both cp1 and cp2 are vectors pointing out of screen, and the (3d) dot product is exactly what you need to check; checking just the product of corresponding Z components is the same. If everything is 3d, this is also correct. (Though I would write simply return DotProduct(cp1, cp2) >= 0.)
For int IntersectLineQuad(), I can guess that the situation is the same: the Quad, whatever it is, is a 3d object, as well as Vector and Point in code. However, if you add more details about what is this function supposed to do, this will help.
In fact, it is obvious that any problem stated in 2d can be extended to 3d, and so any approach which is valid in 3d will also be valid for 2d case too, you just need to imagine a third axis pointing out of screen. So I think this is a valid (though confusing) technique to describe a 2d problem completely in 3d terms. You might yourself doing some extra work, because some values will always be zero in such an approach, but in turn the (almost) same code will work in a general 3d case too.
I have a vector v = <0,0,-1> and four other vectors that form a "square" at z-index of -1 with side length 2*s, such that the four vectors are:
OA = <-s, s, -1>
OB = < s, s, -1>
OC = <-s,-s, -1>
OD = < s,-s, -1>
Now, consider point P anywhere in the 3D space.
I want to rotate v in such a way that it aligns with the position vector OP of point P, and then apply rotations to the other four vectors such that all four vectors stick together in the same relative position from v.
In other words, the whole "pyramid" of vectors needs to be rotated so that v and OP align.
Screenshot of scenario.
The point P is arbitrary and can be any point in the 3D space. Any help is greatly appreciated!
I don't know if this is to late to answer since you are moving the question, but your question is quite heavily used in 3D graphics work. You should look at the wikipedia article for Rotation Matrix and a good article Rotation About an Arbitrary Axis in 3D. Both of those should give you the understanding of how to manipulate a vector or matrix in 3D.
If I understood the question correctly, you want to rotate your shape ABCD around the point O with the constraint that (OP) and (OV) are aligned.
I think of one way to simply do that algorithmitically without the need to compute any transformations or rotations. Let V',A',B',C',D' be your new points.
1/
Place a point V' such that :
--> ||VO|| -->
V'O = ------ . OP
||OP||
This should not be hard since you know O, P, and V.
2/
Vectors V'O or OP are normal to the plane A',B',C',D'. So you can place the latter points on this plane so that they form a square and include V' as a middle. Some maths are needed here (if interested I can deepen the explanations).
Hope you are allowed to do it this way.
As commented before you better ask maybe http://scicomp.stackexchange.com for nice mathematical solutions.