In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

Point Triangle Closest Point 2D

For 3D version see: http://wonderfl.net/c/mBsK
Get Adobe Flash player
by mutantleg 26 Nov 2013
/**
 * Copyright mutantleg ( http://wonderfl.net/user/mutantleg )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/b27F
 */

package {
    import flash.events.Event;
    import flash.display.Sprite;
    public class FlashTest extends Sprite {
        public function FlashTest() {

        //note: triangle winding is important for this test
         
         myTri = new xTri();
         myTri.x0 = 110;
         myTri.y0 = 60;
         myTri.x1 = 280;
         myTri.y1 = 280;
         myTri.x2 = 90;
         myTri.y2 = 290;

            
         
            stage.addEventListener(Event.ENTER_FRAME, onEnter);
        }//ctor
        
        public var myTri:xTri;
        public var temp:xPnt = new xPnt();
        
        public function onEnter(e:Event):void
        {
           graphics.clear();
           graphics.lineStyle(2, 0);
           
           var a:xTri;
           a = myTri;
           
           graphics.moveTo(a.x0, a.y0);
           graphics.lineTo(a.x1, a.y1);
           graphics.lineTo(a.x2, a.y2);
           graphics.lineTo(a.x0, a.y0);
           
           var mx:Number;
           var my:Number;
           mx = stage.mouseX;
           my = stage.mouseY;


           a.getDist(mx, my, temp);

           graphics.moveTo(temp.px, temp.py);
           graphics.lineTo(mx, my);
   
           graphics.drawRect(temp.px-4,temp.py-4,8,8);
            
           graphics.drawCircle(mx,my,8); 
            
        }//onenter
        
    }//classend
}
import flash.display.Graphics;

internal class xPnt
{
  public var px:Number = 0;
  public var py:Number = 0;
}//xpnt

internal class xTri
{
    public var x0:Number = 0;
    public var y0:Number = 0;
    public var x1:Number = 0;
    public var y1:Number = 0;
    public var x2:Number = 0;
    public var y2:Number = 0;
    
    
    //returns squared distance to triangle
    public function getDist(wx:Number, wy:Number, ret:xPnt):Number
    {
      var ax0:Number;    var ay0:Number;
      var bx0:Number;    var by0:Number;
      var ax1:Number;    var ay1:Number;
      var bx1:Number;    var by1:Number;
      var ax2:Number;    var ay2:Number;
      var bx2:Number;    var by2:Number;
      var dz0:Number;    var dz1:Number;    var dz2:Number;
      var rx:Number;     var ry:Number;     var rz:Number;                
      var wd:Number;
      var d:Number;

      // ok so the triangle has multiple zones
      // based on if we are closest to an edge, vertex or inside the triangle
      // (also if we are right on a vertex or edge)

      // by figuring out which side on each 3 sides of the triangle our point is
      // we can figure out which zone the point is in
      // e.g. if we are front of all 3 edges we are inside
      // if we are only front of one of them then we are closest to a vertex
      // if we are are front of two then we are closest to one of the edges    
      //  also because we us this the winding is important

      // if we are right on an edge or vertex then we got a special case
      // here its handled by assuming that a point on the edge is front of it
      // aka a point on a vertex is considered inside the triangle
   
     


      ax0 = x1 - x0;
      ay0 = y1 - y0;
      bx0 = wx - x0;
      by0 = wy - y0;
      dz0 = (ax0 * by0) - (ay0 * bx0);


      ax1 = x2 - x1;
      ay1 = y2 - y1;
      bx1 = wx - x1;
      by1 = wy - y1;
      dz1 = (ax1 * by1) - (ay1 * bx1);


      ax2 = x0 - x2;
      ay2 = y0 - y2;
      bx2 = wx - x2;
      by2 = wy - y2;
      dz2 = (ax2 * by2) - (ay2 * bx2);


      //+++ //inside
      if (dz0 >= 0 && dz1 >= 0 && dz2 >=0) 
      {
        d = 0;
        if (ret) { ret.px = wx; ret.py = wy; }
      }
      else   //-+- //vertex
      if (dz0 < 0 && dz1 >= 0 && dz2 < 0) 
      { 
        d = bx0*bx0 + by0*by0;
        if (ret) { ret.px = x0; ret.py = y0; }
      } 
      else   //--+ //vertex
      if (dz0 < 0 && dz1 < 0 && dz2 >= 0) 
      {
        d = bx1*bx1 + by1*by1;
        if (ret) { ret.px = x1; ret.py = y1; }
      }
      else   //+-- //vertex
      if (dz0 >= 0 && dz1 < 0 && dz2 < 0)
      { 
        d = bx2*bx2 + by2*by2;
        if (ret) { ret.px = x2; ret.py = y2; }
      }
      else //-++  //edge
      if (dz0 < 0 && dz1 >= 0 && dz2 >= 0) 
      {
        wd = ((ax0 * bx0) + (ay0 * by0) ) / ((ax0 * ax0) + (ay0 * ay0));
        if (wd < 0) { wd = 0;} if (wd > 1) { wd = 1; }
        rx = x0 + (x1 - x0) * wd;
        ry = y0 + (y1 - y0) * wd;

        if (ret) { ret.px = rx; ret.py = ry; }  
        rx = wx-rx;   ry = wy-ry;
        d = rx*rx + ry*ry;
      }
      else  //+-+ //edge
      if (dz0 >= 0 && dz1 < 0 && dz2 >= 0) 
      {
        wd = ((ax1 * bx1) + (ay1 * by1) ) / ((ax1 * ax1) + (ay1 * ay1));
        if (wd < 0) { wd = 0;} if (wd > 1) { wd = 1; }
        rx = x1 + (x2 - x1) * wd;
        ry = y1 + (y2 - y1) * wd;
        
        if (ret) { ret.px = rx; ret.py = ry; }  
        rx = wx-rx;   ry = wy-ry;
        d = rx*rx + ry*ry;
      }
      else   //++- //edge
      if (dz0 >= 0 && dz1 >= 0 && dz2 < 0) 
      {
        wd = ((ax2 * bx2) + (ay2 * by2) ) / ((ax2 * ax2) + (ay2 * ay2));
        if (wd < 0) { wd = 0;} if (wd > 1) { wd = 1; }
        rx = x2 + (x0 - x2) * wd;
        ry = y2 + (y0 - y2) * wd;

        if (ret) { ret.px = rx; ret.py = ry; }  
        rx = wx-rx;   ry = wy-ry;
        d = rx*rx + ry*ry;
      }//endif
 

      return d;
    }//isinside
    
    
}//xtris