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