Package gwt.g2d.shared.math

Source Code of gwt.g2d.shared.math.Vector2$ImmutableVector2

/*
* Copyright 2009 Hao Nguyen
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package gwt.g2d.shared.math;

import static gwt.g2d.client.math.MathHelper.square;

import gwt.g2d.client.math.MathHelper;

import java.io.Serializable;
import java.util.Arrays;

import com.google.gwt.regexp.shared.MatchResult;
import com.google.gwt.regexp.shared.RegExp;

/**
* Represents a 2D point or vector.
*
* @author hao1300@gmail.com
*/
public class Vector2 implements Serializable {
  /** A vector at (0, 0). */
  public static final Vector2 ZERO = new ImmutableVector2(0.0, 0.0);
  /** A vector at (1, 1). */
  public static final Vector2 ONE = new ImmutableVector2(1.0, 1.0);
  /** A vector at (1, 0). */
  public static final Vector2 UNIT_X = new ImmutableVector2(1.0, 0.0);
  /** A vector at (0, 1). */
  public static final Vector2 UNIT_Y = new ImmutableVector2(0.0, 1.0);
  /** Any value below this is considered zero. */
  public static final double EPS = 0.0000001;
 
  private static final long serialVersionUID = 5543191998324226983L;
 
  public double x, y;
 
  /**
   * Creates a default vector2 at (0, 0).
   * Uses Vector2.ZERO to represents (0, 0) instead.
   */
  public Vector2() {
  }
 
  public Vector2(Vector2 rhs) {
    this.x = rhs.getX();
    this.y = rhs.getY();
  }
 
  public Vector2(double x, double y) {
    this.x = x;
    this.y = y;
  }
 
  /**
   * Creates a vector at (value, value).
   */
  public Vector2(double value) {
    this(value, value);
  }
 
  /**
   * Catmull-rom interpolation between two vectors.
   *
   * @param value1
   * @param value2
   * @param value3
   * @param value4
   * @param amount the amount to interpolate [0.0, 1.0].
   * @return a new interpolated vector.
   */
  public static final Vector2 catmullRom(Vector2 value1, Vector2 value2, Vector2 value3,
      Vector2 value4, double amount) {
    return new Vector2().mutableCatmullRom(value1, value2, value3, value4, amount);
  }
 
  /**
   * Hermite interpolation between two vectors.
   *
   * @param value1
   * @param tangent1
   * @param value2
   * @param tangent2
   * @param amount the amount to interpolate [0.0, 1.0].
   * @return a new interpolated vector.
   */
  public static final Vector2 hermite(Vector2 value1, Vector2 tangent1, Vector2 value2,
      Vector2 tangent2, double amount) {
    return new Vector2().mutableHermite(value1, tangent1, value2, tangent2, amount);
  }
 
  /**
   * Linear interpolation between two vectors.
   *
   * @param value1
   * @param value2
   * @param amount the amount to interpolate [0.0, 1.0].
   * @return a new interpolated vector.
   */
  public static final Vector2 lerp(Vector2 value1, Vector2 value2, double amount) {
    return new Vector2().mutableLerp(value1, value2, amount);
  }
 
  /**
   * Creates a vector within the given radius.
   *
   * @param radius
   * @return a random vector that lies within a circle with (0, 0) as the
   *          origin and the radius as given.
   */
  public static final Vector2 random(int radius) {
    Vector2 vector = new Vector2(Math.random(), Math.random());
    double radiusSquared = MathHelper.square(radius);
    while (vector.lengthSquared() > radiusSquared) {
      vector.set(Math.random(), Math.random());
    }
    return vector;
  }
 
  /**
   * Creates a random vector2 inside the given range.
   *
   * @param maxX
   * @param maxY
   * @return a random vector whose x value is in [0, maxX), and y value is
   *          in [0, maxY)
   */
  public static final Vector2 random(double maxX, double maxY) {
    return new Vector2(Math.random() * maxX, Math.random() * maxY);
  }
 
  /**
   * Creates a random vector2 inside the given range.
   *
   * @param minX
   * @param minY
   * @param maxX
   * @param maxY
   * @return a random vector whose x value is in [minX, maxX), and y value is
   *          in [minY, maxY)
   */
  public static final Vector2 random(double minX, double minY, double maxX,
      double maxY) {
    return new Vector2(Math.random() * (maxX - minX) + minX,
        Math.random() * (maxY - minY) + minY);
  }
 
