void myActions() { // actions to be executed at each frame size(600, 600); // prints text at top of the graphic window (see TAB UI), line 0 if ((mousePressed)&&(!keyPressed)) dragPoint(); // while mouse pressed moves the selected point by mouse displacement (in TAB polygon) fill(black); // set fill color to black (for writing text in the windows) strokeWeight(3); // set stroke width to 3 stroke(blue); // set current color to blue pt A=P[0]; A.show(2); A.showLabel("D"); // Assign variable point A to P[0], show it as a disk of radius 4, write its label "A" next to it pt B=P[1]; B.show(2); B.showLabel("E"); A.to(B); // draw a line from A to B in current color (see TAB geo2D, end of class pt) stroke(green); pt C=P[2]; C.show(2); C.showLabel("A"); pt D=P[3]; D.show(2); D.showLabel("B"); pt E=P[4]; E.show(2); E.showLabel("C"); C.to(D); C.to(E); D.to(E); stroke(orange); showEdgeEdgeIntersection(A,B,C,D,E); // WHERE THE ACTUAL INTERSECTION IS COMPUTED AND DISPLAYED (see below) fill(black); }; void showEdgeEdgeIntersection(pt A, pt B, pt C, pt D, pt E) { // show intersection point between two edges if it exists int intersections = 0; pt[] intesection = new pt[2]; pt oneSide = P(0,0); boolean overlapping = false; if (edgesCross(A, B, C, D)) { // test if edge(A,B) and edge(C,D) actually intersect (see below) // TESTS THE FIRST SEGMENT CD vec T=V(A,B); // make vector T=AB vec N = R(V(C,D)); // makes vector N by rotating CD by 90 degrees vec AC = V(A,C); float t = dot(AC,N) / dot(T,N); // compute intersection parameter vec test1 = V(A,B); test1.normalize(); vec test2 = V(C,D); test2.normalize(); if(abs(dot(test1,test2)) > .9999){ overlapping = true; pt center = P(0,0); pt xAxis = P(1,0); pt start = A; pt midStart = P(0,0); pt midEnd = P(0,0); pt finish = A; if(dot(V(center,xAxis),V(center,finish)) < dot(V(center,xAxis),V(center,B))){ finish = B; } if(dot(V(center,xAxis),V(center,finish)) < dot(V(center,xAxis),V(center,C))){ finish = C; } if(dot(V(center,xAxis),V(center,finish)) < dot(V(center,xAxis),V(center,D))){ finish = D; } if(dot(V(center,xAxis),V(center,start)) > dot(V(center,xAxis),V(center,B))){ start = B; } if(dot(V(center,xAxis),V(center,start)) > dot(V(center,xAxis),V(center,C))){ start = C; } if(dot(V(center,xAxis),V(center,start)) > dot(V(center,xAxis),V(center,D))){ start = D; } if(A != start && A != finish){ midStart = A; if(B != start && B != finish){ midEnd = B; }else if(C != start && C != finish){ midEnd = C; }else{ midEnd = D; } }else if(B != start && B!=finish){ midStart = B; if(C != start && C != finish){ midEnd = C; }else{ midEnd = D; } }else{ midStart = C; midEnd = D; } midStart.to(midEnd); show(S(midStart,0,T)); show(S(midEnd,0,T)); }else{ show(S(A,t,T)); // show() shows a point as a small disk. S() computes a point on a line (see TAB geo2D) oneSide = S(A,t,T); intesection[intersections] = S(A,t,T); intersections ++; } // EXAMPLES OF DEBUGGING TECHNIQUES if (debugging) println("t="+t); // prints current value of t in the text output pane only once each time user presses '?' // scribe("t of AB="+t,1); // prints the value of t at the top of the graphics window (line 1) at each frame //stroke(cyan,200); arrow(M(C,D),50,U(N)); // shows semi-transparent 50 pixel arrow from (C+D)/2 aligned with N stroke(orange); } if(edgesCross(A,B,D,E)){ //TEST THE SECOND SEGMENT DE vec T = V(A,B); vec N = R(V(D,E)); vec AD = V(A,D); float t = dot(AD,N) / dot(T,N); vec test1 = V(A,B); test1.normalize(); vec test2 = V(D,E); test2.normalize(); if(abs(dot(test1,test2)) > .9999){ overlapping = true; pt center = P(0,0); pt xAxis = P(1,0); pt start = A; pt midStart = P(0,0); pt midEnd = P(0,0); pt finish = A; if(dot(V(center,xAxis),V(center,finish)) < dot(V(center,xAxis),V(center,B))){ finish = B; } if(dot(V(center,xAxis),V(center,finish)) < dot(V(center,xAxis),V(center,D))){ finish = D; } if(dot(V(center,xAxis),V(center,finish)) < dot(V(center,xAxis),V(center,E))){ finish = E; } if(dot(V(center,xAxis),V(center,start)) > dot(V(center,xAxis),V(center,B))){ start = B; } if(dot(V(center,xAxis),V(center,start)) > dot(V(center,xAxis),V(center,D))){ start = D; } if(dot(V(center,xAxis),V(center,start)) > dot(V(center,xAxis),V(center,E))){ start = E; } if(A != start && A != finish){ midStart = A; if(B != start && B != finish){ midEnd = B; }else if(D != start && D != finish){ midEnd = D; }else{ midEnd = E; } }else if(B != start && B!=finish){ midStart = B; if(D != start && D != finish){ midEnd = D; }else{ midEnd = E; } }else{ midStart = D; midEnd = E; } midStart.to(midEnd); show(S(midStart,0,T)); show(S(midEnd,0,T)); }else{ show(S(A,t,T)); // show() shows a point as a small disk. S() computes a point on a line (see TAB geo2D) intesection[intersections] = S(A,t,T); oneSide = S(A,t,T); intersections ++; } if (debugging) println("t="+t); // prints current value of t in the text output pane only once each time user presses '?' // scribe("t of BC="+t,2); // prints the value of t at the top of the graphics window (line 1) at each frame //stroke(cyan,200); arrow(M(D,E),50,U(N)); // shows semi-transparent 50 pixel arrow from (C+D)/2 aligned with N stroke(orange); } if(edgesCross(A,B,E,C)){ //TEST THE THIRD SEGEMNT EC vec T = V(A,B); vec N = R(V(E,C)); vec AE = V(A,E); float t = dot(AE,N) / dot(T,N); vec test1 = V(A,B); test1.normalize(); vec test2 = V(E,C); test2.normalize(); if(abs(dot(test1,test2)) > .9999){ overlapping = true; pt center = P(0,0); pt xAxis = P(1,0); pt start = A; pt midStart = P(0,0); pt midEnd = P(0,0); pt finish = A; if(dot(V(center,xAxis),V(center,finish)) < dot(V(center,xAxis),V(center,B))){ finish = B; } if(dot(V(center,xAxis),V(center,finish)) < dot(V(center,xAxis),V(center,E))){ finish = E; } if(dot(V(center,xAxis),V(center,finish)) < dot(V(center,xAxis),V(center,C))){ finish = C; } if(dot(V(center,xAxis),V(center,start)) > dot(V(center,xAxis),V(center,B))){ start = B; } if(dot(V(center,xAxis),V(center,start)) > dot(V(center,xAxis),V(center,E))){ start = E; } if(dot(V(center,xAxis),V(center,start)) > dot(V(center,xAxis),V(center,C))){ start = C; } if(A != start && A != finish){ midStart = A; if(B != start && B != finish){ midEnd = B; }else if(E != start && E != finish){ midEnd = E; }else{ midEnd = C; } }else if(B != start && B!=finish){ midStart = B; if(E != start && E != finish){ midEnd = E; }else{ midEnd = C; } }else{ midStart = E; midEnd = C; } midStart.to(midEnd); show(S(midStart,0,T)); show(S(midEnd,0,T)); }else{ show(S(A,t,T)); // show() shows a point as a small disk. S() computes a point on a line (see TAB geo2D) intesection[intersections] = S(A,t,T); oneSide = S(A,t,T); intersections ++; } if (debugging) println("t="+t); // prints current value of t in the text output pane only once each time user presses '?' // scribe("t of CA="+t,3); // prints the value of t at the top of the graphics window (line 1) at each frame // stroke(cyan,200); arrow(M(E,C),50,U(N)); // shows semi-transparent 50 pixel arrow from (C+D)/2 aligned with N stroke(orange); } stroke(red); if(!overlapping){ if (intersections == 2){ intesection[0].to(intesection[1]); stroke(orange); show(S(intesection[0],0,V(0,1))); show(S(intesection[1],0,V(0,1))); }else if(intersections == 1){ pt TB = P(D.x-C.x,D.y-C.y); pt TC = P(E.x-C.x,E.y-C.y); pt EA = P(A.x-C.x,A.y-C.y); float T = (EA.y*TB.x-TB.y*EA.x)/(-1*TC.x*TB.y+TC.y*TB.x); float S = (EA.x-(T*TC.x))/TB.x; //scribe("S="+S,4); //scribe("T="+T,5); if(S + T <1 &&S >0 && T >0){ oneSide.to(A); show(S(A,0,V(0,1))); }else{ oneSide.to(B); show(S(B,0,V(0,1))); } stroke(orange); show(S(oneSide,0,V(0,1))); }else{ pt TB = P(D.x-C.x,D.y-C.y); pt TC = P(E.x-C.x,E.y-C.y); pt EA = P(A.x-C.x,A.y-C.y); float T = (EA.y*TB.x-TB.y*EA.x)/(-1*TC.x*TB.y+TC.y*TB.x); float S = (EA.x-(T*TC.x))/TB.x; // scribe("S="+S,4); // scribe("T="+T,5); if(S + T <1 &&S >0 && T >0){ A.to(B); show(S(A,0,V(0,1))); show(S(B,0,V(0,1))); } } } intersections = 0; } boolean ordered(pt A, pt B, pt C) {return (00 != dot(U(R(V(A,B))),V(A,D))>0) // tests whether two edges cross && (dot(U(R(V(C,D))),V(C,A))>0 != dot(U(R(V(C,D))),V(C,B))>0) ; }