Drawing a chart with gradient in Objective C - objective-c

I'm trying to make a simple app where a chart is drawn with a line and X axis. I want to fill parts of the view enclosed by chart and X axis with gradient. To fill them I use the following code
CGContextSaveGState(c);
CGContextAddPath(c, CGContextCopyPath(c));
CGContextClip(c);
CGContextDrawLinearGradient(c, g, previousPointOfIntersection, intersectionPoint, 0);
CGContextRestoreGState(c);
every time the line crosses the X axis. However, the problem is that the gradient fills the whole view between previous point of intersection and current one.
Is this a right way to draw a gradient for a part of view enclosed by lines?
I'd be very happy to hear any suggestions regarding my problem :)
P.S. here's the code of my class http://pastebin.com/wYiHkuVi

I'd say you don't have the path in the context that you think you do.
If you've "stroked" the path for your graph it's been used up.
Replace your Add Path with:
CGContextAddEllipseInRect(c, self.bounds);
to see if you get some clipping occurring.
If so, then you need to rebuild your path here instead of the AddPath/Ellipse code.

Related

How to draw half an ellipse in Win2D?

I want to draw either the lower or the upper half of an elliptical arc using Win2D in a C++/winrt app. I can draw the curve, but it includes a diagonal line at its start that looks as if I had begun with a straight line segment - as if the figure didn't begin at the arc but rather some distance down and to the right. How I can restrict drawing to just the arc? Here is the code and an image of the result:
float2 arcSize(100, 6);
auto pathBuilder = CanvasPathBuilder(drawingSession.Device());
pathBuilder.BeginFigure(244, 175);
//Starting at 3 o"clock, sweep pi radians, that is, to 9:00
pathBuilder.AddArc(arcSize,50,6,0.0, 3.14);
pathBuilder.EndFigure(CanvasFigureLoop::Open); //Don't close path
auto geometry = CanvasGeometry::CreatePath(pathBuilder);
session.DrawGeometry(geometry,244, 175, Colors::Black(),1.5);
OK, thanks to that hint from Inspectable I have the solution: the problem lies in where the path begins. In my code I had mistakenly used the proposed arc size as the first argument to AddArc when really that should be the arc center coordinates. And the BeginFigure in the case of this arc must be the point lying at the right edge, at what would be 3:00 in a circle. With the ArcCenter correct in relation to the BeginFigure then AddArc doesn't draw the extra line.
[Update:] p.s. The x and y coordinates for the DrawGeometry call should be zero in this case; that draws it at its original coordinates from BeginFigure, not offset. Maybe this p.s can gain me another -1 for this question.

Smoothly painting a path of straight line segments in Qt5

I have a series of straight line segments of varying thickness connected end-to-end to create meandering path. Does anyone know a way to paint this as a smooth meandering line, sort of like vectorizing it? I am using QPainter. I haven't had any success finding an appropriate function in QPainterPath.
The data looks something like this:
[(QPointF, width), (QPointF, width), (QPointF, width), ... ]
Thanks!
EDIT: Added example image
I wanted to leave it open to creative responses, but I am just looking to move from linear interpolation (QPainter::drawLine()) to spline interpolation.
If I understand your question correctly...
Don't draw a line, draw a filled polygon that encloses your line data with the right thickness. Drawback: That requires calculations on your data beforehand.

Draw rotated text to parent coordinate system

