Fixed a problem with too thin polygons considered to have infinite size.

Project: http://git-wip-us.apache.org/repos/asf/commons-math/repo
Commit: http://git-wip-us.apache.org/repos/asf/commons-math/commit/e6aae3a8
Tree: http://git-wip-us.apache.org/repos/asf/commons-math/tree/e6aae3a8
Diff: http://git-wip-us.apache.org/repos/asf/commons-math/diff/e6aae3a8

Branch: refs/heads/master
Commit: e6aae3a8bffb981b8dce19642cc1ab831a428cae
Parents: 893ef53
Author: Luc Maisonobe <l...@apache.org>
Authored: Tue Dec 2 22:09:06 2014 +0100
Committer: Luc Maisonobe <l...@apache.org>
Committed: Tue Dec 2 22:09:06 2014 +0100

----------------------------------------------------------------------
 src/changes/changes.xml                         |   3 +
 .../geometry/euclidean/twod/PolygonsSet.java    | 414 +++++++++++++------
 .../euclidean/twod/PolygonsSetTest.java         |  60 +--
 3 files changed, 330 insertions(+), 147 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/commons-math/blob/e6aae3a8/src/changes/changes.xml
----------------------------------------------------------------------
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 46ad704..a4b462c 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -73,6 +73,9 @@ Users are encouraged to upgrade to this version as this 
release not
   2. A few methods in the FastMath class are in fact slower that their
   counterpart in either Math or StrictMath (cf. MATH-740 and MATH-901).
 ">
+      <action dev="luc" type="fix" issue="MATH-1174" >
+        Fixed a problem with too thin polygons considered to have infinite 
size.
+      </action>
       <action dev="luc" type="add" >
         Boundary attributes in regions now provides the BSP tree nodes that
         were used to split the sub-hyperplane froming the boundary part of the 
facet. 

http://git-wip-us.apache.org/repos/asf/commons-math/blob/e6aae3a8/src/main/java/org/apache/commons/math3/geometry/euclidean/twod/PolygonsSet.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/commons/math3/geometry/euclidean/twod/PolygonsSet.java
 
b/src/main/java/org/apache/commons/math3/geometry/euclidean/twod/PolygonsSet.java
index 532d6a0..8361831 100644
--- 
a/src/main/java/org/apache/commons/math3/geometry/euclidean/twod/PolygonsSet.java
+++ 
b/src/main/java/org/apache/commons/math3/geometry/euclidean/twod/PolygonsSet.java
@@ -20,7 +20,6 @@ import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
 
-import org.apache.commons.math3.exception.MathInternalError;
 import org.apache.commons.math3.geometry.Point;
 import org.apache.commons.math3.geometry.euclidean.oned.Euclidean1D;
 import org.apache.commons.math3.geometry.euclidean.oned.Interval;
@@ -31,10 +30,9 @@ import 
org.apache.commons.math3.geometry.partitioning.AbstractSubHyperplane;
 import org.apache.commons.math3.geometry.partitioning.BSPTree;
 import org.apache.commons.math3.geometry.partitioning.BSPTreeVisitor;
 import org.apache.commons.math3.geometry.partitioning.BoundaryAttribute;
+import org.apache.commons.math3.geometry.partitioning.Hyperplane;
 import org.apache.commons.math3.geometry.partitioning.Side;
 import org.apache.commons.math3.geometry.partitioning.SubHyperplane;
