Shift set of points in 3d - c++

I have a set of points in 3d. I form a line by joining these points. I have to obtain another line which is a shifted version of this line, such that the resultant shift is always to the right of the original line. What would be an approach to solve this problem? How to get the up vectors in the right direction each time?
Assume these points to lie on a sphere. Looking at the top view of the sphere i would want something like this
/\/\/\/\
/\/\/\/\
The first line is the original set of points and the second one the shifted set
Ok i am adding the code
std::vector<osg::Vec3> vertArray; // The array containig the 3d points
std::vector<osg::Vec3> shiftVec; // The array to store the shifted vectors
osg::Vec3 line1, line2, result, upVec, p1, p2, cross1, cross2;
result = vertArray[1] - vertArray[0];
result.normalise();
result = result X upVec; // i am not sure how to get this upvec for general set of points
shiftVec.push_back(result);
for(unsigned int i = 1; i < vertArray.size() - 1; i++)
{
line 1 = vertArray[i-1] - vertArray[i];
line 2 = vertArray[i+1] - vertArray[i];
line1.normalise();
line2.normalise();
upVec = line1 X line2;
line 1 = line1 X upVec;
p1 = vertArray[i-1] + line1;
line 2 = line2 X upVec;
p2 = vertArray[i+1] + line2;
cross1 = upVec;
cross2 = (p2-p1)X line2
float factor = cross2.lenght()/cross1.length();
result = p1+line1*factor;
result = result - vertArray[i];
shiftVec.push_back(result);
}
result = vertArray[i] - vertArray[i-1];
result.normalise();
result = result X upVec; // i am not sure how to get this upvec for general set of points
shiftVec.push_back(result);

