/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2006-2008, Open Source Geospatial Foundation (OSGeo) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. */ package org.geotools.geometry.iso.primitive; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Set; import org.geotools.geometry.iso.complex.CompositeCurveImpl; import org.geotools.geometry.iso.coordinate.DirectPositionImpl; import org.geotools.geometry.iso.coordinate.GeometryFactoryImpl; import org.geotools.geometry.iso.coordinate.LineStringImpl; import org.geotools.geometry.iso.io.GeometryToString; import org.geotools.geometry.iso.operation.IsSimpleOp; import org.opengis.geometry.DirectPosition; import org.opengis.geometry.Geometry; import org.opengis.geometry.MismatchedDimensionException; import org.opengis.geometry.complex.Complex; import org.opengis.geometry.coordinate.GeometryFactory; import org.opengis.geometry.coordinate.LineSegment; import org.opengis.geometry.coordinate.LineString; import org.opengis.geometry.coordinate.Position; import org.opengis.geometry.primitive.Curve; import org.opengis.geometry.primitive.CurveBoundary; import org.opengis.geometry.primitive.CurveSegment; import org.opengis.geometry.primitive.OrientableCurve; import org.opengis.geometry.primitive.Primitive; import org.opengis.geometry.primitive.PrimitiveFactory; import org.opengis.geometry.primitive.Ring; import org.opengis.referencing.crs.CoordinateReferenceSystem; import org.opengis.referencing.operation.MathTransform; import org.opengis.referencing.operation.TransformException; /** * This Ring implementation does not do a consistency * check. This Ring should only be used when the user knows the Ring is valid and doesn't * want to spend the expensive processing time to validate it upon creation. Otherwise, * RingImpl should be used which will validate when it is created. * * @author Graham Davis * * @source $URL$ */ public class RingImplUnsafe extends CompositeCurveImpl implements Ring { private SurfaceBoundaryImpl surfaceBoundary; /** * Creates a Ring * @param generator */ public RingImplUnsafe(List<OrientableCurve> generator) { super(generator); } /* (non-Javadoc) * @see org.geotools.geometry.featgeom.complex.CompositeCurveImpl#clone() */ public RingImplUnsafe clone() throws CloneNotSupportedException { // Test OK Iterator<Primitive> elementIter = this.getElements().iterator(); List<OrientableCurve> newElements = new ArrayList<OrientableCurve>(); while (elementIter.hasNext()) { newElements.add((Curve) elementIter.next().clone()); } return new RingImplUnsafe(newElements); } /* (non-Javadoc) * @see org.geotools.geometry.featgeom.complex.CompositeCurveImpl#getBoundary() */ public CurveBoundary getBoundary() { // A Ring does not have a Boundary since it´s start and end points are equal. return null; } /* (non-Javadoc) * @see org.geotools.geometry.featgeom.complex.CompositeCurveImpl#createBoundary() */ public Set<Complex> createBoundary() { // overwrites the boundary definition of CompositeCurve // returns null, cause a Ring does not have a boundary return null; } /** * @return Returns the surfaceBoundary. */ public SurfaceBoundaryImpl getSurfaceBoundary() { return surfaceBoundary; } /** * @param surfaceBoundary * The surfaceBoundary to set. */ public void setSurfaceBoundary(SurfaceBoundaryImpl surfaceBoundary) { this.surfaceBoundary = surfaceBoundary; } /* * (non-Javadoc) * * @see org.geotools.geometry.featgeom.complex.CompositeCurveImpl#isSimple() */ public boolean isSimple() { // Implementation ok // A Ring is always simple return true; } /* * (non-Javadoc) * * @see org.geotools.geometry.featgeom.complex.CompositeCurveImpl#isCycle() */ public boolean isCycle() { // Implementation ok // A Ring is always a cycle return true; } /** * @return */ public List<DirectPosition> asDirectPositions() { List<DirectPosition> rList = new ArrayList<DirectPosition>(); // Iterate all Curves for (int i = 0; i < this.elements.size(); i++) { CurveImpl tCurve = (CurveImpl) this.elements.get(i); Iterator<CurveSegment> tCurveSegmentIter = tCurve.getSegments() .iterator(); CurveSegment tSegment = null; // Iterate all CurveSegments (= LineStrings) while (tCurveSegmentIter.hasNext()) { tSegment = tCurveSegmentIter.next(); // TODO: This version only handles the CurveSegment type // LineString LineStringImpl tLineString = (LineStringImpl) tSegment; Iterator<LineSegment> tLineSegmentIter = tLineString .asLineSegments().iterator(); while (tLineSegmentIter.hasNext()) { LineSegment tLineSegment = tLineSegmentIter.next(); // Add new Coordinate, which is the start point of the // actual LineSegment rList.add( tLineSegment.getStartPoint()); } } // Add new Coordinate, which is the end point of the last // curveSegment rList.add( tSegment.getEndPoint()); } return rList; } /* (non-Javadoc) * @see org.opengis.geometry.coordinate.#getRepresentativePoint() */ public DirectPosition getRepresentativePoint() { // Return the start point of this ring, since it is part of the object return ((CurveImpl)this.getGenerators().get(0)).getStartPoint(); } /* (non-Javadoc) * @see org.geotools.geometry.featgeom.complex.CompositeCurveImpl#toString() */ public String toString() { return GeometryToString.getString(this); } @Override public int hashCode() { final int PRIME = 31; int result = 1; result = PRIME * result + ((surfaceBoundary == null) ? 0 : surfaceBoundary.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; final RingImplUnsafe other = (RingImplUnsafe) obj; if (surfaceBoundary == null) { if (other.surfaceBoundary != null) return false; } else if (!surfaceBoundary.equals(other.surfaceBoundary)) return false; return true; } /* * (non-Javadoc) * * @see org.opengis.geometry.coordinate.root.Geometry#transform(org.opengis.referencing.crs.CoordinateReferenceSystem, * org.opengis.referencing.operation.MathTransform) */ public Geometry transform(CoordinateReferenceSystem newCRS, MathTransform transform) throws MismatchedDimensionException, TransformException { // loop through each point in this Ring and transform it to the new CRS, then // use the new points to build a new Ring and return that. PrimitiveFactory primitiveFactory = new PrimitiveFactoryImpl(newCRS, getPositionFactory()); GeometryFactory geometryFactory = new GeometryFactoryImpl(newCRS, getPositionFactory()); DirectPositionImpl dp1 = null; List<DirectPosition> currentpositions = this.asDirectPositions(); Iterator<DirectPosition> iter = currentpositions.iterator(); List<Position> newpositions = new ArrayList<Position>(); while (iter.hasNext()) { DirectPosition thispos = (DirectPosition) iter.next(); dp1 = new DirectPositionImpl(newCRS); dp1 = (DirectPositionImpl) transform.transform( thispos, dp1); newpositions.add(dp1); } // use the new positions list to build a new Ring and return it LineString lineString = geometryFactory.createLineString(newpositions); List curveSegmentList = Collections.singletonList(lineString); CurveImpl newCurve = (CurveImpl) primitiveFactory.createCurve(curveSegmentList); ArrayList<OrientableCurve> curveList = new ArrayList<OrientableCurve>(); curveList.add(newCurve); Ring newRing = primitiveFactory.createRing(curveList); return newRing; } }