I have an array of 3D paired points in two different coordinate spaces (A and B).
Given points are not coplanar, how do I compute a non-affine transformation matrix which is able to transform a point from A into B?
I have managed to do this in 2D (using a homography), but can't work out how to make it work in 3D. A quick code example would be much appreciated if possible. :)
The approach described in this post will generalize to three dimensions: If you know the coordinates of five points in both coordinate systems, then you can use them to compute a 4×4 projective transformation matrix for this, which will be unique except for a scale factor which is without geometric relevance.
I've included variations of the required code for 2D in various posts, written for sage, and there is also the JavaScript example mentioned along with the description. Any of these could be adapted to the 3D case, but if you also want to change programming language, then you might be better off implementing the formula directly, keeping in mind that the adjoint may serve as alternative for the inverse of a matrix in several locations.
Here are some details on the generalization to 3D:
Use a 4×4 system of linear equations, with the homogenous coordinates of four points on the left and a fifth point on the right hand side.
Use the four solution variables to scale these four columns in order to obtain the transformation matrix.
(as before)
(as before)
(as before)
(as before)
Divide the first three coordinates of the homogenous coordinate vector by the fourth coordinate to obtain dehomogenized coordinates.
Related
I am trying to develop an algorithm that performs the following :
Given a 2D polygon and a 3D polyhedron, determine if the 2D polygon is a projection of the 3D polyhedron (a perspective projection to be precise) without knowing which transformation matrix we may have possibly used for the projection.
input
{2D Polygon}
{3D Polyhedron}
output
{bool} whether or not it's a perspective projection
I am not asking for code, but I would simply like to know if this is feasible in polynomial time.
Any help will be greatly appreciated.
A 3D to 2D perspective projection has 7 degrees of freedom (6 for the relative motion of the scene with respect to the camera, 1 for the focal length).
Select four vertices in the 2D projection and consider all possible correspondences with polyhedron vertices (there is a polynomial number of such associations). Then form a system of 7 equations in the 7 unknown parameters (unfortunately a nonlinear one; maybe the eighth equation can be useful to select among multiple solutions).
Knowing the parameters, you can check a solution by re-projecting the polyhedron and comparing to the polygon (with further search for correspondences with vertices and edges).
All of this will take polynomial time (quartic if I am right), if one admits that the solver takes bounded time (hence bounded precision).
If the focal length is known, then a better approach is possible. Indeed, with only 6 unknowns, you can find the projection parameters from the projection of just three points. This problem is known to have an analytical solution (actually up to 4 of them), as described at length in "New Algorithms for the Perspective-Three-Point Problem, GAO Xiaoshan & CHEN Hangfei, Vol.16 No.3 J. Comput. Sci. & Technol."
This should lead to an O(N³) exact procedure.
More generally speaking, you form putative correspondences between N pairs of points, solve the corresponding Perspective-N-point problem, and check the hypothesis by reprojecting the polyhedron and comparing to the known projection to validate the hypothesis.
Just an idea for an algorithm:
Take a triangle of the projection made of three points next to each other not on the same line. Iterate through all corresponding triangles of the original. For all possible projections that solve the pair of triangles, check if the rest matches.
I must admit I am not sure right now if there could be infinite solutions for triangles (which would be hard to iterate)? If so, start with four points.
I think it is possible but you have to do a fair amount of reverse engineering. A 2D sketch that represents a 3D object is known as an Orthographic Projection. The link shows you the transformation matrices you need apply to transform the 3D point onto its 2D projection. Now, how do you go the opposite way? Inverse matrices with a mix of some inverse transformations (translation, scaling, rotation...)? I think this is a good lead to follow.
While investigating packings of spheres I ran into this problem where I have a list of vectors and I want to know how many planes they generate. I'm generating these lists of vectors that point from the center of a sphere to a contact point on the outside surface of the sphere and I want to know how many of these vectors are coplanar. For example I want an algorithm that will do the following..
Given the vectors {1,2,3}, {2,4,6}, and {0,6,9} it should report that there is only one unique plane generated by either one of the first two and the third.
All of my attempts haven't gotten anywhere because every time I count how many planes are generated I drastically over count. I feel like this should be an easy thing to do and I'm also curios if there is any linear algebra that can somehow come to the rescue. If I can determine how many planes are generated and what those planes are I think it will be easy to determine how many vectors lie in each plane which is the last part of this problem. If anyone can think of a more general approach to any dimension two or greater that would actually be ideal but for now this is all I'm concerned with.
You can use Gaussian elimination to determine the dimension of the span of several vectors. (the space that is created by all linear combinations of these - also called rank of the matrix)
Create a matrix from your vectors by writing the vectors in the rows of your matrix. Then use Gaussian elimination and count the number of Rows that still have non-zero entries. This is the dimension of the spanned vectorspace.
Since you use vectors from R^3 this will never be greater than 3. However a plane is a 2-dimensional vectorspace, so you need to find all combinations of vectors that result in a 2-dimensional span, which can be easily found by iterating over your vectors once you have implemented gaussian elimination.
Edit:
An example since it seems that this can still lead to confusion:
you have a set of 3 vectors: (1,0,0); (0,1,0); (0,0,1)
You can create 3 different planes from these (by combining any two of these vectors you get a different plane.) To formally check if that statement is true you need to do the following for every pair v1,v2 of vectors:
check whether v1,v2 are linear independant - if they aren't, they don't create a plane, so you go ahead and pick the next two vectors. (in this example they always are linear independant)
Check for each other vector in your list, if it (v3) does not lie within the created plane (it is not coplanar to v1,v2). To do this use gaussian elimination on the matrix (v1,v2,v3) and confirm that the rank of the matrix is 3.
If the matrix in step 2 has a rank of 2, this means that the vectors v1,v2,v3 are coplanar. Thus you can pick any two of these vectors to generate the exact same plane.
As an example: you start with vectors (1,0,0) and (0,1,0). Then you check several other vectors and find that two of them are coplanar to your initial vectors (for example (1,1,0) and (-1,-1,0)). This means that for your list of unique planes, you may add the plane generated by any two out of these four vectors, but not add any other combination of these.
Note: this works for finding 2 dimensional planes in higher dimensions as well of course. You can even check for higher dimensional planes, but this needs some adapting in the number of vectors you compare and the rank for which you check.
I have a set points whose coordinates are given by the arrays x, y and z and the value of the density field in each point is stored in the array d.
I would like to reconstruct the density field on a uniform grid. What's the best algorithm to do that?
I know that in python, the scipy module come in handy with the griddata function but I would like to write my own code, I just need a hint.
If you have some sort of scalar field and the points are the origins of the field, you can implement a brute force approach by walking all lattice points and calculating the field intensity given the sources. There are both recursive methods that allow "blanking" wide volumes where the field is more or less constant, and techniques to save some CPU time by calculating the variations from one point to the next.
If the points you have are samplings of a value, then you will have to decompose your space in volumes and interpolate the values. You can employ a simple Voronoi decomposition - this is usually done in 2D for precipitation measurements - or a Delaunay tetrahedralization (you can look into TetGen's documentation). The first approach assumes that the function is constant throughout each Voronoi volume; the last allows rendering a trilinear interpolation.
If you need to smooth a 3D grid, the trilinear interpolation looks like the best approach.
There are also other methods used for fast visualization, that involve maintaining a list of 3D points in order of distance from any one given point in your regular grid. When moving through the grid, you recalculate distances using quadratic increments. Then, you perform a simple interpolation based on a subset of points of chosen cardinality (i.e., if you consider the four nearest points at distances d1..d4, you would calculate the value in P by proportionally weighing the values v1..v4). This approach is fast and easy to implement by yourself, but be warned that it underperforms wherever the minimum distance between points is less than the lattice step (you can compensate by considering more points where this happens; and the effect is less evident if the sampled function is smooth at the same scale).
If you want to implement a mathematical method yourself, you need to learn the theory, of course. In this case, it's 3D scattered data interpolation.
Wikipedia, MATLAB help and scipy help say there are at least half a dozen different methods. WP has a fairly good description of them and there's a comparison article but I strongly suggest you find something in your native language on such a terminology-intensive subject.
One approach is to form the Delaunay triangulation of the scattered points [x,y,z], (actually a tetrahedralisation in your 3d case!) and perform interpolation within each element using a linear representation of the density field, defined at the tetrahedron vertices.
To evaluate the density at each structured grid point you would (i) determine which tetrahedron the point lay within and (ii) evaluate the linear interpolant.
Forming the Delaunay triangulation is non-trivial, put there are a few good libraries that can be used for this, depending on your language of choice. One good option is CGAL.
Hope this helps.
Givens
1- X,y,and Z the world co-ordinate system
2-i,j,k another co-ordinate system.
3-the cosines in which each of i,j, and k make with the X,Y,Z.
problem
how to rotate the i,j,k system about i or j or k??
If you have the cosines of the angles formed by pairing each of i,j,k with each of xhat, yhat, and zhat (nine angles altogether), you have the makings for the direction cosine matrix. For example, see http://www.ae.illinois.edu/~tbretl/ae403/handouts/06-dcm.pdf (or just google direction cosine matrix). The direction cosine matrix is just another name for a transformation or rotation matrix.
Be careful, though!
There is no single standard scheme. You need to know that this is the case and read the literature carefully.
Are you rotating the object or transforming coordinates? Rotation and transformation are conjugate operations. Some people (many people!) use the term 'rotation matrix' when they mean 'transformation matrix', and vice versa.
Do you represent vectors as column vectors or row vectors? Here there is a lot more consistency; most people use column vectors rather than row vectors for things like positions, velocities, etc. BUT there are very good reasons to use row vectors (or column vectors if you are one of those contrarians) for things that properly belong in the dual space.
Quaternions have even more ambiguity of representation than matrices. There's nothing wrong with that (I use quaternions all the time), but you do have to beware of these ambiguities when you read a paper or book, look at someone else's code, or exchange data.
Finally, matrices and quaternions are only two of many charts on SO(3). There are lots of ways to represent rotations in 3-space.
You can first create either a rotation matrix or a quaternion. Then you use that to transform your vectors.
You can find the code to create a rotation matrix or a quaternion in pretty much any 3d maths library.
If I recall correctly you calculated the rotation quaternion as(assuming normalized axis):
q.x=axis.x*sin(alpha)
q.y=axis.y*sin(alpha)
q.y=axis.z*sin(alpha)
q.w=cos(alpha)
I am looking for an algorithm that takes vector image data (e.g. sets of edges) and interpolate another set of edges which is the "average" of the two (or more) sets.
To put it in another way, it is just like Adobe Flash where you "tween" two vector images and the software automatically computes the in-between images. Therefore you only specify the starting image and end image, then Flash takes care of all the in-between images.
Is there any established algorithm to do this? Especially in cases like different number of edges?
What exactly do you mean by edges? Are we talking about smooth vector graphics that use curves?
Well a basic strategy would be to simply do a linear interpolation on the points and directions of your control polygon.
Basically you could simply take two corresponding points (one of each curve/vector form) and interpolate them with:
x(t) = (1-t)*p1 + t*p2 with t in [0,1]
(t=0.5 would then of course give you the average between the two)
Since vector graphics usually use curves you'd need to do the same with the direction vector of each control point to get the direction vector of the averaged curve.
One big problem though is to match the right points of each control polygon, especially if both curves have a different degree. You could try doing a degree elevation on one to match the degree of the other and then one by one assign them to each other and interpolate.
Maybe that helps...