2012-03-04 72 views
1

當從currentPoint.xcurrentPoint.ylastPoint.xlastPoint.ylastPoint.y, 從右上角或右下角繪製時,它在給出的繪圖線中的間隙(空間)顯示在下圖中。移動對角線時,畫筆畫不完整?

sample screenshot

-(void)brushType{ 
      UIGraphicsBeginImageContext(drawImage.frame.size); 
      CGContextRef Mycontext = UIGraphicsGetCurrentContext(); 
      int x, cx, deltax, xstep,y, cy, deltay, ystep,error, st, dupe; 
      int x0, y0, x1, y1; 

      x0 = currentPoint.x; 
      y0 = currentPoint.y; 
      x1 = lastPoint.x; 
      y1 = lastPoint.y; 
      // find largest delta for pixel steps 
      st =(abs(y1 - y0) > abs(x1 - x0)); 
      // if deltay > deltax then swap x,y  
      if (st) { 

       (x0 ^= y0); 
       (y0 ^= x0); 
       (x0 ^= y0); //swap(x0, y0); 
       (x1 ^= y1); 
       (y1 ^= x1); 
       (x1 ^= y1); // swap(x1, y1); 
      } 
      deltax = abs(x1 - x0); 
      deltay = abs(y1 - y0); 
      error = (deltax/4); 
      y = y0; 
      if (x0 > x1) { 
       xstep = -1; 
      } 
      else { 
       xstep = 1; 
      } 
      if (y0 > y1) { 
       ystep = -1; 
      } 
      else { 
       ystep = 1; 
      } 

      for ((x = x0); (x != (x1 + xstep)); (x += xstep)) 
      { 
       (cx = x); 
       (cy = y); // copy of x, copy of y 

       // if x,y swapped above, swap them back now 
       if (st) { 
        (cx ^= cy); 
        (cy ^= cx); 
        (cx ^= cy); 
       } 

       (dupe = 0); // initialize no dupe 

       if(!dupe) { 

        CGContextSetRGBStrokeColor(Mycontext, 0.0, 0.0, 0.0, 1.00f);    
        CGContextMoveToPoint(Mycontext, cx+brushSize*4,cy-brushSize/2); 
        CGContextAddLineToPoint(Mycontext, cx-brushSize/2, cy+brushSize*4); 
      } 

       (error -= deltay); // converge toward end of line 
         if (error < 0) { // not done yet 
        (y += ystep); 
        (error += deltax);} 
       } 
      CGContextStrokePath(Mycontext); 
     [drawImage.image drawInRect:CGRectMake(0, 0, drawImage.frame.size.width, drawImage.frame.size.height)]; 
      drawImage.image = UIGraphicsGetImageFromCurrentImageContext();  
      UIGraphicsEndImageContext(); 
      lastPoint = currentPoint; 

     } 

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { 

    brushSize = 4; 

    mouseSwiped = YES; 
    UITouch *touch = [touches anyObject]; 
    currentPoint = [touch locationInView:drawImage]; 
    currentPoint.y -= 20; 

    [self brushType]; 


} 

,如果任何人有任何想法,請諮詢我解決這個問題!

@Thanks To All提前!

+1

