001    //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/branches/2.2_testing/src/org/deegree/graphics/FeatureLayer.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.graphics;
045    
046    import java.util.ArrayList;
047    import java.util.List;
048    
049    import org.deegree.model.crs.CoordinateSystem;
050    import org.deegree.model.crs.GeoTransformer;
051    import org.deegree.model.feature.Feature;
052    import org.deegree.model.feature.FeatureCollection;
053    import org.deegree.model.feature.FeatureFactory;
054    import org.deegree.model.feature.FeatureProperty;
055    import org.deegree.model.spatialschema.Envelope;
056    import org.deegree.model.spatialschema.Geometry;
057    import org.deegree.model.spatialschema.GeometryFactory;
058    import org.deegree.model.spatialschema.Point;
059    import org.deegree.model.spatialschema.Position;
060    
061    /**
062     * A Layer is a collection of <tt>Feature</tt>s building a thematic 'unit' waterways or country
063     * borders for example. <tt>Feature</tt>s can be added or removed from the layer. A
064     * <tt>Feature</tt> can e changed by a modul of the application using the layer because only
065     * references to <tt>Feature</tt>s are stored within a layer.
066     * 
067     * 
068     * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
069     * @version $Revision: 9440 $ $Date: 2008-01-08 11:53:43 +0100 (Di, 08 Jan 2008) $
070     */
071    
072    public class FeatureLayer extends AbstractLayer {
073    
074        private FeatureCollection fc = null;
075    
076        /**
077         * creates a layer with EPSG:4326 as default coordinate system
078         */
079        FeatureLayer( String name ) throws Exception {
080            super( name );
081    
082            fc = FeatureFactory.createFeatureCollection( name, 50 );
083    
084            init( fc );
085        }
086    
087        /**
088         * Creates a new FeatureLayer object.
089         * 
090         * @param name
091         * @param crs
092         * 
093         * @throws Exception
094         */
095        FeatureLayer( String name, CoordinateSystem crs ) throws Exception {
096            super( name, crs );
097    
098            fc = FeatureFactory.createFeatureCollection( name, 50 );
099    
100            init( fc );
101        }
102    
103        /**
104         * Creates a new AbstractLayer object.
105         * 
106         * @param name
107         * @param crs
108         * @param fc
109         * 
110         * @throws Exception
111         */
112        FeatureLayer( String name, CoordinateSystem crs, FeatureCollection fc ) throws Exception {
113            super( name, crs );
114            init( fc );
115        }
116    
117        /**
118         * initializes serveral parameters of the layer and homogenizes the coordinate reference systems
119         * of the features
120         * 
121         * @param feature
122         * @throws Exception
123         */
124        private void init( FeatureCollection feature )
125                                throws Exception {
126    
127            this.fc = FeatureFactory.createFeatureCollection( feature.getId(), feature.size() );
128            // create object for coordinate transformation
129            GeoTransformer gt = new GeoTransformer( cs );
130            double minx = 9E99;
131            double maxx = -9E99;
132            double miny = 9E99;
133            double maxy = -9E99;
134            String s1 = cs.getName();
135            for ( int i = 0; i < feature.size(); i++ ) {
136                Feature feat = feature.getFeature( i );
137                FeatureProperty[] prop = feat.getProperties();
138                FeatureProperty[] propN = new FeatureProperty[prop.length];
139                boolean changed = false;
140                for ( int k = 0; k < prop.length; k++ ) {
141    
142                    Object value = prop[k].getValue();
143                    propN[k] = prop[k];
144                    if ( value instanceof Geometry ) {
145    
146                        CoordinateSystem _cs_ = ( (Geometry) value ).getCoordinateSystem();
147                        String s2 = null;
148                        if ( _cs_ != null ) {
149                            s2 = _cs_.getName();
150                        } else {
151                            // default reference system
152                            s2 = "EPSG:4326";
153                        }
154    
155                        if ( !s1.equalsIgnoreCase( s2 ) ) {
156                            Geometry transformedGeometry = gt.transform( (Geometry) value );
157                            propN[k] = FeatureFactory.createFeatureProperty( prop[k].getName(), transformedGeometry );
158                            changed = true;
159                            value = transformedGeometry;
160                        }
161                        if ( value instanceof Point ) {
162                            Position pos = ( (Point) value ).getPosition();
163                            if ( pos.getX() > maxx ) {
164                                maxx = pos.getX();
165                            }
166                            if ( pos.getX() < minx ) {
167                                minx = pos.getX();
168                            }
169                            if ( pos.getY() > maxy ) {
170                                maxy = pos.getY();
171                            }
172                            if ( pos.getY() < miny ) {
173                                miny = pos.getY();
174                            }
175                        } else {
176                            Envelope en = ( (Geometry) value ).getEnvelope();
177                            if ( en.getMax().getX() > maxx ) {
178                                maxx = en.getMax().getX();
179                            }
180                            if ( en.getMin().getX() < minx ) {
181                                minx = en.getMin().getX();
182                            }
183                            if ( en.getMax().getY() > maxy ) {
184                                maxy = en.getMax().getY();
185                            }
186                            if ( en.getMin().getY() < miny ) {
187                                miny = en.getMin().getY();
188                            }
189                        }
190                    }
191                }
192                if ( changed ) {
193                    FeatureProperty[] fp = new FeatureProperty[propN.length];
194                    for ( int j = 0; j < fp.length; j++ ) {
195                        fp[j] = FeatureFactory.createFeatureProperty( propN[j].getName(), propN[j].getValue() );
196                    }
197                    feat = FeatureFactory.createFeature( feat.getId(), feat.getFeatureType(), fp );
198                }
199                fc.add( feat );
200            }
201    
202            boundingbox = GeometryFactory.createEnvelope( minx, miny, maxx, maxy, null );
203    
204        }
205    
206        /**
207         * 
208         * 
209         */
210        private void recalculateBoundingbox() {
211    
212            double minx = 9E99;
213            double maxx = -9E99;
214            double miny = 9E99;
215            double maxy = -9E99;
216    
217            for ( int i = 0; i < fc.size(); i++ ) {
218                Geometry[] prop = fc.getFeature( i ).getGeometryPropertyValues();
219                for ( int k = 0; k < prop.length; k++ ) {
220                    if ( prop[k] instanceof Point ) {
221                        Position pos = ( (Point) prop[k] ).getPosition();
222                        if ( pos.getX() > maxx ) {
223                            maxx = pos.getX();
224                        }
225                        if ( pos.getX() < minx ) {
226                            minx = pos.getX();
227                        }
228                        if ( pos.getY() > maxy ) {
229                            maxy = pos.getY();
230                        }
231                        if ( pos.getY() < miny ) {
232                            miny = pos.getY();
233                        }
234                    } else {
235                        Envelope en = ( prop[k] ).getEnvelope();
236                        if ( en.getMax().getX() > maxx ) {
237                            maxx = en.getMax().getX();
238                        }
239                        if ( en.getMin().getX() < minx ) {
240                            minx = en.getMin().getX();
241                        }
242                        if ( en.getMax().getY() > maxy ) {
243                            maxy = en.getMax().getY();
244                        }
245                        if ( en.getMin().getY() < miny ) {
246                            miny = en.getMin().getY();
247                        }
248                    }
249                }
250            }
251    
252            boundingbox = GeometryFactory.createEnvelope( minx, miny, maxx, maxy, null );
253    
254        }
255    
256        /**
257         * returns the feature that matches the submitted id
258         * 
259         * @param id
260         * @return feature identified by its id
261         */
262        public Feature getFeatureById( String id ) {
263            return fc.getFeature( id );
264        }
265    
266        /**
267         * returns the feature that matches the submitted id
268         * 
269         * @param ids
270         * @return features identified by their id
271         */
272        public Feature[] getFeaturesById( String[] ids ) {
273    
274            List<Feature> list = new ArrayList<Feature>();
275    
276            Feature feature = null;
277    
278            for ( int i = 0; i < fc.size(); i++ ) {
279                feature = fc.getFeature( i );
280    
281                for ( int k = 0; k < ids.length; k++ ) {
282                    if ( feature.getId().equals( ids[k] ) ) {
283                        list.add( feature );
284                        break;
285                    }
286                }
287            }
288    
289            return list.toArray( new Feature[list.size()] );
290        }
291    
292        /**
293         * returns the feature that matches the submitted index
294         * 
295         * @param index
296         * @return a feature
297         */
298        public Feature getFeature( int index ) {
299            Feature feature = fc.getFeature( index );
300            return feature;
301        }
302    
303        /**
304         * returns all features
305         * 
306         * @return all features as array
307         */
308        public Feature[] getAllFeatures() {
309            return fc.toArray();
310        }
311    
312        /**
313         * adds a feature to the layer
314         * 
315         * @param feature
316         * @throws Exception
317         */
318        public void addFeature( Feature feature )
319                                throws Exception {
320            fc.add( feature );
321            recalculateBoundingbox();
322        }
323    
324        /**
325         * adds a feature collection to the layer
326         * 
327         * @param featureCollection
328         * @throws Exception
329         */
330        public void addFeatureCollection( FeatureCollection featureCollection )
331                                throws Exception {
332            fc.add( featureCollection );
333            recalculateBoundingbox();
334        }
335    
336        /**
337         * removes a display Element from the layer
338         * 
339         * @param feature
340         * @throws Exception
341         */
342        public void removeFeature( Feature feature )
343                                throws Exception {
344            fc.remove( feature );
345            recalculateBoundingbox();
346        }
347    
348        /**
349         * removes the display Element from the layer that matches the submitted id
350         * 
351         * @param id
352         * @throws Exception
353         */
354        public void removeFeature( int id )
355                                throws Exception {
356            removeFeature( getFeature( id ) );
357        }
358    
359        /**
360         * returns the amount of features within the layer.
361         * 
362         * @return number of contained features
363         */
364        public int getSize() {
365            return fc.size();
366        }
367    
368        /**
369         * sets the coordinate reference system of the MapView. If a new crs is set all geometries of
370         * GeometryFeatures will be transformed to the new coordinate reference system.
371         * 
372         * @param crs
373         * @throws Exception
374         */
375        public void setCoordinatesSystem( CoordinateSystem crs )
376                                throws Exception {
377            if ( !cs.equals( crs ) ) {
378                this.cs = crs;
379                init( fc );
380            }
381        }
382    }