Мой вопрос касается различных техник рисования линий, которые кажутся от руки:
Как вы рисуете, как карандаш?
В частности, Стив Ханов написал это превосходно запись в блоге .
После этого я смог реализовать красивый алгоритм для линий от руки, используя кривые Безье.Тем не менее, я застрял на том, как реализовать эллипс, выглядящий от руки.В идеале я хотел бы дать ему прямоугольник для использования в качестве границы, аналогично другим вызовам рисования эллипса.Но я хочу, чтобы это выглядело очень от руки.
Пока лучшее, что я придумал, это:
- (UIBezierPath*) freehandEllipseFromRect:(CGRect) rect {
// freehand ellipses need a lil more height
rect = CGRectMake(rect.origin.x, rect.origin.y-5, rect.size.width, rect.size.height+10);
UIBezierPath* path = [UIBezierPath bezierPath];
CGPoint topMidPoint = CGPointMake(rect.origin.x + (rect.size.width/2), rect.origin.y);
CGPoint bottomMidPoint = CGPointMake(rect.origin.x + (rect.size.width/2), rect.origin.y+rect.size.height);
// random point along bottom quarter of height, cause makes it look better
CGFloat randomY = (((CGFloat) (arc4random() % RAND_MAX) / RAND_MAX)) * (rect.size.height/4);
CGPoint leftControlPoint = CGPointMake(rect.origin.x-(rect.size.width), rect.origin.y+(rect.size.height-randomY));
// another random y;
randomY = (((CGFloat) (arc4random() % RAND_MAX) / RAND_MAX)) * (rect.size.height/4);
CGPoint rightControlPoint = CGPointMake(rect.origin.x+(rect.size.width*2), rect.origin.y+(rect.size.height-randomY));
CGFloat overshootValueX = (((CGFloat) (arc4random() % RAND_MAX) / RAND_MAX)) * 4;
CGFloat overshootValueY = (((CGFloat) (arc4random() % RAND_MAX) / RAND_MAX)) * 6;
[path moveToPoint:CGPointMake(topMidPoint.x+overshootValueX, topMidPoint.y)];
[path addQuadCurveToPoint:bottomMidPoint controlPoint:leftControlPoint];
// random value to overshoot
overshootValueX = (((CGFloat) (arc4random() % RAND_MAX) / RAND_MAX)) * 20;
overshootValueY = (((CGFloat) (arc4random() % RAND_MAX) / RAND_MAX)) * 4;
[path addQuadCurveToPoint:CGPointMake(topMidPoint.x-overshootValueX, topMidPoint.y-overshootValueY) controlPoint:rightControlPoint];
return path;
}
Результат выглядит так:
НадеюсьМне не нравится, как он указан сверху, и, несмотря на все мои попытки, я просто не могу получить его намного лучше.Кроме того, мне нравится, что кривые выглядят менее совершенными, и не полагаюсь на выступ, как единственную деталь, выглядящую «от руки».Я думаю, что 2 четырехугольных кривых - неправильный путь .....
Может быть, 4 дуги?
У кого-нибудь есть другое решение или пример кода для меня?(любой язык в порядке)