Populating STL surface mesh uniformly with points - fortran

I would like to be able to take a STL file (triangulated surface mesh) and populate the mesh with points such that the density of points in constant. I am writing the program in Fortran.
So far I can read in binary STL files and store vertices and surface normals. Here is an example file which has been read in (2D view for simplicity).
My current algorithm fills each triangle using the following formula:
x = v1 + a(v2 - v1) + b(v3 - v1) (from here)
Where v1, v2, v3 are the vertices of the triangle and x is a arbitrary position within the triangle (or on the edges) . "a" and "b" vary between 0 and 1 and their sum is less than 1. They represent the distance along two of the edges (which start from the same vertex). The gap between the particles should be the same for each edge. Below is an example of the results I get:
The resulting particle density if nowhere near uniform. Do you have any idea how I can adapt my code such that the density will be constant from triangle to triangle? Relevant code below:
! Do for every triangle in the STL file
DO i = 1, nt
! The distance vector from the second point to the first
v12 = (/v(1,j+1)-v(1,j),v(2,j+1)-v(2,j),v(3,j+1)- v(3,j)/)
! The distance vector from the third point to the first
v13 = (/v(1,j+2)-v(1,j),v(2,j+2)-v(2,j),v(3,j+2)- v(3,j)/)
! The scalar distance from the second point to the first
dist_a = sqrt( v12(1)**2 + v12(2)**2 + v12(3)**2 )
! The scalar distance from the third point to the first
dist_b = sqrt( v13(1)**2 + v13(2)**2 + v13(3)**2 )
! The number of particles to be generated along the first edge vector
no_a = INT(dist_a / spacing)
! The number of particles to be generated along the second edge vector
no_b = INT(dist_b / spacing)
! For all the particles to be generated along the first edge
DO a = 1, no_a
! For all the particles to be generated along the second edge
DO b = 1, no_b
IF ((REAL(a)/no_a)+(REAL(b)/no_b)>1) EXIT
temp(1) = v(1,j) + (REAL(a)/no_a)*v12(1) + (REAL(b)/no_b)*v13(1)
temp(2) = v(2,j) + (REAL(a)/no_a)*v12(2) + (REAL(b)/no_b)*v13(2)
temp(3) = v(3,j) + (REAL(a)/no_a)*v12(3) + (REAL(b)/no_b)*v13(3)
k = k + 1
s_points(k, 1:3) = (/temp(1), temp(2), temp(3)/)
END DO
END DO
j = j + 3
END DO

The solution I went with was to split each triangle into two right angled triangles. This is done by projecting the vetex opposite the longest edge orthogonally onto the longest edge. This splits the trianlge into two smaller triangles each with a 90 degree angle. A detailed answer on how to do this can be found here. By generating points along both 90° bends, a uniform distribution of particles can be achieved.
This method needs to be adapted so that particles are not generated more than once along edges which are common to multiple triangles. I have not done this yet. See image below for results. This solution does not achieve an isotropic distribution but this is not a concern for my intended application.
(Thanks to Vladimir F for his comments and advice on norm2, I tried to implement his approach but was not competent enough to get it to work).

Related

Marching Cubes Terrassing/Ridge Effect

I am implementing a marching cubes algorithm generally based on the implementation of Paul Bourke with some major adjustments:
precalculation of the scalarfield (floating point values)
avoiding duplicated vertices in the final list using a std::map
vertex storing to visualize the final mesh in Ogre3D
Basically I changed nearly 80% of his code. My resulting mesh has some ugly terrasses and I am not sure how to avoid them. I assumed that using floating points for the scalar field would do the job. Is this a common effect? How can you avoid it?
calculating the vertex positions on the edges. (cell.val[p1] contains the scalar value for the given vertex):
//if there is an intersection on this edge
if (cell.iEdgeFlags & (1 << iEdge))
{
const int* edge = a2iEdgeConnection[iEdge];
int p1 = edge[0];
int p2 = edge[1];
//find the approx intersection point by linear interpolation between the two edges and the density value
float length = cell.val[p1] / (cell.val[p2] + cell.val[p1]);
asEdgeVertex[iEdge] = cell.p[p1] + length * (cell.p[p2] - cell.p[p1]);
}
You can find the complete sourcecode here: https://github.com/DieOptimistin/MarchingCubes
I use Ogre3D as library for this example.
As Andy Newmann said, the devil was in the linear interpolation. Correct is:
float offset;
float delta = cell.val[p2] - cell.val[p1];
if (delta == 0) offset = 0.5;
else offset = (mTargetValue - cell.val[p1]) / delta;
asEdgeVertex[iEdge] = cell.p[p1] + offset* (cell.p[p2] - cell.p[p1]);

