/* * Copyright (C) 2011-2015, 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.geometry.algs; import georegression.geometry.UtilPolygons2D_F64; import georegression.metric.Intersection2D_F64; import georegression.misc.GrlConstants; import georegression.struct.point.Point2D_F64; import georegression.struct.shapes.Polygon2D_F64; import org.junit.Test; import java.util.Random; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; /** * @author Peter Abeles */ public class TestAndrewMonotoneConvexHull_F64 { Random rand = new Random(2355); @Test public void triangle() { // all points are in hull Point2D_F64 []input = new Point2D_F64[3]; input[0] = new Point2D_F64(2,3); input[1] = new Point2D_F64(7,8); input[2] = new Point2D_F64(8,3); Polygon2D_F64 output = new Polygon2D_F64(); AndrewMonotoneConvexHull_F64 alg = new AndrewMonotoneConvexHull_F64(); alg.process(input,input.length,output); containsOnceEach(input,output); // add a point inside Point2D_F64 []input2 = new Point2D_F64[4]; System.arraycopy(input,0,input2,0,3); input2[3] = new Point2D_F64(4,4); alg.process(input2,input.length,output); containsOnceEach(input,output); } @Test public void rectangle() { // all points are in hull Point2D_F64 []input = new Point2D_F64[4]; input[0] = new Point2D_F64(2,3); input[1] = new Point2D_F64(2,8); input[2] = new Point2D_F64(7,8); input[3] = new Point2D_F64(7,3); Polygon2D_F64 output = new Polygon2D_F64(); AndrewMonotoneConvexHull_F64 alg = new AndrewMonotoneConvexHull_F64(); alg.process(input,input.length,output); containsOnceEach(input,output); // add a point inside Point2D_F64 []input2 = new Point2D_F64[5]; System.arraycopy(input,0,input2,0,4); input2[4] = new Point2D_F64(4,4); alg.process(input2,input.length,output); containsOnceEach(input,output); } @Test public void pentagon() { // all points are in hull Point2D_F64 []input = new Point2D_F64[4]; input[0] = new Point2D_F64(2,3); input[1] = new Point2D_F64(2,8); input[2] = new Point2D_F64(7,8); input[3] = new Point2D_F64(7,3); input[3] = new Point2D_F64(4,10); Polygon2D_F64 output = new Polygon2D_F64(); AndrewMonotoneConvexHull_F64 alg = new AndrewMonotoneConvexHull_F64(); alg.process(input,input.length,output); containsOnceEach(input,output); // add a point inside Point2D_F64 []input2 = new Point2D_F64[6]; System.arraycopy(input,0,input2,0,input.length); input2[5] = new Point2D_F64(4,4); alg.process(input2,input.length,output); containsOnceEach(input,output); } @Test public void randomPoints() { AndrewMonotoneConvexHull_F64 alg = new AndrewMonotoneConvexHull_F64(); Polygon2D_F64 output = new Polygon2D_F64(); for (int numPoints = 10; numPoints < 20; numPoints++) { Point2D_F64 data[] = new Point2D_F64[numPoints]; for (int i = 0; i < numPoints; i++) { double x = rand.nextGaussian()*5; double y = rand.nextGaussian()*5; data[i] = new Point2D_F64(x,y); } alg.process(data,numPoints,output); // check some of the properties of the convex hull assertTrue(output.size() <= numPoints); assertTrue(output.isCCW()); assertTrue(output.isConvex()); for (int i = 0; i < numPoints; i++) { Intersection2D_F64.containConvex(output,data[i]); } } } @Test public void grid() { AndrewMonotoneConvexHull_F64 alg = new AndrewMonotoneConvexHull_F64(); Polygon2D_F64 output = new Polygon2D_F64(); int numRows = 5; int numCols = 6; double w = 1.2; Point2D_F64 points[] = new Point2D_F64[numRows*numCols]; for (int row = 0; row < numRows; row++) { double y = row*w - 2.1; for (int col = 0; col < numCols; col++) { double x = col*w - 2.6; points[ row*numCols + col ] = new Point2D_F64(x,y); } } alg.process(points,points.length,output); // check some of the properties of the convex hull assertTrue(output.size() <= points.length); assertTrue(output.isCCW()); assertTrue(output.isConvex()); for (int i = 0; i < points.length; i++) { Intersection2D_F64.containConvex(output,points[i]); } } private void containsOnceEach( Point2D_F64[] expected , Polygon2D_F64 output ) { assertTrue(UtilPolygons2D_F64.isConvex(output)); int count[] = new int[expected.length]; assertEquals(expected.length,output.size()); for (int i = 0; i < expected.length; i++) { for (int j = 0; j < output.size(); j++) { if( expected[i].distance2(output.get(j)) <= GrlConstants.DOUBLE_TEST_TOL ) { count[i]++; } } } for (int i = 0; i < count.length; i++) { assertEquals(1, count[i]); } } }