[Arakhnę-Dev] [414] * Fixing the functions intersects() and contains() of the Path2f in the case it is open or close.

[ Thread Index | Date Index | More arakhne.org/dev Archives ]


Revision: 414
Author:   galland
Date:     2013-04-05 23:45:07 +0200 (Fri, 05 Apr 2013)
Log Message:
-----------
* Fixing the functions intersects() and contains() of the Path2f in the case it is open or close.

Modified Paths:
--------------
    trunk/math/src/main/java/org/arakhne/afc/math/continous/object2d/Ellipse2f.java
    trunk/math/src/main/java/org/arakhne/afc/math/continous/object2d/Path2f.java
    trunk/math/src/main/java/org/arakhne/afc/math/continous/object2d/Segment2f.java
    trunk/math/src/test/java/org/arakhne/afc/math/continous/object2d/Ellipse2fTest.java
    trunk/math/src/test/java/org/arakhne/afc/math/continous/object2d/Segment2fTest.java

Added Paths:
-----------
    trunk/math/src/test/java/org/arakhne/afc/math/continous/object2d/AbstractPath2fTestCase.java
    trunk/math/src/test/java/org/arakhne/afc/math/continous/object2d/ClosePath2fTest.java
    trunk/math/src/test/java/org/arakhne/afc/math/continous/object2d/OpenPath2fTest.java

Modified: trunk/math/src/main/java/org/arakhne/afc/math/continous/object2d/Ellipse2f.java
===================================================================
--- trunk/math/src/main/java/org/arakhne/afc/math/continous/object2d/Ellipse2f.java	2013-04-05 20:39:57 UTC (rev 413)
+++ trunk/math/src/main/java/org/arakhne/afc/math/continous/object2d/Ellipse2f.java	2013-04-05 21:45:07 UTC (rev 414)
@@ -164,7 +164,7 @@
 	 */
 	public static boolean intersectsEllipseLine(float ex, float ey, float ew, float eh, float x1, float y1, float x2, float y2) {
 		// If the ellipse or line segment are empty, return no intersections.
-		if (eh<=0f || ew<=0f || x1==x2 || y1==y2) {
+		if (eh<=0f || ew<=0f) {
 			return false;
 		}
 
@@ -215,7 +215,7 @@
 	 */
 	public static boolean intersectsEllipseSegment(float ex, float ey, float ew, float eh, float x1, float y1, float x2, float y2) {
 		// If the ellipse or line segment are empty, return no intersections.
-		if (eh<=0f || ew<=0f || x1==x2 || y1==y2) {
+		if (eh<=0f || ew<=0f) {
 			return false;
 		}
 

Modified: trunk/math/src/main/java/org/arakhne/afc/math/continous/object2d/Path2f.java
===================================================================
--- trunk/math/src/main/java/org/arakhne/afc/math/continous/object2d/Path2f.java	2013-04-05 20:39:57 UTC (rev 413)
+++ trunk/math/src/main/java/org/arakhne/afc/math/continous/object2d/Path2f.java	2013-04-05 21:45:07 UTC (rev 414)
@@ -67,7 +67,7 @@
 	public static boolean contains(PathIterator2f pi, float x, float y) {
 		// Copied from the AWT API
 		int mask = (pi.getWindingRule() == PathWindingRule.NON_ZERO ? -1 : 1);
-		int cross = computeCrossingsFromPoint(pi, x, y);
+		int cross = computeCrossingsFromPoint(pi, x, y, false, true);
 		return ((cross & mask) != 0);
 	}
 
@@ -93,7 +93,11 @@
             return false;
         }
         int mask = (pi.getWindingRule() == PathWindingRule.NON_ZERO ? -1 : 2);
-        int crossings = computeCrossingsFromRect(pi, rx, ry, rx+rwidth, ry+rheight);
+        int crossings = computeCrossingsFromRect(
+        		pi, 
+        		rx, ry, rx+rwidth, ry+rheight,
+        		false,
+        		true);
         return (crossings != MathConstants.SHAPE_INTERSECTS &&
                 (crossings & mask) != 0);
 	}
@@ -134,7 +138,7 @@
 			return false;
 		}
 		int mask = (pi.getWindingRule() == PathWindingRule.NON_ZERO ? -1 : 2);
-		int crossings = computeCrossingsFromRect(pi, x, y, x+w, y+h);
+		int crossings = computeCrossingsFromRect(pi, x, y, x+w, y+h, false, true);
 		return (crossings == MathConstants.SHAPE_INTERSECTS ||
 				(crossings & mask) != 0);
 	}
@@ -157,6 +161,34 @@
 	 * @return the crossing
 	 */
 	public static int computeCrossingsFromPoint(PathIterator2f pi, float px, float py) {
+		return computeCrossingsFromPoint(pi, px, py, true, true);
+	}
+	
+	/**
+	 * Calculates the number of times the given path
+	 * crosses the ray extending to the right from (px,py).
+	 * If the point lies on a part of the path,
+	 * then no crossings are counted for that intersection.
+	 * +1 is added for each crossing where the Y coordinate is increasing
+	 * -1 is added for each crossing where the Y coordinate is decreasing
+	 * The return value is the sum of all crossings for every segment in
+	 * the path.
+	 * The path must start with a MOVE_TO, otherwise an exception is
+	 * thrown.
+	 * 
+	 * @param pi is the description of the path.
+	 * @param px is the reference point to test.
+	 * @param py is the reference point to test.
+	 * @param closeable indicates if the shape is automatically closed or not.
+	 * @param onlyIntersectWhenOpen indicates if the crossings is set to 0 when
+	 * the path is open and there is not SHAPE_INTERSECT.
+	 * @return the crossing
+	 */
+	static int computeCrossingsFromPoint(
+			PathIterator2f pi,
+			float px, float py,
+			boolean closeable,
+			boolean onlyIntersectWhenOpen) {	
 		// Copied from the AWT API
 		if (!pi.hasNext()) return 0;
 		PathElement2f element;
@@ -166,12 +198,13 @@
 			throw new IllegalArgumentException("missing initial moveto in path definition"); //$NON-NLS-1$
 		}
 
+		Path2f subPath;
 		float movx = element.toX;
 		float movy = element.toY;
 		float curx = movx;
 		float cury = movy;
 		float endx, endy;
-		int crossings = 0;
+		int r, crossings = 0;
 		while (pi.hasNext()) {
 			element = pi.next();
 			switch (element.type) {
@@ -182,6 +215,8 @@
 			case LINE_TO:
 				endx = element.toX;
 				endy = element.toY;
+				if (endx==px && endy==py)
+					return MathConstants.SHAPE_INTERSECTS;
 				crossings += Segment2f.computeCrossingsFromPoint(
 						px, py,
 						curx, cury,
@@ -192,28 +227,51 @@
 			case QUAD_TO:
 				endx = element.toX;
 				endy = element.toY;
-				crossings += computeQuadCurveCrossingsFromPoint(
-						px, py,
-						curx, cury,
+				if (endx==px && endy==py)
+					return MathConstants.SHAPE_INTERSECTS;
+				subPath = new Path2f();
+				subPath.moveTo(curx, cury);
+				subPath.quadTo(
 						element.ctrlX1, element.ctrlY1,
-						endx, endy, 0);
+						endx, endy);
+				r = computeCrossingsFromPoint(
+						subPath.getPathIterator(MathConstants.SPLINE_APPROXIMATION_RATIO),
+						px, py,
+						false,
+						false);
+				if (r==MathConstants.SHAPE_INTERSECTS)
+					return r;
+				crossings += r;
 				curx = endx;
 				cury = endy;
 				break;
 			case CURVE_TO:
 				endx = element.toX;
 				endy = element.toY;
-				crossings += computeCubicCurveCrossingsFromPoint(
-						px, py,
-						curx, cury,
+				if (endx==px || endy==py)
+					return MathConstants.SHAPE_INTERSECTS;
+				subPath = new Path2f();
+				subPath.moveTo(curx, cury);
+				subPath.curveTo(
 						element.ctrlX1, element.ctrlY1,
 						element.ctrlX2, element.ctrlY2,
-						endx, endy, 0);
+						endx, endy);
+				r = computeCrossingsFromPoint(
+						subPath.getPathIterator(MathConstants.SPLINE_APPROXIMATION_RATIO),
+						px, py,
+						false,
+						false);
+				if (r==MathConstants.SHAPE_INTERSECTS) {
+					return r;
+				}
+				crossings += r;
 				curx = endx;
 				cury = endy;
 				break;
 			case CLOSE:
 				if (cury != movy || curx != movx) {
+					if (movx==px && movy==py)
+						return MathConstants.SHAPE_INTERSECTS;
 					crossings += Segment2f.computeCrossingsFromPoint(
 							px, py,
 							curx, cury,
@@ -225,13 +283,28 @@
 			default:
 			}
 		}
+		
+		assert(crossings!=MathConstants.SHAPE_INTERSECTS);
 
-		if (cury != movy) {
-			crossings += Segment2f.computeCrossingsFromPoint(
-					px, py,
-					curx, cury,
-					movx, movy);
+		boolean isOpen = (curx != movx) || (cury != movy);
+		
+		if (isOpen) {
+			if (closeable) {
+				// Not closed
+				if (movx==px && movy==py)
+					return MathConstants.SHAPE_INTERSECTS;
+				crossings += Segment2f.computeCrossingsFromPoint(
+						px, py,
+						curx, cury,
+						movx, movy);
+			}
+			else if (onlyIntersectWhenOpen) {
+				// Assume that when is the path is open, only
+				// SHAPE_INTERSECTS may be return
+				crossings = 0;
+			}
 		}
+
 		return crossings;
 	}
 
@@ -247,7 +320,7 @@
 	 * @return the crossing or {@link MathConstants#SHAPE_INTERSECTS}
 	 */
 	public static int computeCrossingsFromEllipse(PathIterator2f pi, float ex, float ey, float ew, float eh) {
-		return computeCrossingsFromEllipse(0, pi, ex, ey, ew, eh, true);
+		return computeCrossingsFromEllipse(0, pi, ex, ey, ew, eh, true, true);
 	}
 	
 	/**
@@ -261,9 +334,16 @@
 	 * @param ew is the width of the ellipse.
 	 * @param eh is the height of the ellipse.
 	 * @param closeable indicates if the shape is automatically closed or not.
+	 * @param onlyIntersectWhenOpen indicates if the crossings is set to 0 when
+	 * the path is open and there is not SHAPE_INTERSECT.
 	 * @return the crossing or {@link MathConstants#SHAPE_INTERSECTS}
 	 */
-	static int computeCrossingsFromEllipse(int crossings, PathIterator2f pi, float ex, float ey, float ew, float eh, boolean closeable) {	
+	static int computeCrossingsFromEllipse(
+			int crossings, 
+			PathIterator2f pi, 
+			float ex, float ey, float ew, float eh, 
+			boolean closeable,
+			boolean onlyIntersectWhenOpen) {	
 		// Copied from the AWT API
 		if (!pi.hasNext()) return 0;
 		PathElement2f element;
@@ -294,6 +374,9 @@
 						ex, ey, ew, eh,
 						curx, cury,
 						endx, endy);
+				if (numCrosses==MathConstants.SHAPE_INTERSECTS) {
+					return numCrosses;
+				}
 				curx = endx;
 				cury = endy;
 				break;
@@ -302,7 +385,7 @@
 				endx = element.toX;
 				endy = element.toY;
 				Path2f localPath = new Path2f();
-				localPath.moveTo(element.fromX, element.fromY);
+				localPath.moveTo(curx, cury);
 				localPath.quadTo(
 						element.ctrlX1, element.ctrlY1,
 						endx, endy);
@@ -310,7 +393,11 @@
 						numCrosses,
 						localPath.getPathIterator(MathConstants.SPLINE_APPROXIMATION_RATIO),
 						ex, ey, ew, eh,
+						false,
 						false);
+				if (numCrosses==MathConstants.SHAPE_INTERSECTS) {
+					return numCrosses;
+				}
 				curx = endx;
 				cury = endy;
 				break;
@@ -319,7 +406,7 @@
 				endx = element.toX;
 				endy = element.toY;
 				Path2f localPath = new Path2f();
-				localPath.moveTo(element.fromX, element.fromY);
+				localPath.moveTo(curx, cury);
 				localPath.curveTo(
 						element.ctrlX1, element.ctrlY1,
 						element.ctrlX2, element.ctrlY2,
@@ -328,7 +415,11 @@
 						numCrosses,
 						localPath.getPathIterator(MathConstants.SPLINE_APPROXIMATION_RATIO),
 						ex, ey, ew, eh,
+						false,
 						false);
+				if (numCrosses==MathConstants.SHAPE_INTERSECTS) {
+					return numCrosses;
+				}
 				curx = endx;
 				cury = endy;
 				break;
@@ -339,6 +430,9 @@
 							ex, ey, ew, eh,
 							curx, cury,
 							movx, movy);
+					if (numCrosses==MathConstants.SHAPE_INTERSECTS) {
+						return numCrosses;
+					}
 				}
 				curx = movx;
 				cury = movy;
@@ -347,12 +441,24 @@
 			}
 		}
 
-		if (numCrosses!=MathConstants.SHAPE_INTERSECTS && closeable && cury != movy) {
-			numCrosses = Segment2f.computeCrossingsFromEllipse(
-					numCrosses,
-					ex, ey, ew, eh,
-					curx, cury,
-					movx, movy);
+		assert(numCrosses!=MathConstants.SHAPE_INTERSECTS);
+
+		boolean isOpen = (curx != movx) || (cury != movy);
+
+		if (isOpen) {
+			if (closeable) {
+				// Not closed
+				numCrosses = Segment2f.computeCrossingsFromEllipse(
+						numCrosses,
+						ex, ey, ew, eh,
+						curx, cury,
+						movx, movy);
+			}
+			else if (onlyIntersectWhenOpen) {
+				// Assume that when is the path is open, only
+				// SHAPE_INTERSECTS may be return
+				numCrosses = 0;
+			}
 		}
 		
 		return numCrosses;
@@ -369,7 +475,7 @@
 	 * @return the crossing or {@link MathConstants#SHAPE_INTERSECTS}.
 	 */
 	public static int computeCrossingsFromCircle(PathIterator2f pi, float cx, float cy, float radius) {
-		return computeCrossingsFromCircle(0, pi, cx, cy, radius, true);
+		return computeCrossingsFromCircle(0, pi, cx, cy, radius, true, true);
 	}
 	
 	/**
@@ -382,9 +488,16 @@
 	 * @param cy is the center of the circle.
 	 * @param radius is the radius of the circle.
 	 * @param closeable indicates if the shape is automatically closed or not.
+	 * @param onlyIntersectWhenOpen indicates if the crossings is set to 0 when
+	 * the path is open and there is not SHAPE_INTERSECT.
 	 * @return the crossing
 	 */
-	static int computeCrossingsFromCircle(int crossings, PathIterator2f pi, float cx, float cy, float radius, boolean closeable) {	
+	static int computeCrossingsFromCircle(
+			int crossings, 
+			PathIterator2f pi,
+			float cx, float cy, float radius,
+			boolean closeable,
+			boolean onlyIntersectWhenOpen) {	
 		// Copied from the AWT API
 		if (!pi.hasNext()) return 0;
 		PathElement2f element;
@@ -415,6 +528,9 @@
 						cx, cy, radius,
 						curx, cury,
 						endx, endy);
+				if (numCrosses==MathConstants.SHAPE_INTERSECTS) {
+					return numCrosses;
+				}
 				curx = endx;
 				cury = endy;
 				break;
@@ -431,7 +547,11 @@
 						numCrosses,
 						localPath.getPathIterator(MathConstants.SPLINE_APPROXIMATION_RATIO),
 						cx, cy, radius,
+						false,
 						false);
+				if (numCrosses==MathConstants.SHAPE_INTERSECTS) {
+					return numCrosses;
+				}
 				curx = endx;
 				cury = endy;
 				break;
@@ -449,7 +569,11 @@
 						numCrosses,
 						localPath.getPathIterator(MathConstants.SPLINE_APPROXIMATION_RATIO),
 						cx, cy, radius,
+						false,
 						false);
+				if (numCrosses==MathConstants.SHAPE_INTERSECTS) {
+					return numCrosses;
+				}
 				curx = endx;
 				cury = endy;
 				break;
@@ -460,6 +584,9 @@
 							cx, cy, radius,
 							curx, cury,
 							movx, movy);
+					if (numCrosses==MathConstants.SHAPE_INTERSECTS) {
+						return numCrosses;
+					}
 				}
 				curx = movx;
 				cury = movy;
