001    //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/branches/2.2_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    package org.deegree.io.rtree;
021    
022    import java.io.Serializable;
023    
024    /**
025     * <p>
026     * HyperBoundingBox implementing a bounding box
027     * object in the multidimensional space.
028     * </p>
029     * @author Wolfgang Baer - WBaer@gmx.de
030     */
031    
032    public class HyperBoundingBox implements Serializable {
033    
034        private HyperPoint pMin;
035        private HyperPoint pMax;
036    
037    
038        /**
039             * Constructor.<br>
040             * Creates a HyperBoundingBox for given HyperPoints.
041             * @param pMin - min point
042             * @param pMax - max point
043         */
044        public HyperBoundingBox( HyperPoint pMin, HyperPoint pMax ) {
045                    if(pMin.getDimension() != pMax.getDimension())
046                            throw new IllegalArgumentException("HyperPoints need same dimension: " + pMin.getDimension() +" != " + pMax.getDimension());
047    
048            this.pMin = pMin;
049            this.pMax = pMax;
050        }
051    
052        /**
053             * Creates a null HyperBoundingBox with null HyperPoints.
054             * Mostly used internal.
055             * @param dimension - int for dimension of point
056             * @return HyperBoundingBox
057         */
058            protected static HyperBoundingBox getNullHyperBoundingBox(int dimension) {
059                    return new HyperBoundingBox(HyperPoint.getNullHyperPoint(dimension), HyperPoint.getNullHyperPoint(dimension));          
060        }
061    
062        /**
063         * Returns the minimum HyperPoint
064         * @return HyperPoint
065         * 
066         */
067        public HyperPoint getPMin() {
068            return pMin;
069        }
070    
071        /**
072         * Returns the maximum HyperPoint
073         * @return HyperPoint
074         * 
075         */
076        public HyperPoint getPMax() {
077            return pMax;
078        }
079    
080        /**
081             * Returns the dimension of this HyperBoundingBox.
082             * @return int
083         */
084        public int getDimension() {
085            return pMin.getDimension();
086        }
087    
088        /**
089             * Tests if this and the given HyperBoundingBox overlaps.
090             * @param box - HyperBoundingBox to test
091             * @return boolean
092         */
093        public boolean overlaps( HyperBoundingBox box ) {
094            boolean intersect = true;
095    
096            for ( int i = 0; i < getDimension(); i++ ) {
097                if ( ( pMin.getCoord( i ) > box.getPMax().getCoord( i ) ) || 
098                         ( pMax.getCoord( i ) < box.getPMin().getCoord( i ) ) ) {
099                    intersect = false;
100                    break;
101                }
102            }
103    
104            return intersect;
105        }
106    
107        /**
108             * Tests if this contains the given HyperBoundingBox overlaps.
109             * @param box - HyperBoundingBox to test
110             * @return boolean
111         */
112        public boolean contains( HyperBoundingBox box ) {
113            boolean contains = true;
114    
115            for ( int i = 0; i < getDimension(); i++ ) {
116                if ( ( pMin.getCoord( i ) > box.getPMin().getCoord( i ) ) || 
117                         ( pMax.getCoord( i ) < box.getPMax().getCoord( i ) ) ) {
118                    contains = false;
119                    break;
120                }
121            }
122    
123            return contains;
124        }
125    
126            
127        /**
128             * Computes the area (over all dimension) of this.
129             * @return double
130         */
131        public double getArea() {
132            double area = 1;
133    
134            for ( int i = 0; i < pMin.getDimension(); i++ )
135                area = area * ( pMax.getCoord( i ) - pMin.getCoord( i ) );
136    
137            return area;
138        }
139    
140        /**
141             * Computes the union of this with the given HyperBoundingBox.
142             * @param box - given HyperBoundingBox
143             * @return HyperBoundingBox
144         */
145        public HyperBoundingBox unionBoundingBox( HyperBoundingBox box ) {
146    
147                    if( this.getDimension() != box.getDimension()) 
148                            throw new IllegalArgumentException("HyperBoundingBoxes need same dimension "+ this.getDimension() + " != " + box.getDimension());
149                                    
150                    if(this.equals(HyperBoundingBox.getNullHyperBoundingBox(this.getDimension())))
151                            return box;
152                    if(box.equals(HyperBoundingBox.getNullHyperBoundingBox(this.getDimension())))
153                return this;
154    
155            double[] min = new double[this.getDimension()];
156            double[] max = new double[this.getDimension()];
157    
158            for ( int i = 0; i < this.getDimension(); i++ ) {
159                    
160                            if(this.getPMin().getCoord(i) <= box.getPMin().getCoord(i)) {
161                    min[i] = this.getPMin().getCoord( i );
162                            }
163                            else { 
164                    min[i] = box.getPMin().getCoord( i );
165                            }
166                            if(this.getPMax().getCoord(i) >= box.getPMax().getCoord(i)) {
167                    max[i] = this.getPMax().getCoord( i );
168                            }
169                            else {
170                                    max[i] = box.getPMax().getCoord( i );
171                            }
172            }
173            return new HyperBoundingBox( new HyperPoint( min ), new HyperPoint( max ) );
174        }
175    
176        /**
177             * Computes the minimal distance square of this to the given HyperPoint.
178             * After Roussopoulos Nick: Nearest Neighbor Queries - MINDIST
179             * @param point - HyperPoint
180             * @return double
181         */
182        public double minDist( HyperPoint point ) {
183            double min = 0;
184            double ri = 0;
185    
186            for ( int i = 0; i < point.getDimension(); i++ ) {
187                            if(point.getCoord(i) < this.pMin.getCoord(i)) {
188                    ri = this.pMin.getCoord( i );
189                            }
190                            else {
191                                    if(point.getCoord(i) > this.pMax.getCoord(i)) {
192                        ri = this.pMax.getCoord( i );
193                                    }
194                                    else {
195                        ri = point.getCoord( i );
196                                    }
197                }
198                min = min + Math.pow( point.getCoord( i ) - ri, 2 );
199            }
200            return min;
201        }
202    
203            
204        /**
205             * Deep copy.
206             * @see java.lang.Object#clone()
207         */
208        protected Object clone() {
209            return new HyperBoundingBox( (HyperPoint)pMin.clone(), (HyperPoint)pMax.clone() );
210        }
211    
212        /**
213             * Builds a String representation of the HyperBoundingBox.
214             * @return String 
215         */
216        public String toString() {
217            return "BOX: P-Min (" + pMin.toString() + "), P-Max (" + pMax.toString() + ")";
218        }
219    
220        /**
221             * Implements equals
222             * @see java.lang.Object#equals(java.lang.Object)
223         */
224        public boolean equals( Object obj ) {
225            HyperBoundingBox box = (HyperBoundingBox)obj;
226            return ( this.pMin.equals( box.pMin ) && this.pMax.equals( box.pMax ) );
227        }
228    }