How do I pad a graph so that lines aren't clipped by the edges? - objective-c

I've had a pretty good look around for an answer to this, and tried several solutions in my code, nothing found so far.
I have a line graph that I am plotting, a CPTScatterPlot graph, and I have got points adding to it correctly. I want to show each of these points as a dot about 3-5 pixels in diameter, and connected by lines that are about 3 pixels wide. This all works fine.
The problem is that when the plot is a straight along one of the edges of the graph hosting view, the lines and dots are clipped and don't look right at all.
This is a mockup of what it should look like:
And this is the effect I am seeing much of the time at the moment:
I apologise for the small images, but hopefully you can see that in the second one, the line and dots are rendered only a few pixels into the graph view, not fully in view. In the second one the data is actually at y=1 for the first 75%, then falls down to y=0.
How can I inset the drawing of the graph components by several pixels to prevent the clipping of any shapes?
So far:
I have tried setting the padding on the graph, but that just
contracts the area it draws to, I suppose to make room for titles
which I am not using.
I have also tried adding to the min/max x/y range settings which I
recalculate based on the data I am updating in the background. This
works, but obviously only if the amount I add to those values is
correct in relation to the drawing scale that will be used for the
data values I am inputting.
I am on Mac OS using NSView (actually CPTGraphHostingView) so clipsToBounds isn't available. Also, I tried masksToBounds and masksToBorder on CPTXYGraph.

I think the easiest way to handle this is to simply extend your ranges by a small amount. There is a method in CPTPlotRange that makes it very easy to extend a given range by a fixed percentage (e.g. 1%). I think the main test app example even shows this in action.
Another option would be to turn off the masksToBounds and/or masksToBorder on the CPTPlotArea (plotArea) and possibly the CPTPlotAreaFrame (plotAreaFrame). You access them both via properties of the graph.

This might be of help..
The default padding on the graph itself (not the plot area frame) is 20 pixels on each side. You can change that, too.
graph.paddingLeft = 0.0;
graph.paddingTop = 0.0;
graph.paddingRight = 0.0;
graph.paddingBottom = 0.0;

Related

How do i set the borders of an mplot3d, and also make the grid lines lie behind the plot?

I have this plot as part of a PySide program;
And there are two problems I have with it. The first is the ugly grey border. I know I can can get rid of it using the toolbar option, but I can't find a way to it programatically, or make it default to that when it plots...
The second issue, is that it is drawing the grid lines on top of the surface, which I would rather it didn't do... How do I get the grid lines to be drawn underneath the surface?
EDIT:
i'm using version 1.1.1;
this doesn't happen for all plot types - i.e.
that is fine.
If i try and plot multiple objects, then it can be a problem;
but i understand that's a limitation of mplot3d not being a try 3D engine, just a set of 3D images with a Z-Ordering, so the order of objects drawn becomes orientation dependant. (same graph - different angle: enter link description here).
The grid lines should surely always be at the bottom of the drawing though, no? Is there a way to force them to be?
Will.

Trace a ccsprite cocos2d-iphone

