Вычислить контрольные точки при рисовании в iOS

Я работаю над приложением для рисования, где пользователь может рисовать/писать пальцем или стилусом. Для этого я сослался на код из https://github.com/yusenhan/Smooth-Line-View в своем приложении.

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

Поэтому я думаю, что делаю какую-то ошибку, получая контрольную точку.

Ниже мой код

//Находим середину

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

#pragma mark Gesture handle
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{

    UITouch *touch = [touches anyObject];
    //LocationInView returns the current location of the reciever in coordinate system of the given View.
    m_previousPoint1 = [touch locationInView:self];
    m_previousPoint2 = [touch locationInView:self];
    m_currentPoint   = [touch locationInView:self];    

    [self touchesMoved:touches withEvent:event];}

-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{          
    //AnyObject:- Returns one of the objects in the set, or nil if the set contains no objects.
    UITouch *touch  = [touches anyObject];

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

    if(m_drawStep != ERASE)
    {
        m_drawStep = DRAW;
        m_drawing  = TRUE;        
    }    
}

-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, 0.0);//creates a graphics context suitable for use as an image(size of the image,opquae,scale, if scale = 0.0, means platform will take care of scaling)
    [self.layer renderInContext:UIGraphicsGetCurrentContext()];
    m_curImage = UIGraphicsGetImageFromCurrentImageContext();// to turn the context into a UIImage    
    UIGraphicsEndImageContext();

 }

- (void)drawRect:(CGRect)rect
{
   CGPoint mid1 = midPoint(m_previousPoint1, m_previousPoint2);
   CGPoint mid2 = midPoint(m_currentPoint, m_previousPoint1);            

   [m_curImage drawAtPoint:CGPointMake(0, 0)];

   CGContextRef context = UIGraphicsGetCurrentContext();//Get a reference to current context(The context to draw)
   [self.layer renderInContext:context];
   //Simply keep referring to this context in below functions with proper arguments.
   CGContextMoveToPoint(context, mid1.x, mid1.y);//Position the current point
   CGContextAddQuadCurveToPoint(context, m_previousPoint1.x, m_previousPoint1.y, mid2.x, mid2.y);     
   CGContextSetLineCap(context, kCGLineCapRound);
   CGContextSetBlendMode(context, kCGBlendModeNormal);
   CGContextSetLineJoin(context, kCGLineJoinRound);
   CGContextSetLineWidth(context, self.lineWidth);
   CGContextSetStrokeColorWithColor(context, self.lineColor.CGColor);
   CGContextSetShouldAntialias(context, YES);
   CGContextSetAllowsAntialiasing(context, YES);
   CGContextSetAlpha(context, self.lineAlpha);           
   CGContextSetFlatness(context, 0.6);
   CGContextStrokePath(context);//paints(fills) the line along the current path.            
}

По моему мнению, точки, которые я прохожу в CGContextAddQuadCurveToPoint, можно подправить, но как это подправить, я не понимаю. Я прочитал документы, чтобы найти контрольные точки для Bezier Curve, но я не понимаю.

Итак, друзья, помогите мне понять, где я ошибаюсь.


person Ranjit    schedule 02.01.2014    source источник
comment
Вы можете использовать сплайн Catmull-Rom вместо кривой Безейра, чтобы иметь гладкую кривую нужно"> stackoverflow.com/questions/8702696/   -  person amar    schedule 02.01.2014
comment
@amar, не могли бы вы подсказать, как можно изменить этот код?   -  person Ranjit    schedule 02.01.2014
comment
ranjit проверьте этот URL mobile.tutsplus.com/tutorials /iphone/ это может помочь вам и даст вам представление о том, как создавать эффективные кривые, используя кривую Безье.   -  person kamalesh kumar yadav    schedule 02.01.2014


Ответы (1)


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

Вычисление контрольных точек Безье по существующей кривой очень сложно, так как контрольные точки не находятся на линии.

Лучше использовать кривые Катмулла-Рома. В ВЫДАЮЩЕЙСЯ книге Эрики Садун «Поваренная книга продвинутого разработчика iOS 6» есть отличный «рецепт», который включает рабочий код сглаживания на основе сплайнов Catmull-Rom. Сплайны Катмулла-Рома используют контрольные точки, находящиеся на кривой.

Очень рекомендую купить эту книгу. Пример кода для рецепта 4.3 сделает именно то, что вам нужно.

person Duncan C    schedule 07.01.2014
comment
Здесь, здесь. Книги Эрики Садун потрясающие. Деньги потрачены не зря. - person uchuugaka; 07.01.2014
comment
Здравствуйте @Duncan C, спасибо за ваш ответ. Итак, вы предлагаете мне использовать сплайны Catmull-Rom, а затем найти контрольные точки и передать их в функцию quadCurve, так что все остается прежним, только мне нужно вычислить контрольные точки и пройти. Вы это имели в виду, или это что-то другое? - person Ranjit; 11.01.2014
comment
Нет. Сплайны Катмулла-Рома имеют контрольные точки вдоль кривой. Вы бы использовали сплайны Катмулла-Рома, чтобы разбить свою кривую на более прямые сегменты и вообще не использовать кубические или квадратичные кривые Безье. - person Duncan C; 11.01.2014
comment
Привет @DuncanC, так что я должен полностью отказаться от этого кода, верно? хорошо, я видел этот код в 4.3, он не рисует плавные кривые. - person Ranjit; 12.01.2014
comment
Хорошо, начните заново, используя сглаживание Catmull-Rom. Купить книгу. - person Duncan C; 12.01.2014
comment
Привет @DuncanC, помогите мне с этим stackoverflow.com/questions/21027788/ - person Ranjit; 14.01.2014
comment
Привет @DuncanC, я просмотрел пример кода, функция catmull rom сглаживает заданный путь с определенной степенью детализации. Таким образом, путь может быть CGPath или UIBezierPath, верно? Что я хочу сказать, так это то, что я могу использовать существующий код и просто передать свой путь к функции. Поправьте меня, если я ошибаюсь - person Ranjit; 16.01.2014
comment
Здравствуйте @DuncanC, вы говорите, что в моем нынешнем коде контрольные точки не являются кривой. Я не получил это. - person Ranjit; 16.01.2014
comment
В кривых Безье только первая и последняя точки находятся на кривой. Средние контрольные точки не находятся на кривой, но тянут кривую к ним. Не существует очевидного способа придумать расположение контрольных точек в соответствии с существующей формой. - person Duncan C; 16.01.2014
comment
Здравствуйте, @DuncanC, посмотрите на этот stackoverflow. ком/вопросы/21438586/ мне нужна ваша помощь - person Ranjit; 31.01.2014
comment
Здравствуйте, @DuncanC, помогите мне stackoverflow.com/questions/21545923/multitouch-tracking -проблема - person Ranjit; 09.02.2014
comment
Здравствуйте, @DuncanC, пожалуйста, посмотрите на этот stackoverflow.com/questions /21952274/, пожалуйста, помогите мне - person Ranjit; 22.02.2014