  /**
   * Creates a vector inside the given rectangle.
   *
   * @param rectangle
   * @return a new vector that lies inside the given rectangle.
   */
  public static final Vector2 random(Rectangle rectangle) {
    return new Vector2(Math.random() * rectangle.getWidth() + rectangle.getX(),
        Math.random() * rectangle.getHeight() + rectangle.getY());
  }
 
  /**
   * Creates a normalized vector.
   *
   * @return a random normalized vector.
   */
  public static final Vector2 randomNormalize() {
    Vector2 vector = random(1);
    while (vector.getX() == 0 && vector.getY() == 0) {
      vector = random(1);
    }
    return vector;
  }
 
  /**
   * Smooth interpolation between two vectors.
   *
   * @param value1
   * @param value2
   * @param amount the amount to interpolate [0.0, 1.0].
   * @return a new interpolated vector.
   */
  public static final Vector2 smoothStep(Vector2 value1, Vector2 value2,
      double amount) {
    return new Vector2().mutableSmoothStep(value1, value2, amount);
  }
 
  /**
   * Gets the x-coordinate.
   */
  public final double getX() {
    return x;
  }
 
  /**
   * Gets the x-coordinate as an integer.
   */
  public final int getIntX() {
    return (int) getX();
  }
 
  /**
   * Gets the y-coordinate.
   */
  public final double getY() {
    return y;
  }
 
  /**
   * Gets the y-coordinate as an integer.
   */
  public final int getIntY() {
    return (int) getY();
  }
 
  /**
   * Sets the x-coordinate.
   */
  public void setX(double x) {
    this.x = x;
  }
 
  /**
   * Sets the y-coordinate.
   */
  public void setY(double y) {
    this.y = y;
  }
 
  /**
   * Sets the x and y coordinates of the vector.
   *
   * @param x
   * @param y
   */
  public final void set(double x, double y) {
    this.x = x;
    this.y = y;
  }
 
  /**
   * Calculates whether this vector is zero (using machine epsilon so that very small vectors are also counted as zero.
   *
   * @return whether this vector is zero.
   */
  public final boolean isZero() {
    return this.lengthSquared() < EPS*EPS;
  }
 
  /**
   * Gets (this.x + rhs.x, this.y + rhs.y).
   *
   * @param rhs the vector to add.
   * @return a new vector that is this + rhs.
   */
  public final Vector2 add(Vector2 rhs) {
    return new Vector2(getX() + rhs.getX(), getY() + rhs.getY());
  }
 
  /**
   * Gets (this.x + x, this.y + y).
   *
   * @param x the x coordinate
   * @param y the y coordinate
   * @return a new vector that is this + rhs.
   */
  public final Vector2 add(double x, double y) {
    return new Vector2(getX() + x, getY() + y);
  }
 
  /**
   * Adds rhs to this.
   * Unlike {@link #add(Vector2)}, the returned vector is this, so no new
   * vector is allocated.
   * 
   * @param rhs the vector to add.
   * @return self to support chaining.
   */
  public final Vector2 mutableAdd(Vector2 rhs) {
    this.x += rhs.x;
    this.y += rhs.y;
    return this;
  }
 
  /**
   * Adds rhs to this.
   * Unlike {@link #add(Vector2)}, the returned vector is this, so no new
   * vector is allocated.
   * 
   * @param rhs the vector to add.
   * @return self to support chaining.
   */
  public final Vector2 mutableAdd(double x, double y) {
    this.x += x;
    this.y += y;
    return this;
  }
 
  /**
   * Gets (this.x - rhs.x, this.y - rhs.y).
   *
   * @param rhs the vector to subtract from this.
   * @return a new vector that is this - rhs.
   */
  public final Vector2 subtract(Vector2 rhs) {
    return new Vector2(this.x - rhs.x, this.y - rhs.y);
  }
 
  /**
   * Gets (this.x - rhs.x, this.y - rhs.y).
   *
   * @param rhs the vector to subtract from this.
   * @return a new vector that is this - rhs.
   */
  public final Vector2 subtract(double x, double y) {
    return new Vector2(this.x - x, this.y - y);
  }
 
  /**
   * Subtract rhs from this.
   * Unlike {@link #subtract(Vector2)}, the returned vector is this, so no new
   * vector is allocated.
   *
   * @param rhs the vector to subtract from this.
   * @return self to support chaining.
   */
  public final Vector2 mutableSubtract(Vector2 rhs) {
    this.x -= rhs.x;
    this.y -= rhs.y;
    return this;
  }
 
  /**
   * Subtract rhs from this.
   * Unlike {@link #subtract(Vector2)}, the returned vector is this, so no new
   * vector is allocated.
   *
   * @param rhs the vector to subtract from this.
   * @return self to support chaining.
   */
  public final Vector2 mutableSubtract(double x, double y) {
    this.x -= x;
    this.y -= y;
    return this;
  }
 
  /**
   * Gets (this.x * rhs.x, this.y * rhs.y).
   *
   * @param rhs the vector to multiply.
   * @return a new vector that is this * rhs.
   */
  public final Vector2 multiply(Vector2 rhs) {
    return new Vector2(this.x * rhs.x, this.y * rhs.y);
  }
 
  /**
   * Multiply this by rhs.
   * Unlike {@link #multiply(Vector2)}, the returned vector is this, so no new
   * vector is allocated.
   *
   * @param rhs the vector to multiply.
   * @return self to support chaining.
   */
  public final Vector2 mutableMultiply(Vector2 rhs) {
    this.x *= rhs.x;
    this.y *= rhs.y;
    return this;
  }
 
  /**
   * Gets (this.x * rhs.x, this.y * rhs.y).
   *
   * @param rhs the vector to multiply.
   * @return a new vector that is this * rhs.
   */
  public final Vector2 multiply(double x, double y) {
    return new Vector2(this.x * x, this.y * y);
  }
 
  /**
   * Multiply this by rhs.
   * Unlike {@link #multiply(Vector2)}, the returned vector is this, so no new
   * vector is allocated.
   *
   * @param rhs the vector to multiply.
   * @return self to support chaining.
   */
  public final Vector2 mutableMultiply(double x, double y) {
    this.x *= x;
    this.y *= y;
    return this;
  }
 
  /**
   * Gets (this.x / rhs.x, this.y / rhs.y).
   *
   * @param rhs the vector by which this is to be divided.
   * @return a new vector that is this / rhs.
   */
  public final Vector2 divide(Vector2 rhs) {
    return new Vector2(this.x / rhs.x, this.y / rhs.y);
  }
 
  /**
   * Divide this by rhs.
   * Unlike {@link #divide(Vector2)}, the returned vector is this, so no new
   * vector is allocated.
   *
   * @param rhs the vector by which this is to be divided.
   * @return self to support chaining.
   */
  public final Vector2 mutableDivide(Vector2 rhs) {
    this.x /= rhs.x;
    this.y /= rhs.y;
    return this;
  }
 
  /**
   * Gets (this.x / rhs.x, this.y / rhs.y).
   *
   * @param rhs the vector by which this is to be divided.
   * @return a new vector that is this / rhs.
   */
  public final Vector2 divide(double x, double y) {
    return new Vector2(this.x / x, this.y / y);
  }
 
  /**
   * Divide this by rhs.
   * Unlike {@link #divide(Vector2)}, the returned vector is this, so no new
   * vector is allocated.
   *
   * @param rhs the vector by which this is to be divided.
   * @return self to support chaining.
   */
  public final Vector2 mutableDivide(double x, double y) {
    this.x /= x;
    this.y /= y;
    return this;
  }
 
  /**
   * Clamp this vector between min and max, that is, the new vector's x is
   * between min's x and max's x, and its y is between min's y and max's y.
   *
   * @param min
   * @param max
   * @return a new vector that is inside [min, max]
   */
  public final Vector2 clamp(Vector2 min, Vector2 max) {
    return new Vector2(
        MathHelper.clamp(getX(), min.getX(), max.getX()),
        MathHelper.clamp(getY(), min.getY(), max.getY()));
  }
 
  /**
   * Similar to clamp except the vector returned is this vector whose x and y
   * have been clamped to between min and max.
   *
   * @param min
   * @param max
   * @return self to support chaining.
   */
  public final Vector2 mutatableClamp(Vector2 min, Vector2 max) {
    setX(MathHelper.clamp(getX(), min.getX(), max.getX()));
    setY(MathHelper.clamp(getY(), min.getY(), max.getY()));
    return this;
  }
 
