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 * http://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 package org.apache.commons.geometry.euclidean; 18 19 import org.apache.commons.geometry.core.partitioning.HyperplaneBoundedRegion; 20 import org.apache.commons.numbers.core.Precision; 21 22 /** Base class representing an axis-aligned bounding box with minimum and maximum bounding points. 23 * @param <P> Point implementation type 24 * @param <B> Bounds implementation type 25 */ 26 public abstract class AbstractBounds< 27 P extends EuclideanVector<P>, 28 B extends AbstractBounds<P, B>> { 29 30 /** Minimum point. */ 31 private final P min; 32 33 /** Maximum point. */ 34 private final P max; 35 36 /** Simple constructor. Callers are responsible for ensuring that all coordinate values are finite and 37 * that all values in {@code min} are less than or equal to their corresponding values in {@code max}. 38 * No validation is performed. 39 * @param min minimum point 40 * @param max maximum point 41 */ 42 protected AbstractBounds(final P min, final P max) { 43 this.min = min; 44 this.max = max; 45 } 46 47 /** Get the minimum point. 48 * @return the minimum point 49 */ 50 public P getMin() { 51 return min; 52 } 53 54 /** Get the maximum point. 55 * @return the maximum point 56 */ 57 public P getMax() { 58 return max; 59 } 60 61 /** Get the diagonal of the bounding box. The return value is a vector pointing from 62 * {@code min} to {@code max} and contains the size of the box along each coordinate axis. 63 * @return the diagonal vector of the bounding box 64 */ 65 public P getDiagonal() { 66 return min.vectorTo(max); 67 } 68 69 /** Get the centroid, or geometric center, of the bounding box. 70 * @return the centroid of the bounding box 71 */ 72 public P getCentroid() { 73 return min.lerp(max, 0.5); 74 } 75 76 /** Return true if the bounding box has non-zero size along each coordinate axis, as 77 * evaluated by the given precision context. 78 * @param precision precision context used for floating point comparisons 79 * @return true if the bounding box has non-zero size along each coordinate axis 80 */ 81 public abstract boolean hasSize(Precision.DoubleEquivalence precision); 82 83 /** Return true if the given point is strictly within or on the boundary of the bounding box. 84 * In other words, true if returned if <code>p<sub>t</sub> >= min<sub>t</sub></code> and 85 * <code>p<sub>t</sub> <= max<sub>t</sub></code> for each coordinate value <code>t</code>. 86 * Floating point comparisons are strict; values are considered equal only if they match exactly. 87 * @param pt the point to check 88 * @return true if the given point is strictly within or on the boundary of the instance 89 * @see #contains(EuclideanVector, Precision.DoubleEquivalence) 90 */ 91 public abstract boolean contains(P pt); 92 93 /** Return true if the given point is within or on the boundary of the bounding box, using the given 94 * precision context for floating point comparisons. This is similar to {@link #contains(EuclideanVector)} 95 * but allows points that may be strictly outside of the box due to floating point errors to be considered 96 * inside. 97 * @param pt the point to check 98 * @param precision precision context used to compare floating point values 99 * @return if the given point is within or on the boundary of the bounds, as determined 100 * by the given precision context 101 * @see #contains(EuclideanVector, Precision.DoubleEquivalence) 102 */ 103 public abstract boolean contains(P pt, Precision.DoubleEquivalence precision); 104 105 /** Return true if any point on the interior or boundary of this instance is also considered to be 106 * on the interior or boundary of the argument. Specifically, true is returned if 107 * <code>aMin<sub>t</sub> <= bMax<sub>t</sub></code> and <code>aMax<sub>t</sub> >= bMin<sub>t</sub></code> 108 * for all coordinate values {@code t}, where {@code a} is the current instance and {@code b} is the argument. 109 * Floating point comparisons are strict; values are considered equal only if they match exactly. 110 * @param other bounding box to intersect with 111 * @return true if the bounds intersect 112 */ 113 public abstract boolean intersects(B other); 114 115 /** Return the intersection of this bounding box and the argument, or null if no intersection exists. 116 * Floating point comparisons are strict; values are considered equal only if they match exactly. Note 117 * this this method may return bounding boxes with zero size in one or more coordinate axes. 118 * @param other bounding box to intersect with 119 * @return the intersection of this instance and the argument, or null if no such intersection 120 * exists 121 * @see #intersects(AbstractBounds) 122 */ 123 public abstract B intersection(B other); 124 125 /** Return a hyperplane-bounded region containing the same points as this instance. 126 * @param precision precision context used for floating point comparisons in the returned 127 * region instance 128 * @return a hyperplane-bounded region containing the same points as this instance 129 */ 130 public abstract HyperplaneBoundedRegion<P> toRegion(Precision.DoubleEquivalence precision); 131 132 /** Return true if the current instance and argument are considered equal as evaluated by the 133 * given precision context. Bounds are considered equal if they contain equivalent min and max 134 * points. 135 * @param other bounds to compare with 136 * @param precision precision context to compare floating point numbers 137 * @return true if this instance is equivalent to the argument, as evaluated by the given 138 * precision context 139 * @see EuclideanVector#eq(EuclideanVector, Precision.DoubleEquivalence) 140 */ 141 public boolean eq(final B other, final Precision.DoubleEquivalence precision) { 142 return min.eq(other.getMin(), precision) && 143 max.eq(other.getMax(), precision); 144 } 145 146 /** {@inheritDoc} */ 147 @Override 148 public String toString() { 149 final StringBuilder sb = new StringBuilder(); 150 sb.append(getClass().getSimpleName()) 151 .append("[min= ") 152 .append(min) 153 .append(", max= ") 154 .append(max) 155 .append(']'); 156 157 return sb.toString(); 158 } 159 }