/*
 * 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 java.util.Comparator;
import java.util.regex.Pattern;

import org.apache.commons.numbers.angle.PlaneAngleRadians;
import org.apache.commons.geometry.core.GeometryTestUtils;
import org.apache.commons.geometry.core.exception.IllegalNormException;
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.numbers.core.Precision;
import org.junit.Assert;
import org.junit.Test;

public class Vector2DTest {

    private static final double EPS = Math.ulp(1d);

    @Test
    public void testConstants() {
        // act/assert
        checkVector(Vector2D.ZERO, 0, 0);
        checkVector(Vector2D.Unit.PLUS_X, 1, 0);
        checkVector(Vector2D.Unit.MINUS_X, -1, 0);
        checkVector(Vector2D.Unit.PLUS_Y, 0, 1);
        checkVector(Vector2D.Unit.MINUS_Y, 0, -1);
        checkVector(Vector2D.NaN, Double.NaN, Double.NaN);
        checkVector(Vector2D.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY);
        checkVector(Vector2D.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY);
    }

    @Test
    public void testConstants_normalize() {
        // act/assert
        GeometryTestUtils.assertThrows(() -> Vector2D.ZERO.normalize(),
                IllegalNormException.class);
        GeometryTestUtils.assertThrows(() -> Vector2D.NaN.normalize(),
                IllegalNormException.class);
        GeometryTestUtils.assertThrows(() -> Vector2D.POSITIVE_INFINITY.normalize(),
                IllegalNormException.class);
        GeometryTestUtils.assertThrows(() -> Vector2D.NEGATIVE_INFINITY.normalize(),
                IllegalNormException.class);

        Assert.assertSame(Vector2D.Unit.PLUS_X, Vector2D.Unit.PLUS_X.normalize());
        Assert.assertSame(Vector2D.Unit.MINUS_X, Vector2D.Unit.MINUS_X.normalize());

        Assert.assertSame(Vector2D.Unit.PLUS_Y, Vector2D.Unit.PLUS_Y.normalize());
        Assert.assertSame(Vector2D.Unit.MINUS_Y, Vector2D.Unit.MINUS_Y.normalize());
    }

    @Test
    public void testCoordinateAscendingOrder() {
        // arrange
        Comparator<Vector2D> cmp = Vector2D.COORDINATE_ASCENDING_ORDER;

        // act/assert
        Assert.assertEquals(0, cmp.compare(Vector2D.of(1, 2), Vector2D.of(1, 2)));

        Assert.assertEquals(-1, cmp.compare(Vector2D.of(0, 2), Vector2D.of(1, 2)));
        Assert.assertEquals(-1, cmp.compare(Vector2D.of(1, 1), Vector2D.of(1, 2)));

        Assert.assertEquals(1, cmp.compare(Vector2D.of(2, 2), Vector2D.of(1, 2)));
        Assert.assertEquals(1, cmp.compare(Vector2D.of(1, 3), Vector2D.of(1, 2)));

        Assert.assertEquals(-1, cmp.compare(Vector2D.of(1, 3), null));
        Assert.assertEquals(1, cmp.compare(null, Vector2D.of(1, 2)));
        Assert.assertEquals(0, cmp.compare(null, null));
    }

    @Test
    public void testCoordinates() {
        // arrange
        Vector2D v = Vector2D.of(1, 2);

        // act/assert
        Assert.assertEquals(1.0, v.getX(), EPS);
        Assert.assertEquals(2.0, v.getY(), EPS);
    }

    @Test
    public void testToArray() {
        // arrange
        Vector2D oneTwo = Vector2D.of(1, 2);

        // act
        double[] array = oneTwo.toArray();

        // assert
        Assert.assertEquals(2, array.length);
        Assert.assertEquals(1.0, array[0], EPS);
        Assert.assertEquals(2.0, array[1], EPS);
    }

    @Test
    public void testDimension() {
        // arrange
        Vector2D v = Vector2D.of(1, 2);

        // act/assert
        Assert.assertEquals(2, v.getDimension());
    }

    @Test
    public void testNaN() {
        // act/assert
        Assert.assertTrue(Vector2D.of(0, Double.NaN).isNaN());
        Assert.assertTrue(Vector2D.of(Double.NaN, 0).isNaN());

        Assert.assertFalse(Vector2D.of(1, 1).isNaN());
        Assert.assertFalse(Vector2D.of(1, Double.NEGATIVE_INFINITY).isNaN());
        Assert.assertFalse(Vector2D.of(Double.POSITIVE_INFINITY, 1).isNaN());
    }

    @Test
    public void testInfinite() {
        // act/assert
        Assert.assertTrue(Vector2D.of(0, Double.NEGATIVE_INFINITY).isInfinite());
        Assert.assertTrue(Vector2D.of(Double.NEGATIVE_INFINITY, 0).isInfinite());
        Assert.assertTrue(Vector2D.of(0, Double.POSITIVE_INFINITY).isInfinite());
        Assert.assertTrue(Vector2D.of(Double.POSITIVE_INFINITY, 0).isInfinite());

        Assert.assertFalse(Vector2D.of(1, 1).isInfinite());
        Assert.assertFalse(Vector2D.of(0, Double.NaN).isInfinite());
        Assert.assertFalse(Vector2D.of(Double.NEGATIVE_INFINITY, Double.NaN).isInfinite());
        Assert.assertFalse(Vector2D.of(Double.NaN, Double.NEGATIVE_INFINITY).isInfinite());
        Assert.assertFalse(Vector2D.of(Double.POSITIVE_INFINITY, Double.NaN).isInfinite());
        Assert.assertFalse(Vector2D.of(Double.NaN, Double.POSITIVE_INFINITY).isInfinite());
    }

    @Test
    public void testFinite() {
        // act/assert
        Assert.assertTrue(Vector2D.ZERO.isFinite());
        Assert.assertTrue(Vector2D.of(1, 1).isFinite());

        Assert.assertFalse(Vector2D.of(0, Double.NEGATIVE_INFINITY).isFinite());
        Assert.assertFalse(Vector2D.of(Double.NEGATIVE_INFINITY, 0).isFinite());
        Assert.assertFalse(Vector2D.of(0, Double.POSITIVE_INFINITY).isFinite());
        Assert.assertFalse(Vector2D.of(Double.POSITIVE_INFINITY, 0).isFinite());

        Assert.assertFalse(Vector2D.of(0, Double.NaN).isFinite());
        Assert.assertFalse(Vector2D.of(Double.NEGATIVE_INFINITY, Double.NaN).isFinite());
        Assert.assertFalse(Vector2D.of(Double.NaN, Double.NEGATIVE_INFINITY).isFinite());
        Assert.assertFalse(Vector2D.of(Double.POSITIVE_INFINITY, Double.NaN).isFinite());
        Assert.assertFalse(Vector2D.of(Double.NaN, Double.POSITIVE_INFINITY).isFinite());
    }

    @Test
    public void testGetZero() {
        // act/assert
        checkVector(Vector2D.of(1.0, 1.0).getZero(), 0, 0);
    }

    @Test
    public void testNorm() {
        // act/assert
        Assert.assertEquals(0.0, Vector2D.of(0, 0).norm(), EPS);

        Assert.assertEquals(5.0, Vector2D.of(3, 4).norm(), EPS);
        Assert.assertEquals(5.0, Vector2D.of(3, -4).norm(), EPS);
        Assert.assertEquals(5.0, Vector2D.of(-3, 4).norm(), EPS);
        Assert.assertEquals(5.0, Vector2D.of(-3, -4).norm(), EPS);

        Assert.assertEquals(Math.sqrt(5.0), Vector2D.of(-1, -2).norm(), EPS);
    }

    @Test
    public void testNorm_unitVectors() {
        // arrange
        Vector2D v = Vector2D.of(2.0, 3.0).normalize();

        // act/assert
        Assert.assertEquals(1.0, v.norm(), 0.0);
    }

    @Test
    public void testNormSq() {
        // act/assert
        Assert.assertEquals(0.0, Vector2D.of(0, 0).normSq(), EPS);

        Assert.assertEquals(25.0, Vector2D.of(3, 4).normSq(), EPS);
        Assert.assertEquals(25.0, Vector2D.of(3, -4).normSq(), EPS);
        Assert.assertEquals(25.0, Vector2D.of(-3, 4).normSq(), EPS);
        Assert.assertEquals(25.0, Vector2D.of(-3, -4).normSq(), EPS);

        Assert.assertEquals(5.0, Vector2D.of(-1, -2).normSq(), EPS);
    }

    @Test
    public void testNormSq_unitVectors() {
        // arrange
        Vector2D v = Vector2D.of(2.0, 3.0).normalize();

        // act/assert
        Assert.assertEquals(1.0, v.normSq(), 0.0);
    }

    @Test
    public void testWithNorm() {
        // act/assert
        checkVector(Vector2D.of(3, 4).withNorm(1.0), 0.6, 0.8);
        checkVector(Vector2D.of(4, 3).withNorm(1.0), 0.8, 0.6);

        checkVector(Vector2D.of(-3, 4).withNorm(0.5), -0.3, 0.4);
        checkVector(Vector2D.of(3, -4).withNorm(2.0), 1.2, -1.6);
        checkVector(Vector2D.of(-3, -4).withNorm(3.0), -1.8, 3.0 * Math.sin(Math.atan2(-4, -3)));

        checkVector(Vector2D.of(0.5, 0.5).withNorm(2), Math.sqrt(2), Math.sqrt(2));
    }

    @Test
    public void testWithNorm_illegalNorm() {
        // act/assert
        GeometryTestUtils.assertThrows(() -> Vector2D.ZERO.withNorm(2.0),
                IllegalNormException.class);
        GeometryTestUtils.assertThrows(() -> Vector2D.NaN.withNorm(2.0),
                IllegalNormException.class);
        GeometryTestUtils.assertThrows(() -> Vector2D.POSITIVE_INFINITY.withNorm(2.0),
                IllegalNormException.class);
        GeometryTestUtils.assertThrows(() -> Vector2D.NEGATIVE_INFINITY.withNorm(2.0),
                IllegalNormException.class);
    }

    @Test
    public void testWithNorm_unitVectors() {
        // arrange
        double eps = 1e-14;
        Vector2D v = Vector2D.of(2.0, -3.0).normalize();

        // act/assert
        checkVector(Vector2D.Unit.PLUS_X.withNorm(2.5), 2.5, 0.0);
        checkVector(Vector2D.Unit.MINUS_Y.withNorm(3.14), 0.0, -3.14);

        for (int i = -10; i <= 10; i++) {
            final double mag = i;
            Assert.assertEquals(Math.abs(mag), v.withNorm(mag).norm(), eps);
        }
    }

    @Test
    public void testAdd() {
        // arrange
        Vector2D v1 = Vector2D.of(-1, 2);
        Vector2D v2 = Vector2D.of(3, -4);
        Vector2D v3 = Vector2D.of(5, 6);

        // act/assert
        checkVector(v1.add(v1), -2, 4);

        checkVector(v1.add(v2), 2, -2);
        checkVector(v2.add(v1), 2, -2);

        checkVector(v1.add(v3), 4, 8);
        checkVector(v3.add(v1), 4, 8);
    }

    @Test
    public void testAdd_scaled() {
        // arrange
        Vector2D v1 = Vector2D.of(-1, 2);
        Vector2D v2 = Vector2D.of(3, -4);
        Vector2D v3 = Vector2D.of(5, 6);

        // act/assert
        checkVector(v1.add(2, v1), -3, 6);

        checkVector(v1.add(0, v2), -1, 2);
        checkVector(v2.add(1, v1), 2, -2);

        checkVector(v1.add(-1, v3), -6, -4);
        checkVector(v3.add(-2, v1), 7, 2);
    }

    @Test
    public void testSubtract() {
        // arrange
        Vector2D v1 = Vector2D.of(-1, 2);
        Vector2D v2 = Vector2D.of(3, -4);
        Vector2D v3 = Vector2D.of(5, 6);

        // act/assert
        checkVector(v1.subtract(v1), 0, 0);

        checkVector(v1.subtract(v2), -4, 6);
        checkVector(v2.subtract(v1), 4, -6);

        checkVector(v1.subtract(v3), -6, -4);
        checkVector(v3.subtract(v1), 6, 4);
    }

    @Test
    public void testSubtract_scaled() {
        // arrange
        Vector2D v1 = Vector2D.of(-1, 2);
        Vector2D v2 = Vector2D.of(3, -4);
        Vector2D v3 = Vector2D.of(5, 6);

        // act/assert
        checkVector(v1.subtract(2, v1), 1, -2);

        checkVector(v1.subtract(0, v2), -1, 2);
        checkVector(v2.subtract(1, v1), 4, -6);

        checkVector(v1.subtract(-1, v3), 4, 8);
        checkVector(v3.subtract(-2, v1), 3, 10);
    }

    @Test
    public void testNormalize() {
        // act/assert
        checkVector(Vector2D.of(100, 0).normalize(), 1, 0);
        checkVector(Vector2D.of(-100, 0).normalize(), -1, 0);
        checkVector(Vector2D.of(0, 100).normalize(), 0, 1);
        checkVector(Vector2D.of(0, -100).normalize(), 0, -1);
        checkVector(Vector2D.of(-1, 2).normalize(), -1.0 / Math.sqrt(5), 2.0 / Math.sqrt(5));
    }

    @Test
    public void testNormalize_illegalNorm() {
        // act/assert
        GeometryTestUtils.assertThrows(() -> Vector2D.ZERO.normalize(),
                IllegalNormException.class);
        GeometryTestUtils.assertThrows(() -> Vector2D.NaN.normalize(),
                IllegalNormException.class);
        GeometryTestUtils.assertThrows(() -> Vector2D.POSITIVE_INFINITY.normalize(),
                IllegalNormException.class);
        GeometryTestUtils.assertThrows(() -> Vector2D.NEGATIVE_INFINITY.normalize(),
                IllegalNormException.class);
    }

    @Test
    public void testNormalize_isIdempotent() {
        // arrange
        double invSqrt2 = 1.0 / Math.sqrt(2);
        Vector2D v = Vector2D.of(2, 2).normalize();

        // act/assert
        Assert.assertSame(v, v.normalize());
        checkVector(v.normalize(), invSqrt2, invSqrt2);
    }

    @Test
    public void testNegate() {
        // act/assert
        checkVector(Vector2D.of(1, 2).negate(), -1, -2);
        checkVector(Vector2D.of(-3, -4).negate(), 3, 4);
        checkVector(Vector2D.of(5, -6).negate().negate(), 5, -6);
    }

    @Test
    public void testNegate_unitVectors() {
        // arrange
        Vector2D v1 = Vector2D.of(1.0, 1.0).normalize();
        Vector2D v2 = Vector2D.of(-1.0, -2.0).normalize();
        Vector2D v3 = Vector2D.of(2.0, -3.0).normalize();

        // act/assert
        checkVector(v1.negate(), -1.0 / Math.sqrt(2.0), -1.0 / Math.sqrt(2.0));
        checkVector(v2.negate(), 1.0 / Math.sqrt(5.0), 2.0 / Math.sqrt(5.0));
        checkVector(v3.negate(), -2.0 / Math.sqrt(13.0), 3.0 / Math.sqrt(13.0));
    }

    @Test
    public void testScalarMultiply() {
        // act/assert
        checkVector(Vector2D.of(1, 2).multiply(0), 0, 0);

        checkVector(Vector2D.of(1, 2).multiply(3), 3, 6);
        checkVector(Vector2D.of(1, 2).multiply(-3), -3, -6);

        checkVector(Vector2D.of(2, 3).multiply(1.5), 3, 4.5);
        checkVector(Vector2D.of(2, 3).multiply(-1.5), -3, -4.5);
    }

    @Test
    public void testDistance() {
        // arrange
        Vector2D v1 = Vector2D.of(1, 1);
        Vector2D v2 = Vector2D.of(4, 5);
        Vector2D v3 = Vector2D.of(-1, 0);

        // act/assert
        Assert.assertEquals(0, v1.distance(v1), EPS);

        Assert.assertEquals(5, v1.distance(v2), EPS);
        Assert.assertEquals(5, v2.distance(v1), EPS);

        Assert.assertEquals(Math.sqrt(5), v1.distance(v3), EPS);
        Assert.assertEquals(Math.sqrt(5), v3.distance(v1), EPS);
    }

    @Test
    public void testDistanceSq() {
        // arrange
        Vector2D v1 = Vector2D.of(1, 1);
        Vector2D v2 = Vector2D.of(4, 5);
        Vector2D v3 = Vector2D.of(-1, 0);

        // act/assert
        Assert.assertEquals(0, v1.distanceSq(v1), EPS);

        Assert.assertEquals(25, v1.distanceSq(v2), EPS);
        Assert.assertEquals(25, v2.distanceSq(v1), EPS);

        Assert.assertEquals(5, v1.distanceSq(v3), EPS);
        Assert.assertEquals(5, v3.distanceSq(v1), EPS);
    }

    @Test
    public void testDotProduct() {
        // arrange
        Vector2D v1 = Vector2D.of(1, 1);
        Vector2D v2 = Vector2D.of(4, 5);
        Vector2D v3 = Vector2D.of(-1, 0);

        // act/assert
        Assert.assertEquals(2, v1.dot(v1), EPS);
        Assert.assertEquals(41, v2.dot(v2), EPS);
        Assert.assertEquals(1, v3.dot(v3), EPS);

        Assert.assertEquals(9, v1.dot(v2), EPS);
        Assert.assertEquals(9, v2.dot(v1), EPS);

        Assert.assertEquals(-1, v1.dot(v3), EPS);
        Assert.assertEquals(-1, v3.dot(v1), EPS);

        Assert.assertEquals(1, Vector2D.Unit.PLUS_X.dot(Vector2D.Unit.PLUS_X), EPS);
        Assert.assertEquals(0, Vector2D.Unit.PLUS_X.dot(Vector2D.Unit.PLUS_Y), EPS);
        Assert.assertEquals(-1, Vector2D.Unit.PLUS_X.dot(Vector2D.Unit.MINUS_X), EPS);
        Assert.assertEquals(0, Vector2D.Unit.PLUS_X.dot(Vector2D.Unit.MINUS_Y), EPS);
    }

    @Test
    public void testOrthogonal() {
        // arrange
        double invSqrt2 = 1.0 / Math.sqrt(2.0);

        // act/assert
        checkVector(Vector2D.Unit.PLUS_X.orthogonal(), 0.0, 1.0);
        checkVector(Vector2D.of(1.0, 1.0).orthogonal(), -invSqrt2, invSqrt2);

        checkVector(Vector2D.Unit.PLUS_Y.orthogonal(), -1.0, 0.0);
        checkVector(Vector2D.of(-1.0, 1.0).orthogonal(), -invSqrt2, -invSqrt2);

        checkVector(Vector2D.Unit.MINUS_X.orthogonal(), 0.0, -1.0);
        checkVector(Vector2D.of(-1.0, -1.0).orthogonal(), invSqrt2, -invSqrt2);

        checkVector(Vector2D.Unit.MINUS_Y.orthogonal(), 1.0, 0.0);
        checkVector(Vector2D.of(1.0, -1.0).orthogonal(), invSqrt2, invSqrt2);
    }

    @Test
    public void testOrthogonal_fullCircle() {
        for (double az = 0.0; az<=PlaneAngleRadians.TWO_PI; az += 0.25) {
            // arrange
            Vector2D v = PolarCoordinates.toCartesian(Math.PI, az);

            //act
            Vector2D ortho = v.orthogonal();

            // assert
            Assert.assertEquals(1.0, ortho.norm(), EPS);
            Assert.assertEquals(0.0, v.dot(ortho), EPS);
        }
    }

    @Test
    public void testOrthogonal_illegalNorm() {
        // act/assert
        GeometryTestUtils.assertThrows(() -> Vector2D.ZERO.orthogonal(),
                IllegalNormException.class);
        GeometryTestUtils.assertThrows(() -> Vector2D.NaN.orthogonal(),
                IllegalNormException.class);
        GeometryTestUtils.assertThrows(() -> Vector2D.POSITIVE_INFINITY.orthogonal(),
                IllegalNormException.class);
        GeometryTestUtils.assertThrows(() -> Vector2D.NEGATIVE_INFINITY.orthogonal(),
                IllegalNormException.class);
    }

    @Test
    public void testOrthogonal_givenDirection() {
        // arrange
        double invSqrt2 = 1.0 / Math.sqrt(2.0);

        // act/assert
        checkVector(Vector2D.Unit.PLUS_X.orthogonal(Vector2D.of(-1.0, 0.1)), 0.0, 1.0);
        checkVector(Vector2D.Unit.PLUS_Y.orthogonal(Vector2D.of(2.0, 2.0)), 1.0, 0.0);

        checkVector(Vector2D.of(2.9, 2.9).orthogonal(Vector2D.of(1.0, 0.22)), invSqrt2, -invSqrt2);
        checkVector(Vector2D.of(2.9, 2.9).orthogonal(Vector2D.of(0.22, 1.0)), -invSqrt2, invSqrt2);
    }

    @Test
    public void testOrthogonal_givenDirection_illegalNorm() {
        // act/assert
        GeometryTestUtils.assertThrows(() -> Vector2D.ZERO.orthogonal(Vector2D.Unit.PLUS_X),
                IllegalNormException.class);
        GeometryTestUtils.assertThrows(() -> Vector2D.NaN.orthogonal(Vector2D.Unit.PLUS_X),
                IllegalNormException.class);
        GeometryTestUtils.assertThrows(() -> Vector2D.POSITIVE_INFINITY.orthogonal(Vector2D.Unit.PLUS_X),
                IllegalNormException.class);
        GeometryTestUtils.assertThrows(() -> Vector2D.NEGATIVE_INFINITY.orthogonal(Vector2D.Unit.PLUS_X),
                IllegalNormException.class);

        GeometryTestUtils.assertThrows(() -> Vector2D.Unit.PLUS_X.orthogonal(Vector2D.ZERO),
                IllegalNormException.class);
        GeometryTestUtils.assertThrows(() -> Vector2D.Unit.PLUS_X.orthogonal(Vector2D.NaN),
                IllegalNormException.class);
        GeometryTestUtils.assertThrows(() -> Vector2D.Unit.PLUS_X.orthogonal(Vector2D.POSITIVE_INFINITY),
                IllegalNormException.class);
        GeometryTestUtils.assertThrows(() -> Vector2D.Unit.PLUS_X.orthogonal(Vector2D.NEGATIVE_INFINITY),
                IllegalNormException.class);
    }

    @Test
    public void testOrthogonal_givenDirection_directionIsCollinear() {
        // act/assert
        GeometryTestUtils.assertThrows(() -> Vector2D.Unit.PLUS_X.orthogonal(Vector2D.Unit.PLUS_X),
                IllegalNormException.class);
        GeometryTestUtils.assertThrows(() -> Vector2D.Unit.PLUS_X.orthogonal(Vector2D.Unit.MINUS_X),
                IllegalNormException.class);
        GeometryTestUtils.assertThrows(() -> Vector2D.of(1.0, 1.0).orthogonal(Vector2D.of(2.0, 2.0)),
                IllegalNormException.class);
        GeometryTestUtils.assertThrows(() -> Vector2D.of(-1.01, -1.01).orthogonal(Vector2D.of(20.1, 20.1)),
                IllegalNormException.class);
    }

    @Test
    public void testAngle() {
        // act/assert
        Assert.assertEquals(0, Vector2D.Unit.PLUS_X.angle(Vector2D.Unit.PLUS_X), EPS);

        Assert.assertEquals(PlaneAngleRadians.PI, Vector2D.Unit.PLUS_X.angle(Vector2D.Unit.MINUS_X), EPS);
        Assert.assertEquals(PlaneAngleRadians.PI_OVER_TWO, Vector2D.Unit.PLUS_X.angle(Vector2D.Unit.PLUS_Y), EPS);
        Assert.assertEquals(PlaneAngleRadians.PI_OVER_TWO, Vector2D.Unit.PLUS_X.angle(Vector2D.Unit.MINUS_Y), EPS);

        Assert.assertEquals(PlaneAngleRadians.PI / 4, Vector2D.of(1, 1).angle(Vector2D.of(1, 0)), EPS);
        Assert.assertEquals(PlaneAngleRadians.PI / 4, Vector2D.of(1, 0).angle(Vector2D.of(1, 1)), EPS);

        Assert.assertEquals(0.004999958333958323, Vector2D.of(20.0, 0.0).angle(Vector2D.of(20.0, 0.1)), EPS);
    }


    @Test
    public void testAngle_illegalNorm() {
        // arrange
        Vector2D v = Vector2D.of(1.0, 1.0);

        // act/assert
        GeometryTestUtils.assertThrows(() -> Vector2D.ZERO.angle(v),
                IllegalNormException.class);
        GeometryTestUtils.assertThrows(() -> Vector2D.NaN.angle(v),
                IllegalNormException.class);
        GeometryTestUtils.assertThrows(() -> Vector2D.POSITIVE_INFINITY.angle(v),
                IllegalNormException.class);
        GeometryTestUtils.assertThrows(() -> Vector2D.NEGATIVE_INFINITY.angle(v),
                IllegalNormException.class);

        GeometryTestUtils.assertThrows(() -> v.angle(Vector2D.ZERO),
                IllegalNormException.class);
        GeometryTestUtils.assertThrows(() -> v.angle(Vector2D.NaN),
                IllegalNormException.class);
        GeometryTestUtils.assertThrows(() -> v.angle(Vector2D.POSITIVE_INFINITY),
                IllegalNormException.class);
        GeometryTestUtils.assertThrows(() -> v.angle(Vector2D.NEGATIVE_INFINITY),
                IllegalNormException.class);
    }

    @Test
    public void testSignedArea() {
        // arrange
        double eps = 1e-10;

        Vector2D a = Vector2D.Unit.PLUS_X;
        Vector2D b = Vector2D.Unit.PLUS_Y;
        Vector2D c = Vector2D.of(1, 1).withNorm(2.0);
        Vector2D d = Vector2D.of(-1, 1).withNorm(3.0);

        // act/assert
        Assert.assertEquals(1.0, a.signedArea(b), eps);
        Assert.assertEquals(-1.0, b.signedArea(a), eps);

        double xAxisAndCArea = 2 * Math.cos(0.25 * PlaneAngleRadians.PI);
        Assert.assertEquals(xAxisAndCArea, a.signedArea(c), eps);
        Assert.assertEquals(-xAxisAndCArea, c.signedArea(a), eps);

        double xAxisAndDArea = 3 * Math.cos(0.25 * PlaneAngleRadians.PI);
        Assert.assertEquals(xAxisAndDArea, a.signedArea(d), eps);
        Assert.assertEquals(-xAxisAndDArea, d.signedArea(a), eps);

        Assert.assertEquals(6.0, c.signedArea(d), eps);
        Assert.assertEquals(-6.0, d.signedArea(c), eps);
    }

    @Test
    public void testSignedArea_collinear() {
        // arrange
        Vector2D a = Vector2D.Unit.PLUS_X;
        Vector2D b = Vector2D.Unit.PLUS_Y;
        Vector2D c = Vector2D.of(-3, 8);

        // act/assert
        Assert.assertEquals(0.0, a.signedArea(a), EPS);
        Assert.assertEquals(0.0, b.signedArea(b), EPS);
        Assert.assertEquals(0.0, c.signedArea(c), EPS);

        Assert.assertEquals(0.0, a.signedArea(a.multiply(100.0)), EPS);
        Assert.assertEquals(0.0, b.signedArea(b.negate()), EPS);
        Assert.assertEquals(0.0, c.signedArea(c.multiply(-0.03)), EPS);
    }

    @Test
    public void testProject() {
        // arrange
        Vector2D v1 = Vector2D.of(3.0, 4.0);
        Vector2D v2 = Vector2D.of(1.0, 4.0);

        // act/assert
        checkVector(Vector2D.ZERO.project(v1), 0.0, 0.0);

        checkVector(v1.project(v1), 3.0, 4.0);
        checkVector(v1.project(v1.negate()), 3.0, 4.0);

        checkVector(v1.project(Vector2D.Unit.PLUS_X), 3.0, 0.0);
        checkVector(v1.project(Vector2D.Unit.MINUS_X), 3.0, 0.0);

        checkVector(v1.project(Vector2D.Unit.PLUS_Y), 0.0, 4.0);
        checkVector(v1.project(Vector2D.Unit.MINUS_Y), 0.0, 4.0);

        checkVector(v2.project(v1), (19.0 / 25.0) * 3.0, (19.0 / 25.0) * 4.0);
    }

    @Test
    public void testProject_baseHasIllegalNorm() {
        // arrange
        Vector2D v = Vector2D.of(1.0, 1.0);

        // act/assert
        GeometryTestUtils.assertThrows(() -> v.project(Vector2D.ZERO),
                IllegalNormException.class);
        GeometryTestUtils.assertThrows(() -> v.project(Vector2D.NaN),
                IllegalNormException.class);
        GeometryTestUtils.assertThrows(() -> v.project(Vector2D.POSITIVE_INFINITY),
                IllegalNormException.class);
        GeometryTestUtils.assertThrows(() -> v.project(Vector2D.NEGATIVE_INFINITY),
                IllegalNormException.class);
    }

    @Test
    public void testReject() {
        // arrange
        Vector2D v1 = Vector2D.of(3.0, 4.0);
        Vector2D v2 = Vector2D.of(1.0, 4.0);

        // act/assert
        checkVector(Vector2D.ZERO.reject(v1), 0.0, 0.0);

        checkVector(v1.reject(v1), 0.0, 0.0);
        checkVector(v1.reject(v1.negate()), 0.0, 0.0);

        checkVector(v1.reject(Vector2D.Unit.PLUS_X), 0.0, 4.0);
        checkVector(v1.reject(Vector2D.Unit.MINUS_X), 0.0, 4.0);

        checkVector(v1.reject(Vector2D.Unit.PLUS_Y), 3.0, 0.0);
        checkVector(v1.reject(Vector2D.Unit.MINUS_Y), 3.0, 0.0);

        checkVector(v2.reject(v1), (-32.0 / 25.0), (6.0 / 25.0) * 4.0);
    }

    @Test
    public void testReject_baseHasIllegalNorm() {
        // arrange
        Vector2D v = Vector2D.of(1.0, 1.0);

        // act/assert
        GeometryTestUtils.assertThrows(() -> v.reject(Vector2D.ZERO),
                IllegalNormException.class);
        GeometryTestUtils.assertThrows(() -> v.reject(Vector2D.NaN),
                IllegalNormException.class);
        GeometryTestUtils.assertThrows(() -> v.reject(Vector2D.POSITIVE_INFINITY),
                IllegalNormException.class);
        GeometryTestUtils.assertThrows(() -> v.reject(Vector2D.NEGATIVE_INFINITY),
                IllegalNormException.class);
    }

    @Test
    public void testProjectAndReject_areComplementary() {
        // arrange
        double eps = 1e-12;

        // act/assert
        checkProjectAndRejectFullCircle(Vector2D.of(1.0, 0.0), 1.0, eps);
        checkProjectAndRejectFullCircle(Vector2D.of(0.0, 1.0), 2.0, eps);
        checkProjectAndRejectFullCircle(Vector2D.of(1.0, 1.0), 3.0, eps);

        checkProjectAndRejectFullCircle(Vector2D.of(-2.0, 0.0), 4.0, eps);
        checkProjectAndRejectFullCircle(Vector2D.of(0.0, -2.0), 5.0, eps);
        checkProjectAndRejectFullCircle(Vector2D.of(-2.0, -2.0), 6.0, eps);
    }

    private void checkProjectAndRejectFullCircle(Vector2D vec, double baseMag, double eps) {
        for (double theta = 0.0; theta <= PlaneAngleRadians.TWO_PI; theta += 0.5) {
            Vector2D base = PolarCoordinates.toCartesian(baseMag, theta);

            Vector2D proj = vec.project(base);
            Vector2D rej = vec.reject(base);

            // ensure that the projection and rejection sum to the original vector
            EuclideanTestUtils.assertCoordinatesEqual(vec, proj.add(rej), eps);

            double angle = base.angle(vec);

            // check the angle between the projection and the base; this will
            // be undefined when the angle between the original vector and the
            // base is pi/2 (which means that the projection is the zero vector)
            if (angle < PlaneAngleRadians.PI_OVER_TWO) {
                Assert.assertEquals(0.0, proj.angle(base), eps);
            }
            else if (angle > PlaneAngleRadians.PI_OVER_TWO) {
                Assert.assertEquals(PlaneAngleRadians.PI, proj.angle(base), eps);
            }

            // check the angle between the rejection and the base; this should
            // always be pi/2 except for when the angle between the original vector
            // and the base is 0 or pi, in which case the rejection is the zero vector.
            if (angle > 0.0 && angle < PlaneAngleRadians.PI) {
                Assert.assertEquals(PlaneAngleRadians.PI_OVER_TWO, rej.angle(base), eps);
            }
        }
    }

    @Test
    public void testVectorTo() {
        // arrange
        Vector2D p1 = Vector2D.of(1, 1);
        Vector2D p2 = Vector2D.of(4, 5);
        Vector2D p3 = Vector2D.of(-1, 0);

        // act/assert
        checkVector(p1.vectorTo(p1), 0, 0);
        checkVector(p1.vectorTo(p2), 3, 4);
        checkVector(p2.vectorTo(p1), -3, -4);

        checkVector(p1.vectorTo(p3), -2, -1);
        checkVector(p3.vectorTo(p1), 2, 1);
    }

    @Test
    public void testDirectionTo() {
        // act/assert
        double invSqrt2 = 1.0 / Math.sqrt(2);

        Vector2D p1 = Vector2D.of(1, 1);
        Vector2D p2 = Vector2D.of(1, 5);
        Vector2D p3 = Vector2D.of(-2, -2);

        // act/assert
        checkVector(p1.directionTo(p2), 0, 1);
        checkVector(p2.directionTo(p1), 0, -1);

        checkVector(p1.directionTo(p3), -invSqrt2, -invSqrt2);
        checkVector(p3.directionTo(p1), invSqrt2, invSqrt2);
    }

    @Test
    public void testDirectionTo_illegalNorm() {
        // arrange
        Vector2D p = Vector2D.of(1, 2);

        // act/assert
        GeometryTestUtils.assertThrows(() -> Vector2D.ZERO.directionTo(Vector2D.ZERO),
                IllegalNormException.class);
        GeometryTestUtils.assertThrows(() -> p.directionTo(p),
                IllegalNormException.class);
        GeometryTestUtils.assertThrows(() -> p.directionTo(Vector2D.NaN),
                IllegalNormException.class);
        GeometryTestUtils.assertThrows(() -> Vector2D.NEGATIVE_INFINITY.directionTo(p),
                IllegalNormException.class);
        GeometryTestUtils.assertThrows(() -> p.directionTo(Vector2D.POSITIVE_INFINITY),
                IllegalNormException.class);
    }

    @Test
    public void testLerp() {
        // arrange
        Vector2D v1 = Vector2D.of(1, -5);
        Vector2D v2 = Vector2D.of(-4, 0);
        Vector2D v3 = Vector2D.of(10, -4);

        // act/assert
        checkVector(v1.lerp(v1, 0), 1, -5);
        checkVector(v1.lerp(v1, 1), 1, -5);

        checkVector(v1.lerp(v2, -0.25), 2.25, -6.25);
        checkVector(v1.lerp(v2, 0), 1, -5);
        checkVector(v1.lerp(v2, 0.25), -0.25, -3.75);
        checkVector(v1.lerp(v2, 0.5), -1.5, -2.5);
        checkVector(v1.lerp(v2, 0.75), -2.75, -1.25);
        checkVector(v1.lerp(v2, 1), -4, 0);
        checkVector(v1.lerp(v2, 1.25), -5.25, 1.25);

        checkVector(v1.lerp(v3, 0), 1, -5);
        checkVector(v1.lerp(v3, 0.25), 3.25, -4.75);
        checkVector(v1.lerp(v3, 0.5), 5.5, -4.5);
        checkVector(v1.lerp(v3, 0.75), 7.75, -4.25);
        checkVector(v1.lerp(v3, 1), 10, -4);
    }

    @Test
    public void testTransform() {
        // arrange
        AffineTransformMatrix2D transform = AffineTransformMatrix2D.identity()
                .scale(2)
                .translate(1, 2);

        Vector2D v1 = Vector2D.of(1, 2);
        Vector2D v2 = Vector2D.of(-4, -5);

        // act/assert
        checkVector(v1.transform(transform), 3, 6);
        checkVector(v2.transform(transform), -7, -8);
    }

    @Test
    public void testPrecisionEquals() {
        // arrange
        DoublePrecisionContext smallEps = new EpsilonDoublePrecisionContext(1e-6);
        DoublePrecisionContext largeEps = new EpsilonDoublePrecisionContext(1e-1);

        Vector2D vec = Vector2D.of(1, -2);

        // act/assert
        Assert.assertTrue(vec.eq(vec, smallEps));
        Assert.assertTrue(vec.eq(vec, largeEps));

        Assert.assertTrue(vec.eq(Vector2D.of(1.0000007, -2.0000009), smallEps));
        Assert.assertTrue(vec.eq(Vector2D.of(1.0000007, -2.0000009), largeEps));

        Assert.assertFalse(vec.eq(Vector2D.of(1.004, -2), smallEps));
        Assert.assertFalse(vec.eq(Vector2D.of(1, -2.004), smallEps));
        Assert.assertTrue(vec.eq(Vector2D.of(1.004, -2.004), largeEps));

        Assert.assertFalse(vec.eq(Vector2D.of(1, -3), smallEps));
        Assert.assertFalse(vec.eq(Vector2D.of(2, -2), smallEps));
        Assert.assertFalse(vec.eq(Vector2D.of(1, -3), largeEps));
        Assert.assertFalse(vec.eq(Vector2D.of(2, -2), largeEps));
    }

    @Test
    public void testIsZero() {
        // arrange
        DoublePrecisionContext smallEps = new EpsilonDoublePrecisionContext(1e-6);
        DoublePrecisionContext largeEps = new EpsilonDoublePrecisionContext(1e-1);

        // act/assert
        Assert.assertTrue(Vector2D.of(0.0, -0.0).isZero(smallEps));
        Assert.assertTrue(Vector2D.of(-0.0, 0.0).isZero(largeEps));

        Assert.assertTrue(Vector2D.of(-1e-7, 1e-7).isZero(smallEps));
        Assert.assertTrue(Vector2D.of(1e-7, 1e-7).isZero(largeEps));

        Assert.assertFalse(Vector2D.of(1e-2, 0.0).isZero(smallEps));
        Assert.assertFalse(Vector2D.of(0.0, 1e-2).isZero(smallEps));
        Assert.assertTrue(Vector2D.of(1e-2, -1e-2).isZero(largeEps));

        Assert.assertFalse(Vector2D.of(0.2, 0.0).isZero(smallEps));
        Assert.assertFalse(Vector2D.of(0.0, 0.2).isZero(smallEps));
        Assert.assertFalse(Vector2D.of(0.2, 0.2).isZero(smallEps));
        Assert.assertFalse(Vector2D.of(-0.2, 0.0).isZero(largeEps));
        Assert.assertFalse(Vector2D.of(0.0, -0.2).isZero(largeEps));
        Assert.assertFalse(Vector2D.of(-0.2, -0.2).isZero(largeEps));
    }

    @Test
    public void testHashCode() {
        // arrange
        Vector2D u = Vector2D.of(1, 1);
        Vector2D v = Vector2D.of(1 + 10 * Precision.EPSILON, 1 + 10 * Precision.EPSILON);
        Vector2D w = Vector2D.of(1, 1);

        // act/assert
        Assert.assertTrue(u.hashCode() != v.hashCode());
        Assert.assertEquals(u.hashCode(), w.hashCode());

        Assert.assertEquals(Vector2D.of(0, Double.NaN).hashCode(), Vector2D.NaN.hashCode());
        Assert.assertEquals(Vector2D.of(Double.NaN, 0).hashCode(), Vector2D.NaN.hashCode());
        Assert.assertEquals(Vector2D.of(0, Double.NaN).hashCode(), Vector2D.of(Double.NaN, 0).hashCode());
    }

    @Test
    public void testEquals() {
        // arrange
        Vector2D u1 = Vector2D.of(1, 2);
        Vector2D u2 = Vector2D.of(1, 2);

        // act/assert
        Assert.assertFalse(u1.equals(null));
        Assert.assertFalse(u1.equals(new Object()));

        Assert.assertTrue(u1.equals(u1));
        Assert.assertTrue(u1.equals(u2));

        Assert.assertFalse(u1.equals(Vector2D.of(-1, -2)));
        Assert.assertFalse(u1.equals(Vector2D.of(1 + 10 * Precision.EPSILON, 2)));
        Assert.assertFalse(u1.equals(Vector2D.of(1, 2 + 10 * Precision.EPSILON)));

        Assert.assertTrue(Vector2D.of(0, Double.NaN).equals(Vector2D.of(Double.NaN, 0)));

        Assert.assertTrue(Vector2D.of(0, Double.POSITIVE_INFINITY).equals(Vector2D.of(0, Double.POSITIVE_INFINITY)));
        Assert.assertFalse(Vector2D.of(Double.POSITIVE_INFINITY, 0).equals(Vector2D.of(0, Double.POSITIVE_INFINITY)));

        Assert.assertTrue(Vector2D.of(Double.NEGATIVE_INFINITY, 0).equals(Vector2D.of(Double.NEGATIVE_INFINITY, 0)));
        Assert.assertFalse(Vector2D.of(0, Double.NEGATIVE_INFINITY).equals(Vector2D.of(Double.NEGATIVE_INFINITY, 0)));
    }

    @Test
    public void testToString() {
        // arrange
        Vector2D v = Vector2D.of(1, 2);
        Pattern pattern = Pattern.compile("\\(1.{0,2}, 2.{0,2}\\)");

        // act
        String str = v.toString();

        // assert
        Assert.assertTrue("Expected string " + str + " to match regex " + pattern,
                    pattern.matcher(str).matches());
    }

    @Test
    public void testParse() {
        // act/assert
        checkVector(Vector2D.parse("(1, 2)"), 1, 2);
        checkVector(Vector2D.parse("(-1, -2)"), -1, -2);

        checkVector(Vector2D.parse("(0.01, -1e-3)"), 1e-2, -1e-3);

        checkVector(Vector2D.parse("(NaN, -Infinity)"), Double.NaN, Double.NEGATIVE_INFINITY);

        checkVector(Vector2D.parse(Vector2D.ZERO.toString()), 0, 0);
        checkVector(Vector2D.parse(Vector2D.Unit.MINUS_X.toString()), -1, 0);
    }

    @Test(expected = IllegalArgumentException.class)
    public void testParse_failure() {
        // act/assert
        Vector2D.parse("abc");
    }

    @Test
    public void testOf() {
        // act/assert
        checkVector(Vector2D.of(0, 1), 0, 1);
        checkVector(Vector2D.of(-1, -2), -1, -2);
        checkVector(Vector2D.of(Math.PI, Double.NaN), Math.PI, Double.NaN);
        checkVector(Vector2D.of(Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY), Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY);
    }

    @Test
    public void testOf_arrayArg() {
        // act/assert
        checkVector(Vector2D.of(new double[] { 0, 1 }), 0, 1);
        checkVector(Vector2D.of(new double[] { -1, -2 }), -1, -2);
        checkVector(Vector2D.of(new double[] { Math.PI, Double.NaN }), Math.PI, Double.NaN);
        checkVector(Vector2D.of(new double[] { Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY }), Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY);
    }

    @Test(expected = IllegalArgumentException.class)
    public void testOf_arrayArg_invalidDimensions() {
        // act/assert
        Vector2D.of(new double[] {0.0 });
    }

    @Test
    public void testUnitFrom_coordinates() {
        // arrange
        double invSqrt2 = 1.0 / Math.sqrt(2.0);

        // act/assert
        checkVector(Vector2D.Unit.from(2.0, -2.0), invSqrt2, -invSqrt2);
        checkVector(Vector2D.Unit.from(-4.0, 4.0), -invSqrt2, invSqrt2);
    }

    @Test
    public void testUnitFrom_vector() {
        // arrange
        double invSqrt2 = 1.0 / Math.sqrt(2.0);
        Vector2D vec = Vector2D.of(2.0, -2.0);
        Vector2D.Unit unitVec = Vector2D.Unit.from(2.0, -2.0);

        // act/assert
        checkVector(Vector2D.Unit.from(vec), invSqrt2, -invSqrt2);
        Assert.assertSame(unitVec, Vector2D.Unit.from(unitVec));
    }

    @Test
    public void testUnitFrom_illegalNorm() {
        GeometryTestUtils.assertThrows(() -> Vector2D.Unit.from(0.0, 0.0),
                IllegalNormException.class);
        GeometryTestUtils.assertThrows(() -> Vector2D.Unit.from(Double.NaN, 1.0),
                IllegalNormException.class);
        GeometryTestUtils.assertThrows(() -> Vector2D.Unit.from(1.0, Double.NEGATIVE_INFINITY),
                IllegalNormException.class);
        GeometryTestUtils.assertThrows(() -> Vector2D.Unit.from(1.0, Double.POSITIVE_INFINITY),
                IllegalNormException.class);
    }

    @Test
    public void testLinearCombination1() {
        // arrange
        Vector2D p1 = Vector2D.of(1, 2);

        // act/assert
        checkVector(Vector2D.linearCombination(0, p1), 0, 0);

        checkVector(Vector2D.linearCombination(1, p1), 1, 2);
        checkVector(Vector2D.linearCombination(-1, p1), -1, -2);

        checkVector(Vector2D.linearCombination(0.5, p1), 0.5, 1);
        checkVector(Vector2D.linearCombination(-0.5, p1), -0.5, -1);
    }

    @Test
    public void testLinearCombination2() {
        // arrange
        Vector2D p1 = Vector2D.of(1, 2);
        Vector2D p2 = Vector2D.of(-3, -4);

        // act/assert
        checkVector(Vector2D.linearCombination(2, p1, -3, p2), 11, 16);
        checkVector(Vector2D.linearCombination(-3, p1, 2, p2), -9, -14);
    }

    @Test
    public void testLinearCombination3() {
        // arrange
        Vector2D p1 = Vector2D.of(1, 2);
        Vector2D p2 = Vector2D.of(-3, -4);
        Vector2D p3 = Vector2D.of(5, 6);

        // act/assert
        checkVector(Vector2D.linearCombination(2, p1, -3, p2, 4, p3), 31, 40);
        checkVector(Vector2D.linearCombination(-3, p1, 2, p2, -4, p3), -29, -38);
    }

    @Test
    public void testLinearCombination4() {
        // arrange
        Vector2D p1 = Vector2D.of(1, 2);
        Vector2D p2 = Vector2D.of(-3, -4);
        Vector2D p3 = Vector2D.of(5, 6);
        Vector2D p4 = Vector2D.of(-7, -8);

        // act/assert
        checkVector(Vector2D.linearCombination(2, p1, -3, p2, 4, p3, -5, p4), 66, 80);
        checkVector(Vector2D.linearCombination(-3, p1, 2, p2, -4, p3, 5, p4), -64, -78);
    }

    @Test
    public void testUnitFactoryOptimization() {
        // An already normalized vector will avoid unnecessary creation.
        final Vector2D v = Vector2D.of(4, 5).normalize();
        Assert.assertSame(v, v.normalize());
    }

    private void checkVector(Vector2D v, double x, double y) {
        checkVector(v, x, y, EPS);
    }

    private void checkVector(Vector2D v, double x, double y, double eps) {
        Assert.assertEquals(x, v.getX(), eps);
        Assert.assertEquals(y, v.getY(), eps);
    }
}
