Kevin

Merge pull request #130 from MrWooJ/feature-ScatterGraph

Feature Scatter Graph
@@ -17,3 +17,4 @@ @@ -17,3 +17,4 @@
17 #import "PNCircleChart.h" 17 #import "PNCircleChart.h"
18 #import "PNChartDelegate.h" 18 #import "PNChartDelegate.h"
19 #import "PNPieChart.h" 19 #import "PNPieChart.h"
  20 +#import "PNScatterChart.h"
  1 +//
  2 +// PNScatterChart.h
  3 +// PNChartDemo
  4 +//
  5 +// Created by Alireza Arabi on 12/4/14.
  6 +// Copyright (c) 2014 kevinzhow. All rights reserved.
  7 +//
  8 +
  9 +#import <UIKit/UIKit.h>
  10 +#import <QuartzCore/QuartzCore.h>
  11 +#import "PNChartDelegate.h"
  12 +#import "PNScatterChartData.h"
  13 +#import "PNScatterChartDataItem.h"
  14 +
  15 +@interface PNScatterChart : UIView
  16 +
  17 +@property (nonatomic, retain) id<PNChartDelegate> delegate;
  18 +
  19 +/** Array of `ScatterChartData` objects, one for each line. */
  20 +@property (nonatomic) NSArray *chartData;
  21 +
  22 +/** Controls whether to show the coordinate axis. Default is NO. */
  23 +@property (nonatomic, getter = isShowCoordinateAxis) BOOL showCoordinateAxis;
  24 +@property (nonatomic) UIColor *axisColor;
  25 +@property (nonatomic) CGFloat axisWidth;
  26 +
  27 +/** String formatter for float values in y-axis labels. If not set, defaults to @"%1.f" */
  28 +@property (nonatomic, strong) NSString *yLabelFormat;
  29 +
  30 +/** Default is true. */
  31 +@property (nonatomic) BOOL showLabel;
  32 +
  33 +/** Default is 18-point Avenir Medium. */
  34 +@property (nonatomic) UIFont *descriptionTextFont;
  35 +
  36 +/** Default is white. */
  37 +@property (nonatomic) UIColor *descriptionTextColor;
  38 +
  39 +/** Default is black, with an alpha of 0.4. */
  40 +@property (nonatomic) UIColor *descriptionTextShadowColor;
  41 +
  42 +/** Default is CGSizeMake(0, 1). */
  43 +@property (nonatomic) CGSize descriptionTextShadowOffset;
  44 +
  45 +/** Default is 1.0. */
  46 +@property (nonatomic) NSTimeInterval duration;
  47 +
  48 +@property (nonatomic) CGFloat AxisX_minValue;
  49 +@property (nonatomic) CGFloat AxisX_maxValue;
  50 +
  51 +@property (nonatomic) CGFloat AxisY_minValue;
  52 +@property (nonatomic) CGFloat AxisY_maxValue;
  53 +
  54 +- (void) setAxisXWithMinimumValue:(CGFloat)minVal andMaxValue:(CGFloat)maxVal toTicks:(int)numberOfTicks;
  55 +- (void) setAxisYWithMinimumValue:(CGFloat)minVal andMaxValue:(CGFloat)maxVal toTicks:(int)numberOfTicks;
  56 +- (void) setup;
  57 +- (void) drawLineFromPoint : (CGPoint) startPoint ToPoint : (CGPoint) endPoint WithLineWith : (CGFloat) lineWidth AndWithColor : (UIColor*) color;
  58 +
  59 +/**
  60 + * Update Chart Value
  61 + */
  62 +
  63 +- (void)updateChartData:(NSArray *)data;
  64 +
  65 +@end
  1 +//
  2 +// PNScatterChart.m
  3 +// PNChartDemo
  4 +//
  5 +// Created by Alireza Arabi on 12/4/14.
  6 +// Copyright (c) 2014 kevinzhow. All rights reserved.
  7 +//
  8 +
  9 +#import "PNScatterChart.h"
  10 +#import "PNColor.h"
  11 +#import "PNChartLabel.h"
  12 +#import "PNScatterChartData.h"
  13 +#import "PNScatterChartDataItem.h"
  14 +
  15 +@interface PNScatterChart ()
  16 +
  17 +@property (nonatomic, weak) CAShapeLayer *pathLayer;
  18 +@property (nonatomic, weak) NSMutableArray *verticalLineLayer;
  19 +@property (nonatomic, weak) NSMutableArray *horizentalLinepathLayer;
  20 +
  21 +@property (nonatomic) CGPoint startPoint;
  22 +
  23 +@property (nonatomic) CGPoint startPointVectorX;
  24 +@property (nonatomic) CGPoint endPointVecotrX;
  25 +
  26 +@property (nonatomic) CGPoint startPointVectorY;
  27 +@property (nonatomic) CGPoint endPointVecotrY;
  28 +
  29 +@property (nonatomic) CGFloat vectorX_Steps;
  30 +@property (nonatomic) CGFloat vectorY_Steps;
  31 +
  32 +@property (nonatomic) CGFloat vectorX_Size;
  33 +@property (nonatomic) CGFloat vectorY_Size;
  34 +
  35 +@property (nonatomic) NSMutableArray *axisX_labels;
  36 +@property (nonatomic) NSMutableArray *axisY_labels;
  37 +
  38 +@property (nonatomic) int AxisX_partNumber ;
  39 +@property (nonatomic) int AxisY_partNumber ;
  40 +
  41 +@property (nonatomic) CGFloat AxisX_step ;
  42 +@property (nonatomic) CGFloat AxisY_step ;
  43 +
  44 +@property (nonatomic) CGFloat AxisX_Margin;
  45 +@property (nonatomic) CGFloat AxisY_Margin;
  46 +
  47 +@property (nonatomic) BOOL isForUpdate;
  48 +
  49 +- (void)setDefaultValues;
  50 +
  51 +@end
  52 +
  53 +
  54 +@implementation PNScatterChart
  55 +
  56 +#pragma mark initialization
  57 +
  58 +- (id)initWithCoder:(NSCoder *)coder
  59 +{
  60 + self = [super initWithCoder:coder];
  61 +
  62 + if (self) {
  63 + [self setDefaultValues];
  64 + }
  65 + return self;
  66 +}
  67 +
  68 +- (id)initWithFrame:(CGRect)frame
  69 +{
  70 + self = [super initWithFrame:frame];
  71 +
  72 + if (self) {
  73 + [self setDefaultValues];
  74 + }
  75 + return self;
  76 +}
  77 +
  78 +- (void) setup
  79 +{
  80 + [self vectorXSetup];
  81 + [self vectorYSetup];
  82 +}
  83 +
  84 +- (void)setDefaultValues
  85 +{
  86 + // Initialization code
  87 + self.backgroundColor = [UIColor whiteColor];
  88 + self.clipsToBounds = YES;
  89 + _showLabel = YES;
  90 + _isForUpdate = NO;
  91 + self.userInteractionEnabled = YES;
  92 +
  93 + // Coordinate Axis Default Values
  94 + _showCoordinateAxis = YES;
  95 + _axisColor = [UIColor colorWithRed:0.4f green:0.4f blue:0.4f alpha:1.f];
  96 + _axisWidth = 1.f;
  97 +
  98 + // Initialization code
  99 + _AxisX_Margin = 30 ;
  100 + _AxisY_Margin = 30 ;
  101 +
  102 +// self.frame = CGRectMake((SCREEN_WIDTH - self.frame.size.width) / 2, 200, self.frame.size.width, self.frame.size.height) ;
  103 + self.backgroundColor = [UIColor clearColor];
  104 +
  105 + _startPoint.y = self.frame.size.height - self.AxisY_Margin ;
  106 + _startPoint.x = self.AxisX_Margin ;
  107 +
  108 + _axisX_labels = [NSMutableArray array];
  109 + _axisY_labels = [NSMutableArray array];
  110 +
  111 + _descriptionTextColor = [UIColor blackColor];
  112 + _descriptionTextFont = [UIFont fontWithName:@"Avenir-Medium" size:9.0];
  113 + _descriptionTextShadowColor = [[UIColor blackColor] colorWithAlphaComponent:0.4];
  114 + _descriptionTextShadowOffset = CGSizeMake(0, 1);
  115 + _duration = 1.0;
  116 +
  117 +}
  118 +
  119 +#pragma mark calculating axis
  120 +
  121 +- (void) setAxisXWithMinimumValue:(CGFloat)minVal andMaxValue:(CGFloat)maxVal toTicks:(int)numberOfTicks
  122 +{
  123 + _AxisX_minValue = minVal ;
  124 + _AxisX_maxValue = maxVal ;
  125 + _AxisX_partNumber = numberOfTicks - 1;
  126 + _AxisX_step = (float)((maxVal - minVal)/_AxisX_partNumber);
  127 +
  128 + NSString *LabelFormat = self.yLabelFormat ? : @"%1.f";
  129 + CGFloat tempValue = minVal ;
  130 + UILabel *label = [[UILabel alloc] init];
  131 + label.text = [NSString stringWithFormat:LabelFormat,minVal] ;
  132 + [_axisX_labels addObject:label];
  133 + for (int i = 0 ; i < _AxisX_partNumber; i++) {
  134 + tempValue = tempValue + _AxisX_step;
  135 + UILabel *tempLabel = [[UILabel alloc] init];
  136 + tempLabel.text = [NSString stringWithFormat:LabelFormat,tempValue] ;
  137 + [_axisX_labels addObject:tempLabel];
  138 + }
  139 +}
  140 +
  141 +- (void) setAxisYWithMinimumValue:(CGFloat)minVal andMaxValue:(CGFloat)maxVal toTicks:(int)numberOfTicks
  142 +{
  143 + _AxisY_minValue = minVal ;
  144 + _AxisY_maxValue = maxVal ;
  145 + _AxisY_partNumber = numberOfTicks - 1;
  146 + _AxisY_step = (float)((maxVal - minVal)/_AxisY_partNumber);
  147 +
  148 + NSString *LabelFormat = self.yLabelFormat ? : @"%1.f";
  149 + CGFloat tempValue = minVal ;
  150 + UILabel *label = [[UILabel alloc] init];
  151 + label.text = [NSString stringWithFormat:LabelFormat,minVal] ;
  152 + [_axisY_labels addObject:label];
  153 + for (int i = 0 ; i < _AxisY_partNumber; i++) {
  154 + tempValue = tempValue + _AxisY_step;
  155 + UILabel *tempLabel = [[UILabel alloc] init];
  156 + tempLabel.text = [NSString stringWithFormat:LabelFormat,tempValue] ;
  157 + [_axisY_labels addObject:tempLabel];
  158 + }
  159 +}
  160 +
  161 +- (void) vectorXSetup
  162 +{
  163 + _AxisX_partNumber += 1;
  164 + _vectorX_Size = self.frame.size.width - (_AxisX_Margin) - 15 ;
  165 + _vectorX_Steps = (_vectorX_Size) / (_AxisX_partNumber) ;
  166 + _endPointVecotrX = CGPointMake(_startPoint.x + _vectorX_Size, _startPoint.y) ;
  167 + _startPointVectorX = _startPoint ;
  168 +}
  169 +
  170 +- (void) vectorYSetup
  171 +{
  172 + _AxisY_partNumber += 1;
  173 + _vectorY_Size = self.frame.size.height - (_AxisY_Margin) - 15;
  174 + _vectorY_Steps = (_vectorY_Size) / (_AxisY_partNumber);
  175 + _endPointVecotrY = CGPointMake(_startPoint.x, _startPoint.y - _vectorY_Size) ;
  176 + _startPointVectorY = _startPoint ;
  177 +}
  178 +
  179 +- (void) showXLabel : (UILabel *) descriptionLabel InPosition : (CGPoint) point
  180 +{
  181 + CGRect frame = CGRectMake(point.x, point.y, 30, 10);
  182 + descriptionLabel.frame = frame;
  183 + descriptionLabel.font = _descriptionTextFont;
  184 + descriptionLabel.textColor = _descriptionTextColor;
  185 + descriptionLabel.shadowColor = _descriptionTextShadowColor;
  186 + descriptionLabel.shadowOffset = _descriptionTextShadowOffset;
  187 + descriptionLabel.textAlignment = NSTextAlignmentCenter;
  188 + descriptionLabel.backgroundColor = [UIColor clearColor];
  189 + [self addSubview:descriptionLabel];
  190 +}
  191 +
  192 +- (void)setChartData:(NSArray *)data
  193 +{
  194 + __block CGFloat yFinilizeValue , xFinilizeValue;
  195 + __block CGFloat yValue , xValue;
  196 + CABasicAnimation *pathAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"];
  197 + pathAnimation.duration = _duration;
  198 + pathAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
  199 + pathAnimation.fromValue = @(0.0f);
  200 + pathAnimation.toValue = @(1.0f);
  201 + pathAnimation.fillMode = kCAFillModeForwards;
  202 + self.layer.opacity = 1;
  203 +
  204 + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
  205 + [NSThread sleepForTimeInterval:1];
  206 + // update UI on the main thread
  207 + dispatch_async(dispatch_get_main_queue(), ^{
  208 + for (PNScatterChartData *chartData in data) {
  209 + for (NSUInteger i = 0; i < chartData.itemCount; i++) {
  210 + yValue = chartData.getData(i).y;
  211 + xValue = chartData.getData(i).x;
  212 + if (!(xValue >= _AxisX_minValue && xValue <= _AxisX_maxValue) || !(yValue >= _AxisY_minValue && yValue <= _AxisY_maxValue)) {
  213 + NSLog(@"input is not in correct range.");
  214 + exit(0);
  215 + }
  216 + xFinilizeValue = [self mappingIsForAxisX:true WithValue:xValue];
  217 + yFinilizeValue = [self mappingIsForAxisX:false WithValue:yValue];
  218 + CAShapeLayer *shape = [self drawingPointsForChartData:chartData AndWithX:xFinilizeValue AndWithY:yFinilizeValue];
  219 + self.pathLayer = shape ;
  220 + [self.layer addSublayer:self.pathLayer];
  221 + [self.pathLayer addAnimation:pathAnimation forKey:@"fade"];
  222 + }
  223 + }
  224 + });
  225 + });
  226 +}
  227 +
  228 +- (CGFloat) mappingIsForAxisX : (BOOL) isForAxisX WithValue : (CGFloat) value{
  229 +
  230 + if (isForAxisX) {
  231 + float temp = _startPointVectorX.x + (_vectorX_Steps / 2) ;
  232 + CGFloat xPos = temp + (((value - _AxisX_minValue)/_AxisX_step) * _vectorX_Steps) ;
  233 + return xPos;
  234 + }
  235 + else {
  236 + float temp = _startPointVectorY.y - (_vectorY_Steps / 2) ;
  237 + CGFloat yPos = temp - (((value - _AxisY_minValue) /_AxisY_step) * _vectorY_Steps);
  238 + return yPos;
  239 + }
  240 + return 0;
  241 +}
  242 +
  243 +#pragma mark - Update Chart Data
  244 +
  245 +- (void)updateChartData:(NSArray *)data
  246 +{
  247 + _chartData = data;
  248 +
  249 + // will be work in future.
  250 +}
  251 +
  252 +#pragma drawing methods
  253 +
  254 +- (void)drawRect:(CGRect)rect
  255 +{
  256 + [super drawRect:rect];
  257 +
  258 + CGContextRef context = UIGraphicsGetCurrentContext();
  259 + if (_showCoordinateAxis) {
  260 + CGContextSetStrokeColorWithColor(context, [_axisColor CGColor]);
  261 + CGContextSetLineWidth(context, _axisWidth);
  262 + //drawing x vector
  263 + CGContextMoveToPoint(context, _startPoint.x, _startPoint.y);
  264 + CGContextAddLineToPoint(context, _endPointVecotrX.x, _endPointVecotrX.y);
  265 + //drawing y vector
  266 + CGContextMoveToPoint(context, _startPoint.x, _startPoint.y);
  267 + CGContextAddLineToPoint(context, _endPointVecotrY.x, _endPointVecotrY.y);
  268 + //drawing x arrow vector
  269 + CGContextMoveToPoint(context, _endPointVecotrX.x, _endPointVecotrX.y);
  270 + CGContextAddLineToPoint(context, _endPointVecotrX.x - 5, _endPointVecotrX.y + 3);
  271 + CGContextMoveToPoint(context, _endPointVecotrX.x, _endPointVecotrX.y);
  272 + CGContextAddLineToPoint(context, _endPointVecotrX.x - 5, _endPointVecotrX.y - 3);
  273 + //drawing y arrow vector
  274 + CGContextMoveToPoint(context, _endPointVecotrY.x, _endPointVecotrY.y);
  275 + CGContextAddLineToPoint(context, _endPointVecotrY.x - 3, _endPointVecotrY.y + 5);
  276 + CGContextMoveToPoint(context, _endPointVecotrY.x, _endPointVecotrY.y);
  277 + CGContextAddLineToPoint(context, _endPointVecotrY.x + 3, _endPointVecotrY.y + 5);
  278 + }
  279 +
  280 + if (_showLabel) {
  281 + NSString *str;
  282 + //drawing x steps vector and putting axis x labels
  283 + float temp = _startPointVectorX.x + (_vectorX_Steps / 2) ;
  284 + for (int i = 0; i < _axisX_labels.count; i++) {
  285 + UIBezierPath *path = [UIBezierPath bezierPath];
  286 + [path moveToPoint:CGPointMake(temp, _startPointVectorX.y - 2)];
  287 + [path addLineToPoint:CGPointMake(temp, _startPointVectorX.y + 3)];
  288 + CAShapeLayer *shapeLayer = [CAShapeLayer layer];
  289 + shapeLayer.path = [path CGPath];
  290 + shapeLayer.strokeColor = [_axisColor CGColor];
  291 + shapeLayer.lineWidth = _axisWidth;
  292 + shapeLayer.fillColor = [_axisColor CGColor];
  293 + [self.horizentalLinepathLayer addObject:shapeLayer];
  294 + [self.layer addSublayer:shapeLayer];
  295 + UILabel *lb = [_axisX_labels objectAtIndex:i] ;
  296 + str = lb.text;
  297 + [self showXLabel:lb InPosition:CGPointMake(temp - 15, _startPointVectorX.y + 10 )];
  298 + temp = temp + _vectorX_Steps ;
  299 + }
  300 + //drawing y steps vector and putting axis x labels
  301 + temp = _startPointVectorY.y - (_vectorY_Steps / 2) ;
  302 + for (int i = 0; i < _axisY_labels.count; i++) {
  303 + UIBezierPath *path = [UIBezierPath bezierPath];
  304 + [path moveToPoint:CGPointMake(_startPointVectorY.x - 3, temp)];
  305 + [path addLineToPoint:CGPointMake( _startPointVectorY.x + 2, temp)];
  306 + CAShapeLayer *shapeLayer = [CAShapeLayer layer];
  307 + shapeLayer.path = [path CGPath];
  308 + shapeLayer.strokeColor = [_axisColor CGColor];
  309 + shapeLayer.lineWidth = _axisWidth;
  310 + shapeLayer.fillColor = [_axisColor CGColor];
  311 + [self.verticalLineLayer addObject:shapeLayer];
  312 + [self.layer addSublayer:shapeLayer];
  313 + UILabel *lb = [_axisY_labels objectAtIndex:i];
  314 + str = lb.text;
  315 + [self showXLabel:lb InPosition:CGPointMake(_startPointVectorY.x - 30, temp - 5)];
  316 + temp = temp - _vectorY_Steps ;
  317 + }
  318 + }
  319 + CGContextDrawPath(context, kCGPathStroke);
  320 +}
  321 +
  322 +- (CAShapeLayer*) drawingPointsForChartData : (PNScatterChartData *) chartData AndWithX : (CGFloat) X AndWithY : (CGFloat) Y
  323 +{
  324 + if (chartData.inflexionPointStyle == PNScatterChartPointStyleCircle) {
  325 + float radius = chartData.size;
  326 + CAShapeLayer *circle = [CAShapeLayer layer];
  327 + // Make a circular shape
  328 + circle.path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(X - radius, Y - radius, 2.0*radius, 2.0*radius)
  329 + cornerRadius:radius].CGPath;
  330 + // Configure the apperence of the circle
  331 + circle.fillColor = [chartData.fillColor CGColor];
  332 + circle.strokeColor = [chartData.strokeColor CGColor];
  333 + circle.lineWidth = 1;
  334 +
  335 + // Add to parent layer
  336 + return circle;
  337 + }
  338 + else if (chartData.inflexionPointStyle == PNScatterChartPointStyleSquare) {
  339 + float side = chartData.size;
  340 + CAShapeLayer *square = [CAShapeLayer layer];
  341 + // Make a circular shape
  342 + square.path = [UIBezierPath bezierPathWithRect:CGRectMake(X - (side/2) , Y - (side/2), side, side)].CGPath ;
  343 + // Configure the apperence of the circle
  344 + square.fillColor = [chartData.fillColor CGColor];
  345 + square.strokeColor = [chartData.strokeColor CGColor];
  346 + square.lineWidth = 1;
  347 +
  348 + // Add to parent layer
  349 + return square;
  350 + }
  351 + else {
  352 + // you cann add your own scatter chart poin here
  353 + }
  354 + return nil ;
  355 +}
  356 +
  357 +- (void) drawLineFromPoint : (CGPoint) startPoint ToPoint : (CGPoint) endPoint WithLineWith : (CGFloat) lineWidth AndWithColor : (UIColor*) color{
  358 +
  359 + // call the same method on a background thread
  360 + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
  361 + [NSThread sleepForTimeInterval:2];
  362 + // calculating start and end point
  363 + __block CGFloat startX = [self mappingIsForAxisX:true WithValue:startPoint.x];
  364 + __block CGFloat startY = [self mappingIsForAxisX:false WithValue:startPoint.y];
  365 + __block CGFloat endX = [self mappingIsForAxisX:true WithValue:endPoint.x];
  366 + __block CGFloat endY = [self mappingIsForAxisX:false WithValue:endPoint.y];
  367 + // update UI on the main thread
  368 + dispatch_async(dispatch_get_main_queue(), ^{
  369 + // drawing path between two points
  370 + UIBezierPath *path = [UIBezierPath bezierPath];
  371 + [path moveToPoint:CGPointMake(startX, startY)];
  372 + [path addLineToPoint:CGPointMake(endX, endY)];
  373 + CAShapeLayer *shapeLayer = [CAShapeLayer layer];
  374 + shapeLayer.path = [path CGPath];
  375 + shapeLayer.strokeColor = [color CGColor];
  376 + shapeLayer.lineWidth = lineWidth;
  377 + shapeLayer.fillColor = [color CGColor];
  378 + // adding animation to path
  379 + CABasicAnimation *animateStrokeEnd = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
  380 + animateStrokeEnd.duration = _duration;
  381 + animateStrokeEnd.fromValue = [NSNumber numberWithFloat:0.0f];
  382 + animateStrokeEnd.toValue = [NSNumber numberWithFloat:1.0f];
  383 + [shapeLayer addAnimation:animateStrokeEnd forKey:nil];
  384 + [self.layer addSublayer:shapeLayer];
  385 + });
  386 + });
  387 +}
  388 +
  389 +@end
  1 +//
  2 +// PNScatterChartData.h
  3 +// PNChartDemo
  4 +//
  5 +// Created by Alireza Arabi on 12/4/14.
  6 +// Copyright (c) 2014 kevinzhow. All rights reserved.
  7 +//
  8 +
  9 +#import <Foundation/Foundation.h>
  10 +
  11 +typedef NS_ENUM(NSUInteger, PNScatterChartPointStyle) {
  12 + PNScatterChartPointStyleCircle = 0,
  13 + PNScatterChartPointStyleSquare = 1,
  14 +};
  15 +
  16 +@class PNScatterChartDataItem;
  17 +
  18 +typedef PNScatterChartDataItem *(^LCScatterChartDataGetter)(NSUInteger item);
  19 +
  20 +@interface PNScatterChartData : NSObject
  21 +
  22 +@property (strong) UIColor *fillColor;
  23 +@property (strong) UIColor *strokeColor;
  24 +
  25 +@property NSUInteger itemCount;
  26 +@property (copy) LCScatterChartDataGetter getData;
  27 +
  28 +@property (nonatomic, assign) PNScatterChartPointStyle inflexionPointStyle;
  29 +
  30 +/**
  31 + * If PNLineChartPointStyle is circle, this returns the circle's diameter.
  32 + * If PNLineChartPointStyle is square, each point is a square with each side equal in length to this value.
  33 + */
  34 +@property (nonatomic, assign) CGFloat size;
  35 +
  36 +
  37 +@end
  1 +//
  2 +// PNScatterChartData.m
  3 +// PNChartDemo
  4 +//
  5 +// Created by Alireza Arabi on 12/4/14.
  6 +// Copyright (c) 2014 kevinzhow. All rights reserved.
  7 +//
  8 +
  9 +#import "PNScatterChartData.h"
  10 +
  11 +@implementation PNScatterChartData
  12 +
  13 +- (id)init
  14 +{
  15 + self = [super init];
  16 + if (self) {
  17 + [self setDefaultValues];
  18 + }
  19 +
  20 + return self;
  21 +}
  22 +
  23 +- (void)setDefaultValues
  24 +{
  25 + _inflexionPointStyle = PNScatterChartPointStyleCircle;
  26 + _fillColor = [UIColor grayColor];
  27 + _strokeColor = [UIColor clearColor];
  28 + _size = 3 ;
  29 +}
  30 +
  31 +@end
  1 +//
  2 +// PNScatterChartDataItem.h
  3 +// PNChartDemo
  4 +//
  5 +// Created by Alireza Arabi on 12/4/14.
  6 +// Copyright (c) 2014 kevinzhow. All rights reserved.
  7 +//
  8 +
  9 +#import <Foundation/Foundation.h>
  10 +
  11 +@interface PNScatterChartDataItem : NSObject
  12 +
  13 ++ (PNScatterChartDataItem *)dataItemWithX:(CGFloat)x AndWithY:(CGFloat)y;
  14 +
  15 +@property (readonly) CGFloat x; // should be within the x range
  16 +@property (readonly) CGFloat y; // should be within the y range
  17 +
  18 +@end
  1 +//
  2 +// PNScatterChartDataItem.m
  3 +// PNChartDemo
  4 +//
  5 +// Created by Alireza Arabi on 12/4/14.
  6 +// Copyright (c) 2014 kevinzhow. All rights reserved.
  7 +//
  8 +
  9 +#import "PNScatterChartDataItem.h"
  10 +
  11 +@interface PNScatterChartDataItem ()
  12 +
  13 +- (id)initWithX:(CGFloat)x AndWithY:(CGFloat)y;
  14 +
  15 +@property (readwrite) CGFloat x; // should be within the x range
  16 +@property (readwrite) CGFloat y; // should be within the y range
  17 +
  18 +@end
  19 +
  20 +@implementation PNScatterChartDataItem
  21 +
  22 ++ (PNScatterChartDataItem *)dataItemWithX:(CGFloat)x AndWithY:(CGFloat)y
  23 +{
  24 + return [[PNScatterChartDataItem alloc] initWithX:x AndWithY:y];
  25 +}
  26 +
  27 +- (id)initWithX:(CGFloat)x AndWithY:(CGFloat)y
  28 +{
  29 + if ((self = [super init])) {
  30 + self.x = x;
  31 + self.y = y;
  32 + }
  33 +
  34 + return self;
  35 +}
  36 +
  37 +@end
