public void RemoveFacet(MeshFacet f)
        {
            int i = f.Index;

            if (facets[i] != f)
            {
                return;
            }

            triangles -= f.TrianglesCount;

            if (i != facets.Count - 1)
            {
                facets[i] = facets.Last();
                facets[i].SetGraphInfo(this, i);
            }

            facets.RemoveAt(facets.Count - 1);
            f.Selected = false;
            foreach (MeshEdge e in f.Edges)
            {
                if (e.f1 == f)
                {
                    e.f1 = null;
                }
                else if (e.f2 == f)
                {
                    e.f2 = null;
                }
                else
                {
                    throw new Exception("Unexpected edge");
                }
            }
        }
 public MeshFacet Eqv(MeshFacet f)
 {
     if (f == null)
     {
         return(null);
     }
     return(facets[f.Index]);
 }
        public Tuple <MeshVertex, MeshVertex> VerticesInFacet(MeshFacet f)
        {
            if (f1 == f)
            {
                return(new Tuple <MeshVertex, MeshVertex>(p1, p2));
            }
            if (f2 == f)
            {
                return(new Tuple <MeshVertex, MeshVertex>(p2, p1));
            }

            return(null);
        }
        public MeshGraph Clone()
        {
            MeshGraph mg = new MeshGraph();

            mg.triangles = this.triangles;

            foreach (MeshVertex v in vertices)
            {
                MeshVertex new_v = new MeshVertex(v.Position);
                new_v.SetGraphInfo(mg, mg.vertices.Count);
                mg.vertices.Add(new_v);
            }

            foreach (MeshEdge e in edges)
            {
                MeshEdge new_e = new MeshEdge(mg.Eqv(e.V1), mg.Eqv(e.V2));
                new_e.SetGraphInfo(mg, mg.edges.Count);
                mg.edges.Add(new_e);
            }

            foreach (MeshFacet f in facets)
            {
                MeshFacet new_f = new MeshFacet();
                foreach (MeshVertex v in f.vertices)
                {
                    new_f.vertices.Add(mg.Eqv(v));
                }
                new_f.SetGraphInfo(mg, mg.facets.Count);
                mg.facets.Add(new_f);
            }

            // Maintain adjacency cache
            foreach (MeshEdge e in mg.edges)
            {
                MeshEdge old_e = this.Eqv(e);
                e.f1 = mg.Eqv(old_e.f1);
                e.f2 = mg.Eqv(old_e.f2);
            }

            foreach (MeshVertex v in mg.vertices)
            {
                MeshVertex old_v = this.Eqv(v);
                foreach (var entry in old_v.adjacency)
                {
                    v.adjacency.Add(mg.Eqv(entry.Key), mg.Eqv(entry.Value));
                }
            }

            return(mg);
        }
        public void CreateTriangle()
        {
            MeshVertex v1 = new MeshVertex(1, 0, 1);
            MeshVertex v2 = new MeshVertex(2, 1, 0);
            MeshVertex v3 = new MeshVertex(1, 3, 1);

            MeshGraph mg = new MeshGraph();

            mg.AddVertex(v1);
            mg.AddVertex(v2);
            mg.AddVertex(v3);

            MeshEdge  e1 = mg.AddEdge(v1, v2);
            MeshEdge  e2 = mg.AddEdge(v3, v2);
            MeshFacet f  = mg.AddFacet(v1, v2, v3);

            CollectionAssert.Contains(mg.Vertices, v1);
            CollectionAssert.Contains(mg.Vertices, v2);
            CollectionAssert.Contains(mg.Vertices, v3);
            Assert.AreEqual(v1.EdgeConnecting(v2), v2.EdgeConnecting(v1), "", e1);
            Assert.AreEqual(v3.EdgeConnecting(v2), v2.EdgeConnecting(v3), "", e2);

            CollectionAssert.Contains(mg.Edges, v1.EdgeConnecting(v2));
            CollectionAssert.Contains(mg.Edges, v2.EdgeConnecting(v3));
            CollectionAssert.Contains(mg.Edges, v3.EdgeConnecting(v1));
            CollectionAssert.Contains(e1.AdjacencyFacets, f);
            CollectionAssert.Contains(e1.Endpoints, v1);

            CollectionAssert.Contains(f.Vertices, v1);
            CollectionAssert.Contains(f.Vertices, v2);
            CollectionAssert.Contains(f.Vertices, v3);
            CollectionAssert.Contains(f.Edges, v1.EdgeConnecting(v2));
            CollectionAssert.Contains(f.Edges, v2.EdgeConnecting(v3));
            CollectionAssert.Contains(f.Edges, v3.EdgeConnecting(v1));

            {   // Remove the facet
                MeshGraph rm  = mg.Clone();
                MeshFacet rmf = rm.Eqv(f);
                rm.RemoveFacet(rmf);

                CollectionAssert.DoesNotContain(rm.Facets, rmf);
                CollectionAssert.DoesNotContain(
                    rm.Eqv(e1).AdjacencyFacets, rmf);
                CollectionAssert.DoesNotContain(
                    rm.Eqv(e2).AdjacencyFacets, rmf);
            }

            {   // Remove an edge
                MeshGraph rm  = mg.Clone();
                MeshEdge  rme = rm.Eqv(e1);
                MeshFacet rmf = rm.Eqv(f);
                rm.RemoveEdge(rme);

                CollectionAssert.DoesNotContain(rm.Edges, rme);
                CollectionAssert.DoesNotContain(rm.Facets, rmf);
                CollectionAssert.DoesNotContain(
                    rme.AdjacencyFacets, rmf);
                CollectionAssert.DoesNotContain(
                    rm.Eqv(e2).AdjacencyFacets, rmf);
            }

            {   // Remove an vertex
                MeshGraph  rm   = mg.Clone();
                MeshVertex rmv  = rm.Eqv(v2);
                MeshEdge   rme1 = rm.Eqv(v2.EdgeConnecting(rm.Eqv(v1)));
                MeshEdge   rme2 = rm.Eqv(v2.EdgeConnecting(rm.Eqv(v3)));
                MeshFacet  rmf  = rm.Eqv(f);
                rm.RemoveVertex(rmv);

                CollectionAssert.DoesNotContain(rm.Vertices, rmv);
                CollectionAssert.DoesNotContain(rm.Edges, rme1);
                CollectionAssert.DoesNotContain(rm.Edges, rme2);
                CollectionAssert.DoesNotContain(rm.Facets, rmf);

                Assert.AreEqual(rmv.Edges.Count, 0);
                foreach (var v in rm.Vertices)
                {
                    Assert.AreEqual(v.Edges.Count, 1);
                }
            }
        }
        public MeshFacet AddFacet(params MeshVertex[] vs)
        {
            if (vs.Length < 3)
            {
                throw new Exception("Vertex count less than 3.");
            }
            for (int vi = 0; vi < vs.Length; vi++)
            {
                if (vs[vi] == vs[(vi + 1) % vs.Length])
                {
                    throw new Exception("Ill-formed vertex sequence");
                }
            }

            MeshFacet f = new MeshFacet(vs);

            string failure = "";

            for (int vi = 0; vi < vs.Length; vi++)
            {
                MeshVertex p1 = vs[vi];
                MeshVertex p2 = vs[(vi + 1) % vs.Length];

                MeshEdge e = AddEdge(p1, p2);

                if (e.V1 == p1 && e.V2 == p2)
                {
                    if (e.f1 != null)
                    {
                        failure = "Positive facet has been occupied";
                        break;
                    }
                    e.f1 = f;
                }
                else if (e.V1 == p2 && e.V2 == p1)
                {
                    if (e.f2 != null)
                    {
                        failure = "Negative facet has been occupied";
                        break;
                    }
                    e.f2 = f;
                }
                else
                {
                    throw new Exception("Unexpected edge");
                }
            }

            // rollback
            if (failure.Length > 0)
            {
                foreach (MeshEdge e in f.Edges)
                {
                    if (e == null)
                    {
                        continue;
                    }
                    if (e.f1 == f)
                    {
                        e.f1 = null;
                    }
                    if (e.f2 == f)
                    {
                        e.f2 = null;
                    }
                }
                throw new Exception(failure);
            }

            int i = facets.Count;

            facets.Add(f);
            f.SetGraphInfo(this, i);

            triangles += f.TrianglesCount;

            return(f);
        }
        public MeshEdge AddEdge(MeshVertex p1, MeshVertex p2,
                                bool check_facet = false)
        {
            MeshEdge e = p1.EdgeConnecting(p2);

            if (e != null)
            {
                return(e);
            }
            if (p1 == p2)
            {
                return(null);
            }

            e = new MeshEdge(p1, p2);
            p1.adjacency.Add(p2, e);
            p2.adjacency.Add(p1, e);

            int i = edges.Count;

            edges.Add(e);
            e.SetGraphInfo(this, i);

            if (check_facet)
            {
                // check the intersection
                MeshFacet           common_facet = null;
                HashSet <MeshFacet> p1f          = new HashSet <MeshFacet>(
                    p1.AdjacencyFacets);
                foreach (MeshFacet f in p2.AdjacencyFacets)
                {
                    if (p1f.Contains(f))
                    {
                        common_facet = f;
                        break;
                    }
                }

                if (common_facet != null)
                {
                    List <MeshVertex> f1 = new List <MeshVertex>();
                    List <MeshVertex> f2 = new List <MeshVertex>();

                    List <MeshVertex> current = f1;
                    foreach (MeshVertex v in common_facet.Vertices)
                    {
                        // if current vertex matches p1 or p2, add this vertex
                        // to both vertex list and switch current to the other one
                        current.Add(v);

                        if (v == p1)
                        {
                            current = current == f1 ? f2 : f1;
                            current.Add(p1);
                        }
                        else if (v == p2)
                        {
                            current = current == f1 ? f2 : f1;
                            current.Add(p2);
                        }
                    }

                    this.RemoveFacet(common_facet);
                    this.AddFacet(f1.ToArray());
                    this.AddFacet(f2.ToArray());
                }
            }

            return(e);
        }