001 //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/branches/2.2_testing/src/org/deegree/model/spatialschema/CurveImpl.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.ArrayList; 048 049 import org.deegree.framework.log.ILogger; 050 import org.deegree.framework.log.LoggerFactory; 051 import org.deegree.model.crs.CoordinateSystem; 052 053 /** 054 * default implementation of 055 * 056 * @see org.deegree.model.spatialschema.Curve 057 * 058 * @author Andreas Poth 059 * @version $Revision: 9343 $ $Date: 2007-12-27 14:30:32 +0100 (Do, 27 Dez 2007) $ 060 */ 061 class CurveImpl extends OrientableCurveImpl implements Curve, GenericCurve, Serializable { 062 063 private static final ILogger LOG = LoggerFactory.getLogger( CurveImpl.class ); 064 065 /** Use serialVersionUID for interoperability. */ 066 private final static long serialVersionUID = 4060425075179654976L; 067 068 protected ArrayList<CurveSegment> segments = null; 069 070 /** 071 * initialize the curve by submitting a spatial reference system and an array of curve segments. 072 * the orientation of the curve is '+' 073 * 074 * @param segments 075 * array of CurveSegment 076 */ 077 public CurveImpl( CurveSegment segments ) throws GeometryException { 078 this( '+', new CurveSegment[] { segments } ); 079 } 080 081 /** 082 * initialize the curve by submitting a spatial reference system and an array of curve segments. 083 * the orientation of the curve is '+' 084 * 085 * @param segments 086 * array of CurveSegment 087 */ 088 public CurveImpl( CurveSegment[] segments ) throws GeometryException { 089 this( '+', segments ); 090 } 091 092 /** 093 * initialize the curve by submitting a spatial reference system and an array of curve segments. 094 * the orientation of the curve is '+' 095 * 096 * @param segments 097 * array of CurveSegment 098 * @param crs 099 */ 100 public CurveImpl( CurveSegment[] segments, CoordinateSystem crs ) throws GeometryException { 101 this( '+', segments ); 102 this.crs = crs; 103 } 104 105 /** 106 * initialize the curve by submitting a spatial reference system, an array of curve segments and 107 * the orientation of the curve 108 * 109 * @param segments 110 * array of CurveSegment 111 * @param orientation 112 * of the curve 113 */ 114 public CurveImpl( char orientation, CurveSegment[] segments ) throws GeometryException { 115 super( segments[0].getCoordinateSystem(), orientation ); 116 117 this.segments = new ArrayList<CurveSegment>( segments.length ); 118 119 if ( segments != null ) { 120 for ( int i = 0; i < segments.length; i++ ) { 121 this.segments.add( segments[i] ); 122 // TODO 123 // check if segments touch 124 if ( i > 0 ) { 125 if ( !segments[i - 1].getEndPoint().equals( segments[i].getStartPoint() ) ) { 126 throw new GeometryException( "end-point of segment[i-1] " 127 + "doesn't match start-point of segment[i]!" ); 128 } 129 } 130 } 131 } 132 133 setValid( false ); 134 } 135 136 /** 137 * calculates the envelope of the Curve 138 */ 139 private void calculateEnvelope() { 140 try { 141 Position[] positions = getAsLineString().getPositions(); 142 143 double[] min = positions[0].getAsArray().clone(); 144 double[] max = min.clone(); 145 146 for ( int i = 1; i < positions.length; i++ ) { 147 double[] pos = positions[i].getAsArray(); 148 149 for ( int j = 0; j < pos.length; j++ ) { 150 if ( pos[j] < min[j] ) { 151 min[j] = pos[j]; 152 } else if ( pos[j] > max[j] ) { 153 max[j] = pos[j]; 154 } 155 } 156 } 157 158 envelope = new EnvelopeImpl( new PositionImpl( min ), new PositionImpl( max ), this.crs ); 159 } catch ( GeometryException e ) { 160 } 161 } 162 163 /** 164 * calculates the boundary of the Curve 165 */ 166 private void calculateBoundary() { 167 boundary = new CurveBoundaryImpl( getCoordinateSystem(), getStartPoint().getPosition(), 168 getEndPoint().getPosition() ); 169 } 170 171 /** 172 * calculates the centroid of the Curve 173 */ 174 private void calculateCentroid() { 175 try { 176 Position[] positions = getAsLineString().getPositions(); 177 178 double[] cen = new double[positions[0].getAsArray().length]; 179 180 for ( int i = 0; i < positions.length; i++ ) { 181 double[] pos = positions[i].getAsArray(); 182 183 for ( int j = 0; j < pos.length; j++ ) { 184 cen[j] += ( pos[j] / positions.length ); 185 } 186 } 187 188 centroid = new PointImpl( new PositionImpl( cen ), null ); 189 } catch ( Exception e ) { 190 } 191 } 192 193 /** 194 * 195 */ 196 protected void calculateParam() { 197 calculateCentroid(); 198 calculateEnvelope(); 199 calculateBoundary(); 200 setValid( true ); 201 } 202 203 /** 204 * returns the boundary of the curve 205 */ 206 public CurveBoundary getCurveBoundary() { 207 return (CurveBoundary) boundary; 208 } 209 210 /** 211 * The operation "dimension" shall return the inherent dimension of this Geometry, which shall 212 * be less than or equal to the coordinate dimension. The dimension of a collection of geometric 213 * objects shall be the largest dimension of any of its pieces. Points are 0-dimensional, curves 214 * are 1-dimensional, surfaces are 2-dimensional, and solids are 3-dimensional. 215 */ 216 public int getDimension() { 217 return 1; 218 } 219 220 /** 221 * The operation "coordinateDimension" shall return the dimension of the coordinates that define 222 * this Geometry, which must be the same as the coordinate dimension of the coordinate reference 223 * system for this Geometry. 224 */ 225 public int getCoordinateDimension() { 226 return getStartPoint().getPosition().getCoordinateDimension(); 227 } 228 229 /** 230 * The Boolean valued operation "intersects" shall return TRUE if this Geometry intersects 231 * another Geometry. Within a Complex, the Primitives do not intersect one another. In general, 232 * topologically structured data uses shared geometric objects to capture intersection 233 * information. 234 * <p> 235 * </p> 236 * dummy implementation 237 */ 238 public boolean intersects( Geometry gmo ) { 239 boolean inter = false; 240 241 try { 242 for ( int i = 0; i < segments.size(); i++ ) { 243 CurveSegment cs = getCurveSegmentAt( i ); 244 245 if ( cs.intersects( gmo ) ) { 246 inter = true; 247 break; 248 } 249 } 250 } catch ( Exception e ) { 251 LOG.logError( "", e ); 252 } 253 254 return inter; 255 } 256 257 /** 258 * returns the length of the curve in units of the related spatial reference system 259 */ 260 public double getLength() { 261 return -1; 262 } 263 264 /** 265 * returns the number of segments building the curve 266 */ 267 public int getNumberOfCurveSegments() { 268 return segments.size(); 269 } 270 271 /** 272 * returns the first point of the curve. if the curve doesn't contain a segment or the first 273 * segment doesn't contain a point null will be returned 274 */ 275 public Point getStartPoint() { 276 if ( getNumberOfCurveSegments() == 0 ) { 277 return null; 278 } 279 280 Point gmp = null; 281 282 try { 283 gmp = getCurveSegmentAt( 0 ).getStartPoint(); 284 } catch ( GeometryException e ) { 285 LOG.logError( "", e ); 286 } 287 288 return gmp; 289 } 290 291 /** 292 * returns the last point of the curve.if the curve doesn't contain a segment or the last 293 * segment doesn't contain a point null will be returned 294 */ 295 public Point getEndPoint() { 296 if ( getNumberOfCurveSegments() == 0 ) { 297 return null; 298 } 299 300 Point gmp = null; 301 302 try { 303 gmp = getCurveSegmentAt( getNumberOfCurveSegments() - 1 ).getEndPoint(); 304 } catch ( GeometryException e ) { 305 LOG.logError( "", e ); 306 } 307 308 return gmp; 309 } 310 311 /** 312 * returns the curve as LineString. if there isn't a curve segment within the curve null will be 313 * returned 314 */ 315 public LineString getAsLineString() 316 throws GeometryException { 317 if ( getNumberOfCurveSegments() == 0 ) { 318 return null; 319 } 320 321 Position[] tmp = null; 322 323 // normal orientaton 324 if ( getOrientation() == '+' ) { 325 int cnt = 0; 326 327 for ( int i = 0; i < getNumberOfCurveSegments(); i++ ) { 328 cnt += getCurveSegmentAt( i ).getNumberOfPoints(); 329 } 330 331 tmp = new Position[cnt]; 332 333 int k = 0; 334 335 for ( int i = 0; i < getNumberOfCurveSegments(); i++ ) { 336 Position[] gmps = getCurveSegmentAt( i ).getPositions(); 337 338 for ( int j = 0; j < gmps.length; j++ ) { 339 tmp[k++] = gmps[j]; 340 } 341 } 342 } else { 343 // inverse orientation 344 int cnt = 0; 345 346 for ( int i = getNumberOfCurveSegments() - 1; i >= 0; i-- ) { 347 cnt += getCurveSegmentAt( i ).getNumberOfPoints(); 348 } 349 350 tmp = new Position[cnt]; 351 352 int k = 0; 353 354 for ( int i = getNumberOfCurveSegments() - 1; i >= 0; i-- ) { 355 Position[] gmps = getCurveSegmentAt( i ).getPositions(); 356 357 for ( int j = gmps.length - 1; j >= 0; j-- ) { 358 tmp[k++] = gmps[j]; 359 } 360 } 361 } 362 363 return new LineStringImpl( tmp, this.crs ); 364 } 365 366 /** 367 * returns the curve segment at the submitted index 368 * 369 * @param index 370 * index of the curve segment that should be returned 371 * @exception GeometryException 372 * a exception will be thrown if <tt>index</tt> is smaller than '0' or larger 373 * than <tt>getNumberOfCurveSegments()-1</tt> 374 */ 375 public CurveSegment getCurveSegmentAt( int index ) 376 throws GeometryException { 377 if ( ( index < 0 ) || ( index > getNumberOfCurveSegments() - 1 ) ) { 378 throw new GeometryException( "invalid index/position to get a segment!" ); 379 } 380 381 return segments.get( index ); 382 } 383 384 /** 385 * 386 * @return all segments of a Curve 387 * @throws GeometryException 388 */ 389 public CurveSegment[] getCurveSegments() 390 throws GeometryException { 391 return segments.toArray( new CurveSegment[segments.size()] ); 392 } 393 394 /** 395 * returns true if no segment is within the curve 396 */ 397 public boolean isEmpty() { 398 return ( getNumberOfCurveSegments() == 0 ); 399 } 400 401 /** 402 * translate each point of the curve with the values of the submitted double array. 403 */ 404 public void translate( double[] d ) { 405 try { 406 for ( int i = 0; i < segments.size(); i++ ) { 407 Position[] pos = getCurveSegmentAt( i ).getPositions(); 408 409 for ( int j = 0; j < pos.length; j++ ) { 410 pos[j].translate( d ); 411 } 412 } 413 } catch ( Exception e ) { 414 } 415 setValid( false ); 416 } 417 418 /** 419 * checks if this curve is completly equal to the submitted geometry 420 * 421 * @param other 422 * object to compare to 423 */ 424 public boolean equals( Object other ) { 425 if ( envelope == null ) { 426 calculateEnvelope(); 427 } 428 if ( !super.equals( other ) ) { 429 return false; 430 } 431 432 if ( !( other instanceof CurveImpl ) ) { 433 return false; 434 } 435 436 if ( !envelope.equals( ( (Geometry) other ).getEnvelope() ) ) { 437 return false; 438 } 439 440 if ( segments.size() != ( (Curve) other ).getNumberOfCurveSegments() ) { 441 return false; 442 } 443 444 try { 445 for ( int i = 0; i < segments.size(); i++ ) { 446 if ( !getCurveSegmentAt( i ).equals( ( (Curve) other ).getCurveSegmentAt( i ) ) ) { 447 return false; 448 } 449 } 450 } catch ( Exception e ) { 451 return false; 452 } 453 454 return true; 455 } 456 457 /** 458 * returns a shallow copy of the geometry 459 */ 460 public Object clone() { 461 Curve c = null; 462 463 try { 464 CurveSegment[] cs = null; 465 cs = segments.toArray( new CurveSegment[getNumberOfCurveSegments()] ); 466 c = new CurveImpl( getOrientation(), cs ); 467 } catch ( Exception ex ) { 468 LOG.logError( "Curve_Impl.clone: ", ex ); 469 } 470 471 return c; 472 } 473 474 /** 475 * 476 * 477 * @return 478 */ 479 public String toString() { 480 String ret = null; 481 ret = "segments = " + segments + "\n"; 482 ret += ( "envelope = " + envelope + "\n" ); 483 return ret; 484 } 485 }