001 //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.3_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 }