001    //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/tags/2.1/src/org/deegree/model/spatialschema/MultiPointImpl.java $
002    /*----------------    FILE HEADER  ------------------------------------------
003    
004    This file is part of deegree.
005    Copyright (C) 2001-2006 by:
006    EXSE, Department of Geography, University of Bonn
007    http://www.giub.uni-bonn.de/deegree/
008    lat/lon GmbH
009    http://www.lat-lon.de
010    
011    This library is free software; you can redistribute it and/or
012    modify it under the terms of the GNU Lesser General Public
013    License as published by the Free Software Foundation; either
014    version 2.1 of the License, or (at your option) any later version.
015    
016    This library is distributed in the hope that it will be useful,
017    but WITHOUT ANY WARRANTY; without even the implied warranty of
018    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
019    Lesser General Public License for more details.
020    
021    You should have received a copy of the GNU Lesser General Public
022    License along with this library; if not, write to the Free Software
023    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
024    
025    Contact:
026    
027    Andreas Poth
028    lat/lon GmbH
029    Aennchenstr. 19
030    53115 Bonn
031    Germany
032    E-Mail: poth@lat-lon.de
033    
034    Prof. Dr. Klaus Greve
035    Department of Geography
036    University of Bonn
037    Meckenheimer Allee 166
038    53115 Bonn
039    Germany
040    E-Mail: greve@giub.uni-bonn.de
041    
042                     
043     ---------------------------------------------------------------------------*/
044    package org.deegree.model.spatialschema;
045    
046    import java.io.Serializable;
047    
048    import org.deegree.framework.log.ILogger;
049    import org.deegree.framework.log.LoggerFactory;
050    import org.deegree.model.crs.CoordinateSystem;
051    
052    
053    /**
054    * default implementierung of the MultiPoint interface of
055    * package jago.model. 
056    *
057    * <p>------------------------------------------------------------</p>
058    * @version 12.6.2001
059    * @author Andreas Poth href="mailto:poth@lat-lon.de"
060    * <p>
061    */
062    final class MultiPointImpl extends MultiPrimitiveImpl implements MultiPoint, Serializable {
063        /** Use serialVersionUID for interoperability. */
064        private final static long serialVersionUID = -1105623021535230655L;
065        
066        private static final ILogger LOG = LoggerFactory.getLogger( MultiPointImpl.class );
067    
068        /**
069         * Creates a new MultiPointImpl object.
070         *
071         * @param crs 
072         */
073        public MultiPointImpl( CoordinateSystem crs ) {
074            super( crs );
075        }
076    
077        /**
078         * Creates a new MultiPointImpl object.
079         *
080         * @param gmp 
081         */
082        public MultiPointImpl( Point[] gmp ) {
083            super( gmp[0].getCoordinateSystem() );
084    
085            for ( int i = 0; i < gmp.length; i++ ) {
086                aggregate.add( gmp[i] );
087            }
088    
089        }
090    
091        /**
092         * Creates a new MultiPointImpl object.
093         *
094         * @param gmp 
095         * @param crs 
096         */
097        public MultiPointImpl( Point[] gmp, CoordinateSystem crs ) {
098            super( crs );
099    
100            for ( int i = 0; i < gmp.length; i++ ) {
101                aggregate.add( gmp[i] );
102            }
103    
104        }
105    
106        /**
107         * adds a Point to the aggregation 
108         */
109        public void addPoint( Point gmp ) {
110            super.add( gmp );
111        }
112    
113        /**
114         * inserts a Point into the aggregation. all elements with an index 
115         * equal or larger index will be moved. if index is
116         * larger then getSize() - 1 or smaller then 0 or gmp equals null 
117         * an exception will be thrown.
118         *
119         * @param gmp Point to insert.     
120         * @param index position where to insert the new Point
121         */
122        public void insertPointAt( Point gmp, int index ) throws GeometryException {
123            super.insertObjectAt( gmp, index );
124        }
125    
126        /**
127         * sets the submitted Point at the submitted index. the element
128         * at the position <code>index</code> will be removed. if index is
129         * larger then getSize() - 1 or smaller then 0 or gmp equals null 
130         * an exception will be thrown.
131         *
132         * @param gmp Point to set.     
133         * @param index position where to set the new Point
134         */
135        public void setPointAt( Point gmp, int index ) throws GeometryException {
136            setObjectAt( gmp, index );
137        }
138    
139        /**
140         * removes the submitted Point from the aggregation
141         *
142         * @return the removed Point
143         */
144        public Point removePoint( Point gmp ) {
145            return (Point)super.removeObject( gmp );
146        }
147    
148        /**
149         * removes the Point at the submitted index from the aggregation.
150         * if index is larger then getSize() - 1 or smaller then 0 
151         * an exception will be thrown.
152         *
153         * @return the removed Point
154         */
155        public Point removePointAt( int index ) throws GeometryException {
156            return (Point)super.removeObjectAt( index );
157        }
158    
159        /**
160         * returns the Point at the submitted index. 
161         */
162        public Point getPointAt( int index ) {
163            return (Point)super.getPrimitiveAt( index );
164        }
165    
166        /**
167         * returns all Points as array
168         */
169        public Point[] getAllPoints() {
170            return (Point[])aggregate.toArray( new Point[getSize()] );
171        }
172    
173        /**
174         * updates the bounding box of the aggregation
175         */
176        private void calculateEnvelope() {
177            Point gmp = getPointAt( 0 );
178    
179            double[] min = gmp.getAsArray().clone();
180            double[] max = min.clone();
181    
182            for ( int i = 1; i < getSize(); i++ ) {
183                double[] pos = getPointAt( i ).getAsArray();
184    
185                for ( int j = 0; j < pos.length; j++ ) {
186                    if ( pos[j] < min[j] ) {
187                        min[j] = pos[j];
188                    } else if ( pos[j] > max[j] ) {
189                        max[j] = pos[j];
190                    }
191                }
192            }
193    
194            envelope = new EnvelopeImpl( new PositionImpl( min ), new PositionImpl( max ), this.crs );
195        }
196    
197        /**
198         * calculates the centroid of the surface
199         */
200        private void calculateCentroid() {
201            try {
202                Point gmp = getPointAt( 0 );
203    
204                double[] cen = new double[gmp.getAsArray().length];
205    
206                for ( int i = 0; i < getSize(); i++ ) {
207                    double[] pos = getPointAt( i ).getAsArray();
208    
209                    for ( int j = 0; j < pos.length; j++ ) {
210                        cen[j] += ( pos[j] / getSize() );
211                    }
212                }
213    
214                centroid = new PointImpl( new PositionImpl( cen ), null );
215            } catch ( Exception ex ) {
216                LOG.logError( "", ex );
217            }
218        }
219    
220        /**
221         * calculates the centroid and envelope of the aggregation
222         */
223        protected void calculateParam() {
224            calculateCentroid();
225            calculateEnvelope();
226            setValid( true );
227        }
228    
229        /**
230         * The operation "dimension" shall return the inherent dimension of this
231         * Geometry, which shall be less than or equal to the coordinate dimension.
232         * The dimension of a collection of geometric objects shall be the largest
233         * dimension of any of its pieces. Points are 0-dimensional, curves are
234         * 1-dimensional, surfaces are 2-dimensional, and solids are 3-dimensional.
235         */
236        public int getDimension() {
237            return 0;
238        }
239    
240        /**
241         * The operation "coordinateDimension" shall return the dimension of the
242         * coordinates that define this Geometry, which must be the same as the
243         * coordinate dimension of the coordinate reference system for this Geometry.
244         */
245        public int getCoordinateDimension() {
246            return getPointAt( 0 ).getCoordinateDimension();
247        }
248    
249        /**
250        * returns a shallow copy of the geometry
251        */
252        public Object clone() {
253            MultiPoint mp = null;
254    
255            try {
256                mp = new MultiPointImpl( getCoordinateSystem() );
257    
258                for ( int i = 0; i < this.getSize(); i++ ) {
259                    PointImpl pi = (PointImpl)getPointAt( i );
260                    mp.add( (Point)pi.clone() );
261                }
262            } catch ( Exception ex ) {
263                LOG.logError( "MultiPoint_Impl.clone: ", ex );
264            }
265    
266            return mp;
267        }
268    } /* ********************************************************************
269    Changes to this class. What the people have been up to:
270    $Log$
271    Revision 1.9  2006/11/02 10:20:51  mschneider
272    Fixed null CRS in Envelope creation.
273    
274    Revision 1.8  2006/07/12 14:46:15  poth
275    comment footer added
276    
277    ********************************************************************** */