/******************************************************************************* * Copyright (c) 2010, 2016 IBM Corporation and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Alexander Nyßen (Research Group Software Construction, RWTH Aachen University) - contribution for Bugzilla 245182 * Matthias Wienand (itemis AG) - contribution for Bugzilla #355997 * *******************************************************************************/ package org.eclipse.gef.geometry.tests; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import org.eclipse.gef.geometry.euclidean.Vector; import org.eclipse.gef.geometry.internal.utils.PrecisionUtils; import org.eclipse.gef.geometry.planar.Line; import org.eclipse.gef.geometry.planar.Point; import org.eclipse.gef.geometry.planar.Rectangle; import org.junit.Test; /** * Unit tests for {@link Line}. * * @author anyssen * @author mwienand * */ public class LineTests { private static final double PRECISION_FRACTION = TestUtils .getPrecisionFraction(); private static final double RECOGNIZABLE_FRACTION = PRECISION_FRACTION + PRECISION_FRACTION / 10; private static final double UNRECOGNIZABLE_FRACTION = PRECISION_FRACTION - PRECISION_FRACTION / 10; @Test public void test_constructors() { Line l1 = new Line(0, 0, 5, 0); assertTrue(l1.equals(new Line(new Point(), new Point(5, 0)))); } @Test public void test_contains_Point() { Line l1 = new Line(0, 0, 5, 0); assertTrue(l1.contains(l1.getP1())); assertTrue(l1.contains(l1.getP2())); for (double x = -5; x <= 10; x += 0.1) { assertTrue(l1.contains( new Point(x, 0)) == (PrecisionUtils.smallerEqual(0, x) && PrecisionUtils.smallerEqual(x, 5))); } l1 = new Line(0, 0, 0, 0); assertTrue(l1.contains(l1.getP1())); assertTrue(l1.contains(l1.getP2())); assertFalse(l1.contains(new Point(1, 1))); } @Test public void test_copy() { Line l1 = new Line(0, 0, 5, 0); assertTrue(l1.equals(l1.getCopy())); assertTrue(l1.equals(l1.clone())); assertTrue(l1.getCopy().equals(l1.clone())); } @Test public void test_equals() { Line l1 = new Line(0, 0, 5, 0); assertTrue(l1.equals(l1)); assertTrue(l1.equals(new Line(0.0, 0.0, 5.0, 0.0))); assertTrue(l1.equals(new Line(5.0, 0.0, 0.0, 0.0))); assertFalse(l1.equals(new Line(0.1, 0.0, 5.0, 0.0))); assertFalse(l1.equals(new Line(0.0, 0.1, 5.0, 0.0))); assertFalse(l1.equals(new Line(0.0, 0.0, 5.1, 0.0))); assertFalse(l1.equals(new Line(0.0, 0.0, 5.0, 0.1))); assertFalse(l1.equals(new Point())); assertFalse(l1.equals(null)); assertTrue(l1.equals(new Line(UNRECOGNIZABLE_FRACTION, UNRECOGNIZABLE_FRACTION, 5.0 + UNRECOGNIZABLE_FRACTION, UNRECOGNIZABLE_FRACTION))); assertTrue(l1.equals(new Line(-UNRECOGNIZABLE_FRACTION, -UNRECOGNIZABLE_FRACTION, 5.0 - UNRECOGNIZABLE_FRACTION, -UNRECOGNIZABLE_FRACTION))); assertFalse( l1.equals(new Line(RECOGNIZABLE_FRACTION, RECOGNIZABLE_FRACTION, 5.0 + RECOGNIZABLE_FRACTION, RECOGNIZABLE_FRACTION))); assertFalse(l1 .equals(new Line(-RECOGNIZABLE_FRACTION, -RECOGNIZABLE_FRACTION, 5.0 - RECOGNIZABLE_FRACTION, -RECOGNIZABLE_FRACTION))); } @Test public void test_get() { Line l1 = new Line(100, 100, 200, 200); assertEquals(new Point(100, 100), l1.get(0)); assertEquals(new Point(125, 125), l1.get(0.25)); assertEquals(new Point(150, 150), l1.get(0.5)); assertEquals(new Point(175, 175), l1.get(0.75)); assertEquals(new Point(200, 200), l1.get(1)); Line l2 = new Line(200, 200, 100, 100); assertEquals(new Point(200, 200), l2.get(0)); assertEquals(new Point(175, 175), l2.get(0.25)); assertEquals(new Point(150, 150), l2.get(0.5)); assertEquals(new Point(125, 125), l2.get(0.75)); assertEquals(new Point(100, 100), l2.get(1)); } @Test public void test_getBounds() { Line l1 = new Line(0, 0, 5, 0); Rectangle bounds = l1.getBounds(); assertTrue(bounds.getLeft().equals(l1.getP1())); assertTrue(bounds.getRight().equals(l1.getP2())); assertTrue(bounds.getTopLeft().equals(l1.getP1())); assertTrue(bounds.getBottomLeft().equals(l1.getP1())); assertTrue(bounds.getTopRight().equals(l1.getP2())); assertTrue(bounds.getBottomRight().equals(l1.getP2())); l1 = new Line(-5, -5, 5, 5); bounds = l1.getBounds(); assertTrue(bounds.getTopLeft().equals(l1.getP1())); assertTrue(bounds.getBottomRight().equals(l1.getP2())); l1 = new Line(-5, 5, 5, -5); bounds = l1.getBounds(); assertTrue(bounds.getBottomLeft().equals(l1.getP1())); assertTrue(bounds.getTopRight().equals(l1.getP2())); } @Test public void test_getDirectionCCW() { // build lines by stepping 45deg in CCW order around the origin Line line = new Line(0, 0, 10, 0); assertTrue(PrecisionUtils.equal(0, line.getDirectionCCW().deg())); line = new Line(0, 0, 10, 10); assertTrue(PrecisionUtils.equal(45, line.getDirectionCCW().deg())); line = new Line(0, 0, 0, 10); assertTrue(PrecisionUtils.equal(90, line.getDirectionCCW().deg())); line = new Line(0, 0, -10, 10); assertTrue(PrecisionUtils.equal(135, line.getDirectionCCW().deg())); line = new Line(0, 0, -10, 0); assertTrue(PrecisionUtils.equal(180, line.getDirectionCCW().deg())); line = new Line(0, 0, -10, -10); assertTrue(PrecisionUtils.equal(225, line.getDirectionCCW().deg())); line = new Line(0, 0, 0, -10); assertTrue(PrecisionUtils.equal(270, line.getDirectionCCW().deg())); line = new Line(0, 0, 10, -10); assertTrue(PrecisionUtils.equal(315, line.getDirectionCCW().deg())); } @Test public void test_getDirectionCW() { // build lines by stepping 45deg in CW order around the origin Line line = new Line(0, 0, 10, 0); assertTrue(PrecisionUtils.equal(0, line.getDirectionCW().deg())); line = new Line(0, 0, 10, -10); assertTrue(PrecisionUtils.equal(45, line.getDirectionCW().deg())); line = new Line(0, 0, 0, -10); assertTrue(PrecisionUtils.equal(90, line.getDirectionCW().deg())); line = new Line(0, 0, -10, -10); assertTrue(PrecisionUtils.equal(135, line.getDirectionCW().deg())); line = new Line(0, 0, -10, 0); assertTrue(PrecisionUtils.equal(180, line.getDirectionCW().deg())); line = new Line(0, 0, -10, 10); assertTrue(PrecisionUtils.equal(225, line.getDirectionCW().deg())); line = new Line(0, 0, 0, 10); assertTrue(PrecisionUtils.equal(270, line.getDirectionCW().deg())); line = new Line(0, 0, 10, 10); assertTrue(PrecisionUtils.equal(315, line.getDirectionCW().deg())); } @Test public void test_getIntersection_specials() { // degenerated cases Line degen = new Line(new Point(), new Point()); Line normal = new Line(new Point(-5, 0), new Point(5, 0)); assertEquals(new Point(), degen.getIntersection(normal)); assertEquals(new Point(), normal.getIntersection(degen)); // identical assertNull(normal.getIntersection(normal)); // intersection within precision, no real intersection Line close = new Line(new Point(-5, UNRECOGNIZABLE_FRACTION), new Point(5, UNRECOGNIZABLE_FRACTION)); // parallel so we do not return an intersection point assertNull(normal.getIntersection(close)); assertNull(close.getIntersection(normal)); // non parallel, start point intersection Line closeSp = new Line(new Point(-5, UNRECOGNIZABLE_FRACTION), new Point(-5, 10)); assertEquals(new Point(-5, 0), normal.getIntersection(closeSp)); assertEquals(new Point(-5, 0), closeSp.getIntersection(normal)); // non parallel, end point intersection Line closeEp = new Line(new Point(-5, 10), new Point(-5, UNRECOGNIZABLE_FRACTION)); assertEquals(new Point(-5, 0), normal.getIntersection(closeEp)); assertEquals(new Point(-5, 0), closeEp.getIntersection(normal)); // intersection within precision, straights do intersect too, but the // intersection of the straights is out of precision Line slope = new Line(new Point(-5, UNRECOGNIZABLE_FRACTION), new Point(5, 2 * UNRECOGNIZABLE_FRACTION)); // no point of intersection can be identified, because both endpoints // lie on the line. is is assumed to be parallel. assertNull(normal.getIntersection(slope)); assertNull(slope.getIntersection(normal)); // no intersection, straights do intersect Line elsewhere = new Line(new Point(-5, 1), new Point(5, 10)); assertNull(normal.getIntersection(elsewhere)); assertNull(elsewhere.getIntersection(normal)); // single end point intersection with parallel lines: // X-------X-------X Line l1 = new Line(400.0, 102.48618784530387, 399.99999999999994, 100.0); Line l2 = new Line(400.0, 51.10497237569061, 399.99999999999994, 100.0); assertNotNull(l1.getIntersection(l2)); } @Test public void test_getIntersection_with_Line() { // simple intersection Line l1 = new Line(0, 0, 4, 4); Line l2 = new Line(0, 4, 4, 0); assertTrue(l1.touches(l2)); assertTrue(l1.getIntersection(l2).equals(new Point(2, 2))); assertTrue(l2.getIntersection(l1).equals(new Point(2, 2))); // lines touch in one point Line l3 = new Line(4, 4, 7, 9); assertTrue(l1.getIntersection(l3).equals(new Point(4, 4))); assertTrue(l3.getIntersection(l1).equals(new Point(4, 4))); // lines overlap Line l4 = new Line(2, 2, 6, 6); assertTrue(l1.getIntersection(l4) == null); assertTrue(l4.getIntersection(l1) == null); // lines overlap in one end point Line l5 = new Line(4, 4, 6, 6); assertTrue(l1.getIntersection(l5).equals(new Point(4, 4))); assertTrue(l5.getIntersection(l1).equals(new Point(4, 4))); l5 = new Line(6, 6, 4, 4); assertTrue(l1.getIntersection(l5).equals(new Point(4, 4))); assertTrue(l5.getIntersection(l1).equals(new Point(4, 4))); Line l6 = new Line(-1, -1, 0, 0); assertTrue(l1.getIntersection(l6).equals(new Point())); assertTrue(l6.getIntersection(l1).equals(new Point())); l6 = new Line(0, 0, -1, -1); assertTrue(l1.getIntersection(l6).equals(new Point())); assertTrue(l6.getIntersection(l1).equals(new Point())); // lines do not intersect Line l7 = new Line(4, 0, 5, 4); assertNull(l1.getIntersection(l7)); assertNull(l7.getIntersection(l1)); } @Test public void test_getProjection() { Line x100 = new Line(0, 0, 100, 0); // check start point assertEquals(new Point(0, 0), x100.getProjection(new Point(-10, 0))); assertEquals(new Point(0, 0), x100.getProjection(new Point(-10, 10))); assertEquals(new Point(0, 0), x100.getProjection(new Point(-10, -10))); // check end point assertEquals(new Point(100, 0), x100.getProjection(new Point(110, 0))); assertEquals(new Point(100, 0), x100.getProjection(new Point(110, -10))); assertEquals(new Point(100, 0), x100.getProjection(new Point(110, 10))); // check middle assertEquals(new Point(50, 0), x100.getProjection(new Point(50, 0))); assertEquals(new Point(50, 0), x100.getProjection(new Point(50, 10))); assertEquals(new Point(50, 0), x100.getProjection(new Point(50, -10))); // 25 assertEquals(new Point(25, 0), x100.getProjection(new Point(25, 0))); assertEquals(new Point(25, 0), x100.getProjection(new Point(25, 10))); assertEquals(new Point(25, 0), x100.getProjection(new Point(25, -10))); // 75 assertEquals(new Point(75, 0), x100.getProjection(new Point(75, 0))); assertEquals(new Point(75, 0), x100.getProjection(new Point(75, 10))); assertEquals(new Point(75, 0), x100.getProjection(new Point(75, -10))); Line y100 = new Line(0, 0, 0, 100); // check start point assertEquals(new Point(0, 0), y100.getProjection(new Point(0, -10))); assertEquals(new Point(0, 0), y100.getProjection(new Point(10, -10))); assertEquals(new Point(0, 0), y100.getProjection(new Point(-10, -10))); // check end point assertEquals(new Point(0, 100), y100.getProjection(new Point(0, 110))); assertEquals(new Point(0, 100), y100.getProjection(new Point(-10, 110))); assertEquals(new Point(0, 100), y100.getProjection(new Point(10, 110))); // check middle assertEquals(new Point(0, 50), y100.getProjection(new Point(0, 50))); assertEquals(new Point(0, 50), y100.getProjection(new Point(10, 50))); assertEquals(new Point(0, 50), y100.getProjection(new Point(-10, 50))); // 25 assertEquals(new Point(0, 25), y100.getProjection(new Point(0, 25))); assertEquals(new Point(0, 25), y100.getProjection(new Point(10, 25))); assertEquals(new Point(0, 25), y100.getProjection(new Point(-10, 25))); // 75 assertEquals(new Point(0, 75), y100.getProjection(new Point(0, 75))); assertEquals(new Point(0, 75), y100.getProjection(new Point(10, 75))); assertEquals(new Point(0, 75), y100.getProjection(new Point(-10, 75))); } @Test public void test_getters() { for (double x1 = -2; x1 <= 2; x1 += 0.5) { for (double y1 = -2; y1 <= 2; y1 += 0.5) { Point p1 = new Point(x1, y1); for (double x2 = -2; x2 <= 2; x2 += 0.5) { for (double y2 = -2; y2 <= 2; y2 += 0.5) { Point p2 = new Point(x2, y2); Line line = new Line(p1, p2); assertTrue(line.getP1().equals(p1)); assertTrue(line.getP2().equals(p2)); assertTrue(PrecisionUtils.equal(line.getX1(), p1.x)); assertTrue(PrecisionUtils.equal(line.getX2(), p2.x)); assertTrue(PrecisionUtils.equal(line.getY1(), p1.y)); assertTrue(PrecisionUtils.equal(line.getY2(), p2.y)); Point[] points = line.getPoints(); assertTrue(points[0].equals(p1)); assertTrue(points[1].equals(p2)); } } } } } @Test public void test_hashCode() { // hashCode() has to be the same for two equal()ly lines // (I think this is impossible with the current PrecisionUtils.) Line l1 = new Line(0, 0, 5, 0); assertEquals(l1.hashCode(), l1.hashCode()); assertEquals(l1.hashCode(), new Line(0.0, 0.0, 5.0, 0.0).hashCode()); assertTrue(l1.hashCode() == new Line(UNRECOGNIZABLE_FRACTION, UNRECOGNIZABLE_FRACTION, 5.0 + UNRECOGNIZABLE_FRACTION, UNRECOGNIZABLE_FRACTION).hashCode()); assertTrue(l1.hashCode() == new Line(-UNRECOGNIZABLE_FRACTION, -UNRECOGNIZABLE_FRACTION, 5.0 - UNRECOGNIZABLE_FRACTION, -UNRECOGNIZABLE_FRACTION).hashCode()); } @Test public void test_intersects_specials() { // degenerated cases Line degen = new Line(new Point(), new Point()); Line normal = new Line(new Point(-5, 0), new Point(5, 0)); assertTrue(degen.touches(normal)); assertTrue(normal.touches(degen)); // identical assertTrue(normal.touches(normal)); // intersection within precision. no real intersection Line close = new Line(new Point(-5, UNRECOGNIZABLE_FRACTION), new Point(5, UNRECOGNIZABLE_FRACTION)); assertTrue(normal.touches(close)); assertTrue(close.touches(normal)); Line closeSp = new Line(new Point(-5, UNRECOGNIZABLE_FRACTION), new Point(-5, 10)); assertTrue(normal.touches(closeSp)); assertTrue(closeSp.touches(normal)); Line closeEp = new Line(new Point(-5, 10), new Point(-5, UNRECOGNIZABLE_FRACTION)); assertTrue(normal.touches(closeEp)); assertTrue(closeEp.touches(normal)); // intersection within precision, straights do intersect too, but the // intersection of the straights is out of precision Line slope = new Line(new Point(-5, UNRECOGNIZABLE_FRACTION), new Point(5, 2 * UNRECOGNIZABLE_FRACTION)); assertTrue(normal.touches(slope)); assertTrue(slope.touches(normal)); // no intersection, straights do intersect Line elsewhere = new Line(new Point(-5, 1), new Point(5, 10)); assertTrue(!normal.touches(elsewhere)); assertTrue(!elsewhere.touches(normal)); // big lines, imprecisely parallel but intersecting Line bigX = new Line(new Point(-1000, 0), new Point(1000, 0)); Line impreciselyParallel = new Line( new Point(-1000, -UNRECOGNIZABLE_FRACTION), new Point(1000, UNRECOGNIZABLE_FRACTION)); assertTrue(new Vector(bigX.getP1(), bigX.getP2()) .isParallelTo(new Vector(impreciselyParallel.getP1(), impreciselyParallel.getP2()))); assertTrue(bigX.touches(impreciselyParallel)); } @Test public void test_intersects_with_Line() { // simple intersection Line l1 = new Line(0, 0, 4, 4); Line l2 = new Line(0, 4, 4, 0); assertTrue(l1.touches(l2)); assertTrue(l2.touches(l1)); // lines touch in one point Line l3 = new Line(4, 4, 7, 9); assertTrue(l1.touches(l3)); assertTrue(l3.touches(l1)); // lines overlap Line l4 = new Line(2, 2, 6, 6); assertTrue(l1.touches(l4)); assertTrue(l4.touches(l1)); // one line is a single point Line l5 = new Line(1, 1, 1, 1); assertTrue(l5.touches(l1)); assertTrue(l1.touches(l5)); // straights would intersect, but these lines do not Line l6 = new Line(4, 0, 5, 4); assertFalse(l6.touches(l1)); assertFalse(l1.touches(l6)); } @Test public void test_intersects_with_Rect() { Line l1 = new Line(0, 0, 4, 4); Rectangle r1 = new Rectangle(0, 4, 4, 4); assertTrue(l1.touches(r1)); } @Test public void test_setters() { for (double x1 = -2; x1 <= 2; x1 += 0.5) { for (double y1 = -2; y1 <= 2; y1 += 0.5) { Point p1 = new Point(x1, y1); for (double x2 = -2; x2 <= 2; x2 += 0.5) { for (double y2 = -2; y2 <= 2; y2 += 0.5) { Point p2 = new Point(x2, y2); Line line = new Line(new Point(-5, -5), new Point(-10, -10)); assertFalse(line.getP1().equals(p1)); assertFalse(line.getP2().equals(p2)); line.setP1(p1); line.setP2(p2); assertTrue(line.getP1().equals(p1)); assertTrue(line.getP2().equals(p2)); line.setX1(-5); line.setY1(-5); assertTrue(line.getP1().equals(new Point(-5, -5))); line.setX2(5); line.setY2(5); assertTrue(line.getP2().equals(new Point(5, 5))); Line l2 = new Line(p1, p2); line.setLine(l2); assertTrue(line.equals(l2)); l2 = new Line(p2, p1); line.setLine(p2, p1); assertTrue(line.equals(l2)); line.setLine(0, 1, 2, 3); assertTrue(line.equals(new Line(0, 1, 2, 3))); } } } } } @Test public void test_toString() { Line l1 = new Line(0, 0, 5, 0); assertEquals("Line: (0.0, 0.0) -> (5.0, 0.0)", l1.toString()); } }