001    //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/branches/2.2_testing/src/org/deegree/model/spatialschema/MultiPointImpl.java $
002    /*----------------    FILE HEADER  ------------------------------------------
003    
004     This file is part of deegree.
005     Copyright (C) 2001-2008 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     * default implementierung of the MultiPoint interface of package jago.model.
054     * 
055     * <p>
056     * ------------------------------------------------------------
057     * </p>
058     * 
059     * @version 12.6.2001
060     * @author Andreas Poth href="mailto:poth@lat-lon.de"
061     *         <p>
062     */
063    final class MultiPointImpl extends MultiPrimitiveImpl implements MultiPoint, Serializable {
064        /** Use serialVersionUID for interoperability. */
065        private final static long serialVersionUID = -1105623021535230655L;
066    
067        private static final ILogger LOG = LoggerFactory.getLogger( MultiPointImpl.class );
068    
069        /**
070         * Creates a new MultiPointImpl object.
071         * 
072         * @param crs
073         */
074        public MultiPointImpl( CoordinateSystem crs ) {
075            super( crs );
076        }
077    
078        /**
079         * Creates a new MultiPointImpl object.
080         * 
081         * @param gmp
082         */
083        public MultiPointImpl( Point[] gmp ) {
084            super( gmp[0].getCoordinateSystem() );
085    
086            for ( int i = 0; i < gmp.length; i++ ) {
087                aggregate.add( gmp[i] );
088            }
089    
090        }
091    
092        /**
093         * Creates a new MultiPointImpl object.
094         * 
095         * @param gmp
096         * @param crs
097         */
098        public MultiPointImpl( Point[] gmp, CoordinateSystem crs ) {
099            super( crs );
100    
101            for ( int i = 0; i < gmp.length; i++ ) {
102                aggregate.add( gmp[i] );
103            }
104    
105        }
106    
107        /**
108         * adds a Point to the aggregation
109         */
110        public void addPoint( Point gmp ) {
111            super.add( gmp );
112        }
113    
114        /**
115         * inserts a Point into the aggregation. all elements with an index equal or larger index will
116         * be moved. if index is larger then getSize() - 1 or smaller then 0 or gmp equals null an
117         * exception will be thrown.
118         * 
119         * @param gmp
120         *            Point to insert.
121         * @param index
122         *            position where to insert the new Point
123         */
124        public void insertPointAt( Point gmp, int index )
125                                throws GeometryException {
126            super.insertObjectAt( gmp, index );
127        }
128    
129        /**
130         * sets the submitted Point at the submitted index. the element at the position
131         * <code>index</code> will be removed. if index is larger then getSize() - 1 or smaller then 0
132         * or gmp equals null an exception will be thrown.
133         * 
134         * @param gmp
135         *            Point to set.
136         * @param index
137         *            position where to set the new Point
138         */
139        public void setPointAt( Point gmp, int index )
140                                throws GeometryException {
141            setObjectAt( gmp, index );
142        }
143    
144        /**
145         * removes the submitted Point from the aggregation
146         * 
147         * @return the removed Point
148         */
149        public Point removePoint( Point gmp ) {
150            return (Point) super.removeObject( gmp );
151        }
152    
153        /**
154         * removes the Point at the submitted index from the aggregation. if index is larger then
155         * getSize() - 1 or smaller then 0 an exception will be thrown.
156         * 
157         * @return the removed Point
158         */
159        public Point removePointAt( int index )
160                                throws GeometryException {
161            return (Point) super.removeObjectAt( index );
162        }
163    
164        /**
165         * returns the Point at the submitted index.
166         */
167        public Point getPointAt( int index ) {
168            return (Point) super.getPrimitiveAt( index );
169        }
170    
171        /**
172         * returns all Points as array
173         */
174        public Point[] getAllPoints() {
175            return (Point[]) aggregate.toArray( new Point[getSize()] );
176        }
177    
178        /**
179         * updates the bounding box of the aggregation
180         */
181        private void calculateEnvelope() {
182            Point gmp = getPointAt( 0 );
183    
184            double[] min = gmp.getAsArray().clone();
185            double[] max = min.clone();
186    
187            for ( int i = 1; i < getSize(); i++ ) {
188                double[] pos = getPointAt( i ).getAsArray();
189    
190                for ( int j = 0; j < pos.length; j++ ) {
191                    if ( pos[j] < min[j] ) {
192                        min[j] = pos[j];
193                    } else if ( pos[j] > max[j] ) {
194                        max[j] = pos[j];
195                    }
196                }
197            }
198    
199            envelope = new EnvelopeImpl( new PositionImpl( min ), new PositionImpl( max ), this.crs );
200        }
201    
202        /**
203         * calculates the centroid of the surface
204         */
205        private void calculateCentroid() {
206            try {
207                Point gmp = getPointAt( 0 );
208    
209                double[] cen = new double[gmp.getAsArray().length];
210    
211                for ( int i = 0; i < getSize(); i++ ) {
212                    double[] pos = getPointAt( i ).getAsArray();
213    
214                    for ( int j = 0; j < pos.length; j++ ) {
215                        cen[j] += ( pos[j] / getSize() );
216                    }
217                }
218    
219                centroid = new PointImpl( new PositionImpl( cen ), null );
220            } catch ( Exception ex ) {
221                LOG.logError( "", ex );
222            }
223        }
224    
225        /**
226         * calculates the centroid and envelope of the aggregation
227         */
228        protected void calculateParam() {
229            calculateCentroid();
230            calculateEnvelope();
231            setValid( true );
232        }
233    
234        /**
235         * The operation "dimension" shall return the inherent dimension of this Geometry, which shall
236         * be less than or equal to the coordinate dimension. The dimension of a collection of geometric
237         * objects shall be the largest dimension of any of its pieces. Points are 0-dimensional, curves
238         * are 1-dimensional, surfaces are 2-dimensional, and solids are 3-dimensional.
239         */
240        public int getDimension() {
241            return 0;
242        }
243    
244        /**
245         * The operation "coordinateDimension" shall return the dimension of the coordinates that define
246         * this Geometry, which must be the same as the coordinate dimension of the coordinate reference
247         * system for this Geometry.
248         */
249        public int getCoordinateDimension() {
250            return getPointAt( 0 ).getCoordinateDimension();
251        }
252    
253        /**
254         * returns a shallow copy of the geometry
255         */
256        public Object clone() {
257            MultiPoint mp = null;
258    
259            try {
260                mp = new MultiPointImpl( getCoordinateSystem() );
261    
262                for ( int i = 0; i < this.getSize(); i++ ) {
263                    PointImpl pi = (PointImpl) getPointAt( i );
264                    mp.add( (Point) pi.clone() );
265                }
266            } catch ( Exception ex ) {
267                LOG.logError( "MultiPoint_Impl.clone: ", ex );
268            }
269    
270            return mp;
271        }
272    }