2012-05-17 20 views
5

Tôi đang viết một ứng dụng iPad trong đó tôi đang hiển thị các đối tượng XML đại diện cho các hình dạng thành đồ họa trên màn hình. Một trong những đối tượng mà tôi đang cố gắng render là vòng cung. Về cơ bản, các cung này cung cấp cho tôi một hình chữ nhật bao quanh cũng như góc bắt đầu và kết thúc.Vẽ hình elip với góc bắt đầu và kết thúc trong Mục tiêu-C

thuộc tính Given:

  • x
  • y
  • rộng
  • chiều cao
  • startAngle
  • endAngle

Với những giá trị tôi cần phải vẽ arc (mà về cơ bản là một phần của hình elip). Tôi không thể sử dụng các mục sau:

UIBezierPath *arc = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(x, y, width, height)]; 
    [UIColor blackColor] setStroke]; 
    [arc stroke]; 

vì nó vẽ hình elip đầy đủ. Về cơ bản tôi cần ở trên nhưng nó cần phải đưa vào tài khoản các góc bắt đầu và kết thúc để chỉ một phần của hình elip được hiển thị. Tôi nghĩ rằng điều này sẽ liên quan đến việc vẽ một đường cong Bezier khối hoặc đường cong Bezier bậc hai. Vấn đề là tôi không có đầu mối làm thế nào để tính toán điểm bắt đầu, điểm kết thúc, hoặc các điểm điều khiển với thông tin tôi đã đưa ra.

Trả lời

9

Bạn có lẽ có thể đạt được những gì bạn muốn bằng cách thiết lập một con đường kẹp xung quanh bản vẽ của hình elip.

CGContextSaveGState(theCGContext); 
CGPoint center = CGPointMake(x + width/2.0, y + height/2.0); 
UIBezierPath* clip = [UIBezierPath bezierPathWithArcCenter:center 
                radius:max(width, height) 
               startAngle:startAngle 
                endAngle:endAngle 
               clockwise:YES]; 
[clip addLineToPoint:center]; 
[clip closePath]; 
[clip addClip]; 

UIBezierPath *arc = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(x, y, width, height)]; 
[[UIColor blackColor] setStroke]; 
[arc stroke]; 

CGContextRestoreGState(theCGContext); 

Bán kính chính xác cho việc cắt không quan trọng. Nó cần phải đủ lớn để nó chỉ kẹp hình elip ở hai đầu, không phải qua vòng cung mong muốn.

+0

Cảm ơn, đã làm việc như một say mê (vẫn còn mới với Objective-C cũng như vẽ đồ họa). –

2

Bạn sẽ phải sử dụng addQuadCurveToPoint:controlPoint: thay vì bezierPathWithOvalInRect.

Định nghĩa phương pháp là như sau: -

- (void)addQuadCurveToPoint:(CGPoint)endPoint controlPoint:(CGPoint)controlPoint 

đó là CGPoint là các đối số (đầu vào) cho cả các thông số.

Bạn cũng sẽ phải đặt điểm bắt đầu bằng cách sử dụng moveToPoint: trước khi gọi addQuadCurveToPoint sẽ hoạt động như điểm hiện tại (Vì bạn có thể thấy điểm bắt đầu của chúng không phải là tham số trong phương thức).

Trong trường hợp của bạn, bạn sẽ có

1> x, y làm điểm xuất phát

2> x + chiều rộng và y + chiều cao như thiết bị đầu cuối

bạn không cần góc đây hoặc bạn có thể thực hiện logic của mình để sử dụng các góc. Đang tải lên một hình ảnh để làm rõ mọi thứ.

Here is the image describing the start point,end point and control point

+0

Đường cong bezier bậc hai sẽ không hoạt động. Có lẽ bạn có thể tính toán các điểm kiểm soát cho một đường cong bezier khối sao cho một hình elip được vẽ với các thuộc tính đã cho.Nếu không có toán cần thiết để dịch các thông tin nhất định thành một đường cong bezier, điều này không trả lời câu hỏi. – thundersteele

+0