@@ -467,13 +594,25 @@
 			default:
 			}
 		}
+		
+		assert(numCrosses!=MathConstants.SHAPE_INTERSECTS);
 
-		if (numCrosses!=MathConstants.SHAPE_INTERSECTS && closeable && cury != movy) {
-			numCrosses = Segment2f.computeCrossingsFromCircle(
-					numCrosses,
-					cx, cy, radius,
-					curx, cury,
-					movx, movy);
+		boolean isOpen = (curx != movx) || (cury != movy);
+
+		if (isOpen) {
+			if (closeable) {
+				// Not closed
+				numCrosses = Segment2f.computeCrossingsFromCircle(
+						numCrosses,
+						cx, cy, radius,
+						curx, cury,
+						movx, movy);
+			}
+			else if (onlyIntersectWhenOpen) {
+				// Assume that when is the path is open, only
+				// SHAPE_INTERSECTS may be return
+				numCrosses = 0;
+			}
 		}
 		
 		return numCrosses;
@@ -509,7 +648,7 @@
 	 */
 	static int computeCrossingsFromSegment(int crossings, PathIterator2f pi, float x1, float y1, float x2, float y2, boolean closeable) {	
 		// Copied from the AWT API
-		if (!pi.hasNext()) return 0;
+		if (!pi.hasNext() || crossings==MathConstants.SHAPE_INTERSECTS) return crossings;
 		PathElement2f element;
 
 		element = pi.next();
@@ -537,7 +676,10 @@
 						numCrosses,
 						x1, y1, x2, y2,
 						curx, cury,
-						endx, endy);
+						endx, endy,
+						true);
+				if (numCrosses==MathConstants.SHAPE_INTERSECTS)
+					return numCrosses;
 				curx = endx;
 				cury = endy;
 				break;
@@ -546,7 +688,7 @@
 				endx = element.toX;
 				endy = element.toY;
 				Path2f localPath = new Path2f();
-				localPath.moveTo(element.fromX, element.fromY);
+				localPath.moveTo(curx, cury);
 				localPath.quadTo(
 						element.ctrlX1, element.ctrlY1,
 						endx, endy);
@@ -555,6 +697,8 @@
 						localPath.getPathIterator(MathConstants.SPLINE_APPROXIMATION_RATIO),
 						x1, y1, x2, y2,
 						false);
+				if (numCrosses==MathConstants.SHAPE_INTERSECTS)
+					return numCrosses;
 				curx = endx;
 				cury = endy;
 				break;
@@ -563,7 +707,7 @@
 				endx = element.toX;
 				endy = element.toY;
 				Path2f localPath = new Path2f();
-				localPath.moveTo(element.fromX, element.fromY);
+				localPath.moveTo(curx, cury);
 				localPath.curveTo(
 						element.ctrlX1, element.ctrlY1,
 						element.ctrlX2, element.ctrlY2,
@@ -573,6 +717,8 @@
 						localPath.getPathIterator(MathConstants.SPLINE_APPROXIMATION_RATIO),
 						x1, y1, x2, y2,
 						false);
+				if (numCrosses==MathConstants.SHAPE_INTERSECTS)
+					return numCrosses;
 				curx = endx;
 				cury = endy;
 				break;
@@ -582,8 +728,10 @@
 							numCrosses,
 							x1, y1, x2, y2,
 							curx, cury,
-							movx, movy);
+							movx, movy,
+							true);
 				}
+				if (numCrosses!=0)	return numCrosses;
 				curx = movx;
 				cury = movy;
 				break;
@@ -591,154 +739,55 @@
 			}
 		}
 
-		if (numCrosses!=MathConstants.SHAPE_INTERSECTS && closeable && cury != movy) {
-			numCrosses = Segment2f.computeCrossingsFromSegment(
-					numCrosses,
-					x1, y1, x2, y2,
-					curx, cury,
-					movx, movy);
+		assert(numCrosses!=MathConstants.SHAPE_INTERSECTS);
+		
+		boolean isOpen = (curx != movx) || (cury != movy);
+		
+		if (isOpen) {
+			if (closeable) {
+				numCrosses = Segment2f.computeCrossingsFromSegment(
+						numCrosses,
+						x1, y1, x2, y2,
+						curx, cury,
+						movx, movy,
+						true);
+			}
+			else {
+				// Assume that when is the path is open, only
+				// SHAPE_INTERSECTS may be return
+				numCrosses = 0;
+			}
 		}
 		
 		return numCrosses;
 	}
 
 	/**
-	 * Calculates the number of times the quad from (x0,y0) to (x1,y1)
-	 * crosses the ray extending to the right from (px,py).
-	 * If the point lies on a part of the curve,
-	 * then no crossings are counted for that intersection.
-	 * the level parameter should be 0 at the top-level call and will count
-	 * up for each recursion level to prevent infinite recursion
-	 * +1 is added for each crossing where the Y coordinate is increasing
-	 * -1 is added for each crossing where the Y coordinate is decreasing
+	 * Accumulate the number of times the path crosses the shadow
+	 * extending to the right of the rectangle.  See the comment
+	 * for the RECT_INTERSECTS constant for more complete details.
+	 * The return value is the sum of all crossings for both the
+	 * top and bottom of the shadow for every segment in the path,
+	 * or the special value RECT_INTERSECTS if the path ever enters
+	 * the interior of the rectangle.
+	 * The path must start with a SEG_MOVETO, otherwise an exception is
+	 * thrown.
+	 * The caller must check r[xy]{min,max} for NaN values.
 	 * 
-	 * @param px is the reference point to test.
-	 * @param py is the reference point to test.
-	 * @param x0 is the first point of the quad curve.
-	 * @param y0 is the first point of the quad curve.
-	 * @param xc is the control point of the quad curve.
-	 * @param yc is the control point of the quad curve.
-	 * @param x1 is the last point of the quad curve.
-	 * @param y1 is the last point of the quad curve.
-	 * @param level may be zero.
-	 * @return the crossing.
+	 * @param pi is the iterator on the path elements.
+	 * @param rxmin is the first corner of the rectangle.
+	 * @param rymin is the first corner of the rectangle.
+	 * @param rxmax is the second corner of the rectangle.
+	 * @param rymax is the second corner of the rectangle.
+	 * @return the crossings.
 	 */
-	static int computeQuadCurveCrossingsFromPoint(float px, float py,
-			float x0, float y0,
-			float xc, float yc,
-			float x1, float y1,
-			int level) {
-		// Copied from AWT API
-		if (py <  y0 && py <  yc && py <  y1) return 0;
-		if (py >= y0 && py >= yc && py >= y1) return 0;
-		// Note y0 could equal y1...
-		if (px >= x0 && px >= xc && px >= x1) return 0;
-		if (px <  x0 && px <  xc && px <  x1) {
-			if (py >= y0) {
-				if (py < y1) return 1;
-			} else {
-				// py < y0
-				if (py >= y1) return -1;
-			}
-			// py outside of y01 range, and/or y0==y1
-			return 0;
-		}
-		// float precision only has 52 bits of mantissa
-		if (level > 52) return Segment2f.computeCrossingsFromPoint(px, py, x0, y0, x1, y1);
-		float x0c = (x0 + xc) / 2;
-		float y0c = (y0 + yc) / 2;
-		float xc1 = (xc + x1) / 2;
-		float yc1 = (yc + y1) / 2;
-		float nxc = (x0c + xc1) / 2;
-		float nyc = (y0c + yc1) / 2;
-		if (Double.isNaN(nxc) || Double.isNaN(nyc)) {
-			// [xy]c are NaN if any of [xy]0c or [xy]c1 are NaN
-			// [xy]0c or [xy]c1 are NaN if any of [xy][0c1] are NaN
-			// These values are also NaN if opposing infinities are added
-			return 0;
-		}
-		return (computeQuadCurveCrossingsFromPoint(px, py,
-				x0, y0, x0c, y0c, nxc, nyc,
-				level+1) +
-				computeQuadCurveCrossingsFromPoint(px, py,
-						nxc, nyc, xc1, yc1, x1, y1,
-						level+1));
+	public static int computeCrossingsFromRect(PathIterator2f pi,
+			float rxmin, float rymin,
+			float rxmax, float rymax) {
+		return computeCrossingsFromRect(pi, rxmin, rymin, rxmax, rymax, true, true);
 	}
 
 	/**
-	 * Calculates the number of times the cubic from (x0,y0) to (x1,y1)
-	 * crosses the ray extending to the right from (px,py).
-	 * If the point lies on a part of the curve,
-	 * then no crossings are counted for that intersection.
-	 * the level parameter should be 0 at the top-level call and will count
-	 * up for each recursion level to prevent infinite recursion
-	 * +1 is added for each crossing where the Y coordinate is increasing
-	 * 
-	 * @param px is the reference point to test.
-	 * @param py is the reference point to test.
-	 * @param x0 is the first point of the quad curve.
-	 * @param y0 is the first point of the quad curve.
-	 * @param xc0 is the first control point of the cubic curve.
-	 * @param yc0 is the first control point of the cubic curve.
-	 * @param xc1 is the second control point of the cubic curve.
-	 * @param yc1 is the second control point of the cubic curve.
-	 * @param x1 is the last point of the quad curve.
-	 * @param y1 is the last point of the quad curve.
-	 * @param level may be zero.
-	 * @return the crossing.
-	 * -1 is added for each crossing where the Y coordinate is decreasing
-	 */
-	static int computeCubicCurveCrossingsFromPoint(
-			float px, float py,
-			float x0, float y0,
-			float xc0, float yc0,
-			float xc1, float yc1,
-			float x1, float y1,
-			int level) {
-		// Copied from AWT API
-		if (py <  y0 && py <  yc0 && py <  yc1 && py <  y1) return 0;
-		if (py >= y0 && py >= yc0 && py >= yc1 && py >= y1) return 0;
-		// Note y0 could equal yc0...
-		if (px >= x0 && px >= xc0 && px >= xc1 && px >= x1) return 0;
-		if (px <  x0 && px <  xc0 && px <  xc1 && px <  x1) {
-			if (py >= y0) {
-				if (py < y1) return 1;
-			} else {
-				// py < y0
-				if (py >= y1) return -1;
-			}
-			// py outside of y01 range, and/or y0==yc0
-			return 0;
-		}
-		// float precision only has 52 bits of mantissa
-		if (level > 52) return Segment2f.computeCrossingsFromPoint(px, py, x0, y0, x1, y1);
-		float xmid = (xc0 + xc1) / 2;
-		float ymid = (yc0 + yc1) / 2;
-		float nxc0 = (x0 + xc0) / 2;
-		float nyc0 = (y0 + yc0) / 2;
-		float nxc1 = (xc1 + x1) / 2;
-		float nyc1 = (yc1 + y1) / 2;
-		float xc0m = (nxc0 + xmid) / 2;
-		float yc0m = (nyc0 + ymid) / 2;
-		float xmc1 = (xmid + nxc1) / 2;
-		float ymc1 = (ymid + nyc1) / 2;
-		xmid = (xc0m + xmc1) / 2;
-		ymid = (yc0m + ymc1) / 2;
-		if (Double.isNaN(xmid) || Double.isNaN(ymid)) {
-			// [xy]mid are NaN if any of [xy]c0m or [xy]mc1 are NaN
-			// [xy]c0m or [xy]mc1 are NaN if any of [xy][c][01] are NaN
-			// These values are also NaN if opposing infinities are added
-			return 0;
-		}
-		return (computeCubicCurveCrossingsFromPoint(px, py,
-				x0, y0, nxc0, nyc0,
-				xc0m, yc0m, xmid, ymid, level+1) +
-				computeCubicCurveCrossingsFromPoint(px, py,
-						xmid, ymid, xmc1, ymc1,
-						nxc1, nyc1, x1, y1, level+1));
-	}
-
-	/**
 	 * Accumulate the number of times the path crosses the shadow
 	 * extending to the right of the rectangle.  See the comment
 	 * for the RECT_INTERSECTS constant for more complete details.
@@ -755,11 +804,16 @@
 	 * @param rymin is the first corner of the rectangle.
 	 * @param rxmax is the second corner of the rectangle.
 	 * @param rymax is the second corner of the rectangle.
+	 * @param closeable indicates if the shape is automatically closed or not.
+	 * @param onlyIntersectWhenOpen indicates if the crossings is set to 0 when
+	 * the path is open and there is not SHAPE_INTERSECT.
 	 * @return the crossings.
 	 */
-	public static int computeCrossingsFromRect(PathIterator2f pi,
+	static int computeCrossingsFromRect(PathIterator2f pi,
 			float rxmin, float rymin,
-			float rxmax, float rymax) {
+			float rxmax, float rymax,
+			boolean closeable,
+			boolean onlyIntersectWhenOpen) {
 		// Copied from AWT API
 		if (rxmax <= rxmin || rymax <= rymin) return 0;
 		if (!pi.hasNext()) return 0;
@@ -770,10 +824,12 @@
 			throw new IllegalArgumentException("missing initial moveto in path definition"); //$NON-NLS-1$
 		}
 
+		Path2f subPath;
 		float curx, cury, movx, movy, endx, endy;
 		curx = movx = pathElement.toX;
 		cury = movy = pathElement.toY;
 		int crossings = 0;
+		int n;
 
 		while (crossings != MathConstants.SHAPE_INTERSECTS
 				&& pi.hasNext()) {
@@ -793,31 +849,49 @@
 						rxmax, rymax,
 						curx, cury,
 						endx, endy);
+				if (crossings==MathConstants.SHAPE_INTERSECTS)
+					return crossings;
 				curx = endx;
 				cury = endy;
 				break;
 			case QUAD_TO:
 				endx = pathElement.toX;
 				endy = pathElement.toY;
-				crossings = computeQuadCurveCrossingsFromRect(crossings,
+				subPath = new Path2f();
+				subPath.moveTo(curx, cury);
+				subPath.quadTo(
+						pathElement.ctrlX1, pathElement.ctrlY1,
+						endx, endy);
+				n = computeCrossingsFromRect(
+						subPath.getPathIterator(MathConstants.SPLINE_APPROXIMATION_RATIO),
 						rxmin, rymin,
 						rxmax, rymax,
-						curx, cury,
-						pathElement.ctrlX1, pathElement.ctrlY1,
-						endx, endy, 0);
+						false,
+						false);
+				if (n==MathConstants.SHAPE_INTERSECTS)
+					return n;
+				crossings += n;
 				curx = endx;
 				cury = endy;
 				break;
 			case CURVE_TO:
 				endx = pathElement.toX;
 				endy = pathElement.toY;
-				crossings = computeCubicCurveCrossingsFromRect(crossings,
-						rxmin, rymin,
-						rxmax, rymax,
-						curx, cury,
+				subPath = new Path2f();
+				subPath.moveTo(curx, cury);
+				subPath.curveTo(
 						pathElement.ctrlX1, pathElement.ctrlY1,
 						pathElement.ctrlX2, pathElement.ctrlY2,
-						endx, endy, 0);
+						endx, endy);
+				n = computeCrossingsFromRect(
+						subPath.getPathIterator(MathConstants.SPLINE_APPROXIMATION_RATIO),
+						rxmin, rymin,
+						rxmax, rymax,
+						false,
+						false);
+				if (n==MathConstants.SHAPE_INTERSECTS)
+					return n;
+				crossings += n;
 				curx = endx;
 				cury = endy;
 				break;
@@ -829,233 +903,35 @@
 							curx, cury,
 							movx, movy);
 				}
+				// Stop as soon as possible
+				if (crossings!=0) return crossings;
 				curx = movx;
 				cury = movy;
-				// Count should always be a multiple of 2 here.
-				// assert((crossings & 1) != 0);
 				break;
 			default:
 			}
 		}
+		
+		assert(crossings != MathConstants.SHAPE_INTERSECTS);
 
-		if (crossings != MathConstants.SHAPE_INTERSECTS && (curx != movx || cury != movy)) {
-			crossings = Segment2f.computeCrossingsFromRect(crossings,
-					rxmin, rymin,
-					rxmax, rymax,
-					curx, cury,
-					movx, movy);
-		}
-
-		// Count should always be a multiple of 2 here.
-		// assert((crossings & 1) != 0);
-		return crossings;
-	}
-
-	/**
-	 * Accumulate the number of times the quad crosses the shadow
-	 * extending to the right of the rectangle.  See the comment
-	 * for the RECT_INTERSECTS constant for more complete details.
-	 * 
-	 * @param crossings is the initial value for the crossings.
-	 * @param rxmin is the first corner of the rectangle.
-	 * @param rymin is the first corner of the rectangle.
-	 * @param rxmax is the second corner of the rectangle.
-	 * @param rymax is the second corner of the rectangle.
-	 * @param x0 is the first point of the curve.
-	 * @param y0 is the first point of the curve.
-	 * @param xc is the control point of the curve.
-	 * @param yc is the control point of the curve.
-	 * @param x1 is the last point of the curve.
-	 * @param y1 is the last point of the curve.
-	 * @param level is the recursion level. It may be equal to {@code 0} for the intiial call.
-	 * @return the crossings.
-	 */
-	static int computeQuadCurveCrossingsFromRect(
-			int crossings,
-			float rxmin, float rymin,
-			float rxmax, float rymax,
-			float x0, float y0,
-			float xc, float yc,
-			float x1, float y1,
-			int level) {
-		// Copied from AWT API
-		float ctrlx = xc;
-		float ctrly = yc;
-		int numCrosses = crossings;
-
-		if (y0 >= rymax && ctrly >= rymax && y1 >= rymax) return numCrosses;
-		if (y0 <= rymin && ctrly <= rymin && y1 <= rymin) return numCrosses;
-		if (x0 <= rxmin && ctrlx <= rxmin && x1 <= rxmin) return numCrosses;
-		if (x0 >= rxmax && ctrlx >= rxmax && x1 >= rxmax) {
-			// Quad is entirely to the right of the rect
-			// and the vertical range of the 3 Y coordinates of the quad
-			// overlaps the vertical range of the rect by a non-empty amount
-			// We now judge the crossings solely based on the line segment
-			// connecting the endpoints of the quad.
-			// Note that we may have 0, 1, or 2 crossings as the control
-			// point may be causing the Y range intersection while the
-			// two endpoints are entirely above or below.
-			if (y0 < y1) {
-				// y-increasing line segment...
-				if (y0 <= rymin && y1 >  rymin) ++numCrosses;
-				if (y0 <  rymax && y1 >= rymax) ++numCrosses;
+		boolean isOpen = (curx != movx) || (cury != movy);
+		
+		if (isOpen) {
+			if (closeable) {
+				// Not closed
+				crossings = Segment2f.computeCrossingsFromRect(crossings,
+						rxmin, rymin,
+						rxmax, rymax,
+						curx, cury,
+						movx, movy);
 			}
-			else if (y1 < y0) {
-				// y-decreasing line segment...
-				if (y1 <= rymin && y0 >  rymin) --numCrosses;
-				if (y1 <  rymax && y0 >= rymax) --numCrosses;
+			else if (onlyIntersectWhenOpen) {
+				// Assume that when is the path is open, only
+				// SHAPE_INTERSECTS may be return
+				crossings = 0;
 			}
-			return numCrosses;
 		}
-
-		// The intersection of ranges is more complicated
-		// First do trivial INTERSECTS rejection of the cases
-		// where one of the endpoints is inside the rectangle.
-		if ((x0 < rxmax && x0 > rxmin && y0 < rymax && y0 > rymin) ||
-				(x1 < rxmax && x1 > rxmin && y1 < rymax && y1 > rymin)) {
-			return MathConstants.SHAPE_INTERSECTS;
-		}
-		// Otherwise, subdivide and look for one of the cases above.
-		// float precision only has 52 bits of mantissa
-		if (level > 52) {
-			return Segment2f.computeCrossingsFromRect(numCrosses,
-					rxmin, rymin, rxmax, rymax,
-					x0, y0, x1, y1);
-		}
-		float x0c = (x0 + ctrlx) / 2;
-		float y0c = (y0 + ctrly) / 2;
-		float xc1 = (ctrlx + x1) / 2;
-		float yc1 = (ctrly + y1) / 2;
-		ctrlx = (x0c + xc1) / 2;
-		ctrly = (y0c + yc1) / 2;
-		if (Double.isNaN(ctrlx) || Double.isNaN(ctrly)) {
-			// [xy]c are NaN if any of [xy]0c or [xy]c1 are NaN
-			// [xy]0c or [xy]c1 are NaN if any of [xy][0c1] are NaN
-			// These values are also NaN if opposing infinities are added
-			return 0;
-		}
-		numCrosses = computeQuadCurveCrossingsFromRect(numCrosses,
-				rxmin, rymin, rxmax, rymax,
-				x0, y0, x0c, y0c, ctrlx, ctrly,
-				level+1);
-		if (numCrosses != MathConstants.SHAPE_INTERSECTS) {
-			numCrosses = computeQuadCurveCrossingsFromRect(numCrosses,
-					rxmin, rymin, rxmax, rymax,
-					ctrlx, ctrly, xc1, yc1, x1, y1,
-					level+1);
-		}
-		return numCrosses;
-	}
-
-	/**
-	 * Accumulate the number of times the cubic crosses the shadow
-	 * extending to the right of the rectangle.  See the comment
-	 * for the RECT_INTERSECTS constant for more complete details.
-	 * 
-	 * @param crossings is the initial value for the crossings.
-	 * @param rxmin is the first corner of the rectangle.
-	 * @param rymin is the first corner of the rectangle.
-	 * @param rxmax is the second corner of the rectangle.
-	 * @param rymax is the second corner of the rectangle.
-	 * @param x0 is the first point of the curve.
-	 * @param y0 is the first point of the curve.
-	 * @param xc0 is the first control point of the curve.
-	 * @param yc0 is the first control point of the curve.
-	 * @param xc1 is the second control point of the curve.
-	 * @param yc1 is the second control point of the curve.
-	 * @param x1 is the last point of the curve.
-	 * @param y1 is the last point of the curve.
-	 * @param level is the recursion level. It may be equal to {@code 0} for the intiial call.
-	 * @return the crossings.
-	 */
-	static int computeCubicCurveCrossingsFromRect(
-			int crossings,
-			float rxmin, float rymin,
-			float rxmax, float rymax,
-			float x0,  float y0,
-			float xc0, float yc0,
-			float xc1, float yc1,
-			float x1,  float y1,
-			int level) {
-		// Copied from AWT API
-		float ctrlx0 = xc0;
-		float ctrly0 = yc0;
-		float ctrlx1 = xc1;
-		float ctrly1 = yc1;
-		int numCrosses = crossings;
-
-		if (y0 >= rymax && ctrly0 >= rymax && ctrly1 >= rymax && y1 >= rymax) {
-			return numCrosses;
-		}
-		if (y0 <= rymin && ctrly0 <= rymin && ctrly1 <= rymin && y1 <= rymin) {
-			return numCrosses;
-		}
-		if (x0 <= rxmin && ctrlx0 <= rxmin && ctrlx1 <= rxmin && x1 <= rxmin) {
-			return numCrosses;
-		}
-		if (x0 >= rxmax && ctrlx0 >= rxmax && ctrlx1 >= rxmax && x1 >= rxmax) {
-			// Cubic is entirely to the right of the rect
-			// and the vertical range of the 4 Y coordinates of the cubic
-			// overlaps the vertical range of the rect by a non-empty amount
-			// We now judge the crossings solely based on the line segment
-			// connecting the endpoints of the cubic.
-			// Note that we may have 0, 1, or 2 crossings as the control
-			// points may be causing the Y range intersection while the
-			// two endpoints are entirely above or below.
-			if (y0 < y1) {
-				// y-increasing line segment...
-				if (y0 <= rymin && y1 >  rymin) ++numCrosses;
-				if (y0 <  rymax && y1 >= rymax) ++numCrosses;
-			}
-			else if (y1 < y0) {
-				// y-decreasing line segment...
-				if (y1 <= rymin && y0 >  rymin) --numCrosses;
-				if (y1 <  rymax && y0 >= rymax) --numCrosses;
-			}
-			return numCrosses;
-		}
-		// The intersection of ranges is more complicated
-		// First do trivial INTERSECTS rejection of the cases
-		// where one of the endpoints is inside the rectangle.
-		if ((x0 > rxmin && x0 < rxmax && y0 > rymin && y0 < rymax) ||
-				(x1 > rxmin && x1 < rxmax && y1 > rymin && y1 < rymax)) {
-			return MathConstants.SHAPE_INTERSECTS;
-		}
-		// Otherwise, subdivide and look for one of the cases above.
-		// float precision only has 52 bits of mantissa
-		if (level > 52) {
-			return Segment2f.computeCrossingsFromRect(numCrosses,
-					rxmin, rymin, rxmax, rymax,
-					x0, y0, x1, y1);
-		}
-		float xmid = (ctrlx0 + ctrlx1) / 2;
-		float ymid = (ctrly0 + ctrly1) / 2;
-		ctrlx0 = (x0 + ctrlx0) / 2;
-		ctrly0 = (y0 + ctrly0) / 2;
-		ctrlx1 = (ctrlx1 + x1) / 2;
-		ctrly1 = (ctrly1 + y1) / 2;
-		float xc0m = (ctrlx0 + xmid) / 2;
-		float yc0m = (ctrly0 + ymid) / 2;
-		float xmc1 = (xmid + ctrlx1) / 2;
-		float ymc1 = (ymid + ctrly1) / 2;
-		xmid = (xc0m + xmc1) / 2;
-		ymid = (yc0m + ymc1) / 2;
-		if (Double.isNaN(xmid) || Double.isNaN(ymid)) {
-			// [xy]mid are NaN if any of [xy]c0m or [xy]mc1 are NaN
-			// [xy]c0m or [xy]mc1 are NaN if any of [xy][c][01] are NaN
-			// These values are also NaN if opposing infinities are added
-			return 0;
-		}
-		numCrosses = computeCubicCurveCrossingsFromRect(numCrosses,
-				rxmin, rymin, rxmax, rymax,
-				x0, y0, ctrlx0, ctrly0,
-				xc0m, yc0m, xmid, ymid, level+1);
-		if (numCrosses != MathConstants.SHAPE_INTERSECTS) {
-			numCrosses = computeCubicCurveCrossingsFromRect(numCrosses,
-					rxmin, rymin, rxmax, rymax,
-					xmid, ymid, xmc1, ymc1,
-					ctrlx1, ctrly1, x1, y1, level+1);
-		}
+		
 		return crossings;
 	}
 
@@ -1485,12 +1361,12 @@
 
 	@Override
 	public boolean contains(float x, float y) {
-		return contains(getPathIterator(), x, y);
+		return contains(getPathIterator(MathConstants.SPLINE_APPROXIMATION_RATIO), x, y);
 	}
 
 	@Override
 	public boolean contains(Rectangle2f r) {
-		return contains(getPathIterator(),
+		return contains(getPathIterator(MathConstants.SPLINE_APPROXIMATION_RATIO),
 				r.getMinX(), r.getMinY(), r.getWidth(), r.getHeight());
 	}
 
@@ -1500,8 +1376,9 @@
 		if (s.isEmpty()) return false;
 		int mask = (this.windingRule == PathWindingRule.NON_ZERO ? -1 : 2);
 		int crossings = computeCrossingsFromRect(
-				getPathIterator(),
-				s.getMinX(), s.getMinY(), s.getMaxX(), s.getMaxY());
+				getPathIterator(MathConstants.SPLINE_APPROXIMATION_RATIO),
+				s.getMinX(), s.getMinY(), s.getMaxX(), s.getMaxY(),
+				false, true);
 		return (crossings == MathConstants.SHAPE_INTERSECTS ||
 				(crossings & mask) != 0);
 	}
@@ -1510,8 +1387,10 @@
 	public boolean intersects(Ellipse2f s) {
 		int mask = (this.windingRule == PathWindingRule.NON_ZERO ? -1 : 2);
 		int crossings = computeCrossingsFromEllipse(
-				getPathIterator(),
-				s.getMinX(), s.getMinY(), s.getWidth(), s.getHeight());
+				0,
+				getPathIterator(MathConstants.SPLINE_APPROXIMATION_RATIO),
+				s.getMinX(), s.getMinY(), s.getWidth(), s.getHeight(),
+				false, true);
 		return (crossings == MathConstants.SHAPE_INTERSECTS ||
 				(crossings & mask) != 0);
 	}
@@ -1520,8 +1399,11 @@
 	public boolean intersects(Circle2f s) {
 		int mask = (this.windingRule == PathWindingRule.NON_ZERO ? -1 : 2);
 		int crossings = computeCrossingsFromCircle(
-				getPathIterator(),
-				s.getX(), s.getY(), s.getRadius());
+				0,
+				getPathIterator(MathConstants.SPLINE_APPROXIMATION_RATIO),
+				s.getX(), s.getY(), s.getRadius(),
+				false,
+				true);
 		return (crossings == MathConstants.SHAPE_INTERSECTS ||
 				(crossings & mask) != 0);
 	}
@@ -1530,11 +1412,77 @@
 	public boolean intersects(Segment2f s) {
 		int mask = (this.windingRule == PathWindingRule.NON_ZERO ? -1 : 2);
 		int crossings = computeCrossingsFromSegment(
-				getPathIterator(),
-				s.getX1(), s.getY1(), s.getX2(), s.getY2());
+				0,
+				getPathIterator(MathConstants.SPLINE_APPROXIMATION_RATIO),
+				s.getX1(), s.getY1(), s.getX2(), s.getY2(),
+				false);
 		return (crossings == MathConstants.SHAPE_INTERSECTS ||
 				(crossings & mask) != 0);
 	}
