Triangulation eines einfachen Polygons

Ein Polygon triangulieren

Entwickler können Eckpunkte aus einem Polygon bereich auswählen und dann Dreiecke bilden, indem sie die Triangulate-Methode der PolygonModifier-Klasse aufrufen, wobei jede der Formen V{1}, V{i-1}, V{i} mit dem Index i von 3 bis n. Die Klassen Vertex und PolygonCanvas in der Datei Triangulate/PolygonCanvas.cs unter der Demo-Anwendung (Name: Triangulate) demonstrieren die Art und Weise, ein Polygon mit Aspose.3D API zu triangulieren.

Programmier probe für Triangulation

In diesem Code beispiel werden Scheitel punkte aus einem Polygon bereich ausgewählt und dann ein Algorithmus angewendet, um Dreiecke zu erstellen. Sie können das komplette Arbeits projekt dieses Beispiels von Hier herunter laden.

// 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]];
        }
    }

}