[commited] Points inside the bounds of a LineSegment

Hello,



I have been using a couple of methods to calculate whether a point is inside a line that may be interesting for others. For example, I use this to know whether a bullet is within its calculated path (it will have collided when it's not). I also added some documentation to the class.



I may have misunderstood the internals of LineSegment (I got confused about whether the the origin of the LineSegment is the center of one of its ends. I assume it's the former).



Here is the code for the added methods and the patch for everything is below.



    /**
     * <p>Returns the axis aligned bounding box that contains this LineSegment.</p>
     * @see LineSegment#getBoundingBox(BoundingBox)
     * @see BoundingBox
     */
    public BoundingBox getBoundingBox() {
       return getBoundingBox(null);
    }

    /**
     * <p>Returns the axis aligned bounding box that contains this LineSegment.</p>
     * <p>Accepts a BoundingBox to store the result, and will create a new one if
     * null is passed. The BoundingBox is returned as result.</p>
     * @see BoundingBox
     */
    public BoundingBox getBoundingBox(BoundingBox store) {
       if (store == null) store = new BoundingBox();
       store.xExtent = direction.x * extent;
       store.yExtent = direction.y * extent;
       store.zExtent = direction.z * extent;
       store.getCenter().set(origin);
       return store;
    }


    /**
     * <p>Evaluates whether a given point is contained within the axis aligned bounding box
     * that contains this LineSegment.</p><p>This function is float error aware.</p>
     */
    public boolean pointInsideBounds(Vector3f point) {
       return pointInsideBounds(point, Float.MIN_VALUE * 2);
    }

    /**
     * <p>Evaluates whether a given point is contained within the axis aligned bounding box
     * that contains this LineSegment.</p><p>This function accepts an error parameter, which
     * is added to the extent of the bounding box.</p>
     */
    public boolean pointInsideBounds(Vector3f point, float error) {

       if (FastMath.abs(point.x - origin.x) > FastMath.abs(direction.x * extent) + error) return false;
       if (FastMath.abs(point.y - origin.y) > FastMath.abs(direction.y * extent) + error) return false;
       if (FastMath.abs(point.z - origin.z) > FastMath.abs(direction.z * extent) + error) return false;

       return true;
    }




Index: C:/Documents and Settings/jjmontes/Mis documentos/Proyectos/jme2/jme2/src/com/jme/math/LineSegment.java
===================================================================
--- C:/Documents and Settings/jjmontes/Mis documentos/Proyectos/jme2/jme2/src/com/jme/math/LineSegment.java   (revision 4054)
+++ C:/Documents and Settings/jjmontes/Mis documentos/Proyectos/jme2/jme2/src/com/jme/math/LineSegment.java   (working copy)
@@ -34,6 +34,7 @@
 import java.io.IOException;
 import java.io.Serializable;
 
+import com.jme.bounding.BoundingBox;
 import com.jme.util.export.InputCapsule;
 import com.jme.util.export.JMEExporter;
 import com.jme.util.export.JMEImporter;
@@ -41,8 +42,18 @@
 import com.jme.util.export.Savable;
 
 /**
- * <code>LineSegment</code>
- *
+ * <p>LineSegment represents a segment in the space. This is a portion of a Line
+ * that has a limited start and end points.</p>
+ * <p>A LineSegment is defined by an origin, a direction and an extent (or length).
+ * Direction should be a normalized vector. It is not internally normalized.</p>
+ * <p>This class provides methods to calculate distances between LineSegments, Rays and Vectors.
+ * It is also possible to retrieve both end points of the segment {@link LineSegment#getPositiveEnd(Vector3f)}
+ * and {@link LineSegment#getNegativeEnd(Vector3f)}. There are also methods to check whether
+ * a point is within the Segment bounds.</p>
+ *
+ * @see LineSegment
+ * @see Ray
+ * @see Vector3f
  * @author Mark Powell
  * @author Joshua Slack
  */
@@ -69,12 +80,27 @@
       this.extent = ls.getExtent();
    }
 
+   /**
+    * <p>Creates a new LineSegment with the given origin, direction and extent.</p>
+    * <p>Note that the origin is not one of the ends of the LineSegment, but its center.</p>
+    */
    public LineSegment(Vector3f origin, Vector3f direction, float extent) {
       this.origin = origin;
       this.direction = direction;
       this.extent = extent;
    }
 
+   /**
+    * <p>Creates a new LineSegment with a given origin and end. This constructor will calculate the
+    * center, the direction and the extent.</p>
+    */
+   public LineSegment(Vector3f start, Vector3f end) {
+      this.origin = new Vector3f(0.5f * (start.x + end.x), 0.5f * (start.y + end.y), 0.5f * (start.z + end.z));
+      this.direction = end.subtract(start);
+      this.extent = direction.length();
+      direction.normalizeLocal();
+   }
+
    public void set(LineSegment ls) {
       this.origin = new Vector3f(ls.getOrigin());
       this.direction = new Vector3f(ls.getDirection());
@@ -566,7 +592,7 @@
         direction = (Vector3f)capsule.readSavable("direction", Vector3f.ZERO.clone());
         extent = capsule.readFloat("extent", 0);
     }
-   
+
     public Class<? extends LineSegment> getClassTag() {
         return this.getClass();
     }
@@ -582,4 +608,52 @@
             throw new AssertionError();
         }
     }
