Search code examples
objective-cquartz-2d

Quartz paths not drawing like I expect


I am trying to draw and fill simple paths in Quartz 2d for iPad.

The following method from the class SPTCutPattern defines the paths that I want to draw:

- (void) initDummyCutPattern {
NSArray *piece1Path = [[NSArray alloc] initWithObjects:
                       [NSValue valueWithCGPoint:CGPointMake(0, 0)],
                       [NSValue valueWithCGPoint:CGPointMake(3, 0)],
                       [NSValue valueWithCGPoint:CGPointMake(3, 1)],
                       [NSValue valueWithCGPoint:CGPointMake(2, 1)],
                       [NSValue valueWithCGPoint:CGPointMake(2, 2)],
                       [NSValue valueWithCGPoint:CGPointMake(0, 2)],
                       nil];
SPTPuzzlePiece *Piece1 = [[SPTPuzzlePiece alloc] initWithWidthInGrid:3 andHeightInGrid:2 andLeftInGrid:0 andTopInGrid:0 andBuilt:YES andPathInGrid:piece1Path];

NSArray *piece2Path = [[NSArray alloc] initWithObjects:
                       [NSValue valueWithCGPoint:CGPointMake(3, 0)],
                       [NSValue valueWithCGPoint:CGPointMake(5, 0)],
                       [NSValue valueWithCGPoint:CGPointMake(5, 5)],
                       [NSValue valueWithCGPoint:CGPointMake(4, 5)],
                       [NSValue valueWithCGPoint:CGPointMake(4, 4)],
                       [NSValue valueWithCGPoint:CGPointMake(2, 4)],
                       [NSValue valueWithCGPoint:CGPointMake(2, 3)],
                       [NSValue valueWithCGPoint:CGPointMake(3, 3)],
                       [NSValue valueWithCGPoint:CGPointMake(3, 2)],
                       [NSValue valueWithCGPoint:CGPointMake(2, 2)],
                       [NSValue valueWithCGPoint:CGPointMake(2, 1)],
                       [NSValue valueWithCGPoint:CGPointMake(3, 1)],
                       nil];
SPTPuzzlePiece *Piece2 = [[SPTPuzzlePiece alloc] initWithWidthInGrid:3 andHeightInGrid:5 andLeftInGrid:2 andTopInGrid:0 andBuilt:YES andPathInGrid:piece2Path];

NSArray *piece3Path = [[NSArray alloc] initWithObjects:
                       [NSValue valueWithCGPoint:CGPointMake(0, 2)],
                       [NSValue valueWithCGPoint:CGPointMake(3, 2)],
                       [NSValue valueWithCGPoint:CGPointMake(3, 3)],
                       [NSValue valueWithCGPoint:CGPointMake(2, 3)],
                       [NSValue valueWithCGPoint:CGPointMake(2, 4)],
                       [NSValue valueWithCGPoint:CGPointMake(4, 4)],
                       [NSValue valueWithCGPoint:CGPointMake(4, 5)],
                       [NSValue valueWithCGPoint:CGPointMake(0, 5)],
                       nil];

SPTPuzzlePiece *Piece3 = [[SPTPuzzlePiece alloc] initWithWidthInGrid:4 andHeightInGrid:3 andLeftInGrid:0 andTopInGrid:2 andBuilt:YES andPathInGrid:piece3Path];

self.pieces = [[NSArray alloc] initWithObjects:Piece1, Piece2, Piece3, nil];
}

And this method from the class SPTPuzzlePieceView which is supposed to draw the paths:

- (void)drawRect:(CGRect)rect
{
int widthUnit = self.frame.size.width / self.puzzlePiece.widthInGrid;
int heightUnit = self.frame.size.height / self.puzzlePiece.heightInGrid;
CGContextRef context = UIGraphicsGetCurrentContext();

CGContextSetFillColorWithColor(context, [UIColor blackColor].CGColor);

CGContextMoveToPoint(context, [[puzzlePiece.pathInGrid objectAtIndex:0] CGPointValue].x*widthUnit, 
                     [[puzzlePiece.pathInGrid objectAtIndex:0] CGPointValue].y*heightUnit);

for (NSValue *point in puzzlePiece.pathInGrid) {
    CGContextAddLineToPoint(context, [point CGPointValue].x*widthUnit, [point CGPointValue].y*heightUnit);
}

CGContextFillPath(context);
}

I am getting these three objects, which are absolutely NOT what I expect and want:

screenshot

The objects are supposed to be more (or less) like this:

shapes I wanted

I am sorry that these methods are totally taken out of context, so I hope you can see what I am trying to do. The drawRect method gets called to draw each of the piece objects I defined in the first method in turn.

I cannot figure out why it is not drawing the shapes I want. Help me please.

Thanks!


Solution

  • Your second and third shapes are being initialised with widthInGrid and heightInGrid values smaller than their points. This results in drawing outside the view bounds.

    Three other things:

    1. Consider using UIBezierPath for creating and drawing your path, instead of CGContext... calls. It's harder to make mistakes with. If at any point the user has to touch these shapes and drag them around, its containsPoint: method will be really handy.
    2. The Objective-C naming convention for variables is that they start with lower-case, to distinguish them from class names. So, you would have SPTPuzzlePiece *piece1 instead of *Piece1. Words within the variable name do use upper-case.
    3. In drawRect, use the view's own bounds to get the width and height, not its frame. These will be the same if you haven't distorted your view, but it's good practice to follow. The bounds always define the coordinate space you're drawing into.