Плавное написание на iPad - PullRequest
       33

Плавное написание на iPad

6 голосов
/ 19 сентября 2011

В настоящее время я работаю над проектом для iPad, где мне нужна функциональность, позволяющая пользователю писать стилусом на листе бумаги.

Я проверил пару стилусов и выяснил, что бамбук был лучшим. У них также есть бесплатное приложение, которое вы можете использовать, чтобы написать.

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

- (void)drawRect:(CGRect)rect
{
    CGContextRef context = UIGraphicsGetCurrentContext();
    UIGraphicsBeginImageContext(self.frame.size);

    // draw accumulated lines
    if ([self.lines count] > 0) {
        for (Line *tempLine in self.lines){
            CGContextSetAlpha(context, tempLine.opacity);
            CGContextSetStrokeColorWithColor(context, tempLine.lineColor.CGColor);
            CGContextSetLineWidth(context, tempLine.lineWidth);
            CGContextSetLineCap(context, kCGLineCapRound);
            CGContextSetLineJoin(context, kCGLineJoinRound);
            CGContextAddPath(context, tempLine.linePath);
            CGContextStrokePath(context);

            }
    }

    //draw current line
    CGContextSetAlpha(context, self.currentLine.opacity);


    CGContextSetStrokeColorWithColor(context, self.currentLine.lineColor.CGColor);
    CGContextSetLineWidth(context, self.currentLine.lineWidth);
    CGContextSetLineCap(context, kCGLineCapRound);
    CGContextSetLineJoin(context, kCGLineJoinRound);
    CGContextBeginPath(context);
    CGContextAddPath(context, self.currentLine.linePath);
    CGContextStrokePath(context);


    UIGraphicsEndImageContext();


}

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

    CGPathMoveToPoint(self.currentLine.linePath, NULL, cPoint.x, cPoint.y);

    [self setNeedsDisplay];
}

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

    CGPathAddLineToPoint(self.currentLine.linePath, NULL, currentPoint.x, currentPoint.y);

    [self setNeedsDisplay];
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {  
    UITouch *touch = [touches anyObject];
    CGPoint cPoint = [touch locationInView:self];
    CGPathAddLineToPoint(self.currentLine.linePath, NULL, cPoint.x, cPoint.y);

    [self setNeedsDisplay];
    [self.lines addObject:self.currentLine];
    Line *nextLine = [[Line alloc] initWithOptions:self.currentLine.lineWidth color:self.currentLine.lineColor opacity:self.currentLine.opacity];
    self.currentLine = nextLine;
    [nextLine release];
}

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

enter image description here

Это изображение, если я напишу то же самое в приложении Mamboo Paper:

enter image description here

У кого-нибудь есть идеи, как получить хорошее написание, как в приложении мамбо?

1 Ответ

7 голосов
/ 19 сентября 2011

Вместо того, чтобы соединять точки, используя прямые линии (CGPathAddLineToPoint), вы должны попробовать использовать кривые Безье: CGPathAddCurveToPoint или CGPathAddQuadCurveToPoint.

Это то, что будет делать сглаживание.


Если вы не знакомы с кривыми Безье, вы, вероятно, найдете страницу википедии о кривых Безье интересно (не только математические уравнения, но посмотрите на эскизы и анимированные изображения ). Это даст вам общее представление о том, как контрольные точки влияют на сглаживание линий вокруг ключевых точек вашей линии.

Для вашего случая достаточно квадратичных кривых (только одна контрольная точка для каждого подсегмента между двумя вашими ключевыми точками).

Construction of a quadratic Bézier curve - Source: Wikipedia (одна строка от P0 до P1, сглаженная с помощью контрольной точки P1)


Один из примеров (из коробки, только внушение из моих мыслей, никогда не проверяемое, адаптируйте коэффициенты к вашим потребностям) для вычисления этой контрольной точки C между каждой из ваших ключевых точек A и B - создание AC, скажем, 2/3 длины AB, и (AB, AC) составляет угол 30 градусов или что-то подобное.

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

...