Simplified SubLine API by introducing a public Segment class.
JIRA: MATH-592 git-svn-id: https://svn.apache.org/repos/asf/commons/proper/math/trunk@1137749 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
588f3b4c59
commit
f7ee41ad19
|
@ -22,11 +22,17 @@ import java.util.List;
|
||||||
|
|
||||||
import org.apache.commons.math.exception.MathInternalError;
|
import org.apache.commons.math.exception.MathInternalError;
|
||||||
import org.apache.commons.math.geometry.euclidean.oned.Euclidean1D;
|
import org.apache.commons.math.geometry.euclidean.oned.Euclidean1D;
|
||||||
|
import org.apache.commons.math.geometry.euclidean.oned.Interval;
|
||||||
|
import org.apache.commons.math.geometry.euclidean.oned.IntervalsSet;
|
||||||
import org.apache.commons.math.geometry.euclidean.oned.Vector1D;
|
import org.apache.commons.math.geometry.euclidean.oned.Vector1D;
|
||||||
|
import org.apache.commons.math.geometry.partitioning.AbstractSubHyperplane;
|
||||||
import org.apache.commons.math.geometry.partitioning.BSPTree;
|
import org.apache.commons.math.geometry.partitioning.BSPTree;
|
||||||
|
import org.apache.commons.math.geometry.partitioning.BSPTreeVisitor;
|
||||||
|
import org.apache.commons.math.geometry.partitioning.BoundaryAttribute;
|
||||||
import org.apache.commons.math.geometry.partitioning.SubHyperplane;
|
import org.apache.commons.math.geometry.partitioning.SubHyperplane;
|
||||||
import org.apache.commons.math.geometry.partitioning.AbstractRegion;
|
import org.apache.commons.math.geometry.partitioning.AbstractRegion;
|
||||||
import org.apache.commons.math.geometry.partitioning.utilities.AVLTree;
|
import org.apache.commons.math.geometry.partitioning.utilities.AVLTree;
|
||||||
|
import org.apache.commons.math.geometry.partitioning.utilities.OrderedTuple;
|
||||||
import org.apache.commons.math.util.FastMath;
|
import org.apache.commons.math.util.FastMath;
|
||||||
|
|
||||||
/** This class represents a 2D region: a set of polygons.
|
/** This class represents a 2D region: a set of polygons.
|
||||||
|
@ -202,14 +208,14 @@ public class PolygonsSet extends AbstractRegion<Euclidean2D, Euclidean1D> {
|
||||||
// sort the segments according to their start point
|
// sort the segments according to their start point
|
||||||
final SegmentsBuilder visitor = new SegmentsBuilder();
|
final SegmentsBuilder visitor = new SegmentsBuilder();
|
||||||
getTree(true).visit(visitor);
|
getTree(true).visit(visitor);
|
||||||
final AVLTree<Segment> sorted = visitor.getSorted();
|
final AVLTree<ComparableSegment> sorted = visitor.getSorted();
|
||||||
|
|
||||||
// identify the loops, starting from the open ones
|
// identify the loops, starting from the open ones
|
||||||
// (their start segments are naturally at the sorted set beginning)
|
// (their start segments are naturally at the sorted set beginning)
|
||||||
final ArrayList<List<Segment>> loops = new ArrayList<List<Segment>>();
|
final ArrayList<List<ComparableSegment>> loops = new ArrayList<List<ComparableSegment>>();
|
||||||
while (!sorted.isEmpty()) {
|
while (!sorted.isEmpty()) {
|
||||||
final AVLTree<Segment>.Node node = sorted.getSmallest();
|
final AVLTree<ComparableSegment>.Node node = sorted.getSmallest();
|
||||||
final List<Segment> loop = followLoop(node, sorted);
|
final List<ComparableSegment> loop = followLoop(node, sorted);
|
||||||
if (loop != null) {
|
if (loop != null) {
|
||||||
loops.add(loop);
|
loops.add(loop);
|
||||||
}
|
}
|
||||||
|
@ -219,7 +225,7 @@ public class PolygonsSet extends AbstractRegion<Euclidean2D, Euclidean1D> {
|
||||||
vertices = new Vector2D[loops.size()][];
|
vertices = new Vector2D[loops.size()][];
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
for (final List<Segment> loop : loops) {
|
for (final List<ComparableSegment> loop : loops) {
|
||||||
if (loop.size() < 2) {
|
if (loop.size() < 2) {
|
||||||
// single infinite line
|
// single infinite line
|
||||||
final Line line = loop.get(0).getLine();
|
final Line line = loop.get(0).getLine();
|
||||||
|
@ -280,11 +286,11 @@ public class PolygonsSet extends AbstractRegion<Euclidean2D, Euclidean1D> {
|
||||||
* @return a list of connected sub-hyperplanes starting at
|
* @return a list of connected sub-hyperplanes starting at
|
||||||
* {@code node}
|
* {@code node}
|
||||||
*/
|
*/
|
||||||
private List<Segment> followLoop(final AVLTree<Segment>.Node node,
|
private List<ComparableSegment> followLoop(final AVLTree<ComparableSegment>.Node node,
|
||||||
final AVLTree<Segment> sorted) {
|
final AVLTree<ComparableSegment> sorted) {
|
||||||
|
|
||||||
final ArrayList<Segment> loop = new ArrayList<Segment>();
|
final ArrayList<ComparableSegment> loop = new ArrayList<ComparableSegment>();
|
||||||
Segment segment = node.getElement();
|
ComparableSegment segment = node.getElement();
|
||||||
loop.add(segment);
|
loop.add(segment);
|
||||||
final Vector2D globalStart = segment.getStart();
|
final Vector2D globalStart = segment.getStart();
|
||||||
Vector2D end = segment.getEnd();
|
Vector2D end = segment.getEnd();
|
||||||
|
@ -296,15 +302,15 @@ public class PolygonsSet extends AbstractRegion<Euclidean2D, Euclidean1D> {
|
||||||
while ((end != null) && (open || (globalStart.distance(end) > 1.0e-10))) {
|
while ((end != null) && (open || (globalStart.distance(end) > 1.0e-10))) {
|
||||||
|
|
||||||
// search the sub-hyperplane starting where the previous one ended
|
// search the sub-hyperplane starting where the previous one ended
|
||||||
AVLTree<Segment>.Node selectedNode = null;
|
AVLTree<ComparableSegment>.Node selectedNode = null;
|
||||||
Segment selectedSegment = null;
|
ComparableSegment selectedSegment = null;
|
||||||
double selectedDistance = Double.POSITIVE_INFINITY;
|
double selectedDistance = Double.POSITIVE_INFINITY;
|
||||||
final Segment lowerLeft = new Segment(end, -1.0e-10, -1.0e-10);
|
final ComparableSegment lowerLeft = new ComparableSegment(end, -1.0e-10, -1.0e-10);
|
||||||
final Segment upperRight = new Segment(end, +1.0e-10, +1.0e-10);
|
final ComparableSegment upperRight = new ComparableSegment(end, +1.0e-10, +1.0e-10);
|
||||||
for (AVLTree<Segment>.Node n = sorted.getNotSmaller(lowerLeft);
|
for (AVLTree<ComparableSegment>.Node n = sorted.getNotSmaller(lowerLeft);
|
||||||
(n != null) && (n.getElement().compareTo(upperRight) <= 0);
|
(n != null) && (n.getElement().compareTo(upperRight) <= 0);
|
||||||
n = n.getNext()) {
|
n = n.getNext()) {
|
||||||
segment = (Segment) n.getElement();
|
segment = n.getElement();
|
||||||
final double distance = end.distance(segment.getStart());
|
final double distance = end.distance(segment.getStart());
|
||||||
if (distance < selectedDistance) {
|
if (distance < selectedDistance) {
|
||||||
selectedNode = n;
|
selectedNode = n;
|
||||||
|
@ -339,4 +345,125 @@ public class PolygonsSet extends AbstractRegion<Euclidean2D, Euclidean1D> {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class ComparableSegment extends Segment implements Comparable<ComparableSegment> {
|
||||||
|
|
||||||
|
/** Sorting key. */
|
||||||
|
private OrderedTuple sortingKey;
|
||||||
|
|
||||||
|
/** Build a segment.
|
||||||
|
* @param start start point of the segment
|
||||||
|
* @param end end point of the segment
|
||||||
|
* @param line line containing the segment
|
||||||
|
*/
|
||||||
|
public ComparableSegment(final Vector2D start, final Vector2D end, final Line line) {
|
||||||
|
super(start, end, line);
|
||||||
|
sortingKey = (start == null) ?
|
||||||
|
new OrderedTuple(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY) :
|
||||||
|
new OrderedTuple(start.getX(), start.getY());
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 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
|
||||||
|
*/
|
||||||
|
public ComparableSegment(final Vector2D start, final double dx, final double dy) {
|
||||||
|
super(null, null, null);
|
||||||
|
sortingKey = new OrderedTuple(start.getX() + dx, start.getY() + dy);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** {@inheritDoc} */
|
||||||
|
public int compareTo(final ComparableSegment o) {
|
||||||
|
return sortingKey.compareTo(o.sortingKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** {@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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** {@inheritDoc} */
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return getStart().hashCode() ^ getEnd().hashCode() ^
|
||||||
|
getLine().hashCode() ^ sortingKey.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Visitor building segments. */
|
||||||
|
private static class SegmentsBuilder implements BSPTreeVisitor<Euclidean2D> {
|
||||||
|
|
||||||
|
/** Sorted segments. */
|
||||||
|
private AVLTree<ComparableSegment> sorted;
|
||||||
|
|
||||||
|
/** Simple constructor. */
|
||||||
|
public SegmentsBuilder() {
|
||||||
|
sorted = new AVLTree<ComparableSegment>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** {@inheritDoc} */
|
||||||
|
public Order visitOrder(final BSPTree<Euclidean2D> node) {
|
||||||
|
return Order.MINUS_SUB_PLUS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** {@inheritDoc} */
|
||||||
|
public void visitInternalNode(final BSPTree<Euclidean2D> node) {
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
final BoundaryAttribute<Euclidean2D> attribute = (BoundaryAttribute<Euclidean2D>) node.getAttribute();
|
||||||
|
if (attribute.getPlusOutside() != null) {
|
||||||
|
addContribution(attribute.getPlusOutside(), false);
|
||||||
|
}
|
||||||
|
if (attribute.getPlusInside() != null) {
|
||||||
|
addContribution(attribute.getPlusInside(), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** {@inheritDoc} */
|
||||||
|
public void visitLeafNode(final BSPTree<Euclidean2D> node) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Add he contribution of a boundary facet.
|
||||||
|
* @param sub 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) {
|
||||||
|
@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.getLower()) ?
|
||||||
|
null : (Vector2D) line.toSpace(new Vector1D(i.getLower()));
|
||||||
|
final Vector2D end = Double.isInfinite(i.getUpper()) ?
|
||||||
|
null : (Vector2D) line.toSpace(new Vector1D(i.getUpper()));
|
||||||
|
if (reversed) {
|
||||||
|
sorted.insert(new ComparableSegment(end, start, line.getReverse()));
|
||||||
|
} else {
|
||||||
|
sorted.insert(new ComparableSegment(start, end, line));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Get the sorted segments.
|
||||||
|
* @return sorted segments
|
||||||
|
*/
|
||||||
|
public AVLTree<ComparableSegment> getSorted() {
|
||||||
|
return sorted;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,25 +16,21 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.commons.math.geometry.euclidean.twod;
|
package org.apache.commons.math.geometry.euclidean.twod;
|
||||||
|
|
||||||
import org.apache.commons.math.geometry.partitioning.utilities.OrderedTuple;
|
|
||||||
|
|
||||||
/** This class holds segments information before they are connected.
|
/** Simple container for a two-points segment.
|
||||||
* @version $Id$
|
* @version $Id$
|
||||||
* @since 3.0
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
class Segment implements Comparable<Segment> {
|
public class Segment {
|
||||||
|
|
||||||
/** Start point of the segment. */
|
/** Start point of the segment. */
|
||||||
private final Vector2D start;
|
private final Vector2D start;
|
||||||
|
|
||||||
/** End point of the segments. */
|
/** End point of the segments. */
|
||||||
private final Vector2D end;
|
private final Vector2D end;
|
||||||
|
|
||||||
/** Line containing the segment. */
|
/** Line containing the segment. */
|
||||||
private final Line line;
|
private final Line line;
|
||||||
|
|
||||||
/** Sorting key. */
|
|
||||||
private OrderedTuple sortingKey;
|
|
||||||
|
|
||||||
/** Build a segment.
|
/** Build a segment.
|
||||||
* @param start start point of the segment
|
* @param start start point of the segment
|
||||||
|
@ -45,25 +41,6 @@ class Segment implements Comparable<Segment> {
|
||||||
this.start = start;
|
this.start = start;
|
||||||
this.end = end;
|
this.end = end;
|
||||||
this.line = line;
|
this.line = line;
|
||||||
sortingKey = (start == null) ?
|
|
||||||
new OrderedTuple(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY) :
|
|
||||||
new OrderedTuple(start.getX(), start.getY());
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 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
|
|
||||||
*/
|
|
||||||
public Segment(final Vector2D start, final double dx, final double dy) {
|
|
||||||
this.start = null;
|
|
||||||
this.end = null;
|
|
||||||
this.line = null;
|
|
||||||
sortingKey = new OrderedTuple(start.getX() + dx, start.getY() + dy);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Get the start point of the segment.
|
/** Get the start point of the segment.
|
||||||
|
@ -87,27 +64,4 @@ class Segment implements Comparable<Segment> {
|
||||||
return line;
|
return line;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
public int compareTo(final Segment o) {
|
|
||||||
return sortingKey.compareTo(o.sortingKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
@Override
|
|
||||||
public boolean equals(final Object other) {
|
|
||||||
if (this == other) {
|
|
||||||
return true;
|
|
||||||
} else if (other instanceof Segment) {
|
|
||||||
return compareTo((Segment) other) == 0;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return start.hashCode() ^ end.hashCode() ^ line.hashCode() ^ sortingKey.hashCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,97 +0,0 @@
|
||||||
/*
|
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
||||||
* contributor license agreements. See the NOTICE file distributed with
|
|
||||||
* this work for additional information regarding copyright ownership.
|
|
||||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
|
||||||
* (the "License"); you may not use this file except in compliance with
|
|
||||||
* the License. You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package org.apache.commons.math.geometry.euclidean.twod;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.apache.commons.math.geometry.euclidean.oned.Euclidean1D;
|
|
||||||
import org.apache.commons.math.geometry.euclidean.oned.Interval;
|
|
||||||
import org.apache.commons.math.geometry.euclidean.oned.IntervalsSet;
|
|
||||||
import org.apache.commons.math.geometry.euclidean.oned.Vector1D;
|
|
||||||
import org.apache.commons.math.geometry.partitioning.AbstractSubHyperplane;
|
|
||||||
import org.apache.commons.math.geometry.partitioning.BSPTree;
|
|
||||||
import org.apache.commons.math.geometry.partitioning.BSPTreeVisitor;
|
|
||||||
import org.apache.commons.math.geometry.partitioning.BoundaryAttribute;
|
|
||||||
import org.apache.commons.math.geometry.partitioning.SubHyperplane;
|
|
||||||
import org.apache.commons.math.geometry.partitioning.utilities.AVLTree;
|
|
||||||
|
|
||||||
/** Visitor building segments.
|
|
||||||
* @version $Id$
|
|
||||||
* @since 3.0
|
|
||||||
*/
|
|
||||||
class SegmentsBuilder implements BSPTreeVisitor<Euclidean2D> {
|
|
||||||
|
|
||||||
/** Sorted segments. */
|
|
||||||
private AVLTree<Segment> sorted;
|
|
||||||
|
|
||||||
/** Simple constructor. */
|
|
||||||
public SegmentsBuilder() {
|
|
||||||
sorted = new AVLTree<Segment>();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
public Order visitOrder(final BSPTree<Euclidean2D> node) {
|
|
||||||
return Order.MINUS_SUB_PLUS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
public void visitInternalNode(final BSPTree<Euclidean2D> node) {
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
final BoundaryAttribute<Euclidean2D> attribute = (BoundaryAttribute<Euclidean2D>) node.getAttribute();
|
|
||||||
if (attribute.getPlusOutside() != null) {
|
|
||||||
addContribution(attribute.getPlusOutside(), false);
|
|
||||||
}
|
|
||||||
if (attribute.getPlusInside() != null) {
|
|
||||||
addContribution(attribute.getPlusInside(), true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
public void visitLeafNode(final BSPTree<Euclidean2D> node) {
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Add he contribution of a boundary facet.
|
|
||||||
* @param sub 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) {
|
|
||||||
@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.getLower()) ?
|
|
||||||
null : (Vector2D) line.toSpace(new Vector1D(i.getLower()));
|
|
||||||
final Vector2D end = Double.isInfinite(i.getUpper()) ?
|
|
||||||
null : (Vector2D) line.toSpace(new Vector1D(i.getUpper()));
|
|
||||||
if (reversed) {
|
|
||||||
sorted.insert(new Segment(end, start, line.getReverse()));
|
|
||||||
} else {
|
|
||||||
sorted.insert(new Segment(start, end, line));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get the sorted segments.
|
|
||||||
* @return sorted segments
|
|
||||||
*/
|
|
||||||
public AVLTree<Segment> getSorted() {
|
|
||||||
return sorted;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -56,6 +56,13 @@ public class SubLine extends AbstractSubHyperplane<Euclidean2D, Euclidean1D> {
|
||||||
super(new Line(start, end), buildIntervalSet(start, end));
|
super(new Line(start, end), buildIntervalSet(start, end));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Create a sub-line from a segment.
|
||||||
|
* @param segment single segment forming the sub-line
|
||||||
|
*/
|
||||||
|
public SubLine(final Segment segment) {
|
||||||
|
super(segment.getLine(), buildIntervalSet(segment.getStart(), segment.getEnd()));
|
||||||
|
}
|
||||||
|
|
||||||
/** Get the endpoints of the sub-line.
|
/** Get the endpoints of the sub-line.
|
||||||
* <p>
|
* <p>
|
||||||
* A subline may be any arbitrary number of disjoints segments, so the endpoints
|
* A subline may be any arbitrary number of disjoints segments, so the endpoints
|
||||||
|
@ -70,16 +77,16 @@ public class SubLine extends AbstractSubHyperplane<Euclidean2D, Euclidean1D> {
|
||||||
* </p>
|
* </p>
|
||||||
* @return list of segments endpoints
|
* @return list of segments endpoints
|
||||||
*/
|
*/
|
||||||
public List<Vector2D[]> getSegments() {
|
public List<Segment> getSegments() {
|
||||||
|
|
||||||
final Line line = (Line) getHyperplane();
|
final Line line = (Line) getHyperplane();
|
||||||
final List<Interval> list = ((IntervalsSet) getRemainingRegion()).asList();
|
final List<Interval> list = ((IntervalsSet) getRemainingRegion()).asList();
|
||||||
final List<Vector2D[]> segments = new ArrayList<Vector2D[]>();
|
final List<Segment> segments = new ArrayList<Segment>();
|
||||||
|
|
||||||
for (final Interval interval : list) {
|
for (final Interval interval : list) {
|
||||||
final Vector2D start = line.toSpace(new Vector1D(interval.getLower()));
|
final Vector2D start = line.toSpace(new Vector1D(interval.getLower()));
|
||||||
final Vector2D end = line.toSpace(new Vector1D(interval.getUpper()));
|
final Vector2D end = line.toSpace(new Vector1D(interval.getUpper()));
|
||||||
segments.add(new Vector2D[] { start, end });
|
segments.add(new Segment(start, end, line));
|
||||||
}
|
}
|
||||||
|
|
||||||
return segments;
|
return segments;
|
||||||
|
|
|
@ -28,35 +28,36 @@ public class SubLineTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEndPoints() {
|
public void testEndPoints() {
|
||||||
SubLine sub = new SubLine(new Vector2D(-1, -7), new Vector2D(7, -1));
|
Vector2D p1 = new Vector2D(-1, -7);
|
||||||
List<Vector2D[]> segments = sub.getSegments();
|
Vector2D p2 = new Vector2D(7, -1);
|
||||||
|
Segment segment = new Segment(p1, p2, new Line(p1, p2));
|
||||||
|
SubLine sub = new SubLine(segment);
|
||||||
|
List<Segment> segments = sub.getSegments();
|
||||||
Assert.assertEquals(1, segments.size());
|
Assert.assertEquals(1, segments.size());
|
||||||
Assert.assertEquals(-1, segments.get(0)[0].getX(), 1.0e-10);
|
Assert.assertEquals(0.0, new Vector2D(-1, -7).distance(segments.get(0).getStart()), 1.0e-10);
|
||||||
Assert.assertEquals(-7, segments.get(0)[0].getY(), 1.0e-10);
|
Assert.assertEquals(0.0, new Vector2D( 7, -1).distance(segments.get(0).getEnd()), 1.0e-10);
|
||||||
Assert.assertEquals( 7, segments.get(0)[1].getX(), 1.0e-10);
|
|
||||||
Assert.assertEquals(-1, segments.get(0)[1].getY(), 1.0e-10);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testNoEndPoints() {
|
public void testNoEndPoints() {
|
||||||
SubLine wholeLine = new Line(new Vector2D(-1, 7), new Vector2D(7, 1)).wholeHyperplane();
|
SubLine wholeLine = new Line(new Vector2D(-1, 7), new Vector2D(7, 1)).wholeHyperplane();
|
||||||
List<Vector2D[]> segments = wholeLine.getSegments();
|
List<Segment> segments = wholeLine.getSegments();
|
||||||
Assert.assertEquals(1, segments.size());
|
Assert.assertEquals(1, segments.size());
|
||||||
Assert.assertTrue(Double.isInfinite(segments.get(0)[0].getX()) &&
|
Assert.assertTrue(Double.isInfinite(segments.get(0).getStart().getX()) &&
|
||||||
segments.get(0)[0].getX() < 0);
|
segments.get(0).getStart().getX() < 0);
|
||||||
Assert.assertTrue(Double.isInfinite(segments.get(0)[0].getY()) &&
|
Assert.assertTrue(Double.isInfinite(segments.get(0).getStart().getY()) &&
|
||||||
segments.get(0)[0].getY() > 0);
|
segments.get(0).getStart().getY() > 0);
|
||||||
Assert.assertTrue(Double.isInfinite(segments.get(0)[1].getX()) &&
|
Assert.assertTrue(Double.isInfinite(segments.get(0).getEnd().getX()) &&
|
||||||
segments.get(0)[1].getX() > 0);
|
segments.get(0).getEnd().getX() > 0);
|
||||||
Assert.assertTrue(Double.isInfinite(segments.get(0)[1].getY()) &&
|
Assert.assertTrue(Double.isInfinite(segments.get(0).getEnd().getY()) &&
|
||||||
segments.get(0)[1].getY() < 0);
|
segments.get(0).getEnd().getY() < 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testNoSegments() {
|
public void testNoSegments() {
|
||||||
SubLine empty = new SubLine(new Line(new Vector2D(-1, -7), new Vector2D(7, -1)),
|
SubLine empty = new SubLine(new Line(new Vector2D(-1, -7), new Vector2D(7, -1)),
|
||||||
new RegionFactory<Euclidean1D>().getComplement(new IntervalsSet()));
|
new RegionFactory<Euclidean1D>().getComplement(new IntervalsSet()));
|
||||||
List<Vector2D[]> segments = empty.getSegments();
|
List<Segment> segments = empty.getSegments();
|
||||||
Assert.assertEquals(0, segments.size());
|
Assert.assertEquals(0, segments.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,7 +66,7 @@ public class SubLineTest {
|
||||||
SubLine twoSubs = new SubLine(new Line(new Vector2D(-1, -7), new Vector2D(7, -1)),
|
SubLine twoSubs = new SubLine(new Line(new Vector2D(-1, -7), new Vector2D(7, -1)),
|
||||||
new RegionFactory<Euclidean1D>().union(new IntervalsSet(1, 2),
|
new RegionFactory<Euclidean1D>().union(new IntervalsSet(1, 2),
|
||||||
new IntervalsSet(3, 4)));
|
new IntervalsSet(3, 4)));
|
||||||
List<Vector2D[]> segments = twoSubs.getSegments();
|
List<Segment> segments = twoSubs.getSegments();
|
||||||
Assert.assertEquals(2, segments.size());
|
Assert.assertEquals(2, segments.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,28 +74,26 @@ public class SubLineTest {
|
||||||
public void testHalfInfiniteNeg() {
|
public void testHalfInfiniteNeg() {
|
||||||
SubLine empty = new SubLine(new Line(new Vector2D(-1, -7), new Vector2D(7, -1)),
|
SubLine empty = new SubLine(new Line(new Vector2D(-1, -7), new Vector2D(7, -1)),
|
||||||
new IntervalsSet(Double.NEGATIVE_INFINITY, 0.0));
|
new IntervalsSet(Double.NEGATIVE_INFINITY, 0.0));
|
||||||
List<Vector2D[]> segments = empty.getSegments();
|
List<Segment> segments = empty.getSegments();
|
||||||
Assert.assertEquals(1, segments.size());
|
Assert.assertEquals(1, segments.size());
|
||||||
Assert.assertTrue(Double.isInfinite(segments.get(0)[0].getX()) &&
|
Assert.assertTrue(Double.isInfinite(segments.get(0).getStart().getX()) &&
|
||||||
segments.get(0)[0].getX() < 0);
|
segments.get(0).getStart().getX() < 0);
|
||||||
Assert.assertTrue(Double.isInfinite(segments.get(0)[0].getY()) &&
|
Assert.assertTrue(Double.isInfinite(segments.get(0).getStart().getY()) &&
|
||||||
segments.get(0)[0].getY() < 0);
|
segments.get(0).getStart().getY() < 0);
|
||||||
Assert.assertEquals( 3, segments.get(0)[1].getX(), 1.0e-10);
|
Assert.assertEquals(0.0, new Vector2D(3, -4).distance(segments.get(0).getEnd()), 1.0e-10);
|
||||||
Assert.assertEquals(-4, segments.get(0)[1].getY(), 1.0e-10);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testHalfInfinitePos() {
|
public void testHalfInfinitePos() {
|
||||||
SubLine empty = new SubLine(new Line(new Vector2D(-1, -7), new Vector2D(7, -1)),
|
SubLine empty = new SubLine(new Line(new Vector2D(-1, -7), new Vector2D(7, -1)),
|
||||||
new IntervalsSet(0.0, Double.POSITIVE_INFINITY));
|
new IntervalsSet(0.0, Double.POSITIVE_INFINITY));
|
||||||
List<Vector2D[]> segments = empty.getSegments();
|
List<Segment> segments = empty.getSegments();
|
||||||
Assert.assertEquals(1, segments.size());
|
Assert.assertEquals(1, segments.size());
|
||||||
Assert.assertEquals( 3, segments.get(0)[0].getX(), 1.0e-10);
|
Assert.assertEquals(0.0, new Vector2D(3, -4).distance(segments.get(0).getStart()), 1.0e-10);
|
||||||
Assert.assertEquals(-4, segments.get(0)[0].getY(), 1.0e-10);
|
Assert.assertTrue(Double.isInfinite(segments.get(0).getEnd().getX()) &&
|
||||||
Assert.assertTrue(Double.isInfinite(segments.get(0)[1].getX()) &&
|
segments.get(0).getEnd().getX() > 0);
|
||||||
segments.get(0)[1].getX() > 0);
|
Assert.assertTrue(Double.isInfinite(segments.get(0).getEnd().getY()) &&
|
||||||
Assert.assertTrue(Double.isInfinite(segments.get(0)[1].getY()) &&
|
segments.get(0).getEnd().getY() > 0);
|
||||||
segments.get(0)[1].getY() > 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
Loading…
Reference in New Issue