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 }