001 //$HeadURL: svn+ssh://jwilden@svn.wald.intevation.org/deegree/base/branches/2.5_testing/src/org/deegree/model/spatialschema/RingImpl.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 import org.deegree.model.crs.CoordinateSystem; 044 045 /** 046 * default implementation of the Ring interface of the 047 * 048 * 049 * @version $Revision: 18195 $ 050 * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a> 051 * @author last edited by: $Author: mschneider $ 052 * 053 * @version 1.0. $Revision: 18195 $, $Date: 2009-06-18 17:55:39 +0200 (Do, 18 Jun 2009) $ 054 * 055 * @since 2.0 056 */ 057 public class RingImpl extends OrientableCurveImpl implements Ring, Serializable { 058 /** Use serialVersionUID for interoperability. */ 059 private final static long serialVersionUID = 9157144642050604928L; 060 061 private static final ILogger LOG = LoggerFactory.getLogger( RingImpl.class ); 062 063 private CurveSegment[] segments; 064 065 private SurfacePatch sp = null; 066 067 private int nop = 0; 068 069 private Position[] allPos; 070 071 /** 072 * Constructor, with an array and CoordinateSystem 073 * 074 * @param points 075 * @param crs 076 * @throws GeometryException 077 */ 078 protected RingImpl( Position[] points, CoordinateSystem crs ) throws GeometryException { 079 super( crs ); 080 Position[][] tmp = new Position[1][]; 081 tmp[0] = points; 082 setPositions( tmp ); 083 } 084 085 /** 086 * Constructor, with an array, CoordinateSystem and Orientation 087 * 088 * @param points 089 * @param crs 090 * @param orientation 091 * @throws GeometryException 092 */ 093 protected RingImpl( Position[] points, CoordinateSystem crs, char orientation ) throws GeometryException { 094 super( crs, orientation ); 095 Position[][] tmp = new Position[1][]; 096 tmp[0] = points; 097 setPositions( tmp ); 098 } 099 100 /** 101 * Constructor, with curve segments, CoordinateSystem and Orientation 102 * 103 * @param segments 104 * @param crs 105 * @param orientation 106 * @throws GeometryException 107 */ 108 protected RingImpl( CurveSegment[] segments, CoordinateSystem crs, char orientation ) throws GeometryException { 109 super( crs, orientation ); 110 Position[][] tmp = new Position[segments.length][]; 111 for ( int i = 0; i < segments.length; i++ ) { 112 tmp[i] = segments[i].getPositions(); 113 } 114 setPositions( tmp ); 115 } 116 117 /** 118 * calculates the envelope 119 */ 120 private void calculateEnvelope() { 121 double[] min = allPos[0].getAsArray().clone(); 122 double[] max = min.clone(); 123 124 for ( int k = 1; k < allPos.length; k++ ) { 125 double[] pos = allPos[k].getAsArray(); 126 127 for ( int j = 0; j < pos.length; j++ ) { 128 if ( pos[j] < min[j] ) { 129 min[j] = pos[j]; 130 } else if ( pos[j] > max[j] ) { 131 max[j] = pos[j]; 132 } 133 } 134 } 135 136 envelope = new EnvelopeImpl( new PositionImpl( min ), new PositionImpl( max ), this.crs ); 137 } 138 139 /** 140 * Ring must be closed, so isCycle returns TRUE. 141 */ 142 public boolean isCycle() { 143 return true; 144 } 145 146 /** 147 * Ring is a PrimitiveBoundary, so isSimple returns TRUE. 148 */ 149 public boolean isSimple() { 150 return true; 151 } 152 153 /** 154 * The operation "dimension" shall return the inherent dimension of this Geometry, which shall be less than or equal 155 * to the coordinate dimension. The dimension of a collection of geometric objects shall be the largest dimension of 156 * any of its pieces. Points are 0-dimensional, curves are 1-dimensional, surfaces are 2-dimensional, and solids are 157 * 3-dimensional. 158 */ 159 public int getDimension() { 160 return 1; 161 } 162 163 /** 164 * The operation "coordinateDimension" shall return the dimension of the coordinates that define this Geometry, 165 * which must be the same as the coordinate dimension of the coordinate reference system for this Geometry. 166 */ 167 public int getCoordinateDimension() { 168 return getPositions()[0].getCoordinateDimension(); 169 } 170 171 /** 172 * gets the Ring as a Array of positions. 173 */ 174 public Position[] getPositions() { 175 if ( getOrientation() == '-' ) { 176 Position[] temp = new Position[allPos.length]; 177 178 for ( int i = 0; i < allPos.length; i++ ) { 179 temp[i] = allPos[( allPos.length - 1 ) - i]; 180 } 181 182 return temp; 183 } 184 return allPos; 185 } 186 187 /** 188 * sets the Ring as a ArrayList of points 189 * 190 * @param positions 191 * @throws GeometryException 192 */ 193 protected void setPositions( Position[][] positions ) 194 throws GeometryException { 195 196 segments = new CurveSegment[positions.length]; 197 for ( int i = 0; i < positions.length; i++ ) { 198 segments[i] = new LineStringImpl( positions[i], getCoordinateSystem() ); 199 } 200 201 nop = 0; 202 for ( int i = 0; i < positions.length; i++ ) { 203 nop += positions[i].length; 204 } 205 allPos = new Position[nop]; 206 int k = 0; 207 for ( int i = 0; i < positions.length; i++ ) { 208 for ( int j = 0; j < positions[i].length; j++ ) { 209 allPos[k++] = positions[i][j]; 210 } 211 } 212 213 // checks if the ring has more than 3 elements [!(points.length > 3)] 214 if ( nop < 3 ) { 215 throw new GeometryException( "invalid length of a Ring!" ); 216 } 217 218 // checks if the startpoint = endpoint of the ring 219 if ( !allPos[0].equals( allPos[allPos.length - 1] ) ) { 220 throw new GeometryException( "StartPoint of ring isn't equal to EndPoint!" ); 221 } 222 223 setValid( false ); 224 } 225 226 /** 227 * returns the Ring as one CurveSegment 228 */ 229 public CurveSegment getAsCurveSegment() 230 throws GeometryException { 231 return new LineStringImpl( allPos, getCoordinateSystem() ); 232 } 233 234 /** 235 * returns the Ring as a CurveSegments 236 * 237 * @return curve segments 238 */ 239 public CurveSegment[] getCurveSegments() { 240 return segments; 241 } 242 243 /** 244 * returns the CurveBoundary of the Ring. For a CurveBoundary is defines as the first and the last point of a Curve 245 * the CurveBoundary of a Ring contains two indentical point (because a Ring is closed) 246 */ 247 public CurveBoundary getCurveBoundary() { 248 return (CurveBoundary) boundary; 249 } 250 251 @Override 252 public boolean equals( Object other ) { 253 if ( !super.equals( other ) || !( other instanceof RingImpl ) ) { 254 return false; 255 } 256 257 if ( !envelope.equals( ( (Geometry) other ).getEnvelope() ) ) { 258 return false; 259 } 260 261 Position[] p2 = ( (Ring) other ).getPositions(); 262 263 if ( !Arrays.equals( allPos, p2 ) ) { 264 return false; 265 } 266 267 return true; 268 } 269 270 @Override 271 public Object clone() { 272 Ring r = null; 273 try { 274 CurveSegment[] segments = getCurveSegments(); 275 for ( int i = 0; i < segments.length; i++ ) { 276 segments[i] = new LineStringImpl( segments[i].getPositions(), getCoordinateSystem() ); 277 } 278 r = new RingImpl( segments, getCoordinateSystem(), getOrientation() ); 279 } catch ( Exception ex ) { 280 LOG.logError( ex.getMessage(), ex ); 281 } 282 283 return r; 284 } 285 286 @Override 287 public boolean intersects( Geometry gmo ) { 288 boolean inter = false; 289 290 try { 291 // TODO 292 // use segments 293 CurveSegment sp = new LineStringImpl( allPos, crs ); 294 295 if ( gmo instanceof Point ) { 296 double tolerance = ( (Point) gmo ).getTolerance(); 297 inter = LinearIntersects.intersects( ( (Point) gmo ).getPosition(), sp, tolerance ); 298 } else if ( gmo instanceof Curve ) { 299 Curve curve = new CurveImpl( new CurveSegment[] { sp } ); 300 inter = LinearIntersects.intersects( (Curve) gmo, curve ); 301 } else if ( gmo instanceof Surface ) { 302 Curve curve = new CurveImpl( new CurveSegment[] { sp } ); 303 inter = LinearIntersects.intersects( curve, (Surface) gmo ); 304 } else if ( gmo instanceof MultiPrimitive ) { 305 inter = intersectsAggregate( (MultiPrimitive) gmo ); 306 } 307 } catch ( Exception e ) { 308 LOG.logError( e.getMessage(), e ); 309 } 310 311 return inter; 312 } 313 314 /** 315 * the operations returns true if the submitted multi primitive intersects with the curve segment 316 */ 317 private boolean intersectsAggregate( Aggregate mprim ) 318 throws Exception { 319 boolean inter = false; 320 321 int cnt = mprim.getSize(); 322 323 for ( int i = 0; i < cnt; i++ ) { 324 if ( intersects( mprim.getObjectAt( i ) ) ) { 325 inter = true; 326 break; 327 } 328 } 329 330 return inter; 331 } 332 333 /** 334 * The Boolean valued operation "contains" shall return TRUE if this Geometry contains another Geometry. 335 * <p> 336 * </p> 337 * At the moment the operation just works with point geometries 338 */ 339 @Override 340 public boolean contains( Geometry gmo ) { 341 342 try { 343 if ( sp == null ) { 344 sp = new PolygonImpl( new SurfaceInterpolationImpl(), allPos, null, crs ); 345 } 346 return sp.contains( gmo ); 347 } catch ( Exception e ) { 348 LOG.logError( e.getMessage(), e ); 349 } 350 351 return false; 352 } 353 354 @Override 355 public boolean contains( Position position ) { 356 return contains( new PointImpl( position, null ) ); 357 } 358 359 /** 360 * calculates the centroid of the ring 361 */ 362 protected void calculateCentroid() { 363 double[] cen = new double[getCoordinateDimension()]; 364 365 for ( int k = 0; k < allPos.length; k++ ) { 366 for ( int j = 0; j < getCoordinateDimension(); j++ ) { 367 cen[j] += ( allPos[k].getAsArray()[j] / allPos.length ); 368 } 369 } 370 371 centroid = new PointImpl( new PositionImpl( cen ), crs ); 372 } 373 374 @Override 375 protected void calculateParam() { 376 calculateCentroid(); 377 calculateEnvelope(); 378 setValid( true ); 379 } 380 381 @Override 382 public String toString() { 383 String ret = null; 384 ret = "segements = " + segments.length + "\n"; 385 ret += ( "envelope = " + envelope + "\n" ); 386 return ret; 387 } 388 }