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 }