context: #region Header
  //   Vorspire    _,-'/-'/  Triangle2D.cs
  //   .      __,-; ,'( '/
  //    \.    `-.__`-._`:_,-._       _ , . ``
  //     `:-._,------' ` _,`--` -: `_ , ` ,' :
  //        `---..__,,--'  (C) 2016  ` -'. -'
  //        #  Vita-Nex [http://core.vita-nex.com]  #
  //  {o)xxx|===============-   #   -===============|xxx(o}
  //        #        The MIT License (MIT)          #
  #endregion
  
  #region References
  using System;
  using System.Collections.Generic;
  using System.Linq;
  #endregion
  
  namespace Server
  {
  	[NoSort, Parsable, PropertyObject]
  	public struct Triangle2D : IPoint2D
  	{
  		public static readonly Triangle2D Empty = new Triangle2D(0, 0, 0, 0, 0, 0);
  
  		public static bool Contains(IPoint2D p, IPoint2D a, IPoint2D b, IPoint2D c)
  		{
  			var x = p.X - a.X;
  			var y = p.Y - a.Y;
  
  			var delta = (b.X - a.X) * y - (b.Y - a.Y) * x > 0;
  
  			if ((c.X - a.X) * y - (c.Y - a.Y) * x > 0 == delta)
  			{
  				return false;
  			}
  
  			if ((c.X - b.X) * (p.Y - b.Y) - (c.Y - b.Y) * (p.X - b.X) > 0 != delta)
  			{
  				return false;
  			}
  
  			return true;
  		}
  
  		public static IEnumerable<Point2D> Intersect(Triangle2D t1, Triangle2D t2)
  		{
  			return Line2D.Intersect(new[] {t1._AB, t1._BC, t1._CA}, new[] {t2._AB, t2._BC, t2._CA});
  		}
  
  		public static IEnumerable<Point2D> Intersect(Triangle2D t, Rectangle2D r)
  		{
  			return Line2D.Intersect(
  				new[] {t._AB, t._BC, t._CA},
  				new[]
  				{
  					new Line2D(r.X, r.Y, r.X + r.Width, r.Y), new Line2D(r.X + r.Width, r.Y, r.X + r.Width, r.Y + r.Height),
  					new Line2D(r.X, r.Y, r.X, r.Y + r.Height), new Line2D(r.X, r.Y + r.Height, r.X + r.Width, r.Y + r.Height)
  				});
  		}
  
  		public static bool Intersects(Triangle2D t1, Triangle2D t2)
  		{
  			return Intersect(t1, t2).Any();
  		}
  
  		public static bool Intersects(Triangle2D t, Rectangle2D r)
  		{
  			return Intersect(t, r).Any();
  		}
  
  		public static bool TryParse(string value, out Triangle2D t)
  		{
  			try
  			{
  				t = Parse(value);
  				return true;
  			}
  			catch
  			{
  				t = Empty;
  				return false;
  			}
  		}
  
  		public static Triangle2D Parse(string value)
  		{
  			var param = value.Split('+');
  
  			if (param.Length >= 3 && param.All(p => p.Contains(',')))
  			{
  				return new Triangle2D(Point2D.Parse(param[0]), Point2D.Parse(param[1]), Point2D.Parse(param[2]));
  			}
  
  			throw new FormatException(
  				"The specified triangle must be represented by three Point2D coords using the format " + //
  				"'(x1,y1)+(x2,y2)+(x3,y3)'");
  		}
  
  		private Point2D _A, _B, _C;
  
  		private Line2D _AB, _BC, _CA;
  		private Line2D _AC, _CB, _BA;
  
  		[CommandProperty(AccessLevel.Counselor)]
  		public int X
  		{
  			get { return _A.X; }
  			set
  			{
  				_A.X = value;
  				_AB.Start = _BA.End = _AC.Start = _CA.End = _A;
  			}
  		}
  
  		[CommandProperty(AccessLevel.Counselor)]
  		public int Y
  		{
  			get { return _A.Y; }
  			set
  			{
  				_A.Y = value;
  				_AB.Start = _BA.End = _AC.Start = _CA.End = _A;
  			}
  		}
  
  		[CommandProperty(AccessLevel.Counselor)]
  		public Point2D A { get { return _A; } set { _A = _AB.Start = _BA.End = _AC.Start = _CA.End = value; } }
  
  		[CommandProperty(AccessLevel.Counselor)]
  		public Point2D B { get { return _B; } set { _B = _BC.Start = _CB.End = _BA.Start = _AB.End = value; } }
  
  		[CommandProperty(AccessLevel.Counselor)]
  		public Point2D C { get { return _C; } set { _C = _CA.Start = _AC.End = _CB.Start = _BC.End = value; } }
  
  		[CommandProperty(AccessLevel.Counselor)]
  		public Line2D AB
  		{
  			get { return _AB; }
  			set
  			{
  				_AB = value;
  
  				_A = _BA.End = _AB.Start;
  				_B = _BA.Start = _AB.End;
  			}
  		}
  
  		[CommandProperty(AccessLevel.Counselor)]
  		public Line2D BC
  		{
  			get { return _BC; }
  			set
  			{
  				_BC = value;
  
  				_B = _CB.End = _BC.Start;
  				_C = _CB.Start = _BC.End;
  			}
  		}
  
  		[CommandProperty(AccessLevel.Counselor)]
  		public Line2D CA
  		{
  			get { return _CA; }
  			set
  			{
  				_CA = value;
  
  				_C = _AC.End = _CA.Start;
  				_A = _AC.Start = _CA.End;
  			}
  		}
  
  		[CommandProperty(AccessLevel.Counselor)]
  		public Line2D AC
  		{
  			get { return _AC; }
  			set
  			{
  				_AC = value;
  
  				_A = _CA.End = _AC.Start;
  				_C = _CA.Start = _AC.End;
  			}
  		}
  
  		[CommandProperty(AccessLevel.Counselor)]
  		public Line2D CB
  		{
  			get { return _CB; }
  			set
  			{
  				_CB = value;
  
  				_C = _BC.End = _CB.Start;
  				_B = _BC.Start = _CB.End;
  			}
  		}
  
  		[CommandProperty(AccessLevel.Counselor)]
  		public Line2D BA
  		{
  			get { return _BA; }
  			set
  			{
  				_BA = value;
  
  				_B = _AB.End = _BA.Start;
  				_A = _AB.Start = _BA.End;
  			}
  		}
  
  		[CommandProperty(AccessLevel.Counselor)]
  		public Angle ABC { get { return Angle.FromPoints(_A, _B, _C); } }
  
  		[CommandProperty(AccessLevel.Counselor)]
  		public Angle BCA { get { return Angle.FromPoints(_B, _C, _A); } }
  
  		[CommandProperty(AccessLevel.Counselor)]
  		public Angle CAB { get { return Angle.FromPoints(_C, _A, _B); } }
  
  		public Triangle2D(IPoint2D a, IPoint2D b, IPoint2D c)
  		{
  			_A = new Point2D(a);
  			_B = new Point2D(b);
  			_C = new Point2D(c);
  
  			_AB = new Line2D(_A, _B);
  			_BC = new Line2D(_B, _C);
  			_CA = new Line2D(_C, _A);
  
  			_AC = new Line2D(_A, _C);
  			_CB = new Line2D(_C, _B);
  			_BA = new Line2D(_B, _A);
  		}
  
  		public Triangle2D(int x1, int y1, int x2, int y2, int x3, int y3)
  		{
  			_A = new Point2D(x1, y1);
  			_B = new Point2D(x2, y2);
  
gt: 			_C = new Point2D(x3, y3);