Esempio n. 1
0
        /// <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 DelaunayIncremental()
        {
            List <Entity> p             = new List <Entity>();
            List <Entity> currentPoints = new List <Entity>();

            p.AddRange(Points);

            WingedEdgeMesh mesh = new WingedEdgeMesh();

            // We start by making a first triangle

            mesh.AddVertex(-2.0f, -1.0f, 0.0f);
            mesh.AddVertex(-2.0f, 5.0f, 0.0f);
            mesh.AddVertex(2.0f, -1.0f, 0.0f);

            mesh.AddFace(mesh.Vertices[0], mesh.Vertices[1], mesh.Vertices[2]);

            //  Now, we're  going to triangulate vertex per vertex
            // We get back 1 vertex from the set of vertices, we look for the triangle containing it, then,
            // we subdivide  it in 3 triangles. We then check that every new triangle  is Delaunay. If not, we  flip/switchover the
            // opposite edge of  the new vertex
            while (p.Count > 0)
            {
                // We start by extracting a point from the set of vertices

                Entity point = p[0];
                p.RemoveAt(0);

                FaceWE f      = null;
                int    findex = 0;

                // Looking for the triangle that contains the dot
                for (int i = 0; i < mesh.Faces.Count; i++)
                {
                    FaceWE          currentFace = mesh.Faces[i];
                    List <VertexWE> vertices    = mesh.GetFaceVertices(currentFace);

                    bool isIn = Troll3D.TRaycast.PointInTriangle(vertices[0].Position, vertices[1].Position, vertices[2].Position, point.transform_.position_);

                    if (isIn)
                    {
                        f      = currentFace;
                        findex = i;
                    }
                }

                //  In theory, we should have get back a triangle that contains the vertex. We're now going to divide that
                // in 3 triangles using the current vertex

                List <FaceWE> faces = mesh.AddVertex(f, point.transform_.position_.X, point.transform_.position_.Y, point.transform_.position_.Z);

                // Now we must check  that the triangles we found are Delaunay. Meaning that the
                // circumscribed circle of the triangle must contains only points of the triangle.

                // Checking the faces created
                for (int i = 0; i < faces.Count; i++)
                {
                    InspectEdge(faces[i].Edges, mesh);
                }
            }

            //Removing mesh thing used  for triangulation
            List <FaceWE> faceToRemove = new List <FaceWE>();

            for (int i = mesh.Faces.Count - 1; i >= 0; i--)
            {
                if (mesh.IsFaceBorder(mesh.Faces[i]))
                {
                    faceToRemove.Add(mesh.Faces[i]);
                }
            }

            for (int i = 0; i < faceToRemove.Count; i++)
            {
                mesh.RemoveFace(faceToRemove[i]);
            }

            for (int i = 0; i < CircleCenter.Count; i++)
            {
                Scene.CurrentScene.RemoveRenderable(( MeshRenderer )CircleCenter[i].GetComponent(ComponentType.MeshRenderer));
            }

            if (DisplayCenters)
            {
                for (int i = 0; i < Circles.Count; i++)
                {
                    Scene.CurrentScene.RemoveRenderable(( LineRenderer )Circles[i].GetComponent(ComponentType.LineRenderer));
                }

                CircleCenter.Clear();

                for (int i = 0; i < mesh.Faces.Count; i++)
                {
                    List <VertexWE> vertices = mesh.GetFaceVertices(mesh.Faces[i]);

                    Vector3 circleCenter = GetCircleCenter(vertices[0].Position, vertices[1].Position, vertices[2].Position);
                    float   radius       = GetCircleRadius(vertices[0].Position, vertices[1].Position, vertices[2].Position, circleCenter);

                    AddCircleCenter(circleCenter.X, circleCenter.Y, radius);
                }
            }
            else
            {
                for (int i = 0; i < Circles.Count; i++)
                {
                    Scene.CurrentScene.RemoveRenderable(( LineRenderer )Circles[i].GetComponent(ComponentType.LineRenderer));
                }
                CircleCenter.Clear();
            }

            if (mesh.MakeMesh() != null)
            {
                meshRenderer.model_ = mesh.MakeMesh();
                meshRenderer.SetFillMode(SharpDX.Direct3D11.FillMode.Wireframe);
                meshRenderer.material_.SetMainColor(1.0f, 0.0f, 0.0f, 1.0f);
            }
            else
            {
            }

            if (DisplayVoronoi)
            {
                BuildVoronoi(mesh);
            }
            else
            {
                CleanVoronoi();
            }
        }
        /// <summary>
        /// Check an edge and determine if it needs to  be change? If yes the function call itself again
        /// </summary>
        /// <param name="e"></param>
        private void InspectEdge(List <EdgeWE> edges, WingedEdgeMesh mesh)
        {
            foreach (EdgeWE e in edges)
            {
                // Wefirstcheck that the edge connect 2 triangles
                if (e.LeftFace != null && e.RightFace != null)
                {
                    List <VertexWE> v1 = mesh.GetFaceVertices(e.LeftFace);
                    List <VertexWE> v2 = mesh.GetFaceVertices(e.RightFace);

                    //  We get the opposite side of  the left face
                    VertexWE leftOppositeVertex = null;

                    for (int i = 0; i < v1.Count; i++)
                    {
                        if ((v1[i] != e.Vertex1) && (v1[i] != e.Vertex2))
                        {
                            leftOppositeVertex = v1[i];
                        }
                    }

                    //We get the opposite side of the right face
                    VertexWE rightOppositeVertex = null;

                    for (int i = 0; i < v2.Count; i++)
                    {
                        if ((v2[i] != e.Vertex1) && (v2[i] != e.Vertex2))
                        {
                            rightOppositeVertex = v1[i];
                        }
                    }

                    // We get back informations about the circles from the left and right face

                    Vector3 leftCircleCenter = GetCircleCenter(v1[0].Position, v1[1].Position, v1[2].Position);
                    float   leftCircleRadius = GetCircleRadius(v1[0].Position, v1[1].Position, v1[2].Position, leftCircleCenter);

                    Vector3 rightCircleCenter = GetCircleCenter(v2[0].Position, v2[1].Position, v2[2].Position);
                    float   rightCircleRadius = GetCircleRadius(v2[0].Position, v2[1].Position, v2[2].Position, rightCircleCenter);

                    // We check if one of the opposite side can fit in  the circle of  the opposite face
                    if (IsPointInCircle(leftOppositeVertex.Position, rightCircleCenter, rightCircleRadius) || IsPointInCircle(rightOppositeVertex.Position, leftCircleCenter, leftCircleRadius))
                    {
                        // We switchover the edge
                        List <FaceWE> newfaces = mesh.FlipEdge(e);

                        // We inspect the new edges

                        List <EdgeWE> newEdges = new List <EdgeWE>();

                        for (int i = 0; i < newfaces.Count; i++)
                        {
                            for (int j = 0; j < newfaces[i].Edges.Count; j++)
                            {
                                if (newEdges.Contains(newfaces[i].Edges[j]))
                                {
                                    newEdges.Add(newfaces[i].Edges[j]);
                                }
                            }
                        }
                        InspectEdge(newEdges, mesh);
                        return;
                    }
                }
            }
            return;
        }