look here: ECEF <-> ENU coordinates this might help
I rather use NEH local North,East,Height(or altitude) coordinate system
it is similar to compass + altimeter
if you are not looking in rotation axis direction (ECEF Z-axis) ... on poles
then North vector is just (0,0,6356754.7)-viewer_position (all in ECEF)
East,West vectors can be obtained as North x (0,0,6356754.7)
don`t remember if it is east or west (depends on your coordinate system and cross multiplicants order)
just check it visually and if wrong reverse the order or negate result
Up vector (Height or Altitude) is easy from this just Up=North x East or Up=North x West
again if wrong direction reverse order or negate result ...
[Notes]
6356754.7 [m] is earths polar radius
if you viewing from poles (ECEF Z-axis)
then North vector and Up vector lies on the same axis (in opposite direction)
which means there is no east or west (singularity)
on south hemisphere is usually used South instead of North
in that case South = (0,0,-6356754.7)-viewer_position

If you three points are A, B and C. Then the three point define a plane. In general the points will not lie on a (straight) line. If they do then it becomes ambiguous what "right" means. If everything is on a sphere, then the three points will define a curve formed by the intersection of the sphere and the plane. You could form another line my finding the intersection of the sphere with a parallel plane.
I'm not quite sure what you want but I'm guessing you want the second line to lie in a parallel plane. You can find the normal to the plane by taking the cross product N=(A-B) X (C-B). It looks like you are doing something like this but you need the ^ operator. See https://www8.cs.umu.se/kurser/TDBD12/VT04/lab/osg/html/doc++/osg/Vec3.html#DOC.2.224.21
upVec = line1 ^ line2;

Related

OpenGl Rotate object on Y axis to look at another object

So like in a topic I got 2 objects one i moving around (on z and x axis) the other one is static but should rotate around y axis to always like a look at the other... and i am fighting with this already a week
what i got now is
vector from 1object to 2object and actual look at(also vector) of the 2object
i'am calculating angel betwean this two vectors and adding this to rotattion.y of the 2 object but its not working properly
any idea how to make it work? btw i'am using eular angel transforms
pseudCode:
vectorFrom1to2 = vector1 - vector2;
lookatVectorof2ndObject;
i normalize both of them and then
float angle = acos(dot(vectorFrom1to2, lookatVectorof2ndObject));
object2.rotateY = angle;
i dont know where i do mistake
As a general rule of thumb, which proved itself true in many situations I observed is: As soon as you find yourself calculating angles from vectors, you are most likely doing something in a more unnecessarily complicated way than necessary.
All you need is a basis transformation which transforms the first object's local coordinate system to make its local Z axis point towards the second object. You can do this with a simple rotation matrix (provided you have a matrix/vector library ready to facilitate this more easily).
So, provided you have object 1 with position p1 and object 2 with position p2 and you want p1 to rotate towards p2, then the rotation matrix can be obtained as follows:
(I am just using GLSL pseudo syntax here)
vec3 p1 = ... // <- position of first object
vec3 p2 = ... // <- position of second object
vec3 d = normalize(p2 - p1)
vec3 r = cross(vec3(0.0, 1.0, 0.0), d)
= vec3(d.z, 0, -d.x)
mat3 m = mat3(d.z, 0, -d.x, // <- first column ('right' vector)
0, 1, 0, // <- second column (keep Y)
d.x, 0, d.z) // <- third column (map Z to point towards p2)
When transforming the vertices v of the first object with m by: v' = m * v you get the Z axis of object p1 to point towards the position of p2, all formulated in the same "world" coordinate system.

Set the orientation of objects in 3d space

I have program in which I am drawing some shapes such as rectangle/circle/triangle etc. in 3D space, equidistant from the centre.
Example of two points which are equidistant from the centre (0,0,0) are
x1: 93, 313, 123
x2: -263, -135, -186
and there may be more points as well.
At these two points, I am drawing the shapes by something like
glRectangle(x1, width, height);
The shapes (rectangles/triangles etc.) come out very well at the starting vertex (x1 or x2) equi-distant from the centre. However, the shapes have wrong orientation in space as to what I am looking for.
I want centre of the plane of in which the shape lies to to be prependicular to an imaginary line coming from the centre. This probably can be solved by rotation of the plane but I am not sure about the approach to adopt. For the current example, let's say I have the vertex of the shape but how do I figure out the plane in which the the rectangle is and rotate that plane to make it prependicular (to the line coming from the centre of the space (0,0,0))
If the center needs to be perpendicular to the vector C (Line between coord-center and rect-center), it should work like this (pseudo-code):
A = C x UP_VECTOR (CROSS-PRODUCT to calculate helper vector pointing in "sideway" direction of "rectangle")
B = C x A (CROSS-PRODUCT to get the local "up/down" vector of the "rectangle")
A = normalize(A)
B = normalize(B)
P1 = width/2 * A + height/2 * B
P2 = -width/2 * A + height/2 * B
P3 = -width/2 * A + -height/2 * B
P4 = width/2 * A + -height/2 * B
Hopefully this is understandable and right (didn't try it and had some trouble finding the right vocabulary)
Some additional informations:
A and B are helper vectors and are the local up and left directions on the rectangle, after normalizing they can be used to calculate the 4 points of the rectangle accordingly.
Also be careful if no rectangle is displayed it's probably related to the drawing order so just reverse the order then if front and backfaces are wrong...

Check if the line goes through wall on 2D map

I have 2d map and I want to check if line collides with any element. I need a function that can tell me if the line intersect any object on its way.
Take a look:
Red lines are not correct (function should return false), and green are (return true).
My collision map is map of boolean with 1 for wall and 0 for empty space.
How to this? I've read that I need to check if the line intersect any wall, but i have completely no idea how to do this on 2d map.
Thanx for any replies.
It depends on how your walls are represented.
If they are rectangle, then look for the line/segment intersection between your line and the 4 segments representing the rectangle.
If they are pixels, you can use the bresenham line algorithm to see if the pixels on the line are on these blocks.
If your walls are represented as line-segments you could test for intersection of line-segments as Paul Bourke describes: http://local.wasp.uwa.edu.au/~pbourke/geometry/lineline2d/
If your walls are represented as polygons you could clip your test line against the wall polygon and see if the clipping result is non-empty as Paul Bourke describes: http://local.wasp.uwa.edu.au/~pbourke/geometry/cliplinetopoly/
So, I imagined that your cells are squares... let say they're unit squares. So, if I have any coordinate, for a point like , which are floats or doubles, they are in cell .
you need to know in which cells are the endpoints of the line
walk straight from one endpoint to the other and for each cell, test if it's a wall or not
return false when a wall is found, true otherwise.
To walk from one endpoint to the other, you need to compute the delta of each axis (call delta_x and delta_y, those values are 'int' because we're talking cells here), i.e. the number of cells it goes on the vertical and on the horizontal. You take the largest of the two. You will use that largest value for your loop. Let say it's this value is D = max(delta_x, delta_y) and XX and YY are the coordinate of the cell of one endpoint.
float step = 1.0f / D;
float current_location = 0.0;
for (int i = 0; i <= D; ++i, current_location += step)
{
int cur_x = XX + current_location * delta_x;
int cur_y = YY + current_location * delta_y;
if (intersect_wall(cur_x, cur_y))
return false;
}
return true;
That's it... adapt this to your functions.

Calculating a line from a starting point and angle in 3d

I have a point in 3D space and two angles, I want to calculate the resulting line from this information. I have found how to do this with 2D lines, but not 3D. How can this be calculated?
If it helps: I'm using C++ & OpenGL and have the location of the user's mouse click and the angle of the camera, I want to trace this line for intersections.
In trig terms two angles and a point are required to define a line in 3d space. Converting that to (x,y,z) is just polar coordinates to cartesian coordinates the equations are:
x = r sin(q) cos(f)
y = r sin(q) sin(f)
z = r cos(q)
Where r is the distance from the point P to the origin; the angle q (zenith) between the line OP and the positive polar axis (can be thought of as the z-axis); and the angle f (azimuth) between the initial ray and the projection of OP onto the equatorial plane(usually measured from the x-axis).
Edit:
Okay that was the first part of what you ask. The rest of it, the real question after the updates to the question, is much more complicated than just creating a line from 2 angles and a point in 3d space. This involves using a camera-to-world transformation matrix and was covered in other SO questions. For convenience here's one: How does one convert world coordinates to camera coordinates? The answers cover converting from world-to-camera and camera-to-world.
The line can be fathomed as a point in "time". The equation must be vectorized, or have a direction to make sense, so time is a natural way to think of it. So an equation of a line in 3 dimensions could really be three two dimensional equations of x,y,z related to time, such as:
x = ax*t + cx
y = ay*t + cy
z = az*t + cz
To find that set of equations, assuming the camera is at origin, (0,0,0), and your point is (x1,y1,z1) then
ax = x1 - 0
ay = y1 - 0
az = z1 - 0
cx = cy = cz = 0
so
x = x1*t
y = y1*t
z = z1*t
Note: this also assumes that the "speed" of the line or vector is such that it is at your point (x1,y1,z1) after 1 second.
So to draw that line just fill in the points as fine as you like for as long as required, such as every 1/1000 of a second for 10 seconds or something, might draw a "line", really a series of points that when seen from a distance appear as a line, over 10 seconds worth of distance, determined by the "speed" you choose.

Simple line-plane intersection on a fixed z-axis?

What is, and is there, a fast way to check where in the plane my line will intersect, if i know the plane is always in the same z-axis (so it cannot be rotated), and its width/height is infinite? Also, my "line" isn't actually a line, but a 3d vector, so the "line" can go to infinite distance.
Here is the code that relies on two points:
(p1 and p2 are start and end points of the line. plane_z = where the plane is)
k1 = -p2.z/(p1.z-p2.z-plane_z);
k2 = 1.0f-k1;
ix = k1*p1.x + k2*p2.x;
iy = k1*p1.y + k2*p2.y;
iz = plane_z; // where my plane lays
Another solution which works with a vector (i made it use two points as the first example did too, "p2.x-p1.x" etc. is the vector calculation):
a = (plane_z-p1.z)/(p2.z-p1.z);
ix = p1.x + a*(p2.x-p1.x);
iy = p1.y + a*(p2.y-p1.y);
iz = plane_z;
Edit3: added Orbling's solution which is slightly faster, and doesnt rely on two points necessarily.
You can implement a strait-forward solution like there http://paulbourke.net/geometry/planeline/, then apply your simplifications. In the algebraic solution (#2) A and B are zeros in your case (if i understand correctly this statement)
plane is always in the same z-axis (so it cannot be rotated)
Note: your line should be a point and a direction, or two points right?