001 //$HeadURL: svn+ssh://jwilden@svn.wald.intevation.org/deegree/base/branches/2.5_testing/src/org/deegree/model/spatialschema/MultiSurfaceImpl.java $ 002 /*---------------------------------------------------------------------------- 003 This file is part of deegree, http://deegree.org/ 004 Copyright (C) 2001-2009 by: 005 Department of Geography, University of Bonn 006 and 007 lat/lon GmbH 008 009 This library is free software; you can redistribute it and/or modify it under 010 the terms of the GNU Lesser General Public License as published by the Free 011 Software Foundation; either version 2.1 of the License, or (at your option) 012 any later version. 013 This library is distributed in the hope that it will be useful, but WITHOUT 014 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 015 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 016 details. 017 You should have received a copy of the GNU Lesser General Public License 018 along with this library; if not, write to the Free Software Foundation, Inc., 019 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 020 021 Contact information: 022 023 lat/lon GmbH 024 Aennchenstr. 19, 53177 Bonn 025 Germany 026 http://lat-lon.de/ 027 028 Department of Geography, University of Bonn 029 Prof. Dr. Klaus Greve 030 Postfach 1147, 53001 Bonn 031 Germany 032 http://www.geographie.uni-bonn.de/deegree/ 033 034 e-mail: info@deegree.org 035 ----------------------------------------------------------------------------*/ 036 package org.deegree.model.spatialschema; 037 038 import java.io.Serializable; 039 040 import org.deegree.framework.log.ILogger; 041 import org.deegree.framework.log.LoggerFactory; 042 import org.deegree.model.crs.CoordinateSystem; 043 044 /** 045 * default implementation of the MultiSurface interface from 046 * 047 * 048 * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a> 049 * @author last edited by: $Author: mschneider $ 050 * 051 * @version $Revision: 18195 $, $Date: 2009-06-18 17:55:39 +0200 (Do, 18 Jun 2009) $ 052 */ 053 public class MultiSurfaceImpl extends MultiPrimitiveImpl implements MultiSurface, Serializable { 054 /** Use serialVersionUID for interoperability. */ 055 private final static long serialVersionUID = -6471121873087659850L; 056 057 private static final ILogger LOG = LoggerFactory.getLogger( MultiSurfaceImpl.class ); 058 059 private double area = 0; 060 061 /** 062 * Creates a new MultiSurfaceImpl object. 063 * 064 * @param crs 065 */ 066 protected MultiSurfaceImpl( CoordinateSystem crs ) { 067 super( crs ); 068 } 069 070 /** 071 * Creates a new MultiSurfaceImpl object. 072 * 073 * @param surface 074 */ 075 protected MultiSurfaceImpl( Surface[] surface ) { 076 super( surface[0].getCoordinateSystem() ); 077 078 for ( int i = 0; i < surface.length; i++ ) { 079 aggregate.add( surface[i] ); 080 } 081 082 setValid( false ); 083 } 084 085 /** 086 * Creates a new MultiSurfaceImpl object. 087 * 088 * @param surface 089 * @param crs 090 */ 091 protected MultiSurfaceImpl( Surface[] surface, CoordinateSystem crs ) { 092 super( crs ); 093 094 for ( int i = 0; i < surface.length; i++ ) { 095 aggregate.add( surface[i] ); 096 } 097 098 setValid( false ); 099 } 100 101 /** 102 * adds an Surface to the aggregation 103 */ 104 public void addSurface( Surface gms ) { 105 super.add( gms ); 106 } 107 108 /** 109 * inserts a Surface in the aggregation. all elements with an index equal or larger index will be moved. if index is 110 * larger then getSize() - 1 or smaller then 0 or gms equals null an exception will be thrown. 111 * 112 * @param gms 113 * Surface to insert. 114 * @param index 115 * position where to insert the new Surface 116 */ 117 public void insertSurfaceAt( Surface gms, int index ) 118 throws GeometryException { 119 super.insertObjectAt( gms, index ); 120 } 121 122 /** 123 * sets the submitted Surface at the submitted index. the element at the position <code>index</code> will be 124 * removed. if index is larger then getSize() - 1 or smaller then 0 or gms equals null an exception will be thrown. 125 * 126 * @param gms 127 * Surface to set. 128 * @param index 129 * position where to set the new Surface 130 */ 131 public void setSurfaceAt( Surface gms, int index ) 132 throws GeometryException { 133 setObjectAt( gms, index ); 134 } 135 136 /** 137 * removes the submitted Surface from the aggregation 138 * 139 * @return the removed Surface 140 */ 141 public Surface removeSurface( Surface gms ) { 142 return (Surface) super.removeObject( gms ); 143 } 144 145 /** 146 * removes the Surface at the submitted index from the aggregation. if index is larger then getSize() - 1 or smaller 147 * then 0 an exception will be thrown. 148 * 149 * @return the removed Surface 150 */ 151 public Surface removeSurfaceAt( int index ) 152 throws GeometryException { 153 return (Surface) super.removeObjectAt( index ); 154 } 155 156 /** 157 * returns the Surface at the submitted index. 158 */ 159 public Surface getSurfaceAt( int index ) { 160 return (Surface) super.getPrimitiveAt( index ); 161 } 162 163 /** 164 * returns all Surfaces as array 165 */ 166 public Surface[] getAllSurfaces() { 167 return aggregate.toArray( new Surface[getSize()] ); 168 } 169 170 /** 171 * calculates the bounding box / envelope of the aggregation 172 */ 173 private void calculateEnvelope() { 174 Envelope bb = getSurfaceAt( 0 ).getEnvelope(); 175 176 double[] min = bb.getMin().getAsArray().clone(); 177 double[] max = bb.getMax().getAsArray().clone(); 178 179 for ( int i = 1; i < getSize(); i++ ) { 180 double[] pos1 = getSurfaceAt( i ).getEnvelope().getMin().getAsArray(); 181 double[] pos2 = getSurfaceAt( i ).getEnvelope().getMax().getAsArray(); 182 183 for ( int j = 0; j < pos1.length; j++ ) { 184 if ( pos1[j] < min[j] ) { 185 min[j] = pos1[j]; 186 } else if ( pos1[j] > max[j] ) { 187 max[j] = pos1[j]; 188 } 189 190 if ( pos2[j] < min[j] ) { 191 min[j] = pos2[j]; 192 } else if ( pos2[j] > max[j] ) { 193 max[j] = pos2[j]; 194 } 195 } 196 } 197 198 envelope = new EnvelopeImpl( new PositionImpl( min ), new PositionImpl( max ), this.crs ); 199 } 200 201 /** 202 * calculates the centroid and area of the aggregation 203 */ 204 private void calculateCentroidArea() { 205 206 area = 0; 207 int cnt = getCoordinateDimension(); 208 try { 209 double[] cen = new double[cnt]; 210 211 for ( int i = 0; i < getSize(); i++ ) { 212 double a = getSurfaceAt( i ).getArea(); 213 area = area + a; 214 215 double[] pos = getSurfaceAt( i ).getCentroid().getAsArray(); 216 217 for ( int j = 0; j < cnt; j++ ) { 218 cen[j] = cen[j] + ( pos[j] * a ); 219 } 220 } 221 222 for ( int j = 0; j < cnt; j++ ) { 223 cen[j] = cen[j] / area; 224 } 225 226 centroid = new PointImpl( new PositionImpl( cen ), null ); 227 } catch ( Exception e ) { 228 LOG.logError( "", e ); 229 } 230 } 231 232 /** 233 * calculates the centroid, area and envelope of the aggregation 234 */ 235 @Override 236 protected void calculateParam() { 237 calculateEnvelope(); 238 calculateCentroidArea(); 239 setValid( true ); 240 } 241 242 /** 243 * returns the area of the multi surface. this is calculate as the sum of all containing surface areas. 244 * 245 * @return area 246 */ 247 public double getArea() { 248 if ( !isValid() ) { 249 calculateParam(); 250 } 251 return area; 252 } 253 254 @Override 255 public Object clone() { 256 MultiSurface ms = null; 257 258 try { 259 ms = new MultiSurfaceImpl( getCoordinateSystem() ); 260 261 for ( int i = 0; i < this.getSize(); i++ ) { 262 SurfaceImpl si = (SurfaceImpl) getSurfaceAt( i ); 263 ms.add( (Surface) si.clone() ); 264 } 265 } catch ( Exception ex ) { 266 LOG.logError( "MultiSurface_Impl.clone: ", ex ); 267 } 268 269 return ms; 270 } 271 272 /** 273 * @return 2 274 */ 275 @Override 276 public int getDimension() { 277 return 2; 278 } 279 280 /** 281 * the dimension of the first contained surface. 282 */ 283 @Override 284 public int getCoordinateDimension() { 285 return getSurfaceAt( 0 ).getCoordinateDimension(); 286 } 287 }