@@ -142,6 +142,24 @@ @@ -142,6 +142,24 @@
142 <segue destination="Tha-Wr-sPW" kind="push" identifier="pieChart" id="pvQ-oy-a9a"/> 142 <segue destination="Tha-Wr-sPW" kind="push" identifier="pieChart" id="pvQ-oy-a9a"/>
143 </connections> 143 </connections>
144 </tableViewCell> 144 </tableViewCell>
  145 + <tableViewCell contentMode="scaleToFill" selectionStyle="blue" accessoryType="disclosureIndicator" indentationLevel="1" indentationWidth="0.0" textLabel="YOU-SK-mQU" style="IBUITableViewCellStyleDefault" id="JJR-oU-C7n">
  146 + <rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
  147 + <autoresizingMask key="autoresizingMask"/>
  148 + <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="JJR-oU-C7n" id="iJk-3W-tcy">
  149 + <autoresizingMask key="autoresizingMask"/>
  150 + <subviews>
  151 + <label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="ScatterChart" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="YOU-SK-mQU">
  152 + <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
  153 + <fontDescription key="fontDescription" type="system" pointSize="18"/>
  154 + <color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
  155 + <nil key="highlightedColor"/>
  156 + </label>
  157 + </subviews>
  158 + </tableViewCellContentView>
  159 + <connections>
  160 + <segue destination="Tha-Wr-sPW" kind="push" identifier="scatterChart" id="V7s-JV-4Nx"/>
  161 + </connections>
  162 + </tableViewCell>
