Added a 3D SubLine class.

JIRA: MATH-593

git-svn-id: https://svn.apache.org/repos/asf/commons/proper/math/trunk@1159353 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Luc Maisonobe 2011-08-18 18:50:08 +00:00
parent 290621a860
commit d7121b1c0b
8 changed files with 420 additions and 49 deletions

View File

@ -16,10 +16,11 @@
*/
package org.apache.commons.math.geometry.euclidean.threed;
import org.apache.commons.math.exception.MathArithmeticException;
import org.apache.commons.math.exception.MathIllegalArgumentException;
import org.apache.commons.math.exception.util.LocalizedFormats;
import org.apache.commons.math.geometry.Vector;
import org.apache.commons.math.geometry.euclidean.oned.Euclidean1D;
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.Embedding;
import org.apache.commons.math.util.FastMath;
@ -28,7 +29,7 @@ import org.apache.commons.math.util.MathUtils;
/** The class represent lines in a three dimensional space.
* <p>Each oriented line is intrinsically associated with an abscissa
* wich is a coordinate on the line. The point at abscissa 0 is the
* which is a coordinate on the line. The point at abscissa 0 is the
* orthogonal projection of the origin on the line, another equivalent
* way to express this is to say that it is the point of the line
* which is closest to the origin. Abscissa increases in the line
@ -45,13 +46,13 @@ public class Line implements Embedding<Euclidean3D, Euclidean1D> {
/** Line point closest to the origin. */
private Vector3D zero;
/** Build a line from a point and a direction.
* @param p point belonging to the line (this can be any point)
* @param direction direction of the line
* @exception MathArithmeticException if the direction norm is too small
/** Build a line from two points.
* @param p1 first point belonging to the line (this can be any point)
* @param p2 second point belonging to the line (this can be any point, different from p1)
* @exception MathIllegalArgumentException if the points are equal
*/
public Line(final Vector3D p, final Vector3D direction) {
reset(p, direction);
public Line(final Vector3D p1, final Vector3D p2) {
reset(p1, p2);
}
/** Copy constructor.
@ -64,25 +65,26 @@ public class Line implements Embedding<Euclidean3D, Euclidean1D> {
this.zero = line.zero;
}
/** Reset the instance as if built from a point and a normal.
* @param p point belonging to the line (this can be any point)
* @param dir direction of the line
* @exception MathArithmeticException if the direction norm is too small
/** Reset the instance as if built from two points.
* @param p1 first point belonging to the line (this can be any point)
* @param p2 second point belonging to the line (this can be any point, different from p1)
* @exception MathIllegalArgumentException if the points are equal
*/
public void reset(final Vector3D p, final Vector3D dir) {
final double norm = dir.getNorm();
if (norm == 0.0) {
throw new MathArithmeticException(LocalizedFormats.ZERO_NORM);
public void reset(final Vector3D p1, final Vector3D p2) {
final Vector3D delta = p2.subtract(p1);
final double norm2 = delta.getNormSq();
if (norm2 == 0.0) {
throw new MathIllegalArgumentException(LocalizedFormats.ZERO_NORM);
}
this.direction = new Vector3D(1.0 / norm, dir);
zero = new Vector3D(1.0, p, -p.dotProduct(this.direction), this.direction);
this.direction = new Vector3D(1.0 / FastMath.sqrt(norm2), delta);
zero = new Vector3D(1.0, p1, -p1.dotProduct(delta) / norm2, delta);
}
/** Get a line with reversed direction.
* @return a new instance, with reversed direction
*/
public Line revert() {
return new Line(zero, direction.negate());
return new Line(zero, zero.subtract(direction));
}
/** Get the normalized direction vector.
@ -213,4 +215,11 @@ public class Line implements Embedding<Euclidean3D, Euclidean1D> {
return line.contains(closest) ? closest : null;
}
/** Build a sub-line covering the whole line.
* @return a sub-line covering the whole line
*/
public SubLine wholeLine() {
return new SubLine(this, new IntervalsSet());
}
}

View File

@ -323,8 +323,8 @@ public class Plane implements Hyperplane<Euclidean3D>, Embedding<Euclidean3D, Eu
if (direction.getNorm() < 1.0e-10) {
return null;
}
return new Line(intersection(this, other, new Plane(direction)),
direction);
final Vector3D point = intersection(this, other, new Plane(direction));
return new Line(point, point.add(direction));
}
/** Get the intersection point of three planes.

View File

@ -0,0 +1,67 @@
/*
* 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.threed;
/** Simple container for a two-points segment.
* @version $Id$
* @since 3.0
*/
public class Segment {
/** Start point of the segment. */
private final Vector3D start;
/** End point of the segments. */
private final Vector3D end;
/** Line containing the segment. */
private final Line line;
/** Build a segment.
* @param start start point of the segment
* @param end end point of the segment
* @param line line containing the segment
*/
public Segment(final Vector3D start, final Vector3D end, final Line line) {
this.start = start;
this.end = end;
this.line = line;
}
/** Get the start point of the segment.
* @return start point of the segment
*/
public Vector3D getStart() {
return start;
}
/** Get the end point of the segment.
* @return end point of the segment
*/
public Vector3D getEnd() {
return end;
}
/** Get the line containing the segment.
* @return line containing the segment
*/
public Line getLine() {
return line;
}
}

View File

@ -0,0 +1,137 @@
/*
* 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.threed;
import java.util.ArrayList;
import java.util.List;
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.Hyperplane;
import org.apache.commons.math.geometry.partitioning.Region.Location;
/** This class represents a subset of a {@link Line}.
* @version $Id$
* @since 3.0
*/
public class SubLine {
/** Underlying line. */
private final Line line;
/** Remaining region of the hyperplane. */
private final IntervalsSet remainingRegion;
/** Simple constructor.
* @param line underlying line
* @param remainingRegion remaining region of the line
*/
public SubLine(final Line line, final IntervalsSet remainingRegion) {
this.line = line;
this.remainingRegion = remainingRegion;
}
/** Create a sub-line from two endpoints.
* @param start start point
* @param end end point
*/
public SubLine(final Vector3D start, final Vector3D end) {
this(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) {
this(segment.getLine(), buildIntervalSet(segment.getStart(), segment.getEnd()));
}
/** Get the endpoints of the sub-line.
* <p>
* A subline may be any arbitrary number of disjoints segments, so the endpoints
* are provided as a list of endpoint pairs. Each element of the list represents
* one segment, and each segment contains a start point at index 0 and an end point
* at index 1. If the sub-line is unbounded in the negative infinity direction,
* the start point of the first segment will have infinite coordinates. If the
* sub-line is unbounded in the positive infinity direction, the end point of the
* last segment will have infinite coordinates. So a sub-line covering the whole
* line will contain just one row and both elements of this row will have infinite
* coordinates. If the sub-line is empty, the returned list will contain 0 segments.
* </p>
* @return list of segments endpoints
*/
public List<Segment> getSegments() {
final List<Interval> list = remainingRegion.asList();
final List<Segment> segments = new ArrayList<Segment>();
for (final Interval interval : list) {
final Vector3D start = line.toSpace(new Vector1D(interval.getLower()));
final Vector3D end = line.toSpace(new Vector1D(interval.getUpper()));
segments.add(new Segment(start, end, line));
}
return segments;
}
/** Get the intersection of the instance and another sub-line.
* <p>
* This method is related to the {@link Line#intersection(Hyperplane)
* intersection} method in the {@link Line Line} class, but in addition
* to compute the point along infinite lines, it also checks the point
* lies on both sub-line ranges.
* </p>
* @param subLine other sub-line which may intersect instance
* @param includeEndPoints if true, endpoints are considered to belong to
* instance (i.e. they are closed sets) and may be returned, otherwise endpoints
* are considered to not belong to instance (i.e. they are open sets) and intersection
* occurring on endpoints lead to null being returned
* @return the intersection point if there is one, null if the sub-lines don't intersect
*/
public Vector3D intersection(final SubLine subLine, final boolean includeEndPoints) {
// compute the intersection on infinite line
Vector3D v1D = line.intersection(subLine.line);
// check location of point with respect to first sub-line
Location loc1 = remainingRegion.checkPoint(line.toSubSpace(v1D));
// check location of point with respect to second sub-line
Location loc2 = subLine.remainingRegion.checkPoint(subLine.line.toSubSpace(v1D));
if (includeEndPoints) {
return ((loc1 != Location.OUTSIDE) && (loc2 != Location.OUTSIDE)) ? v1D : null;
} else {
return ((loc1 == Location.INSIDE) && (loc2 == Location.INSIDE)) ? v1D : null;
}
}
/** Build an interval set from two points.
* @param start start point
* @param end end point
* @return an interval set
*/
private static IntervalsSet buildIntervalSet(final Vector3D start, final Vector3D end) {
final Line line = new Line(start, end);
return new IntervalsSet(line.toSubSpace(start).getX(),
line.toSubSpace(end).getX());
}
}

View File

@ -52,6 +52,9 @@ The <action> type attribute can be add,update,fix,remove.
If the output is not quite correct, check for invisible trailing spaces!
-->
<release version="3.0" date="TBD" description="TBD">
<action dev="luc" type="add" issue="MATH-593">
Added a 3D SubLine class.
</action>
<action dev="erans" type="fix" issue="MATH-645">
Fixed exceptions generated by "ebeMultiply" and "ebeDivide" in "OpenMapRealVector".
</action>

View File

@ -27,7 +27,7 @@ public class LineTest {
@Test
public void testContains() {
Vector3D p1 = new Vector3D(0, 0, 1);
Line l = new Line(p1, new Vector3D(0, 0, 1));
Line l = new Line(p1, new Vector3D(0, 0, 2));
Assert.assertTrue(l.contains(p1));
Assert.assertTrue(l.contains(new Vector3D(1.0, p1, 0.3, l.getDirection())));
Vector3D u = l.getDirection().orthogonal();
@ -42,89 +42,89 @@ public class LineTest {
public void testSimilar() {
Vector3D p1 = new Vector3D (1.2, 3.4, -5.8);
Vector3D p2 = new Vector3D (3.4, -5.8, 1.2);
Line lA = new Line(p1, p2.subtract(p1));
Line lB = new Line(p2, p1.subtract(p2));
Line lA = new Line(p1, p2);
Line lB = new Line(p2, p1);
Assert.assertTrue(lA.isSimilarTo(lB));
Assert.assertTrue(! lA.isSimilarTo(new Line(p1, lA.getDirection().orthogonal())));
Assert.assertTrue(! lA.isSimilarTo(new Line(p1, p1.add(lA.getDirection().orthogonal()))));
}
@Test
public void testPointDistance() {
Line l = new Line(new Vector3D(0, 1, 1), new Vector3D(0, 1, 1));
Line l = new Line(new Vector3D(0, 1, 1), new Vector3D(0, 2, 2));
Assert.assertEquals(FastMath.sqrt(3.0 / 2.0), l.distance(new Vector3D(1, 0, 1)), 1.0e-10);
Assert.assertEquals(0, l.distance(new Vector3D(0, -4, -4)), 1.0e-10);
}
@Test
public void testLineDistance() {
Line l = new Line(new Vector3D(0, 1, 1), new Vector3D(0, 1, 1));
Line l = new Line(new Vector3D(0, 1, 1), new Vector3D(0, 2, 2));
Assert.assertEquals(1.0,
l.distance(new Line(new Vector3D(1, 0, 1), Vector3D.PLUS_K)),
l.distance(new Line(new Vector3D(1, 0, 1), new Vector3D(1, 0, 2))),
1.0e-10);
Assert.assertEquals(0.5,
l.distance(new Line(new Vector3D(-0.5, 0, 0), new Vector3D(0, -1, -1))),
l.distance(new Line(new Vector3D(-0.5, 0, 0), new Vector3D(-0.5, -1, -1))),
1.0e-10);
Assert.assertEquals(0.0,
l.distance(l),
1.0e-10);
Assert.assertEquals(0.0,
l.distance(new Line(new Vector3D(0, -4, -4), new Vector3D(0, -1, -1))),
l.distance(new Line(new Vector3D(0, -4, -4), new Vector3D(0, -5, -5))),
1.0e-10);
Assert.assertEquals(0.0,
l.distance(new Line(new Vector3D(0, -4, -4), new Vector3D(0, 1, 0))),
l.distance(new Line(new Vector3D(0, -4, -4), new Vector3D(0, -3, -4))),
1.0e-10);
Assert.assertEquals(0.0,
l.distance(new Line(new Vector3D(0, -4, -4), new Vector3D(1, 0, 0))),
l.distance(new Line(new Vector3D(0, -4, -4), new Vector3D(1, -4, -4))),
1.0e-10);
Assert.assertEquals(FastMath.sqrt(8),
l.distance(new Line(new Vector3D(0, -4, 0), new Vector3D(1, 0, 0))),
l.distance(new Line(new Vector3D(0, -4, 0), new Vector3D(1, -4, 0))),
1.0e-10);
}
@Test
public void testClosest() {
Line l = new Line(new Vector3D(0, 1, 1), new Vector3D(0, 1, 1));
Line l = new Line(new Vector3D(0, 1, 1), new Vector3D(0, 2, 2));
Assert.assertEquals(0.0,
l.closestPoint(new Line(new Vector3D(1, 0, 1), Vector3D.PLUS_K)).distance(new Vector3D(0, 0, 0)),
l.closestPoint(new Line(new Vector3D(1, 0, 1), new Vector3D(1, 0, 2))).distance(new Vector3D(0, 0, 0)),
1.0e-10);
Assert.assertEquals(0.5,
l.closestPoint(new Line(new Vector3D(-0.5, 0, 0), new Vector3D(0, -1, -1))).distance(new Vector3D(-0.5, 0, 0)),
l.closestPoint(new Line(new Vector3D(-0.5, 0, 0), new Vector3D(-0.5, -1, -1))).distance(new Vector3D(-0.5, 0, 0)),
1.0e-10);
Assert.assertEquals(0.0,
l.closestPoint(l).distance(new Vector3D(0, 0, 0)),
1.0e-10);
Assert.assertEquals(0.0,
l.closestPoint(new Line(new Vector3D(0, -4, -4), new Vector3D(0, -1, -1))).distance(new Vector3D(0, 0, 0)),
l.closestPoint(new Line(new Vector3D(0, -4, -4), new Vector3D(0, -5, -5))).distance(new Vector3D(0, 0, 0)),
1.0e-10);
Assert.assertEquals(0.0,
l.closestPoint(new Line(new Vector3D(0, -4, -4), new Vector3D(0, 1, 0))).distance(new Vector3D(0, -4, -4)),
l.closestPoint(new Line(new Vector3D(0, -4, -4), new Vector3D(0, -3, -4))).distance(new Vector3D(0, -4, -4)),
1.0e-10);
Assert.assertEquals(0.0,
l.closestPoint(new Line(new Vector3D(0, -4, -4), new Vector3D(1, 0, 0))).distance(new Vector3D(0, -4, -4)),
l.closestPoint(new Line(new Vector3D(0, -4, -4), new Vector3D(1, -4, -4))).distance(new Vector3D(0, -4, -4)),
1.0e-10);
Assert.assertEquals(0.0,
l.closestPoint(new Line(new Vector3D(0, -4, 0), new Vector3D(1, 0, 0))).distance(new Vector3D(0, -2, -2)),
l.closestPoint(new Line(new Vector3D(0, -4, 0), new Vector3D(1, -4, 0))).distance(new Vector3D(0, -2, -2)),
1.0e-10);
}
@Test
public void testIntersection() {
Line l = new Line(new Vector3D(0, 1, 1), new Vector3D(0, 1, 1));
Assert.assertNull(l.intersection(new Line(new Vector3D(1, 0, 1), Vector3D.PLUS_K)));
Assert.assertNull(l.intersection(new Line(new Vector3D(-0.5, 0, 0), new Vector3D(0, -1, -1))));
Line l = new Line(new Vector3D(0, 1, 1), new Vector3D(0, 2, 2));
Assert.assertNull(l.intersection(new Line(new Vector3D(1, 0, 1), new Vector3D(1, 0, 2))));
Assert.assertNull(l.intersection(new Line(new Vector3D(-0.5, 0, 0), new Vector3D(-0.5, -1, -1))));
Assert.assertEquals(0.0,
l.intersection(l).distance(new Vector3D(0, 0, 0)),
1.0e-10);
Assert.assertEquals(0.0,
l.intersection(new Line(new Vector3D(0, -4, -4), new Vector3D(0, -1, -1))).distance(new Vector3D(0, 0, 0)),
l.intersection(new Line(new Vector3D(0, -4, -4), new Vector3D(0, -5, -5))).distance(new Vector3D(0, 0, 0)),
1.0e-10);
Assert.assertEquals(0.0,
l.intersection(new Line(new Vector3D(0, -4, -4), new Vector3D(0, 1, 0))).distance(new Vector3D(0, -4, -4)),
l.intersection(new Line(new Vector3D(0, -4, -4), new Vector3D(0, -3, -4))).distance(new Vector3D(0, -4, -4)),
1.0e-10);
Assert.assertEquals(0.0,
l.intersection(new Line(new Vector3D(0, -4, -4), new Vector3D(1, 0, 0))).distance(new Vector3D(0, -4, -4)),
l.intersection(new Line(new Vector3D(0, -4, -4), new Vector3D(1, -4, -4))).distance(new Vector3D(0, -4, -4)),
1.0e-10);
Assert.assertNull(l.intersection(new Line(new Vector3D(0, -4, 0), new Vector3D(1, 0, 0))));
Assert.assertNull(l.intersection(new Line(new Vector3D(0, -4, 0), new Vector3D(1, -4, 0))));
}
}

View File

@ -116,12 +116,12 @@ public class PlaneTest {
@Test
public void testIntersection() {
Plane p = new Plane(new Vector3D(1, 2, 3), new Vector3D(-4, 1, -5));
Line l = new Line(new Vector3D(0.2, -3.5, 0.7), new Vector3D(1, 1, -1));
Line l = new Line(new Vector3D(0.2, -3.5, 0.7), new Vector3D(1.2, -2.5, -0.3));
Vector3D point = p.intersection(l);
Assert.assertTrue(p.contains(point));
Assert.assertTrue(l.contains(point));
Assert.assertNull(p.intersection(new Line(new Vector3D(10, 10, 10),
p.getNormal().orthogonal())));
new Vector3D(10, 10, 10).add(p.getNormal().orthogonal()))));
}
@Test

View File

@ -0,0 +1,155 @@
/*
* 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.threed;
import java.util.List;
import org.apache.commons.math.geometry.euclidean.oned.Euclidean1D;
import org.apache.commons.math.geometry.euclidean.oned.IntervalsSet;
import org.apache.commons.math.geometry.partitioning.RegionFactory;
import org.junit.Assert;
import org.junit.Test;
public class SubLineTest {
@Test
public void testEndPoints() {
Vector3D p1 = new Vector3D(-1, -7, 2);
Vector3D p2 = new Vector3D(7, -1, 0);
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(0.0, new Vector3D(-1, -7, 2).distance(segments.get(0).getStart()), 1.0e-10);
Assert.assertEquals(0.0, new Vector3D( 7, -1, 0).distance(segments.get(0).getEnd()), 1.0e-10);
}
@Test
public void testNoEndPoints() {
SubLine wholeLine = new Line(new Vector3D(-1, 7, 2), new Vector3D(7, 1, 0)).wholeLine();
List<Segment> segments = wholeLine.getSegments();
Assert.assertEquals(1, segments.size());
Assert.assertTrue(Double.isInfinite(segments.get(0).getStart().getX()) &&
segments.get(0).getStart().getX() < 0);
Assert.assertTrue(Double.isInfinite(segments.get(0).getStart().getY()) &&
segments.get(0).getStart().getY() > 0);
Assert.assertTrue(Double.isInfinite(segments.get(0).getStart().getZ()) &&
segments.get(0).getStart().getZ() > 0);
Assert.assertTrue(Double.isInfinite(segments.get(0).getEnd().getX()) &&
segments.get(0).getEnd().getX() > 0);
Assert.assertTrue(Double.isInfinite(segments.get(0).getEnd().getY()) &&
segments.get(0).getEnd().getY() < 0);
Assert.assertTrue(Double.isInfinite(segments.get(0).getEnd().getZ()) &&
segments.get(0).getEnd().getZ() < 0);
}
@Test
public void testNoSegments() {
SubLine empty = new SubLine(new Line(new Vector3D(-1, -7, 2), new Vector3D(7, -1, 0)),
(IntervalsSet) new RegionFactory<Euclidean1D>().getComplement(new IntervalsSet()));
List<Segment> segments = empty.getSegments();
Assert.assertEquals(0, segments.size());
}
@Test
public void testSeveralSegments() {
SubLine twoSubs = new SubLine(new Line(new Vector3D(-1, -7, 2), new Vector3D(7, -1, 0)),
(IntervalsSet) new RegionFactory<Euclidean1D>().union(new IntervalsSet(1, 2),
new IntervalsSet(3, 4)));
List<Segment> segments = twoSubs.getSegments();
Assert.assertEquals(2, segments.size());
}
@Test
public void testHalfInfiniteNeg() {
SubLine empty = new SubLine(new Line(new Vector3D(-1, -7, 2), new Vector3D(7, -1, -2)),
new IntervalsSet(Double.NEGATIVE_INFINITY, 0.0));
List<Segment> segments = empty.getSegments();
Assert.assertEquals(1, segments.size());
Assert.assertTrue(Double.isInfinite(segments.get(0).getStart().getX()) &&
segments.get(0).getStart().getX() < 0);
Assert.assertTrue(Double.isInfinite(segments.get(0).getStart().getY()) &&
segments.get(0).getStart().getY() < 0);
Assert.assertTrue(Double.isInfinite(segments.get(0).getStart().getZ()) &&
segments.get(0).getStart().getZ() > 0);
Assert.assertEquals(0.0, new Vector3D(3, -4, 0).distance(segments.get(0).getEnd()), 1.0e-10);
}
@Test
public void testHalfInfinitePos() {
SubLine empty = new SubLine(new Line(new Vector3D(-1, -7, 2), new Vector3D(7, -1, -2)),
new IntervalsSet(0.0, Double.POSITIVE_INFINITY));
List<Segment> segments = empty.getSegments();
Assert.assertEquals(1, segments.size());
Assert.assertEquals(0.0, new Vector3D(3, -4, 0).distance(segments.get(0).getStart()), 1.0e-10);
Assert.assertTrue(Double.isInfinite(segments.get(0).getEnd().getX()) &&
segments.get(0).getEnd().getX() > 0);
Assert.assertTrue(Double.isInfinite(segments.get(0).getEnd().getY()) &&
segments.get(0).getEnd().getY() > 0);
Assert.assertTrue(Double.isInfinite(segments.get(0).getEnd().getZ()) &&
segments.get(0).getEnd().getZ() < 0);
}
@Test
public void testIntersectionInsideInside() {
SubLine sub1 = new SubLine(new Vector3D(1, 1, 1), new Vector3D(3, 1, 1));
SubLine sub2 = new SubLine(new Vector3D(2, 0, 0), new Vector3D(2, 2, 2));
Assert.assertEquals(0.0, new Vector3D(2, 1, 1).distance(sub1.intersection(sub2, true)), 1.0e-12);
Assert.assertEquals(0.0, new Vector3D(2, 1, 1).distance(sub1.intersection(sub2, false)), 1.0e-12);
}
@Test
public void testIntersectionInsideBoundary() {
SubLine sub1 = new SubLine(new Vector3D(1, 1, 1), new Vector3D(3, 1, 1));
SubLine sub2 = new SubLine(new Vector3D(2, 0, 0), new Vector3D(2, 1, 1));
Assert.assertEquals(0.0, new Vector3D(2, 1, 1).distance(sub1.intersection(sub2, true)), 1.0e-12);
Assert.assertNull(sub1.intersection(sub2, false));
}
@Test
public void testIntersectionInsideOutside() {
SubLine sub1 = new SubLine(new Vector3D(1, 1, 1), new Vector3D(3, 1, 1));
SubLine sub2 = new SubLine(new Vector3D(2, 0, 0), new Vector3D(2, 0.5, 0.5));
Assert.assertNull(sub1.intersection(sub2, true));
Assert.assertNull(sub1.intersection(sub2, false));
}
@Test
public void testIntersectionBoundaryBoundary() {
SubLine sub1 = new SubLine(new Vector3D(1, 1, 1), new Vector3D(2, 1, 1));
SubLine sub2 = new SubLine(new Vector3D(2, 0, 0), new Vector3D(2, 1, 1));
Assert.assertEquals(0.0, new Vector3D(2, 1, 1).distance(sub1.intersection(sub2, true)), 1.0e-12);
Assert.assertNull(sub1.intersection(sub2, false));
}
@Test
public void testIntersectionBoundaryOutside() {
SubLine sub1 = new SubLine(new Vector3D(1, 1, 1), new Vector3D(2, 1, 1));
SubLine sub2 = new SubLine(new Vector3D(2, 0, 0), new Vector3D(2, 0.5, 0.5));
Assert.assertNull(sub1.intersection(sub2, true));
Assert.assertNull(sub1.intersection(sub2, false));
}
@Test
public void testIntersectionOutsideOutside() {
SubLine sub1 = new SubLine(new Vector3D(1, 1, 1), new Vector3D(1.5, 1, 1));
SubLine sub2 = new SubLine(new Vector3D(2, 0, 0), new Vector3D(2, 0.5, 0.5));
Assert.assertNull(sub1.intersection(sub2, true));
Assert.assertNull(sub1.intersection(sub2, false));
}
}