+	
+	@Override
+	public boolean intersects(Path2f s) {
+		if (s.size()>size())
+			return intersects(s.getPathIterator(MathConstants.SPLINE_APPROXIMATION_RATIO), getPathIterator(MathConstants.SPLINE_APPROXIMATION_RATIO));
+		return intersects(getPathIterator(MathConstants.SPLINE_APPROXIMATION_RATIO), s.getPathIterator(MathConstants.SPLINE_APPROXIMATION_RATIO));
+	}
+	
+	private static boolean intersects(PathIterator2f iterator1, PathIterator2f iterator2) {
+		int mask = (iterator1.getWindingRule() == PathWindingRule.NON_ZERO ? -1 : 2);
+		Path2f subPath;
+		PathElement2f element;
+		while (iterator1.hasNext()) {
+			element = iterator1.next();
+			switch(element.type) {
+			case CLOSE:
+			case LINE_TO:
+				int crossings = computeCrossingsFromSegment(
+						iterator2,
+						element.fromX, element.fromY,
+						element.toX, element.toY);
+				if (crossings == MathConstants.SHAPE_INTERSECTS ||
+					(crossings & mask) != 0) {
+					return true;
+				}
+				break;
+			case MOVE_TO:
+				break;
+			case CURVE_TO:
+				subPath = new Path2f();
+				subPath.moveTo(element.fromX, element.fromY);
+				subPath.curveTo(
+						element.ctrlX1, element.ctrlY1,
+						element.ctrlX2, element.ctrlY2,
+						element.toX, element.toY);
+				if (intersects(
+						subPath.getPathIterator(MathConstants.SPLINE_APPROXIMATION_RATIO),
+						iterator2)) {
+					return true;
+				}
+				break;
+			case QUAD_TO:
+				subPath = new Path2f();
+				subPath.moveTo(element.fromX, element.fromY);
+				subPath.quadTo(
+						element.ctrlX1, element.ctrlY1,
+						element.toX, element.toY);
+				if (intersects(
+						subPath.getPathIterator(MathConstants.SPLINE_APPROXIMATION_RATIO),
+						iterator2)) {
+					return true;
+				}
+				break;
+			default:
+				throw new IllegalStateException();
+			}
+		}
+		return false;
+	}
+	
+	@Override
+	public boolean intersects(PathIterator2f s) {
+		return intersects(getPathIterator(), s);
+	}
 
 	@Override
 	public Rectangle2f toBoundingBox() {
@@ -1588,28 +1536,18 @@
 
 		int mask = (pi.getWindingRule() == PathWindingRule.NON_ZERO ? -1 : 1);
 		int crossings = 0;
-		boolean isClosed = false;
-		float moveX, moveY, currentX, currentY;
-		moveX = moveY = currentX = currentY = Float.NaN;
 		
 		while (pi.hasNext()) {
 			pe = pi.next();
 
 			candidate = null;
 
-			currentX = pe.toX;
-			currentY = pe.toY;
-
 			switch(pe.type) {
 			case MOVE_TO:
-				moveX = pe.toX;
-				moveY = pe.toY;
-				isClosed = false;
 				candidate = new Point2f(pe.toX, pe.toY);
 				break;
 			case LINE_TO:
 			{
-				isClosed = false;
 				float factor =  MathUtil.projectsPointOnLine(
 						p.getX(), p.getY(),
 						pe.fromX, pe.fromY, pe.toX, pe.toY);
@@ -1626,7 +1564,11 @@
 				break;
 			}
 			case CLOSE:
-				isClosed = true;
+				crossings += Segment2f.computeCrossingsFromPoint(
+						p.getX(), p.getY(),
+						pe.fromX, pe.fromY, pe.toX, pe.toY);
+				if ((crossings & mask) != 0) return p;
+
 				if (!pe.isEmpty()) {
 					float factor =  MathUtil.projectsPointOnLine(
 							p.getX(), p.getY(),
@@ -1638,10 +1580,8 @@
 					candidate = new Point2f(
 							pe.fromX + v.getX(),
 							pe.fromY + v.getY());
-					crossings += Segment2f.computeCrossingsFromPoint(
-							p.getX(), p.getY(),
-							pe.fromX, pe.fromY, pe.toX, pe.toY);
 				}
+				crossings = 0;
 				break;
 			case QUAD_TO:
 			case CURVE_TO:
@@ -1658,14 +1598,6 @@
 			}
 		}
 		
-		if (!isClosed) {
-			crossings += Segment2f.computeCrossingsFromPoint(
-					p.getX(), p.getY(),
-					currentX, currentY,
-					moveX, moveY);
-		}
-		
-		if ((crossings & mask) != 0) return p;
 		return closest;
 	}
 

Modified: trunk/math/src/main/java/org/arakhne/afc/math/continous/object2d/Segment2f.java
===================================================================
--- trunk/math/src/main/java/org/arakhne/afc/math/continous/object2d/Segment2f.java	2013-04-05 20:39:57 UTC (rev 413)
+++ trunk/math/src/main/java/org/arakhne/afc/math/continous/object2d/Segment2f.java	2013-04-05 21:45:07 UTC (rev 414)
@@ -73,6 +73,34 @@
 
 	/**
 	 * Calculates the number of times the line from (x0,y0) to (x1,y1)
+	 * crosses the ray extending to the right from (px,py).
+	 * If the point lies on the line, then no crossings are recorded.
+	 * +1 is returned for a crossing where the Y coordinate is increasing
+	 * -1 is returned for a crossing where the Y coordinate is decreasing
+	 * 
+	 * @param px is the reference point to test.
+	 * @param py is the reference point to test.
+	 * @param x0 is the first point of the line.
+	 * @param y0 is the first point of the line.
+	 * @param x1 is the second point of the line.
+	 * @param y1 is the secondpoint of the line.
+	 * @return the crossing.
+	 */
+	static int computeCrossingsFromPoint1(
+			float px, float py,
+			float x0, float y0,
+			float x1, float y1) {
+		if (py <  y0 && py <  y1) return 0;
+		if (py > y0 && py > y1) return 0;
+		if (px > x0 && px > x1) return 0;
+		if (px <  x0 && px <  x1) return (y0 < y1) ? 1 : -1;
+		float xintercept = x0 + (py - y0) * (x1 - x0) / (y1 - y0);
+		if (px > xintercept) return 0;
+		return (y0 < y1) ? 1 : -1;
+	}
+
+	/**
+	 * Calculates the number of times the line from (x0,y0) to (x1,y1)
 	 * crosses the segment (sx0,sy0) to (sx1,sy1) extending to the right.
 	 * 
 	 * @param crossings is the initial value for the number of crossings.
@@ -92,6 +120,32 @@
 			float sx2, float sy2,
 			float x0, float y0,
 			float x1, float y1) {
+		return computeCrossingsFromSegment(crossings, sx1, sy1, sx2, sy2, x0, y0, x1, y1, false);
+	}
+	
+	/**
+	 * Calculates the number of times the line from (x0,y0) to (x1,y1)
+	 * crosses the segment (sx0,sy0) to (sx1,sy1) extending to the right.
+	 * 
+	 * @param crossings is the initial value for the number of crossings.
+	 * @param sx1 is the first point of the segment to extend.
+	 * @param sy1 is the first point of the segment to extend.
+	 * @param sx2 is the second point of the segment to extend.
+	 * @param sy2 is the second point of the segment to extend.
+	 * @param x0 is the first point of the line.
+	 * @param y0 is the first point of the line.
+	 * @param x1 is the second point of the line.
+	 * @param y1 is the secondpoint of the line.
+	 * @param linesAreCrossing indicates if the shadow lines are crossing.
+	 * @return the crossing, or {@link MathConstants#SHAPE_INTERSECTS}
+	 */
+	static int computeCrossingsFromSegment(
+			int crossings,
+			float sx1, float sy1,
+			float sx2, float sy2,
+			float x0, float y0,
+			float x1, float y1,
+			boolean linesAreCrossing) {
 		int numCrosses = crossings;
 
 		float xmin = Math.min(sx1, sx2);
@@ -128,8 +182,14 @@
 			}
 			if (side1>0 || side2>0) {
 				int n1, n2;
-				n1 = computeCrossingsFromPoint(sx1, sy1, x0, y0, x1, y1);
-				n2 = computeCrossingsFromPoint(sx2, sy2, x0, y0, x1, y1);
+				if (linesAreCrossing) {
+					n1 = computeCrossingsFromPoint1(sx1, sy1, x0, y0, x1, y1);
+					n2 = computeCrossingsFromPoint1(sx2, sy2, x0, y0, x1, y1);
+				}
+				else {
+					n1 = computeCrossingsFromPoint(sx1, sy1, x0, y0, x1, y1);
+					n2 = computeCrossingsFromPoint(sx2, sy2, x0, y0, x1, y1);
+				}
 				numCrosses += n1 + n2;
 			}
 		}
@@ -162,8 +222,8 @@
 
 		float xmin = ex;
 		float ymin = ey;
-		float xmax = ex + Math.max(0, ew);
-		float ymax = ey + Math.max(0, eh);
+		float xmax = ex + ew;
+		float ymax = ey + eh;
 
 		if (y0<=ymin && y1<=ymin) return numCrosses;
 		if (y0>=ymax && y1>=ymax) return numCrosses;
@@ -181,7 +241,7 @@
 			}
 		}
 		else if (Ellipse2f.intersectsEllipseSegment(
-				xmin, ymin, xmax, ymax,
+				xmin, ymin, xmax-xmin, ymax-ymin,
 				x0, y0, x1, y1)) {
 			return MathConstants.SHAPE_INTERSECTS;
 		}
@@ -860,7 +920,7 @@
 	public boolean intersects(Ellipse2f s) {
 		return Ellipse2f.intersectsEllipseSegment(
 				s.getMinX(), s.getMinY(),
-				s.getMaxX(), s.getMaxY(),
+				s.getWidth(), s.getHeight(),
 				getX1(), getY1(),
 				getX2(), getY2());
 	}

Added: trunk/math/src/test/java/org/arakhne/afc/math/continous/object2d/AbstractPath2fTestCase.java
===================================================================
--- trunk/math/src/test/java/org/arakhne/afc/math/continous/object2d/AbstractPath2fTestCase.java	                        (rev 0)
+++ trunk/math/src/test/java/org/arakhne/afc/math/continous/object2d/AbstractPath2fTestCase.java	2013-04-05 21:45:07 UTC (rev 414)
@@ -0,0 +1,216 @@
+/* 
+ * $Id$
+ * 
+ * Copyright (c) 2006-10, Multiagent Team, Laboratoire Systemes et Transports, Universite de Technologie de Belfort-Montbeliard.
+ * Copyright (C) 2012 Stephane GALLAND.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library 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.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * This program is free software; you can redistribute it and/or modify
+ */
+package org.arakhne.afc.math.continous.object2d;
+
+import org.arakhne.afc.math.generic.PathWindingRule;
+
+/** Abstract tests for the paths.
+ * 
+ * @author $Author: galland$
+ * @version $FullVersion$
+ * @mavengroupid $GroupId$
+ * @mavenartifactid $ArtifactId$
+ */
+public abstract class AbstractPath2fTestCase extends AbstractShape2fTestCase<Path2f> {
+	
+	@Override
+	public void testIsEmpty() {
+		assertFalse(this.r.isEmpty());
+
+		this.r.clear();
+		assertTrue(this.r.isEmpty());
+		
+		this.r.moveTo(1f, 2f);
+		assertTrue(this.r.isEmpty());
+		this.r.moveTo(3f, 4f);
+		assertTrue(this.r.isEmpty());
+		this.r.lineTo(5f, 6f);
+		assertFalse(this.r.isEmpty());
+		this.r.closePath();
+		assertFalse(this.r.isEmpty());
+
+		this.r.clear();
+		assertTrue(this.r.isEmpty());
+
+		this.r.moveTo(1f, 2f);
+		assertTrue(this.r.isEmpty());
+		this.r.moveTo(3f, 4f);
+		assertTrue(this.r.isEmpty());
+		this.r.lineTo(3f, 4f);
+		assertTrue(this.r.isEmpty());
+		this.r.closePath();
+		assertTrue(this.r.isEmpty());
+
+		this.r.clear();
+		assertTrue(this.r.isEmpty());
+
+		this.r.moveTo(1f, 2f);
+		assertTrue(this.r.isEmpty());
+		this.r.moveTo(3f, 4f);
+		assertTrue(this.r.isEmpty());
+		this.r.lineTo(3f, 4f);
+		assertTrue(this.r.isEmpty());
+		this.r.lineTo(5f, 6f);
+		assertFalse(this.r.isEmpty());
+	}
+
+	@Override
+	public void testClear() {
+		this.r.clear();
+		assertEquals(0, this.r.size());
+	}
+
+	@Override
+	public void testClone() {
+		Path2f b = this.r.clone();
+
+		assertNotSame(b, this.r);
+		PathElement2f pe1, pe2;
+		PathIterator2f i1 = this.r.getPathIterator();
+		PathIterator2f i2 = b.getPathIterator();
+		assertNotSame(i1, i2);
+		while (i1.hasNext()) {
+			assertTrue(i2.hasNext());
+			pe1 = i1.next();
+			pe2 = i2.next();
+			assertNotSame(pe1, pe2);
+			assertEquals(pe1.type, pe2.type);
+			assertEpsilonEquals(pe1.fromX, pe2.fromX);
+			assertEpsilonEquals(pe1.fromY, pe2.fromY);
+			assertEpsilonEquals(pe1.ctrlX1, pe2.ctrlX1);
+			assertEpsilonEquals(pe1.ctrlY1, pe2.ctrlY1);
+			assertEpsilonEquals(pe1.ctrlX2, pe2.ctrlX2);
+			assertEpsilonEquals(pe1.ctrlY2, pe2.ctrlY2);
+			assertEpsilonEquals(pe1.toX, pe2.toX);
+			assertEpsilonEquals(pe1.toY, pe2.toY);
+			
+		}
+		assertFalse(i2.hasNext());
+		
+		b.translate(1f, 1f);
+
+		i1 = this.r.getPathIterator();
+		i2 = b.getPathIterator();
+		while (i1.hasNext()) {
+			assertTrue(i2.hasNext());
+			pe1 = i1.next();
+			pe2 = i2.next();
+			assertEquals(pe1.type, pe2.type);
+			assertNotEpsilonEquals(pe1.fromX, pe2.fromX);
+			assertNotEpsilonEquals(pe1.fromY, pe2.fromY);
+			assertNotEpsilonEquals(pe1.ctrlX1, pe2.ctrlX1);
+			assertNotEpsilonEquals(pe1.ctrlY1, pe2.ctrlY1);
+			assertNotEpsilonEquals(pe1.ctrlX2, pe2.ctrlX2);
+			assertNotEpsilonEquals(pe1.ctrlY2, pe2.ctrlY2);
+			assertNotEpsilonEquals(pe1.toX, pe2.toX);
+			assertNotEpsilonEquals(pe1.toY, pe2.toY);
+			
+		}
+		assertFalse(i2.hasNext());
+	}
+
+	/**
+	 */
+	public abstract void testContainsPathIterator2fFloatFloat();
+
+	/**
+	 */
+	public abstract void testIntersectsPathIterator2fFloatFloatFloatFloat();
+	
+	/**
+	 */
+	public abstract void testGetClosestPointTo();	
+
+	/**
+	 */
+	public void testSetWindingRule() {
+		assertEquals(PathWindingRule.NON_ZERO, this.r.getWindingRule());
+		for(PathWindingRule rule : PathWindingRule.values()) {
+			this.r.setWindingRule(rule);
+			assertEquals(rule, this.r.getWindingRule());
+		}
+	}
+
+	/**
+	 */
+	public abstract void testAddIterator();
+
+	/** 
+	 */
+	public abstract void testGetPathIteratorVoid();
+
+	/** 
+	 */
+	public abstract void testGetPathIteratorTransform2D();
+
+	/** 
+	 */
+	public abstract void testTransformTransform2D();
+
+	/** 
+	 */
+	public abstract void testCreateTransformedShape2D();
+
+	/** 
+	 */
+	public abstract void testContainsFloatfloat();
+
+	/** 
+	 */
+	public abstract void testContainsRectangle2f();
+
+	/** 
+	 */
+	public abstract void testIntersectsRectangle2f();
+
+	/** 
+	 */
+	public abstract void testIntersectsEllipse2f();
+
+	/** 
+	 */
+	public abstract void testIntersectsCircle2f();
+
+	/** 
+	 */
+	public abstract void testIntersectsSegment2f();
+
+	@Override
+	public abstract void testToBoundingBox();
+	
+	/**
+	 */
+	public abstract void testRemoveLast();
+
+	/**
+	 */
+	public abstract void testSetLastPointFloatFloat();
+	
+	/**
+	 */
+	public abstract void testRemoveFloatFloat();
+
+	/**
+	 */
+	public abstract void testContainsPointPoint2D();
+
+}
\ No newline at end of file

