Advertisement
_takumi

Polygon.cs

Dec 10th, 2019
391
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 7.76 KB | None | 0 0
  1. using MyLibrary;
  2. using System;
  3. using System.Collections;
  4. using System.Collections.Generic;
  5. using System.Drawing;
  6. using System.Linq;
  7.  
  8. namespace PolygonDraft
  9. {
  10.     [Serializable]
  11.     public class Polygon : IEnumerable<Vertex>
  12.     {
  13.         private static Random _rnd = new Random();
  14.         private Color _hullColor;
  15.         private Color _vertexColor;
  16.         private int _radius;
  17.         private List<Vertex> _vertices;
  18.  
  19.         public Polygon(in Color hullColor, in Color vertexColor, in int vertexSize)
  20.         {
  21.             _vertices = new List<Vertex>();
  22.             HullColor = hullColor;
  23.             VertexColor = vertexColor;
  24.             VertexSize = vertexSize;
  25.         }
  26.  
  27.         private int Cross(in Point a, in Point b, in Point c)
  28.         {
  29.             return (a.X - b.X) * (c.Y - b.Y) - (c.X - b.X) * (a.Y - b.Y);
  30.         }
  31.  
  32.         private bool IsInsideTheHull(in Point point)
  33.         {
  34.             int n = _vertices.Count;
  35.             int firstCross = Cross(_vertices[n - 1], new Point(point.X, point.Y), _vertices[0]);
  36.             int neededSign = (firstCross == 0) ? 0 : (firstCross > 0) ? -1 : 1;
  37.             for (int i = 0; i < n - 1; ++i)
  38.             {
  39.                 int currentCross = Cross(_vertices[i], new Point(point.X, point.Y), _vertices[i + 1]);
  40.                 int currentSign = (currentCross == 0) ? 0 : (currentCross > 0) ? -1 : 1;
  41.                 if (currentSign != neededSign)
  42.                     return false;
  43.             }
  44.             return true;
  45.         }
  46.  
  47.         private List<Vertex> Convex()
  48.         {
  49.             int n = _vertices.Count, k = 0;
  50.             List<Vertex> Hull = new List<Vertex>(new Vertex[2 * n]);
  51.  
  52.             _vertices = (from vertex in _vertices
  53.                          orderby vertex.X, vertex.Y ascending
  54.                          select vertex).ToList();
  55.  
  56.             // Нижняя оболочка:
  57.             for (int i = 0; i < n; Hull[k++] = _vertices[i++])
  58.                 for (; k >= 2 && Cross(Hull[k - 2], Hull[k - 1], _vertices[i]) <= 0; k--) ;
  59.  
  60.             // Верхняя оболочка:
  61.             for (int i = n - 2, t = k + 1; i >= 0; Hull[k++] = _vertices[i--])
  62.                 for (; k >= t && Cross(Hull[k - 2], Hull[k - 1], _vertices[i]) <= 0; k--) ;
  63.  
  64.             return Hull.Take(k - 1).ToList();
  65.         }
  66.  
  67.         public Color VertexColor
  68.         {
  69.             get => _vertexColor;
  70.             set
  71.             {
  72.                 _vertexColor = value;
  73.                 _vertices.ForEach(vertex => vertex.FillColor = _vertexColor);
  74.             }
  75.         }
  76.  
  77.         public Color HullColor
  78.         {
  79.             get => _hullColor;
  80.             set
  81.             {
  82.                 _hullColor = value;
  83.                 _vertices.ForEach(vertex => vertex.HullColor = _hullColor);
  84.                 //HullColorChanged?.Invoke(this, EventArgs.Empty);
  85.             }
  86.         }
  87.  
  88.         public int VertexSize
  89.         {
  90.             get => _radius;
  91.             set
  92.             {
  93.                 _radius = value;
  94.                 _vertices.ForEach(vertex => vertex.Radius = _radius);
  95.             }
  96.         }
  97.  
  98.         public int Count => _vertices.Count;
  99.  
  100.         /// <summary>
  101.         /// Returns a list of vertices that will be deleted after the polygon is made convex.
  102.         /// </summary>
  103.         /// <returns></returns>
  104.         public List<Vertex> VerticesToDelete()
  105.         {
  106.             return (Count >= 3) ? _vertices.Except(Convex()).ToList() : new List<Vertex>();
  107.         }
  108.  
  109.         /// <summary>
  110.         /// Returns a list of vertices that will be deleted if <paramref name="vertex"/> is added to the polygon.
  111.         /// </summary>
  112.         /// <param name="vertex"></param>
  113.         /// <returns></returns>
  114.         public List<Vertex> VerticesToDelete(Vertex vertex)
  115.         {
  116.             _vertices.Add(vertex);
  117.             var verticesToDelete = VerticesToDelete();
  118.             _vertices.Remove(vertex);
  119.             return verticesToDelete;
  120.         }
  121.  
  122.         /// <summary>
  123.         /// Returns true if <paramref name="point"/> is inside the polygon, otherwise false.
  124.         /// </summary>
  125.         /// <param name="point"></param>
  126.         /// <returns></returns>
  127.         public bool Contains(in Point point)
  128.         {
  129.             return (_vertices.Count >= 3 && IsInsideTheHull(point));
  130.         }
  131.  
  132.         /// <summary>
  133.         /// Draws the polygon on <paramref name="graphics"/>.
  134.         /// </summary>
  135.         /// <param name="graphics"></param>
  136.         public void Draw(Graphics graphics)
  137.         {
  138.             if (_vertices.Count >= 3)
  139.             {
  140.                 Point[] points = new Point[_vertices.Count];
  141.                 for (int i = 0; i < _vertices.Count; ++i)
  142.                     points[i] = _vertices[i];
  143.                 graphics.DrawPolygon(new Pen(HullColor, 3), points);
  144.             }
  145.             _vertices.ForEach(vertex => vertex.Draw(graphics));
  146.  
  147.         }
  148.  
  149.         /// <summary>
  150.         /// Makes the polygon convex.
  151.         /// </summary>
  152.         public void MakeConvex()
  153.         {
  154.             _vertices = Convex();
  155.         }
  156.  
  157.         /// <summary>
  158.         /// Moves the vertices of the polygon randomly.
  159.         /// </summary>
  160.         public void Move()
  161.         {
  162.             foreach (Vertex vertex in _vertices)
  163.             {
  164.                 vertex.Y += _rnd.Next(-1, 2);
  165.                 vertex.X += _rnd.Next(-1, 2);
  166.             }
  167.         }
  168.  
  169.         /// <summary>
  170.         /// Removes <paramref name="vertex"/> from polygon.
  171.         /// </summary>
  172.         /// <param name="vertex"></param>
  173.         public void Remove(in Vertex vertex)
  174.         {
  175.             _vertices.Remove(vertex);
  176.         }
  177.  
  178.         /// <summary>
  179.         /// Adds <paramref name="vertex"/> to the polygon.
  180.         /// </summary>
  181.         /// <param name="vertex"></param>
  182.         public void Add(Vertex vertex)
  183.         {
  184.             vertex.HullColor = HullColor;
  185.             vertex.FillColor = VertexColor;
  186.             vertex.Radius = VertexSize;
  187.             _vertices.Add(vertex);
  188.         }
  189.  
  190.         /// <summary>
  191.         /// Performs the specified action on each vertex of the polygon.
  192.         /// </summary>
  193.         /// <param name="action"></param>
  194.         public void ForEach(Action<Vertex> action)
  195.         {
  196.             _vertices.ForEach(action);
  197.         }
  198.  
  199.         /// <summary>
  200.         /// Determines whether the polygon contains vertices that match the conditions defined by the specified predicate.
  201.         /// </summary>
  202.         /// <param name="match"></param>
  203.         /// <returns></returns>
  204.         public bool Exists(Predicate<Vertex> match)
  205.         {
  206.             return _vertices.Exists(match);
  207.         }
  208.  
  209.         /// <summary>
  210.         /// Adds the elements of the specified collection to the polgon.
  211.         /// </summary>
  212.         /// <param name="collection"></param>
  213.         public void AddRange(IEnumerable<Vertex> collection)
  214.         {
  215.             foreach (Vertex vertex in collection)
  216.                 Add(vertex);
  217.         }
  218.  
  219.         /// <summary>
  220.         /// Returns the last vertex of the polygon on the <paramref name="point"/>.
  221.         /// </summary>
  222.         /// <param name="point"></param>
  223.         /// <returns></returns>
  224.         public Vertex FindLast(Point point)
  225.         {
  226.             return _vertices.FindLast(vertex => vertex.Check(point.X, point.Y));
  227.         }
  228.  
  229.         public void RemoveRange(List<Vertex> collection)
  230.         {
  231.             _vertices.RemoveAll(vertex => collection.Contains(vertex));
  232.         }
  233.  
  234.         public IEnumerator<Vertex> GetEnumerator()
  235.         {
  236.             return ((IEnumerable<Vertex>)_vertices).GetEnumerator();
  237.         }
  238.  
  239.         IEnumerator IEnumerable.GetEnumerator()
  240.         {
  241.             return ((IEnumerable<Vertex>)_vertices).GetEnumerator();
  242.         }
  243.     }
  244. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement