/*
* Copyright (C) 2016 Google Inc. All Rights Reserved.
*
* 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 com.google.android.apps.santatracker.doodles.shared;
import java.util.Stack;
/**
* A basic 2D vector, with convenience functions to interact with it.
*/
public class Vector2D {
private static final int MAX_POOL_SIZE = 50;
private static final Stack<Vector2D> vectorPool = new Stack<>();
public float x;
public float y;
private Vector2D(float x, float y) {
this.x = x;
this.y = y;
}
public static Vector2D get() {
return get(0, 0);
}
public static synchronized Vector2D get(float x, float y) {
if (!vectorPool.isEmpty()) {
Vector2D v = vectorPool.pop();
v.set(x, y);
return v;
} else {
return new Vector2D(x, y);
}
}
public static Vector2D get(Vector2D other) {
return get(other.x, other.y);
}
/**
* Release this vector back into the vector pool. Note that, once this has been called, the
* vector object may be re-used, and there is no guarantee that the released object will act as
* expected.
*/
public void release() {
if (vectorPool.size() < MAX_POOL_SIZE) {
vectorPool.push(this);
}
}
public Vector2D normalize() {
float length = getLength();
if (length == 0) {
set(0, 0);
} else {
set (x / length, y / length);
}
return this;
}
public Vector2D toNormal() {
return set(y, -x).normalize();
}
public float getLength() {
return getLength(x, y);
}
public static float getLength(float x, float y) {
return (float) Math.sqrt(x * x + y * y);
}
public Vector2D add(Vector2D rhs) {
set(this.x + rhs.x, this.y + rhs.y);
return this;
}
public Vector2D add(float x, float y) {
set(this.x + x, this.y + y);
return this;
}
public Vector2D subtract(Vector2D rhs) {
set(this.x - rhs.x, this.y - rhs.y);
return this;
}
public Vector2D subtract(float x, float y) {
set(this.x - x, this.y - y);
return this;
}
public Vector2D scale(float factor) {
set(this.x * factor, this.y * factor);
return this;
}
public float dot(Vector2D rhs) {
return x * rhs.x + y * rhs.y;
}
public Vector2D rotate(float radians) {
double cos = Math.cos(radians);
double sin = Math.sin(radians);
set((float) (x * cos - y * sin), (float) (x * sin + y * cos));
return this;
}
public Vector2D set(Vector2D other) {
x = other.x;
y = other.y;
return this;
}
public Vector2D set(float x, float y) {
this.x = x;
this.y = y;
return this;
}
@Override
public String toString() {
return "(" + x + ", " + y + ")";
}
public float distanceTo(Vector2D other) {
float dx = x - other.x;
float dy = y - other.y;
return (float) Math.sqrt(dx * dx + dy * dy);
}
}