145 </cells> 163 </cells>
146 </tableViewSection> 164 </tableViewSection>
147 </sections> 165 </sections>
@@ -174,6 +192,6 @@ @@ -174,6 +192,6 @@
174 <simulatedScreenMetrics key="destination" type="retina4"/> 192 <simulatedScreenMetrics key="destination" type="retina4"/>
175 </simulatedMetricsContainer> 193 </simulatedMetricsContainer>
176 <inferredMetricsTieBreakers> 194 <inferredMetricsTieBreakers>
177 - <segue reference="pvQ-oy-a9a"/> 195 + <segue reference="V7s-JV-4Nx"/>
178 </inferredMetricsTieBreakers> 196 </inferredMetricsTieBreakers>
179 </document> 197 </document>
@@ -16,6 +16,7 @@ @@ -16,6 +16,7 @@
16 @property (nonatomic) PNBarChart * barChart; 16 @property (nonatomic) PNBarChart * barChart;
17 @property (nonatomic) PNCircleChart * circleChart; 17 @property (nonatomic) PNCircleChart * circleChart;
18 @property (nonatomic) PNPieChart *pieChart; 18 @property (nonatomic) PNPieChart *pieChart;
  19 +@property (nonatomic) PNScatterChart *scatterChart;
19 20
20 @property (weak, nonatomic) IBOutlet UILabel *titleLabel; 21 @property (weak, nonatomic) IBOutlet UILabel *titleLabel;
21 22
@@ -7,6 +7,7 @@ @@ -7,6 +7,7 @@
7 // 7 //
8 8
9 #import "PCChartViewController.h" 9 #import "PCChartViewController.h"
  10 +#define ARC4RANDOM_MAX 0x100000000
