@@ -113,12 +113,24 @@ - (void)drawRect:(CGRect)rect {
113113 // ----------------------------//
114114 // LINE
115115 NSUInteger numPoints = self.points .count ;
116+ CGFloat rightEdge = CGRectGetMaxX (self.bounds );
117+ NSInteger numOverRightEdge = 0 ;
116118 NSMutableArray <NSValue *> *drawPoints = [NSMutableArray arrayWithCapacity: numPoints];
117- for (NSValue *value in self.points ) {
119+ for (NSUInteger index = 0 ; index < self.points .count ; index++) {
120+ NSValue *value = self.points [index];
118121 CGPoint point = value.CGPointValue ;
119122 CGFloat xValue = point.x ;
120123 CGFloat yValue = point.y ;
121- if (xValue < 0 || xValue > CGRectGetMaxX (self.bounds )) continue ;
124+ if (xValue < 0 ) {
125+ // only include two points to left of view to get curve correct
126+ if (index+2 > self.points .count ) continue ;
127+ if (self.points [index+2 ].CGPointValue .x < 0 ) continue ;
128+ }
129+ if (xValue > rightEdge) {
130+ // only include twp points to right of view to get curve correct
131+ if (numOverRightEdge >= 2 ) continue ;
132+ numOverRightEdge++;
133+ }
122134
123135 if (yValue >= BEMNullGraphValue && self.interpolateNullValues ) {
124136 // need to interpolate. For midpoints, just don't add a point
@@ -354,13 +366,19 @@ + (UIBezierPath *)pathWithPoints:(NSArray <NSValue *> *)points curved:(BOOL) cur
354366 oldControlPoint = p2;
355367 } else if (curved ) {
356368 CGPoint p3 = CGPointZero;
357- // Don't let frame points beyond actual data affect curve.
369+ // Don't let frame points beyond actual data affect curve.
358370 if (pointIndex < dataEnd) p3 = [points[pointIndex+1 ] CGPointValue ] ;
359371 if (p3.y >= BEMNullGraphValue) p3 = CGPointZero;
360- CGPoint newControlPoint = controlPointForPoints2 (p1, p2, p3);
372+ CGPoint newControlPoint = controlPointForPoints (p1, p2, p3);
361373 if (!CGPointEqualToPoint ( newControlPoint, CGPointZero)) {
362374 [path addCurveToPoint: p2 controlPoint1: oldControlPoint controlPoint2: newControlPoint];
363375 oldControlPoint = imaginForPoints ( newControlPoint, p2);
376+ // this "if" not in original algorithm, but seems to smooth so that curves don't "backup" when points are too close in x dimension
377+ if (! CGPointEqualToPoint (p3,CGPointZero)) {
378+ if (oldControlPoint.x > p3.x ) {
379+ oldControlPoint.x = p3.x ;
380+ }
381+ }
364382 } else {
365383 [path addCurveToPoint: p2 controlPoint1: oldControlPoint controlPoint2: p2];
366384 oldControlPoint = p2;
@@ -396,7 +414,7 @@ static CGFloat clamp(CGFloat num, CGFloat bounds1, CGFloat bounds2) {
396414 }
397415}
398416
399- static CGPoint controlPointForPoints2 (CGPoint p1, CGPoint p2, CGPoint p3) {
417+ static CGPoint controlPointForPoints (CGPoint p1, CGPoint p2, CGPoint p3) {
400418 if (CGPointEqualToPoint (p3, CGPointZero)) return CGPointZero;
401419 CGPoint leftMidPoint = midPointForPoints (p1, p2);
402420 CGPoint rightMidPoint = midPointForPoints (p2, p3);
@@ -408,7 +426,9 @@ static CGPoint controlPointForPoints2(CGPoint p1, CGPoint p2, CGPoint p3) {
408426 CGFloat flippedP3 = p2.y + (p2.y -p3.y );
409427
410428 controlPoint.y = clamp (controlPoint.y , p2.y , flippedP3);
411-
429+ // x clamp not in original algorithm, but seems to smooth
430+ // so that curves don't "backup" when points are too close in x dimension
431+ controlPoint.x = clamp (controlPoint.x , p1.x , p2.x );
412432 return controlPoint;
413433}
414434
0 commit comments