Added: trunk/math/src/test/java/org/arakhne/afc/math/continous/object2d/ClosePath2fTest.java
===================================================================
--- trunk/math/src/test/java/org/arakhne/afc/math/continous/object2d/ClosePath2fTest.java	                        (rev 0)
+++ trunk/math/src/test/java/org/arakhne/afc/math/continous/object2d/ClosePath2fTest.java	2013-04-05 21:45:07 UTC (rev 414)
@@ -0,0 +1,538 @@
+/* 
+ * $Id$
+ * 
+ * Copyright (c) 2006-10, Multiagent Team, Laboratoire Systemes et Transports, Universite de Technologie de Belfort-Montbeliard.
+ * Copyright (C) 2012 Stephane GALLAND.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library 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.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * This program is free software; you can redistribute it and/or modify
+ */
+package org.arakhne.afc.math.continous.object2d;
+
+import org.arakhne.afc.math.generic.PathElementType;
+import org.arakhne.afc.math.generic.Point2D;
+import org.arakhne.afc.math.matrix.Transform2D;
+
+/**
+ * @author $Author: galland$
+ * @version $FullVersion$
+ * @mavengroupid $GroupId$
+ * @mavenartifactid $ArtifactId$
+ */
+public class ClosePath2fTest extends AbstractPath2fTestCase {
+	
+	@Override
+	protected Path2f createShape() {
+		Path2f p = new Path2f();
+		p.moveTo(1f, 1f);
+		p.lineTo(2f, 2f);
+		p.quadTo(3f, 0f, 4f, 3f);
+		p.curveTo(5f, -1f, 6f, 5f, 7f, -5f);
+		p.closePath();
+		return p;
+	}
+	
+	/**
+	 */
+	@Override
+	public void testGetClosestPointTo() {
+		Point2D p;
+		
+		p = this.r.getClosestPointTo(new Point2f(0f, 0f));
+		assertEpsilonEquals(1f, p.getX());
+		assertEpsilonEquals(1f, p.getY());
+
+		p = this.r.getClosestPointTo(new Point2f(4f, 0f));
+		assertEpsilonEquals(4f, p.getX());
+		assertEpsilonEquals(0f, p.getY());
+
+		p = this.r.getClosestPointTo(new Point2f(4f, 2f));
+		assertEpsilonEquals(4f, p.getX());
+		assertEpsilonEquals(2f, p.getY());
+
+		p = this.r.getClosestPointTo(new Point2f(1f, 0f));
+		assertEpsilonEquals(1.5f, p.getX());
+		assertEpsilonEquals(.5f, p.getY());
+	}
+	
+
+	@Override
+	public void testDistancePoint2D() {
+		assertEpsilonEquals(1.414213562f, this.r.distance(new Point2f(0f, 0f)));
+		assertEpsilonEquals(0f, this.r.distance(new Point2f(4f, 0f)));
+		assertEpsilonEquals(0f, this.r.distance(new Point2f(4f, 2f)));
+		assertEpsilonEquals(0.707106781f, this.r.distance(new Point2f(1f, 0f)));
+	}
+
+	@Override
+	public void testDistanceSquaredPoint2D() {
+		assertEpsilonEquals(2f, this.r.distanceSquared(new Point2f(0f, 0f)));
+		assertEpsilonEquals(0f, this.r.distanceSquared(new Point2f(4f, 0f)));
+		assertEpsilonEquals(0f, this.r.distanceSquared(new Point2f(4f, 2f)));
+		assertEpsilonEquals(.5f, this.r.distanceSquared(new Point2f(1f, 0f)));
+	}
+
+	@Override
+	public void testDistanceL1Point2D() {
+		// (1,1)
+		assertEpsilonEquals(2f, this.r.distanceL1(new Point2f(0f, 0f)));
+		// (4,0)
+		assertEpsilonEquals(0f, this.r.distanceL1(new Point2f(4f, 0f)));
+		// (4,2)
+		assertEpsilonEquals(0f, this.r.distanceL1(new Point2f(4f, 2f)));
+		// (1.5,.5)
+		assertEpsilonEquals(1f, this.r.distanceL1(new Point2f(1f, 0f)));
+	}
+
+	@Override
+	public void testDistanceLinfPoint2D() {
+		// (1,1)
+		assertEpsilonEquals(1f, this.r.distanceLinf(new Point2f(0f, 0f)));
+		// (4,0)
+		assertEpsilonEquals(0f, this.r.distanceLinf(new Point2f(4f, 0f)));
+		// (4,2)
+		assertEpsilonEquals(0f, this.r.distanceLinf(new Point2f(4f, 2f)));
+		// (1.5,.5)
+		assertEpsilonEquals(.5f, this.r.distanceLinf(new Point2f(1f, 0f)));
+	}
+
+	@Override
+	public void testTranslateFloatFloat() {
+		this.r.translate(3.4f, 4.5f);
+		PathIterator2f pi = this.r.getPathIterator();
+		assertElement(pi, PathElementType.MOVE_TO, 4.4f, 5.5f);
+		assertElement(pi, PathElementType.LINE_TO, 5.4f, 6.5f);
+		assertElement(pi, PathElementType.QUAD_TO, 6.4f, 4.5f, 7.4f, 7.5f);
+		assertElement(pi, PathElementType.CURVE_TO, 8.4f, 3.5f, 9.4f, 9.5f, 10.4f, -.5f);
+		assertElement(pi, PathElementType.CLOSE);
+		assertNoElement(pi);
+	}
+
+	/**
+	 */
+	@Override
+	public void testAddIterator() {
+		Path2f p2 = new Path2f();
+		p2.moveTo(3.4f, 4.5f);
+		p2.lineTo(5.6f, 6.7f);
+		
+		this.r.add(p2.getPathIterator());
+		
+		PathIterator2f pi = this.r.getPathIterator();
+		assertElement(pi, PathElementType.MOVE_TO, 1f, 1f);
+		assertElement(pi, PathElementType.LINE_TO, 2f, 2f);
+		assertElement(pi, PathElementType.QUAD_TO, 3f, 0f, 4f, 3f);
+		assertElement(pi, PathElementType.CURVE_TO, 5f, -1f, 6f, 5f, 7f, -5f);
+		assertElement(pi, PathElementType.CLOSE);
+		assertElement(pi, PathElementType.MOVE_TO, 3.4f, 4.5f);
+		assertElement(pi, PathElementType.LINE_TO, 5.6f, 6.7f);
+		assertNoElement(pi);
+	}
+
+	/** 
+	 */
+	@Override
+	public void testGetPathIteratorVoid() {
+		PathIterator2f pi = this.r.getPathIterator();
+		assertElement(pi, PathElementType.MOVE_TO, 1f, 1f);
+		assertElement(pi, PathElementType.LINE_TO, 2f, 2f);
+		assertElement(pi, PathElementType.QUAD_TO, 3f, 0f, 4f, 3f);
+		assertElement(pi, PathElementType.CURVE_TO, 5f, -1f, 6f, 5f, 7f, -5f);
+		assertElement(pi, PathElementType.CLOSE);
+		assertNoElement(pi);
+	}
+
+	/** 
+	 */
+	@Override
+	public void testGetPathIteratorTransform2D() {
+		Transform2D tr;
+		PathIterator2f pi;
+		
+		tr = new Transform2D();
+		pi = this.r.getPathIterator(tr);
+		assertElement(pi, PathElementType.MOVE_TO, 1f, 1f);
+		assertElement(pi, PathElementType.LINE_TO, 2f, 2f);
+		assertElement(pi, PathElementType.QUAD_TO, 3f, 0f, 4f, 3f);
+		assertElement(pi, PathElementType.CURVE_TO, 5f, -1f, 6f, 5f, 7f, -5f);
+		assertElement(pi, PathElementType.CLOSE);
+		assertNoElement(pi);
+
+		tr = new Transform2D();
+		tr.makeTranslationMatrix(3.4f, 4.5f);
+		pi = this.r.getPathIterator(tr);
+		assertElement(pi, PathElementType.MOVE_TO, 4.4f, 5.5f);
+		assertElement(pi, PathElementType.LINE_TO, 5.4f, 6.5f);
+		assertElement(pi, PathElementType.QUAD_TO, 6.4f, 4.5f, 7.4f, 7.5f);
+		assertElement(pi, PathElementType.CURVE_TO, 8.4f, 3.5f, 9.4f, 9.5f, 10.4f, -.5f);
+		assertElement(pi, PathElementType.CLOSE);
+		assertNoElement(pi);
+	}
+
+	/** 
+	 */
+	@Override
+	public void testTransformTransform2D() {
+		Transform2D tr = new Transform2D();
+		tr.makeTranslationMatrix(3.4f, 4.5f);
+		Transform2D tr2 = new Transform2D();
+		tr2.makeRotationMatrix(5.6f);
+		
+		Path2f clone = this.r.clone();
+		clone.transform(tr);
+
+		PathIterator2f pi = clone.getPathIterator();
+		assertElement(pi, PathElementType.MOVE_TO, 4.4f, 5.5f);
+		assertElement(pi, PathElementType.LINE_TO, 5.4f, 6.5f);
+		assertElement(pi, PathElementType.QUAD_TO, 6.4f, 4.5f, 7.4f, 7.5f);
+		assertElement(pi, PathElementType.CURVE_TO, 8.4f, 3.5f, 9.4f, 9.5f, 10.4f, -.5f);
+		assertElement(pi, PathElementType.CLOSE);
+		assertNoElement(pi);
+
+		clone = this.r.clone();
+		clone.transform(tr2);
+
+		pi = clone.getPathIterator();
+		assertElement(pi, PathElementType.MOVE_TO, 1.406832516382571f, 0.144299240637928f);
+		assertElement(pi, PathElementType.LINE_TO, 2.813665032765142f, 0.288598481275856f);
+		assertElement(pi, PathElementType.QUAD_TO, 2.32669763553075f, -1.89379991361696f,
+				4.996063427657964f, -0.198368915958538f);
+		assertElement(pi, PathElementType.CURVE_TO, 3.24656275467893f, -3.93189906787186f,
+				7.8097284604231056f, 0.0902295653173185f,
+				2.27262796021014f, -8.29669585765750f);
+		assertElement(pi, PathElementType.CLOSE);
+		assertNoElement(pi);
+
+		Transform2D tr3 = new Transform2D();
+		tr3.mul(tr, tr2);
+		clone = this.r.clone();
+		clone.transform(tr3);
+
+		pi = clone.getPathIterator();
+		assertElement(pi, PathElementType.MOVE_TO, 4.80683251638257f, 4.64429924063793f);
+		assertElement(pi, PathElementType.LINE_TO, 6.21366503276514f, 4.78859848127586f);
+		assertElement(pi, PathElementType.QUAD_TO, 5.72669763553075f, 2.60620008638304f,
+				8.39606342765796f, 4.30163108404146f);
+		assertElement(pi, PathElementType.CURVE_TO, 6.646562754678927f, 0.568100932128142f,
+				11.20972846042311f, 4.59022956531732f, 5.67262796021014f, -3.79669585765750f);
+		assertElement(pi, PathElementType.CLOSE);
+		assertNoElement(pi);
+	}
+
+	/** 
+	 */
+	@Override
+	public void testCreateTransformedShape2D() {
+		Transform2D tr = new Transform2D();
+		tr.makeTranslationMatrix(3.4f, 4.5f);
+		Path2f p2 = (Path2f)this.r.createTransformedShape(tr);
+
+		PathIterator2f pi = p2.getPathIterator();
+		assertElement(pi, PathElementType.MOVE_TO, 4.4f, 5.5f);
+		assertElement(pi, PathElementType.LINE_TO, 5.4f, 6.5f);
+		assertElement(pi, PathElementType.QUAD_TO, 6.4f, 4.5f, 7.4f, 7.5f);
+		assertElement(pi, PathElementType.CURVE_TO, 8.4f, 3.5f, 9.4f, 9.5f, 10.4f, -.5f);
+		assertElement(pi, PathElementType.CLOSE);
+		assertNoElement(pi);
+	}
+
+	/**
+	 */
+	@Override
+	public void testContainsPathIterator2fFloatFloat() {
+		assertFalse(Path2f.contains(this.r.getPathIterator(), 0f, 0f));
+		assertTrue(Path2f.contains(this.r.getPathIterator(), 4f, 3f));
+		assertTrue(Path2f.contains(this.r.getPathIterator(), 2f, 2f));
+		assertTrue(Path2f.contains(this.r.getPathIterator(), 2f, 1f));
+		assertTrue(Path2f.contains(this.r.getPathIterator(), 5f, 0f));
+		assertFalse(Path2f.contains(this.r.getPathIterator(), -1f, -1f));
+	}
+
+	/** 
+	 */
+	@Override
+	public void testContainsFloatfloat() {
+		assertFalse(this.r.contains(0f, 0f));
+		assertTrue(this.r.contains(4f, 3f));
+		assertTrue(this.r.contains(2f, 2f));
+		assertTrue(this.r.contains(2f, 1f));
+		assertTrue(this.r.contains(5f, 0f));
+		assertFalse(this.r.contains(-1f, -1f));
+		assertFalse(this.r.contains(5f, 2f));
+		assertFalse(this.r.contains(3.5f, -2.5f));
+		assertFalse(this.r.contains(7f, -4f));
+		assertFalse(this.r.contains(2.5f, 1.5f));
+	}
+
+	/** 
+	 */
+	@Override
+	public void testContainsRectangle2f() {
+		assertFalse(this.r.contains(new Rectangle2f(0f, 0f, 1f, 1f)));
+		assertFalse(this.r.contains(new Rectangle2f(4f, 3f, 1f, 1f)));
+		assertFalse(this.r.contains(new Rectangle2f(2f, 2f, 1f, 1f)));
+		assertFalse(this.r.contains(new Rectangle2f(2f, 1f, 1f, 1f)));
+		assertTrue(this.r.contains(new Rectangle2f(3f, 0f, 1f, 1f)));
+		assertFalse(this.r.contains(new Rectangle2f(-1f, -1f, 1f, 1f)));
+		assertFalse(this.r.contains(new Rectangle2f(4f, -3f, 1f, 1f)));
+		assertFalse(this.r.contains(new Rectangle2f(-3f, 4f, 1f, 1f)));
+		assertFalse(this.r.contains(new Rectangle2f(6f, -5f, 1f, 1f)));
+		assertTrue(this.r.contains(new Rectangle2f(4f, 0f, 1f, 1f)));
+		assertFalse(this.r.contains(new Rectangle2f(5f, 0f, 1f, 1f)));
+		assertFalse(this.r.contains(new Rectangle2f(.01f, .01f, 1f, 1f)));
+	}
+
+	/** 
+	 */
+	@Override
+	public void testIntersectsRectangle2f() {
+		assertFalse(this.r.intersects(new Rectangle2f(0f, 0f, 1f, 1f)));
+		assertFalse(this.r.intersects(new Rectangle2f(4f, 3f, 1f, 1f)));
+		assertFalse(this.r.intersects(new Rectangle2f(2f, 2f, 1f, 1f)));
+		assertTrue(this.r.intersects(new Rectangle2f(2f, 1f, 1f, 1f)));
+		assertTrue(this.r.intersects(new Rectangle2f(3f, 0f, 1f, 1f)));
+		assertFalse(this.r.intersects(new Rectangle2f(-1f, -1f, 1f, 1f)));
+		assertTrue(this.r.intersects(new Rectangle2f(4f, -3f, 1f, 1f)));
+		assertFalse(this.r.intersects(new Rectangle2f(-3f, 4f, 1f, 1f)));
+		assertTrue(this.r.intersects(new Rectangle2f(6f, -5f, 1f, 1f)));
+		assertTrue(this.r.intersects(new Rectangle2f(4f, 0f, 1f, 1f)));
+		assertTrue(this.r.intersects(new Rectangle2f(5f, 0f, 1f, 1f)));
+		assertTrue(this.r.intersects(new Rectangle2f(.01f, .01f, 1f, 1f)));
+	}
+
+	@Override
+	public void testIntersectsPathIterator2fFloatFloatFloatFloat() {
+		assertFalse(Path2f.intersects(this.r.getPathIterator(), 0f, 0f, 1f, 1f));
+		assertFalse(Path2f.intersects(this.r.getPathIterator(), 4f, 3f, 1f, 1f));
+		assertFalse(Path2f.intersects(this.r.getPathIterator(),2f, 2f, 1f, 1f));
+		assertTrue(Path2f.intersects(this.r.getPathIterator(), 2f, 1f, 1f, 1f));
+		assertTrue(Path2f.intersects(this.r.getPathIterator(), 3f, 0f, 1f, 1f));
+		assertFalse(Path2f.intersects(this.r.getPathIterator(), -1f, -1f, 1f, 1f));
+		assertTrue(Path2f.intersects(this.r.getPathIterator(), 4f, -3f, 1f, 1f));
+		assertFalse(Path2f.intersects(this.r.getPathIterator(), -3f, 4f, 1f, 1f));
+		assertTrue(Path2f.intersects(this.r.getPathIterator(), 6f, -5f, 1f, 1f));
+		assertTrue(Path2f.intersects(this.r.getPathIterator(), 4f, 0f, 1f, 1f));
+		assertTrue(Path2f.intersects(this.r.getPathIterator(), 5f, 0f, 1f, 1f));
+		assertTrue(Path2f.intersects(this.r.getPathIterator(), .01f, .01f, 1f, 1f));
+	}
+
+	/** 
+	 */
+	@Override
+	public void testIntersectsEllipse2f() {
+		assertFalse(this.r.intersects(new Ellipse2f(0f, 0f, 1f, 2f)));
+		assertFalse(this.r.intersects(new Ellipse2f(4f, 3f, 1f, 2f)));
+		assertFalse(this.r.intersects(new Ellipse2f(2f, 2f, 1f, 2f)));
+		assertTrue(this.r.intersects(new Ellipse2f(2f, 1f, 1f, 2f)));
+		assertTrue(this.r.intersects(new Ellipse2f(3f, 0f, 1f, 2f)));
+		assertFalse(this.r.intersects(new Ellipse2f(-1f, -1f, 1f, 2f)));
+		assertTrue(this.r.intersects(new Ellipse2f(4f, -3f, 1f, 2f)));
+		assertFalse(this.r.intersects(new Ellipse2f(-3f, 4f, 1f, 2f)));
+		assertTrue(this.r.intersects(new Ellipse2f(6f, -5f, 1f, 2f)));
+		assertTrue(this.r.intersects(new Ellipse2f(6f, -5f, .8f, 2f)));
+		assertTrue(this.r.intersects(new Ellipse2f(4f, 0f, 1f, 2f)));
+		assertFalse(this.r.intersects(new Ellipse2f(6f, 0f, 1f, 2f)));
+	}
+
+	/** 
+	 */
+	@Override
+	public void testIntersectsCircle2f() {
+		assertFalse(this.r.intersects(new Circle2f(0f, 0f, 1f)));
+		assertTrue(this.r.intersects(new Circle2f(4f, 3f, 1f)));
+		assertTrue(this.r.intersects(new Circle2f(2f, 2f, 1f)));
+		assertTrue(this.r.intersects(new Circle2f(2f, 1f, 1f)));
+		assertTrue(this.r.intersects(new Circle2f(3f, 0f, 1f)));
+		assertFalse(this.r.intersects(new Circle2f(-1f, -1f, 1f)));
+		assertTrue(this.r.intersects(new Circle2f(4f, -3f, 1f)));
+		assertFalse(this.r.intersects(new Circle2f(-3f, 4f, 1f)));
+		assertTrue(this.r.intersects(new Circle2f(6f, -5f, 1f)));
+		assertTrue(this.r.intersects(new Circle2f(6f, -5f, .95f)));
+		assertTrue(this.r.intersects(new Circle2f(4f, 0f, 1f)));
+		assertTrue(this.r.intersects(new Circle2f(5f, 0f, 1f)));
+		assertFalse(this.r.intersects(new Circle2f(.01f, .01f, 1f)));
+		assertFalse(this.r.intersects(new Circle2f(6f, 2f, .8f)));
+	}
+
+	/** 
+	 */
+	@Override
+	public void testIntersectsSegment2f() {
+		assertFalse(this.r.intersects(new Segment2f(0f, 0f, 1f, 1f)));
+		assertTrue(this.r.intersects(new Segment2f(4f, 3f, 1f, 1f)));
+		assertTrue(this.r.intersects(new Segment2f(2f, 2f, 1f, 1f)));
+		assertTrue(this.r.intersects(new Segment2f(2f, 1f, 1f, 1f)));
+		assertTrue(this.r.intersects(new Segment2f(3f, 0f, 1f, 1f)));
+		assertTrue(this.r.intersects(new Segment2f(3f, 0f, 1.5f, 1f)));
+		assertFalse(this.r.intersects(new Segment2f(-1f, -1f, 1f, 1f)));
+		assertFalse(this.r.intersects(new Segment2f(4f, -3f, 1f, 1f)));
+		assertFalse(this.r.intersects(new Segment2f(4f, -3f, 1f, 0f)));
+		assertFalse(this.r.intersects(new Segment2f(-3f, 4f, 1f, 1f)));
+		assertFalse(this.r.intersects(new Segment2f(6f, -5f, 1f, 1f)));
+		assertFalse(this.r.intersects(new Segment2f(6f, -5f, 1f, 0f)));
+		assertTrue(this.r.intersects(new Segment2f(4f, 0f, 1f, 1f)));
+		assertTrue(this.r.intersects(new Segment2f(5f, 0f, 1f, 1f)));
+		assertFalse(this.r.intersects(new Segment2f(.01f, .01f, 1f, 1f)));
+	}
+
+	@Override
+	public void testToBoundingBox() {
+		Rectangle2f bb = this.r.toBoundingBox();
+		assertEpsilonEquals(1f, bb.getMinX());
+		assertEpsilonEquals(-5f, bb.getMinY());
+		assertEpsilonEquals(7f, bb.getMaxX());
+		assertEpsilonEquals(5f, bb.getMaxY());
+	}
+	
+	/**
+	 */
+	@Override
+	public void testRemoveLast() {
+		PathIterator2f pi = this.r.getPathIterator();
+		assertElement(pi, PathElementType.MOVE_TO, 1f, 1f);
+		assertElement(pi, PathElementType.LINE_TO, 2f, 2f);
+		assertElement(pi, PathElementType.QUAD_TO, 3f, 0f, 4f, 3f);
+		assertElement(pi, PathElementType.CURVE_TO, 5f, -1f, 6f, 5f, 7f, -5f);
+		assertElement(pi, PathElementType.CLOSE);
+		assertNoElement(pi);
+		
+		this.r.removeLast();
+
+		pi = this.r.getPathIterator();
+		assertElement(pi, PathElementType.MOVE_TO, 1f, 1f);
+		assertElement(pi, PathElementType.LINE_TO, 2f, 2f);
+		assertElement(pi, PathElementType.QUAD_TO, 3f, 0f, 4f, 3f);
+		assertElement(pi, PathElementType.CURVE_TO, 5f, -1f, 6f, 5f, 7f, -5f);
+		assertNoElement(pi);
+
+		this.r.removeLast();
+
+		pi = this.r.getPathIterator();
+		assertElement(pi, PathElementType.MOVE_TO, 1f, 1f);
+		assertElement(pi, PathElementType.LINE_TO, 2f, 2f);
+		assertElement(pi, PathElementType.QUAD_TO, 3f, 0f, 4f, 3f);
+		assertNoElement(pi);
+
+		this.r.removeLast();
+
+		pi = this.r.getPathIterator();
+		assertElement(pi, PathElementType.MOVE_TO, 1f, 1f);
+		assertElement(pi, PathElementType.LINE_TO, 2f, 2f);
+		assertNoElement(pi);
+
+		this.r.removeLast();
+
+		pi = this.r.getPathIterator();
+		assertElement(pi, PathElementType.MOVE_TO, 1f, 1f);
+		assertNoElement(pi);
+
+		this.r.removeLast();
+
+		pi = this.r.getPathIterator();
+		assertNoElement(pi);
+
+		this.r.removeLast();
+
+		pi = this.r.getPathIterator();
+		assertNoElement(pi);
+	}
+
+	/**
+	 */
+	@Override
+	public void testSetLastPointFloatFloat() {
+		PathIterator2f pi = this.r.getPathIterator();
+		assertElement(pi, PathElementType.MOVE_TO, 1f, 1f);
+		assertElement(pi, PathElementType.LINE_TO, 2f, 2f);
+		assertElement(pi, PathElementType.QUAD_TO, 3f, 0f, 4f, 3f);
+		assertElement(pi, PathElementType.CURVE_TO, 5f, -1f, 6f, 5f, 7f, -5f);
+		assertElement(pi, PathElementType.CLOSE);
+		assertNoElement(pi);
+		
+		this.r.setLastPoint(123.456f, 789.1011f);
+
+		pi = this.r.getPathIterator();
+		assertElement(pi, PathElementType.MOVE_TO, 1f, 1f);
+		assertElement(pi, PathElementType.LINE_TO, 2f, 2f);
+		assertElement(pi, PathElementType.QUAD_TO, 3f, 0f, 4f, 3f);
+		assertElement(pi, PathElementType.CURVE_TO, 5f, -1f, 6f, 5f, 123.456f, 789.1011f);
+		assertElement(pi, PathElementType.CLOSE);
+		assertNoElement(pi);
+	}
+	
+	/**
+	 */
+	@Override
+	public void testRemoveFloatFloat() {
+		PathIterator2f pi = this.r.getPathIterator();
+		assertElement(pi, PathElementType.MOVE_TO, 1f, 1f);
+		assertElement(pi, PathElementType.LINE_TO, 2f, 2f);
+		assertElement(pi, PathElementType.QUAD_TO, 3f, 0f, 4f, 3f);
+		assertElement(pi, PathElementType.CURVE_TO, 5f, -1f, 6f, 5f, 7f, -5f);
+		assertElement(pi, PathElementType.CLOSE);
+		assertNoElement(pi);
+		
+		this.r.remove(2f, 2f);
+
+		pi = this.r.getPathIterator();
+		assertElement(pi, PathElementType.MOVE_TO, 1f, 1f);
+		assertElement(pi, PathElementType.QUAD_TO, 3f, 0f, 4f, 3f);
+		assertElement(pi, PathElementType.CURVE_TO, 5f, -1f, 6f, 5f, 7f, -5f);
+		assertElement(pi, PathElementType.CLOSE);
+		assertNoElement(pi);
+
+		this.r.remove(4f, 3f);
+
+		pi = this.r.getPathIterator();
+		assertElement(pi, PathElementType.MOVE_TO, 1f, 1f);
+		assertElement(pi, PathElementType.CURVE_TO, 5f, -1f, 6f, 5f, 7f, -5f);
+		assertElement(pi, PathElementType.CLOSE);
+		assertNoElement(pi);
+
+		this.r.remove(6f, 5f);
+
+		pi = this.r.getPathIterator();
+		assertElement(pi, PathElementType.MOVE_TO, 1f, 1f);
+		assertElement(pi, PathElementType.CLOSE);
+		assertNoElement(pi);
+
+		this.r.remove(6f, 5f);
+
+		pi = this.r.getPathIterator();
+		assertElement(pi, PathElementType.MOVE_TO, 1f, 1f);
+		assertElement(pi, PathElementType.CLOSE);
+		assertNoElement(pi);
+	}
+
+	/**
+	 */
+	@Override
+	public void testContainsPointPoint2D() {
+		PathIterator2f pi = this.r.getPathIterator();
+		assertElement(pi, PathElementType.MOVE_TO, 1f, 1f);
+		assertElement(pi, PathElementType.LINE_TO, 2f, 2f);
+		assertElement(pi, PathElementType.QUAD_TO, 3f, 0f, 4f, 3f);
+		assertElement(pi, PathElementType.CURVE_TO, 5f, -1f, 6f, 5f, 7f, -5f);
+		assertElement(pi, PathElementType.CLOSE);
+		assertNoElement(pi);
+		
+		assertTrue(this.r.containsPoint(new Point2f(2f, 2f)));
+		assertFalse(this.r.containsPoint(new Point2f(4f, 4f)));
+		assertTrue(this.r.containsPoint(new Point2f(6f, 5f)));
+		assertFalse(this.r.containsPoint(new Point2f(-1f, 6f)));
+		assertFalse(this.r.containsPoint(new Point2f(1234f, 5678f)));
+	}
+
+}
\ No newline at end of file

