UIBezierPath intersect

不想你离开。 提交于 2019-11-27 15:38:52

The problem is in the checkLineIntersection method. With

if (ua > 0.0 && ua < 1.0 && ub > 0.0 && ub < 1.0) { return YES; }

you check only if the interior part of the lines segments intersect. But if the start or endpoint of the first line segment is equal to the start or endpoint of the second line segment, ua and ub will be 0.0 or 1.0.

The solution is to include one end of the interval in the condition:

if (ua > 0.0 && ua <= 1.0 && ub > 0.0 && ub <= 1.0) { return YES; }

This seemed to work as expected in my test program.

Some further remarks:

  • I think you should activate the shortcut

    if (denominator == 0.0f) return NO;
    

    again to avoid division by zero.

  • In touchesMoved, you could add the new line to the array after checking for intersections. Now the new line is inserted first, which means that it is checked against itself for intersections.

  • You have declared Line as subclass of UIView, but this is not really a view class. You could just declare Line as subclass of NSObject.


ADDED: The following method might work even better, because it avoids the division and therefore possible overflow problems with small denominators:

-(BOOL)checkLineIntersection:(CGPoint)p1 :(CGPoint)p2 :(CGPoint)p3 :(CGPoint)p4
{
    CGFloat denominator = (p4.y - p3.y) * (p2.x - p1.x) - (p4.x - p3.x) * (p2.y - p1.y);
    CGFloat ua = (p4.x - p3.x) * (p1.y - p3.y) - (p4.y - p3.y) * (p1.x - p3.x);
    CGFloat ub = (p2.x - p1.x) * (p1.y - p3.y) - (p2.y - p1.y) * (p1.x - p3.x);
    if (denominator < 0) {
        ua = -ua; ub = -ub; denominator = -denominator;
    }
    return (ua > 0.0 && ua <= denominator && ub > 0.0 && ub <= denominator);
}

I've found another workaround to check if the line intersect it self. With SceneKit framework it possible to create shape from UIBezierPath. But if the path intersects then bounding box of the node will be zeroed.

   let path = UIBezierPath()

    //...

    let testGeometry = SCNShape(path:path, extrusionDepth: 0.5)
    let testNode = SCNNode(geometry: testGeometry)

    if (testNode.boundingBox.max - testNode.boundingBox.min).length() > 0 {
    // No intersection (or empty)
   }
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!