001    //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.3_testing/src/org/deegree/io/rtree/HyperBoundingBox.java $
002    //----------------------------------------
003    //RTree implementation.
004    //Copyright (C) 2002-2004 Wolfgang Baer - WBaer@gmx.de
005    //
006    //This library is free software; you can redistribute it and/or
007    //modify it under the terms of the GNU Lesser General Public
008    //License as published by the Free Software Foundation; either
009    //version 2.1 of the License, or (at your option) any later version.
010    //
011    //This library is distributed in the hope that it will be useful,
012    //but WITHOUT ANY WARRANTY; without even the implied warranty of
013    //MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014    //Lesser General Public License for more details.
015    //
016    //You should have received a copy of the GNU Lesser General Public
017    //License along with this library; if not, write to the Free Software
018    //Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
019    //----------------------------------------
020    
021    package org.deegree.io.rtree;
022    
023    import java.io.Serializable;
024    
025    /**
026     * <p>
027     * HyperBoundingBox implementing a bounding box object in the multidimensional space.
028     * </p>
029     *
030     * @author Wolfgang Baer - WBaer@gmx.de
031     */
032    
033    public class HyperBoundingBox implements Serializable {
034    
035        private HyperPoint pMin;
036    
037        private HyperPoint pMax;
038    
039        /**
040         * Constructor.<br>
041         * Creates a HyperBoundingBox for given HyperPoints.
042         *
043         * @param pMin -
044         *            min point
045         * @param pMax -
046         *            max point
047         */
048        public HyperBoundingBox( HyperPoint pMin, HyperPoint pMax ) {
049            if ( pMin.getDimension() != pMax.getDimension() )
050                throw new IllegalArgumentException( "HyperPoints need same dimension: " + pMin.getDimension() + " != "
051                                                    + pMax.getDimension() );
052    
053            this.pMin = pMin;
054            this.pMax = pMax;
055        }
056    
057        /**
058         * Creates a null HyperBoundingBox with null HyperPoints. Mostly used internal.
059         *
060         * @param dimension -
061         *            int for dimension of point
062         * @return HyperBoundingBox
063         */
064        protected static HyperBoundingBox getNullHyperBoundingBox( int dimension ) {
065            return new HyperBoundingBox( HyperPoint.getNullHyperPoint( dimension ),
066                                         HyperPoint.getNullHyperPoint( dimension ) );
067        }
068    
069        /**
070         * Returns the minimum HyperPoint
071         *
072         * @return HyperPoint
073         *
074         */
075        public HyperPoint getPMin() {
076            return pMin;
077        }
078    
079        /**
080         * Returns the maximum HyperPoint
081         *
082         * @return HyperPoint
083         *
084         */
085        public HyperPoint getPMax() {
086            return pMax;
087        }
088    
089        /**
090         * Returns the dimension of this HyperBoundingBox.
091         *
092         * @return int
093         */
094        public int getDimension() {
095            return pMin.getDimension();
096        }
097    
098        /**
099         * Tests if this and the given HyperBoundingBox overlaps.
100         *
101         * @param box -
102         *            HyperBoundingBox to test
103         * @return boolean
104         */
105        public boolean overlaps( HyperBoundingBox box ) {
106            boolean intersect = true;
107    
108            for ( int i = 0; i < getDimension(); i++ ) {
109                if ( ( pMin.getCoord( i ) > box.getPMax().getCoord( i ) )
110                     || ( pMax.getCoord( i ) < box.getPMin().getCoord( i ) ) ) {
111                    intersect = false;
112                    break;
113                }
114            }
115    
116            return intersect;
117        }
118    
119        /**
120         * Tests if this contains the given HyperBoundingBox overlaps.
121         *
122         * @param box -
123         *            HyperBoundingBox to test
124         * @return boolean
125         */
126        public boolean contains( HyperBoundingBox box ) {
127            boolean contains = true;
128    
129            for ( int i = 0; i < getDimension(); i++ ) {
130                if ( ( pMin.getCoord( i ) > box.getPMin().getCoord( i ) )
131                     || ( pMax.getCoord( i ) < box.getPMax().getCoord( i ) ) ) {
132                    contains = false;
133                    break;
134                }
135            }
136    
137            return contains;
138        }
139    
140        /**
141         * Computes the area (over all dimension) of this.
142         *
143         * @return double
144         */
145        public double getArea() {
146            double area = 1;
147    
148            for ( int i = 0; i < pMin.getDimension(); i++ )
149                area = area * ( pMax.getCoord( i ) - pMin.getCoord( i ) );
150    
151            return area;
152        }
153    
154        /**
155         * Computes the union of this with the given HyperBoundingBox.
156         *
157         * @param box -
158         *            given HyperBoundingBox
159         * @return HyperBoundingBox
160         */
161        public HyperBoundingBox unionBoundingBox( HyperBoundingBox box ) {
162    
163            if ( this.getDimension() != box.getDimension() )
164                throw new IllegalArgumentException( "HyperBoundingBoxes need same dimension " + this.getDimension()
165                                                    + " != " + box.getDimension() );
166    
167            if ( this.equals( HyperBoundingBox.getNullHyperBoundingBox( this.getDimension() ) ) )
168                return box;
169            if ( box.equals( HyperBoundingBox.getNullHyperBoundingBox( this.getDimension() ) ) )
170                return this;
171    
172            double[] min = new double[this.getDimension()];
173            double[] max = new double[this.getDimension()];
174    
175            for ( int i = 0; i < this.getDimension(); i++ ) {
176    
177                if ( this.getPMin().getCoord( i ) <= box.getPMin().getCoord( i ) ) {
178                    min[i] = this.getPMin().getCoord( i );
179                } else {
180                    min[i] = box.getPMin().getCoord( i );
181                }
182                if ( this.getPMax().getCoord( i ) >= box.getPMax().getCoord( i ) ) {
183                    max[i] = this.getPMax().getCoord( i );
184                } else {
185                    max[i] = box.getPMax().getCoord( i );
186                }
187            }
188            return new HyperBoundingBox( new HyperPoint( min ), new HyperPoint( max ) );
189        }
190    
191        /**
192         * Computes the minimal distance square of this to the given HyperPoint. After Roussopoulos
193         * Nick: Nearest Neighbor Queries - MINDIST
194         *
195         * @param point -
196         *            HyperPoint
197         * @return double
198         */
199        public double minDist( HyperPoint point ) {
200            double min = 0;
201            double ri = 0;
202    
203            for ( int i = 0; i < point.getDimension(); i++ ) {
204                if ( point.getCoord( i ) < this.pMin.getCoord( i ) ) {
205                    ri = this.pMin.getCoord( i );
206                } else {
207                    if ( point.getCoord( i ) > this.pMax.getCoord( i ) ) {
208                        ri = this.pMax.getCoord( i );
209                    } else {
210                        ri = point.getCoord( i );
211                    }
212                }
213                min = min + Math.pow( point.getCoord( i ) - ri, 2 );
214            }
215            return min;
216        }
217    
218        /**
219         * Deep copy.
220         *
221         * @see java.lang.Object#clone()
222         */
223        protected Object clone() {
224            return new HyperBoundingBox( (HyperPoint) pMin.clone(), (HyperPoint) pMax.clone() );
225        }
226    
227        /**
228         * Builds a String representation of the HyperBoundingBox.
229         *
230         * @return String
231         */
232        public String toString() {
233            return "BOX: P-Min (" + pMin.toString() + "), P-Max (" + pMax.toString() + ")";
234        }
235    
236        /**
237         * Implements equals
238         *
239         * @see java.lang.Object#equals(java.lang.Object)
240         */
241        public boolean equals( Object obj ) {
242            HyperBoundingBox box = (HyperBoundingBox) obj;
243            return ( this.pMin.equals( box.pMin ) && this.pMax.equals( box.pMax ) );
244        }
245    }