在Objective-C中绘制起始和结束angular度的椭圆
我正在编写一个iPad应用程序,在该应用程序中,将呈现形状的XML对象呈现在屏幕上的graphics中。 我想渲染的对象之一是弧线。 基本上这些弧为我提供了一个边界矩形以及一个开始和结束angular度。
给定属性:
- X
- ÿ
- 宽度
- 高度
- 由startAngle
- endAngle
有了这些值,我需要绘制弧(其实质上是椭圆的一部分)。 我不能使用以下内容:
UIBezierPath *arc = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(x, y, width, height)]; [UIColor blackColor] setStroke]; [arc stroke];
因为它绘制了一个完整的椭圆。 基本上我需要上面的,但它需要考虑到开始和结束的angular度,所以只有一部分的椭圆显示。 我想这将涉及绘制一个三次贝塞尔曲线或二次贝塞尔曲线。 问题是我不知道如何计算我给出的信息的起点,终点或控制点。
你可以通过在椭圆的graphics周围设置一个剪辑path来达到你想要的效果。
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);
剪切的确切半径并不重要。 它需要足够大,所以它只能夹住椭圆的末端,而不是通过所需的弧线。
这个类别将有所帮助。
#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
您将不得不使用addQuadCurveToPoint:controlPoint:
而不是bezierPathWithOvalInRect.
方法定义如下: –
- (void)addQuadCurveToPoint:(CGPoint)endPoint controlPoint:(CGPoint)controlPoint
即CGPoint是两个参数的参数(input)。
在调用addQuadCurveToPoint
之前,你还必须使用moveToPoint:
来设置addQuadCurveToPoint
,它将作为当前点(正如你可以在方法中看到它们没有起点的参数一样)。
在你的情况下,你会有
1> x,y作为你的出发点
2> x +宽度和y +高度作为终点
你不需要在这里angular度,或者你可以实现你的逻辑使用的angular度。上传图像,使事情清楚。