/*
 * 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);
    }
}
