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

/**
 * A two dimensional triangle
 * 
 * @author Matthias Betz
 *
 */
public class Triangle2d {

	private Vector2d p1;
	private Vector2d p2;
	private Vector2d p3;

	private static final double EPSILON = 0;

	public Triangle2d(Vector2d p1, Vector2d p2, Vector2d p3) {
		this.p1 = p1;
		this.p2 = p2;
		this.p3 = p3;
	}

	public Vector2d getP1() {
		return p1;
	}

	public Vector2d getP2() {
		return p2;
	}

	public Vector2d getP3() {
		return p3;
	}

	public boolean containsPoint(Vector2d point) {
		return containsPoint(point, EPSILON);
	}

	public boolean containsPoint(Vector2d point, double epsilon) {
		double a = (p2.getY() - point.getY()) * (p1.getX() - point.getX())
				- (p1.getY() - point.getY()) * (p2.getX() - point.getX());
		double b = (p3.getY() - point.getY()) * (p1.getX() - point.getX())
				- (p1.getY() - point.getY()) * (p3.getX() - point.getX());
		if (a * b >= -epsilon) {
			return false;
		}

		double c = (p1.getY() - point.getY()) * (p2.getX() - point.getX())
				- (p2.getY() - point.getY()) * (p1.getX() - point.getX());
		double d = (p3.getY() - point.getY()) * (p2.getX() - point.getX())
				- (p2.getY() - point.getY()) * (p3.getX() - point.getX());
		return (c * d < epsilon);
	}

	public boolean hasCornerPoint(Vector2d p) {
		return p.equals(p1) || p.equals(p2) || p.equals(p3);
	}

	public boolean intersects(Triangle2d other) {
		if (hasCornerPoint(other.p1) && hasCornerPoint(other.p2) && hasCornerPoint(other.p3)) {
			// same triangle
			return true;
		}
		Segment2d s1T1 = new Segment2d(p1, p2);
		Segment2d s2T1 = new Segment2d(p1, p3);
		Segment2d s3T1 = new Segment2d(p2, p3);

		Segment2d s1T2 = new Segment2d(other.p1, other.p2);
		Segment2d s2T2 = new Segment2d(other.p1, other.p3);
		Segment2d s3T2 = new Segment2d(other.p2, other.p3);

		return s1T1.intersectsWithoutColinearity(s1T2) || s1T1.intersectsWithoutColinearity(s2T2)
				|| s1T1.intersectsWithoutColinearity(s3T2) || s2T1.intersectsWithoutColinearity(s1T2)
				|| s2T1.intersectsWithoutColinearity(s2T2) || s2T1.intersectsWithoutColinearity(s3T2)
				|| s3T1.intersectsWithoutColinearity(s1T2) || s3T1.intersectsWithoutColinearity(s2T2)
				|| s3T1.intersectsWithoutColinearity(s3T2) || containsPoint(other.p1) || other.containsPoint(p1);
	}

	public Vector2d getCentroid() {
		double x = (p1.getX() + p2.getX() + p3.getX()) / 3d;
		double y = (p1.getY() + p2.getY() + p3.getY()) / 3d;
		return new Vector2d(x, y);
	}

}
