adamwulf / ClippingBezier

ClippingBezier calculates intersection points, paths, and shapes between two UIBezierPaths
http://getlooseleaf.com/opensource/
MIT License
254 stars 34 forks source link

Added intersecting function doesn't give correct intersection #6

Closed AndrewHartAR closed 4 years ago

AndrewHartAR commented 6 years ago

I feel this is an issue with a function I've added to this library, and thus maybe not relevant for an issue, but @adamwulf asked me to add this.

I modified differenceOfPathTo:shapePath:, creating a new function of intersectionOfPathTo::

-(UIBezierPath*) intersectionOfPathTo:(UIBezierPath*)shapePath{
    BOOL beginsInside1 = NO;
    NSMutableArray* tValuesOfIntersectionPoints = [NSMutableArray arrayWithArray:[self findIntersectionsWithClosedPath:shapePath andBeginsInside:&beginsInside1]];
    DKUIBezierPathClippingResult* clipped = [self clipUnclosedPathToClosedPath:shapePath usingIntersectionPoints:tValuesOfIntersectionPoints andBeginsInside:beginsInside1];
    return clipped.entireIntersectionPath;
}

This works well with rectangles:

let bezierPath1 = UIBezierPath(rect: CGRect(x: 0, y: 0, width: 100, height: 100))
let bezierPath2 = UIBezierPath(rect: CGRect(x: 50, y: 10, width: 100, height: 100))

let intersection = bezierPath1.intersectionOfPath(to: bezierPath2)

The intersection bezier path here is correct. But replacing this with ovals with the same rect, the intersection bezier path only covers half of the intersection:

        let bezierPath1 = UIBezierPath(ovalIn: CGRect(x: 0, y: 0, width: 100, height: 100))         let bezierPath2 = UIBezierPath(ovalIn: CGRect(x: 50, y: 10, width: 100, height: 100))

        let intersection = bezierPath1.intersectionOfPath(to: bezierPath2)         let difference = bezierPath1.differenceOfPath(to: bezierPath2)

I've attached a diagram of the output from this, with difference bounds highlighted in red, and intersection bounds highlighted in blue (only covering half of the intersection):

screen shot 2018-07-28 at 19 13 37
adamwulf commented 5 years ago

So I just dug in, and it turns out that method is actually working as intended. My memory was wrong when we talked, that method is actually designed to return clipped elements of the path, not the filled intersection of the path. It'll return the segment of the circle that is intersecting with the other circle, but won't actually calculate the finished intersecting area.

Since the library only has methods to return all shapes from two intersecting paths (both the intersection and difference together) when using uniqueShapesCreatedFromSlicingWithUnclosedPath:, I decided to add two new methods to tease these apart into more normal boolean style methods:

@interface UIBezierPath (MMClipping)
-(NSArray<UIBezierPath *>*)intersectionWithPath:(UIBezierPath*)path;
-(NSArray<UIBezierPath *>*)differenceWithPath:(UIBezierPath*)path;
@end

You can now call intersectionWithPath: and it'll return what you want. :)