10 11
11 @implementation PCChartViewController 12 @implementation PCChartViewController
12 13
@@ -120,6 +121,41 @@ @@ -120,6 +121,41 @@
120 [self.view addSubview:self.pieChart]; 121 [self.view addSubview:self.pieChart];
121 self.changeValueButton.hidden = YES; 122 self.changeValueButton.hidden = YES;
122 } 123 }
  124 + else if ([self.title isEqualToString:@"Scatter Chart"])
  125 + {
  126 + self.titleLabel.text = @"Scatter Chart";
  127 +
  128 + self.scatterChart = [[PNScatterChart alloc] initWithFrame:CGRectMake(SCREEN_WIDTH /6.0 - 30, 135, 280, 200)];
  129 + [self.scatterChart setAxisXWithMinimumValue:20 andMaxValue:100 toTicks:6];
  130 + [self.scatterChart setAxisYWithMinimumValue:30 andMaxValue:50 toTicks:5];
  131 +
  132 + NSArray * data01Array = [self randomSetOfObjects];
  133 + PNScatterChartData *data01 = [PNScatterChartData new];
  134 + data01.strokeColor = PNGreen;
  135 + data01.fillColor = PNFreshGreen;
  136 + data01.size = 2;
  137 + data01.itemCount = [[data01Array objectAtIndex:0] count];
  138 + data01.inflexionPointStyle = PNScatterChartPointStyleCircle;
  139 + __block NSMutableArray *XAr1 = [NSMutableArray arrayWithArray:[data01Array objectAtIndex:0]];
  140 + __block NSMutableArray *YAr1 = [NSMutableArray arrayWithArray:[data01Array objectAtIndex:1]];
  141 + data01.getData = ^(NSUInteger index) {
  142 + CGFloat xValue = [[XAr1 objectAtIndex:index] floatValue];
  143 + CGFloat yValue = [[YAr1 objectAtIndex:index] floatValue];
  144 + return [PNScatterChartDataItem dataItemWithX:xValue AndWithY:yValue];
  145 + };
  146 +
  147 + [self.scatterChart setup];
  148 + self.scatterChart.chartData = @[data01];
  149 +/***
  150 + this is for drawing line to compare
  151 + CGPoint start = CGPointMake(20, 35);
  152 + CGPoint end = CGPointMake(80, 45);
  153 + [self.scatterChart drawLineFromPoint:start ToPoint:end WithLineWith:2 AndWithColor:PNBlack];
  154 +***/
  155 + self.scatterChart.delegate = self;
  156 + self.changeValueButton.hidden = YES;
  157 + [self.view addSubview:self.scatterChart];
  158 + }
