Home | History | Annotate | Download | only in math
      1 /*
      2  * Copyright (c) 2009-2010 jMonkeyEngine
      3  * All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions are
      7  * met:
      8  *
      9  * * Redistributions of source code must retain the above copyright
     10  *   notice, this list of conditions and the following disclaimer.
     11  *
     12  * * Redistributions in binary form must reproduce the above copyright
     13  *   notice, this list of conditions and the following disclaimer in the
     14  *   documentation and/or other materials provided with the distribution.
     15  *
     16  * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
     17  *   may be used to endorse or promote products derived from this software
     18  *   without specific prior written permission.
     19  *
     20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     27  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
     28  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
     29  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     30  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     31  */
     32 package com.jme3.math;
     33 
     34 import com.jme3.export.*;
     35 import com.jme3.util.BufferUtils;
     36 import com.jme3.util.TempVars;
     37 import java.io.IOException;
     38 import java.nio.FloatBuffer;
     39 
     40 /**
     41  * <code>Line</code> defines a line. Where a line is defined as infinite along
     42  * two points. The two points of the line are defined as the origin and direction.
     43  *
     44  * @author Mark Powell
     45  * @author Joshua Slack
     46  */
     47 public class Line implements Savable, Cloneable, java.io.Serializable {
     48 
     49     static final long serialVersionUID = 1;
     50 
     51     private Vector3f origin;
     52     private Vector3f direction;
     53 
     54     /**
     55      * Constructor instantiates a new <code>Line</code> object. The origin and
     56      * direction are set to defaults (0,0,0).
     57      *
     58      */
     59     public Line() {
     60         origin = new Vector3f();
     61         direction = new Vector3f();
     62     }
     63 
     64     /**
     65      * Constructor instantiates a new <code>Line</code> object. The origin
     66      * and direction are set via the parameters.
     67      * @param origin the origin of the line.
     68      * @param direction the direction of the line.
     69      */
     70     public Line(Vector3f origin, Vector3f direction) {
     71         this.origin = origin;
     72         this.direction = direction;
     73     }
     74 
     75     /**
     76      *
     77      * <code>getOrigin</code> returns the origin of the line.
     78      * @return the origin of the line.
     79      */
     80     public Vector3f getOrigin() {
     81         return origin;
     82     }
     83 
     84     /**
     85      *
     86      * <code>setOrigin</code> sets the origin of the line.
     87      * @param origin the origin of the line.
     88      */
     89     public void setOrigin(Vector3f origin) {
     90         this.origin = origin;
     91     }
     92 
     93     /**
     94      *
     95      * <code>getDirection</code> returns the direction of the line.
     96      * @return the direction of the line.
     97      */
     98     public Vector3f getDirection() {
     99         return direction;
    100     }
    101 
    102     /**
    103      *
    104      * <code>setDirection</code> sets the direction of the line.
    105      * @param direction the direction of the line.
    106      */
    107     public void setDirection(Vector3f direction) {
    108         this.direction = direction;
    109     }
    110 
    111     public float distanceSquared(Vector3f point) {
    112         TempVars vars = TempVars.get();
    113 
    114         Vector3f compVec1 = vars.vect1;
    115         Vector3f compVec2 = vars.vect2;
    116 
    117         point.subtract(origin, compVec1);
    118         float lineParameter = direction.dot(compVec1);
    119         origin.add(direction.mult(lineParameter, compVec2), compVec2);
    120         compVec2.subtract(point, compVec1);
    121         float len = compVec1.lengthSquared();
    122         vars.release();
    123         return len;
    124     }
    125 
    126     public float distance(Vector3f point) {
    127         return FastMath.sqrt(distanceSquared(point));
    128     }
    129 
    130     public void orthogonalLineFit(FloatBuffer points) {
    131         if (points == null) {
    132             return;
    133         }
    134 
    135         TempVars vars = TempVars.get();
    136 
    137         Vector3f compVec1 = vars.vect1;
    138         Vector3f compVec2 = vars.vect2;
    139         Matrix3f compMat1 = vars.tempMat3;
    140         Eigen3f compEigen1 = vars.eigen;
    141 
    142         points.rewind();
    143 
    144         // compute average of points
    145         int length = points.remaining() / 3;
    146 
    147         BufferUtils.populateFromBuffer(origin, points, 0);
    148         for (int i = 1; i < length; i++) {
    149             BufferUtils.populateFromBuffer(compVec1, points, i);
    150             origin.addLocal(compVec1);
    151         }
    152 
    153         origin.multLocal(1f / (float) length);
    154 
    155         // compute sums of products
    156         float sumXX = 0.0f, sumXY = 0.0f, sumXZ = 0.0f;
    157         float sumYY = 0.0f, sumYZ = 0.0f, sumZZ = 0.0f;
    158 
    159         points.rewind();
    160         for (int i = 0; i < length; i++) {
    161             BufferUtils.populateFromBuffer(compVec1, points, i);
    162             compVec1.subtract(origin, compVec2);
    163             sumXX += compVec2.x * compVec2.x;
    164             sumXY += compVec2.x * compVec2.y;
    165             sumXZ += compVec2.x * compVec2.z;
    166             sumYY += compVec2.y * compVec2.y;
    167             sumYZ += compVec2.y * compVec2.z;
    168             sumZZ += compVec2.z * compVec2.z;
    169         }
    170 
    171         //find the smallest eigen vector for the direction vector
    172         compMat1.m00 = sumYY + sumZZ;
    173         compMat1.m01 = -sumXY;
    174         compMat1.m02 = -sumXZ;
    175         compMat1.m10 = -sumXY;
    176         compMat1.m11 = sumXX + sumZZ;
    177         compMat1.m12 = -sumYZ;
    178         compMat1.m20 = -sumXZ;
    179         compMat1.m21 = -sumYZ;
    180         compMat1.m22 = sumXX + sumYY;
    181 
    182         compEigen1.calculateEigen(compMat1);
    183         direction = compEigen1.getEigenVector(0);
    184 
    185         vars.release();
    186     }
    187 
    188     /**
    189      *
    190      * <code>random</code> determines a random point along the line.
    191      * @return a random point on the line.
    192      */
    193     public Vector3f random() {
    194         return random(null);
    195     }
    196 
    197     /**
    198      * <code>random</code> determines a random point along the line.
    199      *
    200      * @param result Vector to store result in
    201      * @return a random point on the line.
    202      */
    203     public Vector3f random(Vector3f result) {
    204         if (result == null) {
    205             result = new Vector3f();
    206         }
    207         float rand = (float) Math.random();
    208 
    209         result.x = (origin.x * (1 - rand)) + (direction.x * rand);
    210         result.y = (origin.y * (1 - rand)) + (direction.y * rand);
    211         result.z = (origin.z * (1 - rand)) + (direction.z * rand);
    212 
    213         return result;
    214     }
    215 
    216     public void write(JmeExporter e) throws IOException {
    217         OutputCapsule capsule = e.getCapsule(this);
    218         capsule.write(origin, "origin", Vector3f.ZERO);
    219         capsule.write(direction, "direction", Vector3f.ZERO);
    220     }
    221 
    222     public void read(JmeImporter e) throws IOException {
    223         InputCapsule capsule = e.getCapsule(this);
    224         origin = (Vector3f) capsule.readSavable("origin", Vector3f.ZERO.clone());
    225         direction = (Vector3f) capsule.readSavable("direction", Vector3f.ZERO.clone());
    226     }
    227 
    228     @Override
    229     public Line clone() {
    230         try {
    231             Line line = (Line) super.clone();
    232             line.direction = direction.clone();
    233             line.origin = origin.clone();
    234             return line;
    235         } catch (CloneNotSupportedException e) {
    236             throw new AssertionError();
    237         }
    238     }
    239 }
    240