Modified: trunk/math/src/test/java/org/arakhne/afc/math/continous/object2d/Ellipse2fTest.java
===================================================================
--- trunk/math/src/test/java/org/arakhne/afc/math/continous/object2d/Ellipse2fTest.java	2013-04-05 20:39:57 UTC (rev 413)
+++ trunk/math/src/test/java/org/arakhne/afc/math/continous/object2d/Ellipse2fTest.java	2013-04-05 21:45:07 UTC (rev 414)
@@ -451,6 +451,11 @@
 				6f, -5f, 1f, 2f, 6.9765625f, -4.7685423f, 6.9882812f, -4.8835435f));
 		assertTrue(Ellipse2f.intersectsEllipseLine(
 				6f, -5f, 1f, 2f, 6.9882812f, -4.8835435f, 7f, -5f));
+
+		assertTrue(Ellipse2f.intersectsEllipseLine(
+				0f, 0f, 1f, 2f, .5f, -1f, .5f, 2f));
+		assertTrue(Ellipse2f.intersectsEllipseLine(
+				0f, 0f, 1f, 2f, .5f, -1f, .5f, -.5f));
 	}
 
 	/**
@@ -517,6 +522,11 @@
 				6f, -5f, 1f, 2f, 6.9765625f, -4.7685423f, 6.9882812f, -4.8835435f));
 		assertFalse(Ellipse2f.intersectsEllipseSegment(
 				6f, -5f, 1f, 2f, 6.9882812f, -4.8835435f, 7f, -5f));
+
+		assertTrue(Ellipse2f.intersectsEllipseSegment(
+				0f, 0f, 1f, 2f, .5f, -1f, .5f, 2f));
+		assertFalse(Ellipse2f.intersectsEllipseSegment(
+				0f, 0f, 1f, 2f, .5f, -1f, .5f, -.5f));
 	}
 	
 }
\ No newline at end of file

Added: trunk/math/src/test/java/org/arakhne/afc/math/continous/object2d/OpenPath2fTest.java
===================================================================
--- trunk/math/src/test/java/org/arakhne/afc/math/continous/object2d/OpenPath2fTest.java	                        (rev 0)
+++ trunk/math/src/test/java/org/arakhne/afc/math/continous/object2d/OpenPath2fTest.java	2013-04-05 21:45:07 UTC (rev 414)
@@ -0,0 +1,746 @@
+/* 
+ * $Id$
+ * 
+ * Copyright (c) 2006-10, Multiagent Team, Laboratoire Systemes et Transports, Universite de Technologie de Belfort-Montbeliard.
+ * Copyright (C) 2012 Stephane GALLAND.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library 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.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * This program is free software; you can redistribute it and/or modify
+ */
+package org.arakhne.afc.math.continous.object2d;
+
+import org.arakhne.afc.math.generic.PathElementType;
+import org.arakhne.afc.math.generic.Point2D;
+import org.arakhne.afc.math.matrix.Transform2D;
+
+/**
+ * @author $Author: galland$
+ * @version $FullVersion$
+ * @mavengroupid $GroupId$
+ * @mavenartifactid $ArtifactId$
+ */
+public class OpenPath2fTest extends AbstractPath2fTestCase {
+
+	@Override
+	protected Path2f createShape() {
+		Path2f p = new Path2f();
+		p.moveTo(1f, 1f);
+		p.lineTo(2f, 2f);
+		p.quadTo(3f, 0f, 4f, 3f);
+		p.curveTo(5f, -1f, 6f, 5f, 7f, -5f);
+		return p;
+	}
+
+	/**
+	 */
+	@Override
+	public void testGetClosestPointTo() {
+		Point2D p;
+
+		p = this.r.getClosestPointTo(new Point2f(0f, 0f));
+		assertEpsilonEquals(1f, p.getX());
+		assertEpsilonEquals(1f, p.getY());
+
+		p = this.r.getClosestPointTo(new Point2f(4f, 0f));
+		assertEpsilonEquals(3f, p.getX());
+		assertEpsilonEquals(1.25f, p.getY());
+
+		p = this.r.getClosestPointTo(new Point2f(4f, 2f));
+		assertEpsilonEquals(4.28125f, p.getX());
+		assertEpsilonEquals(2.11724f, p.getY());
+
+		p = this.r.getClosestPointTo(new Point2f(1f, 0f));
+		assertEpsilonEquals(1f, p.getX());
+		assertEpsilonEquals(1f, p.getY());
+	}
+
+
+	@Override
+	public void testDistancePoint2D() {
+		assertEpsilonEquals(1.414213562f, this.r.distance(new Point2f(0f, 0f)));
+		assertEpsilonEquals(1.600781059f, this.r.distance(new Point2f(4f, 0f)));
+		assertEpsilonEquals(0.304707696f, this.r.distance(new Point2f(4f, 2f)));
+		assertEpsilonEquals(1f, this.r.distance(new Point2f(1f, 0f)));
+	}
+
+	@Override
+	public void testDistanceSquaredPoint2D() {
+		assertEpsilonEquals(2f, this.r.distanceSquared(new Point2f(0f, 0f)));
+		assertEpsilonEquals(2.5625f, this.r.distanceSquared(new Point2f(4f, 0f)));
+		assertEpsilonEquals(.09284678f, this.r.distanceSquared(new Point2f(4f, 2f)));
+		assertEpsilonEquals(1f, this.r.distanceSquared(new Point2f(1f, 0f)));
+	}
+
+	@Override
+	public void testDistanceL1Point2D() {
+		// (1,1)
+		assertEpsilonEquals(2f, this.r.distanceL1(new Point2f(0f, 0f)));
+		// (3,1.25)
+		assertEpsilonEquals(2.25f, this.r.distanceL1(new Point2f(4f, 0f)));
+		// (4.28125,2.11724)
+		assertEpsilonEquals(.39849f, this.r.distanceL1(new Point2f(4f, 2f)));
+		// (1,1)
+		assertEpsilonEquals(1f, this.r.distanceL1(new Point2f(1f, 0f)));
+	}
+
+	@Override
+	public void testDistanceLinfPoint2D() {
+		// (1,1)
+		assertEpsilonEquals(1f, this.r.distanceLinf(new Point2f(0f, 0f)));
+		// (3,1.25)
+		assertEpsilonEquals(1.25f, this.r.distanceLinf(new Point2f(4f, 0f)));
+		// (4.28125,2.11724)
+		assertEpsilonEquals(.28125f, this.r.distanceLinf(new Point2f(4f, 2f)));
+		// (1,1)
+		assertEpsilonEquals(1f, this.r.distanceLinf(new Point2f(1f, 0f)));
+	}
+
+	@Override
+	public void testTranslateFloatFloat() {
+		this.r.translate(3.4f, 4.5f);
+		PathIterator2f pi = this.r.getPathIterator();
+		assertElement(pi, PathElementType.MOVE_TO, 4.4f, 5.5f);
+		assertElement(pi, PathElementType.LINE_TO, 5.4f, 6.5f);
+		assertElement(pi, PathElementType.QUAD_TO, 6.4f, 4.5f, 7.4f, 7.5f);
+		assertElement(pi, PathElementType.CURVE_TO, 8.4f, 3.5f, 9.4f, 9.5f, 10.4f, -.5f);
+		assertNoElement(pi);
+	}
+
+	/**
+	 */
+	@Override
+	public void testAddIterator() {
+		Path2f p2 = new Path2f();
+		p2.moveTo(3.4f, 4.5f);
+		p2.lineTo(5.6f, 6.7f);
+
+		this.r.add(p2.getPathIterator());
+
+		PathIterator2f pi = this.r.getPathIterator();
+		assertElement(pi, PathElementType.MOVE_TO, 1f, 1f);
+		assertElement(pi, PathElementType.LINE_TO, 2f, 2f);
+		assertElement(pi, PathElementType.QUAD_TO, 3f, 0f, 4f, 3f);
+		assertElement(pi, PathElementType.CURVE_TO, 5f, -1f, 6f, 5f, 7f, -5f);
+		assertElement(pi, PathElementType.MOVE_TO, 3.4f, 4.5f);
+		assertElement(pi, PathElementType.LINE_TO, 5.6f, 6.7f);
+		assertNoElement(pi);
+	}
+
+	/** 
+	 */
+	@Override
+	public void testGetPathIteratorVoid() {
+		PathIterator2f pi = this.r.getPathIterator();
+		assertElement(pi, PathElementType.MOVE_TO, 1f, 1f);
+		assertElement(pi, PathElementType.LINE_TO, 2f, 2f);
+		assertElement(pi, PathElementType.QUAD_TO, 3f, 0f, 4f, 3f);
+		assertElement(pi, PathElementType.CURVE_TO, 5f, -1f, 6f, 5f, 7f, -5f);
+		assertNoElement(pi);
+	}
+
+	/** 
+	 */
+	@Override
+	public void testGetPathIteratorTransform2D() {
+		Transform2D tr;
+		PathIterator2f pi;
+
+		tr = new Transform2D();
+		pi = this.r.getPathIterator(tr);
+		assertElement(pi, PathElementType.MOVE_TO, 1f, 1f);
+		assertElement(pi, PathElementType.LINE_TO, 2f, 2f);
+		assertElement(pi, PathElementType.QUAD_TO, 3f, 0f, 4f, 3f);
+		assertElement(pi, PathElementType.CURVE_TO, 5f, -1f, 6f, 5f, 7f, -5f);
+		assertNoElement(pi);
+
+		tr = new Transform2D();
+		tr.makeTranslationMatrix(3.4f, 4.5f);
+		pi = this.r.getPathIterator(tr);
+		assertElement(pi, PathElementType.MOVE_TO, 4.4f, 5.5f);
+		assertElement(pi, PathElementType.LINE_TO, 5.4f, 6.5f);
+		assertElement(pi, PathElementType.QUAD_TO, 6.4f, 4.5f, 7.4f, 7.5f);
+		assertElement(pi, PathElementType.CURVE_TO, 8.4f, 3.5f, 9.4f, 9.5f, 10.4f, -.5f);
+		assertNoElement(pi);
+	}
+
+	/** 
+	 */
+	@Override
+	public void testTransformTransform2D() {
+		Transform2D tr = new Transform2D();
+		tr.makeTranslationMatrix(3.4f, 4.5f);
+		Transform2D tr2 = new Transform2D();
+		tr2.makeRotationMatrix(5.6f);
+
+		Path2f clone = this.r.clone();
+		clone.transform(tr);
+
+		PathIterator2f pi = clone.getPathIterator();
+		assertElement(pi, PathElementType.MOVE_TO, 4.4f, 5.5f);
+		assertElement(pi, PathElementType.LINE_TO, 5.4f, 6.5f);
+		assertElement(pi, PathElementType.QUAD_TO, 6.4f, 4.5f, 7.4f, 7.5f);
+		assertElement(pi, PathElementType.CURVE_TO, 8.4f, 3.5f, 9.4f, 9.5f, 10.4f, -.5f);
+		assertNoElement(pi);
+
+		clone = this.r.clone();
+		clone.transform(tr2);
+
+		pi = clone.getPathIterator();
+		assertElement(pi, PathElementType.MOVE_TO, 1.406832516382571f, 0.144299240637928f);
+		assertElement(pi, PathElementType.LINE_TO, 2.813665032765142f, 0.288598481275856f);
+		assertElement(pi, PathElementType.QUAD_TO, 2.32669763553075f, -1.89379991361696f,
+				4.996063427657964f, -0.198368915958538f);
+		assertElement(pi, PathElementType.CURVE_TO, 3.24656275467893f, -3.93189906787186f,
+				7.8097284604231056f, 0.0902295653173185f,
+				2.27262796021014f, -8.29669585765750f);
+		assertNoElement(pi);
+
+		Transform2D tr3 = new Transform2D();
+		tr3.mul(tr, tr2);
+		clone = this.r.clone();
+		clone.transform(tr3);
+
+		pi = clone.getPathIterator();
+		assertElement(pi, PathElementType.MOVE_TO, 4.80683251638257f, 4.64429924063793f);
+		assertElement(pi, PathElementType.LINE_TO, 6.21366503276514f, 4.78859848127586f);
+		assertElement(pi, PathElementType.QUAD_TO, 5.72669763553075f, 2.60620008638304f,
+				8.39606342765796f, 4.30163108404146f);
+		assertElement(pi, PathElementType.CURVE_TO, 6.646562754678927f, 0.568100932128142f,
+				11.20972846042311f, 4.59022956531732f, 5.67262796021014f, -3.79669585765750f);
+		assertNoElement(pi);
+	}
+
+	/** 
+	 */
+	@Override
+	public void testCreateTransformedShape2D() {
+		Transform2D tr = new Transform2D();
+		tr.makeTranslationMatrix(3.4f, 4.5f);
+		Path2f p2 = (Path2f)this.r.createTransformedShape(tr);
+
+		PathIterator2f pi = p2.getPathIterator();
+		assertElement(pi, PathElementType.MOVE_TO, 4.4f, 5.5f);
+		assertElement(pi, PathElementType.LINE_TO, 5.4f, 6.5f);
+		assertElement(pi, PathElementType.QUAD_TO, 6.4f, 4.5f, 7.4f, 7.5f);
+		assertElement(pi, PathElementType.CURVE_TO, 8.4f, 3.5f, 9.4f, 9.5f, 10.4f, -.5f);
+		assertNoElement(pi);
+	}
+
+/*	private static int toX(float x) {
+		return (int)(x * 100) + 20;
+	}
+
+	private static int toY(float y) {
+		return (int)(1000 - ((y * 100) + 600));
+	}
+
+	private static int toS(float s) {
+		return (int)(s * 100);
+	}
+
+	public void testImageGeneration() throws IOException {
+		PathIterator2f pi;
+		BufferedImage img = new BufferedImage(800, 1000, BufferedImage.TYPE_INT_ARGB);
+		Graphics2D g = (Graphics2D)img.getGraphics();
+		//Background
+		g.setColor(Color.WHITE);
+		g.fillRect(0, 0, 800, 1000);
+
+		//
+		// POINTS
+		Point2f[] points = new Point2f[] {
+				//				new Point2f(0f, 0f),
+				//				new Point2f(4f, 3f),
+				//				new Point2f(2f, 2f),
+				//				new Point2f(2f, 1f),
+				//				new Point2f(5f, 0f),
+				//				new Point2f(-1f, -1f),
+				//				new Point2f(5f, 2f),
+				//				new Point2f(3.5f, -2.5f),
+				//				new Point2f(7f, -4f),
+				//				new Point2f(2.5f, 1.5f),
+		};
+
+		//
+		// LINES
+		Segment2f[] lines = new Segment2f[] {
+				//new Segment2f(6.7773438f, -3.0272121f, 6.7890625f, -3.1188917f),
+				//new Segment2f(6.7890625f, -3.1188917f, 6.8007812f, -3.2118688f),
+				//new Segment2f(6.8007812f, -3.2118688f, 6.8125f, -3.3061523f),
+				//new Segment2f(6.9414062f, -4.4321795f, 6.953125f, -4.5428696f),
+				//new Segment2f(.5f, -1f, .5f, 2f),
+		};
+
+		//
+		// SEGMENTS
+		Segment2f[] segments = new Segment2f[] {
+				//				new Segment2f(0f, 0f, 1f, 1f),
+				//				new Segment2f(4f, 3f, 1f, 1f),
+				//				new Segment2f(2f, 2f, 1f, 1f),
+				//				new Segment2f(2f, 1f, 1f, 1f),
+				//				new Segment2f(3f, 0f, 1f, 1f),
+				//				new Segment2f(3f, 0f, 1.5f, 1f),
+				//				new Segment2f(-1f, -1f, 1f, 1f),
+				//				new Segment2f(4f, -3f, 1f, 1f),
+				//				new Segment2f(4f, -3f, 1f, 0f),
+				//				new Segment2f(-3f, 4f, 1f, 1f),
+				//				new Segment2f(6f, -5f, 1f, 1f),
+				//				new Segment2f(6f, -5f, 1f, 0f),
+				//				new Segment2f(4f, 0f, 1f, 1f),
+				//				new Segment2f(5f, 0f, 1f, 1f),
+				//				new Segment2f(.01f, .01f, 1f, 1f),
+		};
+
+		//
+		// CIRCLES
+		Circle2f[] circles = new Circle2f[] {
+				//				new Circle2f(0f, 0f, 1f),
+				//				new Circle2f(4f, 3f, 1f),
+				//				new Circle2f(2f, 2f, 1f),
+				//				new Circle2f(2f, 1f, 1f),
+				//				new Circle2f(3f, 0f, 1f),
+				//				new Circle2f(-1f, -1f, 1f),
+				//				new Circle2f(4f, -3f, 1f),
+				//				new Circle2f(-3f, 4f, 1f),
+				//				new Circle2f(6f, -5f, 1f),
+				//				new Circle2f(6f, -5f, .95f),
+				//				new Circle2f(4f, 0f, 1f),
+				//				new Circle2f(5f, 0f, 1f),
+				//				new Circle2f(.01f, .01f, 1f),
+				//				new Circle2f(6f, 2f, .8f),
+		};
+
+		//
+		// RECTANGLES
+		Rectangle2f[] rectangles = new Rectangle2f[] {
+				new Rectangle2f(0f, 0f, 1f, 1f),
+				new Rectangle2f(4f, 3f, 1f, 1f),
+				new Rectangle2f(2f, 2f, 1f, 1f),
+				new Rectangle2f(2f, 1f, 1f, 1f),
+				new Rectangle2f(3f, 0f, 1f, 1f),
+				new Rectangle2f(-1f, -1f, 1f, 1f),
+				new Rectangle2f(4f, -3f, 1f, 1f),
+				new Rectangle2f(-3f, 4f, 1f, 1f),
+				new Rectangle2f(6f, -5f, 1f, 1f),
+				new Rectangle2f(4f, 0f, 1f, 1f),
+				new Rectangle2f(5f, 0f, 1f, 1f),
+				new Rectangle2f(.01f, .01f, 1f, 1f),
+		};
+
+		//
+		// ELLIPSES
+		Ellipse2f[] ellipses = new Ellipse2f[] {
+				//				new Ellipse2f(0f, 0f, 1f, 2f),
+				//				new Ellipse2f(4f, 3f, 1f, 2f),
+				//				new Ellipse2f(2f, 2f, 1f, 2f),
+				//				new Ellipse2f(2f, 1f, 1f, 2f),
+				//				new Ellipse2f(3f, 0f, 1f, 2f),
+				//				new Ellipse2f(-1f, -1f, 1f, 2f),
+				//				new Ellipse2f(4f, -3f, 1f, 2f),
+				//				new Ellipse2f(-3f, 4f, 1f, 2f),
+				//				new Ellipse2f(6f, -5f, 1f, 2f),
+				//				new Ellipse2f(6f, -5f, .8f, 2f),
+				//				new Ellipse2f(4f, 0f, 1f, 2f),
+				//				new Ellipse2f(6f, 0f, 1f, 2f),
+		};
+
+		// Elements
+		g.setColor(Color.ORANGE);
+		for(Point2f obj : points) {
+			g.fillRect(
+					toX(obj.getX()) - 4, toY(obj.getY()) - 4,
+					9, 9);
+		}
+		Stroke oldStroke = g.getStroke();
+		for(Segment2f obj : lines) {
+			int xx1 = toX(obj.getX1());
+			int yy1 = toY(obj.getY1());
+			int xx2 = toX(obj.getX2());
+			int yy2 = toY(obj.getY2());
+
+			g.setStroke(new BasicStroke(2));
+			Vector2f v = new Vector2f(xx2 - xx1, yy2 - yy1);
+			v.normalize();
+			v.scale(1000);
+			int px1 = (int)(xx1 + v.x);
+			int py1 = (int)(yy1 + v.y);
+			int px2 = (int)(xx1 - v.x);
+			int py2 = (int)(yy1 - v.y);
+			g.drawLine(px1, py1, px2, py2);
+
+			g.setStroke(new BasicStroke(4));
+			g.drawLine(xx1, yy1, xx2, yy2);
+		}
+		g.setStroke(new BasicStroke(3));
+		for(Segment2f obj : segments) {
+			g.drawLine(
+					toX(obj.getX1()), toY(obj.getY1()),
+					toX(obj.getX2()), toY(obj.getY2()));
+		}
+		g.setStroke(oldStroke);
+		for(Circle2f obj : circles) {
+			int r = toS(obj.getRadius());
+			g.drawOval(
+					toX(obj.getX())-r, toY(obj.getY())-r,
+					r*2, r*2);
+		}
+		for(Ellipse2f obj : ellipses) {
+			int x1 = toX(obj.getMinX());
+			int y1 = toY(obj.getMinY());
+			int x2 = toX(obj.getMaxX());
+			int y2 = toY(obj.getMaxY());
+			g.drawOval(
+					Math.min(x1, x2), Math.min(y1, y2),
+					toS(obj.getWidth()), toS(obj.getHeight()));
+		}
+		for(Rectangle2f obj : rectangles) {
+			int x1 = toX(obj.getMinX());
+			int y1 = toY(obj.getMinY());
+			int x2 = toX(obj.getMaxX());
+			int y2 = toY(obj.getMaxY());
+			g.fillRect(
+					Math.min(x1, x2), Math.min(y1, y2),
+					toS(obj.getWidth()), toS(obj.getHeight()));
+		}
+
+		// Cells
+		g.setColor(Color.LIGHT_GRAY);
+		for(float y=-6; y<=4; y+=1) {
+			if (y!=0f) g.drawLine(toX(-10), toY(y), toX(10), toY(y));
+		}
+		for(float x=-1; x<=8; x+=1) {
+			if (x!=0f) g.drawLine(toX(x), toY(-10), toX(x), toY(10));
+		}
+		g.setColor(Color.BLACK);
+		g.drawLine(toX(-10), toY(0), toX(10), toY(0));
+		g.drawLine(toX(0), toY(-10), toX(0), toY(10));
+
+		// Path
+		g.setColor(Color.RED);
+		pi = this.r.getPathIterator(MathConstants.SPLINE_APPROXIMATION_RATIO);
+		boolean closed = false;
+		int mx, my, cx, cy;
+		mx = my = cx = cy = 0;
+		while (pi.hasNext()) {
+			PathElement2f pe = pi.next();
+			switch(pe.type) {
+			case MOVE_TO:
+				cx = mx = toX(pe.toX);
+				cy = my = toY(pe.toY);
+				break;
+			case LINE_TO:
+				cx = toX(pe.toX);
+				cy = toY(pe.toY);
+				g.drawLine(
+						toX(pe.fromX), toY(pe.fromY),
+						cx, cy);
+				break;
+			case CLOSE:
+				cx = toX(pe.toX);
+				cy = toY(pe.toY);
+				g.drawLine(
+						toX(pe.fromX), toY(pe.fromY),
+						cx, cy);
+				closed = true;
+				break;
+			default:
+			}
+		}
+		if (!closed) {
+			g.setStroke(new BasicStroke(
+					1,
+					BasicStroke.CAP_ROUND,
+					BasicStroke.JOIN_ROUND,
+					2,
+					new float[]{5,5},
+					0f));
+			g.drawLine(
+					mx, my,
+					cx, cy);
+		}
+		g.dispose();
+		ImageIO.write(img, "png", new File(FileSystem.getUserHomeDirectory(), "mytest.png"));
+	}*/
+
+	/**
+	 */
+	@Override
+	public void testContainsPathIterator2fFloatFloat() {
+		assertFalse(Path2f.contains(this.r.getPathIterator(), 0f, 0f));
+		assertTrue(Path2f.contains(this.r.getPathIterator(), 4f, 3f));
+		assertTrue(Path2f.contains(this.r.getPathIterator(), 2f, 2f));
+		assertFalse(Path2f.contains(this.r.getPathIterator(), 2f, 1f));
+		assertFalse(Path2f.contains(this.r.getPathIterator(), 5f, 0f));
+		assertFalse(Path2f.contains(this.r.getPathIterator(), -1f, -1f));
+	}
+
+	/** 
+	 */
+	@Override
+	public void testContainsFloatfloat() {
+		assertFalse(this.r.contains(0f, 0f));
+		assertTrue(this.r.contains(4f, 3f));
+		assertTrue(this.r.contains(2f, 2f));
+		assertFalse(this.r.contains(2f, 1f));
+		assertFalse(this.r.contains(5f, 0f));
+		assertFalse(this.r.contains(-1f, -1f));
+		assertFalse(this.r.contains(5f, 2f));
+		assertFalse(this.r.contains(3.5f, -2.5f));
+		assertFalse(this.r.contains(7f, -4f));
+		assertFalse(this.r.contains(2.5f, 1.5f));
+	}
+
+	/** 
+	 */
+	@Override
+	public void testContainsRectangle2f() {
+		assertFalse(this.r.contains(new Rectangle2f(0f, 0f, 1f, 1f)));
+		assertFalse(this.r.contains(new Rectangle2f(4f, 3f, 1f, 1f)));
+		assertFalse(this.r.contains(new Rectangle2f(2f, 2f, 1f, 1f)));
+		assertFalse(this.r.contains(new Rectangle2f(2f, 1f, 1f, 1f)));
+		assertFalse(this.r.contains(new Rectangle2f(3f, 0f, 1f, 1f)));
+		assertFalse(this.r.contains(new Rectangle2f(-1f, -1f, 1f, 1f)));
+		assertFalse(this.r.contains(new Rectangle2f(4f, -3f, 1f, 1f)));
+		assertFalse(this.r.contains(new Rectangle2f(-3f, 4f, 1f, 1f)));
+		assertFalse(this.r.contains(new Rectangle2f(6f, -5f, 1f, 1f)));
+		assertFalse(this.r.contains(new Rectangle2f(4f, 0f, 1f, 1f)));
+		assertFalse(this.r.contains(new Rectangle2f(5f, 0f, 1f, 1f)));
+		assertFalse(this.r.contains(new Rectangle2f(.01f, .01f, 1f, 1f)));
+	}
+
+	/** 
+	 */
+	@Override
+	public void testIntersectsRectangle2f() {
+		assertFalse(this.r.intersects(new Rectangle2f(0f, 0f, 1f, 1f)));
+		assertFalse(this.r.intersects(new Rectangle2f(4f, 3f, 1f, 1f)));
+		assertFalse(this.r.intersects(new Rectangle2f(2f, 2f, 1f, 1f)));
+		assertTrue(this.r.intersects(new Rectangle2f(2f, 1f, 1f, 1f)));
+		assertFalse(this.r.intersects(new Rectangle2f(3f, 0f, 1f, 1f)));
+		assertFalse(this.r.intersects(new Rectangle2f(-1f, -1f, 1f, 1f)));
+		assertFalse(this.r.intersects(new Rectangle2f(4f, -3f, 1f, 1f)));
+		assertFalse(this.r.intersects(new Rectangle2f(-3f, 4f, 1f, 1f)));
+		assertTrue(this.r.intersects(new Rectangle2f(6f, -5f, 1f, 1f)));
+		assertFalse(this.r.intersects(new Rectangle2f(4f, 0f, 1f, 1f)));
+		assertTrue(this.r.intersects(new Rectangle2f(5f, 0f, 1f, 1f)));
+		assertTrue(this.r.intersects(new Rectangle2f(.01f, .01f, 1f, 1f)));
+	}
+
+	@Override
+	public void testIntersectsPathIterator2fFloatFloatFloatFloat() {
+		assertFalse(Path2f.intersects(this.r.getPathIterator(), 0f, 0f, 1f, 1f));
+		assertFalse(Path2f.intersects(this.r.getPathIterator(), 4f, 3f, 1f, 1f));
+		assertFalse(Path2f.intersects(this.r.getPathIterator(), 2f, 2f, 1f, 1f));
+		assertTrue(Path2f.intersects(this.r.getPathIterator(), 2f, 1f, 1f, 1f));
+		assertFalse(Path2f.intersects(this.r.getPathIterator(), 3f, 0f, 1f, 1f));
+		assertFalse(Path2f.intersects(this.r.getPathIterator(), -1f, -1f, 1f, 1f));
+		assertFalse(Path2f.intersects(this.r.getPathIterator(), 4f, -3f, 1f, 1f));
+		assertFalse(Path2f.intersects(this.r.getPathIterator(), -3f, 4f, 1f, 1f));
+		assertTrue(Path2f.intersects(this.r.getPathIterator(), 6f, -5f, 1f, 1f));
+		assertFalse(Path2f.intersects(this.r.getPathIterator(), 4f, 0f, 1f, 1f));
+		assertTrue(Path2f.intersects(this.r.getPathIterator(), 5f, 0f, 1f, 1f));
+		assertTrue(Path2f.intersects(this.r.getPathIterator(), .01f, .01f, 1f, 1f));
+	}
+
+	/** 
+	 */
+	@Override
+	public void testIntersectsEllipse2f() {
+		assertFalse(this.r.intersects(new Ellipse2f(0f, 0f, 1f, 2f)));
+		assertFalse(this.r.intersects(new Ellipse2f(4f, 3f, 1f, 2f)));
+		assertFalse(this.r.intersects(new Ellipse2f(2f, 2f, 1f, 2f)));
+		assertTrue(this.r.intersects(new Ellipse2f(2f, 1f, 1f, 2f)));
+		assertTrue(this.r.intersects(new Ellipse2f(3f, 0f, 1f, 2f)));
+		assertFalse(this.r.intersects(new Ellipse2f(-1f, -1f, 1f, 2f)));
+		assertFalse(this.r.intersects(new Ellipse2f(4f, -3f, 1f, 2f)));
+		assertFalse(this.r.intersects(new Ellipse2f(-3f, 4f, 1f, 2f)));
+		assertTrue(this.r.intersects(new Ellipse2f(6f, -5f, 1f, 2f)));
+		assertFalse(this.r.intersects(new Ellipse2f(6f, -5f, .8f, 2f)));
+		assertTrue(this.r.intersects(new Ellipse2f(4f, 0f, 1f, 2f)));
+		assertFalse(this.r.intersects(new Ellipse2f(6f, 0f, 1f, 2f)));
+	}
+
+	/** 
+	 */
+	@Override
+	public void testIntersectsCircle2f() {
+		assertFalse(this.r.intersects(new Circle2f(0f, 0f, 1f)));
+		assertTrue(this.r.intersects(new Circle2f(4f, 3f, 1f)));
+		assertTrue(this.r.intersects(new Circle2f(2f, 2f, 1f)));
+		assertTrue(this.r.intersects(new Circle2f(2f, 1f, 1f)));
+		assertFalse(this.r.intersects(new Circle2f(3f, 0f, 1f)));
+		assertFalse(this.r.intersects(new Circle2f(-1f, -1f, 1f)));
+		assertFalse(this.r.intersects(new Circle2f(4f, -3f, 1f)));
+		assertFalse(this.r.intersects(new Circle2f(-3f, 4f, 1f)));
+		assertTrue(this.r.intersects(new Circle2f(6f, -5f, 1f)));
+		assertFalse(this.r.intersects(new Circle2f(6f, -5f, .95f)));
+		assertFalse(this.r.intersects(new Circle2f(4f, 0f, 1f)));
+		assertFalse(this.r.intersects(new Circle2f(5f, 0f, 1f)));
+		assertFalse(this.r.intersects(new Circle2f(.01f, .01f, 1f)));
+		assertFalse(this.r.intersects(new Circle2f(6f, 2f, .8f)));
+	}
+
+	/** 
+	 */
+	@Override
+	public void testIntersectsSegment2f() {
+		assertFalse(this.r.intersects(new Segment2f(0f, 0f, 1f, 1f)));
+		assertTrue(this.r.intersects(new Segment2f(4f, 3f, 1f, 1f)));
+		assertTrue(this.r.intersects(new Segment2f(2f, 2f, 1f, 1f)));
+		assertFalse(this.r.intersects(new Segment2f(2f, 1f, 1f, 1f)));
+		assertFalse(this.r.intersects(new Segment2f(3f, 0f, 1f, 1f)));
+		assertFalse(this.r.intersects(new Segment2f(3f, 0f, 1.5f, 1f)));
+		assertFalse(this.r.intersects(new Segment2f(-1f, -1f, 1f, 1f)));
+		assertFalse(this.r.intersects(new Segment2f(4f, -3f, 1f, 1f)));
+		assertFalse(this.r.intersects(new Segment2f(4f, -3f, 1f, 0f)));
+		assertFalse(this.r.intersects(new Segment2f(-3f, 4f, 1f, 1f)));
+		assertFalse(this.r.intersects(new Segment2f(6f, -5f, 1f, 1f)));
+		assertFalse(this.r.intersects(new Segment2f(6f, -5f, 1f, 0f)));
+		assertFalse(this.r.intersects(new Segment2f(4f, 0f, 1f, 1f)));
+		assertFalse(this.r.intersects(new Segment2f(5f, 0f, 1f, 1f)));
+		assertFalse(this.r.intersects(new Segment2f(.01f, .01f, 1f, 1f)));
+	}
+
+	@Override
+	public void testToBoundingBox() {
+		Rectangle2f bb = this.r.toBoundingBox();
+		assertEpsilonEquals(1f, bb.getMinX());
+		assertEpsilonEquals(-5f, bb.getMinY());
+		assertEpsilonEquals(7f, bb.getMaxX());
+		assertEpsilonEquals(5f, bb.getMaxY());
+	}
+
+	/**
+	 */
+	@Override
+	public void testRemoveLast() {
+		PathIterator2f pi = this.r.getPathIterator();
+		assertElement(pi, PathElementType.MOVE_TO, 1f, 1f);
+		assertElement(pi, PathElementType.LINE_TO, 2f, 2f);
+		assertElement(pi, PathElementType.QUAD_TO, 3f, 0f, 4f, 3f);
+		assertElement(pi, PathElementType.CURVE_TO, 5f, -1f, 6f, 5f, 7f, -5f);
+		assertNoElement(pi);
+
+		this.r.removeLast();
+
+		pi = this.r.getPathIterator();
+		assertElement(pi, PathElementType.MOVE_TO, 1f, 1f);
+		assertElement(pi, PathElementType.LINE_TO, 2f, 2f);
+		assertElement(pi, PathElementType.QUAD_TO, 3f, 0f, 4f, 3f);
+		assertNoElement(pi);
+
+		this.r.removeLast();
+
+		pi = this.r.getPathIterator();
+		assertElement(pi, PathElementType.MOVE_TO, 1f, 1f);
+		assertElement(pi, PathElementType.LINE_TO, 2f, 2f);
+		assertNoElement(pi);
+
+		this.r.removeLast();
+
+		pi = this.r.getPathIterator();
+		assertElement(pi, PathElementType.MOVE_TO, 1f, 1f);
+		assertNoElement(pi);
+
+		this.r.removeLast();
+
+		pi = this.r.getPathIterator();
+		assertNoElement(pi);
+
+		this.r.removeLast();
+
+		pi = this.r.getPathIterator();
+		assertNoElement(pi);
+	}
+
+	/**
+	 */
+	@Override
+	public void testSetLastPointFloatFloat() {
+		PathIterator2f pi = this.r.getPathIterator();
+		assertElement(pi, PathElementType.MOVE_TO, 1f, 1f);
+		assertElement(pi, PathElementType.LINE_TO, 2f, 2f);
+		assertElement(pi, PathElementType.QUAD_TO, 3f, 0f, 4f, 3f);
+		assertElement(pi, PathElementType.CURVE_TO, 5f, -1f, 6f, 5f, 7f, -5f);
+		assertNoElement(pi);
+
+		this.r.setLastPoint(123.456f, 789.1011f);
+
+		pi = this.r.getPathIterator();
+		assertElement(pi, PathElementType.MOVE_TO, 1f, 1f);
+		assertElement(pi, PathElementType.LINE_TO, 2f, 2f);
+		assertElement(pi, PathElementType.QUAD_TO, 3f, 0f, 4f, 3f);
+		assertElement(pi, PathElementType.CURVE_TO, 5f, -1f, 6f, 5f, 123.456f, 789.1011f);
+		assertNoElement(pi);
+	}
+
+	/**
+	 */
+	@Override
+	public void testRemoveFloatFloat() {
+		PathIterator2f pi = this.r.getPathIterator();
+		assertElement(pi, PathElementType.MOVE_TO, 1f, 1f);
+		assertElement(pi, PathElementType.LINE_TO, 2f, 2f);
+		assertElement(pi, PathElementType.QUAD_TO, 3f, 0f, 4f, 3f);
+		assertElement(pi, PathElementType.CURVE_TO, 5f, -1f, 6f, 5f, 7f, -5f);
+		assertNoElement(pi);
+
+		this.r.remove(2f, 2f);
+
+		pi = this.r.getPathIterator();
+		assertElement(pi, PathElementType.MOVE_TO, 1f, 1f);
+		assertElement(pi, PathElementType.QUAD_TO, 3f, 0f, 4f, 3f);
+		assertElement(pi, PathElementType.CURVE_TO, 5f, -1f, 6f, 5f, 7f, -5f);
+		assertNoElement(pi);
+
+		this.r.remove(4f, 3f);
+
+		pi = this.r.getPathIterator();
+		assertElement(pi, PathElementType.MOVE_TO, 1f, 1f);
+		assertElement(pi, PathElementType.CURVE_TO, 5f, -1f, 6f, 5f, 7f, -5f);
+		assertNoElement(pi);
+
+		this.r.remove(6f, 5f);
+
+		pi = this.r.getPathIterator();
+		assertElement(pi, PathElementType.MOVE_TO, 1f, 1f);
+		assertNoElement(pi);
+
+		this.r.remove(6f, 5f);
+
+		pi = this.r.getPathIterator();
+		assertElement(pi, PathElementType.MOVE_TO, 1f, 1f);
+		assertNoElement(pi);
+	}
+
+	/**
+	 */
+	@Override
+	public void testContainsPointPoint2D() {
+		PathIterator2f pi = this.r.getPathIterator();
+		assertElement(pi, PathElementType.MOVE_TO, 1f, 1f);
+		assertElement(pi, PathElementType.LINE_TO, 2f, 2f);
+		assertElement(pi, PathElementType.QUAD_TO, 3f, 0f, 4f, 3f);
+		assertElement(pi, PathElementType.CURVE_TO, 5f, -1f, 6f, 5f, 7f, -5f);
+		assertNoElement(pi);
+
+		assertTrue(this.r.containsPoint(new Point2f(2f, 2f)));
+		assertFalse(this.r.containsPoint(new Point2f(4f, 4f)));
+		assertTrue(this.r.containsPoint(new Point2f(6f, 5f)));
+		assertFalse(this.r.containsPoint(new Point2f(-1f, 6f)));
+		assertFalse(this.r.containsPoint(new Point2f(1234f, 5678f)));
+	}
+
+}
\ No newline at end of file

