/*
* Copyright (c) 2005–2012 Goethe Center for Scientific Computing - Simulation and Modelling (G-CSC Frankfurt)
* Copyright (c) 2012-2015 Goethe Center for Scientific Computing - Computational Neuroscience (G-CSC Frankfurt)
*
* This file is part of NeuGen.
*
* NeuGen is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 3
* as published by the Free Software Foundation.
*
* see: http://opensource.org/licenses/LGPL-3.0
* file://path/to/NeuGen/LICENSE
*
* NeuGen is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* This version of NeuGen includes copyright notice and attribution requirements.
* According to the LGPL this information must be displayed even if you modify
* the source code of NeuGen. The copyright statement/attribution may not be removed.
*
* Attribution Requirements:
*
* If you create derived work you must do the following regarding copyright
* notice and author attribution.
*
* Add an additional notice, stating that you modified NeuGen. In addition
* you must cite the publications listed below. A suitable notice might read
* "NeuGen source code modified by YourName 2012".
*
* Note, that these requirements are in full accordance with the LGPL v3
* (see 7. Additional Terms, b).
*
* Publications:
*
* S. Wolf, S. Grein, G. Queisser. NeuGen 2.0 -
* Employing NeuGen 2.0 to automatically generate realistic
* morphologies of hippocapal neurons and neural networks in 3D.
* Neuroinformatics, 2013, 11(2), pp. 137-148, doi: 10.1007/s12021-012-9170-1
*
*
* J. P. Eberhard, A. Wanner, G. Wittum. NeuGen -
* A tool for the generation of realistic morphology
* of cortical neurons and neural networks in 3D.
* Neurocomputing, 70(1-3), pp. 327-343, doi: 10.1016/j.neucom.2006.01.028
*
*/
/**
* Copyright John E. Lloyd, 2004. All rights reserved. Permission to use,
* copy, modify and redistribute is granted, provided that this copyright
* notice is retained and the author is given credit whenever appropriate.
*
* This software is distributed "as is", without any warranty, including
* any implied warranty of merchantability or fitness for a particular
* use. The author assumes no responsibility for, and shall not be liable
* for, any special, indirect, or consequential damages, or any damages
* whatsoever, arising out of or in connection with the use of this
* software.
*/
package org.neugen.quickhull3d;
import java.util.Random;
/**
* A three-element vector. This class is actually a reduced version of the
* Vector3d class contained in the author's matlib package (which was partly
* inspired by javax.vecmath). Only a mininal number of methods which are
* relevant to convex hull generation are supplied here.
*
* @author John E. Lloyd, Fall 2004
*/
public class Vector3d {
/**
* Precision of a double.
*/
static private final double DOUBLE_PREC = 2.2204460492503131e-16;
/**
* First element
*/
public double x;
/**
* Second element
*/
public double y;
/**
* Third element
*/
public double z;
/**
* Creates a 3-vector and initializes its elements to 0.
*/
public Vector3d() {
}
/**
* Creates a 3-vector by copying an existing one.
*
* @param v
* vector to be copied
*/
public Vector3d(Vector3d v) {
set(v);
}
/**
* Creates a 3-vector with the supplied element values.
*
* @param x
* first element
* @param y
* second element
* @param z
* third element
*/
public Vector3d(double x, double y, double z) {
set(x, y, z);
}
/**
* Gets a single element of this vector. Elements 0, 1, and 2 correspond
* to x, y, and z.
*
* @param i
* element index
* @return element value throws ArrayIndexOutOfBoundsException if i is
* not in the range 0 to 2.
*/
public double get(int i) {
switch (i) {
case 0: {
return x;
}
case 1: {
return y;
}
case 2: {
return z;
}
default: {
throw new ArrayIndexOutOfBoundsException(i);
}
}
}
/**
* Sets a single element of this vector. Elements 0, 1, and 2 correspond
* to x, y, and z.
*
* @param i
* element index
* @param value
* element value
* element value throws ArrayIndexOutOfBoundsException if i is
* not in the range 0 to 2.
*/
public void set(int i, double value) {
switch (i) {
case 0: {
x = value;
break;
}
case 1: {
y = value;
break;
}
case 2: {
z = value;
break;
}
default: {
throw new ArrayIndexOutOfBoundsException(i);
}
}
}
/**
* Sets the values of this vector to those of v1.
*
* @param v1
* vector whose values are copied
*/
public void set(Vector3d v1) {
x = v1.x;
y = v1.y;
z = v1.z;
}
/**
* Adds vector v1 to v2 and places the result in this vector.
*
* @param v1
* left-hand vector
* @param v2
* right-hand vector
*/
public void add(Vector3d v1, Vector3d v2) {
x = v1.x + v2.x;
y = v1.y + v2.y;
z = v1.z + v2.z;
}
/**
* Adds this vector to v1 and places the result in this vector.
*
* @param v1
* right-hand vector
*/
public void add(Vector3d v1) {
x += v1.x;
y += v1.y;
z += v1.z;
}
/**
* Subtracts vector v1 from v2 and places the result in this vector.
*
* @param v1
* left-hand vector
* @param v2
* right-hand vector
*/
public void sub(Vector3d v1, Vector3d v2) {
x = v1.x - v2.x;
y = v1.y - v2.y;
z = v1.z - v2.z;
}
/**
* Subtracts v1 from this vector and places the result in this vector.
*
* @param v1
* right-hand vector
*/
public void sub(Vector3d v1) {
x -= v1.x;
y -= v1.y;
z -= v1.z;
}
/**
* Scales the elements of this vector by <code>s</code>.
*
* @param s
* scaling factor
*/
public void scale(double s) {
x = s * x;
y = s * y;
z = s * z;
}
/**
* Scales the elements of vector v1 by <code>s</code> and places the
* results in this vector.
*
* @param s
* scaling factor
* @param v1
* vector to be scaled
*/
public void scale(double s, Vector3d v1) {
x = s * v1.x;
y = s * v1.y;
z = s * v1.z;
}
/**
* Returns the 2 norm of this vector. This is the square root of the sum
* of the squares of the elements.
*
* @return vector 2 norm
*/
public double norm() {
return Math.sqrt(x * x + y * y + z * z);
}
/**
* Returns the square of the 2 norm of this vector. This is the sum of
* the squares of the elements.
*
* @return square of the 2 norm
*/
public double normSquared() {
return x * x + y * y + z * z;
}
/**
* Returns the Euclidean distance between this vector and vector v.
*
* @return distance between this vector and v
*/
public double distance(Vector3d v) {
double dx = x - v.x;
double dy = y - v.y;
double dz = z - v.z;
return Math.sqrt(dx * dx + dy * dy + dz * dz);
}
/**
* Returns the squared of the Euclidean distance between this vector and
* vector v.
*
* @return squared distance between this vector and v
*/
public double distanceSquared(Vector3d v) {
double dx = x - v.x;
double dy = y - v.y;
double dz = z - v.z;
return (dx * dx + dy * dy + dz * dz);
}
/**
* Returns the dot product of this vector and v1.
*
* @param v1
* right-hand vector
* @return dot product
*/
public double dot(Vector3d v1) {
return x * v1.x + y * v1.y + z * v1.z;
}
/**
* Normalizes this vector in place.
*/
public void normalize() {
double lenSqr = x * x + y * y + z * z;
double err = lenSqr - 1;
if (err > (2 * DOUBLE_PREC) || err < -(2 * DOUBLE_PREC)) {
double len = Math.sqrt(lenSqr);
x /= len;
y /= len;
z /= len;
}
}
/**
* Sets the elements of this vector to zero.
*/
public void setZero() {
x = 0;
y = 0;
z = 0;
}
/**
* Sets the elements of this vector to the prescribed values.
*
* @param x
* value for first element
* @param y
* value for second element
* @param z
* value for third element
*/
public void set(double x, double y, double z) {
this.x = x;
this.y = y;
this.z = z;
}
/**
* Computes the cross product of v1 and v2 and places the result in this
* vector.
*
* @param v1
* left-hand vector
* @param v2
* right-hand vector
*/
public void cross(Vector3d v1, Vector3d v2) {
double tmpx = v1.y * v2.z - v1.z * v2.y;
double tmpy = v1.z * v2.x - v1.x * v2.z;
double tmpz = v1.x * v2.y - v1.y * v2.x;
x = tmpx;
y = tmpy;
z = tmpz;
}
/**
* Sets the elements of this vector to uniformly distributed random
* values in a specified range, using a supplied random number
* generator.
*
* @param lower
* lower random value (inclusive)
* @param upper
* upper random value (exclusive)
* @param generator
* random number generator
*/
protected void setRandom(double lower, double upper, Random generator) {
double range = upper - lower;
x = generator.nextDouble() * range + lower;
y = generator.nextDouble() * range + lower;
z = generator.nextDouble() * range + lower;
}
/**
* Returns a string representation of this vector, consisting of the x,
* y, and z coordinates.
*
* @return string representation
*/
public String toString() {
return x + " " + y + " " + z;
}
}