/******************************************************************************* * Copyright (c) 2011, 2015 itemis AG and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Matthias Wienand (itemis AG) - initial API and implementation * *******************************************************************************/ package org.eclipse.gef.geometry.projective; import org.eclipse.gef.geometry.euclidean.Straight; import org.eclipse.gef.geometry.planar.Point; /** * A two-dimensional infinite line that is defined by three coordinates of which * the third is a so called homogeneous coordinate. Calculations are easier to * do on such lines: * <ul> * <li>the point of intersection between two lines is the cross product of their * respective three dimensional vectors</li> * <li>the distance from a point to the line is the scalar product of both three * dimensional vectors</li> * </ul> * <p> * This is the complement to the {@link Vector3D} which represents a * {@link Point} with a third, homogeneous coordinate. * </p> * * @author mwienand * */ public final class Straight3D { /** * Constructs a new {@link Straight3D} through the given start and end * {@link Vector3D}s. * * @param start * The first {@link Vector3D} which lies on to the * {@link Straight3D} which is constructed. * @param end * The second {@link Vector3D} which lies on the * {@link Straight3D} which is constructed. * @return a new {@link Straight3D} through start and end {@link Vector3D}s */ public static Straight3D through(Vector3D start, Vector3D end) { Straight3D self = new Straight3D(); self.sp = start; self.line = self.sp.getCrossProduct(end); self.f = Math .sqrt(self.line.x * self.line.x + self.line.y * self.line.y); if (self.f == 0d) { return null; } return self; } private Vector3D sp, line; private double f; private Straight3D() { } /** * Returns the intersection between this and the given other * {@link Straight3D}. The intersection is the cross product of both * {@link Vector3D}s. * * @param other * The {@link Straight3D} for which intersections are computed. * @return the intersection between this and the given other * {@link Straight3D} */ public Vector3D getIntersection(Straight3D other) { return line.getCrossProduct(other.line); } /** * Returns the orthogonal {@link Straight3D} through this {@link Straight3D} * 's start {@link Vector3D}. * * @return the orthogonal {@link Straight3D} through this {@link Straight3D} * 's start {@link Vector3D} */ public Straight3D getOrtho() { return getOrtho(sp); } /** * Returns the orthogonal {@link Straight3D} through the given * {@link Vector3D}. * * @param vp * The {@link Vector3D} which lies on the orthogonal * {@link Straight3D}. * @return the orthogonal {@link Straight3D} through the given * {@link Vector3D} */ public Straight3D getOrtho(Vector3D vp) { return Straight3D.through(vp, new Vector3D(vp.x + line.x, vp.y + line.y, vp.z)); } /** * Returns the clock-wise signed distance of the given {@link Vector3D} to * this {@link Straight3D}. The clock-wise signed distance is the dot * product of the both {@link Vector3D}s divided by the length of the line's * (x,y) vector: <code>|(x,y)|</code>. * * @param vp * The {@link Vector3D} to which the distance is computed. * @return the clock-wise signed distance of the {@link Vector3D} to this * {@link Straight3D} */ public double getSignedDistanceCW(Vector3D vp) { Point p = vp.toPoint(); return (line.x * p.x + line.y * p.y + line.z) / f; } /** * Transfer this {@link Straight3D} into a representative {@link Straight}. * * @return a representative {@link Straight} */ public Straight toStraight() { return new Straight(sp.toPoint(), sp.toPoint().getTranslated(new Point(line.y, -line.x))); } }