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