Dot crossing a line?

Hello,

Given 2 point A(x,y) and B(x,y), is there a way to tell if C(x,y) is crossing the line that A,B do? I mean in between thoses to 2 points…
TiA :smiley:

hitTest?

yeah, i would say you could use a “lineto” “onEnterFrame” and then hitTest it.

well i was looking for a Mathematical way :slight_smile:

I’m no mathmatician, and someone here can probably point out the fallacy of this reasoning, but it seems to me that if the slope between the two points that define your line equals the slope between your test point and one of the two line defining points then that test point must be on the line… Right (I’m asking)?
If that’s actually true, you can use something like this:
[AS]import flash.geom.Point;
//
// Points A & B are known to define line
var A:Point = new Point(20, 20);
var B:Point = new Point(50, 50);
//
// Point C is point to test
var C:Point = new Point(10, 10);
//
trace(isPointOnLine(A, B, C));
//
// First two points define line - p3 is point in question
function isPointOnLine(p1:Point, p2:Point, p3:Point):Boolean {
var m1:Number = getSlope(p1, p2);
if (m1 == -Infinity || m1 == Infinity) m1 = Math.abs(m1);
var m2:Number = getSlope(p2, p3);
if (m2 == -Infinity || m2 == Infinity) m2 = Math.abs(m2);
return (m1 == m2) ? true : false;
}
function getSlope(p1:Point, p2:Point):Number {
var m:Number = (p2.y - p1.y) / (p2.x - p1.x);
return m;
}[/AS]

Im not sure about this but… when you look at a generic line equasion (y=ax+b) you can use point A x and y coordinates and put them into that your specific exuation (e.g y=2x+1). If you try it with point A[1;1] then you will see that left and right-hand sides of that formula dont match (= point does not belong that line). If you try point B[1;3] you will see that 3=3, thus it lays on that line.

To see if that point also belong only to the line serment between your two points you can just check with a condition or use line-segment equasion instead.

lol I got a super easy solution to this

Let be two points P1, P2 and point P3 which you want to check…

When distance |P1, P3| + |P2, P3| is same as distance |P1, P2| then P3 lays on a line between P1 and P2 :hugegrin:

http://www.senocular.com/flash/source.php?id=0.36

Is that what you are looking for =)

Thats not realy it, Crayon. Senoculars example show intersection of two lines and finding a cross point… thats not applicable to this problem (at least I dont see the application here :wink: )

devonair’s solution is going to be your best bet, the only modification you need to do is make sure that the line is contained within the two points… you can simply do this…


import flash.geom.Point;
//
// Points A & B are known to define line
var A:Point = new Point(20, 20);
var B:Point = new Point(50, 50);
//
// Point C is point to test
var C:Point = new Point(10, 10);
var D:Point = new Point(30, 30);
//
trace(isPointOnLine(A, B, C));
trace(isPointOnLine(A, B, D));
//
//  First two points define line - p3 is point in question
function isPointOnLine(p1:Point, p2:Point, p3:Point):Boolean {
    var m1:Number = getSlope(p1, p2);
    if (m1 == -Infinity || m1 == Infinity) m1 = Math.abs(m1);
    var m2:Number = getSlope(p2, p3);
    if (m2 == -Infinity || m2 == Infinity) m2 = Math.abs(m2);
	 
	 var greaterXPoint:Point = (p1.x > p2.x) ? p1 : p2;
	 var greaterYPoint:Point = (p1.y > p2.y) ? p1 : p2;
	 var lesserXPoint:Point = (p1.x < p2.x) ? p1 : p2;
	 var lesserYPoint:Point = (p1.y < p2.y) ? p1 : p2;
	 
	 if ( p3.x > greaterXPoint.x || p3.y > greaterYPoint.y || p3.x < lesserXPoint.x || p3.y < lesserYPoint.y )
	 {
		 return false;
	 }
	 
    return (m1 == m2) ? true : false;
}
function getSlope(p1:Point, p2:Point):Number {
    var m:Number = (p2.y - p1.y) / (p2.x - p1.x);
    return m;
}

