Triangulation d'un polygone simple

Triangulation d’un polygone

Les développeurs peuvent choisir des sommets dans une zone de polygone, puis former des triangles en appelant la méthode Triangulate de la classe PolygonModifier, chacune de la forme V{1}, V{i-1}, V{i} avec l’index i allant de 3 à n. Les classes Vertex et PolygonCanvas du fichier Triangulate/PolygonCanvas.cs sous l’application de démonstration (nom: Triangulate) montrent comment trianguler un polygone en utilisant Aspose.3D API.

Échantillon de programmation pour la triangulation

Cet exemple de code sélectionne les sommets d’une zone de polygone, puis applique un algorithme pour créer des triangles. Vous pouvez télécharger le projet de travail complet de cet exemple à partir de Ici.

// For complete examples and data files, please go to https://github.com/aspose-3d/Aspose.3D-for-.NET
public class Vertex
{
    [Browsable(false)]
    public int Index { get; set; }
    public double X { get; set; }
    public double Y { get; set; }

    public Vertex(int index, double x, double y)
    {
        Index = index;
        X = x;
        Y = y;
    }
    public override string ToString()
    {
        return string.Format("#{0}: {1} {2}", Index, X, Y);
    }
}
    
class PolygonCanvas : Control
{
    public List<Vertex> points = new List<Vertex>();

    public event EventHandler TriangleUpdated;

    private Point mousePos;
    private Pen virtualLine = new Pen(Color.DarkSeaGreen);
    private Vector4[][] triangles;
    private int[][] triangleIndices;
    private Pen polygonPen = Pens.Black;

    private Brush[] brushes = new Brush[] {Brushes.Blue, Brushes.BlueViolet, Brushes.DarkCyan, Brushes.ForestGreen, Brushes.LimeGreen};
    private Brush textBrush = Brushes.Black;
    public PolygonCanvas()
    {
        SetStyle(ControlStyles.ResizeRedraw, true);
        SetStyle(ControlStyles.UserPaint, true);
        SetStyle(ControlStyles.Selectable, true);
        SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
        SetStyle(ControlStyles.AllPaintingInWmPaint   , true);


        Cursor = Cursors.Cross;

        virtualLine.DashStyle = DashStyle.Dash;
        virtualLine.DashPattern = new float[] {10, 10};
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        base.OnPaint(e);
        Graphics g = e.Graphics;
        g.Clear(Color.AliceBlue);

        if (points.Count == 0)
            return;
        Size size = this.Size;
        if (points.Count == 1)
        {
            // Draw virtual line
            PointF pt = ToPoint(points[0], size);
            g.DrawLine(virtualLine, mousePos, pt);

        }
        else if (points.Count == 2)
        {
            // Draw virtual triangle
            PointF pt1 = ToPoint(points[0], size);
            PointF pt2 = ToPoint(points[1], size);
            g.DrawLine(polygonPen, pt2, pt1);
            g.DrawLine(virtualLine, mousePos, pt1);
            g.DrawLine(virtualLine, mousePos, pt2);
        }
        else
        {
            // Draw polygon and virtual line

            // Draw triangles
            if (triangles != null)
            {
                for (int i = 0; i < triangles.Length; i++)
                {
                    PointF[] tri = ToPoints(triangles[i]);
                    // Shrink the triangle so we can see each triangle
                    float inv = 1.0f/3.0f;
                    float cx= (tri[0].X + tri[1].X + tri[2].X) * inv;
                    float cy= (tri[0].Y + tri[1].Y + tri[2].Y) * inv;
                    Shrink(tri, 0, cx, cy);
                    Shrink(tri, 1, cx, cy);
                    Shrink(tri, 2, cx, cy);
                    Brush brush = brushes[i%brushes.Length];
                    g.FillPolygon(brush, tri);
                    // Draw triangle index
                    string text = string.Format("{0}/{1}/{2}", triangleIndices[i][0], triangleIndices[i][1], triangleIndices[i][2]);
                    g.DrawString(text, Font, textBrush, cx, cy);
                }
            }
            // Draw index of each vertex
            PointF[] polygon = ToPoints(this.points);
            g.DrawPolygon(polygonPen, polygon);
            for (int i = 0; i < polygon.Length; i++)
            {
                string text = string.Format("{0}", i);
                g.DrawString(text, Font, textBrush, polygon[i]);
            }

            g.DrawLine(virtualLine, mousePos, polygon[0]);
            g.DrawLine(virtualLine, mousePos, polygon[polygon.Length - 1]);

        }

    }

    private void Shrink(PointF[] tri, int i, float cx, float cy)
    {
        float dx = tri[i].X - cx;
        float dy = tri[i].Y - cy;
        float inv = 5.0f/(float) Math.Sqrt(dx*dx + dy*dy);
        dx *= inv;
        dy *= inv;
        tri[i] = new PointF(tri[i].X - dx, tri[i].Y - dy);
    }

    private PointF[] ToPoints(IList<Vector4> vec)
    {
        Size size = Size;
        PointF[] ret = new PointF[vec.Count];
        for(int i = 0; i < ret.Length; i++)
            ret[i] = new PointF((float)vec[i].x * size.Width, (float)vec[i].y * Height);
        return ret;

    }
    private PointF[] ToPoints(IList<Vertex> vec)
    {
        Size size = Size;
        PointF[] ret = new PointF[vec.Count];
        for(int i = 0; i < ret.Length; i++)
            ret[i] = ToPoint(vec[i], size);
        return ret;

    }
    private PointF ToPoint(Vertex vec, Size size)
    {
        return new PointF((float)vec.X * size.Width, (float)vec.Y * Height);
    }

    protected override void OnMouseMove(MouseEventArgs e)
    {
        base.OnMouseMove(e);
        mousePos = e.Location;
        Invalidate();
    }

    protected override void OnMouseUp(MouseEventArgs e)
    {
        base.OnMouseUp(e);
        if (e.Button == MouseButtons.Left)
        {
            Vertex pt = new Vertex(points.Count, e.X*1.0/Width, e.Y*1.0/Height);
            points.Add(pt);
            UpdateTriangles();
        }
        else
        {
            // Erase last point
            if (points.Count > 0)
            {
                points.RemoveAt(points.Count - 1);
                UpdateTriangles();
            }
        }
    }

    public void UpdateTriangles()
    {
        DoTriangulate();
        Invalidate();
        if(TriangleUpdated != null)
            TriangleUpdated(this, new EventArgs());
    }

    /// <summary>
    /// Triangulate the polygon into a lot of triangles
    /// </summary>
    private void DoTriangulate()
    {
        triangles = null;
        if (points.Count <= 3)
            return;
        // Convert to Vector4[]
        Vector4[] controlPoints = new Vector4[points.Count];
        for (int i = 0; i < points.Count; i++)
        {
            controlPoints[i] = new Vector4(points[i].X, points[i].Y, 0);
        }
        // Triangulate the polygon
        triangleIndices = PolygonModifier.Triangulate(controlPoints);
        // Save triangle vertex for later drawing.
        triangles = new Vector4[triangleIndices.Length][];
        for (int i = 0; i < triangleIndices.Length; i++)
        {
            int[] triangleFace = triangleIndices[i];


            Vector4[] triangle = triangles[i] = new Vector4[3];


            triangle[0] = controlPoints[triangleFace[0]];
            triangle[1] = controlPoints[triangleFace[1]];
            triangle[2] = controlPoints[triangleFace[2]];
        }
    }

}