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