2014-01-15 1 views
2

Я делаю приложение для рисования, и я пытаюсь сгладить линию, которую рисую пальцем. Для этой цели я использую функцию quadCurveToPoint. Но я не понимаю.Добавление QuadCurve к UIBezierPath

Ниже мой код:

- (void) drawRect:(CGRect)rect 
{ 
    [path stroke]; 
} 

- (id) initWithFrame:(CGRect)frame 
{ 
    if (self = [super initWithFrame:frame]) 
     self.multipleTouchEnabled = NO; 

    path = [UIBezierPath bezierPath]; 
    path.lineWidth = IS_IPAD? 2.0f : 1.0f; 

    return self; 
} 



- (void) touchesBegan:(NSSet *) touches withEvent:(UIEvent *) event 
{ 
    UITouch *touch = [touches anyObject]; 

    m_previousPoint1 = [touch locationInView:self]; 
    m_previousPoint2 = [touch locationInView:self]; 
    m_currentPoint = [touch locationInView:self]; 
} 

//Find the midpoint 
CGPoint midPoint(CGPoint p1, CGPoint p2) 
{ 
    return CGPointMake((p1.x + p2.x) * 0.5, (p1.y + p2.y) * 0.5); 
} 


- (void) touchesMoved:(NSSet *) touches withEvent:(UIEvent *) event 
{ 
    UITouch *touch = [touches anyObject]; 

    m_previousPoint2 = m_previousPoint1; 
    m_previousPoint1 = m_currentPoint; 

    m_currentPoint = [touch locationInView:self]; 

    CGPoint mid1 = midPoint(m_previousPoint1, m_previousPoint2); 
    CGPoint mid2 = midPoint(m_currentPoint, m_previousPoint1); 



    [path setFlatness:1.0f]; 
    [path setLineCapStyle:kCGLineCapRound]; 
    [path setLineJoinStyle:kCGLineJoinRound]; 
    [path moveToPoint:m_previousPoint1]; 
    [path addLineToPoint:mid1]; 

    [path addQuadCurveToPoint:mid2 controlPoint:m_currentPoint]; 
    [self setNeedsDisplay]; 
} 

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

} 

Когда я рисую пальцем, я адресности этот путь ниже:

enter image description here

Я не понимая, что мне не хватает. Поэтому мне нужна помощь в этом отношении.

EDIT: изображение размещено w.r.t. к нижнему ответу.

enter image description here

Благодаря Ранджит

ответ

5

Ваш код выглядит хорошо. Но чтобы решить эту проблему, вы упомянули, изменить текущий код на следующее:

Изменение:

[path moveToPoint:m_previousPoint1]; 
[path addLineToPoint:mid1]; 

To:

[path moveToPoint:mid1]; 
[path addLineToPoint:m_previousPoint1]; 

И изменить это:

[path addQuadCurveToPoint:mid2 controlPoint:m_currentPoint]; 

К :

[path addQuadCurveToPoint:m_currentPoint controlPoint:mid2]; 

Протестировано.


Добавление (WWDC Алгоритм):

фон:

Идея заключается в соответствии с WWDC:

1.) Вместо того чтобы использовать текущую точку , мы используем средние точки как начальную точку и конечную точку.

2.) В результате мы используем фактические точки касания в качестве контрольных точек.

Анализ/Коррекция кода:

Так вот это упрощенная версия кода, который я сделал что делает использовать идею, которая была введена в WWDC.

У вас есть идея. Почти. Учитывая вышеизложенное, мы должны внести изменения в ваш код в touchesMoved следующим образом:

1.)

Если мы используем среднюю точку как значение ToPoint, мы должны заботиться о первом случае , когда есть только один текущий момент, так как только с одной текущей точки, мы не можем вывести среднюю точку из него - Нам нужно 2 очка.

Итак, нам нужно будет «прочитать» одну точку за текущую точку первоначально, чтобы вычислить среднюю точку. Далее делает это:

UITouch *touch = [touches anyObject]; 

