diff --git a/mesh/MeshEditor.cs b/mesh/MeshEditor.cs index 0b840ee6..89d66585 100644 --- a/mesh/MeshEditor.cs +++ b/mesh/MeshEditor.cs @@ -84,8 +84,8 @@ public virtual int[] AddTriangleFan_OrderedEdgeLoop(int center, int[] edge_loop, operation_failed: // remove what we added so far if (i > 0) { - if (remove_triangles(new_tris, i) == false) - throw new Exception("MeshConstructor.AddTriangleFan_OrderedEdgeLoop: failed to add fan, and also falied to back out changes."); + if (remove_triangles(new_tris, i-1) == false) + throw new Exception("MeshConstructor.AddTriangleFan_OrderedEdgeLoop: failed to add fan, and also failed to back out changes."); } return null; } @@ -94,6 +94,48 @@ public virtual int[] AddTriangleFan_OrderedEdgeLoop(int center, int[] edge_loop, + public virtual int[] StitchLoop(int[] vloop1, int[] vloop2, int group_id = -1) + { + int N = vloop1.Length; + if (N != vloop2.Length) + throw new Exception("MeshEditor.StitchLoop: loops are not the same length!!"); + + int[] new_tris = new int[N * 2]; + + int i = 0; + for ( ; i < N; ++i ) { + int a = vloop1[i]; + int b = vloop1[(i + 1) % N]; + int c = vloop2[i]; + int d = vloop2[(i + 1) % N]; + + Index3i t1 = new Index3i(b, a, d); + Index3i t2 = new Index3i(a, c, d); + + int tid1 = Mesh.AppendTriangle(t1, group_id); + int tid2 = Mesh.AppendTriangle(t2, group_id); + + if (tid1 == DMesh3.InvalidID || tid2 == DMesh3.InvalidID) + goto operation_failed; + + new_tris[2 * i] = tid1; + new_tris[2 * i + 1] = tid2; + } + + return new_tris; + + + operation_failed: + // remove what we added so far + if (i > 0) { + if (remove_triangles(new_tris, 2*(i-1)) == false) + throw new Exception("MeshConstructor.StitchLoop: failed to add all triangles, and also failed to back out changes."); + } + return null; + } + + + // [TODO] cannot back-out this operation right now diff --git a/mesh_ops/MeshExtrusion.cs b/mesh_ops/MeshExtrusion.cs new file mode 100644 index 00000000..979b0ee0 --- /dev/null +++ b/mesh_ops/MeshExtrusion.cs @@ -0,0 +1,71 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace g3 +{ + public class MeshExtrusion + { + public DMesh3 Mesh; + public EdgeLoop Loop; + + // arguments + + // set new position based on original loop vertex position, normal, and index + public Func PositionF; + + // outputs + + public int[] NewTriangles; + public EdgeLoop NewLoop; + + + public MeshExtrusion(DMesh3 mesh, EdgeLoop loop) + { + Mesh = mesh; + Loop = loop; + + PositionF = (pos, normal, idx) => { + return pos + Vector3d.AxisY; + }; + } + + + public virtual ValidationStatus Validate() + { + ValidationStatus loopStatus = MeshValidation.IsBoundaryLoop(Mesh, Loop); + return loopStatus; + } + + + public virtual bool Extrude(int group_id = -1) + { + // duplicate loop vertices + int NV = Loop.Vertices.Length; + NewLoop = new EdgeLoop(Mesh); + NewLoop.Vertices = new int[NV]; + + for ( int i = 0; i < NV; ++i ) { + int vid = Loop.Vertices[i]; + NewLoop.Vertices[i] = Mesh.AppendVertex(Mesh, vid); + } + + // move to offset positions + for ( int i = 0; i < NV; ++i ) { + Vector3d v = Mesh.GetVertex(Loop.Vertices[i]); + Vector3f n = Mesh.GetVertexNormal(Loop.Vertices[i]); + Vector3d new_v = PositionF(v, n, i); + Mesh.SetVertex(NewLoop.Vertices[i], new_v); + } + + // stitch interior + MeshEditor edit = new MeshEditor(Mesh); + NewTriangles = edit.StitchLoop(Loop.Vertices, NewLoop.Vertices, group_id); + + return true; + } + + + } +} diff --git a/mesh_ops/SimpleHoleFiller.cs b/mesh_ops/SimpleHoleFiller.cs index 18b3bb87..53cad00e 100644 --- a/mesh_ops/SimpleHoleFiller.cs +++ b/mesh_ops/SimpleHoleFiller.cs @@ -10,8 +10,8 @@ public class SimpleHoleFiller public DMesh3 Mesh; public EdgeLoop Loop; - int NewVertex; - int[] NewTriangles; + public int NewVertex; + public int[] NewTriangles; public SimpleHoleFiller(DMesh3 mesh, EdgeLoop loop) @@ -24,7 +24,15 @@ public SimpleHoleFiller(DMesh3 mesh, EdgeLoop loop) } - public bool Fill(int group_id = -1) + + public virtual ValidationStatus Validate() + { + ValidationStatus loopStatus = MeshValidation.IsBoundaryLoop(Mesh, Loop); + return loopStatus; + } + + + public virtual bool Fill(int group_id = -1) { if (Loop.Vertices.Length < 3) return false; diff --git a/queries/MeshValidation.cs b/queries/MeshValidation.cs new file mode 100644 index 00000000..4d4fc1de --- /dev/null +++ b/queries/MeshValidation.cs @@ -0,0 +1,52 @@ +using System; +using System.Collections.Generic; + + +namespace g3 +{ + public enum ValidationStatus + { + Ok, + + NotBoundaryVertex, + NotBoundaryEdge, + + VerticesNotConnectedByEdge, + IncorrectLoopOrientation + } + + + public static class MeshValidation + { + + public static ValidationStatus IsBoundaryLoop(DMesh3 mesh, EdgeLoop loop) + { + int N = loop.Vertices.Length; + + for ( int i = 0; i < N; ++i ) { + if ( ! mesh.vertex_is_boundary(loop.Vertices[i]) ) + return ValidationStatus.NotBoundaryVertex; + } + + for ( int i = 0; i < N; ++i ) { + int a = loop.Vertices[i]; + int b = loop.Vertices[(i + 1) % N]; + + int eid = mesh.FindEdge(a, b); + if (eid == DMesh3.InvalidID) + return ValidationStatus.VerticesNotConnectedByEdge; + + if (mesh.edge_is_boundary(eid) == false) + return ValidationStatus.NotBoundaryEdge; + + Index2i ev = mesh.GetOrientedBoundaryEdgeV(eid); + if (!(ev.a == a && ev.b == b)) + return ValidationStatus.IncorrectLoopOrientation; + } + + return ValidationStatus.Ok; + } + + + } +}