/** Build a region covering the whole space. * @return a region containing the instance (really an {@link * IntervalsSet IntervalsSet} instance) */ public IntervalsSet wholeSpace() { return new IntervalsSet(tolerance); }
/** {@inheritDoc} */ @Override protected void computeGeometricalProperties() { if (getTree(false).getCut() == null) { setBarycenter((Point<Euclidean1D>) Vector1D.NaN); setSize(((Boolean) getTree(false).getAttribute()) ? Double.POSITIVE_INFINITY : 0); } else { double size = 0.0; double sum = 0.0; for (final Interval interval : asList()) { size += interval.getSize(); sum += interval.getSize() * interval.getBarycenter(); } setSize(size); if (Double.isInfinite(size)) { setBarycenter((Point<Euclidean1D>) Vector1D.NaN); } else if (size >= Precision.SAFE_MIN) { setBarycenter((Point<Euclidean1D>) new Vector1D(sum / size)); } else { setBarycenter((Point<Euclidean1D>) ((OrientedPoint) getTree(false).getCut().getHyperplane()).getLocation()); } } }
/** Build an intervals set corresponding to a single interval. * @param lower lower bound of the interval, must be lesser or equal * to {@code upper} (may be {@code Double.NEGATIVE_INFINITY}) * @param upper upper bound of the interval, must be greater or equal * to {@code lower} (may be {@code Double.POSITIVE_INFINITY}) * @param tolerance tolerance below which points are considered identical. * @since 3.3 */ public IntervalsSet(final double lower, final double upper, final double tolerance) { super(buildTree(lower, upper, tolerance), tolerance); }
/** {@inheritDoc} */ @Override public IntervalsSet buildNew(final BSPTree<Euclidean1D> tree) { return new IntervalsSet(tree, getTolerance()); }
/** Find the leaf node just after an internal node. * @param node internal node at which the sub-tree starts * @return leaf node just after the internal node */ private BSPTree<Euclidean1D> leafAfter(BSPTree<Euclidean1D> node) { node = childAfter(node); while (node.getCut() != null) { node = childBefore(node); } return node; }
/** Get the node corresponding to the first interval boundary. * @return smallest internal node, * or null if there are no internal nodes (i.e. the set is either empty or covers the real line) */ private BSPTree<Euclidean1D> getFirstIntervalBoundary() { // start search at the tree root BSPTree<Euclidean1D> node = getTree(false); if (node.getCut() == null) { return null; } // walk tree until we find the smallest internal node node = getFirstLeaf(node).getParent(); // walk tree until we find an interval boundary while (node != null && !(isIntervalStart(node) || isIntervalEnd(node))) { node = nextInternalNode(node); } return node; }
/** Get the next internal node. * @param node current internal node * @return next internal node in ascending order, or null * if this is the last internal node */ private BSPTree<Euclidean1D> nextInternalNode(BSPTree<Euclidean1D> node) { if (childAfter(node).getCut() != null) { // the next node is in the sub-tree return leafAfter(node).getParent(); } // there is nothing left deeper in the tree, we backtrack while (isAfterParent(node)) { node = node.getParent(); } return node.getParent(); }
/** Get the previous internal node. * @param node current internal node * @return previous internal node in ascending order, or null * if this is the first internal node */ private BSPTree<Euclidean1D> previousInternalNode(BSPTree<Euclidean1D> node) { if (childBefore(node).getCut() != null) { // the next node is in the sub-tree return leafBefore(node).getParent(); } // there is nothing left deeper in the tree, we backtrack while (isBeforeParent(node)) { node = node.getParent(); } return node.getParent(); }
/** Simple constructor. */ SubIntervalsIterator() { current = getFirstIntervalBoundary(); if (current == null) { // all the leaf tree nodes share the same inside/outside status if ((Boolean) getFirstLeaf(getTree(false)).getAttribute()) { // it is an inside node, it represents the full real line pending = new double[] { Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY }; } else { pending = null; } } else if (isIntervalEnd(current)) { // the first boundary is an interval end, // so the first interval starts at infinity pending = new double[] { Double.NEGATIVE_INFINITY, getAngle(current) }; } else { selectPending(); } }
/** 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>(list.size()); for (final Interval interval : list) { final Vector3D start = line.toSpace((Point<Euclidean1D>) new Vector1D(interval.getInf())); final Vector3D end = line.toSpace((Point<Euclidean1D>) new Vector1D(interval.getSup())); segments.add(new Segment(start, end, line)); } return segments; }
/** Check if a node is the child after its parent in ascending order. * @param node child node considered * @return true is the node has a parent end is after it in ascending order */ private boolean isAfterParent(final BSPTree<Euclidean1D> node) { final BSPTree<Euclidean1D> parent = node.getParent(); if (parent == null) { return false; } else { return node == childAfter(parent); } }
/** Check if a node is the child before its parent in ascending order. * @param node child node considered * @return true is the node has a parent end is before it in ascending order */ private boolean isBeforeParent(final BSPTree<Euclidean1D> node) { final BSPTree<Euclidean1D> parent = node.getParent(); if (parent == null) { return false; } else { return node == childBefore(parent); } }
/** Get the intersection of the instance and another sub-line. * <p> * This method is related to the {@link Line#intersection(Line) * 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); if (v1D == null) { return null; } // check location of point with respect to first sub-line Location loc1 = remainingRegion.checkPoint((Point<Euclidean1D>) line.toSubSpace((Point<Euclidean3D>) v1D)); // check location of point with respect to second sub-line Location loc2 = subLine.remainingRegion.checkPoint((Point<Euclidean1D>) subLine.line.toSubSpace((Point<Euclidean3D>) v1D)); if (includeEndPoints) { return ((loc1 != Location.OUTSIDE) && (loc2 != Location.OUTSIDE)) ? v1D : null; } else { return ((loc1 == Location.INSIDE) && (loc2 == Location.INSIDE)) ? v1D : null; } }
final double currentOffset = a[0] - x; if (previousOffset < currentOffset) { return new BoundaryProjection<Euclidean1D>(point, finiteOrNullPoint(previous), previousOffset); } else { return new BoundaryProjection<Euclidean1D>(point, finiteOrNullPoint(a[0]), currentOffset); final double offset1 = x - a[1]; if (offset0 < offset1) { return new BoundaryProjection<Euclidean1D>(point, finiteOrNullPoint(a[1]), offset1); } else { return new BoundaryProjection<Euclidean1D>(point, finiteOrNullPoint(a[0]), offset0); return new BoundaryProjection<Euclidean1D>(point, finiteOrNullPoint(previous), x - previous);
/** Get the node corresponding to the first interval boundary. * @return smallest internal node, * or null if there are no internal nodes (i.e. the set is either empty or covers the real line) */ private BSPTree<Euclidean1D> getFirstIntervalBoundary() { // start search at the tree root BSPTree<Euclidean1D> node = getTree(false); if (node.getCut() == null) { return null; } // walk tree until we find the smallest internal node node = getFirstLeaf(node).getParent(); // walk tree until we find an interval boundary while (node != null && !(isIntervalStart(node) || isIntervalEnd(node))) { node = nextInternalNode(node); } return node; }
/** Get the next internal node. * @param node current internal node * @return next internal node in ascending order, or null * if this is the last internal node */ private BSPTree<Euclidean1D> nextInternalNode(BSPTree<Euclidean1D> node) { if (childAfter(node).getCut() != null) { // the next node is in the sub-tree return leafAfter(node).getParent(); } // there is nothing left deeper in the tree, we backtrack while (isAfterParent(node)) { node = node.getParent(); } return node.getParent(); }
/** Get the previous internal node. * @param node current internal node * @return previous internal node in ascending order, or null * if this is the first internal node */ private BSPTree<Euclidean1D> previousInternalNode(BSPTree<Euclidean1D> node) { if (childBefore(node).getCut() != null) { // the next node is in the sub-tree return leafBefore(node).getParent(); } // there is nothing left deeper in the tree, we backtrack while (isBeforeParent(node)) { node = node.getParent(); } return node.getParent(); }
/** Find the leaf node just before an internal node. * @param node internal node at which the sub-tree starts * @return leaf node just before the internal node */ private BSPTree<Euclidean1D> leafBefore(BSPTree<Euclidean1D> node) { node = childBefore(node); while (node.getCut() != null) { node = childAfter(node); } return node; }
/** {@inheritDoc} */ @Override public IntervalsSet buildNew(final BSPTree<Euclidean1D> tree) { return new IntervalsSet(tree, getTolerance()); }
/** Get the lowest value belonging to the instance. * @return lowest value belonging to the instance * ({@code Double.NEGATIVE_INFINITY} if the instance doesn't * have any low bound, {@code Double.POSITIVE_INFINITY} if the * instance is empty) */ public double getInf() { BSPTree<Euclidean1D> node = getTree(false); double inf = Double.POSITIVE_INFINITY; while (node.getCut() != null) { final OrientedPoint op = (OrientedPoint) node.getCut().getHyperplane(); inf = op.getLocation().getX(); node = op.isDirect() ? node.getMinus() : node.getPlus(); } return ((Boolean) node.getAttribute()) ? Double.NEGATIVE_INFINITY : inf; }