Trên thực tế, tôi nghĩ rằng nếu bạn muốn vẽ đường dẫn một cách rõ ràng (nghĩa là KHÔNG với cắt), bạn cần phương trình tham số cho elip. Sau đó, bạn sẽ phải thực hiện một loạt các phân đoạn ngắn (bậc hai hoặc khối, hoặc thậm chí tuyến tính) mà APPROXIMATE elipse. Clipping là tốt hơn. – samson

+1

Đây là một Techotopia tuyệt vời: http://www.techotopia.com/index.php/An_iPhone_Graphics_Drawing_Tutorial_using_Quartz_2D#Drawing_an_Ellipse_or_Circle – Aardvark

3

Danh mục này sẽ hữu ích.

#import <Foundation/Foundation.h> 

@interface UIBezierPath (OvalSegment) 

+ (UIBezierPath *)bezierPathWithOvalInRect:(CGRect)rect startAngle:(CGFloat)startAngle endAngle:(CGFloat)endAngle; 
+ (UIBezierPath *)bezierPathWithOvalInRect:(CGRect)rect startAngle:(CGFloat)startAngle endAngle:(CGFloat)endAngle angleStep:(CGFloat)angleStep; 

@end 

#import "UIBezierPath+OvalSegment.h" 

@implementation UIBezierPath (OvalSegment) 

+ (UIBezierPath *)bezierPathWithOvalInRect:(CGRect)rect startAngle:(CGFloat)startAngle endAngle:(CGFloat)endAngle angleStep:(CGFloat)angleStep { 
    CGPoint center = CGPointMake(CGRectGetMidX(rect), CGRectGetMidY(rect)); 
    CGFloat xRadius = CGRectGetWidth(rect)/2.0f; 
    CGFloat yRadius = CGRectGetHeight(rect)/2.0f; 

    UIBezierPath *ellipseSegment = [UIBezierPath new]; 

    CGPoint firstEllipsePoint = [self ellipsePointForAngle:startAngle withCenter:center xRadius:xRadius yRadius:yRadius]; 
    [ellipseSegment moveToPoint:firstEllipsePoint]; 

    for (CGFloat angle = startAngle + angleStep; angle < endAngle; angle += angleStep) { 
     CGPoint ellipsePoint = [self ellipsePointForAngle:angle withCenter:center xRadius:xRadius yRadius:yRadius]; 
     [ellipseSegment addLineToPoint:ellipsePoint]; 
    } 

    CGPoint lastEllipsePoint = [self ellipsePointForAngle:endAngle withCenter:center xRadius:xRadius yRadius:yRadius]; 
    [ellipseSegment addLineToPoint:lastEllipsePoint]; 

    return ellipseSegment; 
} 

+ (UIBezierPath *)bezierPathWithOvalInRect:(CGRect)rect startAngle:(CGFloat)startAngle endAngle:(CGFloat)endAngle { 
    return [UIBezierPath bezierPathWithOvalInRect:rect startAngle:startAngle endAngle:endAngle angleStep:M_PI/20.0f]; 
} 

+ (CGPoint)ellipsePointForAngle:(CGFloat)angle withCenter:(CGPoint)center xRadius:(CGFloat)xRadius yRadius:(CGFloat)yRadius { 
    CGFloat x = center.x + xRadius * cosf(angle); 
    CGFloat y = center.y - yRadius * sinf(angle); 
    return CGPointMake(x, y); 
} 

@end 
+0

Danh mục tuyệt vời !!! Chỉ để làm cho nó hoàn hảo, điểm đầu tiên để thêm dòng vào không nên bao gồm điểm bắt đầu là firstEllipsePoint trong đoạn mã trên. Vì vậy, câu lệnh 'for' sẽ là' cho (CGFloat angle = startAngle + angleStep; góc

+0

@RungeZhai: là đúng, đã hoàn tất! – kanobius

+0

EllipsePointForAngle có vẻ không chính xác hoặc có sự khác biệt về phương pháp tôi sử dụng. Khi góc tăng xung quanh hình bầu dục, nó có vẻ hơi lệch qua lại. Điều này một phần là do không bao gồm chiều rộng và chiều cao của hình elip, điều này rất quan trọng và khác với việc chỉ tìm một điểm trên một vòng tròn từ một góc. – VagueExplanation