Vector Projection Confusion - vector

If I have a vector (0, 0, 9) and I want to project it onto the vector (0, 0.7, 0.7) shouldn't that give me a vector of (0, 9, 9).
I am using the following formula
Vector3.Dot (vector, normal) * normal.magnitude * normal;
which is returning (0, 0.45, 0.45). What have I missed, isn't the returned vector z suppose to end at the same z position as the projected vector. Like this

When you project a vector onto another vector, the result's magnitude is always less than or equal to the magnitude of the original vector.
Given a normalized vector u, project v onto u with the formula:
proju v = 〈u, v〉u
Or, in code,
Vector3.Dot(vector, normal) * normal
The result of projecting (0, 0, 9) onto (0, √1/2, √1/2) is (0, 4.5, 4.5).
Note that normal.magnitude is always 1, unless normal is not "normal" (in which case you named your variable wrong); and if it's not normal, you need to divide by the squared magnitude, not multiply.
Vector3.Dot(vector, direction) * direction
* (1.0 / direction.magnitude_squared)

Related

How to find 3D points coordinates in a perpendicular plane to a given vector

I have two points in a 3d space, one point is (x,0,z) and the other one is the origin (0,0,0), through those points there is a passing line with length L that is starting from the first point and continuing after the origin point, in the end of this line there is a perpendicular (to the line) flat board with dimensions of W x H, the line ends in the middle of this board.
Assume that x,z,L,H,W are given, I need a way to find all the 3D points coordinates where those points forming a pixels image over the board (meaning each point has a distance of 1 from its left, right, top, bottom neighboring points).
Attached a pretty ugly drawing :) I made trying to illustrate the problem (I marked the pixels points with two question marks but I need them all).
Thanks.
It is possible to define that plane. But there is no selected direction to build a grid uniquelly.
Let we choose OY direction as base (because normal has zero Y-component).
So we have:
Normal vector N = (xx, 0, zz) //I renamed values to avoid confusion with coordinate
variables
Unit normal vector n = (nx, 0, nz), where
nx = xx / Sqrt(xx*xx+zz*zz)
nz = zz / Sqrt(xx*xx+zz*zz)
Base point
B = (bx, 0, bz) = (xx - nx * L, 0, zz - nz * L)
Unit base vector in the plane
dy = (0, 1, 0)
Another base vector
dc = dy x n //vector product
= (-bz, 0, bx)
Now it is possible to generate a grid, using integer indexes i, j in ranges (-W/2..W/2) and (-H/2.. H/2). Grid nodes coordinates:
x(i, j) = bx - j * bz
y(i, j) = 0 + i
z(i, j) = bz + j * bx

How to find a point in 3-D at an arbitrary perpendicular line given distance to the point

I have a line AB. I would like to draw a line BC, perpendicular to AB. I know xyz of the points A and B, I also know the distance N between B and C. How can I find an arbitrary point C which fits into the given parameters? The calculations should be done in 3-D. Any point, perpendicular to AB can be the point C, if its distance to B equals N.
An almost identical question is given here, but I would like to know how the same thing is done in 3-D: How do you find a point at a given perpendicular distance from a line?
The calculation that works for me in 2-D was given in the link above:
dx = A.x-B.x
dy = A.y-B.y
dist = sqrt(dx*dx + dy*dy)
dx /= dist
dy /= dist
C.x = B.x + N*dy
C.y = B.y - N*dx
I tried adding Z axis to it like this:
dz = A.z - B.z
dist = sqrt(dx*dx + dy*dy + dz*dz)
dz /=dist
C.z = .... at this point it becomes a mystery to me
If I put something like "C.z - N*dz" into C.z, the distance is accurate only in some rotation angles, I would like to know the correct solution. I can imagine that in 3-D it is calculated in a completely different manner.
Clarification
Point C is not unique. It can be any point on a circle with its
centre at B and radius N. The circle is perpendicular to AB
If the desired point C can be any of the infinitely-many points fitting your requirements, here is one method.
Choose any vector that is not parallel or anti-parallel to vector AB. You could try the vector (1, 0, 0), and if that is parallel you could use (0, 1, 0) instead. Then take the cross-product of vector AB and the chosen vector. That cross-product is perpendicular to vector AB. Divide that cross-product by its length then multiply by the desired length N. Finally extend that vector from point B to find your desired point C.
Here is code in Python 3 that follows that algorithm. This code is somewhat non-pythonic to make it easier to convert to other languages. (If I really did this for myself I would use the numpy module to avoid coordinates completely and shorten this code.) But it does treat the points as tuples of 3 values: many languages will require you to handle each coordinate separately. Any real-life code would need to check for "near zero" rather than "zero" and to check that the sqrt calculation does not result in zero. I'll leave those additional steps to you. Ask if you have more questions.
from math import sqrt
def pt_at_given_distance_from_line_segment_and_endpoint(a, b, dist):
"""Return a point c such that line segment bc is perpendicular to
line segment ab and segment bc has length dist.
a and b are tuples of length 3, dist is a positive float.
"""
vec_ab = (b[0]-a[0], b[1]-a[1], b[2]-a[2])
# Find a vector not parallel or antiparallel to vector ab
if vec_ab[1] != 0 or vec_ab[2] != 0:
vec = (1, 0, 0)
else:
vec = (0, 1, 0)
# Find the cross product of the vectors
cross = (vec_ab[1] * vec[2] - vec_ab[2] * vec[1],
vec_ab[2] * vec[0] - vec_ab[0] * vec[2],
vec_ab[0] * vec[1] - vec_ab[1] * vec[0])
# Find the vector in the same direction with length dist
factor = dist / sqrt(cross[0]**2 + cross[1]**2 + cross[2]**2)
newvec = (factor * cross[0], factor * cross[1], factor * cross[2])
# Find point c such that vector bc is that vector
c = (b[0] + newvec[0], b[1] + newvec[1], b[2] + newvec[2])
# Done!
return c
The resulting output from the command
print(pt_at_given_distance_from_line_segment_and_endpoint((1, 2, 3), (4, 5, 6), 2))
is
(4.0, 6.414213562373095, 4.585786437626905)

