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 }