-import org.apache.commons.math3.geometry.partitioning.utilities.AVLTree;
-import org.apache.commons.math3.geometry.partitioning.utilities.OrderedTuple;
 import org.apache.commons.math3.util.FastMath;
 
 /** This class represents a 2D region: a set of polygons.
@@ -689,19 +687,34 @@ public class PolygonsSet extends 
AbstractRegion<Euclidean2D, Euclidean1D> {
                 vertices = new Vector2D[0][];
             } else {
 
-                // sort the segments according to their start point
-                final SegmentsBuilder visitor = new SegmentsBuilder();
+                // build the unconnected segments
+                final SegmentsBuilder visitor = new 
SegmentsBuilder(getTolerance());
                 getTree(true).visit(visitor);
-                final AVLTree<ComparableSegment> sorted = visitor.getSorted();
-
-                // identify the loops, starting from the open ones
-                // (their start segments are naturally at the sorted set 
beginning)
-                final ArrayList<List<ComparableSegment>> loops = new 
ArrayList<List<ComparableSegment>>();
-                while (!sorted.isEmpty()) {
-                    final AVLTree<ComparableSegment>.Node node = 
sorted.getSmallest();
-                    final List<ComparableSegment> loop = followLoop(node, 
sorted);
+                final List<ConnectableSegment> segments = 
visitor.getSegments();
+
+                // connect all segments, using topological criteria first
+                // and using Euclidean distance only as a last resort
+                int pending = segments.size();
+                pending -= naturalFollowerConnections(segments);
+                if (pending > 0) {
+                    pending -= splitEdgeConnections(segments);
+                }
+                if (pending > 0) {
+                    pending -= closeVerticesConnections(segments);
+                }
+
+                // create the segment loops
+                final ArrayList<List<ConnectableSegment>> loops = new 
ArrayList<List<ConnectableSegment>>();
+                for (ConnectableSegment s = getUnprocessed(segments); s != 
null; s = getUnprocessed(segments)) {
+                    final List<ConnectableSegment> loop = followLoop(s);
                     if (loop != null) {
-                        loops.add(loop);
+                        if (loop.get(0).getStart() == null) {
+                            // this is an open loop, we put it on the front
+                            loops.add(0, loop);
+                        } else {
+                            // this is a closed loop, we put it on the back
+                            loops.add(loop);
+                        }
                     }
                 }
 
@@ -709,7 +722,7 @@ public class PolygonsSet extends 
AbstractRegion<Euclidean2D, Euclidean1D> {
                 vertices = new Vector2D[loops.size()][];
                 int i = 0;
 
-                for (final List<ComparableSegment> loop : loops) {
+                for (final List<ConnectableSegment> loop : loops) {
                     if (loop.size() < 2 ||
                         (loop.size() == 2 && loop.get(0).getStart() == null && 
loop.get(1).getEnd() == null)) {
                         // single infinite line
@@ -764,126 +777,245 @@ public class PolygonsSet extends 
AbstractRegion<Euclidean2D, Euclidean1D> {
 
     }
 
-    /** Follow a boundary loop.
-     * @param node node containing the segment starting the loop
-     * @param sorted set of segments belonging to the boundary, sorted by
-     * start points (contains {@code node})
-     * @return a list of connected sub-hyperplanes starting at
-     * {@code node}
+    /** Connect the segments using only natural follower information.
+     * @param segments segments complete segments list
+     * @return number of connections performed
      */
