@@ -24,6 +24,7 @@ public class CatmullRomSpline : IInterpolationAlgorithm
2424 /// The alpha.
2525 /// </summary>
2626 public double Alpha { get ; }
27+ public int MaxSegments { get ; set ; }
2728
2829 /// <summary>
2930 /// Initializes a new instance of the <see cref = "CatmullRomSpline" /> class.
@@ -32,6 +33,7 @@ public class CatmullRomSpline : IInterpolationAlgorithm
3233 public CatmullRomSpline ( double alpha )
3334 {
3435 this . Alpha = alpha ;
36+ this . MaxSegments = 100 ;
3537 }
3638
3739 /// <summary>
@@ -41,8 +43,9 @@ public CatmullRomSpline(double alpha)
4143 /// <param name="isClosed">True if the spline is closed.</param>
4244 /// <param name="tolerance">The tolerance.</param>
4345 /// <returns>A list of data points.</returns>
44- public List < DataPoint > CreateSpline ( List < DataPoint > points , bool isClosed , double tolerance ) {
45- return CreateSpline ( points , this . Alpha , isClosed , tolerance ) ;
46+ public List < DataPoint > CreateSpline ( List < DataPoint > points , bool isClosed , double tolerance )
47+ {
48+ return CreateSpline ( points , this . Alpha , isClosed , tolerance , MaxSegments ) ;
4649 }
4750
4851 /// <summary>
@@ -52,8 +55,9 @@ public List<DataPoint> CreateSpline(List<DataPoint> points, bool isClosed, doubl
5255 /// <param name="isClosed">True if the spline is closed.</param>
5356 /// <param name="tolerance">The tolerance.</param>
5457 /// <returns>A list of screen points.</returns>
55- public List < ScreenPoint > CreateSpline ( IList < ScreenPoint > points , bool isClosed , double tolerance ) {
56- return CreateSpline ( points , this . Alpha , isClosed , tolerance ) ;
58+ public List < ScreenPoint > CreateSpline ( IList < ScreenPoint > points , bool isClosed , double tolerance )
59+ {
60+ return CreateSpline ( points , this . Alpha , isClosed , tolerance , MaxSegments ) ;
5761 }
5862
5963 /// <summary>
@@ -64,10 +68,10 @@ public List<ScreenPoint> CreateSpline(IList<ScreenPoint> points, bool isClosed,
6468 /// <param name="isClosed">True if the spline is closed.</param>
6569 /// <param name="tolerance">The tolerance.</param>
6670 /// <returns>A list of data points.</returns>
67- internal static List < DataPoint > CreateSpline ( List < DataPoint > points , double alpha , bool isClosed , double tolerance )
71+ internal static List < DataPoint > CreateSpline ( List < DataPoint > points , double alpha , bool isClosed , double tolerance , int maxSegments )
6872 {
6973 var screenPoints = points . Select ( p => new ScreenPoint ( p . X , p . Y ) ) . ToList ( ) ;
70- var interpolatedScreenPoints = CreateSpline ( screenPoints , alpha , isClosed , tolerance ) ;
74+ var interpolatedScreenPoints = CreateSpline ( screenPoints , alpha , isClosed , tolerance , maxSegments ) ;
7175 var interpolatedDataPoints = new List < DataPoint > ( interpolatedScreenPoints . Count ) ;
7276
7377 foreach ( var s in interpolatedScreenPoints )
@@ -87,7 +91,7 @@ internal static List<DataPoint> CreateSpline(List<DataPoint> points, double alph
8791 /// <param name="tolerance">The tolerance.</param>
8892 /// <returns>A list of screen points.</returns>
8993 internal static List < ScreenPoint > CreateSpline (
90- IList < ScreenPoint > points , double alpha , bool isClosed , double tolerance )
94+ IList < ScreenPoint > points , double alpha , bool isClosed , double tolerance , int maxSegments )
9195 {
9296 var result = new List < ScreenPoint > ( ) ;
9397 if ( points == null )
@@ -111,12 +115,12 @@ internal static List<ScreenPoint> CreateSpline(
111115 {
112116 if ( ! isClosed )
113117 {
114- Segment ( result , points [ 0 ] , points [ 0 ] , points [ 1 ] , points [ 1 ] , alpha , tolerance ) ;
118+ Segment ( result , points [ 0 ] , points [ 0 ] , points [ 1 ] , points [ 1 ] , alpha , tolerance , maxSegments ) ;
115119 }
116120 else
117121 {
118- Segment ( result , points [ 1 ] , points [ 0 ] , points [ 1 ] , points [ 0 ] , alpha , tolerance ) ;
119- Segment ( result , points [ 0 ] , points [ 1 ] , points [ 0 ] , points [ 1 ] , alpha , tolerance ) ;
122+ Segment ( result , points [ 1 ] , points [ 0 ] , points [ 1 ] , points [ 0 ] , alpha , tolerance , maxSegments ) ;
123+ Segment ( result , points [ 0 ] , points [ 1 ] , points [ 0 ] , points [ 1 ] , alpha , tolerance , maxSegments ) ;
120124 }
121125 }
122126 else
@@ -132,7 +136,8 @@ internal static List<ScreenPoint> CreateSpline(
132136 points [ 1 ] ,
133137 points [ 2 ] ,
134138 alpha ,
135- tolerance ) ;
139+ tolerance ,
140+ maxSegments ) ;
136141 }
137142 else if ( i == n - 2 )
138143 {
@@ -143,18 +148,19 @@ internal static List<ScreenPoint> CreateSpline(
143148 points [ i + 1 ] ,
144149 isClosed ? points [ 0 ] : points [ i + 1 ] ,
145150 alpha ,
146- tolerance ) ;
151+ tolerance ,
152+ maxSegments ) ;
147153 }
148154 else if ( i == n - 1 )
149155 {
150156 if ( isClosed )
151157 {
152- Segment ( result , points [ i - 1 ] , points [ i ] , points [ 0 ] , points [ 1 ] , alpha , tolerance ) ;
158+ Segment ( result , points [ i - 1 ] , points [ i ] , points [ 0 ] , points [ 1 ] , alpha , tolerance , maxSegments ) ;
153159 }
154160 }
155161 else
156162 {
157- Segment ( result , points [ i - 1 ] , points [ i ] , points [ i + 1 ] , points [ i + 2 ] , alpha , tolerance ) ;
163+ Segment ( result , points [ i - 1 ] , points [ i ] , points [ i + 1 ] , points [ i + 2 ] , alpha , tolerance , maxSegments ) ;
158164 }
159165 }
160166 }
@@ -172,7 +178,7 @@ internal static List<ScreenPoint> CreateSpline(
172178 /// <param name="pt3">The pt 3.</param>
173179 /// <param name="alpha">The alpha.</param>
174180 /// <param name="tolerance">The tolerance.</param>
175- /// <param name="maxSegments">The maximum number of segments. Default is <c>1000</c>. </param>
181+ /// <param name="maxSegments">The maximum number of segments.</param>
176182 private static void Segment (
177183 IList < ScreenPoint > points ,
178184 ScreenPoint pt0 ,
@@ -181,7 +187,7 @@ private static void Segment(
181187 ScreenPoint pt3 ,
182188 double alpha ,
183189 double tolerance ,
184- int maxSegments = 1000 )
190+ int maxSegments )
185191 {
186192 if ( Equals ( pt1 , pt2 ) )
187193 {
@@ -204,7 +210,12 @@ private static void Segment(
204210 double t2 = GetT ( t1 , pt1 , pt2 , alpha ) ;
205211 double t3 = GetT ( t2 , pt2 , pt3 , alpha ) ;
206212
207- int iterations = Math . Min ( ( int ) ( ( Math . Abs ( pt1 . X - pt2 . X ) + Math . Abs ( pt1 . Y - pt2 . Y ) ) / tolerance ) , maxSegments ) ;
213+
214+ int iterations = ( int ) ( ( Math . Abs ( pt1 . X - pt2 . X ) + Math . Abs ( pt1 . Y - pt2 . Y ) ) / tolerance ) ;
215+ //Make sure it is positive (negative means an integer overflow)
216+ iterations = Math . Max ( 0 , iterations ) ;
217+ //Never more iterations than maxSegments
218+ iterations = Math . Min ( maxSegments , iterations ) ;
208219 for ( double t = t1 ; t < t2 ; t += ( t2 - t1 ) / iterations )
209220 {
210221 ScreenPoint a1 = Sum ( Mult ( ( t1 - t ) / ( t1 - t0 ) , pt0 ) , Mult ( ( t - t0 ) / ( t1 - t0 ) , pt1 ) ) ;
@@ -247,4 +258,4 @@ private static ScreenPoint Sum(ScreenPoint a, ScreenPoint b)
247258 return new ScreenPoint ( a . X + b . X , a . Y + b . Y ) ;
248259 }
249260 }
250- }
261+ }
0 commit comments