I want to interpolate in a distorted box. As We have 8 points around a distorted box (p0, p1, p2, ..., p7), if we find the transformation matrix which transform this box to a box with points ((0, 0, 0), (0, 0, 1), (0, 1, 1), (0, 1, 0), (1, 0, 0), (1, 0, 1), (1, 1, 1), (1, 1, 0) ), the interpolation can be done easily. In other words, If we find a transformation from a distorted box to a normal box which length, width and height of the box are equal to 1, the interpolation can be done very simple. Anyone has any idea about interpolating in a distorted box or finding transformation from a distorted box to a normal box?
Not answering the original question since in the comment you said that you simply wanted to interpolate a function inside the cube, using the values at the 8 vertices.
So in order to do that, you can reason as follow:
1) Split the cube in 6 tetrahedra
2) Find the tetrahedron that contains the point you want to interpolate
3) An irregular tetrahedron can be easily mapped to a regular one, that is you can easily obtain the generalized tetrahedral coordinates of a point. Check eq. 9-11 here.
4) Once you have the tetrahedral coordinates of your point, the interpolation is trivial (see previous link).
This is the easiest way I can think of, the big downside is that there are 13 ways to split a cube in tetrahedras, and this choice will produce (slightly) different results, especially if the cube is heavily deformed. You should aim for a delaunay tetrahedralization of the cube to minimize this effect.
Also notice that the interpolated function defined in this way is continuous across the faces of the tetrahedra (but not differentiable).
You can apply the inverse of a scaling matrix to the cube where vx, vy and vz
are the cube's spacial extents.
Related
Given the source data for a Venn diagram, e.g. A=10, B=15, C=12, A+B=5, B+C=3, A+C=2, A+B+C=1, I need to draw a Venn diagram with the circle sizes proportional to A,B, and C, and their overlap proportional to the A+B, B+C, and A+C. The graph does not need to be perfectly matching the data, but be as close to it as possible (I prefer simpler computation method). It must correctly represent cases of no overlap and when one set is a proper subset of another set. How would I compute the correct positioning and radius of the circles for a given canvas size (width/height). I was able to find mathematics for two-circle Venn. Has anyone done the 3 circle calculation?
P.S. The example numbers above were random, and might be invalid.
The distance between circles A, B must be the solution to the two-circle Venn problem with intersection area equal to (A+B) + (A+B+C) (or simply (A+B) if by your definition it includes (A+B+C)). Similarly for B, C the intersection is (B+C) + (A+B+C), and likewise for C, A.
Solve these independently with the algorithm you have found, and you get three distances equal to the side lengths of the triangle joining the centers of the three circles. Constructing the triangle and hence drawing the circles is then an easy task with some high-school trigonometry.
The solution is unique, and only valid if the intersection values themselves are valid.
There are 8 regions defined by a 3-circle Venn diagram. If we define set A as including binary numbers 0 though 7 that have the 1-bit set, B as those with the 2-bit set, and C ans those with the 4-bit set, we get
A = {1, 3, 5, 7}; B = {2, 3, 6, 7}; C = {4, 5, 6, 7}
Each one of those numbers defined a region in the diagram, with 0 representing the region outside the circles and inside the universal set: i.e. A' ∩ B' ∩ C'.
You know how to do the 2-circle problem. So solve that for A and B (using the sizes of A, B, and A ∩ B), B and C, and A and C. that gives you distances between the circle centers and the sizes of the circle. Use the three distances to draw a triangle for those circle centers, then draw the circles around those centers. If that makes the exterior region 0have the wrong size, you can shrink or expand the entire 3-circle setup to get that right as well.
That makes all regions correct--except for region 7, the intersection of all three sets. That size will be set from all the others--you have no choice here. Therefore, it will probably not have the size you desire. You will need to experiment to see if the size of that region is usually close enough to what you want. My brief research implies that there is no way to use circles in your diagram and always get the sizes of all eight regions. If you use ellipses or some other more-general shape instead, this should be possible, but you seem to want circles.
Note that if you solve the 2-circle problem correctly, the situation of disjoint circles and of subset circles will automatically be handled. For example, if A and B are disjoint, then regions 3 and 7 are empty, and your solution will make the two circles to not overlap. They will probably touch, if you use the obvious algorithm from your linked site, but without overlap. Similarly, if one set is a subset of another, one circle will be inside the other, though they will probably touch. If you do not want the touching, the algorithm to avoid that should be easy, unless of course you have the situation where two of your three sets are equal.
I have some points (3D) all on the same (known) plane. Now I want to scale these points within the plane as opposed to the whole 3D space.
Is there some quick solution for this e.g. a modified scaling matrix?
Can someone help me?
Thanks.
EDIT: I'm more looking for an idea/pseudocode how to do this. If you want use MatLab or some convenient language
Your plane can be known by three non-collinear points P0, P1, P2, or by its implicit equation,
A.x + B.y + C.z + D = 0
In the first case, consider the vector P0P1 and normalize it (U = P0P1/|P0P1|). Then compute a second vector orthogonal with the first, V = P0P2 - (P0P2.U).U and normalize it.
In the second case you can take the three intersection points with the axes, (-D/A, 0, 0), (0, -D/B, 0), (0, 0, -D/C) and you are back in the first case (but mind degenerate cases).
Use the two vectors to compute the desired 2D coordinates of any point P = (X, Y, Z) by the dot products
(x, y) = (P.U, P.V)
(This transform is a rotation that makes P0P1 parallel to the x axis and brings P0P1P2 in the plane xy.)
Let's say I have 3 vectors, forward = Vector(1,0,0), up = Vector(0,1,0), right = Vector(0,0,1).
Now I replace the up vector by something else, but forward and right should stay in relation to the new up vector as they have to the old one.
e.g. if the new up vector is Vector(1,0,0), forward should be Vector(0,-1,0) and right should still be Vector(0,0,1).
What mathematical formula can be used for this?
You can not do it without a rotation axis. Even in your simplified (axis aligned) case where one vector is changed to the opposite direction you need a rotation axis:
Both (actually there are four)
forward( 0,-1, 0), up(1,0,0), right(0, 0, 1) and
forward( 0, 1, 0), up(1,0,0), right(0, 0,-1)
are valid solutions.
However having the rotation from Vector(0,1,0) to Vector(1,0,0), it (may) implicitly defines the rotation axis(0, 0, 1) and angle PI/2. Hence you can build a rotation matrix and multiply that matrix with the two other vectors.
The SCNNode take a rotation using a SCNVector4, which has an angle (w) and a magnitude how that angle applies to each axis (x, y, z). For example, to rotate 45 degrees around the x-axis I'd create a SCNVector4 like this:
SCNVector4Make(1.0f, 0, 0, DEG2RAD(45))
What I'd like to do is rotate it across all three axis, for example: 45 degrees on the x-axis, 15 degrees on the y-axis and -135 degress across the z-axis. Does anyone know the math to calculate the final SCNVector4?
Instead of rotation property, use eulerAngles and specify angle for each axis
You'll need to generate an SCNVector4 for each of the rotations, and then multiply them. Note that the order of operations matters!
http://www.cprogramming.com/tutorial/3d/rotationMatrices.html has a pretty good writeup of the math. Any OpenGL reference that deals with rotation matrices is worth a look too.
If you're not animating the rotation, it might be cleaner to just set the transform matrix directly, like:
node.transform = CATransform3DRotate(CATransform3DRotate(CATransform3DRotate(node.transform, xAngle, 1, 0, 0), yAngle, 0, 1, 0), zAngle, 0, 0, 1);
Do you ask for rotation matrix or how to simply rotate in general? If the second is correct then for example:
[node runAction:[SCNAction rotateByX:0 y:M_PI z:0 duration:0]];
I'm using the python OpenGL bindings, and trying to only use modern opengl calls. I have a VBO with verticies, and I am trying to render with an orthographic projection matrix passed to the vertex shader.
At present I am calculating my projection matrix with the following values:
from numpy import array
w = float(width)
h = float(height)
n = 0.5
f = 3.0
matrix = array([
[2/w, 0, 0, 0],
[ 0, 2/h, 0, 0],
[ 0, 0, 1/(f-n), -n/(f-n)],
[ 0, 0, 0, 1],
], 'f')
#later
projectionUniform = glGetUniformLocation(shader, 'projectionMatrix')
glUniformMatrix4fv(projectionUniform, 1, GL_FALSE, matrix)
That code I got from here:
Formula for a orthogonal projection matrix?
This seems to work fine, but I would like my Origin to be in the bottom left corner of the screen. Is this a function I can apply over my matrix so everything "just works", or must I translate every object by w/2 h/2 manually?
side note: Will the coordinates match pixel positions with this working correctly?
Because I'm using modern OpenGL techniques, I don't think I should be using gluOrtho2d or GL_PROJECTION calls.
glUniformMatrix4fv(projectionUniform, 1, GL_FALSE, matrix)
Your matrix is stored in row-major ordering. So you should pass GL_TRUE, or you should change your matrix to column-major.
I'm not completely familiar with projections yet, as I've only started OpenGL programming recently, but your current matrix does not translate any points. The diagonal will apply scaling, but the right most column will apply translation. The link Dirk gave gives you a projection matrix that will make your origin (0,0 is what you want, yes?) the bottom-left corner of your screen.
A matrix I've used to do this (each row is actually a column to OpenGL):
OrthoMat = mat4(
vec4(2.0/(screenDim.s - left), 0.0, 0.0, 0.0),
vec4(0.0, 2.0/(screenDim.t - bottom), 0.0, 0.0),
vec4(0.0, 0.0, -1 * (2.0/(zFar - zNear)), 0.0),
vec4(-1.0 * (screenDim.s + left)/(screenDim.s - left), -1.0 * (screenDim.t + bottom)/(screenDim.t - bottom), -1.0 * (zFar + zNear)/(zFar - zNear), 1.0)
);
The screenDim math is effectively the width or height, since left and bottom are both set to 0. zFar and zNear are 1 and -1, respectively (since it's 2D, they're not extremely important).
This matrix takes values in pixels, and the vertex positions need to be in pixels as well. The point (0, 32) will always be at the same position when you resize the screen too.
Hope this helps.
Edit #1: To be clear, the left/bottom/zfar/znear values I stated are the ones I chose to make them. You can change these how you see fit.
You can use a more general projection matrix which additionally uses left,right positions.
See Wikipedia for the definition.