Skip to content
This repository has been archived by the owner on Dec 2, 2020. It is now read-only.

Commit

Permalink
Merge pull request #221 from Boris-Em/bug-fixes
Browse files Browse the repository at this point in the history
Fixes bezier curve boundary issues
  • Loading branch information
Sam Spencer committed Jul 31, 2015
2 parents 0bb60c9 + 17fe25f commit ae944b9
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 83 deletions.
1 change: 1 addition & 0 deletions Classes/BEMAverageLine.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
// Copyright (c) 2015 Boris Emorine. All rights reserved.
//

@import Foundation;
@import UIKit;


Expand Down
14 changes: 3 additions & 11 deletions Classes/BEMCircle.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,9 @@
// Copyright (c) 2014 Sam Spencer.
//


#if __has_feature(objc_modules)
// We recommend enabling Objective-C Modules in your project Build Settings for numerous benefits over regular #imports
@import Foundation;
@import UIKit;
@import CoreGraphics;
#else
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import <CoreGraphics/CoreGraphics.h>
#endif
@import Foundation;
@import UIKit;
@import CoreGraphics;


/// Class to draw the circle for the points.
Expand Down
66 changes: 23 additions & 43 deletions Classes/BEMLine.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,9 @@
// Copyright (c) 2014 Sam Spencer.
//


#if __has_feature(objc_modules)
// We recommend enabling Objective-C Modules in your project Build Settings for numerous benefits over regular #imports
@import Foundation;
@import UIKit;
@import CoreGraphics;
#else
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import <CoreGraphics/CoreGraphics.h>
#endif
@import Foundation;
@import UIKit;
@import CoreGraphics;

#import "BEMAverageLine.h"

