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