Advertisement
KvanTTT

Polygon Triangulation

Oct 8th, 2012
410
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 4.92 KB | None | 0 0
  1. using System.Collections.Generic;
  2. using System.Drawing;
  3.  
  4. public class Triangulator
  5. {
  6.     /// <summary>
  7.     /// Calculate list of concave polygons or triangles.
  8.     /// </summary>
  9.     /// <param name="Polygon">Input polygon without self-intersections (it can be checked with SelfIntersection().</param>
  10.     /// <param name="triangulate">true: splitting on triangles; false: splitting on concave polygons.</param>
  11.     /// <returns></returns>
  12.     public static List<List<PointF>> Triangulate(List<PointF> Polygon, bool triangulate = false)
  13.     {
  14.         var result = new List<List<PointF>>();
  15.         var tempPolygon = new List<PointF>(Polygon);
  16.         var convPolygon = new List<PointF>();
  17.  
  18.         int begin_ind = 0;
  19.         int cur_ind;
  20.         int begin_ind1;
  21.         int N = Polygon.Count;
  22.         int Range;
  23.  
  24.         if (Square(tempPolygon) < 0)
  25.             tempPolygon.Reverse();
  26.  
  27.         while (N >= 3)
  28.         {
  29.             while ((PMSquare(tempPolygon[begin_ind], tempPolygon[(begin_ind + 1) % N],
  30.                       tempPolygon[(begin_ind + 2) % N]) < 0) ||
  31.                       (Intersect(tempPolygon, begin_ind, (begin_ind + 1) % N, (begin_ind + 2) % N) == true))
  32.             {
  33.                 begin_ind++;
  34.                 begin_ind %= N;
  35.             }
  36.             cur_ind = (begin_ind + 1) % N;
  37.             convPolygon.Add(tempPolygon[begin_ind]);
  38.             convPolygon.Add(tempPolygon[cur_ind]);
  39.             convPolygon.Add(tempPolygon[(begin_ind + 2) % N]);
  40.  
  41.             if (triangulate == false)
  42.             {
  43.                 begin_ind1 = cur_ind;
  44.                 while ((PMSquare(tempPolygon[cur_ind], tempPolygon[(cur_ind + 1) % N],
  45.                                 tempPolygon[(cur_ind + 2) % N]) > 0) && ((cur_ind + 2) % N != begin_ind))
  46.                 {
  47.                     if ((Intersect(tempPolygon, begin_ind, (cur_ind + 1) % N, (cur_ind + 2) % N) == true) ||
  48.                         (PMSquare(tempPolygon[begin_ind], tempPolygon[(begin_ind + 1) % N],
  49.                                   tempPolygon[(cur_ind + 2) % N]) < 0))
  50.                         break;
  51.                     convPolygon.Add(tempPolygon[(cur_ind + 2) % N]);
  52.                     cur_ind++;
  53.                     cur_ind %= N;
  54.                 }
  55.             }
  56.  
  57.             Range = cur_ind - begin_ind;
  58.             if (Range > 0)
  59.             {
  60.                 tempPolygon.RemoveRange(begin_ind + 1, Range);
  61.             }
  62.             else
  63.             {
  64.                 tempPolygon.RemoveRange(begin_ind + 1, N - begin_ind - 1);
  65.                 tempPolygon.RemoveRange(0, cur_ind + 1);
  66.             }
  67.             N = tempPolygon.Count;
  68.             begin_ind++;
  69.             begin_ind %= N;
  70.  
  71.             result.Add(convPolygon);
  72.         }
  73.  
  74.         return result;
  75.     }
  76.  
  77.     public static int SelfIntersection(List<PointF> polygon)
  78.     {
  79.         if (polygon.Count < 3)
  80.             return 0;
  81.         int High = polygon.Count - 1;
  82.         PointF O = new PointF();
  83.         int i;
  84.         for (i = 0; i < High; i++)
  85.         {
  86.             for (int j = i + 2; j < High; j++)
  87.             {
  88.                 if (LineIntersect(polygon[i], polygon[i + 1],
  89.                                   polygon[j], polygon[j + 1], ref O) == 1)
  90.                     return 1;
  91.             }
  92.         }
  93.         for (i = 1; i < High - 1; i++)
  94.             if (LineIntersect(polygon[i], polygon[i + 1], polygon[High], polygon[0], ref O) == 1)
  95.                 return 1;
  96.         return -1;
  97.     }
  98.  
  99.     public static float Square(List<PointF> polygon)
  100.     {
  101.         float S = 0;
  102.         if (polygon.Count >= 3)
  103.         {
  104.             for (int i = 0; i < polygon.Count - 1; i++)
  105.                 S += PMSquare((PointF)polygon[i], (PointF)polygon[i + 1]);
  106.             S += PMSquare((PointF)polygon[polygon.Count - 1], (PointF)polygon[0]);
  107.         }
  108.         return S;
  109.     }
  110.  
  111.     static bool Intersect(List<PointF> polygon, int vertex1Ind, int vertex2Ind, int vertex3Ind)
  112.     {
  113.         float s1, s2, s3;
  114.         for (int i = 0; i < polygon.Count; i++)
  115.         {
  116.             if ((i == vertex1Ind) || (i == vertex2Ind) || (i == vertex3Ind))
  117.                 continue;
  118.             s1 = PMSquare(polygon[vertex1Ind], polygon[vertex2Ind], polygon[i]);
  119.             s2 = PMSquare(polygon[vertex2Ind], polygon[vertex3Ind], polygon[i]);
  120.             if (((s1 < 0) && (s2 > 0)) || ((s1 > 0) && (s2 < 0)))
  121.                 continue;
  122.             s3 = PMSquare(polygon[vertex3Ind], polygon[vertex1Ind], polygon[i]);
  123.             if (((s3 >= 0) && (s2 >= 0)) || ((s3 <= 0) && (s2 <= 0)))
  124.                 return true;
  125.         }
  126.         return false;
  127.     }
  128.  
  129.     static float PMSquare(PointF p1, PointF p2)
  130.     {
  131.         return (p2.X * p1.Y - p1.X * p2.Y);
  132.     }
  133.  
  134.     static float PMSquare(PointF p1, PointF p2, PointF p3)
  135.     {
  136.         return (p3.X - p1.X) * (p2.Y - p1.Y) - (p2.X - p1.X) * (p3.Y - p1.Y);
  137.     }
  138.  
  139.     static int LineIntersect(PointF A1, PointF A2, PointF B1, PointF B2, ref PointF O)
  140.     {
  141.         float a1 = A2.Y - A1.Y;
  142.         float b1 = A1.X - A2.X;
  143.         float d1 = -a1 * A1.X - b1 * A1.Y;
  144.         float a2 = B2.Y - B1.Y;
  145.         float b2 = B1.X - B2.X;
  146.         float d2 = -a2 * B1.X - b2 * B1.Y;
  147.         float t = a2 * b1 - a1 * b2;
  148.  
  149.         if (t == 0)
  150.             return -1;
  151.  
  152.         O.Y = (a1 * d2 - a2 * d1) / t;
  153.         O.X = (b2 * d1 - b1 * d2) / t;
  154.  
  155.         if (A1.X > A2.X)
  156.         {
  157.             if ((O.X < A2.X) || (O.X > A1.X))
  158.                 return 0;
  159.         }
  160.         else
  161.         {
  162.             if ((O.X < A1.X) || (O.X > A2.X))
  163.                 return 0;
  164.         }
  165.  
  166.         if (A1.Y > A2.Y)
  167.         {
  168.             if ((O.Y < A2.Y) || (O.Y > A1.Y))
  169.                 return 0;
  170.         }
  171.         else
  172.         {
  173.             if ((O.Y < A1.Y) || (O.Y > A2.Y))
  174.                 return 0;
  175.         }
  176.  
  177.         if (B1.X > B2.X)
  178.         {
  179.             if ((O.X < B2.X) || (O.X > B1.X))
  180.                 return 0;
  181.         }
  182.         else
  183.         {
  184.             if ((O.X < B1.X) || (O.X > B2.X))
  185.                 return 0;
  186.         }
  187.  
  188.         if (B1.Y > B2.Y)
  189.         {
  190.             if ((O.Y < B2.Y) || (O.Y > B1.Y))
  191.                 return 0;
  192.         }
  193.         else
  194.         {
  195.             if ((O.Y < B1.Y) || (O.Y > B2.Y))
  196.                 return 0;
  197.         }
  198.  
  199.         return 1;
  200.     }
  201. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement