Translate and transform plane geometry based on corner coordinates - three.js

I have a plane mesh with divisions and I want to specify the coordinates that each of the corners should be positioned. Moving and updating the mesh vertices achieves what I'm trying to do, so long as the plane only has no internal segments. If internal segments are added then I have more vertices than I can manually place, so these need to automatically fall in line with the transformation of the outer edges.
My initial thought here was that I could create a geometry with only four vertices, reposition them, and then increase the number of segments on my plane, apparently, this isn't something that Three.js supports, so I'm looking for a workaround.
Any thoughts would be appreciated.

I don't think that this sort of transformation is expressible as a single matrix that you could then just apply to your plane mesh. I think you really do need to calculate the coordinates of each vertex of the subdivided plane manually.
There are different ways to do this calculation. Bilinear interpolation is this case seems to do the job. Here's how you do it. If you have four points A, B, C, D, then for each internal points, its position can be found as the weighted average of (the weighted average of A and B, and the weighted average of C and D). The weights for the averages come from the index of the subdivision vertex in one direction (say, X) for the inner averages and in the other direction (say, Y) for the outer average. Your indexes run from 0 up to the number of subdivisions in that direction (inclusive), the weight should be from 0 to 1, so the weight = index / number of subdivisions.

Related

Snapping vector to a point from a grid on a sphere (icosahedron)