I have a layer with a sprite of a simple black donut. I want the user to be able to draw on the sprite in a different color (which I've managed to do without any problem using CCRenderTexture).
My question is how I can calculate whether the image has been traced at least 95% (meaning, find out when 95% of the black pixels are now the new color). I've tried methods like taking a screenshot of the layer and counting the number of black pixels, but it hasn't worked that well (using this solution: https://stackoverflow.com/a/1262893/1577738).
It would be even better if I could just change the color of each pixel as it's touched (to avoid issues with coloring out of the lines). I could theoretically just split the donut into like 10 sprites and change that section's color if the user touches it, but that seems ridiculous if I give the user options to use a bunch of different colors.
Am I going about this the wrong way? Your suggestions are much appreciated!
Reading pixel colors will be rather inaccurate and slow. I suggest dividing the area into smaller rectangles (ie 8x8 or 4x4) and then flag each as "visited" when the user draws on it. If most rectangle areas are flagged, the user has drawn on most parts of the texture.

How to move a Core Plot graph

I have a Core-Plot Graph within a Mac Application. But the inside table is appearing shifted down and to the left of the containing "frame/border" so that neither of the axis' are showing. I cannot figure out how to change this does anyone know what parameters I need to change to fix this?
Update: Sorry I did not realize I could upload an image, I have done so know and will try your suggestions in the mean-time.
Not sure what you mean by "inside table". It would be easier to offer suggestions if you could post a screenshot.
Without seeing what's wrong, here are some common areas to look at:
If you haven't already done so, look at the example apps included with Core Plot for ideas. The Plot Gallery app has many sample plots and the others are useful, too.
You may need to add padding (paddingLeft, paddingBottom, etc.) on the graph and/or plot area frame. Padding the graph pushes everything in away from the edges of the graph. Padding the plot area frame pushes the plot area in so the axes and titles can hang outside the plot area (the area where the plots are drawn).
If you want to keep an axes pinned to a specific place, e.g., the edge of the graph, set up a floating axis. Otherwise make sure the orthogonal coordinate is set (it defaults to 0). For example, the orthogonal coordinate for the x-axis is the y-value where the x-axis crosses the y-axis.

Get size of an expanding circle in a CABasicAnimation at any point in time

I would like to know how I can get the diameter (or radius) of an expanding circle animation at a at any point in time during the animation. I will end up stoping the animation right after I get the size as well, but figure I couldn't stop and remove it form the layer until I get the size of the circle.
For an example of how the expanding circle animation is implemented, it is a variation on the implementation shown in the addGrowingCircleAtPoint:(CGPoint)point method in the answer in the iPhone Quartz2D render expanding circle question.
I have tried to check various values on the layers, animation, etc but can't seem to find anything. I figure worse case I can attempt to make a best guess by taking the current time it is into its animation and use that to figure where it "should" be at based on its to and from size states. This seems like overkill for what I would assume is a value that is incrementing someplace I can just get easily.
Update:
I have tried several properties on the Presentation Layer including the Transform which never seems to change all the values are always the same regardless of what size the circle is at the time checked.
Okay here is how you get the current state of the an animation while it is animating.
While Rob was close he left out two pieces of key information.
First from the layer.presentationLayer.subLayers you have to get the layer you are animating on, which for me is the only sub layer available.
Second, from this sub layer you cannot just access the transform directly you have to do it by valueForKeyPath to get transform.scale.x. I used x because its a circle and x and y are the same.
I then use this to calculate the size of the circle at the time of the based on the values used to create the Arc.
I assume what you're trying to get to is the current CATransform3D, and that from that, you can get to your circle size.
What you want is the layer.presentationLayer.transform. See the CALayer docs for details on the presentationLayer. Also see the Core Animation Rendering Architecture.

how to generate graphs using integer values in iphone

i want to show a grapph/bar chart in iphone how do i do this without custom API;s
You may want to investigate the Core Plot project [code.google.com]. Core Plot was the subject of this year's scientific coding project at WWDC and is pretty useable for some cases already. From its inception, Core Plot was intended for both OS X and iPhone uses. The source distribution (there hasn't been a binary release yet) comes with both OS X and iPhone example applications and there's info on the project wiki for using it as a library in an iPhone app. Here's an example of it's current plotting capabilities.
(source: googlecode.com)
Write your own. It's not easy, I'm in the process of doing the same thing right now. Here's how I'm doing it:
First, ignore any desire you may have to try using a UIScrollView if you want to allow zooming. It's totally not worth it.
Second, create something like a GraphElement protocol. I have a hierarchy that looks something like this:
GraphElement
GraphPathElement
GraphDataElement
GraphDataSupplierElement
GraphElement contains the basic necessary methods for a graph element, including how to draw, a maximum width (for zooming in), whether a point is within that element (for touches) and the standard touchBegan, touchMoved, and touchEnded functions.
GraphPathElement contains a CGPath, a line color and width, a fill color and a drawing mode. Whenever it's prompted to draw, it simply adds the path to the context, sets the colors and line width, and draws the path with the given drawing mode.
GraphDataElement, as a subclass of GraphPathElement, takes in a set of data in x-y coordinates, a graph type (bar or line), a frame, and a bounds. The frame is the actual size of the created output CGPath. The bounds is the size of the data in input coordinates. Essentially, it lets you scale the data to the screen size.
It creates a graph by first calculating an affine transform to transform the bounds to the frame, then it loops through each point and adds it as data to a path, applying that transform to the point before adding it. How it adds data depends on the type.
If it's a bar graph, it creates a rectangle of width 0, origin at (x,frame.size.height-y), and height=y. Then it "insets" the graph by -3 pixels horizontally, and adds that to the path.
If it's a line graph, it's much simpler. It just moves to the first point, then for each other point, it adds a line to that point, adds a circle in a rect around that point, then moves back to that point to go on to the next point.
GraphDataSupplierElement is the interface to my database that actually contains all the data. It determines what kind of graph it should be, formats the data into the required type for GraphDataElement, and passes it on, with the color to use for that particular graph.
For me, the x-axis is time, and is represented as NSTimeIntervals. The GraphDataSupplierElement contains a minDate and maxDate so that a GraphDateElement can draw the x-axis labels as required.
Once all this is done, you need to create the actual graph. You can go about it several ways. One option is to keep all the elements in an NSArray and whenever drawRect: is called, loop through each element and draw it. Another option is to create a CALayer for each element, and use the GraphPathElement as the CALayer's delegate. Or you could make GraphPathElement extend from CALayer directly. It's up to you on this one. I haven't gotten as far as trying CALayers yet, I'm still stuck in the simple NSArray stage. I may move to CALayers at some point, once I'm satisfied with how everything looks.
So, all in all, the idea is that you create the graph as one or many CGPaths beforehand, and just draw that when you need to draw the graph, rather than trying to actually parse data whenever you get a drawRect: call.
Scaling can be done by keeping the source data in your GraphDataElement, and just change the frame so that the scaling of the bounds to the frame creates a CGPath wider than the screen, or whatever your needs are. I basically re-implemented my own pinch-zoom for my Graph UIView subclass that only scales horizontally, by changing its transform, then on completion, get the current frame, reset the transform to identity, set the frame to the saved value, and set the frame of all of the GraphElements to the new frame as well, to make them scale. Then just call [self setNeedsDisplay] to draw.
Anyway, that's a bit ramble-ish, but it's an outline of how I made it happen. If you have more specific questions, feel free to comment.