2011-09-19 23 views
6

Obecnie pracuję nad projektem na iPada, w którym potrzebuję funkcji pozwalającej użytkownikowi pisać na kartce papieru za pomocą rysika.Płynne pisanie na iPadzie

Przetestowałem kilka rysików i odkryłem, że bambus jest najlepszy. Mają też darmową aplikację, której możesz użyć do napisania.

Problem, który napotykam, polega na tym, że metoda, której używam, nie zapewnia płynnych krzywych. Bambusowa aplikacja na papier zapewnia idealnie wyglądające linie. To jest kod, który mam do tej pory:

- (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]; 
} 

Oto obrazy, które jasno pokazują, jaki problem mam do czynienia. Jest to obraz tego, co zostanie wygenerowany podczas pisania kodu podany powyżej:

enter image description here

To jest obraz, czy piszę to samo w aplikacji mamboo papieru:

enter image description here

Does Czy ktoś ma pomysł, jak uzyskać ładne pisanie, jak w aplikacji mamboo?

+0

możliwy duplikat [algorytmu rysowania gładzi iPhone'a] (http://stackoverflow.com/questions/5076622/iphone-smooth-sketch-sketch-drawing-algorithm) –

+0

Zobacz także [jak mogę śledzić ruch palca na dotyku do rysowania gładkich krzywych?] (http://stackoverflow.com/questions/1052119/how-can-i-trace-the-finger-movement-on-touch-for-drawing-beooth-curves). –

+0

zobacz przykładowy https: // github.com/yusenhan/Smooth-Line-View –

Odpowiedz

7

Zamiast łączenia punktów za pomocą linii prostych (CGPathAddLineToPoint) należy spróbować użyć krzywych Beziera: CGPathAddCurveToPoint lub CGPathAddQuadCurveToPoint.

To właśnie spowoduje wygładzenie.


Jeżeli nie jesteś familliar z krzywych Beziera, prawdopodobnie okaże the wikipedia page about Bézier curves ciekawe (które nie zostały równań matematycznych, ale spojrzeć na szkice i animacjami). Przedstawi ogólne pojęcie o tym, w jaki sposób punkty kontrolne wpływają na wygładzanie linii wokół kluczowych punktów linii.

Dla Twojego przypadku krzywe kwadratowe (tylko jeden punkt kontrolny dla każdego podsegmentu między dwoma kluczowymi punktami) powinny wystarczyć.

Construction of a quadratic Bézier curve - Source: Wikipedia (Jedna linia od P0 do P1, wygładzona za pomocą punktu kontrolnego P1)


Jednym z przykładów (po wyjęciu z pudełka, tylko sugestia z mojego umysłu, nie testowane, dostosowanie współczynniki do twoich potrzeb) do obliczenia tego punktu kontrolnego C pomiędzy każdym z twoich punktów A i B jest sprawienie, by AC był, powiedzmy, 2/3 długości AB, i (AB, AC) tworząc kąt 30 stopni lub sthg podobne.

Możesz nawet zaproponować w ustawieniach swojej aplikacji, aby dostosować siłę wygładzania za pomocą suwaka, co wpłynie na wartości, które wybierzesz, aby obliczyć poszczególne punkty kontrolne i zobaczyć, które współczynniki pasują najlepiej.

+0

Ok, nigdy nie użyłem krzywych Beziera w aplikacji na iOS (użyłem ich kilka lat temu do gry Java, jeśli dobrze pamiętam) Przeszukuję w Internecie kilka dobrych przykładów . Jeśli masz dobre przykłady, daj mi znać: D Dziękujemy za odpowiedź! (Obiekt linePath, którego teraz używam to CGMutablePathRef) – CyberK

+0

Nie jestem pewien, czy go widziałeś, ale edytowałem swoją odpowiedź od czasu pierwszej odpowiedzi z pewnymi sugestiami;) – AliSoftware

+0

Tak, widziałem to ;-) – CyberK