The issue you are dealing with is that CGPath’s ==
doesn’t imply “comprises the identical factors.” It means “comprises the identical drawing directions in the identical order.” And union(utilizing:)
doesn’t promise to protect the order of the drawing directions. It will probably’t, because it has a fill rule. It is not simply appending two paths; it is merging them.
You’ll be able to see this by printing out the contents:
func printPath(ptr: UnsafePointer<CGPathElement>) {
let factor = ptr.pointee
swap factor.sort {
case .moveToPoint:
print("MOVE: (factor.factors[0])")
case .addCurveToPoint:
print("CURVE") // Do not care; have no
case .addLineToPoint:
print("LINE: (factor.factors[0])")
case .closeSubpath:
print("CLOSE")
case .addQuadCurveToPoint:
print("QUAD") // Do not care; have no
}
}
let rect1 = CGPath(rect: CGRect(origin: .zero, dimension: CGSize(width: 100, top: 100)),
rework: nil)
rect1.applyWithBlock(printPath)
=>
MOVE: (0.0, 0.0)
LINE: (100.0, 0.0)
LINE: (100.0, 100.0)
LINE: (0.0, 100.0)
CLOSE
CGMutablePath().union(rect1, utilizing: .evenOdd).applyWithBlock(printPath)
=>
MOVE: (100.0, 100.0)
LINE: (0.0, 100.0)
LINE: (0.0, 0.0)
LINE: (100.0, 0.0)
CLOSE
These will not be “equal.” The device you need right here is .addPath
.
let added = CGMutablePath()
added.addPath(rect1)
added.applyWithBlock(printPath)
=>
MOVE: (0.0, 0.0)
LINE: (100.0, 0.0)
LINE: (100.0, 100.0)
LINE: (0.0, 100.0)
CLOSE
added == rect1 // true
Now this can be a bit annoying on your use case, however you possibly can clear it up:
extension CGPath {
static var zero: CGPath { CGMutablePath() }
func appending(_ path: CGPath) -> CGPath {
var copy = self.mutableCopy()!
copy.addPath(path)
return copy
}
}
let bunchOfPaths = [rect1]
let unionPath = bunchOfPaths.cut back(CGPath.zero) { $0.appending($1) }
unionPath == rect1 // true