我知道這是無關的,真正的問題,但你真的[不應該使用XOR互換將變量(HTTP ://en.wikipedia.org/wiki/Xor_swap#Reasons_for_avoidance_in_practice)。它使你的代碼變得更慢,更安全,可讀性更低。 – 2012-03-05 00:20:41

回答

2

我看到一堆問題與你的功能,其中大多數是不良風格。您正在使用XOR-swap,這會使代碼難以閱讀。你在方法的頂部聲明瞭所有的變量,這使得更難理解每個變量的生命週期。你在整個地方放置不必要的括號,使得代碼難以閱讀。您可以在循環中重複呼叫CGContextSetRGBStrokeColor,但只需設置筆觸顏色一次。因此,首先讓我們來重寫你的方法來解決這些問題:

static inline void swap(int *a, int *b) { 
    int t = *a; 
    *a = *b; 
    *b = t; 
} 

-(void)brushType { 
    int x0 = currentPoint.x; 
    int y0 = currentPoint.y; 
    int x1 = lastPoint.x; 
    int y1 = lastPoint.y; 
    int deltax = abs(x1 - x0); 
    int deltay = abs(y1 - y0); 

    int needSwap = deltay > deltax; 
    if (needSwap) { 
     swap(&x0, &y0); 
     swap(&x1, &y1); 
     swap(&deltax, &deltay); 
    } 

    int error = deltax/4; 
    int y = y0; 
    int xstep = x0 > x1 ? -1 : 1; 
    int ystep = y0 > y1 ? -1 : 1; 

    CGSize size = self.drawImage.bounds.size; 
    UIGraphicsBeginImageContext(size); { 
     CGContextRef gc = UIGraphicsGetCurrentContext(); 
     for (int x = x0; x != x1 + xstep; x += xstep) 
     { 
      int cx = x; 
      int cy = y; 
      if (needSwap) 
       swap(&cx, &cy); 

      CGContextMoveToPoint(gc, cx + brushSize*4, cy - brushSize/2); 
      CGContextAddLineToPoint(gc, cx - brushSize/2, cy + brushSize*4); 

      error -= deltay; // converge toward end of line 
      if (error < 0) { // not done yet 
       y += ystep; 
       error += deltax; 
      } 
     } 
     [UIColor.blackColor setStroke]; 
     CGContextStrokePath(gc); 
     [self.drawImage.image drawInRect:CGRectMake(0, 0, size.width, size.height)]; 
     self.drawImage.image = UIGraphicsGetImageFromCurrentImageContext();  
    } UIGraphicsEndImageContext(); 
    lastPoint = currentPoint; 
} 

所以現在更容易理解,你沿着直線步進從lastPointcurrentPoint。如果該行主要是水平的,則在每一步中將x增加1(或-1),並根據需要增加y以保持接近真實直線。如果該行主要是垂直的,則交換x和y。

這是問題所在。假設直線處於45度角。你將在每一步中將x增加1,y增加1。畢達哥拉斯告訴我們,你正在移動sqrt(2)的距離≈每步約1.4142點。由於您的「筆刷」以默認筆劃寬度爲1點的方式撫摸,因此筆刷的相鄰郵票之間存在間隙。

解決此問題的正確方法是停止使用int s和糾錯術語來計算沿線的點。核心圖形和UIKit無論如何都使用CGFloat s,所以通過使用int s,您不僅會得到不準確的結果,還會觸發從CGFloatint之間的額外轉換,並返回。

你需要做的是店x和y爲CGFloat,並且在每一步增加他們兩個,這樣刷郵票之間的距離是1

-(void)brushType { 
    CGFloat dx = currentPoint.x - lastPoint.x; 
    CGFloat dy = currentPoint.y - lastPoint.y; 
    CGFloat length = hypotf(dx, dy); 
    dx /= length; 
    dy /= length; 

    CGSize size = self.drawImage.bounds.size; 
    // Bonus! This works correctly on Retina devices! 
    UIGraphicsBeginImageContextWithOptions(size, NO, self.drawImage.window.screen.scale); { 
     CGContextRef gc = UIGraphicsGetCurrentContext(); 

     for (CGFloat i = 0; i < length; ++i) { 
      CGFloat x = lastPoint.x + i * dx; 
      CGFloat y = lastPoint.y + i * dy; 
      CGContextMoveToPoint(gc, x + brushSize * 4, y - brushSize/2); 
      CGContextAddLineToPoint(gc, x - brushSize/2, y + brushSize * 4); 
     } 

     [UIColor.blackColor setStroke]; 
     CGContextSetLineWidth(gc, 1.01); 
     CGContextStrokePath(gc); 
     [self.drawImage.image drawAtPoint:CGPointZero]; 
     self.drawImage.image = UIGraphicsGetImageFromCurrentImageContext(); 
    } UIGraphicsEndImageContext(); 
    lastPoint = currentPoint; 
} 

如果你使用這個版本的方法,你會發現,它看起來好多了,但仍然不是很完美:

better screenshot

的問題,我認爲,這是對角劃使用抗鋸齒繪製和抗鋸齒是近似值。如果您將兩條寬度爲1的線繪製爲1點,則每條線對公共像素貢獻的部分着色不會完美疊加。

解決這個問題的一個簡單而方便的方法是讓您的筆觸寬度稍寬一些。只需CGContextStrokePath前補充一點:

 CGContextSetLineWidth(gc, 1.1); 

結果:

best screen shot

+1

你真棒!非常感謝 – kiran 2012-03-05 06:19:32

+1

它真的很好運!再次感謝! – kiran 2012-03-05 06:20:43