CurveLinearizer { public LineStringSegment linearizeCubicSpline( CubicSpline spline, LinearizationCriterion crit ) { if ( spline.getCoordinateDimension() != 2 ) { throw new UnsupportedOperationException( "Linearization of the cubic spline is only suported for a spline in 2D." ); } Points controlPts = spline.getControlPoints(); Point[] pts = new Point[controlPts.size()]; int n = controlPts.size() - 1; for ( int i = 0; i <= n; i++ ) { pts[i] = controlPts.get( i ); } double startTan = Math.atan2( spline.getVectorAtStart().get1(), spline.getVectorAtStart().get0() ); double endTan = Math.atan2( spline.getVectorAtEnd().get1(), spline.getVectorAtEnd().get0() ); boolean ascending = true; if ( pts[0].get0() > pts[1].get0() ) { ascending = false; } for ( int i = 0; i <= n - 1; i++ ) { if ( ascending ) { if ( pts[i].get0() > pts[i + 1].get0() ) { throw new UnsupportedOperationException( "It is expected that the control points are ordered on the X-axis either ascendingly or descendingly." ); } } else { if ( pts[i].get0() < pts[i + 1].get0() ) { throw new UnsupportedOperationException( "It is expected that the control points are ordered on the X-axis either ascendingly or descendingly." ); } } } if ( !ascending ) { for ( int i = 0; i <= ( n / 2 ); i++ ) { Point aux = pts[i]; pts[i] = pts[n - i]; pts[n - i] = aux; } startTan = Math.atan2( -spline.getVectorAtEnd().get1(), -spline.getVectorAtEnd().get0() ); endTan = Math.atan2( -spline.getVectorAtStart().get1(), -spline.getVectorAtStart().get0() ); } double xcoor[] = new double[n + 1]; double ycoor[] = new double[n + 1]; for ( int i = 0; i <= n; i++ ) { xcoor[i] = pts[i].get0(); ycoor[i] = pts[i].get1(); } double[] h = new double[n]; for ( int i = 0; i <= n - 1; i++ ) { h[i] = xcoor[i + 1] - xcoor[i]; } double[][] matrixA = constructMatrixA( h, n ); double[] vectorb = constructVectorB( n, ycoor, h, startTan, endTan ); double[] vectorx = solveLinearEquation( matrixA, vectorb ); int numPoints = -1; if ( crit instanceof NumPointsCriterion ) { numPoints = ( (NumPointsCriterion) crit ).getNumberOfPoints(); } else if ( crit instanceof MaxErrorCriterion ) { numPoints = ( (MaxErrorCriterion) crit ).getMaxNumPoints(); if ( numPoints <= 0 ) { throw new UnsupportedOperationException( "Linearization of the cubic spline with MaxErrorCriterion is currently not supported, unless the number of points is provided." ); } } double[] interpolated = interpolateSpline( n, h, xcoor, ycoor, vectorx, numPoints ); List<Point> iPoints = new ArrayList<Point>(); ICRS crs = spline.getControlPoints().get( 0 ).getCoordinateSystem(); PrecisionModel pm = spline.getControlPoints().get( 0 ).getPrecision(); for ( int i = 0; i < numPoints; i++ ) { iPoints.add( new DefaultPoint( null, crs, pm, new double[] { interpolated[2 * i], interpolated[2 * i + 1] } ) ); } LineStringSegment lineSegment = geomFac.createLineStringSegment( new PointsList( iPoints ) ); return lineSegment; } CurveLinearizer( GeometryFactory geomFac ); Curve linearize( Curve curve, LinearizationCriterion crit ); LineStringSegment linearize( CurveSegment segment, LinearizationCriterion crit ); LineStringSegment linearizeArc( Arc arc, LinearizationCriterion crit ); LineStringSegment linearizeArcString( ArcString arcString, LinearizationCriterion crit ); LineStringSegment linearizeCubicSpline( CubicSpline spline, LinearizationCriterion crit ); static boolean areCollinear( Point p0, Point p1, Point p2 );  }
@Test public void testLinearizeCubicSpline() { List<Point> pList = new ArrayList<Point>(); pList.add( geomFac.createPoint( null, new double[] { -2, 0 }, null ) ); pList.add( geomFac.createPoint( null, new double[] { -4, 0 }, null ) ); pList.add( geomFac.createPoint( null, new double[] { -6, 1 }, null ) ); CubicSpline spline = new DefaultCubicSpline( new PointsList( pList ), geomFac.createPoint( null, new double[] { 0, -1 }, null ), geomFac.createPoint( null, new double[] { -1, 1 }, null ) ); int numOfPoints = 10000; Points pts = linearizer.linearize( spline, new NumPointsCriterion( numOfPoints ) ).getControlPoints(); for ( int i = 0; i < numOfPoints; i++ ) { if ( Math.abs( pts.get( i ).get0() - -3 ) < 1E-3 ) { Assert.assertEquals( pts.get( i ).get1(), -0.535536466911, 1E-3 ); } if ( Math.abs( pts.get( i ).get0() - -5 ) < 1E-3 ) { Assert.assertEquals( pts.get( i ).get1(), 0.4464878443629, 1E-3 ); } } }