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

public class GmStraight2d {

	private Point2d origin;
	private UnitVector2d direction;

	public GmStraight2d(Point2d org, UnitVector2d dir) {
		this.direction = dir;
		this.origin = org;
	}

	public GmStraight2d(Point2d org, Vector2d dir) {
		this.origin = org;
		this.direction = dir.normalize();
	}

	public GmStraight2d(Point2d from, Point2d to) {
		origin = from;
		direction = to.minus(from).normalize();
	}

	/**
	 * Just intersects two GmStraights2d.
	 * 
	 * <br>
	 * <br>
	 * If the two straights are parallel the method will return false, so the user
	 * has to determine, if the straight are just parallel or identical
	 * 
	 * @param other First Straight
	 * 
	 * @return intersection result
	 */
	public GmStraight2dIntersectionResult intersect(GmStraight2d other) {
		Point2d p1 = origin;
		UnitVector2d r1 = direction;
		Point2d p2 = other.getOrigin();
		UnitVector2d r2 = other.getDirection();
		Vector2d q = p2.minus(p1);

		Vector2d r2Perpendicular = r2.getPerpendicularVector();
		double diff = r1.dot(r2Perpendicular);

		if (Math.abs(diff) < Global.getZeroAngleCosinus()) {
			return GmStraight2dIntersectionResult.parallel(this, other);
		} else {
			double invR1DotPerpR2 = 1.0 / diff;
			double qDotPerpR1 = q.dot(r1.getPerpendicularVector());
			double qDotPerpR2 = q.dot(r2Perpendicular);
			double rParam1 = qDotPerpR2 * invR1DotPerpR2;
			double rParam2 = qDotPerpR1 * invR1DotPerpR2;
			return GmStraight2dIntersectionResult.intersecting(rParam1, rParam2, this, other);
		}

	}

	public UnitVector2d getDirection() {
		return direction;
	}

	public Point2d getOrigin() {
		return origin;
	}

	public Point2d evaluate(double param) {
		return origin.plus(direction.mult(param));
	}

	@Override
	public String toString() {
		return "GmStraight2d [origin=" + origin + ", direction=" + direction + "]";
	}

}
