blob: 874a6d0d6f2b6bc28b65164319b16f23182d88fa [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2010 IBM Corporation 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
* Alexander Nyßen (Research Group Software Construction, RWTH Aachen University) - Contribution for Bugzilla 245182
*
*******************************************************************************/
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())));
// compensate rounding effects that may occur
if (cosAlpha > 1) {
cosAlpha = 1;
} else if (cosAlpha < -1) {
cosAlpha = -1;
}
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;
}
}