-    private List<ComparableSegment> followLoop(final 
AVLTree<ComparableSegment>.Node node,
-                                               final 
AVLTree<ComparableSegment> sorted) {
-
-        final ArrayList<ComparableSegment> loop = new 
ArrayList<ComparableSegment>();
-        ComparableSegment segment = node.getElement();
-        loop.add(segment);
-        final Vector2D globalStart = segment.getStart();
-        Vector2D end = segment.getEnd();
-        node.delete();
-
-        // is this an open or a closed loop ?
-        final boolean open = segment.getStart() == null;
-
-        while ((end != null) && (open || 
(globalStart.distance((Point<Euclidean2D>) end) > getTolerance()))) {
-
-            // search the sub-hyperplane starting where the previous one ended
-            AVLTree<ComparableSegment>.Node selectedNode = null;
-            ComparableSegment       selectedSegment  = null;
-            double                  selectedDistance = 
Double.POSITIVE_INFINITY;
-            final ComparableSegment lowerLeft        = new 
ComparableSegment(end, -1.0e-10, -1.0e-10);
-            final ComparableSegment upperRight       = new 
ComparableSegment(end, +1.0e-10, +1.0e-10);
-            for (AVLTree<ComparableSegment>.Node n = 
sorted.getNotSmaller(lowerLeft);
-                 (n != null) && (n.getElement().compareTo(upperRight) <= 0);
-                 n = n.getNext()) {
-                segment = n.getElement();
-                final double distance = end.distance((Point<Euclidean2D>) 
segment.getStart());
-                if (distance < selectedDistance) {
-                    selectedNode     = n;
-                    selectedSegment  = segment;
-                    selectedDistance = distance;
+    private int naturalFollowerConnections(final List<ConnectableSegment> 
segments) {
+        int connected = 0;
+        for (final ConnectableSegment segment : segments) {
+            if (segment.getNext() == null) {
+                final BSPTree<Euclidean2D> node = segment.getNode();
+                final BSPTree<Euclidean2D> end  = segment.getEndNode();
+                for (final ConnectableSegment candidateNext : segments) {
+                    if (candidateNext.getPrevious()  == null &&
+                        candidateNext.getNode()      == end &&
+                        candidateNext.getStartNode() == node) {
+                        // connect the two segments
+                        segment.setNext(candidateNext);
+                        candidateNext.setPrevious(segment);
+                        ++connected;
+                        break;
+                    }
                 }
             }
+        }
+        return connected;
+    }
 
-            if (selectedDistance > 1.0e-10) {
-                // this is a degenerated loop, it probably comes from a very
-                // tiny region with some segments smaller than the threshold, 
we
-                // simply ignore it
-                return null;
+    /** Connect the segments resulting from a line splitting a straight edge.
+     * @param segments segments complete segments list
+     * @return number of connections performed
+     */
+    private int splitEdgeConnections(final List<ConnectableSegment> segments) {
+        int connected = 0;
+        for (final ConnectableSegment segment : segments) {
+            if (segment.getNext() == null) {
+                final Hyperplane<Euclidean2D> hyperplane = 
segment.getNode().getCut().getHyperplane();
+                final BSPTree<Euclidean2D> end  = segment.getEndNode();
+                for (final ConnectableSegment candidateNext : segments) {
+                    if (candidateNext.getPrevious()                      == 
null &&
+                        candidateNext.getNode().getCut().getHyperplane() == 
hyperplane &&
+                        candidateNext.getStartNode()                     == 
end) {
+                        // connect the two segments
+                        segment.setNext(candidateNext);
+                        candidateNext.setPrevious(segment);
+                        ++connected;
+                        break;
+                    }
+                }
             }
+        }
+        return connected;
+    }
 
-            end = selectedSegment.getEnd();
-            loop.add(selectedSegment);
-            selectedNode.delete();
+    /** Connect the segments using Euclidean distance.
+     * <p>
+     * This connection heuristic should be used last, as it relies
+     * only on a fuzzy distance criterion.
+     * </p>
+     * @param segments segments complete segments list
+     * @return number of connections performed
+     */
+    private int closeVerticesConnections(final List<ConnectableSegment> 
segments) {
+        int connected = 0;
+        for (final ConnectableSegment segment : segments) {
+            if (segment.getNext() == null) {
+                final Vector2D end = segment.getEnd();
+                for (final ConnectableSegment candidateNext : segments) {
+                    if (candidateNext.getPrevious() == null &&
+                        Vector2D.distance(end, candidateNext.getStart()) <= 
getTolerance()) {
+                        // connect the two segments
+                        segment.setNext(candidateNext);
+                        candidateNext.setPrevious(segment);
+                        ++connected;
+                        break;
+                    }
+                }
+            }
+        }
+        return connected;
+    }
 
+    /** Get first unprocessed segment from a list.
+     * @param segments segments list
+     * @return first segment that has not been processed yet
+     * or null if all segments have been processed
+     */
+    private ConnectableSegment getUnprocessed(final List<ConnectableSegment> 
segments) {
+        for (final ConnectableSegment segment : segments) {
+            if (!segment.isProcessed()) {
+                return segment;
+            }
         }
+        return null;
+    }
 
-        if ((loop.size() == 2) && !open) {
-            // this is a degenerated infinitely thin loop, we simply ignore it
-            return null;
+    /** Build the loop containing a segment.
+     * <p>
+     * The segment put in the loop will be marked as processed.
+     * </p>
+     * @param defining segment used to define the loop
+     * @return loop containing the segment (may be null if the loop is a
+     * degenerated infinitely thin 2 points loop
+     */
+    private List<ConnectableSegment> followLoop(final ConnectableSegment 
defining) {
+
+        final List<ConnectableSegment> loop = new 
ArrayList<ConnectableSegment>();
+        loop.add(defining);
+        defining.setProcessed(true);
+
+        // add segments in connection order
+        ConnectableSegment next = defining.getNext();
+        while (next != defining && next != null) {
+            loop.add(next);
+            next.setProcessed(true);
+            next = next.getNext();
         }
 
-        if ((end == null) && !open) {
-            throw new MathInternalError();
+        if (next == null) {
+            // the loop is open and we have found its end,
+            // we need to find its start too
+            ConnectableSegment previous = defining.getPrevious();
+            while (previous != null) {
+                loop.add(0, previous);
+                previous.setProcessed(true);
+                previous = previous.getPrevious();
+            }
+        } else {
+            if (loop.size() == 2) {
+                // this is a degenerated infinitely thin loop, we simply 
ignore it
+                return null;
+            }
         }
 
         return loop;
 
     }
 
-    /** Private extension of Segment allowing comparison. */
-    private static class ComparableSegment extends Segment implements 
Comparable<ComparableSegment> {
+    /** Private extension of Segment allowing connection. */
+    private static class ConnectableSegment extends Segment {
+
+        /** Node containing segment. */
+        private final BSPTree<Euclidean2D> node;
 
-        /** Sorting key. */
-        private OrderedTuple sortingKey;
+        /** Node whose intersection with current node defines start point. */
+        private final BSPTree<Euclidean2D> startNode;
+
+        /** Node whose intersection with current node defines end point. */
+        private final BSPTree<Euclidean2D> endNode;
+
+        /** Previous segment. */
+        private ConnectableSegment previous;
+
+        /** Next segment. */
+        private ConnectableSegment next;
+
+        /** Indicator for completely processed segments. */
+        private boolean processed;
 
         /** Build a segment.
          * @param start start point of the segment
          * @param end end point of the segment
          * @param line line containing the segment
+         * @param node node containing the segment
+         * @param startNode node whose intersection with current node defines 
start point
+         * @param endNode node whose intersection with current node defines 
end point
          */
-        public ComparableSegment(final Vector2D start, final Vector2D end, 
final Line line) {
+        public ConnectableSegment(final Vector2D start, final Vector2D end, 
final Line line,
+                                  final BSPTree<Euclidean2D> node,
+                                  final BSPTree<Euclidean2D> startNode,
+                                  final BSPTree<Euclidean2D> endNode) {
             super(start, end, line);
-            sortingKey = (start == null) ?
-                         new OrderedTuple(Double.NEGATIVE_INFINITY, 
Double.NEGATIVE_INFINITY) :
-                         new OrderedTuple(start.getX(), start.getY());
+            this.node      = node;
+            this.startNode = startNode;
+            this.endNode   = endNode;
+            this.previous  = null;
+            this.next      = null;
+            this.processed = false;
         }
 
-        /** Build a dummy segment.
-         * <p>
-         * The object built is not a real segment, only the sorting key is 
used to
-         * allow searching in the neighborhood of a point. This is an horrible 
hack ...
-         * </p>
-         * @param start start point of the segment
-         * @param dx abscissa offset from the start point
-         * @param dy ordinate offset from the start point
+        /** Get the node containing segment.
+         * @return node containing segment
          */
-        public ComparableSegment(final Vector2D start, final double dx, final 
double dy) {
-            super(null, null, null);
-            sortingKey = new OrderedTuple(start.getX() + dx, start.getY() + 
dy);
+        public BSPTree<Euclidean2D> getNode() {
+            return node;
         }
 
-        /** {@inheritDoc} */
-        public int compareTo(final ComparableSegment o) {
-            return sortingKey.compareTo(o.sortingKey);
+        /** Get the node whose intersection with current node defines start 
point.
+         * @return node whose intersection with current node defines start 
point
+         */
+        public BSPTree<Euclidean2D> getStartNode() {
+            return startNode;
         }
 
-        /** {@inheritDoc} */
-        @Override
-        public boolean equals(final Object other) {
-            if (this == other) {
-                return true;
-            } else if (other instanceof ComparableSegment) {
-                return compareTo((ComparableSegment) other) == 0;
-            } else {
-                return false;
-            }
+        /** Get the node whose intersection with current node defines end 
point.
+         * @return node whose intersection with current node defines end point
+         */
+        public BSPTree<Euclidean2D> getEndNode() {
+            return endNode;
         }
 
-        /** {@inheritDoc} */
-        @Override
-        public int hashCode() {
-            return getStart().hashCode() ^ getEnd().hashCode() ^
-                   getLine().hashCode() ^ sortingKey.hashCode();
+        /** Get the previous segment.
+         * @return previous segment
+         */
+        public ConnectableSegment getPrevious() {
+            return previous;
+        }
+
+        /** Set the previous segment.
+         * @param previous previous segment
+         */
+        public void setPrevious(final ConnectableSegment previous) {
+            this.previous = previous;
+        }
+
+        /** Get the next segment.
+         * @return next segment
+         */
+        public ConnectableSegment getNext() {
+            return next;
+        }
+
+        /** Set the next segment.
+         * @param next previous segment
+         */
+        public void setNext(final ConnectableSegment next) {
+            this.next = next;
+        }
+
+        /** Set the processed flag.
+         * @param processed processed flag to set
+         */
+        public void setProcessed(final boolean processed) {
+            this.processed = processed;
+        }
+
+        /** Check if the segment has been processed.
+         * @return true if the segment has been processed
+         */
+        public boolean isProcessed() {
+            return processed;
         }
 
     }
@@ -891,12 +1023,18 @@ public class PolygonsSet extends 
AbstractRegion<Euclidean2D, Euclidean1D> {
     /** Visitor building segments. */
     private static class SegmentsBuilder implements 
BSPTreeVisitor<Euclidean2D> {
 
-        /** Sorted segments. */
-        private AVLTree<ComparableSegment> sorted;
+        /** Tolerance for close nodes connection. */
+        private final double tolerance;
 
-        /** Simple constructor. */
-        public SegmentsBuilder() {
-            sorted = new AVLTree<ComparableSegment>();
+        /** Built segments. */
+        private final List<ConnectableSegment> segments;
+
+        /** Simple constructor.
+         * @param tolerance tolerance for close nodes connection
+         */
+        public SegmentsBuilder(final double tolerance) {
+            this.tolerance = tolerance;
+            this.segments  = new ArrayList<ConnectableSegment>();
         }
 
         /** {@inheritDoc} */
@@ -908,11 +1046,12 @@ public class PolygonsSet extends 
AbstractRegion<Euclidean2D, Euclidean1D> {
         public void visitInternalNode(final BSPTree<Euclidean2D> node) {
             @SuppressWarnings("unchecked")
             final BoundaryAttribute<Euclidean2D> attribute = 
(BoundaryAttribute<Euclidean2D>) node.getAttribute();
+            final Iterable<BSPTree<Euclidean2D>> splitters = 
attribute.getSplitters();
             if (attribute.getPlusOutside() != null) {
-                addContribution(attribute.getPlusOutside(), false);
+                addContribution(attribute.getPlusOutside(), node, splitters, 
false);
             }
             if (attribute.getPlusInside() != null) {
-                addContribution(attribute.getPlusInside(), true);
+                addContribution(attribute.getPlusInside(), node, splitters, 
true);
             }
         }
 
@@ -922,32 +1061,69 @@ public class PolygonsSet extends 
AbstractRegion<Euclidean2D, Euclidean1D> {
 
         /** Add the contribution of a boundary facet.
          * @param sub boundary facet
+         * @param node node containing segment
+         * @param splitters splitters for the boundary facet
          * @param reversed if true, the facet has the inside on its plus side
          */
-        private void addContribution(final SubHyperplane<Euclidean2D> sub, 
final boolean reversed) {
+        private void addContribution(final SubHyperplane<Euclidean2D> sub,
+                                     final BSPTree<Euclidean2D> node,
+                                     final Iterable<BSPTree<Euclidean2D>> 
splitters,
+                                     final boolean reversed) {
             @SuppressWarnings("unchecked")
             final AbstractSubHyperplane<Euclidean2D, Euclidean1D> absSub =
                 (AbstractSubHyperplane<Euclidean2D, Euclidean1D>) sub;
             final Line line      = (Line) sub.getHyperplane();
             final List<Interval> intervals = ((IntervalsSet) 
absSub.getRemainingRegion()).asList();
             for (final Interval i : intervals) {
-                final Vector2D start = Double.isInfinite(i.getInf()) ?
-                                      null : (Vector2D) 
line.toSpace((Point<Euclidean1D>) new Vector1D(i.getInf()));
-                final Vector2D end   = Double.isInfinite(i.getSup()) ?
-                                      null : (Vector2D) 
line.toSpace((Point<Euclidean1D>) new Vector1D(i.getSup()));
+
+                // find the 2D points
+                final Vector2D startV = Double.isInfinite(i.getInf()) ?
+                                        null : (Vector2D) 
line.toSpace((Point<Euclidean1D>) new Vector1D(i.getInf()));
+                final Vector2D endV   = Double.isInfinite(i.getSup()) ?
+                                        null : (Vector2D) 
line.toSpace((Point<Euclidean1D>) new Vector1D(i.getSup()));
+
+                // recover the connectivity information
+                final BSPTree<Euclidean2D> startN = selectClosest(startV, 
splitters);
+                final BSPTree<Euclidean2D> endN   = selectClosest(endV, 
splitters);
+
                 if (reversed) {
-                    sorted.insert(new ComparableSegment(end, start, 
line.getReverse()));
+                    segments.add(new ConnectableSegment(endV, startV, 
line.getReverse(),
+                                                        node, endN, startN));
                 } else {
-                    sorted.insert(new ComparableSegment(start, end, line));
+                    segments.add(new ConnectableSegment(startV, endV, line,
+                                                        node, startN, endN));
+                }
+
+            }
+        }
+
+        /** Select the node whose cut sub-hyperplane is closest to specified 
point.
+         * @param point reference point
+         * @param candidates candidate nodes
+         * @return node closest to point, or null if no node is closer than 
tolerance
+         */
+        private BSPTree<Euclidean2D> selectClosest(final Vector2D point, final 
Iterable<BSPTree<Euclidean2D>> candidates) {
+
+            BSPTree<Euclidean2D> selected = null;
+            double min = Double.POSITIVE_INFINITY;
+
+            for (final BSPTree<Euclidean2D> node : candidates) {
+                final double distance = 
FastMath.abs(node.getCut().getHyperplane().getOffset(point));
+                if (distance < min) {
+                    selected = node;
+                    min      = distance;
                 }
             }
+
+            return min <= tolerance ? selected : null;
+
         }
 
-        /** Get the sorted segments.
-         * @return sorted segments
+        /** Get the segments.
+         * @return built segments
          */
-        public AVLTree<ComparableSegment> getSorted() {
-            return sorted;
+        public List<ConnectableSegment> getSegments() {
+            return segments;
         }
 
     }

http://git-wip-us.apache.org/repos/asf/commons-math/blob/e6aae3a8/src/test/java/org/apache/commons/math3/geometry/euclidean/twod/PolygonsSetTest.java
----------------------------------------------------------------------
diff --git 
a/src/test/java/org/apache/commons/math3/geometry/euclidean/twod/PolygonsSetTest.java
 
b/src/test/java/org/apache/commons/math3/geometry/euclidean/twod/PolygonsSetTest.java
index c6c68a0..52bbbca 100644
--- 
a/src/test/java/org/apache/commons/math3/geometry/euclidean/twod/PolygonsSetTest.java
+++ 
b/src/test/java/org/apache/commons/math3/geometry/euclidean/twod/PolygonsSetTest.java
@@ -850,34 +850,42 @@ public class PolygonsSetTest {
         Line[] l = {
             new Line(new Vector2D(0.0, 0.625000007541172),
                      new Vector2D(1.0, 0.625000007541172), 1.0e-10),
-                     new Line(new Vector2D(-0.19204433621902645, 0.0),
-                              new Vector2D(-0.19204433621902645, 1.0), 
1.0e-10),
-                              new Line(new Vector2D(-0.40303524786887,  
0.4248364535319128),
-                                       new Vector2D(-1.12851149797877, 
-0.2634107480798909), 1.0e-10),
-                                       new Line(new Vector2D(0.0, 2.0),
-                                                new Vector2D(1.0, 2.0), 
1.0e-10)
+            new Line(new Vector2D(-0.19204433621902645, 0.0),
+                     new Vector2D(-0.19204433621902645, 1.0), 1.0e-10),
+            new Line(new Vector2D(-0.40303524786887,  0.4248364535319128),
+                     new Vector2D(-1.12851149797877, -0.2634107480798909), 
1.0e-10),
+            new Line(new Vector2D(0.0, 2.0),
+                     new Vector2D(1.0, 2.0), 1.0e-10)
         };
 
         BSPTree<Euclidean2D> node1 =
             new BSPTree<Euclidean2D>(new SubLine(l[0],
-                                          new 
IntervalsSet(intersectionAbscissa(l[0], l[1]),
-                                                           
intersectionAbscissa(l[0], l[2]),
-                                                           1.0e-10)),
-                                                           new 
BSPTree<Euclidean2D>(Boolean.TRUE), new BSPTree<Euclidean2D>(Boolean.FALSE),
-                                                           null);
+                                                 new 
IntervalsSet(intersectionAbscissa(l[0], l[1]),
+                                                                  
intersectionAbscissa(l[0], l[2]),
+                                                                  1.0e-10)),
+                                     new BSPTree<Euclidean2D>(Boolean.TRUE),
+                                     new BSPTree<Euclidean2D>(Boolean.FALSE),
+                                     null);
         BSPTree<Euclidean2D> node2 =
             new BSPTree<Euclidean2D>(new SubLine(l[1],
-                                          new 
IntervalsSet(intersectionAbscissa(l[1], l[2]),
-                                                           
intersectionAbscissa(l[1], l[3]),
-                                                           1.0e-10)),
-                                                           node1, new 
BSPTree<Euclidean2D>(Boolean.FALSE), null);
+                                                 new 
IntervalsSet(intersectionAbscissa(l[1], l[2]),
+                                                                  
intersectionAbscissa(l[1], l[3]),
+                                                                  1.0e-10)),
+                                     node1,
+                                     new BSPTree<Euclidean2D>(Boolean.FALSE),
+                                     null);
         BSPTree<Euclidean2D> node3 =
             new BSPTree<Euclidean2D>(new SubLine(l[2],
-                                          new 
IntervalsSet(intersectionAbscissa(l[2], l[3]),
-                                                           
Double.POSITIVE_INFINITY, 1.0e-10)),
-                                                           node2, new 
BSPTree<Euclidean2D>(Boolean.FALSE), null);
+                                                 new 
IntervalsSet(intersectionAbscissa(l[2], l[3]),
+                                                 Double.POSITIVE_INFINITY, 
1.0e-10)),
+                                     node2,
+                                     new BSPTree<Euclidean2D>(Boolean.FALSE),
+                                     null);
         BSPTree<Euclidean2D> node4 =
-            new BSPTree<Euclidean2D>(l[3].wholeHyperplane(), node3, new 
BSPTree<Euclidean2D>(Boolean.FALSE), null);
+            new BSPTree<Euclidean2D>(l[3].wholeHyperplane(),
+                                     node3,
+                                     new BSPTree<Euclidean2D>(Boolean.FALSE),
+                                     null);
 
         PolygonsSet set = new PolygonsSet(node4, 1.0e-10);
         Assert.assertEquals(0, set.getVertices().length);
@@ -1062,9 +1070,9 @@ public class PolygonsSetTest {
                 RegionFactory<Euclidean2D>().difference(set1.copySelf(),
                                                         set2.copySelf());
 
-        Vector2D[][] verticies = set.getVertices();
-        Assert.assertTrue(verticies[0][0] != null);
-        Assert.assertEquals(1, verticies.length);
+        Vector2D[][] vertices = set.getVertices();
+        Assert.assertTrue(vertices[0][0] != null);
+        Assert.assertEquals(1, vertices.length);
     }
 
     @Test
@@ -1167,12 +1175,8 @@ public class PolygonsSetTest {
     private SubHyperplane<Euclidean2D> buildHalfLine(Vector2D start, Vector2D 
end,
                                                      boolean startIsVirtual) {
         Line   line  = new Line(start, end, 1.0e-10);
-        double lower = startIsVirtual
-        ? Double.NEGATIVE_INFINITY
-        : (line.toSubSpace(start)).getX();
-        double upper = startIsVirtual
-        ? (line.toSubSpace(end)).getX()
-        : Double.POSITIVE_INFINITY;
+        double lower = startIsVirtual ? Double.NEGATIVE_INFINITY : 
(line.toSubSpace(start)).getX();
+        double upper = startIsVirtual ? (line.toSubSpace(end)).getX() : 
Double.POSITIVE_INFINITY;
         return new SubLine(line, new IntervalsSet(lower, upper, 1.0e-10));
     }
 

Reply via email to