forked from: 2D ray intersect triangle test

by Glidias forked from 2D ray intersect triangle test (diff: 22)
Try when starting from inside terrain triangle. 

The normalized ratio r multiplier of a given slope diagonal's length, based on gradient is: r = sqrt(1+gradient*gradient);  This is used to determine the perimeter travel time when walking along terrain triangles given a specific direction.
♥0 | Line 139 | Modified 2015-11-02 23:55:36 | MIT License
play

ActionScript3 source code

/**
 * Copyright Glidias ( http://wonderfl.net/user/Glidias )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/eECN
 */

// forked from Glidias's 2D ray intersect triangle test
package 
{
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.geom.Vector3D;
    import flash.text.TextField;
    
    /**
     * ...
     * @author Glenn Ko
     */
    [SWF(frameRate="60", backgroundColor="#ffffff")]
    public class LineIntersectTest extends Sprite
    {
      
        private var startPt:Vector3D = new Vector3D(150,65);
        private var endPt:Vector3D = new Vector3D();
        private var backPt:Vector3D = new Vector3D();
        
        private var pt1:Vector3D = new Vector3D(100, 60, 60);
        private var pt2:Vector3D = new Vector3D(100+60, 60, 120);
        private var pt3:Vector3D = new Vector3D(70,180, 100);
        private var r:Number;
        private var s:Number;
        
        private var intersectTimes:Vector.<Number> = new Vector.<Number>(2, true);
        private var intersectZ:Vector.<Number> = new Vector.<Number>(2, true);
        private var debugField:TextField;
        
        public function LineIntersectTest() {
            addEventListener(Event.ENTER_FRAME, onEnterFrame);
            debugField = new TextField();
            debugField.autoSize = "left";
            addChild(debugField);
        }
    
        private function onEnterFrame(e:Event):void {
            var gotIntersect:Boolean;
            endPt.x = mouseX;
            endPt.y = mouseY;
            graphics.clear();
            
              _coincident = false;
              
            gotIntersect = IsIntersecting(startPt, endPt, pt1, pt2);
           

            
            var count:int = 0;
            var color:uint =   0;
            if (gotIntersect ) {
                color = 0xFF0000;
                intersectTimes[count] = r;
                intersectZ[count] = pt2.z * s - pt1.z * s  + pt1.z;
                count++;
                
            }
            gotIntersect = IsIntersecting(startPt, endPt, pt2, pt3);
            if (gotIntersect ) {
                color = 0xFF0000;
                intersectTimes[count] = r;
                intersectZ[count] = pt3.z * s - pt2.z * s  + pt2.z;
                count++;
            }
            
            gotIntersect = IsIntersecting(startPt, endPt, pt3, pt1);
            if (gotIntersect ) {
                if (count <2) {
                    color = 0xFF0000;
                    intersectTimes[count] = r;
                    intersectZ[count] = pt1.z * s - pt3.z * s  + pt3.z;
                    count++;
                }
            }
            
            graphics.lineStyle(0, color, 1);
            graphics.moveTo(startPt.x, startPt.y);
            graphics.lineTo(endPt.x, endPt.y);
            
            graphics.moveTo(pt1.x, pt1.y);
            graphics.lineTo(pt2.x, pt2.y);
            graphics.lineTo(pt3.x, pt3.y);
            graphics.lineTo(pt1.x, pt1.y);
            
            var dx:Number = endPt.x - startPt.x;
            var dy:Number  = endPt.y - startPt.y;
            
            var temp:Number = intersectTimes[0];
            var temp2:Number = intersectZ[0];
            
           

            
            if (intersectTimes[1] < temp ) {
                intersectTimes[0] = intersectTimes[1];
                intersectZ[0] = intersectZ[1];
                
                intersectTimes[1] = temp;
                intersectZ[1]=temp2;
            }
            
            
            if (color == 0xFF0000) {
                graphics.beginFill(0, 1);
                var ax:Number;
                var ay:Number;
                var bx:Number;
                var by:Number;
                
              if (intersectTimes[0] < 0) {  // start dot from inside instead mod
                 intersectZ[0] -= intersectTimes[0]/(intersectTimes[1]-intersectTimes[0])*(intersectZ[1] - intersectZ[0]);
                 intersectTimes[0]  = 0;
              }

                graphics.drawCircle(ax=startPt.x + dx * intersectTimes[0], ay = startPt.y + dy * intersectTimes[0], 2);
                graphics.drawCircle(bx= startPt.x + dx * intersectTimes[1], by = startPt.y + dy * intersectTimes[1], 3);
                
                var rd:Number = (intersectTimes[1] - intersectTimes[0]);
           
               var gradient:Number;
               
             
               
             
             
               if (_coincident) {
                     
                    gradient = ( - intersectZ[0]) / rd;
                    debugField.text = "Coincident found (gradient):" + gradient + ", "+(count > 1);
               }
                else if (count > 1) {
                    if (rd> 0) {
                        
                      gradient = (intersectZ[1] - intersectZ[0]) / rd;
                      debugField.text = "penetrate dist:" + rd + ", gradient:"+gradient + ", "+intersectTimes;
                    }
                    else {
                         debugField.text = "Hit a fully vertical wall!:"+[0];
                    }
                }
            
                else {
                    debugField.text = "Should not happen! Exception occured!";
                }

            
            }
            else {
                debugField.text = "No penetrate";
            }
        }
        
        public function sqDistBetween2DVector(a:Vector3D, b:Vector3D):Number {
            var dx:Number = b.x - a.x;
            var dy:Number = b.y - a.y;
            return dx * dx + dy * dy;
        }
        
        public function rBetween2DVec(a:Vector3D, b:Vector3D, c:Vector3D):Number {
            var dx:Number = b.x - a.x;
            var dy:Number = b.y - a.y;
            var dx2:Number = c.x - a.x;
            var dy2:Number = c.y - a.y;
            return dx * dx2 + dy * dy2;
        }
        

     private var _coincident:Boolean;
        
        public function IsIntersecting(a:Vector3D, b:Vector3D, c:Vector3D, d:Vector3D):Boolean
        {
            var denominator:Number = ((b.x - a.x) * (d.y - c.y)) - ((b.y - a.y) * (d.x - c.x));
            var numerator1:Number = ((a.y - c.y) * (d.x - c.x)) - ((a.x - c.x) * (d.y - c.y));
            var numerator2:Number = ((a.y - c.y) * (b.x - a.x)) - ((a.x - c.x) * (b.y - a.y));

            // Detect coincident lines (has a problem, read below)
            if (denominator == 0) {
                // find between c and d, which is closer to a, clamp to s to 1 and 0, set r to c/d
               s = sqDistBetween2DVector(a, c) < sqDistBetween2DVector(a, d) ? 0 : 1;
               r = s != 0 ? rBetween2DVec(a, b, d)  : rBetween2DVec(a, b, c);
              // throw new Error("DETECT");
               _coincident = true;
                return false;// (r >= 0) && (s >= 0 && s <= 1);
               //  return numerator1 == 0 && numerator2 == 0;
            }


            r = numerator1 / denominator;
            s = numerator2 / denominator;
            // && r <= 1
            // (r >= 0) &&
            return  (s >= 0 && s <= 1);
        }
    
     }
    
}