/*
* 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.UtilEllipse_F64;
import georegression.geometry.UtilLine2D_F64;
import georegression.misc.GrlConstants;
import georegression.struct.line.LineGeneral2D_F64;
import georegression.struct.line.LineParametric2D_F64;
import georegression.struct.line.LineSegment2D_F64;
import georegression.struct.point.Point2D_F64;
import georegression.struct.point.Point3D_F64;
import georegression.struct.se.Se2_F64;
import georegression.struct.shapes.*;
import georegression.transform.se.SePointOps_F64;
import org.junit.Test;
import java.util.Random;
import static org.junit.Assert.*;
/**
* @author Peter Abeles
*/
public class TestIntersection2D_F64 {
Random rand = new Random( 234 );
@Test
public void containConvex() {
Polygon2D_F64 poly = new Polygon2D_F64(4);
poly.vertexes.data[0].set(-1,-1);
poly.vertexes.data[1].set(1, -1);
poly.vertexes.data[2].set(1, 1);
poly.vertexes.data[3].set(-1, 1);
Point2D_F64 online = new Point2D_F64(1,-1);
Point2D_F64 inside = new Point2D_F64(0.5,0.5);
Point2D_F64 outside = new Point2D_F64(1.5,0.5);
assertFalse(Intersection2D_F64.containConvex(poly,online));
assertTrue(Intersection2D_F64.containConvex(poly,inside));
assertFalse(Intersection2D_F64.containConvex(poly,outside));
// change the order of the vertexes
poly.flip();
assertFalse(Intersection2D_F64.containConvex(poly,online));
assertTrue(Intersection2D_F64.containConvex(poly,inside));
assertFalse(Intersection2D_F64.containConvex(poly,outside));
}
@Test
public void containConcave_rectangle() {
Polygon2D_F64 poly = new Polygon2D_F64(4);
poly.vertexes.data[0].set(-1,-1);
poly.vertexes.data[1].set(1, -1);
poly.vertexes.data[2].set(1, 1);
poly.vertexes.data[3].set(-1, 1);
assertTrue(Intersection2D_F64.containConcave(poly, new Point2D_F64(0, 0)));
// perimeter cases intentionally not handled here
assertFalse(Intersection2D_F64.containConcave(poly, new Point2D_F64(2, 0)));
assertFalse(Intersection2D_F64.containConcave(poly, new Point2D_F64(-2, 0)));
assertFalse(Intersection2D_F64.containConcave(poly, new Point2D_F64(0, 2)));
assertFalse(Intersection2D_F64.containConcave(poly, new Point2D_F64(0, -2)));
}
@Test
public void contains_quadrilateral() {
Quadrilateral_F64 quad = new Quadrilateral_F64();
quad.a.set(-1, -1);
quad.b.set(1, -1);
quad.c.set(1, 1);
quad.d.set(-1, 1);
assertTrue(Intersection2D_F64.contains(quad, new Point2D_F64(0, 0)));
// perimeter cases intentionally not handled here
assertFalse(Intersection2D_F64.contains(quad, new Point2D_F64(2, 0)));
assertFalse(Intersection2D_F64.contains(quad, new Point2D_F64(-2, 0)));
assertFalse(Intersection2D_F64.contains(quad, new Point2D_F64(0, 2)));
assertFalse(Intersection2D_F64.contains(quad, new Point2D_F64(0, -2)));
}
@Test
public void containTriangle() {
Point2D_F64 a = new Point2D_F64(1,2);
Point2D_F64 b = new Point2D_F64(4,2);
Point2D_F64 c = new Point2D_F64(4,5);
Point2D_F64 inside = new Point2D_F64(3,3);
Point2D_F64 outside = new Point2D_F64(-10,2);
assertTrue(Intersection2D_F64.containTriangle(a, b, c, inside));
assertFalse(Intersection2D_F64.containTriangle(a, b, c, outside));
}
@Test
public void containEllipseRotated() {
EllipseRotated_F64 ellipse = new EllipseRotated_F64(5,6,4,3, GrlConstants.PId2);
assertFalse(Intersection2D_F64.contains(ellipse,0,0));
assertTrue(Intersection2D_F64.contains(ellipse,5,6));
assertTrue(Intersection2D_F64.contains(ellipse,5,6+4 - GrlConstants.DOUBLE_TEST_TOL));
assertTrue(Intersection2D_F64.contains(ellipse,5+3.0 - GrlConstants.DOUBLE_TEST_TOL,6));
assertFalse(Intersection2D_F64.contains(ellipse,5,6+4.0 + GrlConstants.DOUBLE_TEST_TOL));
assertFalse(Intersection2D_F64.contains(ellipse,5+3 + GrlConstants.DOUBLE_TEST_TOL,6));
}
@Test
public void containConcave_concave() {
Polygon2D_F64 poly = new Polygon2D_F64(5);
poly.vertexes.data[0].set(-1,-1);
poly.vertexes.data[1].set( 0, 0);
poly.vertexes.data[2].set(1, -1);
poly.vertexes.data[3].set(1, 1);
poly.vertexes.data[4].set(-1, 1);
assertTrue(Intersection2D_F64.containConcave(poly, new Point2D_F64(0,0.5)));
assertTrue(Intersection2D_F64.containConcave(poly, new Point2D_F64(-0.75,-0.25)));
assertTrue(Intersection2D_F64.containConcave(poly, new Point2D_F64(0.75,-0.25)));
assertFalse(Intersection2D_F64.containConcave(poly, new Point2D_F64(0,-0.5)));
assertFalse(Intersection2D_F64.containConcave(poly, new Point2D_F64(2,0)));
assertFalse(Intersection2D_F64.containConcave(poly, new Point2D_F64(-2,0)));
assertFalse(Intersection2D_F64.containConcave(poly, new Point2D_F64(0, 2)));
assertFalse(Intersection2D_F64.containConcave(poly, new Point2D_F64(0, -2)));
}
@Test
public void intersection_ls_to_ls() {
// check positive, none pathological cases
checkIntersection(new LineSegment2D_F64(0, 2, 2, 2), new LineSegment2D_F64(2, 0, 2, 3), new Point2D_F64(2, 2));
checkIntersection(new LineSegment2D_F64(0, 2, 2, 0), new LineSegment2D_F64(0, 0, 2, 2), new Point2D_F64(1, 1));
// check boundary conditions
checkIntersection(new LineSegment2D_F64(0, 2, 2, 2), new LineSegment2D_F64(0, 0, 0, 2), new Point2D_F64(0, 2));
checkIntersection(new LineSegment2D_F64(0, 2, 2, 2), new LineSegment2D_F64(2, 0, 2, 2), new Point2D_F64(2, 2));
checkIntersection(new LineSegment2D_F64(1, 0, 1, 2), new LineSegment2D_F64(0, 0, 2, 0), new Point2D_F64(1, 0));
// check negative
checkIntersection(new LineSegment2D_F64(0, 2, 2, 2), new LineSegment2D_F64(0, 0, 0, 1.9), null);
checkIntersection(new LineSegment2D_F64(0, 2, 2, 2), new LineSegment2D_F64(2, 0, 2, 1.9), null);
checkIntersection(new LineSegment2D_F64(1, 0.1, 1, 2), new LineSegment2D_F64(0, 0, 2, 0), null);
// check parallel closestPoint
checkIntersection(new LineSegment2D_F64(0, 2, 0, 5), new LineSegment2D_F64(0, 1, 0, 3), null);
}
public void checkIntersection( LineSegment2D_F64 a, LineSegment2D_F64 b, Point2D_F64 expected ) {
Point2D_F64 found = Intersection2D_F64.intersection( a, b, null );
if( found == null )
assertTrue( expected == null );
else {
assertEquals( found.getX(), expected.getX(), GrlConstants.DOUBLE_TEST_TOL );
assertEquals( found.getY(), expected.getY(), GrlConstants.DOUBLE_TEST_TOL );
}
}
/**
* Checks to see if the expected distance is returned and that the end points of the
* line segment are respected. The test cases are rotated around in a circle to test
* more geometric configurations
*/
@Test
public void intersection_p_to_ls() {
LineParametric2D_F64 paraLine = new LineParametric2D_F64();
LineSegment2D_F64 target = new LineSegment2D_F64( -1, 1, 1, 1 );
Se2_F64 tran = new Se2_F64();
// rotate it in a circle to check more geometric configurations
for( int i = 0; i < 20; i++ ) {
tran.setTranslation( rand.nextGaussian(), rand.nextGaussian() );
tran.setYaw( (double) ( 2 * Math.PI * i / 20 ) );
checkIntersection_p_to_ls( paraLine, target, tran );
}
// check parallel overlapping lines
paraLine.setPoint(-1,1);
paraLine.setSlope(2,0);
assertTrue( Double.isNaN( Intersection2D_F64.intersection(paraLine,target) ) );
}
private void checkIntersection_p_to_ls( LineParametric2D_F64 paraLine,
LineSegment2D_F64 target,
Se2_F64 tran ) {
// create a copy so the original isn't modified
paraLine = paraLine.copy();
target = target.copy();
// apply the transform to the two lines
paraLine.setPoint( SePointOps_F64.transform( tran, paraLine.getPoint(), null ) );
target.setA( SePointOps_F64.transform( tran, target.getA(), null ) );
target.setB( SePointOps_F64.transform( tran, target.getB(), null ) );
// should hit it dead center
paraLine.setSlope( 0, 1 );
paraLine.setAngle( paraLine.getAngle() + tran.getYaw() );
double dist = Intersection2D_F64.intersection( paraLine, target );
assertEquals( 1, dist, GrlConstants.DOUBLE_TEST_TOL );
// should hit dead center, but negative
paraLine.setSlope( 0, -1 );
paraLine.setAngle( paraLine.getAngle() + tran.getYaw() );
dist = Intersection2D_F64.intersection( paraLine, target );
assertEquals( -1, dist, GrlConstants.DOUBLE_TEST_TOL );
// should miss it to the left
paraLine.setSlope( -1.1, 1 );
paraLine.setAngle( paraLine.getAngle() + tran.getYaw() );
dist = Intersection2D_F64.intersection( paraLine, target );
assertTrue( Double.isNaN( dist ) );
// should miss it to the right
paraLine.setSlope( 1.1, 1 );
paraLine.setAngle( paraLine.getAngle() + tran.getYaw() );
dist = Intersection2D_F64.intersection( paraLine, target );
assertTrue( Double.isNaN( dist ) );
}
@Test
public void intersection_l_to_l_parametric_pt() {
LineParametric2D_F64 a = new LineParametric2D_F64(2,3,1,0);
LineParametric2D_F64 b = new LineParametric2D_F64(-2,-4,0,1);
Point2D_F64 found = Intersection2D_F64.intersection(a,b,null);
assertEquals( -2, found.x, GrlConstants.DOUBLE_TEST_TOL);
assertEquals(3, found.y, GrlConstants.DOUBLE_TEST_TOL);
LineParametric2D_F64 c = new LineParametric2D_F64(-8,2,0,1);
assertTrue(null == Intersection2D_F64.intersection(b,c,null));
}
@Test
public void intersection_l_to_l_parametric_t() {
LineParametric2D_F64 a = new LineParametric2D_F64(2,3,1,0);
LineParametric2D_F64 b = new LineParametric2D_F64(-2,-4,0,1);
double t = Intersection2D_F64.intersection(a,b);
Point2D_F64 found = new Point2D_F64(2+t,3);
assertEquals( -2, found.x, GrlConstants.DOUBLE_TEST_TOL);
assertEquals(3, found.y, GrlConstants.DOUBLE_TEST_TOL);
LineParametric2D_F64 c = new LineParametric2D_F64(-8,2,0,1);
assertTrue(Double.isNaN(Intersection2D_F64.intersection(b, c)));
}
@Test
public void intersection_l_to_l_general_3D() {
// check two arbitrary lines
LineGeneral2D_F64 a = new LineGeneral2D_F64(1,2,3);
LineGeneral2D_F64 b = new LineGeneral2D_F64(2,-1,0.5);
Point3D_F64 found = Intersection2D_F64.intersection(a,b,(Point3D_F64)null);
assertEquals(0,a.A*found.x/found.z+a.B*found.y/found.z+a.C, GrlConstants.DOUBLE_TEST_TOL);
assertEquals(0,a.A*found.x+a.B*found.y+a.C*found.z, GrlConstants.DOUBLE_TEST_TOL);
// give it two parallel lines
a = new LineGeneral2D_F64(1,2,3);
b = new LineGeneral2D_F64(1,2,0.5);
Intersection2D_F64.intersection(a, b, found);
assertEquals(0,found.z,GrlConstants.DOUBLE_TEST_TOL);
assertEquals(0, a.A * found.x + a.B * found.y + a.C * found.z, GrlConstants.DOUBLE_TEST_TOL);
}
@Test
public void intersection_l_to_l_general_2D() {
// check two arbitrary lines
LineGeneral2D_F64 a = new LineGeneral2D_F64(1,2,3);
LineGeneral2D_F64 b = new LineGeneral2D_F64(2,-1,0.5);
Point2D_F64 found = Intersection2D_F64.intersection(a,b,(Point2D_F64)null);
assertEquals(0,a.A*found.x+a.B*found.y+a.C, GrlConstants.DOUBLE_TEST_TOL);
// give it two parallel lines
a = new LineGeneral2D_F64(1,2,3);
b = new LineGeneral2D_F64(1,2,0.5);
assertTrue(null == Intersection2D_F64.intersection(a, b, found));
}
@Test
public void intersects_rect_corners() {
// check several positive cases
check( new Rectangle2D_F64(0,0,100,120),new Rectangle2D_F64(0,0,100,120),true);
check( new Rectangle2D_F64(0,0,100,120),new Rectangle2D_F64(10,12,99,119),true);
check( new Rectangle2D_F64(0,0,100,120),new Rectangle2D_F64(50,50,200,200),true);
check( new Rectangle2D_F64(0,0,100,120),new Rectangle2D_F64(-10,-10,10,10),true);
check( new Rectangle2D_F64(0,0,100,120),new Rectangle2D_F64(90,-10,105,1),true);
check( new Rectangle2D_F64(0,0,100,120),new Rectangle2D_F64(90,5,105,105),true);
// negative cases
check( new Rectangle2D_F64(0,0,100,120),new Rectangle2D_F64(200,200,300,305),false);
check( new Rectangle2D_F64(0,0,100,120),new Rectangle2D_F64(-200,-200,-10,-10),false);
check( new Rectangle2D_F64(0,0,100,120),new Rectangle2D_F64(0,-20,100,-5),false);
check( new Rectangle2D_F64(0,0,100,120),new Rectangle2D_F64(0,125,100,130),false);
// edge cases
check( new Rectangle2D_F64(0,0,100,120),new Rectangle2D_F64(0,0,0,0),false);
check( new Rectangle2D_F64(0,0,100,120),new Rectangle2D_F64(100,120,100,120),false);
check(new Rectangle2D_F64(0, 0, 100, 120), new Rectangle2D_F64(-10, 0, 0, 120), false);
check( new Rectangle2D_F64(0,0,100,120),new Rectangle2D_F64(100,0,105,120),false);
check( new Rectangle2D_F64(0,0,100,120),new Rectangle2D_F64(0,-10,100,0),false);
check(new Rectangle2D_F64(0, 0, 100, 120), new Rectangle2D_F64(0, 120, 100, 125), false);
}
private void check( Rectangle2D_F64 a , Rectangle2D_F64 b , boolean expected ) {
assertTrue(expected==Intersection2D_F64.intersects(a,b));
}
@Test
public void intersection_rect_corners() {
// check several positive cases
check( new Rectangle2D_F64(0,0,100,120),new Rectangle2D_F64(0,0,100,120),
new Rectangle2D_F64(0,0,100,120));
check( new Rectangle2D_F64(0,0,100,120),new Rectangle2D_F64(10,12,99,119),
new Rectangle2D_F64(10,12,99,119));
check( new Rectangle2D_F64(0,0,100,120),new Rectangle2D_F64(50,50,200,200),
new Rectangle2D_F64(50,50,100,120));
check( new Rectangle2D_F64(0,0,100,120),new Rectangle2D_F64(-10,-10,10,10),
new Rectangle2D_F64(0,0,10,10));
check( new Rectangle2D_F64(0,0,100,120),new Rectangle2D_F64(90,-10,105,1),
new Rectangle2D_F64(90,0,100,1));
check( new Rectangle2D_F64(0,0,100,120),new Rectangle2D_F64(90,5,105,105),
new Rectangle2D_F64(90,5,100,105));
// negative cases
check( new Rectangle2D_F64(0,0,100,120),new Rectangle2D_F64(200,200,300,305),null);
check( new Rectangle2D_F64(0,0,100,120),new Rectangle2D_F64(-200,-200,-10,-10),null);
check( new Rectangle2D_F64(0,0,100,120),new Rectangle2D_F64(0,-20,100,-5),null);
check( new Rectangle2D_F64(0,0,100,120),new Rectangle2D_F64(0,125,100,130),null);
// edge cases
check( new Rectangle2D_F64(0,0,100,120),new Rectangle2D_F64(0,0,0,0),null);
check( new Rectangle2D_F64(0,0,100,120),new Rectangle2D_F64(100,120,100,120),null);
check( new Rectangle2D_F64(0,0,100,120),new Rectangle2D_F64(-10,0,0,120),null);
check( new Rectangle2D_F64(0,0,100,120),new Rectangle2D_F64(100,0,105,120),null);
check( new Rectangle2D_F64(0,0,100,120),new Rectangle2D_F64(0,-10,100,0),null);
check( new Rectangle2D_F64(0,0,100,120),new Rectangle2D_F64(0,120,100,125),null);
}
private void check( Rectangle2D_F64 a , Rectangle2D_F64 b , Rectangle2D_F64 expected ) {
if( expected == null ) {
assertFalse(Intersection2D_F64.intersection(a, b, null));
return;
}
Rectangle2D_F64 found = new Rectangle2D_F64();
assertTrue(Intersection2D_F64.intersection(a, b, found));
assertEquals(expected.p0.x,found.p0.x,GrlConstants.DOUBLE_TEST_TOL);
assertEquals(expected.p1.x,found.p1.x,GrlConstants.DOUBLE_TEST_TOL);
assertEquals(expected.p0.y,found.p0.y,GrlConstants.DOUBLE_TEST_TOL);
assertEquals(expected.p1.y,found.p1.y,GrlConstants.DOUBLE_TEST_TOL);
}
@Test
public void contains_rectLength_pt() {
RectangleLength2D_F64 rect = new RectangleLength2D_F64(-10,-5,5,10);
assertTrue(Intersection2D_F64.contains(rect,-10,-5));
assertTrue(Intersection2D_F64.contains(rect,-6,4));
assertTrue(Intersection2D_F64.contains(rect,-9.9,-4.99));
assertTrue(Intersection2D_F64.contains(rect,-6.001,4.99));
assertTrue(Intersection2D_F64.contains(rect,-5.99,4));
assertTrue(Intersection2D_F64.contains(rect, -10, 4.001));
assertFalse(Intersection2D_F64.contains(rect, -11, -5));
assertFalse(Intersection2D_F64.contains(rect, -10, -6));
assertFalse(Intersection2D_F64.contains(rect, -5, 4));
assertFalse(Intersection2D_F64.contains(rect, -6, 5));
}
@Test
public void contains2_rectLength_pt() {
RectangleLength2D_F64 rect = new RectangleLength2D_F64(-10,-5,5,10);
assertTrue(Intersection2D_F64.contains2(rect, -10, -5));
assertTrue(Intersection2D_F64.contains2(rect, -6, 4));
assertTrue(Intersection2D_F64.contains2(rect, -9.9, -4.99));
assertTrue(Intersection2D_F64.contains2(rect, -6.001, 4.99));
assertTrue(Intersection2D_F64.contains2(rect, -5.99, 4));
assertTrue(Intersection2D_F64.contains2(rect, -10, 4.001));
assertFalse(Intersection2D_F64.contains2(rect, -11, -5));
assertFalse(Intersection2D_F64.contains2(rect, -10, -6));
assertTrue(Intersection2D_F64.contains2(rect, -5, 4));
assertTrue(Intersection2D_F64.contains2(rect, -6, 5));
}
@Test
public void contains_rect_pt() {
Rectangle2D_F64 rect = new Rectangle2D_F64(-10,-5,-5,5);
assertTrue(Intersection2D_F64.contains(rect, -10, -5));
assertTrue(Intersection2D_F64.contains(rect, -6, 4));
assertTrue(Intersection2D_F64.contains(rect, -9.9, -4.99));
assertTrue(Intersection2D_F64.contains(rect, -6.001, 4.99));
assertTrue(Intersection2D_F64.contains(rect, -5.99, 4));
assertTrue(Intersection2D_F64.contains(rect, -10, 4.001));
assertFalse(Intersection2D_F64.contains(rect, -11, -5));
assertFalse(Intersection2D_F64.contains(rect, -10, -6));
assertFalse(Intersection2D_F64.contains(rect, -5, 4));
assertFalse(Intersection2D_F64.contains(rect, -6, 5));
}
@Test
public void contains2_rect_pt() {
Rectangle2D_F64 rect = new Rectangle2D_F64(-10,-5,-5,5);
assertTrue(Intersection2D_F64.contains2(rect, -10, -5));
assertTrue(Intersection2D_F64.contains2(rect, -6, 4));
assertTrue(Intersection2D_F64.contains2(rect, -9.9, -4.99));
assertTrue(Intersection2D_F64.contains2(rect, -6.001, 4.99));
assertTrue(Intersection2D_F64.contains2(rect, -5.99, 4));
assertTrue(Intersection2D_F64.contains2(rect, -10, 4.001));
assertFalse(Intersection2D_F64.contains2(rect, -11, -5));
assertFalse(Intersection2D_F64.contains2(rect, -10, -6));
assertTrue(Intersection2D_F64.contains2(rect, -5, 4));
assertTrue(Intersection2D_F64.contains2(rect, -6, 5));
}
@Test
public void intersectionArea_rect_rect() {
// check several positive cases
check( new Rectangle2D_F64(0,0,100,120),new Rectangle2D_F64(0,0,100,120), 100*120);
check( new Rectangle2D_F64(0,0,100,120),new Rectangle2D_F64(10,12,99,119), 89*107);
check( new Rectangle2D_F64(0,0,100,120),new Rectangle2D_F64(50,50,200,200), 50*70 );
check( new Rectangle2D_F64(0,0,100,120),new Rectangle2D_F64(-10,-10,10,10), 10*10 );
check( new Rectangle2D_F64(0,0,100,120),new Rectangle2D_F64(90,-10,105,1), 10*1 );
check( new Rectangle2D_F64(0,0,100,120),new Rectangle2D_F64(90,5,105,105), 10*100 );
// negative cases
check(new Rectangle2D_F64(0, 0, 100, 120), new Rectangle2D_F64(200, 200, 300, 305), 0);
check(new Rectangle2D_F64(0, 0, 100, 120), new Rectangle2D_F64(-200, -200, -10, -10), 0);
check(new Rectangle2D_F64(0, 0, 100, 120), new Rectangle2D_F64(0, -20, 100, -5), 0);
check(new Rectangle2D_F64(0, 0, 100, 120), new Rectangle2D_F64(0, 125, 100, 130), 0);
// edge cases
check(new Rectangle2D_F64(0, 0, 100, 120), new Rectangle2D_F64(0, 0, 0, 0), 0);
check(new Rectangle2D_F64(0, 0, 100, 120), new Rectangle2D_F64(100, 120, 100, 120), 0);
check(new Rectangle2D_F64(0, 0, 100, 120), new Rectangle2D_F64(-10, 0, 0, 120), 0);
check(new Rectangle2D_F64(0, 0, 100, 120), new Rectangle2D_F64(100, 0, 105, 120), 0);
check(new Rectangle2D_F64(0, 0, 100, 120), new Rectangle2D_F64(0, -10, 100, 0), 0);
check(new Rectangle2D_F64(0, 0, 100, 120), new Rectangle2D_F64(0, 120, 100, 125), 0);
}
private void check( Rectangle2D_F64 a , Rectangle2D_F64 b , double expected ) {
assertEquals(expected,Intersection2D_F64.intersectionArea(a,b),GrlConstants.DOUBLE_TEST_TOL);
}
@Test
public void line_ellipse() {
// easy cases where the ellipse is at the original aligned to the coordinate axis
EllipseRotated_F64 ellipse = new EllipseRotated_F64(0,0,2,1,0);
checkIntersection(new LineGeneral2D_F64(1,0,0),ellipse); // vertical line
checkIntersection(new LineGeneral2D_F64(0,1,0),ellipse); // horizontal line
checkIntersection(new LineGeneral2D_F64(0.25,2.0,1),ellipse); // angled line
checkIntersection(new LineGeneral2D_F64(2.0,0.25,1),ellipse); // angled line
checkSingleIntersection(new LineGeneral2D_F64(1,0,-2),ellipse); // single point
checkSingleIntersection(new LineGeneral2D_F64(0,1,-1),ellipse); // single point
checkNoIntersection(new LineGeneral2D_F64(1,0,20),ellipse);// no intersection
// Test to see if the rotation is handled correctly. Still centered at the original but rotated 90 degrees
ellipse = new EllipseRotated_F64(0,0,2,1, GrlConstants.PId2);
checkIntersection(new LineGeneral2D_F64(1,0,0),ellipse); // vertical line
checkIntersection(new LineGeneral2D_F64(0,1,0),ellipse); // horizontal line
checkIntersection(new LineGeneral2D_F64(0.25,2.0,1),ellipse); // angled line
checkIntersection(new LineGeneral2D_F64(2.0,0.25,1),ellipse); // angled line
checkSingleIntersection(new LineGeneral2D_F64(1,0,-1),ellipse); // single point
checkSingleIntersection(new LineGeneral2D_F64(0,1,-2),ellipse); // single point
checkNoIntersection(new LineGeneral2D_F64(1,0,20),ellipse);// no intersection
// Offset it from the original
ellipse = new EllipseRotated_F64(0.1,0,2,1,0);
checkIntersection(new LineGeneral2D_F64(1,0,0),ellipse); // vertical line
checkIntersection(new LineGeneral2D_F64(0,1,0),ellipse); // horizontal line
// Hardest case. not at origin and rotated an arbitrary amount
ellipse = new EllipseRotated_F64(0.12,-0.13,2,1,0.4);
checkIntersection(new LineGeneral2D_F64(1,0,0),ellipse); // vertical line
checkIntersection(new LineGeneral2D_F64(0,1,0),ellipse); // horizontal line
checkIntersection(new LineGeneral2D_F64(0.25,2.0,1),ellipse); // angled line
checkIntersection(new LineGeneral2D_F64(2.0,0.25,1),ellipse); // angled line
checkIntersection(new LineGeneral2D_F64(1,0,-2),ellipse); // single point
checkIntersection(new LineGeneral2D_F64(0,1,-1),ellipse); // single point
checkNoIntersection(new LineGeneral2D_F64(1,0,20),ellipse);// no intersection
}
private void checkNoIntersection( LineGeneral2D_F64 line , EllipseRotated_F64 ellipse ) {
Point2D_F64 a = new Point2D_F64();
Point2D_F64 b = new Point2D_F64();
assertEquals(0,Intersection2D_F64.intersection(line,ellipse,a,b,-1));
}
private void checkIntersection( LineGeneral2D_F64 line , EllipseRotated_F64 ellipse ) {
Point2D_F64 a = new Point2D_F64();
Point2D_F64 b = new Point2D_F64();
assertEquals(2,Intersection2D_F64.intersection(line,ellipse,a,b, -1));
// use the line and ellipse definition to check solution
assertEquals(0, line.evaluate(a.x, a.y), GrlConstants.DOUBLE_TEST_TOL);
assertEquals(0, line.evaluate(b.x, b.y), GrlConstants.DOUBLE_TEST_TOL);
assertEquals(1.0, UtilEllipse_F64.evaluate(a.x, a.y, ellipse), GrlConstants.DOUBLE_TEST_TOL);
assertEquals(1.0, UtilEllipse_F64.evaluate(b.x, b.y, ellipse), GrlConstants.DOUBLE_TEST_TOL);
}
private void checkSingleIntersection( LineGeneral2D_F64 line , EllipseRotated_F64 ellipse ) {
Point2D_F64 a = new Point2D_F64();
Point2D_F64 b = new Point2D_F64();
assertEquals(1,Intersection2D_F64.intersection(line,ellipse,a,b, -1));
assertEquals(0, a.distance(b), GrlConstants.DOUBLE_TEST_TOL);
// use the line and ellipse definition to check solution
assertEquals(0, line.evaluate(a.x, a.y), GrlConstants.DOUBLE_TEST_TOL);
assertEquals(1.0, UtilEllipse_F64.evaluate(a.x, a.y, ellipse), GrlConstants.DOUBLE_TEST_TOL);
}
}