7

How would one crosshatch (apply a set of parallel lines at 45 degrees) across the fill of a shape in IOS using core graphics? Sample code?

(I'm specially interested in use with an MKPolygon in MKMapKit, however for the moment just trying to see if it's possible in a UIView using drawRect?. So fill the background of a UIView with crosshatch'ing)

Greg
  • 34,042
  • 79
  • 253
  • 454

4 Answers4

7

for swift 3., using approach from @user3230875

final class CrossHatchView: UIView {
    
    // MARK: - LifeCycle
    
    override func draw(_ rect: CGRect) {

        // create rect path with bounds that equal to the 
        // size of a view, in addition it adds rounded corners, this will
        // be used later as a canvas for dash drawing
        let path:UIBezierPath = UIBezierPath(roundedRect: bounds, cornerRadius: 5)

        // specify the new area where the our drawing will be visible
        // check [link][1] for more
        path.addClip()
                
        // grab the size of drawing area
        let pathBounds = path.bounds

        // cleanUp rounded rect, that is drawn above
        // just remove roundedRect in the words
        path.removeAllPoints()

        // get start and end point of the line
        let p1 = CGPoint(x:pathBounds.maxX, y:0)
        let p2 = CGPoint(x:0, y:pathBounds.maxX)

        // draw line
        path.move(to: p1)
        path.addLine(to: p2)

        // set line width equal to double width of view
        // because we later will draw this line using dash pattern
        path.lineWidth = bounds.width * 2
        
        // set dash pattern with some interval
        let dashes:[CGFloat] = [0.5, 7.0]
        path.setLineDash(dashes, count: 2, phase: 0.0)

        // set color for line 
        UIColor.lightGray.withAlphaComponent(0.5).set()

        // actually draw a line using specific
        // color and dash pattern
        path.stroke()
    }
}

result:

enter image description here

hbk
  • 10,908
  • 11
  • 91
  • 124
4

Create a UIImage containing your crosshatch pattern in whatever way you want (e.g. by drawing it with Core Graphics or by loading it from a PNG file).

Then use +[UIColor colorWithPatternImage:] (Swift UIColor(patternImage:)) to create a “color” that draws the crosshatch image.

Finally, set the pattern color as your fill color, and fill the shape (presumably by filling a path that outlines the shape, or by using UIRectFill).

If you need more control over the pattern (to change how it's tiled or aligned), you can drop down to the Core Graphics level and use CGPatternCreate and CGColorCreateWithPattern.

rob mayoff
  • 375,296
  • 67
  • 796
  • 848
  • I'm interested in an approach that doesnt require images. Are you suggesting there is no existing method like "gradient" that would do it?. Ie would have to effectively programmatically draw one in drawrect using CG commands? – Greg Jun 15 '16 at 02:44
  • 1
    There is nothing built-in that will automatically draw a crosshatch pattern for you. – rob mayoff Jun 15 '16 at 02:45
2

hey try this sample code which i tried on a 300x300 UIView

- (void)drawRect:(CGRect)rect
{
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetLineWidth(context, 1.5);
    CGContextSetStrokeColorWithColor(context, [UIColor grayColor].CGColor);
    int backward=0;

    for (int i=0;i<15; i++)
    {
        CGContextMoveToPoint(context, backward, 0);
        CGContextAddLineToPoint(context, 300, 300-backward);
        backward=backward+20;
    }
    int backwardNegitive=0;
    for (int i=0;i<15; i++)
    {
        CGContextMoveToPoint(context, 0,backwardNegitive);
        CGContextAddLineToPoint(context, 300-backwardNegitive,300);
        backwardNegitive=backwardNegitive+20;
    }
    int forward=0;
    for (int i=0;i<15; i++)
    {
        CGContextMoveToPoint(context, 300-forward, 0);
        CGContextAddLineToPoint(context, 0, 300-forward);
        forward=forward+20;
    }
    int forwardNegative=0;
    for (int i=0;i<15; i++)
    {
        CGContextMoveToPoint(context, 0,300+forwardNegative);
        CGContextAddLineToPoint(context,300+forwardNegative,0);
        forwardNegative=forwardNegative+20;
    }
    CGContextStrokePath(context);

}

Hope this help you.

Abhishek
  • 39
  • 3
  • 14
2

Here's what I was talking about over in the Apple Developer Forum:

#import "CrossHatchView.h"

@implementation CrossHatchView

static  CGFloat  sides = 5.0;

- (void)drawRect:(CGRect)rect
{
    CGRect  bounds = self.bounds;

    UIBezierPath  *path = [UIBezierPath bezierPath];

    CGFloat  xCentre = CGRectGetMidX(bounds);
    CGFloat  yCentre = CGRectGetMidY(bounds);
    CGFloat  radius = 0.0;

    if (CGRectGetWidth(bounds) > CGRectGetHeight(bounds)) {
        radius = CGRectGetHeight(bounds) / 2.0;
    } else {
        radius = CGRectGetWidth(bounds) / 2.0;
    }
    CGFloat  angleIncrement = 2.0 * M_PI / sides;

    CGFloat  initialAngle = ( M_PI + (2.0 * M_PI / sides) ) / 2.0;

    for (NSUInteger  i = 0;  i < sides;  i++) {
        CGFloat  angle = initialAngle + i * angleIncrement;
        CGFloat  x = xCentre + radius * cos(angle);
        CGFloat  y = yCentre + radius * sin(angle);
        CGPoint  point = CGPointMake(x, y);
        if (i == 0) {
            [path moveToPoint:point];
        } else {
            [path addLineToPoint:point];
        }
    }
    [path closePath];
    [[UIColor cyanColor] set];
    [path addClip];

    CGRect  pathBounds = [path bounds];

    [path removeAllPoints];
    CGPoint  p1 = pathBounds.origin;
    CGPoint  p2 = CGPointMake(CGRectGetMaxX(pathBounds), CGRectGetMaxY(pathBounds));
    [path moveToPoint:p1];
    [path addLineToPoint:p2];
    path.lineWidth = 400.0;
    CGFloat  dashes[] = { 2.0, 2.0 };
    [path setLineDash:dashes count:2 phase:0.0];
    [[UIColor blackColor] set];
    [path stroke];
}

@end
hbk
  • 10,908
  • 11
  • 91
  • 124
user3230875
  • 689
  • 6
  • 4