public void Flip(HalfEdge a_HalfEdge) { HalfEdge h1 = a_HalfEdge; HalfEdge h2 = h1.Next; HalfEdge h3 = h2.Next; HalfEdge h4 = a_HalfEdge.Twin; HalfEdge h5 = h4.Next; HalfEdge h6 = h5.Next; if (h1.Triangle == null || h4.Triangle == null) { return; } // Remove old triangles m_Triangles.Remove(a_HalfEdge.Triangle); m_Triangles.Remove(a_HalfEdge.Twin.Triangle); h1.Next = h6; h6.Prev = h1; h6.Next = h2; h2.Prev = h6; h2.Next = h1; h1.Prev = h2; h1.Origin = h3.Origin; h4.Next = h3; h3.Prev = h4; h3.Next = h5; h5.Prev = h3; h5.Next = h4; h4.Prev = h5; h4.Origin = h6.Origin; m_Triangles.Add(new Triangle(h1)); m_Triangles.Add(new Triangle(h1.Twin)); }
public Triangle(HalfEdge a_HalfEdge) { m_Vertices = new Vertex[3]; m_HalfEdge = a_HalfEdge; m_Color = Color.red; Vertex v1 = m_HalfEdge.Origin; Vertex v2 = m_HalfEdge.Next.Origin; Vertex v3 = m_HalfEdge.Next.Next.Origin; Vertex v4 = m_HalfEdge.Next.Next.Next.Origin; if (v1 == v2 || v2 == v3 || v1 == v3) { Debug.LogError("Triangle does not have a correct 3 vertex loop."); } if (v1 != v4) { Debug.LogError("Triangle does not have a correct 3 vertex loop."); } // Fix halfedges to this triangle m_HalfEdge.Triangle = this; m_HalfEdge.Next.Triangle = this; m_HalfEdge.Next.Next.Triangle = this; // Add vertices to the array m_Vertices[0] = v1; m_Vertices[1] = v2; m_Vertices[2] = v3; }
public HalfEdge(Vertex a_Vertex) { // Using new here prevents reference equality. Is it really necessary to copy? m_Origin = new Vertex(a_Vertex.X, a_Vertex.Y, a_Vertex.Ownership); Triangle = null; Twin = null; Next = null; Prev = null; }
protected void AddVertex(Triangle a_Triangle, Vertex a_Vertex) { m_Vertices.Add(a_Vertex); m_Triangles.Remove(a_Triangle); HalfEdge h1 = a_Triangle.HalfEdge; HalfEdge h2 = h1.Next; HalfEdge h3 = h2.Next; HalfEdge h4 = new HalfEdge(h1.Origin); HalfEdge h5 = new HalfEdge(h2.Origin); HalfEdge h6 = new HalfEdge(h3.Origin); HalfEdge h7 = new HalfEdge(a_Vertex); HalfEdge h8 = new HalfEdge(a_Vertex); HalfEdge h9 = new HalfEdge(a_Vertex); m_HalfEdges.AddRange(new List<HalfEdge>() { h4, h5, h6, h7, h8, h9 }); h4.Twin = h7; h7.Twin = h4; h5.Twin = h8; h8.Twin = h5; h6.Twin = h9; h9.Twin = h6; // Set all next h1.Next = h5; h5.Prev = h1; h5.Next = h7; h7.Prev = h5; h7.Next = h1; h1.Prev = h7; h2.Next = h6; h6.Prev = h2; h6.Next = h8; h8.Prev = h6; h8.Next = h2; h2.Prev = h8; h3.Next = h4; h4.Prev = h3; h4.Next = h9; h9.Prev = h4; h9.Next = h3; h3.Prev = h9; m_Triangles.Add(new Triangle(h1)); m_Triangles.Add(new Triangle(h2)); m_Triangles.Add(new Triangle(h3)); }
private void LegalizeEdge(Vertex a_Vertex, HalfEdge a_HalfEdge, Triangle a_Triangle) { if (a_Vertex == null || a_HalfEdge == null || a_Triangle == null) { Debug.LogError("Invalid call to LegalizeEdge"); return; } Vertex v1, v2, v3; try { // Points to test v1 = a_HalfEdge.Twin.Next.Next.Origin; v2 = a_HalfEdge.Next.Twin.Next.Next.Origin; v3 = a_HalfEdge.Next.Next.Twin.Next.Next.Origin; } catch (NullReferenceException) { Debug.LogError("Null pointers in call to LegalizeEdge"); return; } if (v1 == null || v2 == null || v3 == null) { Debug.LogError("Invalid halfedge in call to LegalizeEdge"); return; } if (a_Triangle.InsideCircumcenter(v1) || a_Triangle.InsideCircumcenter(v2) || a_Triangle.InsideCircumcenter(v3)) { HalfEdge h1 = a_HalfEdge.Twin.Next.Twin; HalfEdge h2 = a_HalfEdge.Twin.Prev.Twin; Flip(a_HalfEdge); LegalizeEdge(a_Vertex, h1.Twin, h1.Twin.Triangle); LegalizeEdge(a_Vertex, h2.Twin, h2.Twin.Triangle); } }
private static void ProcessHalfEdge(HalfEdge a_H1, Dictionary<Vertex, HashSet<Vertex>> a_VoronoiEdges, Dictionary<Vertex, HashSet<Vertex>> a_InternalEdges, Dictionary<Vertex, HashSet<Vertex>> a_VoronoiToInternalEdges) { if (a_H1.Twin == null) { return; } Triangle t1 = a_H1.Triangle; Triangle t2 = a_H1.Twin.Triangle; if (t1 != null && t2 != null) { Vertex voronoiVertex = t1.Circumcenter; Vertex voronoiVertex2 = t2.Circumcenter; HashSet<Vertex> existingVoronoiEdges; if (a_VoronoiEdges.TryGetValue(voronoiVertex, out existingVoronoiEdges)) { existingVoronoiEdges.Add(voronoiVertex2); } else { a_VoronoiEdges.Add(voronoiVertex, new HashSet<Vertex>{voronoiVertex2}); } if (a_VoronoiEdges.TryGetValue (voronoiVertex2, out existingVoronoiEdges)) { existingVoronoiEdges.Add(voronoiVertex); } else { a_VoronoiEdges.Add(voronoiVertex2, new HashSet<Vertex>{voronoiVertex}); } foreach (Vertex inputVertex in t1.Vertices) { HashSet<Vertex> existingValue; if (a_InternalEdges.TryGetValue(inputVertex, out existingValue)) { existingValue.Add(voronoiVertex); } else { a_InternalEdges.Add(inputVertex, new HashSet<Vertex>{voronoiVertex}); } } HashSet<Vertex> inputVertices = new HashSet<Vertex>(t1.Vertices); HashSet<Vertex> existingInputVertices; if (a_VoronoiToInternalEdges.TryGetValue(voronoiVertex, out existingInputVertices)) { existingInputVertices.UnionWith(inputVertices); } else { a_VoronoiToInternalEdges.Add(voronoiVertex, inputVertices); } // Yes, yes, code duplication is bad. foreach (Vertex inputVertex in t2.Vertices) { HashSet<Vertex> existingValue; if (a_InternalEdges.TryGetValue(inputVertex, out existingValue)) { existingValue.Add(voronoiVertex2); } else { a_InternalEdges.Add(inputVertex, new HashSet<Vertex>{voronoiVertex2}); } } inputVertices = new HashSet<Vertex>(t2.Vertices); existingInputVertices = null; if (a_VoronoiToInternalEdges.TryGetValue(voronoiVertex2, out existingInputVertices)) { existingInputVertices.UnionWith(inputVertices); } else { a_VoronoiToInternalEdges.Add(voronoiVertex2, inputVertices); } } }
public void Create() { Vertex v1 = new Vertex(-500000, -500000); Vertex v2 = new Vertex(500000, 500000); Vertex v3 = new Vertex(-500000, 500000); Vertex v4 = new Vertex(500000, -500000); m_Vertices.AddRange(new List<Vertex>() { v1, v2, v3, v4 }); HalfEdge h1 = new HalfEdge(v1); HalfEdge h2 = new HalfEdge(v2); HalfEdge h3 = new HalfEdge(v3); m_HalfEdges.AddRange(new List<HalfEdge>() { h1, h2, h3 }); h1.Next = h2; h2.Next = h3; h3.Next = h1; h2.Prev = h1; h3.Prev = h2; h1.Prev = h3; HalfEdge h4 = new HalfEdge(v2); HalfEdge h5 = new HalfEdge(v1); HalfEdge h6 = new HalfEdge(v4); m_HalfEdges.AddRange(new List<HalfEdge>() { h4, h5, h6 }); h4.Twin = h1; h1.Twin = h4; h4.Next = h5; h5.Next = h6; h6.Next = h4; h5.Prev = h4; h6.Prev = h5; h4.Prev = h6; HalfEdge h7 = new HalfEdge(v1); HalfEdge h8 = new HalfEdge(v2); HalfEdge h9 = new HalfEdge(v3); HalfEdge h10 = new HalfEdge(v4); m_HalfEdges.AddRange(new List<HalfEdge>() { h7, h8, h9, h10 }); h10.Next = h7; h7.Prev = h10; h8.Next = h10; h10.Prev = h8; h9.Next = h8; h8.Prev = h9; h7.Next = h9; h9.Prev = h7; h3.Twin = h7; h7.Twin = h3; h8.Twin = h6; h6.Twin = h8; h2.Twin = h9; h9.Twin = h2; h10.Twin = h5; h5.Twin = h10; m_Triangles.Add(new Triangle(h1)); m_Triangles.Add(new Triangle(h4)); }
/// <summary> /// Deletes HalfEdge. This delete routine cannot reclaim the node, since /// hash table pointers may still be present. /// </summary> /// <param name="he">node to delete</param> internal void Delete(HalfEdge he) { he.Left.Right = he.Right; he.Right.Left = he.Left; he.Edge = null; }