/* * Copyright (C) 2011-2016, Peter Abeles. All Rights Reserved. * * This file is part of Geometric Regression Library (GeoRegression). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package georegression.metric; import georegression.geometry.UtilPlane3D_F64; import georegression.misc.GrlConstants; import georegression.struct.line.LineParametric3D_F64; import georegression.struct.line.LineSegment3D_F64; import georegression.struct.plane.PlaneGeneral3D_F64; import georegression.struct.plane.PlaneNormal3D_F64; import georegression.struct.point.Point3D_F64; import georegression.struct.shapes.Box3D_F64; import georegression.struct.shapes.BoxLength3D_F64; import georegression.struct.shapes.Sphere3D_F64; import georegression.struct.shapes.Triangle3D_F64; import org.junit.Test; import static org.junit.Assert.*; /** * @author Peter Abeles */ public class TestIntersection3D_F64 { @Test public void intersect_planenorm_linepara() { // simple case with a known solution PlaneNormal3D_F64 plane = new PlaneNormal3D_F64(2,1,0,2,0,0); LineParametric3D_F64 line = new LineParametric3D_F64(0,0,0,3,0,0); Point3D_F64 found = new Point3D_F64(); assertTrue(Intersection3D_F64.intersect(plane, line, found)); assertEquals(2,found.x, GrlConstants.DOUBLE_TEST_TOL); assertEquals(0,found.y, GrlConstants.DOUBLE_TEST_TOL); assertEquals(0,found.z, GrlConstants.DOUBLE_TEST_TOL); } @Test public void intersect_planegen_linepara() { // simple case with a known solution PlaneNormal3D_F64 plane = new PlaneNormal3D_F64(2,1,0,2,0,0); LineParametric3D_F64 line = new LineParametric3D_F64(0,0,0,3,0,0); PlaneGeneral3D_F64 general = UtilPlane3D_F64.convert(plane,(PlaneGeneral3D_F64)null); Point3D_F64 found = new Point3D_F64(); assertTrue(Intersection3D_F64.intersect(general, line, found)); assertEquals(2,found.x, GrlConstants.DOUBLE_TEST_TOL); assertEquals(0,found.y, GrlConstants.DOUBLE_TEST_TOL); assertEquals(0,found.z, GrlConstants.DOUBLE_TEST_TOL); } @Test public void intersect_plane_plane() { PlaneGeneral3D_F64 a = new PlaneGeneral3D_F64(3,-4,0.5,6); PlaneGeneral3D_F64 b = new PlaneGeneral3D_F64(1.5,0.95,-4,-2); LineParametric3D_F64 line = new LineParametric3D_F64(); Intersection3D_F64.intersect(a,b,line); // see if the origin of the line lies on both planes assertEquals(0, UtilPlane3D_F64.evaluate(a,line.p), GrlConstants.DOUBLE_TEST_TOL); assertEquals(0, UtilPlane3D_F64.evaluate(b,line.p), GrlConstants.DOUBLE_TEST_TOL); // now try another point on the line double x = line.p.x + line.slope.x; double y = line.p.y + line.slope.y; double z = line.p.z + line.slope.z; Point3D_F64 p = new Point3D_F64(x,y,z); assertEquals(0, UtilPlane3D_F64.evaluate(a,p), GrlConstants.DOUBLE_TEST_TOL); assertEquals(0, UtilPlane3D_F64.evaluate(b,p), GrlConstants.DOUBLE_TEST_TOL); } @Test public void intersection_triangle_ls() { LineSegment3D_F64 ls = new LineSegment3D_F64(); Point3D_F64 p = new Point3D_F64(); // degenerate triangle Triangle3D_F64 triangle = new Triangle3D_F64(1,1,1,2,2,2,3,3,3); assertEquals(-1,Intersection3D_F64.intersection(triangle,ls,p)); // no intersection triangle.set(1,0,0, 3,0,0, 3,2,0); ls.set(0,0,0, 0,0,10); // completely miss assertEquals(0, Intersection3D_F64.intersection(triangle, ls, p)); ls.set(0,0,0, 0,0,10); // hits the plain but not the triangle assertEquals(0, Intersection3D_F64.intersection(triangle, ls, p)); ls.set(2,0.5,-1, 2,0.5,-0.5); // would hit, but is too short assertEquals(0, Intersection3D_F64.intersection(triangle, ls, p)); ls.set(2,0.5,-0.5, 2,0.5,-1); // would hit, but is too short assertEquals(0,Intersection3D_F64.intersection(triangle,ls,p)); // unique intersection ls.set(2,0.5,1, 2,0.5,-1); assertEquals(1,Intersection3D_F64.intersection(triangle,ls,p)); assertEquals(0,p.distance(new Point3D_F64(2,0.5,0)),GrlConstants.DOUBLE_TEST_TOL); // infinite intersections ls.set(0, 0, 0, 4, 0, 0); assertEquals(2,Intersection3D_F64.intersection(triangle, ls, p)); } @Test public void contained_boxLength_point() { BoxLength3D_F64 box = new BoxLength3D_F64(2,3,4,1,1.5,2.5); // point clearly inside the code assertTrue(Intersection3D_F64.contained(box,new Point3D_F64(2.1,3.1,4.1))); // point way outside assertFalse(Intersection3D_F64.contained(box,new Point3D_F64(-2,9,8))); // test edge cases assertTrue(Intersection3D_F64.contained(box,new Point3D_F64(2,3,4))); assertFalse(Intersection3D_F64.contained(box, new Point3D_F64(2+1, 3.1, 4.1))); assertFalse(Intersection3D_F64.contained(box, new Point3D_F64(2.1, 3+1.5, 4.1))); assertFalse(Intersection3D_F64.contained(box, new Point3D_F64(2.1, 3.1, 4+2.5))); } @Test public void contained_box_point() { Box3D_F64 box = new Box3D_F64(2,3,4,3,4.5,6.5); // point clearly inside the code assertTrue(Intersection3D_F64.contained(box,new Point3D_F64(2.1,3.1,4.1))); // point way outside assertFalse(Intersection3D_F64.contained(box,new Point3D_F64(-2,9,8))); // test edge cases assertTrue(Intersection3D_F64.contained(box,new Point3D_F64(2,3,4))); assertFalse(Intersection3D_F64.contained(box, new Point3D_F64(2+1, 3.1, 4.1))); assertFalse(Intersection3D_F64.contained(box, new Point3D_F64(2.1, 3+1.5, 4.1))); assertFalse(Intersection3D_F64.contained(box, new Point3D_F64(2.1, 3.1, 4+2.5))); } @Test public void contained2_box_point() { Box3D_F64 box = new Box3D_F64(2,3,4,3,4.5,6.5); // point clearly inside the code assertTrue(Intersection3D_F64.contained2(box, new Point3D_F64(2.1, 3.1, 4.1))); // point way outside assertFalse(Intersection3D_F64.contained2(box, new Point3D_F64(-2, 9, 8))); // test edge cases assertTrue(Intersection3D_F64.contained2(box, new Point3D_F64(2, 3, 4))); assertTrue(Intersection3D_F64.contained2(box, new Point3D_F64(2 + 1, 3.1, 4.1))); assertTrue(Intersection3D_F64.contained2(box, new Point3D_F64(2.1, 3 + 1.5, 4.1))); assertTrue(Intersection3D_F64.contained2(box, new Point3D_F64(2.1, 3.1, 4 + 2.5))); } @Test public void contained_box_box() { Box3D_F64 box = new Box3D_F64(2,3,4,3,4.5,6.5); // identical assertTrue(Intersection3D_F64.contained(box,new Box3D_F64(2,3,4,3,4.5,6.5))); // smaller assertTrue(Intersection3D_F64.contained(box,new Box3D_F64(2.1,3.1,4.1,2.9,4.4,6.4))); // partial x-axis assertFalse(Intersection3D_F64.contained(box,new Box3D_F64(1.9,3,4,3,4.5,6.5))); assertFalse(Intersection3D_F64.contained(box,new Box3D_F64(2,3,4,3.1,4.5,6.5))); // partial y-axis assertFalse(Intersection3D_F64.contained(box,new Box3D_F64(2,2.9,4,3,4.5,6.5))); assertFalse(Intersection3D_F64.contained(box,new Box3D_F64(2,3,4,3,4.6,6.5))); // partial z-axis assertFalse(Intersection3D_F64.contained(box,new Box3D_F64(2,3,3.9,3,4.5,6.5))); assertFalse(Intersection3D_F64.contained(box,new Box3D_F64(2,3,4,3,4.5,6.6))); } @Test public void intersect_box_box() { Box3D_F64 box = new Box3D_F64(2,3,4,3,4.5,6.5); // identical assertTrue(Intersection3D_F64.contained(box,new Box3D_F64(2,3,4,3,4.5,6.5))); // outside assertFalse(Intersection3D_F64.contained(box,new Box3D_F64(10,10,10,12,12,12))); assertFalse(Intersection3D_F64.contained(box,new Box3D_F64(10,3,4, 12,4.5,6.5))); assertFalse(Intersection3D_F64.contained(box,new Box3D_F64(2,10,4, 3,12,6.5))); assertFalse(Intersection3D_F64.contained(box,new Box3D_F64(2,3,10, 3,4.5,12))); // assume the 1D tests are sufficient. the above tests do check to see if each axis is handled // individually } @Test public void intersect_1d() { // identical assertTrue(Intersection3D_F64.intersect(0,0,1,1)); // bigger assertTrue(Intersection3D_F64.intersect(0,-1,1,2)); assertTrue(Intersection3D_F64.intersect(-1,0,2,1)); // shifted assertTrue(Intersection3D_F64.intersect(0,0.1,1,1.1)); assertTrue(Intersection3D_F64.intersect(0,-0.1,1,0.9)); assertTrue(Intersection3D_F64.intersect(0.1,0,1.1,1)); assertTrue(Intersection3D_F64.intersect(-0.1,0,0.9,1)); // graze assertFalse(Intersection3D_F64.intersect(0,1,1,2)); assertFalse(Intersection3D_F64.intersect(1,0,2,1)); // outside assertFalse(Intersection3D_F64.intersect(0,2,1,3)); } @Test public void intersect_line_sphere() { Point3D_F64 a = new Point3D_F64(); Point3D_F64 b = new Point3D_F64(); // test a negative case first assertFalse(Intersection3D_F64.intersect( new LineParametric3D_F64(0,0,-10,1,0,0),new Sphere3D_F64(0,0,0,2),a,b)); // Now a positive case assertTrue(Intersection3D_F64.intersect( new LineParametric3D_F64(0,0,2,1,0,0),new Sphere3D_F64(0,0,2,2),a,b)); assertTrue( a.distance(new Point3D_F64( 2,0,2)) <= GrlConstants.DOUBLE_TEST_TOL); assertTrue( b.distance(new Point3D_F64(-2,0,2)) <= GrlConstants.DOUBLE_TEST_TOL); } }