/******************************************************************************* * Copyright (c) 2000, 2010, 2012 IBM Corporation, Gerhardt Informatics Kft. 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: * IBM Corporation - initial API and implementation * Research Group Software Construction, * RWTH Aachen University, Germany - Contribution for Bugzilla 245182 * Gerhardt Informatics Kft. - GEFGWT port *******************************************************************************/ package org.eclipse.draw2d.geometry; /** * Represents a vector within 2-dimensional Euclidean space. * * @since 3.6 */ public class Vector { /** the X value */ public double x; /** the Y value */ public double y; // internal constant used for comparisons. private static final Vector NULL = new Vector(0, 0); /** * Constructs a Vector pointed in the specified direction. * * @param x * X value. * @param y * Y value. */ public Vector(double x, double y) { this.x = x; this.y = y; } /** * Constructs a Vector pointed in the direction specified by a Point. * * @param p * the point */ public Vector(PrecisionPoint p) { x = p.preciseX(); y = p.preciseY(); } /** * Constructs a Vector representing the direction and magnitude between to * provided Points. * * @param start * starting point * @param end * End Point */ public Vector(PrecisionPoint start, PrecisionPoint end) { x = end.preciseX() - start.preciseX(); y = end.preciseY() - start.preciseY(); } /** * Constructs a Vector representing the difference between two provided * Vectors. * * @param start * The start Ray * @param end * The end Ray */ public Vector(Vector start, Vector end) { x = end.x - start.x; y = end.y - start.y; } /** * Calculates the magnitude of the cross product of this Vector with * another. Represents the amount by which two Vectors are directionally * different. Parallel Vectors return a value of 0. * * @param other * Vector being compared * @return The dissimilarity */ public double getDissimilarity(Vector other) { return PrecisionGeometry.preciseAbs(getCrossProduct(other)); } /** * Calculates whether this Vector and the provided one are parallel to each * other. * * @param other * The Vector to test for parallelism * @return true if this Vector and the provided one are parallel, false * otherwise. */ public boolean isParallelTo(Vector other) { return getDissimilarity(other) == 0; } /** * Calculates the dot product of this Vector with another. * * @param other * the Vector used to calculate the dot product * @return The dot product */ public double getDotProduct(Vector other) { return PrecisionGeometry.preciseAdd( PrecisionGeometry.preciseMultiply(x, other.x), PrecisionGeometry.preciseMultiply(y, other.y)); } /** * Calculates the cross product of this Vector with another. * * @param other * the Vector used to calculate the cross product * @return The cross product. */ public double getCrossProduct(Vector other) { return PrecisionGeometry.preciseSubtract( PrecisionGeometry.preciseMultiply(x, other.y), PrecisionGeometry.preciseMultiply(y, other.x)); } /** * Creates a new Vector which is the sum of this Vector with another. * * @param other * Vector to be added to this Vector * @return a new Vector representing the sum */ public Vector getAdded(Vector other) { return new Vector(PrecisionGeometry.preciseAdd(x, other.x), PrecisionGeometry.preciseAdd(y, other.y)); } /** * Creates a new Vector which is the difference of this Vector with the * provided Vector. * * @param other * Vector to be subtracted from this Vector * @return a new Vector representing the difference. */ public Vector getSubtracted(Vector other) { return new Vector(PrecisionGeometry.preciseSubtract(x, other.x), PrecisionGeometry.preciseSubtract(y, other.y)); } /** * Returns the angle (in degrees) between this Vector and the provided * Vector. * * @param other * Vector to calculate the angle. * @return the angle between the two Vectors in degrees. */ public double getAngle(Vector other) { double cosAlpha = PrecisionGeometry.preciseDivide( getDotProduct(other), (PrecisionGeometry.preciseMultiply(getLength(), other.getLength()))); return Math.toDegrees(Math.acos(cosAlpha)); } /** * Creates a new Vector which represents the average of this Vector with * another. * * @param other * Vector to calculate the average. * @return a new Vector */ public Vector getAveraged(Vector other) { return new Vector(PrecisionGeometry.preciseDivide( PrecisionGeometry.preciseAdd(x, other.x), 2), PrecisionGeometry.preciseDivide( PrecisionGeometry.preciseAdd(y, other.y), 2)); } /** * Creates a new Vector which represents this Vector multiplied by the * provided scalar factor. * * @param factor * Value providing the amount to scale. * @return a new Vector */ public Vector getMultiplied(double factor) { return new Vector(PrecisionGeometry.preciseMultiply(x, factor), PrecisionGeometry.preciseMultiply(y, factor)); } /** * Creates a new Vector which represents this Vector divided by the provided * scalar factor. * * @param factor * Value providing the amount to scale. * @return a new Vector */ public Vector getDivided(double factor) { return new Vector(PrecisionGeometry.preciseDivide(x, factor), PrecisionGeometry.preciseDivide(y, factor)); } /** * Returns the orthogonal complement of this Vector, which is defined to be * (-y, x). * * @return the orthogonal complement of this Vector */ public Vector getOrthogonalComplement() { return new Vector(PrecisionGeometry.preciseNegate(y), x); } /** * Returns the length of this Vector. * * @return Length of this Vector */ public double getLength() { return Math.sqrt(getDotProduct(this)); } /** * Calculates the similarity of this Vector with another. Similarity is * defined as the absolute value of the dotProduct(). Orthogonal vectors * return a value of 0. * * @param other * Vector being tested for similarity * @return the Similarity * @see #getDissimilarity(Vector) */ public double getSimilarity(Vector other) { return PrecisionGeometry.preciseAbs(getDotProduct(other)); } /** * Calculates whether this Vector and the provided one are orthogonal to * each other. * * @param other * Vector being tested for orthogonality * @return true, if this Vector and the provide one are orthogonal, false * otherwise */ public boolean isOrthogonalTo(Vector other) { return getSimilarity(other) == 0; } /** * Checks whether this vector has a horizontal component. * * @return true if x != 0, false otherwise. */ public boolean isHorizontal() { return x != 0; } /** * Checks whether this vector has a vertical component. * * @return true if y != 0, false otherwise. */ public boolean isVertical() { return y != 0; } /** * Checks whether this vector equals (0,0); * * @return true if x == 0 and y == 0. */ public boolean isNull() { return equals(NULL); } /** * Returns a point representation of this Vector. * * @return a PrecisionPoint representation */ public PrecisionPoint toPoint() { return new PrecisionPoint(x, y); } /** * @see java.lang.Object#toString() */ public String toString() { return "(" + x + "," + y + ")";//$NON-NLS-3$//$NON-NLS-2$//$NON-NLS-1$ } /** * @see java.lang.Object#equals(Object) */ public boolean equals(Object obj) { if (obj == this) return true; if (obj instanceof Vector) { Vector r = (Vector) obj; return x == r.x && y == r.y; } return false; } /** * @see java.lang.Object#hashCode() */ public int hashCode() { return (int) x + (int) y; } }