001    //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/branches/2.2_testing/src/org/deegree/model/spatialschema/MultiCurveImpl.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 implementation of the MultiCurve interface from package jago.model.
054     * 
055     * ------------------------------------------------------------
056     * 
057     * @version 12.6.2001
058     * @author Andreas Poth
059     */
060    final class MultiCurveImpl extends MultiPrimitiveImpl implements MultiCurve, Serializable {
061        /** Use serialVersionUID for interoperability. */
062        private final static long serialVersionUID = 2730942874409216686L;
063    
064        private static final ILogger LOG = LoggerFactory.getLogger( MultiCurveImpl.class );
065    
066        /**
067         * Creates a new MultiCurveImpl object.
068         * 
069         * @param crs
070         */
071        public MultiCurveImpl( CoordinateSystem crs ) {
072            super( crs );
073        }
074    
075        /**
076         * Creates a new MultiCurveImpl object.
077         * 
078         * @param gmc
079         */
080        public MultiCurveImpl( Curve[] gmc ) {
081            super( gmc[0].getCoordinateSystem() );
082    
083            for ( int i = 0; i < gmc.length; i++ ) {
084                aggregate.add( gmc[i] );
085            }
086    
087        }
088    
089        /**
090         * Creates a new MultiCurveImpl object.
091         * 
092         * @param gmc
093         * @param crs
094         */
095        public MultiCurveImpl( Curve[] gmc, CoordinateSystem crs ) {
096            super( crs );
097    
098            for ( int i = 0; i < gmc.length; i++ ) {
099                aggregate.add( gmc[i] );
100            }
101    
102        }
103    
104        /**
105         * adds a Curve to the aggregation
106         */
107        public void addCurve( Curve gmc ) {
108            super.add( gmc );
109        }
110    
111        /**
112         * inserts a Curve in the aggregation. all elements with an index equal or larger index will be
113         * moved. if index is larger then getSize() - 1 or smaller then 0 or gmc equals null an
114         * exception will be thrown.
115         * 
116         * @param gmc
117         *            Curve to insert.
118         * @param index
119         *            position where to insert the new Curve
120         */
121        public void insertCurveAt( Curve gmc, int index )
122                                throws GeometryException {
123            super.insertObjectAt( gmc, index );
124        }
125    
126        /**
127         * sets the submitted Curve at the submitted index. the element at the position
128         * <code>index</code> will be removed. if index is larger then getSize() - 1 or smaller then 0
129         * or gmc equals null an exception will be thrown.
130         * 
131         * @param gmc
132         *            Curve to set.
133         * @param index
134         *            position where to set the new Curve
135         */
136        public void setCurveAt( Curve gmc, int index )
137                                throws GeometryException {
138            setObjectAt( gmc, index );
139        }
140    
141        /**
142         * removes the submitted Curve from the aggregation
143         * 
144         * @return the removed Curve
145         */
146        public Curve removeCurve( Curve gmc ) {
147            return (Curve) super.removeObject( gmc );
148        }
149    
150        /**
151         * removes the Curve at the submitted index from the aggregation. if index is larger then
152         * getSize() - 1 or smaller then 0 an exception will be thrown.
153         * 
154         * @return the removed Curve
155         */
156        public Curve removeCurveAt( int index )
157                                throws GeometryException {
158            return (Curve) super.removeObjectAt( index );
159        }
160    
161        /**
162         * removes all Curve from the aggregation.
163         */
164        public void removeAll() {
165            super.removeAll();
166        }
167    
168        /**
169         * returns the Curve at the submitted index.
170         */
171        public Curve getCurveAt( int index ) {
172            return (Curve) super.getPrimitiveAt( index );
173        }
174    
175        /**
176         * returns all Curves as array
177         */
178        public Curve[] getAllCurves() {
179            return aggregate.toArray( new Curve[getSize()] );
180        }
181    
182        /**
183         * returns true if the submitted Curve is within the aggregation
184         */
185        public boolean isMember( Curve gmc ) {
186            return super.isMember( gmc );
187        }
188    
189        /**
190         * returns the boundary of the MultiCurve
191         * <p>
192         * not implemented yet
193         */
194        public Boundary getBoundary() {
195            return null;
196        }
197    
198        /**
199         * calculates the bounding box / envelope of the aggregation
200         */
201        protected void calculateEnvelope() {
202            Envelope bb = getCurveAt( 0 ).getEnvelope();
203    
204            double[] min = bb.getMin().getAsArray().clone();
205            double[] max = bb.getMax().getAsArray().clone();
206    
207            for ( int i = 1; i < getSize(); i++ ) {
208                double[] pos1 = getCurveAt( i ).getEnvelope().getMin().getAsArray();
209                double[] pos2 = getCurveAt( i ).getEnvelope().getMax().getAsArray();
210    
211                for ( int j = 0; j < pos1.length; j++ ) {
212                    if ( pos1[j] < min[j] ) {
213                        min[j] = pos1[j];
214                    } else if ( pos1[j] > max[j] ) {
215                        max[j] = pos1[j];
216                    }
217    
218                    if ( pos2[j] < min[j] ) {
219                        min[j] = pos2[j];
220                    } else if ( pos2[j] > max[j] ) {
221                        max[j] = pos2[j];
222                    }
223                }
224            }
225    
226            envelope = new EnvelopeImpl( new PositionImpl( min ), new PositionImpl( max ), this.crs );
227        }
228    
229        /**
230         * calculates the centroid of the aggregation
231         */
232        protected void calculateCentroid() {
233            try {
234                double cnt = 0;
235                Point gmp = getCurveAt( 0 ).getCentroid();
236    
237                double[] cen = new double[gmp.getAsArray().length];
238    
239                for ( int i = 0; i < getSize(); i++ ) {
240                    cnt += getCurveAt( i ).getNumberOfCurveSegments();
241    
242                    double[] pos = getCurveAt( i ).getCentroid().getAsArray();
243    
244                    for ( int j = 0; j < getCoordinateDimension(); j++ ) {
245                        cen[j] += pos[j];
246                    }
247                }
248    
249                for ( int j = 0; j < getCoordinateDimension(); j++ ) {
250                    cen[j] = cen[j] / cnt / getSize();
251                }
252    
253                centroid = new PointImpl( new PositionImpl( cen ), null );
254            } catch ( Exception ex ) {
255                LOG.logError( "", ex );
256            }
257        }
258    
259        /**
260         * calculates the centroid and envelope of the aggregation
261         */
262        protected void calculateParam() {
263            calculateCentroid();
264            calculateEnvelope();
265            setValid( true );
266        }
267    
268        /**
269         * The operation "dimension" shall return the inherent dimension of this Geometry, which shall
270         * be less than or equal to the coordinate dimension. The dimension of a collection of geometric
271         * objects shall be the largest dimension of any of its pieces. Points are 0-dimensional, curves
272         * are 1-dimensional, surfaces are 2-dimensional, and solids are 3-dimensional.
273         */
274        public int getDimension() {
275            return 1;
276        }
277    
278        /**
279         * The operation "coordinateDimension" shall return the dimension of the coordinates that define
280         * this Geometry, which must be the same as the coordinate dimension of the coordinate reference
281         * system for this Geometry.
282         */
283        public int getCoordinateDimension() {
284            return getCurveAt( 0 ).getCoordinateDimension();
285        }
286    
287        /**
288         * returns a shallow copy of the geometry
289         */
290        public Object clone() {
291            MultiCurve mc = null;
292    
293            try {
294                mc = new MultiCurveImpl( getCoordinateSystem() );
295    
296                for ( int i = 0; i < this.getSize(); i++ ) {
297                    CurveImpl ci = (CurveImpl) getCurveAt( i );
298                    mc.addCurve( (Curve) ci.clone() );
299                }
300            } catch ( Exception ex ) {
301                LOG.logError( "MultiCurve_Impl.clone: ", ex );
302            }
303    
304            return mc;
305        }
306    }