  /**
   * Gets the dot product for this and rhs.
   *
   * @param rhs
   * @return the dot product of this and rhs.
   */
  public final double dot(Vector2 rhs) {
    return getX() * rhs.getX() + getY() * rhs.getY();
  }
 
  /**
   * Gets the distance squared from this to rhs.
   *
   * @param rhs
   * @return the distance squared from this to rhs.
   */
  public final double distanceSquared(Vector2 rhs) {
    return square(getX() - rhs.getX()) + square(getY() - rhs.getY());
  }
 
  /**
   * Gets the distance from this to rhs.
   *
   * @param rhs
   * @return the distance from this to rhs.
   */
  public final double distance(Vector2 rhs) {
    return Math.sqrt(distanceSquared(rhs));
  }
 
  /**
   * Gets the length of this vector squared.
   *
   * @return the length of this vector squared.
   */
  public final double lengthSquared() {
    return square(getX()) + square(getY());
  }
 
  /**
   * Gets the length of this vector.
   *
   * @return the length of this vector.
   */
  public final double length() {
    return Math.sqrt(lengthSquared());
  }
 
  /**
   * Gets a vector whose x is the max of this's x and rhs's x, and y is the
   * max of this'y and rhs's y.
   *
   * @param rhs
   * @return a new vector whose x and y values are the max of this and rhs.
   */
  public final Vector2 max(Vector2 rhs) {
    return new Vector2(
        Math.max(getX(), rhs.getX()),
        Math.max(getY(), rhs.getY()));
  }
 
  /**
   * Similar to max() except the vector returned is this vector whose x and y
   * values have been set to the result of max().
   *
   * @param rhs
   * @return self to support chaining.
   */
  public final Vector2 mutableMax(Vector2 rhs) {
    setX(Math.max(getX(), rhs.getX()));
    setY(Math.max(getY(), rhs.getY()));
    return this;
  }
 
  /**
   * Gets a vector whose x is the min of this's x and rhs's x, and y is the
   * min of this'y and rhs's y.
   *
   * @param rhs
   * @return a new vector whose x and y values are the min of this and rhs.
   */
  public final Vector2 min(Vector2 rhs) {
    return new Vector2(
        Math.min(getX(), rhs.getX()),
        Math.min(getY(), rhs.getY()));
  }
 
  /**
   * Similar to min() except the vector returned is this vector whose x and y
   * values have been set to the result of min().
   *
   * @param rhs
   * @return self to support chaining.
   */
  public final Vector2 mutableMin(Vector2 rhs) {
    setX(Math.min(getX(), rhs.getX()));
    setY(Math.min(getY(), rhs.getY()));
    return this;
  }
 
  /**
   * Gets the negate of this vector.
   *
   * @return a new vector whose x and y values have the opposite sign of this
   *          vector's x and y values.
   */
  public final Vector2 negate() {
      return new Vector2(-getX(), -getY());
  }

  /**
   * Similar to negate() except the vector returned is this vector whose x and
   * y values have been set to be the result of negate().
   *
   * @return self to support chaining.
   */
  public final Vector2 mutableNegate() {
      setX(-getX());
      setY(-getY());
      return this;
  }
 
  /**
   * Gets the normal of this vector.
   *
   * @return a new vector that is the unit vector of this vector.
   */
  public final Vector2 normalize() {
    return this.scale(1.0 / length());
  }

  /**
   * Similar to normalize() except the vector returned is this vector whose
   * x and y values have been set to be the result of normalize().
   *
   * @return self to support chaining.
   */
  public final Vector2 mutableNormalize() {
    return this.mutableScale(1.0 / length());
  }
 
  /**
   * Gets (this.x * rhs, this.y * rhs).
   *
   * @param rhs the value to scale this vector by.
   * @return a new vector that is this * rhs.
   */
  public final Vector2 scale(double rhs) {
    return new Vector2(getX() * rhs, getY() * rhs);
  }
 
  /**
   * Scale this by rhs.
   * Unlike scale(), the returned vector is this, so no new vector is allocated.
   *
   * @param rhs the value to scale this vector by.
   * @return self to support chaining.
   */
  public final Vector2 mutableScale(double rhs) {
    setX(getX() * rhs);
    setY(getY() * rhs);
    return this;
  }
 