lineStyle(0, 0x0, 100);
moveTo( A.x, A.y );
lineTo( B.x, B.y );

lineStyle(10, 0x0, 100);
moveTo( C.x, C.y );
lineTo( C.x, C.y+1 );

lineStyle(10, 0x00FF00, 100);
moveTo( D.x, D.y );
lineTo( D.x, D.y+1 );

Take Care.
_Michael

Thats too complicated…

import flash.geom.Point;
// points forming a line segment
var p1:Point = new Point(0, 0);
var p2:Point = new Point(100, 100);
// point to be checked
var A:Point = new Point(50,50);
var B:Point = new Point(60,30);

trace(isPointOnLine(p1, p2, A)); // true
trace(isPointOnLine(p1, p2, B)); // false

function isPointOnLine(p1:Point, p2:Point, p3:Point):Boolean {
	d1 = Point.distance(p1, p3) + Point.distance(p2, p3);
	d2 = Point.distance(p1, p2) ;
	return (d1 == d2) ? true : false;
}

@matthew.er - I like it, elegant

I’d benchmark the two and see which runs better, I’m not sure how intense the distance formula is in Actionscript in comparison to the conditionals (which are way less) but the memory allocation might push it just over the distance calls.

I’m not sure which way it would work best, if you benchmark please post results, I am interested. I personally would like to know because though it’s a bit more complicated I’d sacrifice how intuitive it is for how quickly it runs.

Take Care.
_Michael

You’re a super genius… how simple…

I tested with 1000 calls and my function was about 4 time slower (970ms vs. 270ms). Strange, I always tought that built-in functions are faster :slight_smile:

Well the problem is that you are making distance calls…

distance is…

Math.sqrt( (a * a) + ( b * b ) );

The implementation of sqrt is rather intense in comparison to other methods, whether or not it is a built-in function isn’t relative, the implementations are the same.

I hope this make sense, if you have any questions about any of this feel free to ask.

Take Care.
_Michael

Looking over this I optimized the code even further… due to the nature of how actionscript handles numbers (and it’s limits as far as points and lines are concerned)

You can replace the isPointOnLine method with the following…


function isPointOnLine(p1:Point, p2:Point, p3:Point):Boolean {
    var m1:Number = getSlope(p1, p2);
    var m2:Number = getSlope(p2, p3);

	 if ( p3.x > ((p1.x > p2.x) ? p1.x : p2.x) || p3.x < ((p1.x < p2.x) ? p1.x : p2.x) )
	 {
		 return false;
	 }
	 
    return (m1 == m2) ? true : false;
}

If you could benchmark this again and post the results that would be awesome. Take Care.

_Michael

Ok, here are results on 1Ghz PIII, with 10.000 loops

the old one cca 2732 ms
this new version cca 1793 ms

thats one nice improvement :thumb:

I figured that it would be significant… Thank you very much matthew.er, I usually have no probelm doing the benchmarking myself, but I yesterday I was in and out all day. You take care, if I come up with any improvements they will be posted here.

TakeCare
_Michael

function isPointOnLine(p1:Point, p2:Point, p3:Point):Boolean {
     if ( p3.x > ((p1.x > p2.x) ? p1.x : p2.x) || p3.x < ((p1.x < p2.x) ? p1.x : p2.x) )
     {
         return false;
     }

    var m1:Number = getSlope(p1, p2);
    var m2:Number = getSlope(p2, p3);
    
    return (m1 == m2) ? true : false;
}

Here the optimization is actually not significant, and you’d only see a performance benefit with large iterations over points that do not exist on the line. I don’t know what I was thinking before ;), because if the point is not within the range on the x axis then there is no possibility that the point exists on that segment, therefore the calls to getSlope() and the allocation of memory are overkill and create unnecessary overhead on invocation of this method.

_Michael

[ot]lol, Michael, where do you get all that insight on how these things work?[/ot]