Difficulty with multiple plot spaces in CorePLot - core-plot

I have several graphs to be plotted over each other, and I need them to share an x axis of time, but have different Y-Axes... To do this, I know I have to create a new plot space for the 2nd through n-th graph, and add those plot spaces to the graph:
Here is a snippet from my "Add a new graph to the diagram" function
BOOL isNew=FALSE;
CPTXYPlotSpace *defaultPlotSpace = (CPTXYPlotSpace *)graph.defaultPlotSpace;
CPTXYPlotSpace *plotSpace=nil;
if([g_Data count]==1){
plotSpace = (CPTXYPlotSpace *)graph.defaultPlotSpace;
NSLog(#"Reuse existing plot space");
}
else
{
NSLog(#"New plot space");
plotSpace = [[CPTXYPlotSpace alloc] init];
isNew=TRUE;
}
[dataDictionary setObject:plotSpace forKey:#"plotspace"];
float xSize=[mainGraphView bounds].size.width;
float ySize=[mainGraphView bounds].size.height;
float XRatio=(xSize-50.0)/xSize;
float YRatio=(ySize-50.0)/ySize;
NSDecimalNumber *plotWidth=[x_max decimalNumberBySubtracting:x_min];
plotWidth=[plotWidth decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:[NSString stringWithFormat:#"%0.2f",XRatio]]];
NSDecimalNumber *plotX=[x_min decimalNumberBySubtracting:[plotWidth decimalNumberBySubtracting:[x_max decimalNumberBySubtracting:x_min]]];
NSDecimalNumber *plotHeight=[y_max decimalNumberBySubtracting:y_min];
plotHeight=[plotHeight decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:[NSString stringWithFormat:#"%0.2f",YRatio]]];
NSDecimalNumber *plotY=[y_min decimalNumberBySubtracting:[plotHeight decimalNumberBySubtracting:[y_max decimalNumberBySubtracting:y_min]]];
NSLog(#"%#: XRange: Original: %# x %0.2f becomes %#",identifier,[x_max decimalNumberBySubtracting:x_min],XRatio,plotWidth);
NSLog(#"%#: YRange: %#-%# is %# x %0.2f becomes %#",identifier,y_min,y_max,[y_max decimalNumberBySubtracting:y_min],YRatio,plotHeight);
if(isNew){
plotSpace.xRange = defaultPlotSpace.xRange;
}
else
{
plotSpace.xRange = [CPTPlotRange plotRangeWithLocation:[plotX decimalValue] length:[plotWidth decimalValue]];
}
plotSpace.yRange = [CPTPlotRange plotRangeWithLocation:[plotY decimalValue]
length:[plotHeight decimalValue]];
NSLog(#"**********YPLOT IS FROM %# len %#",plotY,plotHeight );
plotSpace.allowsUserInteraction=TRUE;
if(isNew)[graph addPlotSpace:plotSpace];
CPTScatterPlot *newPlot = [[CPTScatterPlot alloc] initWithFrame:graph.bounds];
newPlot.identifier = identifier;
newPlot.dataSource = self;
CPTMutableLineStyle *lineStyle = [newPlot.dataLineStyle mutableCopy];
lineStyle.lineWidth = 2.0;
lineStyle.lineColor = graphColor;
newPlot.dataLineStyle = lineStyle;
[g_Plots addObject:newPlot];
[graph addPlot:newPlot toPlotSpace:plotSpace];
NSLog(#"Adding plot to graph system");
[graph addPlot:newPlot];
and my log:
2013-10-28 15:24:35.166 BodyMetrics[2234:303] -------[NEW PLOT FOR Pulse (bpm)]-----------------------------------------------------------
2013-10-28 15:24:35.169 BodyMetrics[2234:303] 85 rows for data: BM_Measure measuredate measuretype = 'Heart Pulse'
2013-10-28 15:24:35.173 BodyMetrics[2234:303] The size of the arrays for x and y are: 85;85
2013-10-28 15:24:35.173 BodyMetrics[2234:303] XMIN: 1380566085 XMAX: 1382980783
2013-10-28 15:24:35.173 BodyMetrics[2234:303] YMIN: 43 YMAX: 154
2013-10-28 15:24:35.173 BodyMetrics[2234:303] Reuse existing plot space
2013-10-28 15:24:35.174 BodyMetrics[2234:303] Pulse (bpm): XRange: Original: 2414698 x 0.95 becomes 2541787.36842105263157894736842105263157
2013-10-28 15:24:35.174 BodyMetrics[2234:303] Pulse (bpm): YRange: 43-154 is 111 x 0.90 becomes 123.333333333333333333333333333333333333
2013-10-28 15:24:35.174 BodyMetrics[2234:303] **********YPLOT IS FROM 30.666666666666666666666666666666666667 len 123.333333333333333333333333333333333333
2013-10-28 15:24:35.175 BodyMetrics[2234:303] Adding plot to graph system
2013-10-28 15:24:35.176 BodyMetrics[2234:303] Added... 1
2013-10-28 15:24:35.176 BodyMetrics[2234:303] Configure axes
2013-10-28 15:24:35.177 BodyMetrics[2234:303] Now addign Y axes...
2013-10-28 15:24:35.177 BodyMetrics[2234:303] Creating axis for Pulse (bpm)
2013-10-28 15:24:35.177 BodyMetrics[2234:303] Reusing the existing Y Axis...
2013-10-28 15:24:35.178 BodyMetrics[2234:303] This axes is from 43 to 154 being a range of 111 so the major ticks will bat 10.3 floats away, for an interval length of 10.7766990291262135922330097087378640776
2013-10-28 15:24:35.178 BodyMetrics[2234:303] About to add the following axes: 2 (
"<<<CPTXYAxis: 0x10040ca80> bounds: {{0, 0}, {959, 515}}> with range: <<CPTPlotRange: 0x60800027cc40> {1380438995.6315789473684210526315789474, 2541787.36842105263157894736842105263157}> viewCoordinates: {0, 50} to {959, 50}>",
"<<<CPTXYAxis: 0x10040d8f0> bounds: {{0, 0}, {959, 515}}> with range: <<CPTPlotRange: 0x60800027cd00> {30.666666666666666666666666666666666667, 123.333333333333333333333333333333333333}> viewCoordinates: {50, 0} to {50, 515}>"
)
2013-10-28 15:24:35.179 BodyMetrics[2234:303] Added
2013-10-28 15:24:35.179 BodyMetrics[2234:303] -------[NEW PLOT FOR Weight (Kg)]-----------------------------------------------------------
2013-10-28 15:24:35.181 BodyMetrics[2234:303] 44 rows for data: BM_Measure measuredate measuretype = 'Weight'
2013-10-28 15:24:35.183 BodyMetrics[2234:303] The size of the arrays for x and y are: 44;44
2013-10-28 15:24:35.183 BodyMetrics[2234:303] XMIN: 1380330622 XMAX: 1382957809
2013-10-28 15:24:35.183 BodyMetrics[2234:303] YMIN: 83.225 YMAX: 85.701
2013-10-28 15:24:35.183 BodyMetrics[2234:303] New plot space
2013-10-28 15:24:35.183 BodyMetrics[2234:303] Weight (Kg): XRange: Original: 2627187 x 0.95 becomes 2765460
2013-10-28 15:24:35.184 BodyMetrics[2234:303] Weight (Kg): YRange: 83.225-85.701 is 2.476 x 0.90 becomes 2.75111111111111111111111111111111111111
2013-10-28 15:24:35.184 BodyMetrics[2234:303] **********YPLOT IS FROM 82.9498888888888888888888888888889 len 2.75111111111111111111111111111111111111
2013-10-28 15:24:35.184 BodyMetrics[2234:303] Adding plot to graph system
2013-10-28 15:24:35.184 BodyMetrics[2234:303] Added... 2
2013-10-28 15:24:35.185 BodyMetrics[2234:303] Configure axes
2013-10-28 15:24:35.185 BodyMetrics[2234:303] Now addign Y axes...
2013-10-28 15:24:35.185 BodyMetrics[2234:303] Creating axis for Pulse (bpm)
2013-10-28 15:24:35.185 BodyMetrics[2234:303] Reusing the existing Y Axis...
2013-10-28 15:24:35.185 BodyMetrics[2234:303] This axes is from 43 to 154 being a range of 111 so the major ticks will bat 10.3 floats away, for an interval length of 10.7766990291262135922330097087378640776
2013-10-28 15:24:35.186 BodyMetrics[2234:303] Creating axis for Weight (Kg)
2013-10-28 15:24:35.186 BodyMetrics[2234:303] Adding a new Y axis...
2013-10-28 15:24:35.186 BodyMetrics[2234:303] This axes is from 83.225 to 85.701 being a range of 2.476 so the major ticks will bat 10.3 floats away, for an interval length of 0.240388349514563106796116504854368932038
2013-10-28 15:24:35.187 BodyMetrics[2234:303] About to add the following axes: 2 (
"<<<CPTXYAxis: 0x10040ca80> bounds: {{0, 0}, {959, 515}}> with range: <<CPTPlotRange: 0x60800027cc40> {1380438995.6315789473684210526315789474, 2541787.36842105263157894736842105263157}> viewCoordinates: {0, 50} to {959, 50}>",
"<<<CPTXYAxis: 0x10040d8f0> bounds: {{0, 0}, {959, 515}}> with range: <<CPTPlotRange: 0x60800027cd00> {30.666666666666666666666666666666666667, 123.333333333333333333333333333333333333}> viewCoordinates: {50, 0} to {50, 515}>"
)
2013-10-28 15:24:35.187 BodyMetrics[2234:303] Added
However my graphs do not scale correctly:

You're adding the plot to the graph twice, first with [graph addPlot:newPlot toPlotSpace:plotSpace]; and again with [graph addPlot:newPlot];. The second call moves the plot back to the default plot space which is configured for the first plot.
Remove the redundant call to -addPlot:.

Related

Find outer-line of given shape

I have various solid shapes that i need to find the outer-lines for.
I get the shapes from an API, as a list of x,y-coordinates for every pixel in the shape. I would like to remove the "filler points" so i only have a list of the "outer-line", the red pixels in this image:
How can this be done?
If you open up that image and zoom in on it, you can easily see what distinguishes the red pixels from the blue ones: a red pixel has at least one white pixel either directly above, below, to the left or to the right of it, whereas a blue pixel has zero. Diagonals don't count.
So you can find the outer-line of the shape (the red pixels) with the following algorithm, given a list of pixel co-ordinates:
Convert all the pixel co-ordinates to integers if they aren't already.
Iterate through all the points in the list and find the min and max x and y co-ordinates.
Create an array with size [(max y - min y) + 1][(max x - min x) + 1] and set all the elements to 0
Iterate through all the points in the list and set array[point y - min y][point x - min x] to 1
Create an empty list for your outer-line co-ordinates
Iterate through the array, and for each element array[y][x]:
If array[y][x] equals 1 AND (array[y-1][x] equals 0 OR array[y+1][x] equals 0 OR array[y][x-1] equals 0 OR array[y][x+1] equals 0), then:
add (x + min x, y + min y) to the list of outer-line points.
Be careful that (max y - min y) and (max x - min x) are not to large, or you might get an out of memory error when trying to allocate the array. Also, to avoid index out of bounds errors when checking the array, just add any pixel at the edges of the array (x or y = 0, x or y = x or y array size - 1) where array[y][x] equals 1 to the list and avoid the other checks.
You can use CAShapeLayer,
here is one example for how to achieve that.
CAShapeLayer *shape = [CAShapeLayer layer];
shape.frame = self.label.bounds; // Give your created shape bounds
shape.path = maskPath.CGPath;
shape.lineWidth = 3.0f;
shape.strokeColor = [UIColor redColor].CGColor;
[self.label.layer addSublayer:shape];
You can use UIBiezerPath also, for connecting points,
Here is a example of that
UIBezierPath *aPath = [UIBezierPath bezierPath];
// Set the starting point of the shape.
[aPath moveToPoint:CGPointMake(100.0, 0.0)];
// Draw the lines.
[aPath addLineToPoint:CGPointMake(200.0, 40.0)];
[aPath addLineToPoint:CGPointMake(160, 140)];
[aPath addLineToPoint:CGPointMake(40.0, 140)];
[aPath addLineToPoint:CGPointMake(0.0, 40.0)];
// To make path closed you can use this
[aPath closePath];
Hope this helps you, Happy coding..

How to fix a gap between the x and y axes in core plot

I am using [_graph.defaultPlotSpace scaleToFitPlots:[_graph allPlots]];
and if where none of the plots has a y value of 0, there is a gap between the bottom of the Y axis and the X axis.
I've tried using _graph.axisSet.xAxis.orthogonalCoordinateDecimal = CPTDecimalFromDouble(0.0);
as well as a calculated yMin instead of 0.0.
Yet, I still get this:
I've also tried to rescale the plot space, thus:
[_graph.defaultPlotSpace setPlotRange:r forCoordinate:CPTCoordinateY];
but couldn't figure out how to set a new minLimit for r.
Use the axisConstraints to position the x-axis at the lower edge of the plot area:
x.axisConstraints = [CPTConstraints constraintWithLowerOffset:0.0];

Core Plot - Bar plot automatic initial zooming

How do I set an initial zoom based the maximum value of the x-axis and y-axis?
Example:
Plot 1:
Maximum value:
x-axis = 100;
y-axis = 110;
Plot 2:
Maximum value:
x-axis = 180;
y-axis = 230;
I need to the initial zoom be equal to two plots.
Regards
This will adjust the plot space to fit the plot data for two plots:
[plotSpace scaleToFitPlots:#[plot1, plot2]];
You can use this shortcut to scale the plot space to fit all of the plots in a graph:
[plotSpace scaleToFitPlots:[graph allPlots]];

Kivy garden-Graph absolute position of 0,0 on the graph

I'd like to find the relative position of the graph origin in order to display the correct mouse position when it's inside it. But the size and pos property of the graph class are relative to the labels too.
How can I find the absolute position of the point 0,0 on the graph?
There is a member Graph._plot_area. It is a StencilView and it's position and size are equal to the plot area of the graph, meaning it ranges from the start of the xmin, ymin to xmax, ymax in pixel position.
If graph point x,y = 0,0 is in view, it should be equal to _plot_area.pos, however if 0,0 is not in view, you will have to calculate where it is expected to be using a ratio for the x and y axis, they can be calculated by:
x_ratio = (xmax - xmin) / _plot_area.width
y_ratio = (ymax - ymin) / _plot_area.height
and the point calculated by:
x = xmin + x_ratio * ( x - xmin)
y = ymin + y_ratio * ( y - ymin)
Hope this helps!

Core-Plot : y Axis labels should start from 60

I need to draw a scatter plot, in which the x axis should intersect with y axis at (0,60).
I also need interval of 20 on the y Axis.
The problems I am facing right now are:
y axis is starting from 0
The gap between y axis labels example, from 60 - 80 is too much.
What I have done so far:
To set the intersection points:
x.orthogonalCoordinateDecimal = CPTDecimalFromString(#"60");
To set the major tick locations:
NSSet *majorTickLocations = [NSSet setWithObjects:[NSDecimalNumber zero],
[NSDecimalNumber numberWithUnsignedInteger:60],
[NSDecimalNumber numberWithUnsignedInteger:80],
[NSDecimalNumber numberWithUnsignedInteger:100],
[NSDecimalNumber numberWithUnsignedInteger:120],
nil];
y.majorTickLocations = majorTickLocations;
Any pointer in the direction will be helpful.
Regards,
Ishan
To make the axes cross at (0, 60), set the orthogonalCoordinateDecimal of each axis:
x.orthogonalCoordinateDecimal = CPTDecimalFromDouble(60.0);
y.orthogonalCoordinateDecimal = CPTDecimalFromDouble(0.0);
The axis labeling policy determines how the tick marks and labels are positioned. If you are providing the tick and label positions yourself (CPTAxisLabelingPolicyNone), you can put them anywhere you want. See the "Axis Labeling Policies" demo in the Plot Gallery example app for samples of each available labeling policy.

Resources