  /**
   * Similar to catmullRom() except the vector returned is this vector whose
   * x and y have been set to the result of catmullRom().
   *
   * @param value1
   * @param value2
   * @param value3
   * @param value4
   * @param amount the amount to interpolate [0.0, 1.0].
   * @return self to support chaining.
   */
  public final Vector2 mutableCatmullRom(Vector2 value1, Vector2 value2,
      Vector2 value3, Vector2 value4, double amount) {
    setX(MathHelper.catmullRom(value1.getX(), value2.getX(), value3.getX(),
        value4.getX(), amount));
    setY(MathHelper.catmullRom(value1.getY(), value2.getY(), value3.getY(),
        value4.getY(), amount));
    return this;
  }
 
  /**
   * Similar to hermit() except the vector returned is this vector whose
   * x and y have been set to the result of hermite().
   *
   * @param value1
   * @param tangent1
   * @param value2
   * @param tangent2
   * @param amount the amount to interpolate [0.0, 1.0].
   * @return self to support chaining.
   */
  public final Vector2 mutableHermite(Vector2 value1, Vector2 tangent1,
      Vector2 value2, Vector2 tangent2, double amount) {
    setX(MathHelper.hermite(value1.getX(), tangent1.getX(), value2.getX(),
        tangent2.getX(), amount));
    setY(MathHelper.hermite(value1.getY(), tangent1.getY(), value2.getY(),
        tangent2.getY(), amount));
    return this;
  }
 
  /**
   * Similar to lerp() except the vector returned is this vector whose
   * x and y have been set to the result of lerp().
   *
   * @param value1
   * @param value2
   * @param amount the amount to interpolate [0.0, 1.0].
   * @return self to support chaining.
   */
  public final Vector2 mutableLerp(Vector2 value1, Vector2 value2, double amount) {
    setX(MathHelper.lerp(value1.getX(), value2.getX(), amount));
    setY(MathHelper.lerp(value1.getY(), value2.getY(), amount));
    return this;
  }
 
  /**
   * Similar to smoothStep() except the vector returned is this vector whose
   * x and y have been set to the result of smoothStep().

   *
   * @param value1
   * @param value2
   * @param amount the amount to interpolate [0.0, 1.0].
   * @return a new interpolated vector.
   */
  public final Vector2 mutableSmoothStep(Vector2 value1, Vector2 value2, double amount) {
    setX(MathHelper.smoothStep(value1.getX(), value2.getX(), amount));
    setY(MathHelper.smoothStep(value1.getY(), value2.getY(), amount));
    return this;
  }
 
  @Override
  public final boolean equals(Object obj) {
    return (obj instanceof Vector2) ? equals((Vector2) obj) : false;
  }
 
  public final boolean equals(Vector2 rhs) {
    return (this.x - rhs.x) < EPS && (this.y - rhs.y) < EPS;
  }
 
  @Override
  public final int hashCode() {
    return Arrays.hashCode(new double[]{getX(), getY()});
  }
 
  @Override
  public final String toString() {
    return "[" + this.x + ", " + this.y + "]";
  }
 
 
  // regular expression for parsing a vector
  private static RegExp Pattern = RegExp.compile("\\[\\s*([0-9]*[\\.]?[0-9]+)\\s*,\\s*([0-9]*[\\.]?[0-9]+)\\s*\\]");
 
 
  // parse from String
  public static Vector2 parseVector2(String s) {
    MatchResult res = Pattern.exec(s);
    if (res == null) return null;
    return new Vector2(Double.parseDouble(res.getGroup(1)), Double.parseDouble(res.getGroup(2)));
  }
 
 
 
  // clone a vector
  public final Vector2 copy() {
    return new Vector2(this.x, this.y);
  }
 
  /**
   * An unmodifiable vector2.
   */
  private static class ImmutableVector2 extends Vector2 {
    private static final long serialVersionUID = -4931305479279295158L;
    private static final String MODIFICATION_ERROR_MESSAGE =
        "Cannot modify an immutable vector";
   
    public ImmutableVector2(double x, double y) {
      super(x, y);
    }
   
    @Override
    public void setX(double x) {
      throw new UnsupportedOperationException(MODIFICATION_ERROR_MESSAGE);
    }
   
    @Override
    public void setY(double y) {
      throw new UnsupportedOperationException(MODIFICATION_ERROR_MESSAGE);
    }
  }
}
TOP

Related Classes of gwt.g2d.shared.math.Vector2$ImmutableVector2

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.