Esempio n. 5
0
        /// <summary>
        /// Implémentation de l'algorithme de triangulation de Delaunay incremental
        /// </summary>
        public void DelaunayIncremental()
        {
            List <Entity> p             = new List <Entity>();
            List <Entity> currentPoints = new List <Entity>();

            p.AddRange(Points);

            WingedEdgeMesh mesh = new WingedEdgeMesh();

            // On commence par créer un big triangle capable de contenir tout les autres

            mesh.AddVertex(-2.0f, -1.0f, 0.0f);
            mesh.AddVertex(-2.0f, 5.0f, 0.0f);
            mesh.AddVertex(2.0f, -1.0f, 0.0f);

            mesh.AddFace(mesh.Vertices[0], mesh.Vertices[1], mesh.Vertices[2]);

            // Maintenant, on va trianguler point par point
            // On récupère un point de l'ensemble de point, on cherche le triangle qui le contient,
            // puis, on subdivise en 3 triangles. On vérifie ensuite que chacun des triangles crée est
            // Delaunay, si ce n'est pas le cas, on flip l'arrête "opposé" au sommet rajouté
            while (p.Count > 0)
            {
                // On commence par extraire le point

                Entity point = p[0];
                p.RemoveAt(0);

                FaceWE f      = null;
                int    findex = 0;
                // On cherche le triangle qui contient le point
                for (int i = 0; i < mesh.Faces.Count; i++)
                {
                    FaceWE          currentFace = mesh.Faces[i];
                    List <VertexWE> vertices    = mesh.GetFaceVertices(currentFace);

                    bool isIn = Troll3D.TRaycast.PointInTriangle(vertices[0].Position, vertices[1].Position, vertices[2].Position, point.transform_.position_);

                    if (isIn)
                    {
                        f      = currentFace;
                        findex = i;
                    }
                }

                // En théorie, on a récupéré le triangle qui contient le point, on va désormais diviser
                // ce triangle en 3 en utilisant le point actuel

                List <FaceWE> faces = mesh.AddVertex(f, point.transform_.position_.X, point.transform_.position_.Y, point.transform_.position_.Z);

                // Maintenant, on doit vérifier que les triangles obtenus sont delaunay, c'est à dire
                // que le cercle circonscrit au triangle ne contienne que des points du triangle

                // On inspecte les faces crées
                for (int i = 0; i < faces.Count; i++)
                {
                    InspectEdge(faces[i].Edges, mesh);
                }
            }

            // Je retire les parties du maillage qui sont utilisé pour construire la triangulation

            List <FaceWE> faceToRemove = new List <FaceWE>();

            for (int i = mesh.Faces.Count - 1; i >= 0; i--)
            {
                if (mesh.IsFaceBorder(mesh.Faces[i]))
                {
                    faceToRemove.Add(mesh.Faces[i]);
                }
            }

            for (int i = 0; i < faceToRemove.Count; i++)
            {
                mesh.RemoveFace(faceToRemove[i]);
            }

            for (int i = 0; i < CircleCenter.Count; i++)
            {
                Scene.CurrentScene.RemoveRenderable(( MeshRenderer )CircleCenter[i].GetComponent(ComponentType.MeshRenderer));
            }

            if (DisplayCenters)
            {
                for (int i = 0; i < Circles.Count; i++)
                {
                    Scene.CurrentScene.RemoveRenderable(( LineRenderer )Circles[i].GetComponent(ComponentType.LineRenderer));
                }

                CircleCenter.Clear();

                for (int i = 0; i < mesh.Faces.Count; i++)
                {
                    List <VertexWE> vertices = mesh.GetFaceVertices(mesh.Faces[i]);

                    Vector3 circleCenter = GetCircleCenter(vertices[0].Position, vertices[1].Position, vertices[2].Position);
                    float   radius       = GetCircleRadius(vertices[0].Position, vertices[1].Position, vertices[2].Position, circleCenter);

                    AddCircleCenter(circleCenter.X, circleCenter.Y, radius);
                }
            }
            else
            {
                for (int i = 0; i < Circles.Count; i++)
                {
                    Scene.CurrentScene.RemoveRenderable(( LineRenderer )Circles[i].GetComponent(ComponentType.LineRenderer));
                }
                CircleCenter.Clear();
            }

            if (mesh.MakeMesh() != null)
            {
                meshRenderer.model_ = mesh.MakeMesh();
                meshRenderer.SetFillMode(SharpDX.Direct3D11.FillMode.Wireframe);
                meshRenderer.material_.SetMainColor(1.0f, 0.0f, 0.0f, 1.0f);
            }
            else
            {
            }

            if (DisplayVoronoi)
            {
                BuildVoronoi(mesh);
            }
            else
            {
                CleanVoronoi();
            }
        }