Expand Down Expand Up @@ -50,51 +42,39 @@ typedef NS_ENUM(NSUInteger, BEMLineGradientDirection) {

//----- POINTS -----//

/// The previous point. Necessary for Bezier curve
@property (assign, nonatomic) CGPoint P0;

/// The starting point of the line
@property (assign, nonatomic) CGPoint P1;

/// The ending point of the line
@property (assign, nonatomic) CGPoint P2;

/// The next point. Necessary for Bezier curve
@property (assign, nonatomic) CGPoint P3;

/// All of the Y-axis values for the points
@property (nonatomic) NSArray *arrayOfPoints;
@property (strong, nonatomic) NSArray *arrayOfPoints;

/// All of the X-Axis coordinates used to draw vertical lines through
@property (nonatomic) NSArray *arrayOfVerticalRefrenceLinePoints;
@property (strong, nonatomic) NSArray *arrayOfVerticalRefrenceLinePoints;

/// The value used to offset the fringe vertical reference lines when the x-axis labels are on the edge
@property (assign, nonatomic) CGFloat verticalReferenceHorizontalFringeNegation;

/// All of the Y-Axis coordinates used to draw horizontal lines through
@property (nonatomic) NSArray *arrayOfHorizontalRefrenceLinePoints;
@property (strong, nonatomic) NSArray *arrayOfHorizontalRefrenceLinePoints;

/// All of the point values
@property (nonatomic) NSArray *arrayOfValues;
@property (strong, nonatomic) NSArray *arrayOfValues;

/** Draw thin, translucent, reference lines using the provided X-Axis and Y-Axis coordinates.
@see Use \p arrayOfVerticalRefrenceLinePoints to specify vertical reference lines' positions. Use \p arrayOfHorizontalRefrenceLinePoints to specify horizontal reference lines' positions. */
@property (nonatomic) BOOL enableRefrenceLines;
@property (assign, nonatomic) BOOL enableRefrenceLines;

/** Draw a thin, translucent, frame on the edge of the graph to separate it from the labels on the X-Axis and the Y-Axis. */
@property (nonatomic) BOOL enableRefrenceFrame;
@property (assign, nonatomic) BOOL enableRefrenceFrame;

/** If reference frames are enabled, this will enable/disable specific borders. Default: YES */
@property (nonatomic) BOOL enableLeftReferenceFrameLine;
@property (assign, nonatomic) BOOL enableLeftReferenceFrameLine;

/** If reference frames are enabled, this will enable/disable specific borders. Default: YES */
@property (nonatomic) BOOL enableBottomReferenceFrameLine;
@property (assign, nonatomic) BOOL enableBottomReferenceFrameLine;

/** If reference frames are enabled, this will enable/disable specific borders. Default: NO */
@property (nonatomic) BOOL enableRightReferenceFrameLine;
@property (assign, nonatomic) BOOL enableRightReferenceFrameLine;

/** If reference frames are enabled, this will enable/disable specific borders. Default: NO */
@property (nonatomic) BOOL enableTopReferenceFrameLine;
@property (assign, nonatomic) BOOL enableTopReferenceFrameLine;

/** Dash pattern for the references line on the X axis */
@property (nonatomic, strong) NSArray *lineDashPatternForReferenceXAxisLines;
Expand All @@ -103,10 +83,10 @@ typedef NS_ENUM(NSUInteger, BEMLineGradientDirection) {
@property (nonatomic, strong) NSArray *lineDashPatternForReferenceYAxisLines;

/** If a null value is present, interpolation would draw a best fit line through the null point bound by its surrounding points. Default: YES */
@property (nonatomic) BOOL interpolateNullValues;
@property (assign, nonatomic) BOOL interpolateNullValues;

/** Draws everything but the main line on the graph; correlates to the \p displayDotsOnly property. Default: NO */
@property (nonatomic) BOOL disableMainLine;
@property (assign, nonatomic) BOOL disableMainLine;



Expand Down Expand Up @@ -141,20 +121,20 @@ typedef NS_ENUM(NSUInteger, BEMLineGradientDirection) {
//----- ALPHA -----//

/// The line alpha
@property (nonatomic) float lineAlpha;
@property (assign, nonatomic) float lineAlpha;

/// The alpha value of the area above the line, inside of its superview
@property (nonatomic) float topAlpha;
@property (assign, nonatomic) float topAlpha;

/// The alpha value of the area below the line, inside of its superview
@property (nonatomic) float bottomAlpha;
@property (assign, nonatomic) float bottomAlpha;



//----- SIZE -----//

/// The width of the line
@property (nonatomic) float lineWidth;
@property (assign, nonatomic) float lineWidth;

/// The width of a reference line
@property (nonatomic) float referenceLineWidth;
Expand All @@ -164,17 +144,17 @@ typedef NS_ENUM(NSUInteger, BEMLineGradientDirection) {
//----- BEZIER CURVE -----//

/// The line is drawn with smooth curves rather than straight lines when set to YES.
@property (nonatomic) BOOL bezierCurveIsEnabled;
@property (assign, nonatomic) BOOL bezierCurveIsEnabled;



//----- ANIMATION -----//

/// The entrance animation period in seconds.
@property (nonatomic) CGFloat animationTime;
@property (assign, nonatomic) CGFloat animationTime;

/// The type of entrance animation.
@property (nonatomic) BEMLineAnimation animationType;
@property (assign, nonatomic) BEMLineAnimation animationType;



Expand All @@ -184,7 +164,7 @@ typedef NS_ENUM(NSUInteger, BEMLineGradientDirection) {
@property (strong, nonatomic) BEMAverageLine *averageLine;

/// The average line's y-value translated into the coordinate system
@property (nonatomic) CGFloat averageLineYCoordinate;
@property (assign, nonatomic) CGFloat averageLineYCoordinate;



Expand Down
85 changes: 57 additions & 28 deletions Classes/BEMLine.m
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,22 @@
#define CGFloatValue floatValue
#endif

@interface BEMLine ()

/// The previous point. Necessary for Bezier curve
@property (assign, nonatomic) CGPoint P0;

/// The starting point of the line
@property (assign, nonatomic) CGPoint P1;

/// The ending point of the line
@property (assign, nonatomic) CGPoint P2;

/// The next point. Necessary for Bezier curve
@property (assign, nonatomic) CGPoint P3;

@end

@implementation BEMLine

- (instancetype)initWithFrame:(CGRect)frame {
Expand Down Expand Up @@ -151,10 +167,10 @@ - (void)drawRect:(CGRect)rect {
UIBezierPath *fillTop = [UIBezierPath bezierPath];
UIBezierPath *fillBottom = [UIBezierPath bezierPath];

CGPoint p0;
CGPoint p1;
CGPoint p2;
CGPoint p3;
CGPoint point0;
CGPoint point1;
CGPoint point2;
CGPoint point3;
CGFloat tensionBezier1 = 0.3;
CGFloat tensionBezier2 = 0.3;
CGFloat xIndexScale = self.frame.size.width/([self.arrayOfPoints count] - 1);
Expand All @@ -176,33 +192,38 @@ - (void)drawRect:(CGRect)rect {
CGPoint previousPoint2 = CGPointMake(0,0);

for (int i = 0; i < points.count - 1; i++) {
p1 = [[points objectAtIndex:i] CGPointValue];
p2 = [[points objectAtIndex:i + 1] CGPointValue];
point1 = [[points objectAtIndex:i] CGPointValue];
point2 = [[points objectAtIndex:i + 1] CGPointValue];

if (!self.interpolateNullValues && (p1.y == BEMNullGraphValue || p2.y == BEMNullGraphValue)) continue;
if (!self.interpolateNullValues && (point1.y == BEMNullGraphValue || point2.y == BEMNullGraphValue)) continue;

if (self.disableMainLine == NO) [line moveToPoint:p1];
[fillBottom addLineToPoint:p1];
[fillTop addLineToPoint:p1];
if (self.disableMainLine == NO) [line moveToPoint:point1];
[fillBottom addLineToPoint:point1];
[fillTop addLineToPoint:point1];

// Check if bézier curves are enabled
if (self.bezierCurveIsEnabled == YES) {
// Bézier curves are enabled, proceed to draw line with curve
// Determine the maximum amount of bézier tension
const CGFloat maxTension = 1.0f / 3.0f;
tensionBezier1 = maxTension;
tensionBezier2 = maxTension;

// Set tension and points
if (i > 0) { // Exception for first line because there is no previous point
p0 = previousPoint1;
if (p2.y - p1.y == p1.y - p0.y) tensionBezier1 = 0;
point0 = previousPoint1;
if (point2.y - point1.y == point1.y - point0.y) tensionBezier1 = 0;
} else {
tensionBezier1 = 0;
p0 = p1;
point0 = point1;
}

// Set tension and points
if (i < points.count - 2) { // Exception for last line because there is no next point
p3 = [[points objectAtIndex:i + 2] CGPointValue];
if (p3.y - p2.y == p2.y - p1.y) tensionBezier2 = 0;
point3 = [[points objectAtIndex:i + 2] CGPointValue];
if (point3.y - point2.y == point2.y - point1.y) tensionBezier2 = 0;
} else {
p3 = p2;
point3 = point2;
tensionBezier2 = 0;
}

Expand All @@ -211,24 +232,32 @@ - (void)drawRect:(CGRect)rect {
if (tensionBezier2 > maxTension) tensionBezier2 = maxTension;

// First control point
CP1 = CGPointMake(p1.x + (p2.x - p1.x)/3,
p1.y - (p1.y - p2.y)/3 - (p0.y - p1.y)*tensionBezier1);
CGFloat CP1x = point1.x + (point2.x - point1.x)/3;
CGFloat CP1y = point1.y - (point1.y - point2.y)/3 - (point0.y - point1.y)*tensionBezier1;
if (CP1x > self.frame.size.width) CP1x = self.frame.size.width - 1;
if (CP1y > self.frame.size.height) CP1y = self.frame.size.height - 1;
else if (CP1y < 0) CP1y = 0;
CP1 = CGPointMake(CP1x, CP1y);

// Second control point
CP2 = CGPointMake(p1.x + 2*(p2.x - p1.x)/3,
(p1.y - 2*(p1.y - p2.y)/3) + (p2.y - p3.y)*tensionBezier2);
CGFloat CP2x = point1.x + 2*(point2.x - point1.x)/3;
CGFloat CP2y = (point1.y - 2*(point1.y - point2.y)/3) + (point2.y - point3.y)*tensionBezier2;
if (CP2x > self.frame.size.width) CP2x = self.frame.size.width - 1;
if (CP2y > self.frame.size.height) CP2y = self.frame.size.height - 1;
else if (CP2y < 0) CP2y = 0; // Control points that go out of bounds will cause the graph curve to draw outside of its bounds, so we must implement a safety check to ensure that the graph does not leave its bounds
CP2 = CGPointMake(CP2x, CP2y);

if (self.disableMainLine == NO) [line addCurveToPoint:p2 controlPoint1:CP1 controlPoint2:CP2];
[fillBottom addCurveToPoint:p2 controlPoint1:CP1 controlPoint2:CP2];
[fillTop addCurveToPoint:p2 controlPoint1:CP1 controlPoint2:CP2];
if (self.disableMainLine == NO) [line addCurveToPoint:point2 controlPoint1:CP1 controlPoint2:CP2];
[fillBottom addCurveToPoint:point2 controlPoint1:CP1 controlPoint2:CP2];
[fillTop addCurveToPoint:point2 controlPoint1:CP1 controlPoint2:CP2];
} else {
if (self.disableMainLine == NO) [line addLineToPoint:p2];
[fillBottom addLineToPoint:p2];
[fillTop addLineToPoint:p2];
if (self.disableMainLine == NO) [line addLineToPoint:point2];
[fillBottom addLineToPoint:point2];
[fillTop addLineToPoint:point2];
}

previousPoint1 = p1;
previousPoint2 = p2;
previousPoint1 = point1;
previousPoint2 = point2;
}


Expand Down
3 changes: 2 additions & 1 deletion Classes/BEMPermanentPopupView.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
// Copyright (c) 2015 Boris Emorine. All rights reserved.
//

#import <UIKit/UIKit.h>
@import UIKit;


@interface BEMPermanentPopupView : UIView

Expand Down

0 comments on commit ae944b9

Please sign in to comment.