/*-
 *  Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart
 * 
 *  This file is part of CityDoctor2.
 *
 *  CityDoctor2 is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Lesser General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  CityDoctor2 is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public License
 *  along with CityDoctor2.  If not, see <https://www.gnu.org/licenses/>.
 */
package de.hft.stuttgart.citydoctor2.math;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import org.junit.Test;

/**
 * 
 * @author Matthias Betz
 *
 */
public class Segment2dTest {

	@Test
	public void testDistance() {
		Vector2d p1 = new Vector2d(0, 0);
		Vector2d p2 = new Vector2d(5, 0);
		
		Segment2d seg = new Segment2d(p1, p2);
		
		Vector2d p3 = new Vector2d(2.5, 1);
		assertEquals(1d, seg.distance(p3), 0.00001);

		Vector2d p4 = new Vector2d(1, 1);
		assertEquals(1d, seg.distance(p4), 0.00001);

		Vector2d p5 = new Vector2d(0, -2);
		assertEquals(2d, seg.distance(p5), 0.00001);
}
	
	@Test
	public void testIntersect() {
		Vector2d p1 = new Vector2d(0, 0);
		Vector2d p2 = new Vector2d(5, 5);
		Vector2d p3 = new Vector2d(0, 5);
		Vector2d p4 = new Vector2d(5, 0);
		
		Segment2d seg1 = new Segment2d(p1, p2);
		Segment2d seg2 = new Segment2d(p3, p4);
		
		assertTrue(seg1.intersects(seg2));
	}
	
	/**
	 * two segments on same line, not intersecting
	 */
	@Test
	public void testIntersect2() {
		Vector2d p1 = new Vector2d(0, 0);
		Vector2d p2 = new Vector2d(5, 0);
		Vector2d p3 = new Vector2d(7, 0);
		Vector2d p4 = new Vector2d(10, 0);
		
		Segment2d seg1 = new Segment2d(p1, p2);
		Segment2d seg2 = new Segment2d(p3, p4);
		
		assertFalse(seg1.intersects(seg2));
	}
	
	/**
	 * two segments on same line, intersecting
	 */
	@Test
	public void testIntersect3() {
		Vector2d p1 = new Vector2d(0, 0);
		Vector2d p2 = new Vector2d(5, 0);
		Vector2d p3 = new Vector2d(3, 0);
		Vector2d p4 = new Vector2d(10, 0);
		
		Segment2d seg1 = new Segment2d(p1, p2);
		Segment2d seg2 = new Segment2d(p3, p4);
		
		assertTrue(seg1.intersects(seg2));
	}
	
	/**
	 * two segments on same line, same segments
	 */
	@Test
	public void testIntersect4() {
		Vector2d p1 = new Vector2d(0, 0);
		Vector2d p2 = new Vector2d(5.1, 0);
		Vector2d p3 = new Vector2d(0, 0);
		Vector2d p4 = new Vector2d(5, 0);
		
		Segment2d seg1 = new Segment2d(p1, p2);
		Segment2d seg2 = new Segment2d(p3, p4);
		
		assertTrue(seg1.intersects(seg2));
	}
	
	/**
	 * two segments parallel
	 */
	@Test
	public void testIntersect5() {
		Vector2d p1 = new Vector2d(0, 0);
		Vector2d p2 = new Vector2d(5, 0);
		Vector2d p3 = new Vector2d(0, 1);
		Vector2d p4 = new Vector2d(5, 1);
		
		Segment2d seg1 = new Segment2d(p1, p2);
		Segment2d seg2 = new Segment2d(p3, p4);
		
		assertFalse(seg1.intersects(seg2));
	}
	
	/**
	 * two segments not parallel, not intersecting
	 */
	@Test
	public void testIntersect6() {
		Vector2d p1 = new Vector2d(0, 0);
		Vector2d p2 = new Vector2d(5, 0);
		Vector2d p3 = new Vector2d(0, 1);
		Vector2d p4 = new Vector2d(5, 0.1);
		
		Segment2d seg1 = new Segment2d(p1, p2);
		Segment2d seg2 = new Segment2d(p3, p4);
		
		assertFalse(seg1.intersects(seg2));
	}
	
	/**
	 * two segments intersecting, calculate intersection point
	 */
	@Test
	public void testIntersectionPoint1() {
		Vector2d p1 = new Vector2d(1, 1);
		Vector2d p2 = new Vector2d(3, 2);
		Vector2d p3 = new Vector2d(1, 4);
		Vector2d p4 = new Vector2d(2, -1);
		
		Segment2d seg1 = new Segment2d(p1, p2);
		Segment2d seg2 = new Segment2d(p3, p4);
		
		Vector2d expected = new Vector2d(17d/11d, 14d/11d);
		
		assertTrue(expected.equalsWithinEpsilon(seg1.intersectionPoint(seg2), 0.00001));
	}
	
	/**
	 * two segments on same line, intersecting
	 */
	@Test
	public void testIntersectionPoint2() {
		Vector2d p1 = new Vector2d(0, 0);
		Vector2d p2 = new Vector2d(5, 0);
		Vector2d p3 = new Vector2d(3, 0);
		Vector2d p4 = new Vector2d(10, 0);
		
		Segment2d seg1 = new Segment2d(p1, p2);
		Segment2d seg2 = new Segment2d(p3, p4);
		
		assertTrue(p3.equalsWithinEpsilon(seg1.intersectionPoint(seg2), 0.00001));
	}

}
