How do I transform 3D coordinates to a new normal vector? - python

I have a series of coordinates, all coplanar to the same plane with a specific normal vector. I have also defined two vectors perpendicular to the normal vector that describe "up/down" and "left/right" within that 3D plane. The center of the plane around which the transformation should take place is also known.
Let's say I have a new normal vector, how would I transform all those 3D coordinates to still be in that plane? So their relative position to the center of the plane with its new normal is still the same?
I have read about a rotation matrix before, but the thing is that I have a vector to transform to, not an angle that describes a rotation, though the plane essentially does make a rotation. I was wondering if there wasn't any method that would make this transformation quick and easy.

So I dug some more into rotation matrices and I found out that you don't necessarily need to know the angle to rotate to that new position.
Really all you need to do is multiply the rotation matrix with the coordinates relative to the previous rotation matrix. After that you add the coordinates of the point around which you were rotating and there you have it.
I needed to do this in python and used numpy's matmul method for this. The rotation matrix was made using the vectors that I had already available:
[[right.x up.x, forward.x],
[right.y, up.y, forward.y],
[right.z, up.z, forward.z]]
right, up and forward being 3 vectors of size 1 perpendicular to each other.

Related

Converting a Plane to FiniteSet in SymPy

I am currently working with 3D geometry and I decided to use sympy.geometry to manage objects in space.
I had to solve a non-linear system of equations to find the intersection between a plane and a sphere, which yields a FiniteSet as a result (which is the correct equation of the circle, so that works). After that, I have to find the intersection between this circle and another plane, which I'm finding difficult to do as the two objects are of different type, so no direct comparison can be done.
I am asking if there is any automatic way of converting a Plane object from the module into a FiniteSet or I have to do it manually by defining a symbolic set with the coordinates of the points on the plane (which can be done as I have full description of this new plane).
Edit: By equation of the circle, I mean the following. The set is described as a collection of points (in the example, the circle is perpendicular to the z=0 plane, but this has to be done in general so few assumptions can be made to simplify the problem):
FiniteSet((70,18-sqrt(-(z-6)(z-2)),z),(70,18+sqrt(-(z-6)(z-2)),z))
Here, z is bound to be real so it is limited to the [2,4] interval.

How to determine the first triangle (out of a set of triangles) passed through by a 3-D ray?

I am trying to solve the following problem in Python. The problem comes from an image processing problem when i use the Finite Element Method.
In my problem, I have a set of triangles and a ray. Each triangle consists of three 3-D points, and the ray is in the form of a 3-D point and a 3-D vector. How can I determine the first triangle that is passed through by the ray? Now I do not even have an algorithm for this. Any inputs will be appreciated.
The first thing I would do, is translate the whole data set, subtracting the 3D ray origin. Then rotate the data set so that the ray's 3D vector aligns with the X-axis. See How to find the orthonormal transformation that will rotate a vector to the x axis?.
Now the problem has been converted to filter for triangles that cross the X-axis with a non-negative X-coordinate, and among those find the one whose crossing point has the minimal X-coordinate. So
For each triangle check where its plane crosses the X-axis. See Determine point of interesction of plane with axis given points of plane
Then throw away the triangles where that crossing point (on the X-axis) is not within the bounds of the triangle (check for each of the three edges that this point is at the "inner" side of it). See Check whether a point is within a 3D Triangle
Throw away the triangles whose crossing point has a negative X-coordinate.
Among the remaining triangles (that really cross the X-axis on the positive side) find the one with the minimum crossing point in terms of X-coordinate.

Python library for rotation and translation on a seesaw-like object

