class Vert { public float x, y; Vert(float posX, float posY) { x = posX; y = posY; } public void update() { point(x, y); } public float distPointToLine(Line L) { Vert v = vectSub(L.v1, L.v0); Vert w = vectSub(this, L.v0); float c1 = dot(w,v); if (c1 <= 0) { return distance(this, L.v0); } float c2 = dot(v,v); if (c2 <= c1) { return distance(this, L.v1); } if (c2 != 0) { float b = c1 / c2; Vert pr = vectMult(b, v); Vert Pb = vectAdd(L.v0, pr); return distance(this, Pb); } else { return 0; } } }; class Line { Vert v0; Vert v1; float cPoint; float targetPoint; Line(Vert p0, Vert p1) { v0 = p0; v1 = p1; } public float diffX() { return v1.x - v0.x; } public float diffY() { return v1.y - v0.y; } public void update() { line(v0.x, v0.y, v1.x, v1.y); } public void update(float mX, float mY) { v1.x = mX; v1.y = mY; line(v0.x, v0.y, v1.x, v1.y); } public void drawCpoint() { float cX = diffX() * cPoint; float cY = diffY() * cPoint; point(v0.x + cX, v0.y + cY); } public void drawTargetPoint(float targetV) { float cX = diffX() * targetV; float cY = diffY() * targetV; point(v0.x + cX, v0.y + cY); strokeWeight(0.5); ellipse(v0.x + cX, v0.y + cY, 50, 50); } public void drawInverse(float x, float y, float len) { float endX = diffY() / distance(v0, v1); float endY = diffX() / distance(v0, v1); endX *= len; endY *= len; line(x, y, x - endX, y+ endY); } }; Vert vectAdd(Vert one, Vert two) { Vert result; float x = one.x + two.x; float y = one.y + two.y; result = new Vert(x, y); return result; } Vert vectSub(Vert one, Vert two) { Vert result; float x = one.x - two.x; float y = one.y - two.y; result = new Vert(x, y); return result; } Vert vectMult(float scalar, Vert vector) { Vert result; float x = vector.x * scalar; float y = vector.y * scalar; result = new Vert(x, y); return result; } float dot(Vert one, Vert two) { float result; result = (one.x * two.x) + (one.y * two.y); return result; } float vectNorm(Vert one) { float result; result = sqrt(dot(one, one)); return result; } float distance(Vert one, Vert two) { float result; result = vectNorm(vectSub(one, two)); return result; } float distLineToLine( Line S1, Line S2) { Vert u = vectSub(S1.v1, S1.v0); Vert v = vectSub(S2.v1, S2.v0); Vert w = vectSub(S1.v0, S2.v0); float a = dot(u, u); // always >= 0 float b = dot(u, v); float c = dot(v, v); // always >= 0 float d = dot(u, w); float e = dot(v, w); float vDist = (a * c) - (b * b); // always >= 0 float sc, sN, sD = vDist; // sc = sN / sD, default sD = D >= 0 float tc, tN, tD = vDist; // tc = tN / tD, default tD = D >= 0 // compute the line parameters of the two closest points if (vDist < 0.00001) { // the lines are almost parallel sN = 0.0; // force using point P0 on segment S1 sD = 1.0; // to prevent possible division by 0.0 later tN = e; tD = c; } else { // get the closest points on the infinite lines sN = (b*e - c*d); tN = (a*e - b*d); if (sN < 0.0) { // sc < 0 => the s=0 edge is visible sN = 0.0; tN = e; tD = c; } else if (sN > sD) { // sc > 1 => the s=1 edge is visible sN = sD; tN = e + b; tD = c; } } if (tN < 0.0) { // tc < 0 => the t=0 edge is visible tN = 0.0; // recompute sc for this edge if (-d < 0.0) sN = 0.0; else if (-d > a) sN = sD; else { sN = -d; sD = a; } } else if (tN > tD) { // tc > 1 => the t=1 edge is visible tN = tD; // recompute sc for this edge if ((-d + b) < 0.0) sN = 0; else if ((-d + b) > a) sN = sD; else { sN = (-d + b); sD = a; } } // finally do the division to get sc and tc sc = (abs(sN) < 0.00001 ? 0.0 : sN / sD); tc = (abs(tN) < 0.00001 ? 0.0 : tN / tD); // the contact points along the lines S1.cPoint = sc; S2.cPoint = tc; // get the difference of the two closest points Vert sub1 = vectMult(sc, u); Vert sub2 = vectMult(tc, v); Vert add1 = w; Vert add2 = vectSub(sub1, sub2); Vert dP = vectAdd(add1, add2); // = S1(sc) - S2(tc) float finalDist = vectNorm(dP); finalDist = (finalDist < 0.0001 ? 0.0 : finalDist); return finalDist; // return the closest distance }