I have a UIView, which I'm drawing manually in the 'drawRect'-Function.
It is basically a coordinate system, which has 'Values' on the Y-Axis and 'Time' on the 'X-Axis'.
Due to space issues, I want the Timestamps to be vertical, instead of horizontal.
For this purpose, I use:
CGContextSaveGState(ctx); //Saves the current graphic context state
CGContextRotateCTM(ctx, M_PI_2); //Rotates the context by 90° clockwise
strPos = CGContextConvertPointToUserSpace(ctx, strPos); //SHOULD convert to Usercoordinates
[str drawAtPoint:strPos withFont:fnt]; //Draws the text to the rotated CTM
CGContextRestoreGState(ctx); //Restores the CTM to the previous state.
ctx (CGContextRef), strPos (CGPoint) and str (NSString) are variables, that have been initialized properly and correctly for 'horizontal text', with a width of the text height.
While this code works flawlessly on the iPhone 3, it gives me a complete mess on the iPhone 4 (Retina), because the CGContextConvertPointToUserSpace function produces completely different results, even though the coordinate system of the iPhone is supposed to remain the same.
I also tried using CGAffineTransform, but only with the same results.
To summarize my question: How do I draw a text to a calculated position in the parent coordinate system (0, 0 being top left)?
After studying the Apple docs regarding Quartz 2D once more, I came to realize, that the rotation by Pi/2 moves all my writing off screen to the left.
I can make the writing appear in a vertical line by translating the CTM by +height.
I'll keep trying, but would still be happy to get an answer.
Edit: Thanks to lawicko's heads-up I was able to fix the problem. See Answer for details.
I would like to thank lawicko for pointing this out.
During my tests I made two mistakes...but he is of course correct. Using CGContextShowTextAtPoint is the most simple solution, since it doesn't require the rotation of the entire CTM.
Again, THANK you.
Now, for the actual answer to my question.
To draw a rotated text at position x/y, the following code works for me.
CGAffineTransform rot = CGAffineTransformMakeRotation(M_PI_2); //Creates the rotation
CGContextSelectFont(ctx, "TrebuchetMS", 10, kCGEncodingMacRoman); //Selects the font
CGContextSetTextMatrix(ctx, CGAffineTransformScale(rot, 1, -1)); //Mirrors the rotated text, so it will be displayed correctly.
CGContextShowTextAtPoint(ctx, strPos.x, strPos.y, TS, 5); //Draws the text
ctx is the CGContext, strPos the desired position in the parent coordinate system, TS a char array.
Again, thank you lawicko.
I probably would've searched forever if not for your suggestion.
Maybe this answer will help someone else, who comes across the same problem.

Core Plot - adding a vertical/horizontal line indicator on a selected value point

I am using core plot to make a line graph for my iPhone app. So far I successfully made the line graph from my xml data.
Furthermore I added a text layer that shows the value (for example 40) once I select the cell
holding the value 40. For this, I use the function:
(CPTLayer *)dataLabelForPlot:(CPTPlot *)plot recordIndex:(NSUInteger)index
So now I want to have a vertical line on the graph to indicate the selected value (the 40). I tried adding CPTBarplot but somehow the bars show only at the beginning of the graph axis.
Is there a function from core plot like the above that will create a line indicator?
I would appreciate if someone can give me some hint how to solve this problem and thank you very much in advance.
You could use a scatter plot for that. There's a point selection demo in the Mac CPTTestApp that draws a crosshair over the selected point. It would be trivial to modify that to only draw the vertical line.
The -numberOfRecordsForPlot: datasource method returns the number of points in the selection indicator (5 for the crosshairs) or zero (0) if there is no current selection. The -numberForPlot:field:recordIndex: method returns the points in the indicator. The points are drawn in this order:
Left
Right
Center (with plot symbol)
Top
Bottom
The -symbolForScatterPlot:recordIndex: method controls the plot symbol in the center. You can eliminate this method if you don't need any symbols on the indicator plot.

How to display line chart in a view?

I want line chart in my application can any one tell me how can we make line chart & display it in view.& which frame work is needed for that.
You mean a graph done with lines showing relationships between coordinates?
If so, Quartz drawing might be easiest. The framework is CoreGraphics. You get a reference to the CGContext, tell it where the line starts (moveToPoint, x, y) and ends (addLineToPoint, x, y), and stroke the path.
Check out Core-plot.
http://code.google.com/p/core-plot/