/*$************************************************************************************************ ** ** $Id$ ** ** $Source: /cvs/ctree/LiteGO1/src/jar/com/polexis/lite/spatialschema/geometry/primitive/CurveImpl.java,v $ ** ** Copyright (C) 2003 Open GIS Consortium, Inc. All Rights Reserved. http://www.opengis.org/Legal/ ** *************************************************************************************************/ package org.geotools.geometry.jts.spatialschema.geometry.primitive; // J2SE direct dependencies import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Set; import org.opengis.referencing.crs.CoordinateReferenceSystem; import org.opengis.geometry.DirectPosition; import org.opengis.geometry.complex.CompositeCurve; import org.opengis.geometry.coordinate.LineString; import org.opengis.geometry.coordinate.ParamForPoint; import org.opengis.geometry.coordinate.Position; import org.opengis.geometry.primitive.Curve; import org.opengis.geometry.primitive.CurveSegment; import org.opengis.geometry.primitive.OrientableCurve; import org.geotools.geometry.jts.spatialschema.geometry.NotifyingArrayList; import org.geotools.geometry.jts.spatialschema.geometry.GeometryImpl; import org.geotools.geometry.jts.spatialschema.geometry.geometry.LineStringImpl; import org.geotools.geometry.jts.JTSGeometry; import org.geotools.geometry.jts.JTSUtils; import org.opengis.geometry.primitive.CurveBoundary; /** * Simple implementation of the Curve interface that does not implement any * of the (hard) math functions like intersection, etc. A curve consists of * any number of CurveSegment objects (such as LineStrings) that must be * connected end-to-end. * * * * @source $URL$ */ public class CurveImpl extends GeometryImpl implements Curve { /** * Component parts of the Curve. Each element must implement CurveSegment. */ private List curveSegments; //************************************************************************* // constructors //************************************************************************* /** * Creates a new {@code CurveImpl}. */ public CurveImpl() { this(null); } /** * Creates a new {@code CurveImpl}. * @param crs */ public CurveImpl(final CoordinateReferenceSystem crs) { super(crs); curveSegments = new NotifyingArrayList(this); } //************************************************************************* // //************************************************************************* public CurveBoundary getBoundary() { return (CurveBoundary) super.getBoundary(); } /** * @inheritDoc * @see org.opengis.geometry.primitive.Curve#getSegments() */ public final List<CurveSegment> getSegments() { return curveSegments; } /** * @inheritDoc * @see org.opengis.geometry.coordinate.GenericCurve#getStartPoint() */ public final DirectPosition getStartPoint() { return ((CurveSegment) curveSegments.get(0)).getStartPoint(); } /** * @inheritDoc * @see org.opengis.geometry.coordinate.GenericCurve#getEndPoint() */ public final DirectPosition getEndPoint() { return ((CurveSegment) curveSegments.get(curveSegments.size()-1)).getEndPoint(); } /** * @inheritDoc * @see org.opengis.geometry.coordinate.GenericCurve#getTangent(double) */ public double [] getTangent(double s) { // PENDING(CSD): Implement me! return new double[0]; } public final double getStartParam() { return 0.0; } public final double getEndParam() { return this.length(0, getEndConstructiveParam()); } public final double getStartConstructiveParam() { return 0.0; } public final double getEndConstructiveParam() { return curveSegments.size(); } // We choose to parameterize the curve as a function from the interval // [0, n] to R_n, where interval [i, i+1] corresponds to curve i, and // the in between points are mapped linearly between the constructive params // of curve i, i.e. C(i+d) = C_i((1-d)*scp + d*ecp), 0 <= d < 1, scp is the // start constructive param of curve segment i, ecp is the end constructive // param of curve segment i. public final DirectPosition forConstructiveParam(double cp) { int n = curveSegments.size(); int i = (int) cp; if (i < 0) { i = 0; } else if (i > n) { i = n; } if (i == n) { return ((CurveSegment) curveSegments.get(n-1)).getEndPoint(); } else { CurveSegment cs = (CurveSegment) curveSegments.get(i); double d = cp - i; // 0 <= d < 1 return cs.forConstructiveParam( (1-d) * cs.getStartConstructiveParam() + d * cs.getEndConstructiveParam()); } } public final DirectPosition forParam(double s) { return null; } /** * Not implemented. Always just returns null. */ public ParamForPoint getParamForPoint(DirectPosition p) { return null; } /** * Not implemented. Always returns zero. */ public double length(Position point1, Position point2) { return 0.0; } /** * Not implemented. Always returns 0. * This wouldn't be hard to implement, though. You'd just sum over the * CurveSegments that comprise this object. */ public double length(double cparam1, double cparam2) { return 0.0; } /** * Not fully implemented. Returns null, unless all CurveSegments are LineStrings, * in which case it returns a concatenation of all the LineStrings. * In future versions this could be implemented by delegating to the comprising segments. */ public LineString asLineString(double maxSpacing, double maxOffset) { int count = curveSegments.size(); if (count == 1) { Object segment1 = curveSegments.get(0); if (segment1 instanceof LineString) { return (LineString) segment1; } } else if (count > 0) { boolean allLineString = true; LineStringImpl lsi = new LineStringImpl(); LineString ls = null; List retList = lsi.getControlPoints(); Object lastPoint = null; List segList = null; for (int i = 0; i < count && allLineString; i++) { Object segment = curveSegments.get(0); if (segment instanceof LineString) { segList = ((LineString) segment).getControlPoints(); if (segList.get(0).equals(lastPoint)) { retList.remove(retList.size() - 1); } retList.addAll(segList); lastPoint = retList.get(retList.size() - 1); } else { allLineString = false; } } if (allLineString) { return lsi; } } return null; } /** * Returns null. */ public CompositeCurve getComposite() { return null; } public int getOrientation() { return +1; } /** * Returns "this". Should return the containing primitive, if any. */ public Curve getPrimitive() { return this; } /** * Not implemented. Always returns an empty set. */ public Set getContainedPrimitives() { return Collections.EMPTY_SET; } /** * Not implemented (and probably never will be since traversal of this * association would require a lot of extra work). Always returns an * empty set. */ public Set getContainingPrimitives() { return Collections.EMPTY_SET; } /** * Not implemented (and probably never will be since traversal of this * association would require a lot of extra work). Always returns an * empty set. */ public Set getComplexes() { return Collections.EMPTY_SET; } /** * Not implemented. Returns null. */ public OrientableCurve[] getProxy() { return null; } protected com.vividsolutions.jts.geom.Geometry computeJTSPeer() { // For each segment that comprises us, get the JTS peer. int n = curveSegments.size(); ArrayList allCoords = new ArrayList(); for (int i=0; i<n; i++) { JTSGeometry g = (JTSGeometry) curveSegments.get(i); com.vividsolutions.jts.geom.LineString jts = (com.vividsolutions.jts.geom.LineString) g.getJTSGeometry(); int m = jts.getNumPoints(); for (int j=0; j<m; j++) { allCoords.add(jts.getCoordinateN(j)); } if (i != (n-1)) allCoords.remove(allCoords.size()-1); } com.vividsolutions.jts.geom.Coordinate [] coords = new com.vividsolutions.jts.geom.Coordinate[allCoords.size()]; allCoords.toArray(coords); return JTSUtils.GEOMETRY_FACTORY.createLineString(coords); } }