001 //$HeadURL: http://svn.wald.intevation.org/svn/deegree/base/trunk/src/org/deegree/model/spatialschema/SurfaceBoundaryImpl.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 import java.util.Arrays;
040
041 import org.deegree.framework.log.ILogger;
042 import org.deegree.framework.log.LoggerFactory;
043
044 /**
045 * default implementation of the SurfaceBoundary interface.
046 *
047 * ------------------------------------------------------------
048 *
049 * @version 11.6.2001
050 * @author Andreas Poth href="mailto:poth@lat-lon.de"
051 */
052
053 public class SurfaceBoundaryImpl extends PrimitiveBoundaryImpl implements SurfaceBoundary, Serializable {
054 /** Use serialVersionUID for interoperability. */
055 private final static long serialVersionUID = 1399131144729310956L;
056
057 private static final ILogger LOG = LoggerFactory.getLogger( SurfaceBoundaryImpl.class );
058
059 /**
060 * The exterior ring of the surface boundary
061 */
062 public Ring exterior = null;
063
064 /**
065 * The interior ring of the surface boundary
066 */
067 public Ring[] interior = null;
068
069 /**
070 * @param exterior
071 * @param interior
072 */
073 protected SurfaceBoundaryImpl( Ring exterior, Ring[] interior ) {
074 super( exterior.getCoordinateSystem() );
075 this.exterior = exterior;
076 this.interior = interior;
077 setValid( false );
078 }
079
080 public Ring getExteriorRing() {
081 return exterior;
082 }
083
084 public Ring[] getInteriorRings() {
085 return interior;
086 }
087
088 /**
089 * @return the boundary of the boundary
090 */
091 @Override
092 public Boundary getBoundary() {
093 return null;
094 }
095
096 @Override
097 public boolean equals( Object other ) {
098 if ( !super.equals( other ) || !( other instanceof SurfaceBoundaryImpl ) ) {
099 return false;
100 }
101
102 if ( !exterior.equals( ( (SurfaceBoundary) other ).getExteriorRing() ) ) {
103 return false;
104 }
105
106 if ( interior != null ) {
107 Ring[] r1 = getInteriorRings();
108 Ring[] r2 = ( (SurfaceBoundary) other ).getInteriorRings();
109
110 if ( !Arrays.equals( r1, r2 ) ) {
111 return false;
112 }
113 } else {
114 if ( ( (SurfaceBoundary) other ).getInteriorRings() != null ) {
115 return false;
116 }
117 }
118
119 return true;
120 }
121
122 /**
123 * The operation "dimension" shall return the inherent dimension of this Geometry, which shall be less than or equal
124 * to the coordinate dimension. The dimension of a collection of geometric objects shall be the largest dimension of
125 * any of its pieces. Points are 0-dimensional, curves are 1-dimensional, surfaces are 2-dimensional, and solids are
126 * 3-dimensional.
127 */
128 public int getDimension() {
129 return 1;
130 }
131
132 /**
133 * The operation "coordinateDimension" shall return the dimension of the coordinates that define this Geometry,
134 * which must be the same as the coordinate dimension of the coordinate reference system for this Geometry.
135 */
136 public int getCoordinateDimension() {
137 return exterior.getPositions()[0].getCoordinateDimension();
138 }
139
140 @Override
141 public Object clone() {
142 SurfaceBoundary sb = null;
143
144 try {
145 Ring ext = (Ring) ( (RingImpl) getExteriorRing() ).clone();
146 Ring[] inn = new Ring[interior.length];
147
148 for ( int i = 0; i < inn.length; i++ ) {
149 inn[i] = (Ring) ( (RingImpl) interior[i] ).clone();
150 }
151
152 sb = new SurfaceBoundaryImpl( ext, inn );
153 } catch ( Exception ex ) {
154 LOG.logError( "SurfaceBoundary_Impl.clone: ", ex );
155 }
156
157 return sb;
158 }
159
160 @Override
161 public boolean intersects( Geometry gmo ) {
162 boolean inter = exterior.intersects( gmo );
163
164 if ( !inter ) {
165 if ( interior != null ) {
166 for ( int i = 0; i < interior.length; i++ ) {
167 if ( interior[i].intersects( gmo ) ) {
168 inter = true;
169 break;
170 }
171 }
172 }
173 }
174
175 return inter;
176 }
177
178 @Override
179 public boolean contains( Geometry gmo ) {
180 boolean con = false;
181
182 con = exterior.contains( gmo );
183
184 if ( con ) {
185 if ( interior != null ) {
186 for ( int i = 0; i < interior.length; i++ ) {
187 Position[] pos = interior[i].getPositions();
188 for ( int j = 0; j < pos.length / 2; j++ ) {
189 Position p = pos[j];
190 pos[j] = pos[pos.length - j - 1];
191 pos[pos.length - j - 1] = p;
192 }
193 Ring ring = null;
194 try {
195 ring = new RingImpl( pos, getCoordinateSystem() );
196 } catch ( GeometryException e ) {
197 e.printStackTrace();
198 }
199 if ( ring.intersects( gmo ) || ring.contains( gmo ) ) {
200 con = false;
201 break;
202 }
203 }
204 }
205 }
206
207 return con;
208 }
209
210 /**
211 * The Boolean valued operation "contains" shall return TRUE if this Geometry contains a single point given by a
212 * coordinate.
213 * <p>
214 * </p>
215 * dummy implementation
216 */
217 @Override
218 public boolean contains( Position position ) {
219 return contains( new PointImpl( position, null ) );
220 }
221
222 /**
223 * calculates the envelope of the surface boundary
224 */
225 private void calculateEnvelope() {
226 envelope = (Envelope) ( (EnvelopeImpl) exterior.getEnvelope() ).clone();
227 }
228
229 /**
230 * calculates the centroid of the surface boundary
231 */
232 private void calculateCentroid() {
233 try {
234 double[] cen = exterior.getCentroid().getAsArray().clone();
235 double cnt = exterior.getAsCurveSegment().getNumberOfPoints();
236
237 for ( int i = 0; i < cen.length; i++ ) {
238 cen[i] *= cnt;
239 }
240
241 if ( interior != null ) {
242 for ( int i = 0; i < interior.length; i++ ) {
243 double[] pos = interior[i].getCentroid().getAsArray();
244 cnt += interior[i].getAsCurveSegment().getNumberOfPoints();
245
246 for ( int j = 0; j < pos.length; j++ ) {
247 cen[j] += ( pos[j] * interior[i].getAsCurveSegment().getNumberOfPoints() );
248 }
249 }
250 }
251
252 for ( int j = 0; j < cen.length; j++ ) {
253 cen[j] /= cnt;
254 }
255
256 centroid = new PositionImpl( cen );
257 } catch ( Exception ex ) {
258 LOG.logError( "", ex );
259 }
260 }
261
262 @Override
263 protected void calculateParam() {
264 calculateEnvelope();
265 calculateCentroid();
266 setValid( true );
267 }
268
269 @Override
270 public String toString() {
271 String ret = null;
272 ret = "interior = " + interior + "\n";
273 ret += ( "exterior = " + exterior + "\n" );
274 return ret;
275 }
276 }