1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * https://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 /* 19 * This is not the original file distributed by the Apache Software Foundation 20 * It has been modified by the Hipparchus project 21 */ 22 package org.hipparchus.geometry.euclidean.threed; 23 24 import java.util.ArrayList; 25 import java.util.List; 26 27 import org.hipparchus.exception.MathIllegalArgumentException; 28 import org.hipparchus.geometry.Point; 29 import org.hipparchus.geometry.euclidean.oned.Euclidean1D; 30 import org.hipparchus.geometry.euclidean.oned.Interval; 31 import org.hipparchus.geometry.euclidean.oned.IntervalsSet; 32 import org.hipparchus.geometry.euclidean.oned.Vector1D; 33 import org.hipparchus.geometry.partitioning.Region.Location; 34 35 /** This class represents a subset of a {@link Line}. 36 */ 37 public class SubLine { 38 39 /** Underlying line. */ 40 private final Line line; 41 42 /** Remaining region of the hyperplane. */ 43 private final IntervalsSet remainingRegion; 44 45 /** Simple constructor. 46 * @param line underlying line 47 * @param remainingRegion remaining region of the line 48 */ 49 public SubLine(final Line line, final IntervalsSet remainingRegion) { 50 this.line = line; 51 this.remainingRegion = remainingRegion; 52 } 53 54 /** Create a sub-line from two endpoints. 55 * @param start start point 56 * @param end end point 57 * @param tolerance tolerance below which points are considered identical 58 * @exception MathIllegalArgumentException if the points are equal 59 */ 60 public SubLine(final Vector3D start, final Vector3D end, final double tolerance) 61 throws MathIllegalArgumentException { 62 this(new Line(start, end, tolerance), buildIntervalSet(start, end, tolerance)); 63 } 64 65 /** Create a sub-line from a segment. 66 * @param segment single segment forming the sub-line 67 * @exception MathIllegalArgumentException if the segment endpoints are equal 68 */ 69 public SubLine(final Segment segment) throws MathIllegalArgumentException { 70 this(segment.getLine(), 71 buildIntervalSet(segment.getStart(), segment.getEnd(), segment.getLine().getTolerance())); 72 } 73 74 /** Get the endpoints of the sub-line. 75 * <p> 76 * A subline may be any arbitrary number of disjoints segments, so the endpoints 77 * are provided as a list of endpoint pairs. Each element of the list represents 78 * one segment, and each segment contains a start point at index 0 and an end point 79 * at index 1. If the sub-line is unbounded in the negative infinity direction, 80 * the start point of the first segment will have infinite coordinates. If the 81 * sub-line is unbounded in the positive infinity direction, the end point of the 82 * last segment will have infinite coordinates. So a sub-line covering the whole 83 * line will contain just one row and both elements of this row will have infinite 84 * coordinates. If the sub-line is empty, the returned list will contain 0 segments. 85 * </p> 86 * @return list of segments endpoints 87 */ 88 public List<Segment> getSegments() { 89 90 final List<Interval> list = remainingRegion.asList(); 91 final List<Segment> segments = new ArrayList<>(list.size()); 92 93 for (final Interval interval : list) { 94 final Vector3D start = line.toSpace((Point<Euclidean1D>) new Vector1D(interval.getInf())); 95 final Vector3D end = line.toSpace((Point<Euclidean1D>) new Vector1D(interval.getSup())); 96 segments.add(new Segment(start, end, line)); 97 } 98 99 return segments; 100 101 } 102 103 /** Get the intersection of the instance and another sub-line. 104 * <p> 105 * This method is related to the {@link Line#intersection(Line) 106 * intersection} method in the {@link Line Line} class, but in addition 107 * to compute the point along infinite lines, it also checks the point 108 * lies on both sub-line ranges. 109 * </p> 110 * @param subLine other sub-line which may intersect instance 111 * @param includeEndPoints if true, endpoints are considered to belong to 112 * instance (i.e. they are closed sets) and may be returned, otherwise endpoints 113 * are considered to not belong to instance (i.e. they are open sets) and intersection 114 * occurring on endpoints lead to null being returned 115 * @return the intersection point if there is one, null if the sub-lines don't intersect 116 */ 117 public Vector3D intersection(final SubLine subLine, final boolean includeEndPoints) { 118 119 // compute the intersection on infinite line 120 Vector3D v1D = line.intersection(subLine.line); 121 if (v1D == null) { 122 return null; 123 } 124 125 // check location of point with respect to first sub-line 126 Location loc1 = remainingRegion.checkPoint((Point<Euclidean1D>) line.toSubSpace((Point<Euclidean3D>) v1D)); 127 128 // check location of point with respect to second sub-line 129 Location loc2 = subLine.remainingRegion.checkPoint((Point<Euclidean1D>) subLine.line.toSubSpace((Point<Euclidean3D>) v1D)); 130 131 if (includeEndPoints) { 132 return ((loc1 != Location.OUTSIDE) && (loc2 != Location.OUTSIDE)) ? v1D : null; 133 } else { 134 return ((loc1 == Location.INSIDE) && (loc2 == Location.INSIDE)) ? v1D : null; 135 } 136 137 } 138 139 /** Build an interval set from two points. 140 * @param start start point 141 * @param end end point 142 * @return an interval set 143 * @param tolerance tolerance below which points are considered identical 144 * @exception MathIllegalArgumentException if the points are equal 145 */ 146 private static IntervalsSet buildIntervalSet(final Vector3D start, final Vector3D end, final double tolerance) 147 throws MathIllegalArgumentException { 148 final Line line = new Line(start, end, tolerance); 149 return new IntervalsSet(line.toSubSpace((Point<Euclidean3D>) start).getX(), 150 line.toSubSpace((Point<Euclidean3D>) end).getX(), 151 tolerance); 152 } 153 154 }