Cut a rectangle out of an NSBezierPath
Asked Answered
P

3

7

Is it possible to remove a chunk of NSBezierPath that is defined by an NSRect region within the path?

Parkman answered 15/4, 2011 at 21:23 Comment(0)
K
5

Absolutely. This is what clipping regions do:

// Save the current clipping region
[NSGraphicsContext saveGraphicsState];
NSRect dontDrawThisRect = NSMakeRect(x, y, w, h);
// Either:
NSRectClip(dontDrawThisRect);
// Or (usually for more complex shapes):
//[[NSBezierPath bezierPathWithRect:dontDrawThisRect] addClip];
[myBezierPath fill];    // or stroke, or whatever you do
// Restore the clipping region for further drawing
[NSGraphicsContext restoreGraphicsState];
Korney answered 15/4, 2011 at 23:17 Comment(3)
NSRectClip is not correct. It intersects with the current clippath. So after applying it only content within dontDrawThisRect is drawn instead taking out this area from the clipping region. So it is quite the opposite of what the OP wanted.Candie
Can I use this to remove a circle drawn in my program? I am trying to animate a circle in my program.The circle is moving along a path so I am doing is create a new circle in every iteration of a for loop.But how do I remove the old circle? Can anybody please help me?Waxwing
Here is my question #19651188Waxwing
P
11

As was noted in the comments, Mr. Caswell's answer is actually the opposite of what the OP was asking. This code sample shows how to remove a rect from a circle (or any bezier path from any other bezier path). The trick is to "reverse" the path that you want to remove, then append it to the original path:

NSBezierPath *circlePath = [NSBezierPath bezierPathWithOvalInRect:NSMakeRect(0, 0, 100, 100)];
NSBezierPath *rectPath = [NSBezierPath bezierPathWithRect:NSMakeRect(25, 25, 50, 50)];
rectPath = [rectPath bezierPathByReversingPath];
[circlePath appendBezierPath:rectPath];

Note: things get a little trickier if the bezier paths cross each other. Then you have to set the proper "winding rule".

Pseudocarp answered 13/7, 2013 at 0:7 Comment(0)
K
5

Absolutely. This is what clipping regions do:

// Save the current clipping region
[NSGraphicsContext saveGraphicsState];
NSRect dontDrawThisRect = NSMakeRect(x, y, w, h);
// Either:
NSRectClip(dontDrawThisRect);
// Or (usually for more complex shapes):
//[[NSBezierPath bezierPathWithRect:dontDrawThisRect] addClip];
[myBezierPath fill];    // or stroke, or whatever you do
// Restore the clipping region for further drawing
[NSGraphicsContext restoreGraphicsState];
Korney answered 15/4, 2011 at 23:17 Comment(3)
NSRectClip is not correct. It intersects with the current clippath. So after applying it only content within dontDrawThisRect is drawn instead taking out this area from the clipping region. So it is quite the opposite of what the OP wanted.Candie
Can I use this to remove a circle drawn in my program? I am trying to animate a circle in my program.The circle is moving along a path so I am doing is create a new circle in every iteration of a for loop.But how do I remove the old circle? Can anybody please help me?Waxwing
Here is my question #19651188Waxwing
P
0

Based on Roberto's answer, I've updated the code to Swift 5. This will draw a red 100x100 circle, with a 60x60 rectangle cut out in the middle.

let path = NSBezierPath(ovalIn: NSRect(x: 0, y: 0, width: 100, height: 100))
let cutoutRect = NSBezierPath(rect: NSRect(x: 20, y: 20, width: 60, height: 60)).reversed
path.append(cutoutRect)
NSColor.red.setFill()
path.fill()
Phobe answered 26/9, 2022 at 13:50 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.