classdef Triangle
% Operations with Triangles
   properties
   % A triangle has three vertices that are Points
        v = Point.empty()
   end
    
   methods
      % Construct a Triangle object..
      function T = Triangle(P1,P2,P3)
      % P1, P2, and P3 are Points that are to be the vertices of the
      % triangle.
         T.v(1) = P1;
         T.v(2) = P2;
         T.v(3) = P3;
      end
            
      function Q = Nearest(ThisTriangle,P)
      % P is a point.
      % Q is that point on the perimeter of ThisTriangle that 
      % is closest to P.
         T = ThisTriangle;
         A = T.v(1);
         B = T.v(2);
         C = T.v(3);
         % Compute the closest points on each of the sides and their 
         % their respective distances to P...
         QAB = Nearest(P,A,B); dAB = P.Dist(QAB);
         QBC = Nearest(P,B,C); dBC = P.Dist(QBC);
         QCA = Nearest(P,C,A); dCA = P.Dist(QCA);
         % Which is the best...
         if dAB<=dBC && dAB<=dCA
            Q = QAB;
         elseif dBC<=dCA && dBC<=dAB
            Q = QBC;
         else
            Q = QCA;
         end
      end
        
      function alfa = Include(ThisTriangle,P)
      % P is a point.
      % alfa is true if and only if P is inside ThisTriangle
         A = ThisTriangle.v(1);
         B = ThisTriangle.v(2);
         C = ThisTriangle.v(3);
         alfa = ~A.DiffSide(P,B,C) && ~B.DiffSide(P,C,A) &&  ~C.DiffSide(P,A,B);
      end
      % Note that because of lazy evaluation, the evaluation of the "&&"
      % stops as soon as it is discovered that the point is outside the
      % triangle.
                
      function C = InCircle(ThisTriangle)
      % C is the largest circle that fits inside ThisTriangle.
         T = ThisTriangle;
         Q = T.InCenter();
         % Q is equidistant to the three sides, compute that distance...
         P = Q.Nearest(T.v(1),T.v(2));
         r = Q.Dist(P);
         % Create the incircle...
         C = Circle(r,Q);
      end
    
      function C = OutCircle(ThisTriangle)
      % C is the smallest circle that contains ThisTriangle.
      T = ThisTriangle;
      Q = T.OutCenter();
      % Q is equidistant to the three vertices, compute that distance...
      r = Q.Dist(T.v(1));
      % Create the outcircle..
         C = Circle(r,Q);
      end
    
      function Q = InCenter(ThisTriangle)
      % Q is the center of the incircle for ThisTriangle.
         TA = ThisTriangle.v(1);
         TB = ThisTriangle.v(2);
         TC = ThisTriangle.v(3);
         a = TB.Dist(TC);
         b = TC.Dist(TA);
         c = TA.Dist(TB);
         p = a+b+c;
         Q = Point((a*TA.x+b*TB.x+c*TC.x)/p,(a*TA.y+b*TB.y+c*TC.y)/p);
      end
        
      function Q = OutCenter(ThisTriangle)
      % Q is the center of the outcircle for ThisTriangle.
         A = ThisTriangle.v(1);
         B = ThisTriangle.v(2);
         C = ThisTriangle.v(3)
         d = 2*( A.x*(B.y-C.y) + B.x*(C.y-A.y) + C.x*(A.y-B.y));
         xc = ((A.x^2+A.y^2)*(B.y-C.y) + (B.x^2+B.y^2)*(C.y-A.y) + (C.x^2+C.y^2)*(A.y-B.y))/d;
         yc = ((A.x^2+A.y^2)*(C.x-B.x) + (B.x^2+B.y^2)*(A.x-C.x) + (C.x^2+C.y^2)*(B.x-A.x))/d;
         Q = Point(xc,yc);
      end
          
      function Show(ThisTriangle,c)
      % c is a character that encodes a color.
      % Displays ThisTriangle in the current figure window assuming that
      % hold is on.
         x = [ThisTriangle.v(1).x  ThisTriangle.v(2).x  ThisTriangle.v(3).x];
         y = [ThisTriangle.v(1).y  ThisTriangle.v(2).y  ThisTriangle.v(3).y];
         plot([x x(1)],[y y(1)],c)
      end
      
   end % methods   
end % classdef