Modified: trunk/math/src/test/java/org/arakhne/afc/math/continous/object2d/Segment2fTest.java
===================================================================
--- trunk/math/src/test/java/org/arakhne/afc/math/continous/object2d/Segment2fTest.java	2013-04-05 20:39:57 UTC (rev 413)
+++ trunk/math/src/test/java/org/arakhne/afc/math/continous/object2d/Segment2fTest.java	2013-04-05 21:45:07 UTC (rev 414)
@@ -336,6 +336,30 @@
 						0,
 						7f, -5f, 1f, 1f,
 						4f, -3f, 1f, 1f));
+		assertEquals(
+				1,
+				Segment2f.computeCrossingsFromSegment(
+						0,
+						4f, -3f, 1f, 1f,
+						7f, -5f, 1f, 1f));
+		assertEquals(
+				1,
+				Segment2f.computeCrossingsFromSegment(
+						0,
+						1f, 1f, 4f, -3f,
+						7f, -5f, 1f, 1f));
+		assertEquals(
+				-1,
+				Segment2f.computeCrossingsFromSegment(
+						0,
+						4f, -3f, 1f, 1f,
+						1f, 1f, 7f, -5f));
+		assertEquals(
+				-1,
+				Segment2f.computeCrossingsFromSegment(
+						0,
+						1f, 1f, 4f, -3f,
+						1f, 1f, 7f, -5f));
 	}
 
 	/**


Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/