I'd like to do calculations on the 3D positions on both end's of a rigid object (see spot where the children are usually sitting in image below). The geometrical situation of the rigid object corresponds to a seesaw. Rotation has to be possible on three axes and can be represented by a ball bearing, which initially is located at the middle of the rod.
The input to the desired function should consist of three rotations performed at the position of the ball bearing, three translations along the bearing and the initial 3D positions of both ends of the object.
The output needs to be the calculated new 3D positions of both ends.
Does anyone know a python library that does provide functionalities regarding this issue?
I've just found out that Open3D has implemented exactly what I was looking for. As it is working with point clouds, all that needs to be done is to create two points in 3D space, define a rotation matrix and the center (= ball bearing in this case). The function "rotate" then calculates the altered positions of the rotated points. This also works for translation.
# Rotation
pcd.rotate(r, center = (0,0,0))
# Translation
pcd.translate(t)
With r = rotation matrix (3x3) and t = translation matrix (3x1).

Calculate 3D Plane that Rests on a 3D Surface

I have about 300,000 points defining my 3D surface. I would like to know if I dropped a infinitely stiff sheet onto my 3D surface, what the equation of that plane would be. I know I need to find the 3 points the sheet would rest on as that defines a plane, but I'm not sure how to find my 3 points out of the ~300,000. You can assume this 3D surface is very bumpy and that this sheet will most likely lie on 3 "hills".
Edit: Some more background knowledge. This is point cloud data for a scan of a 3D surface which is nearly flat. What I would like to know is how this object would rest if I flipped it over and put it on a completely flat surface. I realize that this surface may be able to rest on the table in various different ways depending on the density and thickness of the object but you can assume the number of ways is finite and I would like to know all of the different ways just in case.
Edit: After looking at some point cloud libraries I'm thinking of doing something like computing the curvature using a kd tree (using SciPy) and only looking at regions that have a negative curvature and then there should be 3+ regions with negative curvature so some combinatorics + iterations should give the correct 3 points for the plane(s).

Determining the pattern orientation of a spatiotemporal image

How can I obtain average direction of the pattern shown in the figure below. It is the direction of the red arrow relative to the yellow (horizontal) line. Any ideas for an approach? I couldn't figure out a way to approach. This is a spatio-temporal image created from a video. Thank you.
Here is my original image:
The simplest approach would be to compute the gradient vector (x derivative and y derivative) and find its direction at each pixel (atan2(y,x)). The average orientation is what you want, not the average direction (will cancel out). So apply modulus pi, then average across the image.
The best way to compute image gradients is through the Gaussian gradients.
The structure tensor is the more robust way of accomplishing this. In short, it computes local averages of the gradient vector to reduce the effect of noise. It does this by computing the outer product of the gradient vector with itself, which produces a symmetric matrix. The individual components of this matrix can then be locally averaged (i.e. apply a smoothing filter). This is similar to computing the angle of the vectors, doubling the angles to make vectors in opposite directions equal, then averaging them.
Note that you can apply either of these solutions in 3D (you can think of the video data as 2D + time = 3D). That way, you compute both the speed and the direction of motion within the 2D frame, rather than just the speed along the direction in which you extracted the 2D image you show in the question. The image gradient and the concept of the structure tensor easily extend to 3D. This 3D approach is similar to the approach by Lucas-Kanade for optical flow. If you follow that link to Wikipedia, you'll see it uses the structure tensor in 2D, and adds gradients along the time dimension.
Might be useful to try Fourier transform.
In your case you should get two vertical lines in the middle of the transformed image corresponding to the information when traveling vertically in the image.
On the other hand there shouldn't be a horizontal line since when traveling horizontally in the image there is little information (little change)
For example you can use this online site to play with fourier transforms:
https://www.ejectamenta.com/Fourifier-fullscreen/
It might sound like the problem remains the same but in fact it is much easier now.
The 2D pattern is converted into dominant lines which are quite easy to find in the transformed image.
For example you can search for the strongest pixels in the image and simply determine if they are more likely to be horizontal line or a vertical line or determine the angle of the dominant line. Then rotate by 90 degrees.
For example see this image of wood grain and the resulting transformed image:
And don't worry about the two lines. The image is symmetric so just ignore 3/4 of the image and look in 1 quarter.
I recommend giving the Hough transform a go, it is available in OpenCv. The Hough transform maps lines to angles, and might be useful in your case.

Categories