How to find all equals paths in degenerate tree from specific start vertex? [duplicate]

I have some degenerate tree (it looks like as array or doubly linked list). For example, it is this tree:
Each edge has some weight. I want to find all equal paths, which starts in each vertex.
In other words, I want to get all tuples (v1, v, v2) where v1 and v2 are an arbitrary ancestor and descendant such that c(v1, v) = c(v, v2).
Let edges have the following weights (it is just example):
a-b = 3
b-c = 1
c-d = 1
d-e = 1
Then:
The vertex A does not have any equal path (there is no vertex from left side).
The vertex B has one equal pair. The path B-A equals to the path B-E (3 == 3).
The vertex C has one equal pair. The path B-C equals to the path C-D (1 == 1).
The vertex D has one equal pair. The path C-D equals to the path D-E (1 == 1).
The vertex E does not have any equal path (there is no vertex from right side).
I implement simple algorithm, which works in O(n^2). But it is too slow for me.
You write, in comments, that your current approach is
It seems, I looking for a way to decrease constant in O(n^2). I choose
some vertex. Then I create two set. Then I fill these sets with
partial sums, while iterating from this vertex to start of tree and to
finish of tree. Then I find set intersection and get number of paths
from this vertex. Then I repeat algorithm for all other vertices.
There is a simpler and, I think, faster O(n^2) approach, based on the so called two pointers method.
For each vertix v go at the same time into two possible directions. Have one "pointer" to a vertex (vl) moving in one direction and another (vr) into another direction, and try to keep the distance from v to vl as close to the distance from v to vr as possible. Each time these distances become equal, you have equal paths.
for v in vertices
vl = prev(v)
vr = next(v)
while (vl is still inside the tree)
and (vr is still inside the tree)
if dist(v,vl) < dist(v,vr)
vl = prev(vl)
else if dist(v,vr) < dist(v,vl)
vr = next(vr)
else // dist(v,vr) == dist(v,vl)
ans = ans + 1
vl = prev(vl)
vr = next(vr)
(By precalculating the prefix sums, you can find dist in O(1).)
It's easy to see that no equal pair will be missed provided that you do not have zero-length edges.
Regarding a faster solution, if you want to list all pairs, then you can't do it faster, because the number of pairs will be O(n^2) in the worst case. But if you need only the amount of these pairs, there might exist faster algorithms.
UPD: I came up with another algorithm for calculating the amount, which might be faster in case your edges are rather short. If you denote the total length of your chain (sum of all edges weight) as L, then the algorithm runs in O(L log L). However, it is much more advanced conceptually and more advanced in coding too.
Firstly some theoretical reasoning. Consider some vertex v. Let us have two arrays, a and b, not the C-style zero-indexed arrays, but arrays with indexation from -L to L.
Let us define
for i>0, a[i]=1 iff to the right of v on the distance exactly i there
is a vertex, otherwise a[i]=0
for i=0, a[i]≡a[0]=1
for i<0, a[i]=1 iff to the left of v on the distance exactly -i there is a vertex, otherwise a[i]=0
A simple understanding of this array is as follows. Stretch your graph and lay it along the coordinate axis so that each edge has the length equal to its weight, and that vertex v lies in the origin. Then a[i]=1 iff there is a vertex at coordinate i.
For your example and for vertex "b" chosen as v:
a--------b--c--d--e
--|--|--|--|--|--|--|--|--|-->
-4 -3 -2 -1 0 1 2 3 4
a: ... 0 1 0 0 1 1 1 1 0 ...
For another array, array b, we define the values in a symmetrical way with respect to origin, as if we have inverted the direction of the axis:
for i>0, b[i]=1 iff to the left of v on the distance exactly i there
is a vertex, otherwise b[i]=0
for i=0, b[i]≡b[0]=1
for i<0, b[i]=1 iff to the right of v on the distance exactly -i there is a vertex, otherwise b[i]=0
Now consider a third array c such that c[i]=a[i]*b[i], asterisk here stays for ordinary multiplication. Obviously c[i]=1 iff the path of length abs(i) to the left ends in a vertex, and the path of length abs(i) to the right ends in a vertex. So for i>0 each position in c that has c[i]=1 corresponds to the path you need. There are also negative positions (c[i]=1 with i<0), which just reflect the positive positions, and one more position where c[i]=1, namely position i=0.
Calculate the sum of all elements in c. This sum will be sum(c)=2P+1, where P is the total number of paths which you need with v being its center. So if you know sum(c), you can easily determine P.
Let us now consider more closely arrays a and b and how do they change when we change the vertex v. Let us denote v0 the leftmost vertex (the root of your tree) and a0 and b0 the corresponding a and b arrays for that vertex.
For arbitrary vertex v denote d=dist(v0,v). Then it is easy to see that for vertex v the arrays a and b are just arrays a0 and b0 shifted by d:
a[i]=a0[i+d]
b[i]=b0[i-d]
It is obvious if you remember the picture with the tree stretched along a coordinate axis.
Now let us consider one more array, S (one array for all vertices), and for each vertex v let us put the value of sum(c) into the S[d] element (d and c depend on v).
More precisely, let us define array S so that for each d
S[d] = sum_over_i(a0[i+d]*b0[i-d])
Once we know the S array, we can iterate over vertices and for each vertex v obtain its sum(c) simply as S[d] with d=dist(v,v0), because for each vertex v we have sum(c)=sum(a0[i+d]*b0[i-d]).
But the formula for S is very simple: S is just the convolution of the a0 and b0 sequences. (The formula does not exactly follow the definition, but is easy to modify to the exact definition form.)
So what we now need is given a0 and b0 (which we can calculate in O(L) time and space), calculate the S array. After this, we can iterate over S array and simply extract the numbers of paths from S[d]=2P+1.
Direct application of the formula above is O(L^2). However, the convolution of two sequences can be calculated in O(L log L) by applying the Fast Fourier transform algorithm. Moreover, you can apply a similar Number theoretic transform (don't know whether there is a better link) to work with integers only and avoid precision problems.
So the general outline of the algorithm becomes
calculate a0 and b0 // O(L)
calculate S = corrected_convolution(a0, b0) // O(L log L)
v0 = leftmost vertex (root)
for v in vertices:
d = dist(v0, v)
ans = ans + (S[d]-1)/2
(I call it corrected_convolution because S is not exactly a convolution, but a very similar object for which a similar algorithm can be applied. Moreover, you can even define S'[2*d]=S[d]=sum(a0[i+d]*b0[i-d])=sum(a0[i]*b0[i-2*d]), and then S' is the convolution proper.)

C++ Detect collision between two points and bouncing off the normal if there is a collision

I have a ground set up of various points, some of which are flat and others are at an angle, I'm trying to check if there is a collision between the angled points (non-axis aligned).
I have a vector array consisting of two floats at each point - This is each of the points of the ground.
Here's an image representation of what the ground looks like.
http://i.imgur.com/cgEMqUv.png?1?4597
At the moment I want to check collisions between points 1 and 2 and then go onto the others.
I shall use points 1 and 2 as an example.
g1x = 150; g2x = 980;
g2x = 500; g2y = 780;
The dxdy of this is dx = 350 and dy = -200
The normal x of this is dy and the normal y is -dx
nx = -200;
ny = -350;
normalized it is the length between points 1 and 2 which is 403.11
nx/normalized = -0.496
ny/normalized = -0.868
//get position of object - Don't know if its supposed to be velocity or not
float vix = object->getPosition().x;
float viy = object->getPosition().y;
//calculate dot product - unsure if vix/viy are supposed to be minused
float dot = ((-vix * nrmx) + (-viy * nrmy)) * nrmx; //= -131.692
Is this information correct to calculate the normal and dot product between the two points.
How can I check if there is a collision with this line and then reflect according to the normal.
Thanks :) any and all changes are welcome.
Say you have a particle at position x travelling at velocity v and a boundary defined by the line between a and b.
We can find how far along the boundary (as a fraction) the particle collides by projecting c-a onto b-a and dividing by the length ||b-a||. That is,
u = ((c-a).((b-a)/||b-a||))/||b-a|| == (c-a).(b-a) / ||b-a||2.
If u > 1 then the particle travels past the boundary on the b side, if u < 0 then the particle travels past the boundary on the a side. The point of collision would be
c = a + u b.
The time to collision could be found by solving
x + t v = a + s (b-a)
for t. The reflection matrix can be found here. But it will need to be rotated by 90 deg (or pi/2) so that you're reflecting orthogonal to the line, not across it.
In terms of multiple boundaries, calculate the time to collision for each of them, sort by that time (discarding negative times) and check for collisions through the list. Once you've found the one that you will collide with then you can move your particle to the point of collision, reflect it's velocity, change the delta t and redo the whole thing again (ignoring the one you just collided with) as you may collide with more than one boundary in a corner case (get it? It's a maths pun).
Linear algebra can be fun, and you can do so much more with it, getting to grips with linear algebra allows you to do some powerful things. Good luck!

Drawing Euler Angles rotational model on a 2d image

I'm currently attempting to draw a 3d representation of euler angles within a 2d image (no opengl or 3d graphic windows). The image output can be similar to as below.
Essentially I am looking for research or an algorithm which can take a Rotation Matrix or a set of Euler angles and then output them onto a 2d image, like above. This will be implemented in a C++ application that uses OpenCV. It will be used to output annotation information on a OpenCV window based on the state of the object.
I think I'm over thinking this because I should be able to decompose the unit vectors from a rotation matrix and then extract their x,y components and draw a line in cartesian space from (0,0). Am i correct in this thinking?
EDIT: I'm looking for an Orthographic Projection. You can assume the image above has the correct camera/viewing angle.
Any help would be appreciated.
Thanks,
EDIT: The example source code can now be found in my repo.
Header: https://bitbucket.org/jluzwick/tennisspindetector/src/6261524425e8d80772a58fdda76921edb53b4d18/include/projection_matrix.h?at=master
Class Definitions: https://bitbucket.org/jluzwick/tennisspindetector/src/6261524425e8d80772a58fdda76921edb53b4d18/src/projection_matrix.cpp?at=master
It's not the best code but it works and shows the steps necessary to get the projection matrix described in the accepted answer.
Also here is a youtube vid of the projection matrix in action (along with scale and translation added): http://www.youtube.com/watch?v=mSgTFBFb_68
Here are my two cents. Hope it helps.
If I understand correctly, you want to rotate 3D system of coordinates and then project it orthogonally onto a given 2D plane (2D plane is defined with respect to the original, unrotated 3D system of coordinates).
"Rotating and projecting 3D system of coordinates" is "rotating three 3D basis vectors and projecting them orthogonally onto a 2D plane so they become 2D vectors with respect to 2D basis of the plane". Let the original 3D vectors be unprimed and the resulting 2D vectors be primed. Let {e1, e2, e3} = {e1..3} be 3D orthonormal basis (which is given), and {e1', e2'} = {e1..2'} be 2D orthonormal basis (which we have to define). Essentially, we need to find such operator PR that PR * v = v'.
While we can talk a lot about linear algebra, operators and matrix representation, it'd be too long of a post. It'll suffice to say that :
For both 3D rotation and 3D->2D projection operators there are real matrix representations (linear transformations; 2D is subspace of 3D).
These are two transformations applied consequently, i.e. PR * v = P * R * v = v', so we need to find rotation matrix R and projection matrix P. Clearly, after we rotated v using R, we can project the result vector vR using P.
You have the rotation matrix R already, so we consider it is a given 3x3 matrix. So for simplicity we will talk about projecting vector vR = R * v.
Projection matrix P is a 2x3 matrix with i-th column being a projection of i-th 3D basis vector ei onto {e1..2'} basis.
Let's find P projection matrix such as a 3D vector vR is linearly transformed into 2D vector v' on a 2D plane with an orthonormal basis {e1..2'}.
A 2D plane can be easily defined by a vector normal to it. For example, from the figures in the OP, it seems that our 2D plane (the plane of the paper) has normal unit vector n = 1/sqrt(3) * ( 1, 1, 1 ). We need to find a 2D basis in the 2D plane defined by this n. Since any two linearly independent vectors lying in our 2D plane would form such basis, here are infinite number of such basis. From the problem's geometry and for the sake of simplicity, let's impose two additional conditions: first, the basis should be orthonormal; second, should be visually appealing (although, this is somewhat a subjective condition). As it can be easily seen, such basis is formed trivially in the primed system by setting e1' = ( 1, 0 )' = x'-axis (horizontal, positive direction from left to right) and e2' = ( 0, 1 )' = y'-axis (vertical, positive direction from bottom to top).
Let's now find this {e1', e2'} 2D basis in {e1..3} 3D basis.
Let's denote e1' and e2' as e1" and e2" in the original basis. Noting that in our case e1" has no e3-component (z-component), and using the fact that n dot e1" = 0, we get that e1' = ( 1, 0 )' -> e1" = ( -1/sqrt(2), 1/sqrt(2), 0 ) in the {e1..3} basis. Here, dot denotes dot-product.
Then e2" = n cross e1" = ( -1/sqrt(6), -1/sqrt(6), 2/sqrt(6) ). Here, cross denotes cross-product.
The 2x3 projection matrix P for the 2D plane defined by n = 1/sqrt(3) * ( 1, 1, 1 ) is then given by:
( -1/sqrt(2) 1/sqrt(2) 0 )
( -1/sqrt(6) -1/sqrt(6) 2/sqrt(6) )
where first, second and third columns are transformed {e1..3} 3D basis onto our 2D basis {e1..2'}, i.e. e1 = ( 1, 0, 0 ) from 3D basis has coordinates ( -1/sqrt(2), -1/sqrt(6) ) in our 2D basis, and so on.
To verify the result we can check few obvious cases:
n is orthogonal to our 2D plane, so there should be no projection. Indeed, P * n = P * ( 1, 1, 1 ) = 0.
e1, e2 and e3 should be transformed into their representation in {e1..2'}, namely corresponding column in P matrix. Indeed, P * e1 = P * ( 1, 0 ,0 ) = ( -1/sqrt(2), -1/sqrt(6) ) and so on.
To finalize the problem. We now constructed a projection matrix P from 3D into 2D for an arbitrarily chosen 2D plane. We now can project any vector, previously rotated by rotation matrix R, onto this plane. For example, rotated original basis {R * e1, R * e2, R * e3}. Moreover, we can multiply given P and R to get a rotation-projection transformation matrix PR = P * R.
P.S. C++ implementation is left as a homework exercise ;).
The rotation matrix will be easy to display,
A Rotation matrix can be constructed by using a normal, binormal and tangent.
You should be able to get them back out as follows:-
Bi-Normal (y') : matrix[0][0], matrix[0][1], matrix[0][2]
Normal (z') : matrix[1][0], matrix[1][1], matrix[1][2]
Tangent (x') : matrix[2][0], matrix[2][1], matrix[2][2]
Using a perspective transform you can the add perspective (x,y) = (x/z, y/z)
To acheive an orthographic project similar to that shown you will need to multiply by another fixed rotation matrix to move to the "camera" view (45° right and then up)
You can then multiply your end points x(1,0,0),y(0,1,0),z(0,0,1) and center(0,0,0) by the final matrix, use only the x,y coordinates.
center should always transform to 0,0,0
You can then scale these values to draw to you 2D canvas.

Enlarge and restrict a quadrilateral polygon in opencv 2.3 with C++

I can't find this answer anywhere, I hope somebody could help me.
I have an image (all black) with a white generic quadrilateral polygon inside it, and the correspondent 4 corners coordinates of such polygon.
I need to find the corners of a slightly enlarged quadrilateral and the same for a slightly reduced one (the shape must be the same, just a resize of the quadrilateral inside the image).
Is there a function which allows me to do that, or should I compute manually some geometry?
Thank you for your help.
Consider a vertex p of the polygon, with its predecessor p1 and successor p2.
The vectors between these points are
v1 = p1 - p
v2 = p2 - p
(The computation is componentwise for the x and y coordinates respectively).
In the shrunk polygon the vertex p is moved to p' along the line
which halves the angle a between the vectors v1 and v2.
The vector w in this direction is
w = v1 + v2
and the unit vector v in this direction is
v = w / |w| = (w_x, w_y) / sqrt(w_x*w_x + w_y*w_y)
The new point p' is
p' = p + k * v , i.e. :
p_x' = p_x + k * v_x
p_y' = p_y + k * v_y
where k is the shifting distance (a scalar).
If the vertex p is convex (as in the figure), then k >= 0 means
shrinking and k <= 0 means expanding.
If the vertex p is concave, then k >= 0 means
expanding and k <= 0 means shrinking.
What you want is polygon offset. If you want to use an existing library. Consider using Clipper
void OffsetPolygons(const Polygons &in_polys,
Polygons &out_polys,
double delta,
JoinType jointype = jtSquare, double MiterLimit = 2.0);
This function offsets the 'polys' polygons parameter by the 'delta' amount. Positive delta values expand outer polygons and contract inner 'hole' polygons. Negative deltas do the reverse.
Although I must add for a simple geometry like a Quadrilateral it is easy to do it from scratch.
Identity all four infinite lines that form the Quadrilateral
Offset the lines parallel to themselves
Compute intersection of these new lines
Just be careful of corner cases. When you offset a quadrilateral which has one very small edge. It will become a triangle on offset.
I agree with the answer of parapura rajkumar. I wanted to add that the solution of Jiri is not 100% correct because the vertex centroid of a quadrilateral is different to the area centroid of a quadrilateral, as it is written here. For the enlargement one would have to use the area centroid - or the much more elegant solution with the parallel lines mentioned by parapura rajkumar. I just want to add the following to this answer:
You can simply determine the outer points of the enlarged quadrilateral by computing the normal vectors of the vectors between the points of the original quadrilateral. Afterwards, normalize the normal vectors, multiply them with the offset and add them to the points of the original quadrilateral. Given these outer points you can now compute the intersection of the parallel lines with this formula.