Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fill UIBezierPath with parallel lines

I'm trying to draw custom shape using UIBezierPath:

UIBezierPath *aPath = [UIBezierPath bezierPath];

    [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)];
    [aPath closePath];

I want to fill it with parallel lines to make this stripped. I want to change color of this lines too. Assume that I want to make them vertical. I have to calculate somehow points on this path with regular interval, how I can do this?

I have found this UIColor colorWithPatternImage but then i cant change color and "density" of my lines inside shape.

like image 855
Prettygeek Avatar asked Jan 10 '23 23:01

Prettygeek


2 Answers

Like Nikolai Ruhe said, the best option is to use your shape as the clipping path, and then draw some pattern inside the bounding box of the shape. Here's an example of what the code would look like

- (void)drawRect:(CGRect)rect
{
    // create a UIBezierPath for the outline shape
    UIBezierPath *aPath = [UIBezierPath bezierPath];
    [aPath moveToPoint:CGPointMake(100.0, 0.0)];
    [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)];
    [aPath closePath];
    [aPath setLineWidth:10];

    // get the bounding rectangle for the outline shape
    CGRect bounds = aPath.bounds;

    // create a UIBezierPath for the fill pattern
    UIBezierPath *stripes = [UIBezierPath bezierPath];
    for ( int x = 0; x < bounds.size.width; x += 20 )
    {
        [stripes moveToPoint:CGPointMake( bounds.origin.x + x, bounds.origin.y )];
        [stripes addLineToPoint:CGPointMake( bounds.origin.x + x, bounds.origin.y + bounds.size.height )];
    }
    [stripes setLineWidth:10];

    CGContextRef context = UIGraphicsGetCurrentContext();

    // draw the fill pattern first, using the outline to clip
    CGContextSaveGState( context );         // save the graphics state
    [aPath addClip];                        // use the outline as the clipping path
    [[UIColor blueColor] set];              // blue color for vertical stripes
    [stripes stroke];                       // draw the stripes
    CGContextRestoreGState( context );      // restore the graphics state, removes the clipping path

    // draw the outline of the shape
    [[UIColor greenColor] set];             // green color for the outline
    [aPath stroke];                         // draw the outline
}

Using Swift

override func draw(_ rect: CGRect){

        // create a UIBezierPath for the outline shape
        let aPath = UIBezierPath()
        aPath.move(to: CGPoint(x: 100.0, y: 0.0))
        aPath.addLine(to: CGPoint(x: 200.0, y: 40.0))
        aPath.addLine(to: CGPoint(x: 160, y: 140))
        aPath.addLine(to: CGPoint(x: 40.0, y: 140))
        aPath.addLine(to: CGPoint(x: 0.0, y: 40.0))
        aPath.close()
        aPath.lineWidth = 10

        // get the bounding rectangle for the outline shape
        let bounds = aPath.bounds

        // create a UIBezierPath for the fill pattern
        let stripes = UIBezierPath()
        for x in stride(from: 0, to: bounds.size.width, by: 20){
            stripes.move(to: CGPoint(x: bounds.origin.x + x, y: bounds.origin.y ))
            stripes.addLine(to: CGPoint(x: bounds.origin.x + x, y: bounds.origin.y + bounds.size.height ))
        }
        stripes.lineWidth = 10

        let context = UIGraphicsGetCurrentContext()

        // draw the fill pattern first, using the outline to clip
        context!.saveGState()         // save the graphics state
        aPath.addClip()                        // use the outline as the clipping path
        UIColor.blue.set()                    // blue color for vertical stripes
        stripes.stroke()                       // draw the stripes
        context!.restoreGState()      // restore the graphics state, removes the clipping path

        // draw the outline of the shape
        UIColor.green.set()             // green color for the outline
        aPath.stroke()                         // draw the outline
    }

Produces

enter image description here

like image 162
user3386109 Avatar answered Jan 18 '23 22:01

user3386109


The best option is to set the original shape that you want to draw as a clipping path (CGContextClip) on the context.

Now, just draw all the parallel lines into the bounding box of the shape. You are free to vary the color or distance of the lines, then.

like image 33
Nikolai Ruhe Avatar answered Jan 18 '23 23:01

Nikolai Ruhe