How to fill the area below the path in Quartz 2D?

I use Quartz 2D in a UIView object to draw multiple curves, like this example:

Two curves drawn using Quartz 2D with <code> CGContextStrokePath </code>

This is the code that I have right now (I missed the calculation of control points and other things):

for (int i = 1; i < points.count; ++i) { CGContextMoveToPoint(context, previousXValue, previousYValue); CGContextAddCurveToPoint(context, firstControlPointXValue, firstControlPointYValue, secondControlPointXValue, secondControlPointYValue, xValue, yValue ); // CGContextFillPath(context); CGContextStrokePath(context); } 

Now I would like to fill the area under the curve, but if I use CGContextFillPath , the result will be as follows:

Two curves filled using Quartz 2D with <code> CGContextFillPath </code>

which makes sense because according to Quartz 2D documentation :

When you fill out the current path, Quartz acts as if every sub-item contained in the path has been closed. He then uses these closed subpaths and calculates the pixels to fill.

Then I tried to move the path to the lower right corner and close the path, but the fill method has no effect:

 CGContextMoveToPoint(context, rect.size.width, rect.size.height); CGContextClosePath(context); CGContextFillPath(context); 

How could I fill the entire area below the curve, and not just the subarea closed in each subpath?

EDIT:

I found a temporary solution: drawing a figure using a curve and two vertical lines on each subpath:

 for (int i = 1; i < points.count; ++i) { // Draw the curve CGContextMoveToPoint(context, previousXValue, previousYValue); CGContextAddCurveToPoint(context, firstControlPointXValue, firstControlPointYValue, secondControlPointXValue, secondControlPointYValue, xValue, yValue ); CGContextStrokePath(context); // Draw a shape using curve initial and final points CGContextMoveToPoint(context, previousXValue, rect.size.height); CGContextAddLineToPoint(context, previousXValue, previousYValue); CGContextAddCurveToPoint(context, firstControlPointXValue, firstControlPointYValue, secondControlPointXValue, secondControlPointYValue, xValue, yValue ); CGContextAddLineToPoint(context, xValue, rect.size.height); CGContextFillPath(context); } 

I don't know if this is redundant, so improvements are also welcome. In addition, I get this result:

Two curves drawn using Quartz 2D with the area below them filled

Note that vertical lines appear as a result of drawing subareas next to each other. How can this be avoided?

+4
source share
1 answer

The idea is correct, but you should not fill out individual curves, but rather create one path and then fill it. So, start with CGContextMoveToPoint in the lower left corner, CGContextAddLineToPoint to the first point, make CGContextAddCurveToPoint for all the curves, and in the end make CGContextAddLineToPoint in the lower right corner (and you can also do a CGContextClosePath .

This is a simplified example where I only have an array of points, but it illustrates the idea:

 - (void)drawRect:(CGRect)rect { if (!self.points) [self configurePoints]; DataPoint *point; CGContextRef context = UIGraphicsGetCurrentContext(); CGColorRef color = [[UIColor redColor] CGColor]; CGContextSetStrokeColorWithColor(context, color); CGContextSetFillColorWithColor(context, color); point = self.points[0]; CGContextMoveToPoint(context, point.x, self.bounds.size.height); CGContextAddLineToPoint(context, point.x, point.y); for (point in self.points) { // you'd do your CGContextAddCurveToPoint here; I'm just adding lines CGContextAddLineToPoint(context, point.x, point.y); } point = [self.points lastObject]; CGContextAddLineToPoint(context, point.x, self.bounds.size.height); CGContextClosePath(context); CGContextDrawPath(context, kCGPathFillStroke); } 
+3
source

All Articles