Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Intersection of a mesh with a parametric surface

I'm wondering how a precise algorithm can be written to compute the frontier of the surface of intersection between a parametric surface f : R^2 --> R^3 and a triangulated mesh.

I've thought to a first approach:

nStepsU = 100
nStepsV = 100
tolerance=0.01 // pick some sensical value
intersectionVertices={}
for  u from minU to maxU in nStepsU:
    for v from minV to maxV in nStepsV:
        for v in verticesInMesh:
             if euclidean distance( f(u,v), v ) < tolerance:
                 add vertex v in a set

connect the vertices in intersectionVertices with a line strip
draw the vertices in intersectionVertices

This algorithm, is very simple but slow (n^3) and does not keep in account that the topography of the mesh is based on triangles so the output points are points of the mesh and not points computed exploiting the intersection of surface with the triangles and is heavily dependent of the tolerance one has to set.

Has someone some better idea or can one drive me to a suitable library for this purpose?

like image 866
linello Avatar asked Jun 10 '13 20:06

linello


Video Answer


2 Answers

I would iterate over each triangle, and compute the intersection of the triangle with the surface. I would use a geometry shader which takes the triangles as input, and outputs line strips. For each vertex in the triangle, compute the signed distance to the surface. Then iterate over the edges: If there are two vertices where h has different signs, the edge between these vertices intersects with the surface. While I'm sure the exact intersection can be computed, the easiest solution would be to interpolate linearly, i.e.

vec3 intersection = (h0 * v1 + h1 * v0) / (h0 + h1);

Then output each intersection as a vertex of your line segment.

The code I posted here can get you started. If you want to just draw the result, you will probably run into the same problem that I described in that question. If you need the vertices on the client, you can use transform feedback.

Edit: I just did a little test. As the distance function I used

float distToHelicoid(in vec3 p)
{
  float theta = p.y / 5 + offset.x / 50;
  float a = mod(theta - atan(p.z, p.x), 2*PI) - PI; // [-PI, PI[
  if (abs(a) > PI/2)
    a = mod(theta - atan(-p.z, -p.x), 2*PI) - PI;
  return a;
}

Since there is no inside/outside, and this distance function goes from -90° to 90°, you can only emit vertices if the sign goes from small negative to small positive or vice versa, not when it flips from 90° to -90°. Here I simply filtered out distances where abs(dist) > 45°:

enter image description here

The clean way would be to determine the index of the closest revolution. E.g. [-pi, pi] would be revolution 0, [pi, 3pi] = revolution 1, etc. You would then only emit if two distances refer to the same revolution.

like image 198
Andreas Haferburg Avatar answered Oct 29 '22 12:10

Andreas Haferburg


If your surface is always helicoid, you can try to project everything on a cylinder around axis Y.

The surface of helicoid consists of lines orthogonal to the surface of that cylinder and after projection you will get a spiral. After projection of 3D triangle mesh onto that cylinder you will get 2D triangle mesh (note that some areas may be covered with several layers of triangles).

So the task becomes finding triangles in 2D triangle mesh intersecting the spiral which is simpler. If you are OK with approximations, you can segment that spiral and use some kind of tree to find triangles intersecting the spiral.

When you have a triangle intersecting part of spiral, its intersection will be a segment, you can just recalculate 3D coordinates of the segment and set of these segments is your intersection line.

like image 24
maxim1000 Avatar answered Oct 29 '22 14:10

maxim1000