Esempio n. 6
0
        /// <summary>
        /// Inspecte une edge et détermine si un basculement est nécéssaire
        /// Si un basculement a eu lieu, réinvoque la fonction
        /// </summary>
        /// <param name="e"></param>
        private void InspectEdge(List <EdgeWE> edges, WingedEdgeMesh mesh)
        {
            foreach (EdgeWE e in edges)
            {
                // On vérifie d'abord que l'arrête relie 2 triangles
                if (e.LeftFace != null && e.RightFace != null)
                {
                    List <VertexWE> v1 = mesh.GetFaceVertices(e.LeftFace);
                    List <VertexWE> v2 = mesh.GetFaceVertices(e.RightFace);

                    // Récupère le coté opposé à la face gauche
                    VertexWE leftOppositeVertex = null;

                    for (int i = 0; i < v1.Count; i++)
                    {
                        if ((v1[i] != e.Vertex1) && (v1[i] != e.Vertex2))
                        {
                            leftOppositeVertex = v1[i];
                        }
                    }

                    // Récupère le coté opposé à la face droite
                    VertexWE rightOppositeVertex = null;

                    for (int i = 0; i < v2.Count; i++)
                    {
                        if ((v2[i] != e.Vertex1) && (v2[i] != e.Vertex2))
                        {
                            rightOppositeVertex = v1[i];
                        }
                    }

                    // On récupère les informations sur les cercle Right et Left Face

                    Vector3 leftCircleCenter = GetCircleCenter(v1[0].Position, v1[1].Position, v1[2].Position);
                    float   leftCircleRadius = GetCircleRadius(v1[0].Position, v1[1].Position, v1[2].Position, leftCircleCenter);

                    Vector3 rightCircleCenter = GetCircleCenter(v2[0].Position, v2[1].Position, v2[2].Position);
                    float   rightCircleRadius = GetCircleRadius(v2[0].Position, v2[1].Position, v2[2].Position, rightCircleCenter);

                    // On vérifie si un des coté opposé ne rentre pas dans le cercle de la face opposé

                    if (IsPointInCircle(leftOppositeVertex.Position, rightCircleCenter, rightCircleRadius) || IsPointInCircle(rightOppositeVertex.Position, leftCircleCenter, leftCircleRadius))
                    {
                        // On bascule l'arrête
                        List <FaceWE> newfaces = mesh.FlipEdge(e);

                        // On inspecte les nouvelles arrêtes

                        List <EdgeWE> newEdges = new List <EdgeWE>();

                        for (int i = 0; i < newfaces.Count; i++)
                        {
                            for (int j = 0; j < newfaces[i].Edges.Count; j++)
                            {
                                if (newEdges.Contains(newfaces[i].Edges[j]))
                                {
                                    newEdges.Add(newfaces[i].Edges[j]);
                                }
                            }
                        }
                        InspectEdge(newEdges, mesh);
                        return;
                    }
                }
            }
            return;
        }