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