2011-05-03 32 views
9

Ben şu kod:Satır tekrar kendi kendine tekrar katlandığında neden birleştirme yapılmıyor?

- (void)drawRect:(CGRect)rect { 
    CGContextRef c = UIGraphicsGetCurrentContext(); 

    CGContextSetFillColorWithColor(c, [UIColor blackColor].CGColor); 
    CGContextFillRect(c, rect); 

    CGContextSetLineJoin(c, kCGLineJoinRound); 
    CGContextSetLineCap(c, kCGLineCapRound); 
    CGContextSetLineWidth(c, 50.0); 

    CGContextSetStrokeColorWithColor(c, [UIColor redColor].CGColor); 
    CGContextBeginPath(c); 
    CGContextMoveToPoint(c, 60, 60); 
    CGContextAddLineToPoint(c, 60, 250); 
    CGContextAddLineToPoint(c, 60, 249); 
    CGContextStrokePath(c); 

    CGContextSetStrokeColorWithColor(c, [UIColor blueColor].CGColor); 
    CGContextBeginPath(c); 
    CGContextMoveToPoint(c, 160, 60); 
    CGContextAddLineToPoint(c, 160, 250); 
    CGContextAddLineToPoint(c, 160.01, 249); 
    CGContextStrokePath(c); 
} 

Bu aşağıdaki çıktıyı oluşturur: kırmızı şeklin alt kenarı yuvarlak değildir bu iyi bir neden

Output of the code

var mı? Yoksa çizgi tam olarak kendi kendine ikiye katlandığında Çekirdek Grafikteki bir hata mı?

cevap

4

Kesinlikle bir böcek. Yola başka bir satır eklemeyi denerseniz, Çekirdek Grafiğin nasıl işleyemediğini görebilirsiniz.

CGContextMoveToPoint(c, 60.0, 60.0); 
CGContextAddLineToPoint(c, 60.0, 250.0); 
CGContextAddLineToPoint(c, 60.0, 249.0); 
CGContextAddLineToPoint(c, 60.0, 250.0); 

enter image description here

O katına ne zaman yuvarlak uçları oluşturur ve katılır maskeleme ters alırsa olarak var

.

+0

Tabii * bu 'CGContextSetLineCap' var ve burada soru değil, yuvarlanır çizginin * biter. Soru, 'kCGLineJoinRound' ile' CGContextSetLineJoin', yol 180 ° döndüğünde (ancak 179.427 ° gibi bir şey döndürdüğünde) birleştirme işlemini tamamlamamasının nedenidir. – Anomie

+0

Üzgünüz, hat kapağını daha yeni gördüm ve satır eklemeyi gözden kaçırdım. Büyük ihtimalle bir hata bulmuşsunuzdur. KCGLineJoinRound dokümantasyonu, birleştirmelerin yuvarlatılmış olması gerektiğini açıkça belirtmektedir, ancak açık değildir. –

+0

Cevabımı güncelledi. –

3

mortenfast bu bir hata olduğunu kanıtladı. Fakat bu cevabı geçici çözümümüzü sunmak için göndereceğim.

bir geçici çözüm, böyle bir şey bu davayı algılamak ve mevcut hattına dik çok kısa çizgi segmentini eklemektir: Bu prevPt adında bir ivar ihtiyacı

- (void)addPtToPath:(CGPoint)newPt { 
    // CoreGraphics seems to have a bug if a path doubles back on itself. 
    // Detect that and apply a workaround. 
    CGPoint curPt = CGPathGetCurrentPoint(self.currentPath); 
    if (!CGPointEqualToPoint(newPt, curPt)) { 
     CGFloat slope1 = (curPt.y - prevPt.y)/(curPt.x - prevPt.x); 
     CGFloat slope2 = (curPt.y - newPt.y)/(curPt.x - newPt.x); 
     CGFloat diff; 
     BOOL between; 
     if (isinf(slope1) && isinf(slope2)) { 
      // Special-case vertical lines 
      diff = 0; 
      between = ((prevPt.y < curPt.y) != (curPt.y < newPt.y)); 
     } else { 
      diff = slope1 - slope2; 
      between = ((prevPt.x < curPt.x) != (curPt.x < newPt.x)); 
     } 
     if (between && diff > -0.1 && diff < 0.1) { 
      //NSLog(@"Hack alert! (%g,%g) (%g,%g) (%g,%g) => %g %g => %g", prevPt.x, prevPt.y, curPt.x, curPt.y, newPt.x, newPt.y, slope1, slope2, diff); 
      if (isinf(slope1)) { 
       curPt.x += 0.1; 
      } else if (slope1 == 0) { 
       curPt.y += 0.1; 
      } else if (slope1 < -1 || slope1 > 1) { 
       curPt.x += 0.1; curPt.y -= 0.1/slope1; 
      } else { 
       curPt.x -= 0.1 * slope1; curPt.y += 0.1; 
      } 
      CGPathAddLineToPoint(self.currentPath, NULL, curPt.x, curPt.y); 
     } 
     prevPt = curPt; 
    } 
    CGPathAddLineToPoint(self.currentPath, NULL, newPt.x, newPt.y); 
} 

ve Ivar yolun çalışır currentPath.

İlgili konular