Difficulty with SICP Picture Language - Image Scaling Example

The picture language example in the SICP book discusses the notion of a frame:
A frame can be described by
three vectors—an origin vector and two edge vectors. The origin vector
specifies the offset of the frame’s origin from some absolute origin in
the plane, and the edge vectors specify the offsets of the frame’s corners
from its origin.
The book then goes on to say that if we have an image described in terms of points in the unit square, we can map a given point, (x, y), to a point within a new frame, f, using the following formula:
origin(f) + x * edge1(f) + y * edge2(f)
where + and * are defined as vector arithmetic operators:
(x1, y1) + (x2, y2) = (x1 + x2, y1 + y2) and
k * (x, y) = (kx, ky).
Using this formula, if I define a frame as
origin = (1, 1); edge1 = (3, 1); edge2 = (1, 3)
the point (1, 1) from the unit square maps to (5, 5); whereas it seems like it ought to be `(3, 3).
What am I not getting?
First, let's review the definition of frame:
A frame can be described by three vectors -- an origin vector and two edge vectors. The origin vector specifies the offset of the frame's origin from some absolute origin in the plane, and the edge vectors specify the offsets of the frame's corners from its origin.
And the point of above definition is :
edge vectors are measured based on origin vector of the frame, not the absolute origin in the plane.
So, when you choose three vectors (1, 1); (3, 1); (1, 3), the coordinate of the frame is actually
origin = (1, 1);
edge1 = (3, 1) - (1, 1) = (2, 0)
edge2 = (1, 3) - (1, 1) = (0, 2)
Back to your question, if you define the frame as origin = (1, 1); edge1 = (3, 1); edge2 = (1, 3), then the absolute coordinates are (1, 1); (4, 2); (2, 4).
The point (1, 1) of a painter specified in the unit square maps to (5, 5), not (3, 3) for the frame isn't a rectangular, just a more general parallelogram.

Transfer object to a predetermined distance

I have an object at coordinates (0, 0, 0) and I want to translate this object in any direction a predetermined distance, for example 5.
How do I to find the final coordinates? (not iteratively checking)
You can achieve exactly the same as T.Kiley said just picking a totally random vector, it will have a random direction and random magnitude. You can then normalize that vector and multiply it by 5 (or the desired magnitude).
I believe what you are asking is how do you generate a point that is 5 away from the origin (0,0,0). In general, you can use the parametric equations of a sphere to generate these points by first picking two random numbers in the range [0, 2pi] and [0, pi] respectively, then your point is
x = r * cos(theta) * sin(phi)
y = r * sin(theta) * sin(phi)
z = r * cos(phi)
Where theta is the first random number, phi is the second and r is your distance from the origin.
In Unity, it is even easier as you can use Random.onUnitSphere to give you a point exactly 1 away from the origin. Then just multiply by 5, e.g.:
finalPosition = Random.onUnitSphere * r
Again, where r in your example would be 5.

Cant find angle between 2 vectors

Could someone help me solve this problem? How can I find the angle shown in picture? I think I need to find angle between 2 vectors but im really bad at geometry.
http://i.stack.imgur.com/W0RKh.png
If you are developing your program in C++, then to calculating an angle between two vectors you can use the atan2 function, it is present in many programming languages.
You need to call atan2 giving it the two components of a single vector and then you make calculations this way:
Calculating for the first vector: atan2(v1_y, v1_x)
Calculating for the second vector: atan2(v2_y, v2_x)
Caution:
If the value returned by atan2 is negative (as atan2 returns value from range (-pi;+pi]), then you need to add 2 * pi to the result for each of the vector.
Finally you subtract the values of the vectors and what you get is the angle. The angle will be either positive or negative, depending which atan2 value you subtract from which one.
You need to normalize both vectors and then perform a dot product.
Step 1: Vector normalization:
A normalized vector has a length of 1. To achieve this, you divide its coordinates by its length:
float d = 1 / sqrt(X * X + Y * Y + Z * Z);
normalizedX = X * d;
normalizedY = Y * d;
normalizedZ = Z * d;
Note: The length is inversed and then multiplied instead of divided in order to increase performance.
Step 2: Dot product
After your normalized both vectors like in Step 1, you need to perform a dot product:
float angle = acos(x1 * x2 + y1 * y2 + z1 * z2);
The result is the cosine of the angle between the two vectors. After an acos you have your angle.

Resources