Monday, June 5, 2017

Intersection Of Lines

Calculate where two lines cross defined by
segments pa1-pa2 and pb1-pb2 


Usage:


function  IntersectionOfLines(pa1, pa2, pb1, pb2)=
let(
da = [(pa1.x-pa2.x),(pa1.y-pa2.y)], 
db = [(pb1.x-pb2.x),(pb1.y-pb2.y)],
the = da.x*db.y - da.y*db.x                 )
(the == 0)? 
undef: /* no in tersection*/
let (
A = (pa1.x * pa2.y - pa1.y * pa2.x),
B = (pb1.x * pb2.y - pb1.y * pb2.x)         )
[( A*db.x - da.x*B ) / the , ( A*db.y - da.y*B ) / the]
;

// demo code
pa1=[rnd(100),rnd(100)];
pa2 =[rnd(100),rnd(100)];
pb1=[rnd(100),rnd(100)];
pb2=[rnd(100),rnd(100)];
I=IntersectionOfLines(pa1, pa2, pb1, pb2);
line(pa1, pa2);
line(pb1, pb2);


// show in red if intersecting 
// else extend linese outside segments
if(I.x>min(pa1.x,pa2.x)&&I.x<max(pa1.x,pa2.x)
&&I.y>min(pa1.y,pa2.y)&&I.y<max(pa1.y,pa2.y))
{color("red")translate(I) sphere(3);
}
else{
translate(I) sphere(3);
hull(){
translate(I) sphere(0.5);
translate(pa1) sphere(0.5);}
hull(){
translate(I) sphere(0.5);
translate(pb1) sphere(0.5);}
}


echo(I);

module line(p1,p2){hull(){
translate(p1) sphere(1);
translate(p2) sphere(1);
}}

function rnd(a = 1, b = 0, s = []) =
s == [] ?
  (rands(min(a, b), max(
    a, b), 1)[0]) :
  (rands(min(a, b), max(a, b), 1, s)[0]);
 

2 comments:

  1. Search for line intersection is correct. Later check whether two line segments have common point is incorrect: not enough checks. It may show cross point in red, while segments do not touch each other.
    Should be like this:
    if (xyBelongsToAB(I, pa1, pa2) && xyBelongsToAB(I, pb1, pb2))
    {color("red")translate(I) sphere(3);
    }
    ...

    ReplyDelete
    Replies
    1. Excellent catch. The current check is a lazy box intersection. I leave it as an exercise for the user to implement the correct checks. Tanks for the catch.

      Delete