blob: 0e26c92e2a77a572ef2816f20c58d239df4c59a7 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 org.apache.commons.geometry.euclidean.twod;
import org.apache.commons.geometry.core.Geometry;
import org.apache.commons.geometry.core.GeometryTestUtils;
import org.apache.commons.geometry.core.exception.GeometryValueException;
import org.apache.commons.geometry.core.partitioning.Transform;
import org.apache.commons.geometry.core.precision.DoublePrecisionContext;
import org.apache.commons.geometry.core.precision.EpsilonDoublePrecisionContext;
import org.apache.commons.geometry.euclidean.EuclideanTestUtils;
import org.apache.commons.geometry.euclidean.oned.Vector1D;
import org.apache.commons.numbers.angle.PlaneAngleRadians;
import org.junit.Assert;
import org.junit.Test;
public class LineTest {
private static final double TEST_EPS = 1e-10;
private static final DoublePrecisionContext TEST_PRECISION =
new EpsilonDoublePrecisionContext(TEST_EPS);
@Test
public void testFromPoints() {
// act/assert
checkLine(Line.fromPoints(Vector2D.ZERO, Vector2D.PLUS_X, TEST_PRECISION),
Vector2D.ZERO, Vector2D.PLUS_X);
checkLine(Line.fromPoints(Vector2D.ZERO, Vector2D.of(100, 0), TEST_PRECISION),
Vector2D.ZERO, Vector2D.PLUS_X);
checkLine(Line.fromPoints(Vector2D.of(100, 0), Vector2D.ZERO, TEST_PRECISION),
Vector2D.ZERO, Vector2D.MINUS_X);
checkLine(Line.fromPoints(Vector2D.of(-100, 0), Vector2D.of(100, 0), TEST_PRECISION),
Vector2D.ZERO, Vector2D.PLUS_X);
checkLine(Line.fromPoints(Vector2D.of(-2, 0), Vector2D.of(0, 2), TEST_PRECISION),
Vector2D.of(-1, 1), Vector2D.of(1, 1).normalize());
checkLine(Line.fromPoints(Vector2D.of(0, 2), Vector2D.of(-2, 0), TEST_PRECISION),
Vector2D.of(-1, 1), Vector2D.of(-1, -1).normalize());
}
@Test
public void testFromPoints_pointsTooClose() {
// act/assert
GeometryTestUtils.assertThrows(() -> Line.fromPoints(Vector2D.PLUS_X, Vector2D.PLUS_X, TEST_PRECISION),
GeometryValueException.class, "Line direction cannot be zero");
GeometryTestUtils.assertThrows(() -> Line.fromPoints(Vector2D.PLUS_X, Vector2D.of(1 + 1e-11, 1e-11), TEST_PRECISION),
GeometryValueException.class, "Line direction cannot be zero");
}
@Test
public void testFromPointAndDirection() {
// act/assert
checkLine(Line.fromPointAndDirection(Vector2D.ZERO, Vector2D.PLUS_X, TEST_PRECISION),
Vector2D.ZERO, Vector2D.PLUS_X);
checkLine(Line.fromPointAndDirection(Vector2D.ZERO, Vector2D.of(100, 0), TEST_PRECISION),
Vector2D.ZERO, Vector2D.PLUS_X);
checkLine(Line.fromPointAndDirection(Vector2D.of(-100, 0), Vector2D.of(100, 0), TEST_PRECISION),
Vector2D.ZERO, Vector2D.PLUS_X);
checkLine(Line.fromPointAndDirection(Vector2D.of(-2, 0), Vector2D.of(1, 1), TEST_PRECISION),
Vector2D.of(-1, 1), Vector2D.of(1, 1).normalize());
checkLine(Line.fromPointAndDirection(Vector2D.of(0, 2), Vector2D.of(-1, -1), TEST_PRECISION),
Vector2D.of(-1, 1), Vector2D.of(-1, -1).normalize());
}
@Test
public void testFromPointAndDirection_directionIsZero() {
// act/assert
GeometryTestUtils.assertThrows(() -> Line.fromPointAndDirection(Vector2D.PLUS_X, Vector2D.ZERO, TEST_PRECISION),
GeometryValueException.class, "Line direction cannot be zero");
GeometryTestUtils.assertThrows(() -> Line.fromPointAndDirection(Vector2D.PLUS_X, Vector2D.of(1e-11, -1e-12), TEST_PRECISION),
GeometryValueException.class, "Line direction cannot be zero");
}
@Test
public void testFromPointAndAngle() {
// act/assert
checkLine(Line.fromPointAndAngle(Vector2D.ZERO, 0, TEST_PRECISION),
Vector2D.ZERO, Vector2D.PLUS_X);
checkLine(Line.fromPointAndAngle(Vector2D.of(1, 1), Geometry.HALF_PI, TEST_PRECISION),
Vector2D.of(1, 0), Vector2D.PLUS_Y);
checkLine(Line.fromPointAndAngle(Vector2D.of(-1, -1), Geometry.PI, TEST_PRECISION),
Vector2D.of(0, -1), Vector2D.MINUS_X);
checkLine(Line.fromPointAndAngle(Vector2D.of(1, -1), Geometry.MINUS_HALF_PI, TEST_PRECISION),
Vector2D.of(1, 0), Vector2D.MINUS_Y);
checkLine(Line.fromPointAndAngle(Vector2D.of(-1, 1), Geometry.TWO_PI, TEST_PRECISION),
Vector2D.of(0, 1), Vector2D.PLUS_X);
}
@Test
public void testGetAngle() {
// arrange
Vector2D vec = Vector2D.of(1, 2);
for (double theta = -4 * Geometry.PI; theta < 2 * Geometry.PI; theta += 0.1) {
Line line = Line.fromPointAndAngle(vec, theta, TEST_PRECISION);
// act/assert
Assert.assertEquals(PlaneAngleRadians.normalizeBetweenZeroAndTwoPi(theta),
line.getAngle(), TEST_EPS);
}
}
@Test
public void testGetAngle_multiplesOfPi() {
// arrange
Vector2D vec = Vector2D.of(-1, -2);
// act/assert
Assert.assertEquals(0, Line.fromPointAndAngle(vec, Geometry.ZERO_PI, TEST_PRECISION).getAngle(), TEST_EPS);
Assert.assertEquals(Geometry.PI, Line.fromPointAndAngle(vec, Geometry.PI, TEST_PRECISION).getAngle(), TEST_EPS);
Assert.assertEquals(0, Line.fromPointAndAngle(vec, Geometry.TWO_PI, TEST_PRECISION).getAngle(), TEST_EPS);
Assert.assertEquals(0, Line.fromPointAndAngle(vec, -2 * Geometry.PI, TEST_PRECISION).getAngle(), TEST_EPS);
Assert.assertEquals(Geometry.PI, Line.fromPointAndAngle(vec, -3 * Geometry.PI, TEST_PRECISION).getAngle(), TEST_EPS);
Assert.assertEquals(0, Line.fromPointAndAngle(vec, -4 * Geometry.TWO_PI, TEST_PRECISION).getAngle(), TEST_EPS);
}
@Test
public void testGetDirection() {
// act/assert
EuclideanTestUtils.assertCoordinatesEqual(Vector2D.PLUS_X,
Line.fromPoints(Vector2D.of(0, 0), Vector2D.of(1, 0), TEST_PRECISION).getDirection(), TEST_EPS);
EuclideanTestUtils.assertCoordinatesEqual(Vector2D.MINUS_Y,
Line.fromPoints(Vector2D.of(0, 1), Vector2D.of(0, -1), TEST_PRECISION).getDirection(), TEST_EPS);
EuclideanTestUtils.assertCoordinatesEqual(Vector2D.MINUS_X,
Line.fromPoints(Vector2D.of(2, 2), Vector2D.of(1, 2), TEST_PRECISION).getDirection(), TEST_EPS);
EuclideanTestUtils.assertCoordinatesEqual(Vector2D.PLUS_X,
Line.fromPoints(Vector2D.of(10, -2), Vector2D.of(10.1, -2), TEST_PRECISION).getDirection(), TEST_EPS);
EuclideanTestUtils.assertCoordinatesEqual(Vector2D.MINUS_Y,
Line.fromPoints(Vector2D.of(3, 2), Vector2D.of(3, 1), TEST_PRECISION).getDirection(), TEST_EPS);
EuclideanTestUtils.assertCoordinatesEqual(Vector2D.PLUS_Y,
Line.fromPoints(Vector2D.of(-3, 10), Vector2D.of(-3, 10.1), TEST_PRECISION).getDirection(), TEST_EPS);
EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(1, -1).normalize(),
Line.fromPoints(Vector2D.of(0, 2), Vector2D.of(2, 0), TEST_PRECISION).getDirection(), TEST_EPS);
EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(-1, 1).normalize(),
Line.fromPoints(Vector2D.of(2, 0), Vector2D.of(0, 2), TEST_PRECISION).getDirection(), TEST_EPS);
}
@Test
public void testGetOffsetDirection() {
// act/assert
EuclideanTestUtils.assertCoordinatesEqual(Vector2D.MINUS_Y,
Line.fromPoints(Vector2D.of(0, 0), Vector2D.of(1, 0), TEST_PRECISION).getOffsetDirection(), TEST_EPS);
EuclideanTestUtils.assertCoordinatesEqual(Vector2D.MINUS_X,
Line.fromPoints(Vector2D.of(0, 1), Vector2D.of(0, -1), TEST_PRECISION).getOffsetDirection(), TEST_EPS);
EuclideanTestUtils.assertCoordinatesEqual(Vector2D.PLUS_Y,
Line.fromPoints(Vector2D.of(2, 2), Vector2D.of(1, 2), TEST_PRECISION).getOffsetDirection(), TEST_EPS);
EuclideanTestUtils.assertCoordinatesEqual(Vector2D.MINUS_Y,
Line.fromPoints(Vector2D.of(10, -2), Vector2D.of(10.1, -2), TEST_PRECISION).getOffsetDirection(), TEST_EPS);
EuclideanTestUtils.assertCoordinatesEqual(Vector2D.MINUS_X,
Line.fromPoints(Vector2D.of(3, 2), Vector2D.of(3, 1), TEST_PRECISION).getOffsetDirection(), TEST_EPS);
EuclideanTestUtils.assertCoordinatesEqual(Vector2D.PLUS_X,
Line.fromPoints(Vector2D.of(-3, 10), Vector2D.of(-3, 10.1), TEST_PRECISION).getOffsetDirection(), TEST_EPS);
EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(-1, -1).normalize(),
Line.fromPoints(Vector2D.of(0, 2), Vector2D.of(2, 0), TEST_PRECISION).getOffsetDirection(), TEST_EPS);
EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(1, 1).normalize(),
Line.fromPoints(Vector2D.of(2, 0), Vector2D.of(0, 2), TEST_PRECISION).getOffsetDirection(), TEST_EPS);
}
@Test
public void testGetOrigin() {
// act/assert
EuclideanTestUtils.assertCoordinatesEqual(Vector2D.ZERO,
Line.fromPoints(Vector2D.of(0, 0), Vector2D.of(1, 0), TEST_PRECISION).getOrigin(), TEST_EPS);
EuclideanTestUtils.assertCoordinatesEqual(Vector2D.ZERO,
Line.fromPoints(Vector2D.of(0, 1), Vector2D.of(0, -1), TEST_PRECISION).getOrigin(), TEST_EPS);
EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(0, 2),
Line.fromPoints(Vector2D.of(2, 2), Vector2D.of(3, 2), TEST_PRECISION).getOrigin(), TEST_EPS);
EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(0, -2),
Line.fromPoints(Vector2D.of(10, -2), Vector2D.of(10.1, -2), TEST_PRECISION).getOrigin(), TEST_EPS);
EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(3, 0),
Line.fromPoints(Vector2D.of(3, 2), Vector2D.of(3, 1), TEST_PRECISION).getOrigin(), TEST_EPS);
EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(-3, 0),
Line.fromPoints(Vector2D.of(-3, 10), Vector2D.of(-3, 10.1), TEST_PRECISION).getOrigin(), TEST_EPS);
EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(1, 1),
Line.fromPoints(Vector2D.of(0, 2), Vector2D.of(2, 0), TEST_PRECISION).getOrigin(), TEST_EPS);
EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(1, 1),
Line.fromPoints(Vector2D.of(2, 0), Vector2D.of(0, 2), TEST_PRECISION).getOrigin(), TEST_EPS);
}
@Test
public void testGetOriginOffset() {
// arrange
double sqrt2 = Math.sqrt(2);
// act/assert
Assert.assertEquals(0.0,
Line.fromPoints(Vector2D.of(0, 0), Vector2D.of(1, 1), TEST_PRECISION).getOriginOffset(), TEST_EPS);
Assert.assertEquals(0.0,
Line.fromPoints(Vector2D.of(0, 0), Vector2D.of(-1, -1), TEST_PRECISION).getOriginOffset(), TEST_EPS);
Assert.assertEquals(sqrt2,
Line.fromPoints(Vector2D.of(-1, 1), Vector2D.of(0, 2), TEST_PRECISION).getOriginOffset(), TEST_EPS);
Assert.assertEquals(-sqrt2,
Line.fromPoints(Vector2D.of(0, -2), Vector2D.of(1, -1), TEST_PRECISION).getOriginOffset(), TEST_EPS);
Assert.assertEquals(-sqrt2,
Line.fromPoints(Vector2D.of(0, 2), Vector2D.of(-1, 1), TEST_PRECISION).getOriginOffset(), TEST_EPS);
Assert.assertEquals(sqrt2,
Line.fromPoints(Vector2D.of(1, -1), Vector2D.of(0, -2), TEST_PRECISION).getOriginOffset(), TEST_EPS);
}
@Test
public void testGetPrecision() {
// act/assert
Assert.assertSame(TEST_PRECISION, Line.fromPoints(Vector2D.ZERO, Vector2D.PLUS_X, TEST_PRECISION).getPrecision());
Assert.assertSame(TEST_PRECISION, Line.fromPointAndDirection(Vector2D.ZERO, Vector2D.PLUS_X, TEST_PRECISION).getPrecision());
Assert.assertSame(TEST_PRECISION, Line.fromPointAndAngle(Vector2D.ZERO, 0, TEST_PRECISION).getPrecision());
}
@Test
public void testCopySelf() {
// arrange
Line line = Line.fromPoints(Vector2D.ZERO, Vector2D.PLUS_X, TEST_PRECISION);
// act/assert
Assert.assertSame(line, line.copySelf());
}
@Test
public void testReverse() {
// arrange
Vector2D pt = Vector2D.of(0, 1);
Vector2D dir = Vector2D.PLUS_X;
Line line = Line.fromPointAndDirection(pt, dir, TEST_PRECISION);
// act
Line reversed = line.reverse();
Line doubleReversed = reversed.reverse();
// assert
checkLine(reversed, pt, dir.negate());
Assert.assertEquals(-1, reversed.getOriginOffset(), TEST_EPS);
checkLine(doubleReversed, pt, dir);
Assert.assertEquals(1, doubleReversed.getOriginOffset(), TEST_EPS);
}
@Test
public void testToSubSpace() {
// arrange
Line line = Line.fromPoints(Vector2D.of(2, 1), Vector2D.of(-2, -2), TEST_PRECISION);
// act/assert
Assert.assertEquals(0.0, line.toSubSpace(Vector2D.of(-3, 4)).getX(), TEST_EPS);
Assert.assertEquals(0.0, line.toSubSpace(Vector2D.of( 3, -4)).getX(), TEST_EPS);
Assert.assertEquals(-5.0, line.toSubSpace(Vector2D.of(7, -1)).getX(), TEST_EPS);
Assert.assertEquals(5.0, line.toSubSpace(Vector2D.of(-1, -7)).getX(), TEST_EPS);
}
@Test
public void testToSpace_throughOrigin() {
// arrange
double invSqrt2 = 1 / Math.sqrt(2);
Vector2D dir = Vector2D.of(invSqrt2, invSqrt2);
Line line = Line.fromPoints(Vector2D.ZERO, Vector2D.of(1, 1), TEST_PRECISION);
// act/assert
EuclideanTestUtils.assertCoordinatesEqual(Vector2D.ZERO, line.toSpace(Vector1D.of(0)), TEST_EPS);
for (int i=0; i<100; ++i) {
EuclideanTestUtils.assertCoordinatesEqual(dir.multiply(i), line.toSpace(Vector1D.of(i)), TEST_EPS);
EuclideanTestUtils.assertCoordinatesEqual(dir.multiply(-i), line.toSpace(Vector1D.of(-i)), TEST_EPS);
}
}
@Test
public void testToSpace_offsetFromOrigin() {
// arrange
double angle = Geometry.PI / 6;
double cos = Math.cos(angle);
double sin = Math.sin(angle);
Vector2D pt = Vector2D.of(-5, 0);
double h = Math.abs(pt.getX()) * cos;
double d = h * cos;
Vector2D origin = Vector2D.of(
pt.getX() + d,
h * sin
);
Vector2D dir = Vector2D.of(cos, sin);
Line line = Line.fromPointAndAngle(pt, angle, TEST_PRECISION);
// act/assert
EuclideanTestUtils.assertCoordinatesEqual(origin, line.toSpace(Vector1D.of(0)), TEST_EPS);
for (int i=0; i<100; ++i) {
EuclideanTestUtils.assertCoordinatesEqual(origin.add(dir.multiply(i)), line.toSpace(Vector1D.of(i)), TEST_EPS);
EuclideanTestUtils.assertCoordinatesEqual(origin.add(dir.multiply(-i)), line.toSpace(Vector1D.of(-i)), TEST_EPS);
}
}
@Test
public void testIntersection() {
// arrange
Line a = Line.fromPointAndDirection(Vector2D.ZERO, Vector2D.PLUS_X, TEST_PRECISION);
Line b = Line.fromPointAndDirection(Vector2D.ZERO, Vector2D.PLUS_Y, TEST_PRECISION);
Line c = Line.fromPointAndDirection(Vector2D.of(0, 2), Vector2D.of(2, 1), TEST_PRECISION);
Line d = Line.fromPointAndDirection(Vector2D.of(0, -1), Vector2D.of(2, -1), TEST_PRECISION);
// act/assert
EuclideanTestUtils.assertCoordinatesEqual(Vector2D.ZERO, a.intersection(b), TEST_EPS);
EuclideanTestUtils.assertCoordinatesEqual(Vector2D.ZERO, b.intersection(a), TEST_EPS);
EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(-4, 0), a.intersection(c), TEST_EPS);
EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(-4, 0), c.intersection(a), TEST_EPS);
EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(-2, 0), a.intersection(d), TEST_EPS);
EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(-2, 0), d.intersection(a), TEST_EPS);
EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(0, 2), b.intersection(c), TEST_EPS);
EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(0, 2), c.intersection(b), TEST_EPS);
EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(0, -1), b.intersection(d), TEST_EPS);
EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(0, -1), d.intersection(b), TEST_EPS);
EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(-3, 0.5), c.intersection(d), TEST_EPS);
EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(-3, 0.5), d.intersection(c), TEST_EPS);
}
@Test
public void testIntersection_parallel() {
// arrange
Line a = Line.fromPointAndDirection(Vector2D.ZERO, Vector2D.PLUS_X, TEST_PRECISION);
Line b = Line.fromPointAndDirection(Vector2D.of(0, 1), Vector2D.PLUS_X, TEST_PRECISION);
Line c = Line.fromPointAndDirection(Vector2D.of(0, 2), Vector2D.of(2, 1), TEST_PRECISION);
Line d = Line.fromPointAndDirection(Vector2D.of(0, -1), Vector2D.of(2, 1), TEST_PRECISION);
// act/assert
Assert.assertNull(a.intersection(b));
Assert.assertNull(b.intersection(a));
Assert.assertNull(c.intersection(d));
Assert.assertNull(d.intersection(c));
}
@Test
public void testIntersection_coincident() {
// arrange
Line a = Line.fromPointAndDirection(Vector2D.ZERO, Vector2D.PLUS_X, TEST_PRECISION);
Line b = Line.fromPointAndDirection(Vector2D.ZERO, Vector2D.PLUS_X, TEST_PRECISION);
Line c = Line.fromPointAndDirection(Vector2D.of(0, 2), Vector2D.of(2, 1), TEST_PRECISION);
Line d = Line.fromPointAndDirection(Vector2D.of(0, 2), Vector2D.of(2, 1), TEST_PRECISION);
// act/assert
Assert.assertNull(a.intersection(b));
Assert.assertNull(b.intersection(a));
Assert.assertNull(c.intersection(d));
Assert.assertNull(d.intersection(c));
}
@Test
public void testProject() {
// --- arrange
Line xAxis = Line.fromPointAndDirection(Vector2D.ZERO, Vector2D.PLUS_X, TEST_PRECISION);
Line yAxis = Line.fromPointAndDirection(Vector2D.ZERO, Vector2D.PLUS_Y, TEST_PRECISION);
double diagonalYIntercept = 1;
Vector2D diagonalDir = Vector2D.of(1, 2);
Line diagonal = Line.fromPointAndDirection(Vector2D.of(0, diagonalYIntercept), diagonalDir, TEST_PRECISION);
EuclideanTestUtils.permute(-5, 5, 0.5, (x, y) -> {
Vector2D pt = Vector2D.of(x, y);
// --- act/assert
EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(x, 0), xAxis.project(pt), TEST_EPS);
EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(0, y), yAxis.project(pt), TEST_EPS);
Vector2D diagonalPt = diagonal.project(pt);
Assert.assertTrue(diagonal.contains(diagonalPt));
Assert.assertEquals(diagonal.distance(pt), pt.distance(diagonalPt), TEST_EPS);
// check that y = mx + b is true
Assert.assertEquals(diagonalPt.getY(),
(diagonalDir.getY() * diagonalPt.getX() / diagonalDir.getX()) + diagonalYIntercept, TEST_EPS);
});
}
@Test
public void testWholeHyperplane() {
// arrange
Line line = Line.fromPoints(Vector2D.ZERO, Vector2D.PLUS_X, TEST_PRECISION);
// act
SubLine result = line.wholeHyperplane();
// assert
Assert.assertSame(line, result.getHyperplane());
GeometryTestUtils.assertPositiveInfinity(result.getSize());
}
@Test
public void testWholeSpace() {
// arrange
Line line = Line.fromPoints(Vector2D.ZERO, Vector2D.PLUS_X, TEST_PRECISION);
// act
PolygonsSet result = line.wholeSpace();
// assert
GeometryTestUtils.assertPositiveInfinity(result.getSize());
Assert.assertSame(TEST_PRECISION, result.getPrecision());
}
@Test
public void testGetOffset_parallelLines() {
// arrange
double dist = Math.sin(Math.atan2(2, 1));
Line a = Line.fromPoints(Vector2D.of(-2, 0), Vector2D.of(0, 4), TEST_PRECISION);
Line b = Line.fromPoints(Vector2D.of(-3, 0), Vector2D.of(0, 6), TEST_PRECISION);
Line c = Line.fromPoints(Vector2D.of(-1, 0), Vector2D.of(0, 2), TEST_PRECISION);
Line d = Line.fromPoints(Vector2D.of(1, 0), Vector2D.of(0, -2), TEST_PRECISION);
// act/assert
Assert.assertEquals(-dist, a.getOffset(b), TEST_EPS);
Assert.assertEquals(dist, b.getOffset(a), TEST_EPS);
Assert.assertEquals(dist, a.getOffset(c), TEST_EPS);
Assert.assertEquals(-dist, c.getOffset(a), TEST_EPS);
Assert.assertEquals(3 * dist, a.getOffset(d), TEST_EPS);
Assert.assertEquals(3 * dist, d.getOffset(a), TEST_EPS);
}
@Test
public void testGetOffset_coincidentLines() {
// arrange
Line a = Line.fromPoints(Vector2D.of(-2, 0), Vector2D.of(0, 4), TEST_PRECISION);
Line b = Line.fromPoints(Vector2D.of(-2, 0), Vector2D.of(0, 4), TEST_PRECISION);
Line c = b.reverse();
// act/assert
Assert.assertEquals(0, a.getOffset(a), TEST_EPS);
Assert.assertEquals(0, a.getOffset(b), TEST_EPS);
Assert.assertEquals(0, b.getOffset(a), TEST_EPS);
Assert.assertEquals(0, a.getOffset(c), TEST_EPS);
Assert.assertEquals(0, c.getOffset(a), TEST_EPS);
}
@Test
public void testGetOffset_nonParallelLines() {
// arrange
Line a = Line.fromPoints(Vector2D.ZERO, Vector2D.PLUS_X, TEST_PRECISION);
Line b = Line.fromPoints(Vector2D.ZERO, Vector2D.PLUS_Y, TEST_PRECISION);
Line c = Line.fromPoints(Vector2D.of(-1, 0), Vector2D.of(0, 2), TEST_PRECISION);
Line d = Line.fromPoints(Vector2D.of(1, 0), Vector2D.of(0, 4), TEST_PRECISION);
// act/assert
Assert.assertEquals(0, a.getOffset(b), TEST_EPS);
Assert.assertEquals(0, b.getOffset(a), TEST_EPS);
Assert.assertEquals(0, a.getOffset(c), TEST_EPS);
Assert.assertEquals(0, c.getOffset(a), TEST_EPS);
Assert.assertEquals(0, a.getOffset(d), TEST_EPS);
Assert.assertEquals(0, d.getOffset(a), TEST_EPS);
}
@Test
public void testGetOffset_point() {
// arrange
Line line = Line.fromPoints(Vector2D.of(-1, 0), Vector2D.of(0, 2), TEST_PRECISION);
Line reversed = line.reverse();
// act/assert
Assert.assertEquals(0.0, line.getOffset(Vector2D.of(-0.5, 1)), TEST_EPS);
Assert.assertEquals(0.0, line.getOffset(Vector2D.of(-1.5, -1)), TEST_EPS);
Assert.assertEquals(0.0, line.getOffset(Vector2D.of(0.5, 3)), TEST_EPS);
double d = Math.sin(Math.atan2(2, 1));
Assert.assertEquals(d, line.getOffset(Vector2D.ZERO), TEST_EPS);
Assert.assertEquals(-d, line.getOffset(Vector2D.of(-1, 2)), TEST_EPS);
Assert.assertEquals(-d, reversed.getOffset(Vector2D.ZERO), TEST_EPS);
Assert.assertEquals(d, reversed.getOffset(Vector2D.of(-1, 2)), TEST_EPS);
}
@Test
public void testGetOffset_point_permute() {
// arrange
Line line = Line.fromPoints(Vector2D.of(-1, 0), Vector2D.of(0, 2), TEST_PRECISION);
Vector2D lineOrigin = line.getOrigin();
EuclideanTestUtils.permute(-5, 5, 0.5, (x, y) -> {
Vector2D pt = Vector2D.of(x, y);
// act
double offset = line.getOffset(pt);
// arrange
Vector2D vec = lineOrigin.vectorTo(pt).reject(line.getDirection());
double dot = vec.dot(line.getOffsetDirection());
double expected = Math.signum(dot) * vec.norm();
Assert.assertEquals(expected, offset, TEST_EPS);
});
}
@Test
public void testSameOrientationAs() {
// arrange
Line a = Line.fromPointAndAngle(Vector2D.ZERO, Geometry.ZERO_PI, TEST_PRECISION);
Line b = Line.fromPointAndAngle(Vector2D.of(4, 5), Geometry.ZERO_PI, TEST_PRECISION);
Line c = Line.fromPointAndAngle(Vector2D.of(-1, -3), 0.4 * Geometry.PI, TEST_PRECISION);
Line d = Line.fromPointAndAngle(Vector2D.of(1, 0), -0.4 * Geometry.PI, TEST_PRECISION);
Line e = Line.fromPointAndAngle(Vector2D.of(6, -3), Geometry.PI, TEST_PRECISION);
Line f = Line.fromPointAndAngle(Vector2D.of(8, 5), 0.8 * Geometry.PI, TEST_PRECISION);
Line g = Line.fromPointAndAngle(Vector2D.of(6, -3), -0.8 * Geometry.PI, TEST_PRECISION);
// act/assert
Assert.assertTrue(a.sameOrientationAs(a));
Assert.assertTrue(a.sameOrientationAs(b));
Assert.assertTrue(b.sameOrientationAs(a));
Assert.assertTrue(a.sameOrientationAs(c));
Assert.assertTrue(c.sameOrientationAs(a));
Assert.assertTrue(a.sameOrientationAs(d));
Assert.assertTrue(d.sameOrientationAs(a));
Assert.assertFalse(c.sameOrientationAs(d));
Assert.assertFalse(d.sameOrientationAs(c));
Assert.assertTrue(e.sameOrientationAs(f));
Assert.assertTrue(f.sameOrientationAs(e));
Assert.assertTrue(e.sameOrientationAs(g));
Assert.assertTrue(g.sameOrientationAs(e));
Assert.assertFalse(a.sameOrientationAs(e));
Assert.assertFalse(e.sameOrientationAs(a));
}
@Test
public void testSameOrientationAs_orthogonal() {
// arrange
Line a = Line.fromPointAndDirection(Vector2D.ZERO, Vector2D.PLUS_X, TEST_PRECISION);
Line b = Line.fromPointAndDirection(Vector2D.of(4, 5), Vector2D.PLUS_Y, TEST_PRECISION);
Line c = Line.fromPointAndDirection(Vector2D.of(-4, -5), Vector2D.MINUS_Y, TEST_PRECISION);
// act/assert
Assert.assertTrue(a.sameOrientationAs(b));
Assert.assertTrue(b.sameOrientationAs(a));
Assert.assertTrue(a.sameOrientationAs(c));
Assert.assertTrue(c.sameOrientationAs(a));
}
@Test
public void testDistance_parallelLines() {
// arrange
double dist = Math.sin(Math.atan2(2, 1));
Line a = Line.fromPoints(Vector2D.of(-2, 0), Vector2D.of(0, 4), TEST_PRECISION);
Line b = Line.fromPoints(Vector2D.of(-3, 0), Vector2D.of(0, 6), TEST_PRECISION);
Line c = Line.fromPoints(Vector2D.of(-1, 0), Vector2D.of(0, 2), TEST_PRECISION);
Line d = Line.fromPoints(Vector2D.of(1, 0), Vector2D.of(0, -2), TEST_PRECISION);
// act/assert
Assert.assertEquals(dist, a.distance(b), TEST_EPS);
Assert.assertEquals(dist, b.distance(a), TEST_EPS);
Assert.assertEquals(dist, a.distance(c), TEST_EPS);
Assert.assertEquals(dist, c.distance(a), TEST_EPS);
Assert.assertEquals(3 * dist, a.distance(d), TEST_EPS);
Assert.assertEquals(3 * dist, d.distance(a), TEST_EPS);
}
@Test
public void testDistance_coincidentLines() {
// arrange
Line a = Line.fromPoints(Vector2D.of(-2, 0), Vector2D.of(0, 4), TEST_PRECISION);
Line b = Line.fromPoints(Vector2D.of(-2, 0), Vector2D.of(0, 4), TEST_PRECISION);
Line c = b.reverse();
// act/assert
Assert.assertEquals(0, a.distance(a), TEST_EPS);
Assert.assertEquals(0, a.distance(b), TEST_EPS);
Assert.assertEquals(0, b.distance(a), TEST_EPS);
Assert.assertEquals(0, a.distance(c), TEST_EPS);
Assert.assertEquals(0, c.distance(a), TEST_EPS);
}
@Test
public void testDistance_nonParallelLines() {
// arrange
Line a = Line.fromPoints(Vector2D.ZERO, Vector2D.PLUS_X, TEST_PRECISION);
Line b = Line.fromPoints(Vector2D.ZERO, Vector2D.PLUS_Y, TEST_PRECISION);
Line c = Line.fromPoints(Vector2D.of(-1, 0), Vector2D.of(0, 2), TEST_PRECISION);
Line d = Line.fromPoints(Vector2D.of(1, 0), Vector2D.of(0, 4), TEST_PRECISION);
// act/assert
Assert.assertEquals(0, a.distance(b), TEST_EPS);
Assert.assertEquals(0, b.distance(a), TEST_EPS);
Assert.assertEquals(0, a.distance(c), TEST_EPS);
Assert.assertEquals(0, c.distance(a), TEST_EPS);
Assert.assertEquals(0, a.distance(d), TEST_EPS);
Assert.assertEquals(0, d.distance(a), TEST_EPS);
}
@Test
public void testDistance() {
// arrange
Line line = Line.fromPoints(Vector2D.of(2, 1), Vector2D.of(-2, -2), TEST_PRECISION);
// act/assert
Assert.assertEquals(0, line.distance(line.getOrigin()), TEST_EPS);
Assert.assertEquals(+5.0, line.distance(Vector2D.of(5, -3)), TEST_EPS);
Assert.assertEquals(+5.0, line.distance(Vector2D.of(-5, 2)), TEST_EPS);
}
@Test
public void testPointAt() {
// arrange
Vector2D origin = Vector2D.of(-1, 1);
double d = Math.sqrt(2);
Line line = Line.fromPointAndDirection(origin, Vector2D.of(1, 1), TEST_PRECISION);
// act/assert
EuclideanTestUtils.assertCoordinatesEqual(origin, line.pointAt(0, 0), TEST_EPS);
EuclideanTestUtils.assertCoordinatesEqual(Vector2D.ZERO, line.pointAt(0, d), TEST_EPS);
EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(-2, 2), line.pointAt(0, -d), TEST_EPS);
EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(-2, 0), line.pointAt(-d, 0), TEST_EPS);
EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(0, 2), line.pointAt(d, 0), TEST_EPS);
EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(1, 1), line.pointAt(d, d), TEST_EPS);
EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(-3, 1), line.pointAt(-d, -d), TEST_EPS);
}
@Test
public void testPointAt_abscissaOffsetRoundtrip() {
// arrange
Line line = Line.fromPoints(Vector2D.of(2, 1), Vector2D.of(-2, -2), TEST_PRECISION);
for (double abscissa = -2.0; abscissa < 2.0; abscissa += 0.2) {
for (double offset = -2.0; offset < 2.0; offset += 0.2) {
// act
Vector2D point = line.pointAt(abscissa, offset);
// assert
Assert.assertEquals(abscissa, line.toSubSpace(point).getX(), TEST_EPS);
Assert.assertEquals(offset, line.getOffset(point), TEST_EPS);
}
}
}
@Test
public void testContains_line() {
// arrange
Vector2D pt = Vector2D.of(1, 2);
Vector2D dir = Vector2D.of(3, 7);
Line a = Line.fromPointAndDirection(pt, dir, TEST_PRECISION);
Line b = Line.fromPointAndDirection(Vector2D.of(0, -4), dir, TEST_PRECISION);
Line c = Line.fromPointAndDirection(Vector2D.of(-2, -2), dir.negate(), TEST_PRECISION);
Line d = Line.fromPointAndDirection(Vector2D.ZERO, Vector2D.PLUS_X, TEST_PRECISION);
Line e = Line.fromPointAndDirection(pt, dir, TEST_PRECISION);
Line f = Line.fromPointAndDirection(pt, dir.negate(), TEST_PRECISION);
// act/assert
Assert.assertTrue(a.contains(a));
Assert.assertTrue(a.contains(e));
Assert.assertTrue(e.contains(a));
Assert.assertTrue(a.contains(f));
Assert.assertTrue(f.contains(a));
Assert.assertFalse(a.contains(b));
Assert.assertFalse(a.contains(c));
Assert.assertFalse(a.contains(d));
}
@Test
public void testIsParallel_closeToEpsilon() {
// arrange
double eps = 1e-3;
DoublePrecisionContext precision = new EpsilonDoublePrecisionContext(eps);
Vector2D p = Vector2D.of(1, 2);
Line line = Line.fromPointAndAngle(p, Geometry.ZERO_PI, precision);
// act/assert
Vector2D offset1 = Vector2D.of(0, 1e-4);
Vector2D offset2 = Vector2D.of(0, 2e-3);
Assert.assertTrue(line.contains(Line.fromPointAndAngle(p.add(offset1), Geometry.ZERO_PI, precision)));
Assert.assertTrue(line.contains(Line.fromPointAndAngle(p.subtract(offset1), Geometry.ZERO_PI, precision)));
Assert.assertFalse(line.contains(Line.fromPointAndAngle(p.add(offset2), Geometry.ZERO_PI, precision)));
Assert.assertFalse(line.contains(Line.fromPointAndAngle(p.subtract(offset2), Geometry.ZERO_PI, precision)));
Assert.assertTrue(line.contains(Line.fromPointAndAngle(p, 1e-4, precision)));
Assert.assertFalse(line.contains(Line.fromPointAndAngle(p, 1e-2, precision)));
}
@Test
public void testContains_point() {
// arrange
Vector2D p1 = Vector2D.of(-1, 0);
Vector2D p2 = Vector2D.of(0, 2);
Line line = Line.fromPoints(p1, p2, TEST_PRECISION);
// act/assert
Assert.assertTrue(line.contains(p1));
Assert.assertTrue(line.contains(p2));
Assert.assertFalse(line.contains(Vector2D.ZERO));
Assert.assertFalse(line.contains(Vector2D.of(100, 79)));
Vector2D offset1 = Vector2D.of(0.1, 0);
Vector2D offset2 = Vector2D.of(0, -0.1);
Vector2D v;
for (double t=-2; t<=2; t+=0.1) {
v = p1.lerp(p2, t);
Assert.assertTrue(line.contains(v));
Assert.assertFalse(line.contains(v.add(offset1)));
Assert.assertFalse(line.contains(v.add(offset2)));
}
}
@Test
public void testContains_point_closeToEpsilon() {
// arrange
double eps = 1e-3;
DoublePrecisionContext precision = new EpsilonDoublePrecisionContext(eps);
Vector2D p1 = Vector2D.of(-1, 0);
Vector2D p2 = Vector2D.of(0, 2);
Vector2D mid = p1.lerp(p2, 0.5);
Line line = Line.fromPoints(p1, p2, precision);
Vector2D dir = line.getOffsetDirection();
// act/assert
Assert.assertTrue(line.contains(mid.add(dir.multiply(1e-4))));
Assert.assertTrue(line.contains(mid.add(dir.multiply(-1e-4))));
Assert.assertFalse(line.contains(mid.add(dir.multiply(2e-3))));
Assert.assertFalse(line.contains(mid.add(dir.multiply(-2e-3))));
}
@Test
public void testDistance_point() {
// arrange
Line line = Line.fromPoints(Vector2D.of(-1, 0), Vector2D.of(0, 2), TEST_PRECISION);
Line reversed = line.reverse();
// act/assert
Assert.assertEquals(0.0, line.distance(Vector2D.of(-0.5, 1)), TEST_EPS);
Assert.assertEquals(0.0, line.distance(Vector2D.of(-1.5, -1)), TEST_EPS);
Assert.assertEquals(0.0, line.distance(Vector2D.of(0.5, 3)), TEST_EPS);
double d = Math.sin(Math.atan2(2, 1));
Assert.assertEquals(d, line.distance(Vector2D.ZERO), TEST_EPS);
Assert.assertEquals(d, line.distance(Vector2D.of(-1, 2)), TEST_EPS);
Assert.assertEquals(d, reversed.distance(Vector2D.ZERO), TEST_EPS);
Assert.assertEquals(d, reversed.distance(Vector2D.of(-1, 2)), TEST_EPS);
}
@Test
public void testDistance_point_permute() {
// arrange
Line line = Line.fromPoints(Vector2D.of(-1, 0), Vector2D.of(0, 2), TEST_PRECISION);
Vector2D lineOrigin = line.getOrigin();
EuclideanTestUtils.permute(-5, 5, 0.5, (x, y) -> {
Vector2D pt = Vector2D.of(x, y);
// act
double dist = line.distance(pt);
// arrange
Vector2D vec = lineOrigin.vectorTo(pt).reject(line.getDirection());
Assert.assertEquals(vec.norm(), dist, TEST_EPS);
});
}
@Test
public void testIsParallel() {
// arrange
Vector2D dir = Vector2D.of(3, 7);
Line a = Line.fromPointAndDirection(Vector2D.of(1, 2), dir, TEST_PRECISION);
Line b = Line.fromPointAndDirection(Vector2D.of(0, -4), dir, TEST_PRECISION);
Line c = Line.fromPointAndDirection(Vector2D.of(-2, -2), dir.negate(), TEST_PRECISION);
Line d = Line.fromPointAndDirection(Vector2D.ZERO, Vector2D.PLUS_X, TEST_PRECISION);
// act/assert
Assert.assertTrue(a.isParallel(a));
Assert.assertTrue(a.isParallel(b));
Assert.assertTrue(b.isParallel(a));
Assert.assertTrue(a.isParallel(c));
Assert.assertTrue(c.isParallel(a));
Assert.assertFalse(a.isParallel(d));
Assert.assertFalse(d.isParallel(a));
}
@Test
public void testIsParallel_closeToParallel() {
// arrange
double eps = 1e-3;
DoublePrecisionContext precision = new EpsilonDoublePrecisionContext(eps);
Vector2D p1 = Vector2D.of(1, 2);
Vector2D p2 = Vector2D.of(1, -2);
Line line = Line.fromPointAndAngle(p1, Geometry.ZERO_PI, precision);
// act/assert
Assert.assertTrue(line.isParallel(Line.fromPointAndAngle(p2, 1e-4, precision)));
Assert.assertFalse(line.isParallel(Line.fromPointAndAngle(p2, 1e-2, precision)));
}
@Test
public void testTransform() {
// arrange
AffineTransformMatrix2D scale = AffineTransformMatrix2D.createScale(2, 3);
AffineTransformMatrix2D reflect = AffineTransformMatrix2D.createScale(-1, 1);
AffineTransformMatrix2D translate = AffineTransformMatrix2D.createTranslation(3, 4);
AffineTransformMatrix2D rotate = AffineTransformMatrix2D.createRotation(Geometry.HALF_PI);
AffineTransformMatrix2D rotateAroundPt = AffineTransformMatrix2D.createRotation(Vector2D.of(0, 1), Geometry.HALF_PI);
Vector2D p1 = Vector2D.of(0, 1);
Vector2D p2 = Vector2D.of(1, 0);
Line horizontal = Line.fromPointAndDirection(p1, Vector2D.PLUS_X, TEST_PRECISION);
Line vertical = Line.fromPointAndDirection(p2, Vector2D.PLUS_Y, TEST_PRECISION);
Line diagonal = Line.fromPointAndDirection(Vector2D.ZERO, Vector2D.of(1, 1), TEST_PRECISION);
// act/assert
Assert.assertSame(TEST_PRECISION, horizontal.transform(scale).getPrecision());
checkLine(horizontal.transform(scale), Vector2D.of(0, 3), Vector2D.PLUS_X);
checkLine(vertical.transform(scale), Vector2D.of(2, 0), Vector2D.PLUS_Y);
checkLine(diagonal.transform(scale), Vector2D.ZERO, Vector2D.of(2, 3).normalize());
checkLine(horizontal.transform(reflect), p1, Vector2D.MINUS_X);
checkLine(vertical.transform(reflect), Vector2D.of(-1, 0), Vector2D.PLUS_Y);
checkLine(diagonal.transform(reflect), Vector2D.ZERO, Vector2D.of(-1, 1).normalize());
checkLine(horizontal.transform(translate), Vector2D.of(0, 5), Vector2D.PLUS_X);
checkLine(vertical.transform(translate), Vector2D.of(4, 0), Vector2D.PLUS_Y);
checkLine(diagonal.transform(translate), Vector2D.of(-0.5, 0.5), Vector2D.of(1, 1).normalize());
checkLine(horizontal.transform(rotate), Vector2D.of(-1, 0), Vector2D.PLUS_Y);
checkLine(vertical.transform(rotate), Vector2D.of(0, 1), Vector2D.MINUS_X);
checkLine(diagonal.transform(rotate), Vector2D.ZERO, Vector2D.of(-1, 1).normalize());
checkLine(horizontal.transform(rotateAroundPt), Vector2D.ZERO, Vector2D.PLUS_Y);
checkLine(vertical.transform(rotateAroundPt), Vector2D.of(0, 2), Vector2D.MINUS_X);
checkLine(diagonal.transform(rotateAroundPt), Vector2D.of(1, 1), Vector2D.of(-1, 1).normalize());
}
@Test
public void testTransform_collapsedPoints() {
// arrange
AffineTransformMatrix2D scaleCollapse = AffineTransformMatrix2D.createScale(0, 1);
Line line = Line.fromPointAndDirection(Vector2D.ZERO, Vector2D.PLUS_X, TEST_PRECISION);
// act/assert
GeometryTestUtils.assertThrows(() -> {
line.transform(scaleCollapse);
}, GeometryValueException.class, "Line direction cannot be zero");
}
@Test
public void testHashCode() {
// arrange
DoublePrecisionContext precision1 = new EpsilonDoublePrecisionContext(1e-4);
DoublePrecisionContext precision2 = new EpsilonDoublePrecisionContext(1e-5);
Vector2D p = Vector2D.of(1, 2);
Vector2D v = Vector2D.of(1, 1);
Line a = Line.fromPointAndDirection(p, v, precision1);
Line b = Line.fromPointAndDirection(Vector2D.ZERO, v, precision1);
Line c = Line.fromPointAndDirection(p, v.negate(), precision1);
Line d = Line.fromPointAndDirection(p, v, precision2);
Line e = Line.fromPointAndDirection(p, v, precision1);
// act/assert
int aHash = a.hashCode();
Assert.assertEquals(aHash, a.hashCode());
Assert.assertEquals(aHash, e.hashCode());
Assert.assertNotEquals(aHash, b.hashCode());
Assert.assertNotEquals(aHash, c.hashCode());
Assert.assertNotEquals(aHash, d.hashCode());
}
@Test
public void testEquals() {
// arrange
DoublePrecisionContext precision1 = new EpsilonDoublePrecisionContext(1e-4);
DoublePrecisionContext precision2 = new EpsilonDoublePrecisionContext(1e-5);
Vector2D p = Vector2D.of(1, 2);
Vector2D v = Vector2D.of(1, 1);
Line a = Line.fromPointAndDirection(p, v, precision1);
Line b = Line.fromPointAndDirection(Vector2D.ZERO, v, precision1);
Line c = Line.fromPointAndDirection(p, v.negate(), precision1);
Line d = Line.fromPointAndDirection(p, v, precision2);
Line e = Line.fromPointAndDirection(p, v, precision1);
// act/assert
Assert.assertTrue(a.equals(a));
Assert.assertTrue(a.equals(e));
Assert.assertTrue(e.equals(a));
Assert.assertFalse(a.equals(null));
Assert.assertFalse(a.equals(new Object()));
Assert.assertFalse(a.equals(b));
Assert.assertFalse(a.equals(c));
Assert.assertFalse(a.equals(d));
}
@Test
public void testToString() {
// arrange
Line line = Line.fromPointAndDirection(Vector2D.ZERO, Vector2D.PLUS_X, TEST_PRECISION);
// act
String str = line.toString();
// assert
Assert.assertTrue(str.contains("Line"));
Assert.assertTrue(str.contains("origin= (0.0, 0.0)"));
Assert.assertTrue(str.contains("direction= (1.0, 0.0)"));
}
@Test
public void testLineTransform() {
Line l1 = Line.fromPoints(Vector2D.of(1.0 ,1.0), Vector2D.of(4.0 ,1.0), TEST_PRECISION);
Transform<Vector2D, Vector1D> t1 =
Line.getTransform(Vector2D.of(0.0, 0.5), Vector2D.of(-1.0, 0.0), Vector2D.of(1.0, 1.5));
Assert.assertEquals(0.5 * Math.PI,
((Line) t1.apply(l1)).getAngle(),
1.0e-10);
Line l2 = Line.fromPoints(Vector2D.of(0.0, 0.0), Vector2D.of(1.0, 1.0), TEST_PRECISION);
Transform<Vector2D, Vector1D> t2 =
Line.getTransform(Vector2D.of(0.0, 0.5), Vector2D.of(-1.0, 0.0), Vector2D.of(1.0, 1.5));
Assert.assertEquals(Math.atan2(1.0, -2.0),
((Line) t2.apply(l2)).getAngle(),
1.0e-10);
}
/**
* Check that the line has the given defining properties.
* @param line
* @param origin
* @param dir
*/
private void checkLine(Line line, Vector2D origin, Vector2D dir) {
EuclideanTestUtils.assertCoordinatesEqual(origin, line.getOrigin(), TEST_EPS);
EuclideanTestUtils.assertCoordinatesEqual(dir, line.getDirection(), TEST_EPS);
}
}