here is a problem that will turn your brain inside out, I'm trying to deal with it for a quite some time already.
Suppose you have sphere located in the origin of a 3d space. The sphere is segmented into a grid of equidistant points. The procedure that forms grid isn't that important but what seems simple to me is to use regular 3d computer graphics sphere generation procedure (The algorithm that forms the sphere described in the picture below)
Now, after I have such sphere (i.e. icosahedron of some degree) I need a computationally trivial procedure that will be capable to snap (an angle) of a random unit vector to it's closest icosahedron edge points. Also it is acceptable if the vector will be snapped to a center point of triangle that the vector is intersecting.
I would like to emphasise that it is important that the procedure should be computationally trivial. This means that procedures that actually create a sphere in memory and then involve a search among every triangle in sphere is not a good idea because such search will require access to global heap and ram which is slow because I need to perform this procedure millions of times on a low end mobile hardware.
The procedure should yield it's result through a set of mathematical equations based only on two values, the vector and degree of icosahedron (i.e. sphere)
Any thoughts? Thank you in advance!
============
Edit
One afterthought that just came to my mind, it seems that within diagram below step 3 (i.e. Project each new vertex to the unit sphere) is not important at all, because after bisection, projection of every vertex to a sphere would preserve all angular characteristics of a bisected shape that we are trying to snap to. So the task simplifies to identifying a bisected sub triangle coordinates that are penetrated by vector.
Make a table with 20 entries of top-level icosahedron faces coordinates - for example, build them from wiki coordinate set)
The vertices of an icosahedron centered at the origin with an
edge-length of 2 and a circumscribed sphere radius of 2 sin (2π/5) are
described by circular permutations of:
V[] = (0, ±1, ±ϕ)
where ϕ = (1 + √5)/2
is the golden ratio (also written τ).
and calculate corresponding central vectors C[] (sum of three vectors for vertices of every face).
Find the closest central vector using maximum of dot product (DP) of your vector P and all C[]. Perhaps, it is possible to reduce number of checks accounting for P components (for example if dot product of P and some V[i] is negative, there is no sense to consider faces being neighbors of V[i]). Don't sure that this elimination takes less time than direct full comparison of DP's with centers.
When big triangle face is determined, project P onto the plane of that face and get coordinates of P' in u-v (decompose AP' by AB and AC, where A,B,C are face vertices).
Multiply u,v by 2^N (degree of subdivision).
u' = u * 2^N
v' = v * 2^N
iu = Floor(u')
iv = Floor(v')
fu = Frac(u')
fv = Frac(v')
Integer part of u' is "row" of small triangle, integer part of v' is "column". Fractional parts are trilinear coordinates inside small triangle face, so we can choose the smallest value of fu, fv, 1-fu-fv to get the closest vertice. Calculate this closest vertex and normalize vector if needed.
It's not equidistant, you can see if you study this version:
It's a problem of geodesic dome frequency and some people have spent time researching all known methods to do that geometry: http://geo-dome.co.uk/article.asp?uname=domefreq, see that guy is a self labelled geodesizer :)
One page told me that the progression goes like this: 2 + 10·4N (12,42,162...)
You can simplify it down to a simple flat fractal triangle, where every triangle devides into 4 smaller triangles, and every time the subdivision is rotated 12 times around a sphere.
Logically, it is only one triangle rotated 12 times, and if you solve the code on that side, then you have the lowest computation version of the geodesic spheres.
If you don't want to keep the 12 sides as a series of arrays, and you want a lower memory version, then you can read about midpoint subdivision code, there's a lot of versions of midpoint subdivision.
I may have completely missed something. just that there isn't a true equidistant geodesic dome, because a triangle doesn't map to a sphere, only for icos.

How to Judge the Equality of 2 Triangular Meshes?

Given a triangular mesh A in 3D space. Rotate and translate all its points to generate a new mesh B.
How to determine the equality of A and B, just by their vertices and faces?
Topology of the mesh is not important, I only care about the geometric equality, A and B should be equal even if their triangulation are changed. It is
something like the transform in-variance problem for triangular mesh, only translate and rotation is considered.
To complete #Spektre's answer, if the two meshes are not exactly the same, that is there is at least a pair of nodes or edges which does not perfectly overlap, You can use the Hausdorff distance to quantify the "difference" between the two meshes.
Assuming triangle faces only.
compare number of triangles
if not matching return false.
sort triangles by their size
if the sizes and order does not match between both meshes return false.
find distinct triangle in shapes
So either the biggest or smallest in area, edge length or whatever. If not present then you need other distinct feature like 2 most distant points etc ... If none present even that then you need the RANSAC for this.
Align both meshes so the matching triangles (or feature points) will have the same position in both meshes.
compare matching vertexes
so find the closest vertex form Mesh A to each vertex in mesh B and if the distance of any them cross some threshold return false
return true
In case meshes has no distinct features for 3 you need to either use brute force loop through all combinations of triangles form A and B until #4 returns true or all combinations tested or use RANSAC for this.
There are alternatives to #3 like find the centroid and closest and farthermost points to it and use them as basis vectors instead of triangle. that requires single vertex or close group of vertexes to be the min and max. if not present like in symmetrical meshes like cube icosahedron, sphere you're out of luck.
You can enhance this by using other features from the mesh if present like color, texture coordinate ...
[Edit1] just a crazy thinking on partial approach without the need of aligninig
compute average point C
compute biggest inscribed sphere centered at C
just distance from C to its closest point
compute smallest outscribed sphere centered at C
just distance from C to its farthest point
compare the radiuses between the shapes
if not equal shapes are not identical for sure. If equal then you have to check with approaches above.
The paper On 3D Shape Similarity (Heung-yeung Shum, Martial Hebert, Katsushi Ikeuchi) computes a similarity score between two triangular meshes by comparing semiregular sphere tessellations that have been deformed to approximate the original meshes.
In this case, the meshes are expected to be identical (up to some small error due to the transformation), so an algorithm inspired by the paper could be constructed as follows:
Group the vertices of each mesh A, B by the number of neighboring vertices they have.
Choose one vertex V_A from mesh A and vertex V_Bi from mesh B, both with same number of neighbors.
The vertex and its N neighbors V_n1...V_nN form a triangle fan of N triangles. Construct N transforms which take vertex V_Bi to V_A and each possible fan (starting from a different neighbor V_Bn1, V_Bn2, ..., V_BnN) to V_An1...V_AnN.
Find the minimum of the sums of distances from each vertex of B to the closest vertex to it in A, for each N transforms for each vertex V_Bi.
If a sum of near zero is found, the vertices of the transformed mesh B coincide with vertices of A, a mapping between them can be constructed, and you can do further topological, edge presence or direction checks, as needed.

Optimize calculating distance between two borders

I have a bitmap world map where each country is drawn in a unique color. Upon loading the map I have stored all border pixels in an array per country.
Next I calculate the distance between two counties (A and B). I do this by looping over every pixel in A's border array and calculating the distance between it and every pixel in B's border array. After finding the shortest distance I store it in a lookup table.
To optimize this I have:
Filtered out all immediate neighbors beforehand
When trying to find the shortest distance between two pixels I only compare the squared distance (only when I've found the closest one do I calculate the actual distance using square root).
When storing the distance I store it for both A->B and B->A so B will then only calculate distance against C to Z and C only against D to Z, etc.
With a large map this still takes quite a lot of time, so are there any other optimizations that I could do?
Store the border pixel data in quadtree or another hierarchical structure exploiting the actual geometry (perhaps in a triangular tree). Instead of calculating true distances for N*N/2 pixels, you will calculate ranges of min/max distances for log2(N)*log2(N)/2 areas containing the border pixels, ruling out large sets of impossible candidates, then refining to next level.
Here in sample A, there are 12 squares to be compared to 4 candidate squares of sample B, leading probably to 4*5 next level candidates (all B squares and 5 closest regions in A).
Consider calculating distance not between every pixel border of A and B but let's say each 10-th. This will give you rough solution. If the precision is not enough for your purpose, you can make it more accurate by more comparisons.
Another approach may be to introduce new model of border data structure. Store it not as each point but the set of 'characteristic' points

Surface subdivision into equal parts

I have a closed contour represented by a list of points and I need to split it into equal parts, knowing the area of the parts.
I think that I can use some subdivision algorithm, like Delanuy subdivision. But with this method I have to give the centroid of the subdivded parts.
Anyone has some hints?
if i understand correctly: given say a rectangle say of area 10, and a target area of 1, you would need to partition rectangle into 10 parts, each having area of 1. So slicing the rectangles into 10 thin rectangles (like guitar frets, or bread slices) would do.
If that's the case, then I would do the following:
Create a function to compute the area of a convex poly. This is fairly trivial (since poly is convex).
Observe, since input poly is convex, any line segment that splits the polygon into two, will intersect the polygon in exactly two places. Specifically, you can triangulate the polygon by picking a vertex of the poly and connecting it to every other vert of the polygon, like a fan.
Triangulating in this fashion would create a partition that would be close to what you need. Assume that the input polygon is given by a vertex list poly = {v1, v2, v3, ..., vn}, where verts are unique and no three are co-linear (convex poly).
Observe that given a triangle of that poly formed by say (v2,v3,v4) we can compute its area, A1. Now if we grow the triangle into a poly by adding one extra vert to the next, say v5, to form (v2, v3, v4, v5) the area increased to A2 (sum of two triangles, (v2,v3,v4) and (v2,v4,v5). Due to linearity if you wanted to grow the original triangle to say A2' where A1 < A2' < A2, you can interpolate on the line segment (v4,v5) to find v4' that will give you the right area A2' that you need.
Since you can compute the total area of initial input poly, and you know the target area of each subdivision, you can cut the input poly into pieces of desired area until you subdivide the entire thing. If you want a nicer partition, you can start from the center of the polygon, i.e. first (seed triangle) would be (center, v1,v2). Then shrink/grow it until desired area, move to the next triangle, repeat.
Hope that makes sense :D

marching cubes efficiency- you can reduce 3/4rs of the edge calculations?

Normal marching cubes finds 12 edges per cube, but you can do 3 edges per cube, save the edges inside an array, and then go through the cubes again, referencing the edges from the cubes adjacent rather than calculating them.
The process to reference adjacent cubes isn't clearly discussed on the Internet so anyone using marching cubes would be welcome to help find the details of the solution. do you know an implementation already?
here is a picture showing the 3 edges in yellow that you need for each cube, instead of 12.
EDIT- I just found this solution, although it's just a part of it:
Imagine 3 edges coming from the corner of the cube with lowerest coordinates. Then all other edges just belong to other cubes. If our cube has coordinates (x,y,z), the neiboring cubes have coordinates (x+1,y,z), (x,y+1,z), (x,y,z+1), (x+1,y+1,z), (x+1,y,z+1), (x,y+1,z+1). You can imagine the edge as a vector. Then the corner of the cube have edges (1,0,0), (0,1,0), (0,0,1). The cube with coordinates (x+1,y,z) have edges (0,1,0) and (0,0,1) that belong to our cube. The cube (x+1,y+1,z) has only one edge (0,0,1) that belongs to our cube. So if you store 4 elements for the cube you can access them like that:
edge1 = cube[x][y][z][0];
edge2 = cube[x][y][z][1];
edge3 = cube[x][y][z][2];
edge4 = cube[x+1][y][z][1];
edge5 = cube[x+1][y][z][2];
edge6 = cube[x][y+1][z][0];
edge7 = cube[x][y+1][z][2];
edge8 = cube[x][y][z+1][0];
edge9 = cube[x][y][z+1][1];
edge10 = cube[x+1][y+1][z][2];
edge11 = cube[x+1][y][z+1][1];
edge12 = cube[x][y+1][z+1][0];
Now which points edge7 connect? The answer is (x,y+1,z) and (x,y+1,z)+(0,0,1)=(x,y+1,z+1).
Now which cubes edge7 connect? It is more harder. We see that coordinate z is changes along the edge this means that neibour cube has the same z coordinate. Now all others coordinates change. Where we have +1, the cube has large coordinate. Where we have +0, the cube has smaller coordinates. So the edge connects cubes (x,y,z) and (x-1,y+1,z). Other 2 cubes that has the same edge are (x,y+1,z) and (x-1,y,z).
-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=--=-=
EDIT2-
So I am doing this, and it isn't so simple. I have a loop which simultaneously calculate 8 points, 12 edges, the interpolation of edges, the bit values and a vertex the values for the edges, all in one loop.
so I am doing a new loop previous to it to calculate as much as possible and place it in arrays to used in the complicated loop.
I can recycle the interpolated values of the intersection points along edges, in an array, although I will have to recalculate all the points again in the complicated loop, because the values of the points I used to decide bit numbers that reference values in the vertex table. That confuses me! I thought that once I have the edge intersection values, I could use those directly to get the triangle tables, without having to calculate the points all over again!
in fact no.
anyway, here is another bit of information with someone that already did it, if only it was readable!
http://www.new-npac.org/projects/sv2all/sv2/vtk/patented/vtkImageMarchingCubes.cxx
scroll to this line: Cubes are responsible for edges on their min faces.
A simple way to reduce edge calculations in the way you are suggesting is to compute cubes one axis aligned plane at a time.
If you kept all of the cubes, with their edges, in memory, it would be easy to compute each edge only once and to find adjacent edges by indexing. However, you usually don't want to keep all the cubes in memory at once because of the space requirements.
A solution to this is to compute one plane of cubes at a time. i.e. an axis aligned cross-section, starting from one side and progressing to the opposite side. You then only need to keep at most two full planes of cubes in memory at a time. As you move through each plane you can reference shared edges in the previous plane and previously computed cubes in the current plane. As you move to the next plane you can deallocate the plane you will no longer need.
Edit: This article discusses doing just what I suggest:
http://alphanew.net/index.php?section=articles&site=marchoptim&lang=eng
Funny, because when I implemented my own MCs I came up with similar solution.
When you start working with MCs you treat them as a distinct cubes but if you want to go for high performance you'll need to create entire mesh as a whole, and creating vertex indices etc. is not so easy here. It gets even more interesting when you want to add smooth per-vertex normals :).
To solve this I created a simple index cache mechanism to store vertex indices for each edge.
Then, for each computed edge I have cube position x,y,z and edge index and I do as follows:
For each axis:
if the edge is on '+' side of axis:
replace edge index with its '-' side sibling
increment cube position along axis
This simple operation gives me the correct cube position, and edge index of 0,1,2. Then I compute a total cache index from x,y,z,edgeIndex values with simple bit rotations.
When I have cache index I check if it's bigger than -1. If it is then there was an already computed vertex at this edge and I can reuse it. If it's -1 I need to create a new vertex and store its index in the cache. This way you'll compute each vertex only once, and you can even add a normal value shared between every triangle containing your vertex.
Yes, I think I do it similar to kolenda. I have a struct with 5 ints: (cube)index and 4 vertexindices (A, B, C, D).
for the most inner loop (x), I have just lastXCache and nextXCache. On the 4 edges pointing in the -x direction, i ask if lastXCache.A != -1 and if so, assign the previously calculated value, etc.
In the +x direction I store calculated vertices in nextXCache. when cube is done: lastXCache = nextXCache;
For y and z direction it needs to be a list (unity term for mutable array), next y is next row (so sizex) and next z is the next plane (so sizex * sizey)
only diadvantage is that this way it has to run cube after cube, so serially. But you can calculate different chunks in parallel.
Another way I thought of that could be more parallel would need 2 passes: 1. calculate 3 edges every cube, when 1 is done -> 2. draw the triangles.
Don't really know what is better, but the way it actually works seems to be fast enough. even better with unity jobs. Create one IJob for 1 chunk/mesh.

Resources