123 } 159 }
124 160
125 161
@@ -171,6 +207,10 @@ @@ -171,6 +207,10 @@
171 { 207 {
172 [self.circleChart updateChartByCurrent:@(arc4random() % 100)]; 208 [self.circleChart updateChartByCurrent:@(arc4random() % 100)];
173 } 209 }
  210 + else if ([self.title isEqualToString:@"Scatter Chart"])
  211 + {
  212 + // will be code soon.
  213 + }
174 214
175 } 215 }
176 216
@@ -195,4 +235,19 @@ @@ -195,4 +235,19 @@
195 [bar.layer addAnimation:animation forKey:@"Float"]; 235 [bar.layer addAnimation:animation forKey:@"Float"];
196 } 236 }
197 237
  238 +/* this function is used only for creating random points */
  239 +- (NSArray *) randomSetOfObjects{
  240 + NSMutableArray *array = [NSMutableArray array];
  241 + NSString *LabelFormat = @"%1.f";
  242 + NSMutableArray *XAr = [NSMutableArray array];
  243 + NSMutableArray *YAr = [NSMutableArray array];
  244 + for (int i = 0; i < 25 ; i++) {
  245 + [XAr addObject:[NSString stringWithFormat:LabelFormat,(((double)arc4random() / ARC4RANDOM_MAX) * (self.scatterChart.AxisX_maxValue - self.scatterChart.AxisX_minValue) + self.scatterChart.AxisX_minValue)]];
  246 + [YAr addObject:[NSString stringWithFormat:LabelFormat,(((double)arc4random() / ARC4RANDOM_MAX) * (self.scatterChart.AxisY_maxValue - self.scatterChart.AxisY_minValue) + self.scatterChart.AxisY_minValue)]];
  247 + }
  248 + [array addObject:XAr];
  249 + [array addObject:YAr];
  250 + return (NSArray*) array;
  251 +}
  252 +
198 @end 253 @end
@@ -40,9 +40,12 @@ @@ -40,9 +40,12 @@
40 //Add pie chart 40 //Add pie chart
41 41
42 viewController.title = @"Pie Chart"; 42 viewController.title = @"Pie Chart";
  43 + } else if ([segue.identifier isEqualToString:@"scatterChart"])
  44 + {
  45 + //Add scatter chart
  46 +
  47 + viewController.title = @"Scatter Chart";
43 } 48 }
44 } 49 }
45 50
46 -  
47 -  
48 @end 51 @end