+
+    /**
+     * <p>Returns the axis aligned bounding box that contains this LineSegment.</p>
+     * @see LineSegment#getBoundingBox(BoundingBox)
+     * @see BoundingBox
+     */
+    public BoundingBox getBoundingBox() {
+       return getBoundingBox(null);
+    }
+
+    /**
+     * <p>Returns the axis aligned bounding box that contains this LineSegment.</p>
+     * <p>Accepts a BoundingBox to store the result, and will create a new one if
+     * null is passed. The BoundingBox is returned as result.</p>
+     * @see BoundingBox
+     */
+    public BoundingBox getBoundingBox(BoundingBox store) {
+       if (store == null) store = new BoundingBox();
+       store.xExtent = direction.x * extent;
+       store.yExtent = direction.y * extent;
+       store.zExtent = direction.z * extent;
+       store.getCenter().set(origin);
+       return store;
+    }
+
+
+    /**
+     * <p>Evaluates whether a given point is contained within the axis aligned bounding box
+     * that contains this LineSegment.</p><p>This function is float error aware.</p>
+     */
+    public boolean pointInsideBounds(Vector3f point) {
+       return pointInsideBounds(point, Float.MIN_VALUE * 2);
+    }
+
+    /**
+     * <p>Evaluates whether a given point is contained within the axis aligned bounding box
+     * that contains this LineSegment.</p><p>This function accepts an error parameter, which
+     * is added to the extent of the bounding box.</p>
+     */
+    public boolean pointInsideBounds(Vector3f point, float error) {
+
+       if (FastMath.abs(point.x - origin.x) > FastMath.abs(direction.x * extent) + error) return false;
+       if (FastMath.abs(point.y - origin.y) > FastMath.abs(direction.y * extent) + error) return false;
+       if (FastMath.abs(point.z - origin.z) > FastMath.abs(direction.z * extent) + error) return false;
+
+       return true;
+    }
+
 }


I have removed the getBoundingBox methods from the patch above. I am not using them and they are not properly tested.



I am not really convinced about how appropriate this method is, so feel free to post feedback on that. Other than that, if there are no comments I would push the isPointWithinBounds() method and the extra documentation:



Index: C:/Documents and Settings/jjmontes/Mis documentos/Proyectos/jme2/jme2/src/com/jme/math/LineSegment.java
===================================================================
--- C:/Documents and Settings/jjmontes/Mis documentos/Proyectos/jme2/jme2/src/com/jme/math/LineSegment.java   (revision 4054)
+++ C:/Documents and Settings/jjmontes/Mis documentos/Proyectos/jme2/jme2/src/com/jme/math/LineSegment.java   (working copy)
@@ -41,8 +41,16 @@
 import com.jme.util.export.Savable;
 
 /**
- * <code>LineSegment</code>
- *
+ * <p>LineSegment represents a segment in the space. This is a portion of a Line
+ * that has a limited start and end points.</p>
+ * <p>A LineSegment is defined by an origin, a direction and an extent (or length).
+ * Direction should be a normalized vector. It is not internally normalized.</p>
+ * <p>This class provides methods to calculate distances between LineSegments, Rays and Vectors.
+ * It is also possible to retrieve both end points of the segment {@link LineSegment#getPositiveEnd(Vector3f)}
+ * and {@link LineSegment#getNegativeEnd(Vector3f)}. There are also methods to check whether
+ * a point is within the segment bounds.</p>
+ *
+ * @see Ray
  * @author Mark Powell
  * @author Joshua Slack
  */
@@ -69,12 +77,27 @@
       this.extent = ls.getExtent();
    }
 
+   /**
+    * <p>Creates a new LineSegment with the given origin, direction and extent.</p>
+    * <p>Note that the origin is not one of the ends of the LineSegment, but its center.</p>
+    */
    public LineSegment(Vector3f origin, Vector3f direction, float extent) {
       this.origin = origin;
       this.direction = direction;
       this.extent = extent;
    }
 
+   /**
+    * <p>Creates a new LineSegment with a given origin and end. This constructor will calculate the
+    * center, the direction and the extent.</p>
+    */
+   public LineSegment(Vector3f start, Vector3f end) {
+      this.origin = new Vector3f(0.5f * (start.x + end.x), 0.5f * (start.y + end.y), 0.5f * (start.z + end.z));
+      this.direction = end.subtract(start);
+      this.extent = direction.length();
+      direction.normalizeLocal();
+   }
+
    public void set(LineSegment ls) {
       this.origin = new Vector3f(ls.getOrigin());
       this.direction = new Vector3f(ls.getDirection());
@@ -566,7 +589,7 @@
         direction = (Vector3f)capsule.readSavable("direction", Vector3f.ZERO.clone());
         extent = capsule.readFloat("extent", 0);
     }
-   
+
     public Class<? extends LineSegment> getClassTag() {
         return this.getClass();
     }
@@ -582,4 +605,27 @@
             throw new AssertionError();
         }
     }
+
+    /**
+     * <p>Evaluates whether a given point is contained within the axis aligned bounding box
+     * that contains this LineSegment.</p><p>This function is float error aware.</p>
+     */
+    public boolean isPointInsideBounds(Vector3f point) {
+       return isPointInsideBounds(point, Float.MIN_VALUE);
+    }
+
+    /**
+     * <p>Evaluates whether a given point is contained within the axis aligned bounding box
+     * that contains this LineSegment.</p><p>This function accepts an error parameter, which
+     * is added to the extent of the bounding box.</p>
+     */
+    public boolean isPointInsideBounds(Vector3f point, float error) {
+
+       if (FastMath.abs(point.x - origin.x) > FastMath.abs(direction.x * extent) + error) return false;
+       if (FastMath.abs(point.y - origin.y) > FastMath.abs(direction.y * extent) + error) return false;
+       if (FastMath.abs(point.z - origin.z) > FastMath.abs(direction.z * extent) + error) return false;
+
+       return true;
+    }
+
 }

Commited. Revision 4060:



Added documentation and methods to calculate if a point is inside the bounds of a LineSegment (http://www.jmonkeyengine.com/jmeforum/index.php?topic=9907.0).