UIBezierPath相交 [英] UIBezierPath intersect

查看:162
本文介绍了UIBezierPath相交的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在寻找了几个小时一个答案,但无法找到关于这个专题的东西。

I've been searching for an answer for hours but have trouble finding anything on the topic.

我有相关的Objective-C的一个问题。我正在其中一个UIView检查来自用户触摸并且如果用户触摸并移动他/她的手指的应用程序,使用UIBezierPath路径绘制。如果用户绘制以便路径相交本身应该从屏幕上消失。当用户完成绘制图案,从在路径中的最后一个点的线应与在自动的路径的第一点连接(我使用方法调用closePath此)中,如果与另一种线这条线相交在路径中的路径也应该从屏幕上消失。

I have a question related to Objective-c. I'm making an application in which a UIView checks for touches from the user and if the user touches and moves his/her finger, a path using UIBezierPath is drawn. If the user draws so that the path intersects itself it should disappear from the screen. When the user is done drawing the pattern, a line from the last point in the path should connect with the first point in the path automatically (I'm using the method "closePath" for this), if this line intersects with another "line" in the path the path should also disappear from the screen.

我存储的每个接触点在一个CGPoint,我存储在另一个类称为线为点A和点B.我然后保存在行到一个NSMutableArray称为线。每一个时间点被添加到路径I检查,看看是否该点与点之间的线之前绘制用的方法(具有任意的行中的线相交 - (布尔)checkLineIntersection:(CGPoint)p1所:(CGPoint)P2:(CGPoint)P3:(CGPoint)P4)我从本教程得到HTTP://www.iossource$c$c.com/2012/08/02/how-to-make-a-游戏般切割的最绳部分-2 /".

I store every touch point in a CGPoint that I store in another class called Line as point A and point B. I'm then saving the "line" to an NSMutableArray called "lines". Every time a point is added to the path I check to see if the line between that point and the point drawn before it intersects with any of the "lines" in lines by using a method (-(BOOL)checkLineIntersection:(CGPoint)p1 :(CGPoint)p2 :(CGPoint)p3 :(CGPoint)p4) I got from this tutorial "http://www.iossourcecode.com/2012/08/02/how-to-make-a-game-like-cut-the-rope-part-2/".

问题

现在的问题是,当我运行该应用程序它的工作原理,但有时有时我得到这么线相交的道路并没有消失。我想不通为什么...这似乎正好更多的时候,当我慢慢地画。

The problem is that when I run the application it works sometimes but sometimes when I draw so the lines intersect the path doesn't disappear. I can't figure out why... It seems as it happens more often when I draw slowly.

的code:

MyView.h:

#import <UIKit/UIKit.h>
#import "Line.h"
@interface MyView : UIView {

NSMutableArray *pathArray;
UIBezierPath *myPath;
NSMutableArray *lines;
Line *line;
} 

@end

MyView.m:

#import "MyView.h"

@implementation MyView


- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
    // Initialization code
    pathArray=[[NSMutableArray alloc]init];

}
return self;
}

- (void)drawRect:(CGRect)rect
{
[[UIColor redColor] setStroke];
[[UIColor blueColor] setFill];

for (UIBezierPath *_path in pathArray) {
    //[_path fill];

    [_path strokeWithBlendMode:kCGBlendModeNormal alpha:1.0];
}
}

#pragma mark - Touch Methods
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
myPath = [[UIBezierPath alloc]init];
lines = [[NSMutableArray alloc]init];
myPath.lineWidth=1;

UITouch *mytouch = [[event allTouches] anyObject];
[myPath moveToPoint:[mytouch locationInView:mytouch.view]];

[pathArray addObject:myPath];

}

-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{

if(myPath.isEmpty) {

} else {

    UITouch *mytouch = [[event allTouches] anyObject];
    [myPath addLineToPoint:[mytouch locationInView:mytouch.view]];

    CGPoint pointA = [mytouch previousLocationInView:mytouch.view];
    CGPoint pointB = [mytouch locationInView:mytouch.view];

    line = [[Line alloc]init];
    [line setPointA:pointA];
    [line setPointB:pointB];

    [lines addObject:line];

    for(Line *l in lines) {

        CGPoint pa = l.pointA;
        CGPoint pb = l.pointB;

        //NSLog(@"Point A: %@", NSStringFromCGPoint(pa));
        //NSLog(@"Point B: %@", NSStringFromCGPoint(pb));

        if ([self checkLineIntersection:pointA :pointB :pa :pb])
        {
            [pathArray removeLastObject];
            [myPath removeAllPoints];
            [self setNeedsDisplay];
            NSLog(@"Removed path!");
            return;
        }
    }
}
[self setNeedsDisplay];
}

-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
if(myPath.isEmpty) {


} else if ([lines count] != 0){
    line = [[Line alloc]init];
    line = [lines lastObject];
    CGPoint pointA = line.pointA;
    line = [[Line alloc]init];
    line = [lines objectAtIndex:0];
    CGPoint pointB = line.pointA;

    [myPath closePath];
    for(Line *l in lines) {

        CGPoint pa = l.pointA;
        CGPoint pb = l.pointB;

        if ([self checkLineIntersection:pointA :pointB :pa :pb])
        {
            [pathArray removeLastObject];
            [myPath removeAllPoints];
            [self setNeedsDisplay];
            NSLog(@"Removed path!");
            return;
        }
    } 
}
[self setNeedsDisplay];
}

-(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);

/*
// In this case the lines are parallel so you assume they don't intersect
if (denominator == 0.0f)
    return NO;
*/

CGFloat ua = ((p4.x - p3.x) * (p1.y - p3.y) - (p4.y - p3.y) * (p1.x - p3.x)) / denominator;
CGFloat ub = ((p2.x - p1.x) * (p1.y - p3.y) - (p2.y - p1.y) * (p1.x - p3.x)) / denominator;

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

return NO;
}


@end

Line.h:

#import <UIKit/UIKit.h>

@interface Line : UIView 

@property (nonatomic, assign) CGPoint pointA;
@property (nonatomic, assign) CGPoint pointB;

@end

Line.m:

#import "Line.h"

@implementation Line

@synthesize pointA;
@synthesize pointB;

- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
    // Initialization code
}
return self;
}

/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
// Drawing code
}
*/

@end

我希望有人也许能回答这个问题。如果它的明显的东西对不起。预先感谢您!

I hope someone might be able to answer this. Sorry if it's something obvious. Thank you in advance!

推荐答案

现在的问题是,在 checkLineIntersection 方法。随着

The problem is in the checkLineIntersection method. With

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

您只检查是否内饰部分的段相交的线。但是,如果开始或第一条线段的端点的等于的第二个线段的起点或终点, UA UB 0.0 1.0

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.

一些进一步的说明:

  • 我想你应该激活快捷

  • I think you should activate the shortcut

if (denominator == 0.0f) return NO;

再次被零避免分裂。

again to avoid division by zero.

touchesMoved ,你可以在的添加新线到阵列的检查交叉点。现在,新的行被插入第一,这意味着它是核对本身为交叉点

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.

您已经声明的UIView 的子类,但这不是一个真正的视图类。你可以只声明作为子类 NSObject的的。

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);
}

这篇关于UIBezierPath相交的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