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