public boolean intersects(Circle circle) { // using Vector Projection // https://en.wikipedia.org/wiki/Vector_projection Vector c = Vector.create(circle.x(), circle.y()); Vector a = Vector.create(x1, y1); Vector cMinusA = c.minus(a); float radiusSquared = circle.radius() * circle.radius(); if (x1 == x2 && y1 == y2) { return cMinusA.modulusSquared() <= radiusSquared; } else { Vector b = Vector.create(x2, y2); Vector bMinusA = b.minus(a); float bMinusAModulus = bMinusA.modulus(); float lambda = cMinusA.dot(bMinusA) / bMinusAModulus; // if projection is on the segment if (lambda >= 0 && lambda <= bMinusAModulus) { Vector dMinusA = bMinusA.times(lambda / bMinusAModulus); // calculate distance to line from c using pythagoras' theorem return cMinusA.modulusSquared() - dMinusA.modulusSquared() <= radiusSquared; } else { // return true if and only if an endpoint is within radius of // centre return cMinusA.modulusSquared() <= radiusSquared || c.minus(b).modulusSquared() <= radiusSquared; } } }
public void testMinus() throws Exception { Vector val = test.minus(test); assertEquals("size", test.size(), val.size()); for (int i = 0; i < test.size(); i++) { assertEquals("get [" + i + ']', 0.0, val.get(i)); } val = test.minus(test).minus(test); assertEquals("cardinality", test.size(), val.size()); for (int i = 0; i < test.size(); i++) { assertEquals("get [" + i + ']', 0.0, val.get(i) + test.get(i)); } Vector val1 = test.plus(1); val = val1.minus(test); for (int i = 0; i < test.size(); i++) { assertEquals("get [" + i + ']', 1.0, val.get(i)); } val1 = test.plus(-1); val = val1.minus(test); for (int i = 0; i < test.size(); i++) { assertEquals("get [" + i + ']', -1.0, val.get(i)); } }
// intersectRayAndTriangle(): intersect a ray with a 3D triangle // Input: a ray R, and a triangle T // Output: *I = intersection point (when it exists) // Return: -1 = triangle is degenerate (a segment or point) // 0 = disjoint (no intersect) // 1 = intersect in unique point I1 // 2 = are in the same plane public static int intersectRayAndTriangle(Ray R, Triangle T, float[] I) { float[] u, v, n; // triangle vectors float[] dir, w0, w; // ray vectors float r, a, b; // params to calc ray-plane intersect // get triangle edge vectors and plane normal u = Vector.minus(T.V1, T.V0); v = Vector.minus(T.V2, T.V0); n = Vector.crossProduct(u, v); // cross product if (Arrays.equals(n, new float[] {0.0f, 0.0f, 0.0f})) { // triangle is degenerate return -1; // do not deal with this case } dir = Vector.minus(R.P1, R.P0); // ray direction vector w0 = Vector.minus(R.P0, T.V0); a = -Vector.dot(n, w0); b = Vector.dot(n, dir); if (Math.abs(b) < SMALL_NUM) { // ray is parallel to triangle plane if (a == 0) { // ray lies in triangle plane return 2; } else { return 0; // ray disjoint from plane } } // get intersect point of ray with triangle plane r = a / b; if (r < 0.0f) { // ray goes away from triangle return 0; // => no intersect } // for a segment, also test if (r > 1.0) => no intersect float[] tempI = Vector.addition(R.P0, Vector.scalarProduct(r, dir)); // intersect point of ray and a plane I[0] = tempI[0]; I[1] = tempI[1]; I[2] = tempI[2]; // is I inside T? float uu, uv, vv, wu, wv, D; uu = Vector.dot(u, u); uv = Vector.dot(u, v); vv = Vector.dot(v, v); w = Vector.minus(I, T.V0); wu = Vector.dot(w, u); wv = Vector.dot(w, v); D = (uv * uv) - (uu * vv); // get and test parametric coords float s, t; s = ((uv * wv) - (vv * wu)) / D; if (s < 0.0f || s > 1.0f) // I is outside T return 0; t = (uv * wu - uu * wv) / D; if (t < 0.0f || (s + t) > 1.0f) // I is outside T return 0; return 1; // I is in T }
public void testGetDistanceSquared() { Vector other = new RandomAccessSparseVector(test.size()); other.set(1, -2); other.set(2, -5); other.set(3, -9); other.set(4, 1); double expected = test.minus(other).getLengthSquared(); assertTrue( "a.getDistanceSquared(b) != a.minus(b).getLengthSquared", Math.abs(expected - test.getDistanceSquared(other)) < 10.0E-7); }