m_previousPoint1 = m_currentPoint; 
m_currentPoint = [touch locationInView:self]; 
mid1 = midPoint(m_currentPoint, m_previousPoint1); 

if(counter == 1) 
{ 
    [path moveToPoint:m_currentPoint]; 
    [path addLineToPoint:mid1]; 
    [self setNeedsDisplay]; 
} 

переменная счетчика сначала устанавливаются в 0. Таким образом, ничто не нарисованный до второго прохода, когда счетчик равен 1. А когда мы будем иметь 2 очка для расчета средняя точка.

Тогда здесь приходит остальные штрихи:

2.)

После того, как первый случай позаботятся, мы продвигаемся к остальной части кривой и получить соответственно точки, с которыми мы связываем сегменты:

else if(counter > 1) 
{ 
    [path addQuadCurveToPoint:mid1 controlPoint:m_previousPoint1]; 
    [self setNeedsDisplay]; 
} 
counter++; 

Вот else if сразу после первого if выше. Мы вводим здесь, когда обрабатывается только первый случай, потому что я использую простой счетчик и увеличиваю его каждый раз, когда вызывается touchesMoved.

Здесь происходит то, что мы соединяемся с предыдущей средней точкой до mid1, используя предыдущую точку в качестве контрольной точки. Итак, как насчет текущей точки? Мы используем его до следующего прохода.

3.) И, наконец, мы позаботимся последний отрезок кривой в touchesEnded:

- (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event 
{ 
    [path addLineToPoint:[[touches anyObject] locationInView:self]]; 
    [self setNeedsDisplay]; 
} 

Это просто рисует линию от вашей средней точки до последней точки.

И наконец, в touchesBegan, я установил counter = 0;, поэтому следующая кривая снова запустит вышеуказанный процесс.

Я тестировал выше, с использованием как тренажера и устройства, а вот снимок экрана:

screenshot

А вот полный источник:

- (void) touchesBegan:(NSSet *) touches withEvent:(UIEvent *) event 
{ 
    UITouch *touch = [touches anyObject]; 
    counter = 0; 
    m_previousPoint1 = [touch locationInView:self]; 
    m_currentPoint = [touch locationInView:self]; 
} 

//Find the midpoint 
CGPoint midPoint(CGPoint p1, CGPoint p2) 
{ 
    return CGPointMake((p1.x + p2.x) * 0.5, (p1.y + p2.y) * 0.5); 
} 


- (void) touchesMoved:(NSSet *) touches withEvent:(UIEvent *) event 
{ 
    UITouch *touch = [touches anyObject]; 

    m_previousPoint1 = m_currentPoint; 
    m_currentPoint = [touch locationInView:self]; 

    mid1 = midPoint(m_currentPoint, m_previousPoint1); 

    [path setFlatness:1.0f]; 
    [path setLineCapStyle:kCGLineCapRound]; 
    [path setLineJoinStyle:kCGLineJoinRound]; 

    if(counter == 1) 
    { 
     [path moveToPoint:m_currentPoint]; 
     [path addLineToPoint:mid1]; 
     [self setNeedsDisplay]; 
    } 
    else if(counter > 1) 
    { 
     [path addQuadCurveToPoint:mid1 controlPoint:m_previousPoint1]; 
     [self setNeedsDisplay]; 
    } 
    counter++; 
} 

- (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event 
{ 
    [path addLineToPoint:[[touches anyObject] locationInView:self]]; 
    [self setNeedsDisplay]; 
} 
+0

Эй, спасибо за Ваш ответ, Я путешествую, поэтому не могу проверить прямо сейчас, но я проверю как можно скорее, когда вернусь. Я хочу знать, как вы выяснили эту проблему, будь то от проб и ошибок или правильного понимания понятий? Если это правильное понимание понятий, какой секретный совет, вы хотите дать мне, чтобы я мог лучше понимать понятия. Спасибо – Ranjit

+0

Здравствуйте, спасибо, я попробовал ваш код, он работает, но я не получаю плавные кривые.Можете ли вы предложить что-то по этому поводу. – Ranjit

+0

Проверьте изображение выше, как я получаю кривую. – Ranjit