void myActions() { // actions to be executed at each frame scribe("Jarek Rossignac's triangle / triangle Booleans (general position)"); //*:01 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); //*:05 reset fill color to black (for writing text in the windows) pt A=P[0], B=P[2], C=P[4], D=P[1], E=P[3], F=P[5]; stroke(dblue); fill(cyan,200); strokeWeight(2); showTriangle(A,B,C); showTriangle(D,E,F); A.show(2); B.show(2); C.show(2); D.show(2); E.show(2); F.show(2); fill(black); A.showLabel("A"); B.showLabel("B"); C.showLabel("C"); D.showLabel("D"); E.showLabel("E"); F.showLabel("F"); // INTERSECTION pushMatrix(); translate(width/2,0); stroke(black); strokeWeight(4); fill(red); showBdry(A,B,C,D,E,F,0); noFill(); stroke(dblue,100); noFill(); strokeWeight(1); showTriangle(A,B,C); showTriangle(D,E,F); popMatrix(); // DIFFERENCE pushMatrix(); translate(0,height/2); stroke(black); strokeWeight(4); fill(blue); showBdry(A,B,C,D,E,F,1); noFill(); stroke(dblue,100); noFill(); strokeWeight(1); showTriangle(A,B,C); showTriangle(D,E,F); popMatrix(); // UNION pushMatrix(); translate(width/2,height/2); stroke(black); strokeWeight(4); fill(green); showBdry(A,B,C,D,E,F,2); noFill(); stroke(dblue,100); noFill(); strokeWeight(1); showTriangle(A,B,C); showTriangle(D,E,F); popMatrix(); }; void showBdry(pt A, pt B, pt C, pt D, pt E, pt F, int o) { // computes, draws, & fills the boundary of a Boolean between 2 triangles int maxn = 12; // max number of vertices on the boundary int n=0; // counts the number of vertices on the boundary pt[] X = new pt[maxn]; // table of vertices of the boundary int[] E1 = new int[maxn], E2 = new int[maxn]; // table of IDs of the 2 triangle edges touching or crossing at the corresponding vertex // ********** Make table X of bounding vertices and record which triangle edges they lie on ************** if(o==0) { // intersection : test original vertices and add proper ones to the vertex table if(A.isInTriangle(D,E,F)) {X[n]=A; E1[n]=3; E2[n]=1; n++;}; if(B.isInTriangle(D,E,F)) {X[n]=B; E1[n]=1; E2[n]=2; n++;}; if(C.isInTriangle(D,E,F)) {X[n]=C; E1[n]=2; E2[n]=3; n++;}; if(D.isInTriangle(A,B,C)) {X[n]=D; E1[n]=6; E2[n]=4; n++;}; if(E.isInTriangle(A,B,C)) {X[n]=E; E1[n]=4; E2[n]=5; n++;}; if(F.isInTriangle(A,B,C)) {X[n]=F; E1[n]=5; E2[n]=6; n++;}; }; if(o==1) { // difference: test original vertices and add proper ones to the vertex table if(!A.isInTriangle(D,E,F)) {X[n]=A; E1[n]=3; E2[n]=1; n++;}; if(!B.isInTriangle(D,E,F)) {X[n]=B; E1[n]=1; E2[n]=2; n++;}; if(!C.isInTriangle(D,E,F)) {X[n]=C; E1[n]=2; E2[n]=3; n++;}; if(D.isInTriangle(A,B,C)) {X[n]=D; E1[n]=6; E2[n]=4; n++;}; if(E.isInTriangle(A,B,C)) {X[n]=E; E1[n]=4; E2[n]=5; n++;}; if(F.isInTriangle(A,B,C)) {X[n]=F; E1[n]=5; E2[n]=6; n++;}; }; if(o==2) { // union: test original vertices and add proper ones to the vertex table if(!A.isInTriangle(D,E,F)) {X[n]=A; E1[n]=3; E2[n]=1; n++;}; if(!B.isInTriangle(D,E,F)) {X[n]=B; E1[n]=1; E2[n]=2; n++;}; if(!C.isInTriangle(D,E,F)) {X[n]=C; E1[n]=2; E2[n]=3; n++;}; if(!D.isInTriangle(A,B,C)) {X[n]=D; E1[n]=6; E2[n]=4; n++;}; if(!E.isInTriangle(A,B,C)) {X[n]=E; E1[n]=4; E2[n]=5; n++;}; if(!F.isInTriangle(A,B,C)) {X[n]=F; E1[n]=5; E2[n]=6; n++;}; }; // add all edge/edge crossing as to the vertex table if(edgesCross(A,B,D,E)) {X[n]=EE(A,B,D,E); E1[n]=1; E2[n]=4; n++;}; if(edgesCross(A,B,E,F)) {X[n]=EE(A,B,E,F); E1[n]=1; E2[n]=5; n++;}; if(edgesCross(A,B,F,D)) {X[n]=EE(A,B,F,D); E1[n]=1; E2[n]=6; n++;}; if(edgesCross(B,C,D,E)) {X[n]=EE(B,C,D,E); E1[n]=2; E2[n]=4; n++;}; if(edgesCross(B,C,E,F)) {X[n]=EE(B,C,E,F); E1[n]=2; E2[n]=5; n++;}; if(edgesCross(B,C,F,D)) {X[n]=EE(B,C,F,D); E1[n]=2; E2[n]=6; n++;}; if(edgesCross(C,A,D,E)) {X[n]=EE(C,A,D,E); E1[n]=3; E2[n]=4; n++;}; if(edgesCross(C,A,E,F)) {X[n]=EE(C,A,E,F); E1[n]=3; E2[n]=5; n++;}; if(edgesCross(C,A,F,D)) {X[n]=EE(C,A,F,D); E1[n]=3; E2[n]=6; n++;}; // ********** Make table of bounding edges recording their vertex IDs in edges[][] ************** int [][] edges = new int[12][2]; // edges of the boundary each defined by 2 indices to their end vertices in the X table boolean [] usedX = new boolean[maxn]; // table for marking used vertices when building loops boolean [] usedE = new boolean[12]; // table for marking used edges when making loops int ne=0; // counter of in the boundary edges for (int e=1; e<7; e++) { // for each triangle edge int[] I = new int[4]; // store up to 4 vertex IDs int ni = 0; // counter of intersections found on this edge for (int i=0; i0 != 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) ; } pt EE(pt A, pt B, pt C, pt D) { // returns intersection point between two edges assuming it exists 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 return S(A,t,T); // returns intersection. S() computes a point on a line (see TAB geo2D) }