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