private void TestFlip(List <Vector3> points, Triangles triangles, WorkBuffer <Int2> stack, int a, int b, int x) { var y = triangles.Opposite(a, b); //Test boundary edge if (y < 0) { return; } //Swap edge if order flipped if (b < a) { var tmp = a; a = b; b = tmp; tmp = x; x = y; y = tmp; } //Test if edge is constrained if (triangles.IsConstraint(a, b)) { return; } //Test if edge is delaunay if (Robust.InSphere(points[a], points[b], points[x], points[y]) < 0f) { var v = new Int2(a, b); stack.Push(ref v); } }
//Assume edges are sorted lexicographically public void RefineTriangles(Triangles triangles) { var stack = WorkBufferPool.Get <Int2>(); var points = triangles.Vertices; var numPoints = points.Count; var stars = triangles.Stars; for (var a = 0; a < numPoints; ++a) { var star = stars[a]; var starData = star.Data; var sl = star.UsedSize; for (var j = 0; j < sl; ++j) { var s = starData[j]; var b = s.y; //If order is not consistent, then skip edge if (b < a) { continue; } //Check if edge is constrained if (triangles.IsConstraint(a, b)) { continue; } //Find opposite edge var x = s.x; var y = -1; for (var k = 0; k < sl; ++k) { if (starData[k].x == b) { y = starData[k].y; break; } } //If this is a boundary edge, don't flip it if (y < 0) { continue; } //If edge is in circle, flip it if (Robust.InSphere(points[a], points[b], points[x], points[y]) < 0f) { var v = new Int2(a, b); stack.Push(ref v); } } } while (stack.UsedSize > 0) { var v = stack.Pop(); var a = v.x; var b = v.y; //Find opposite pairs var x = -1; var y = -1; var star = stars[a]; var starData = star.Data; var sl = star.UsedSize; for (var i = 0; i < sl; ++i) { var s = starData[i].x; var t = starData[i].y; if (s == b) { y = t; } else if (t == b) { x = s; } } //If x/y are both valid then skip edge if (x < 0 || y < 0) { continue; } //If edge is now delaunay, then don't flip it if (Robust.InSphere(points[a], points[b], points[x], points[y]) >= 0f) { continue; } //Flip the edge triangles.Flip(a, b); //Test flipping neighboring edges TestFlip(points, triangles, stack, x, a, y); TestFlip(points, triangles, stack, a, y, x); TestFlip(points, triangles, stack, y, b, x); TestFlip(points, triangles, stack, b, x, y); } WorkBufferPool.Release(ref stack); }
private FaceIndex IndexCells(Triangles triangles) { var zero = 0; var fals = false; var index = new FaceIndex(WorkBufferPool); triangles.Fill(index.Cells); //First get cells and canonicalize var cells = index.Cells; var nc = cells.UsedSize; var cellsData = cells.Data; for (var i = 0; i < nc; ++i) { var c = cellsData[i]; var x = c.x; var y = c.y; var z = c.z; if (y < z) { if (y < x) { c.x = y; c.y = z; c.z = x; cellsData[i] = c; } } else if (z < x) { c.x = z; c.y = x; c.z = y; cellsData[i] = c; } } WorkBuffer <Int3> .Sort(cells); //Initialize flag array var flags = index.Flags; flags.Fill(ref zero, nc); //Build neighbor index, initialize queues var active = index.Active; var next = index.Next; var neighbor = index.Neighbor; var constraint = index.Constraint; var boundary = index.Boundary; neighbor.Fill(ref zero, nc * 3); constraint.Fill(ref fals, nc * 3); var flagsData = flags.Data; var neighborData = neighbor.Data; var constraintData = constraint.Data; for (var i = 0; i < nc; ++i) { var c = cellsData[i]; for (var j = 0; j < 3; ++j) { var x = 0; var y = 0; switch (j) { case 0: x = c.x; y = c.y; break; case 1: x = c.y; y = c.z; break; case 2: x = c.z; y = c.x; break; } var a = neighborData[3 * i + j] = Locate(cells, y, x, triangles.Opposite(y, x)); var b = constraintData[3 * i + j] = triangles.IsConstraint(x, y); if (a < 0) { if (b) { next.Push(ref i); } else { active.Push(ref i); flagsData[i] = 1; } if (Infinity) { var v = new Int3(y, x, -1); boundary.Push(ref v); } } } } return(index); }