/// <summary> /// Construit une représentation graphique du Diagramme de Voronoi de la triangulation /// </summary> public void BuildVoronoi(WingedEdgeMesh mesh) { List <StandardVertex> lines = new List <StandardVertex>(); // On va commencer par construire les sommets correspondant aux centre des faces de la triangulation // qui sont les noeuds du diagramme de voronoir CleanVoronoi(); for (int i = 0; i < mesh.Faces.Count; i++) { // On récupère le centre de la face (barycentre) List <VertexWE> vertices = mesh.GetFaceVertices(mesh.Faces[i]); Vector3 center = vertices[0].Position + vertices[1].Position + vertices[2].Position; center = center / 3.0f; Troll3D.Entity entity = new Troll3D.Entity(Entity); entity.transform_.SetPosition( center.X, center.Y, 0.0f); entity.transform_.SetScale(0.02f, 0.02f, 1.0f); MaterialDX11 material = new MaterialDX11(); material.SetMainColor(0.0f, 1.0f, 1.0f, 1.0f); MeshRenderer meshrenderer = entity.AddComponent <MeshRenderer>(); meshrenderer.material_ = material; meshrenderer.model_ = Quad.GetMesh(); // On récupère les voisins List <FaceWE> neighbours = mesh.GetFaceNeighbours(mesh.Faces[i]); for (int j = 0; j < neighbours.Count; j++) { // On récupère le centre de la face (barycentre) List <VertexWE> verticesNeighbour = mesh.GetFaceVertices(neighbours[j]); Vector3 centerNeighbour = verticesNeighbour[0].Position + verticesNeighbour[1].Position + verticesNeighbour[2].Position; centerNeighbour = centerNeighbour / 3.0f; lines.Add(new StandardVertex(center)); lines.Add(new StandardVertex(centerNeighbour)); } VoronoiPoints.Add(entity); } if (lines.Count > 0) { (( LineRenderer )VoronoiLines.GetComponent(ComponentType.LineRenderer)).Display = true; (( LineRenderer )VoronoiLines.GetComponent(ComponentType.LineRenderer)).Vertices = lines; (( LineRenderer )VoronoiLines.GetComponent(ComponentType.LineRenderer)).UpdateRenderer(); } }
public void BuildVoronoi(WingedEdgeMesh mesh) { List <StandardVertex> lines = new List <StandardVertex>(); // We start by building the vertices corresponding to the face's center of the triangulation who are node of the Voronoi diagram CleanVoronoi(); for (int i = 0; i < mesh.Faces.Count; i++) { // We get back the face's center (barycentre) List <VertexWE> vertices = mesh.GetFaceVertices(mesh.Faces[i]); Vector3 center = vertices[0].Position + vertices[1].Position + vertices[2].Position; center = center / 3.0f; Troll3D.Entity entity = new Troll3D.Entity(Entity); entity.transform_.SetPosition( center.X, center.Y, 0.0f); entity.transform_.SetScale(0.02f, 0.02f, 1.0f); MaterialDX11 material = new MaterialDX11(); material.SetMainColor(0.0f, 1.0f, 1.0f, 1.0f); MeshRenderer meshrenderer = entity.AddComponent <MeshRenderer>(); meshrenderer.material_ = material; meshrenderer.model_ = Quad.GetMesh(); // We get back the neighbours List <FaceWE> neighbours = mesh.GetFaceNeighbours(mesh.Faces[i]); for (int j = 0; j < neighbours.Count; j++) { // On récupère le centre de la face (barycentre) List <VertexWE> verticesNeighbour = mesh.GetFaceVertices(neighbours[j]); Vector3 centerNeighbour = verticesNeighbour[0].Position + verticesNeighbour[1].Position + verticesNeighbour[2].Position; centerNeighbour = centerNeighbour / 3.0f; lines.Add(new StandardVertex(center)); lines.Add(new StandardVertex(centerNeighbour)); } VoronoiPoints.Add(entity); } if (lines.Count > 0) { (( LineRenderer )VoronoiLines.GetComponent(ComponentType.LineRenderer)).Display = true; (( LineRenderer )VoronoiLines.GetComponent(ComponentType.LineRenderer)).Vertices = lines; (( LineRenderer )VoronoiLines.GetComponent(ComponentType.LineRenderer)).UpdateRenderer(); } }
public void Reorder(int width, int height) { //Checks if the site is fully included in the frame : if (Edges.Select(e => e.VVertexA).All(p => IsVectorInRange(p, width, height)) && Edges.Select(e => e.VVertexB).All(p => IsVectorInRange(p, width, height))) { IsOnBorder = false; } else { IsOnBorder = true; Vector previousIntersection = null; for (int i = Edges.Count - 1; i >= 0; i--) { VoronoiEdge edge = Edges[i]; bool isAIn = IsVectorInRange(edge.VVertexA, width, height); bool isBIn = IsVectorInRange(edge.VVertexB, width, height); if (isAIn && isBIn) // Edge is fully in, nothing to do { continue; } if (isAIn || isBIn) // One point in in, needs to be clipped { double slope = edge.DirectionVector[1] / edge.DirectionVector[0]; Vector pointIn = isAIn ? new Vector(edge.VVertexA) : new Vector(edge.VVertexB); List <Vector> intersections = new List <Vector>(); //Test collision with (0,0) => (width,0) edge : intersections.Add(new Vector(pointIn[0] - pointIn[1] / slope, 0)); //Test collision with (0,height) => (width,height) edge : intersections.Add(new Vector(pointIn[0] + (height - pointIn[1]) / slope, height)); //Test collision with (0,0) => (0,height) edge : intersections.Add(new Vector(0, pointIn[1] - pointIn[0] * slope)); //Test collision with (width,0) => (width,height) edge : intersections.Add(new Vector(width, pointIn[1] + (width - pointIn[0]) * slope)); Vector intersection = intersections.MinBy(p => Vector.Dist(p, pointIn)); Edges.RemoveAt(i); Edges.Add(new VoronoiEdge { VVertexA = intersection, VVertexB = pointIn }); if (previousIntersection == null) { previousIntersection = intersection; } else { if (intersection[0].Equals(previousIntersection[0]) || intersection[1].Equals(previousIntersection[1])) { Edges.Add(new VoronoiEdge { VVertexA = intersection, VVertexB = previousIntersection }); IsOnBorder = true; previousIntersection = null; } else { List <Vector> corners = new List <Vector> { new Vector(0, 0), new Vector(width, 0), new Vector(width, height), new Vector(0, height) }; foreach (Vector corner in corners) { if ((corner[0].Equals(previousIntersection[0]) || corner[0].Equals(intersection[0])) && (corner[1].Equals(previousIntersection[1]) || corner[1].Equals(intersection[1]))) { Edges.Add(new VoronoiEdge { VVertexA = corner, VVertexB = previousIntersection }); Edges.Add(new VoronoiEdge { VVertexA = corner, VVertexB = intersection }); IsOnBorder = true; break; } } previousIntersection = null; } } } else // Edge fully out, can be safely removed { Edges.RemoveAt(i); } } if (previousIntersection != null) { throw new InvalidOperationException("Error"); } } if (Edges.Count == 0) { throw new InvalidOperationException("No edges"); } VoronoiEdge first = Edges[Edges.Count - 1]; Edges.RemoveAt(Edges.Count - 1); Vector point; VoronoiPoints.Add(point = first.VVertexA); Edges.RemoveAll((e) => Equals(e.VVertexA, e.VVertexB)); do { VoronoiEdge edge = Edges.Single(e => e.VVertexA.Equals(point) || e.VVertexB.Equals(point)); Edges.Remove(edge); if (Equals(edge.VVertexA, point)) { VoronoiPoints.Add(point = edge.VVertexB); } else { VoronoiPoints.Add(point = edge.VVertexA); } } while (!Equals(point, first.VVertexB)); Edges.Clear(); //Reverse ordering of the points if needed : Vector v1 = VoronoiPoints[0] - VoronoiPoints[1]; Vector v2 = VoronoiCenter - VoronoiPoints[0]; if (v1[0] * v2[1] - v1[1] * v2[0] > 0) { VoronoiPoints.Reverse(); } }