/*
* Copyright (C) 2011-2015, Peter Abeles. All Rights Reserved.
*
* This file is part of Geometric Regression Library (GeoRegression).
*
* 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 georegression.geometry;
import georegression.struct.GeoTuple3D_F64;
import georegression.struct.point.Vector3D_F64;
import org.ejml.data.DenseMatrix64F;
import java.util.Random;
/**
* @author Peter Abeles
*/
// TODO create a UtilGeoTuple3D class for this and point 3d?
public class UtilVector3D_F64 {
/**
* Creates a random vector where each axis is selected from a uniform distribution.
*
* @param min minimum value
* @param max maximum value
* @param rand random number generator
* @return the new random vector
*/
public static Vector3D_F64 createRandom( double min, double max, Random rand ) {
double range = max - min;
Vector3D_F64 a = new Vector3D_F64();
a.x = range * rand.nextDouble() + min;
a.y = range * rand.nextDouble() + min;
a.z = range * rand.nextDouble() + min;
return a;
}
/**
* Checks to see if the two vectors are identical to within tolerance. Each axis is checked
* individually.
*
* @param a First vector.
* @param b Second vector.
* @param tol Tolerance for equality.
* @return true if identical and false if not.
*/
public static boolean isIdentical( Vector3D_F64 a, Vector3D_F64 b, double tol ) {
if( Math.abs( a.x - b.x ) > tol )
return false;
if( Math.abs( a.y - b.y ) > tol )
return false;
return Math.abs( a.z - b.z ) <= tol;
}
/**
* Rescales the vector such that its normal is equal to one.
*
* @param v Vector being normalized.
*/
public static void normalize( Vector3D_F64 v ) {
double a = v.norm();
v.x /= a;
v.y /= a;
v.z /= a;
}
/**
* Creates a matrix from the set of column vectors. Each vector is a column in the new matrix.
*
* @param v Set of vectors. Not modified.
* @param R If not null the vectors are stored here.
* @return Matrix.
*/
public static DenseMatrix64F createMatrix( DenseMatrix64F R, Vector3D_F64... v ) {
if( R == null ) {
R = new DenseMatrix64F( 3, v.length );
}
for( int i = 0; i < v.length; i++ ) {
R.set( 0, i, v[i].x );
R.set( 1, i, v[i].y );
R.set( 2, i, v[i].z );
}
return R;
}
/**
* Converts matrices into vectors. All matrices must be vectors with 3 elements.
*
* @param m A 3x1 or 1x3 matrix
* @return Equivalent 3D vector
*/
public static Vector3D_F64 convert( DenseMatrix64F m ) {
Vector3D_F64 v = new Vector3D_F64();
v.x = (double) m.data[0];
v.y = (double) m.data[1];
v.z = (double) m.data[2];
return v;
}
/**
* Returns the acute angle between the two vectors. Computed using the dot product.
* @param a vector
* @param b vector
* @return acute angle
*/
public static double acute(GeoTuple3D_F64 a , GeoTuple3D_F64 b ) {
double dot = a.x*b.x + a.y*b.y + a.z*b.z;
double value = dot/(a.norm()*b.norm());
if( value > 1.0 )
value = 1.0;
else if( value < -1.0 )
value = -1.0;
return Math.acos( value );
}
}