2012-05-17 20 views
5

Ich schreibe eine iPad-App, in der ich XML-Objekte, die Formen darstellen, in Grafiken auf dem Bildschirm rendere. Eines der Objekte, die ich zu rendern versuche, sind Bögen. Im Wesentlichen liefern diese Bögen ein begrenzendes Rechteck sowie einen Start- und Endwinkel.Zeichnen Ellipse mit Anfangs- und Endwinkel in Objective-C

angegebenen Attributen:

  • x
  • y
  • Breite
  • Höhe
  • startangle
  • endAngle

Mit diesen Werten I um den Lichtbogen ziehen, müssen (welches im wesentlichen Teil einer Ellipse ist). Ich kann Folgendes nicht verwenden:

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

weil es eine volle Ellipse zeichnet. Grundsätzlich benötige ich das oben genannte, aber es muss die Anfangs- und Endwinkel berücksichtigen, so dass nur ein Teil der Ellipse angezeigt wird. Ich denke, dies wird entweder eine kubische Bezier-Kurve oder eine quadratische Bezier-Kurve zeichnen. Das Problem ist, dass ich keine Ahnung habe, wie ich den Startpunkt, den Endpunkt oder die Kontrollpunkte mit den Informationen berechnen kann, die ich bekomme.

Antwort

9

Sie können sich wahrscheinlich erreichen, was Sie einen Clip Bahn um die Zeichnung der Ellipse durch die Einrichtung wollen.

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); 

Der genaue Radius für den Ausschnitt ist nicht wichtig. Es muss groß genug sein, damit es nur die Ellipse an den Enden, nicht durch den gewünschten Bogen schneidet.

+0

Danke, funktionierte wie ein Zauber (noch neu bei Objective-C und Zeichnungsgrafiken). –

2

Sie addQuadCurveToPoint:controlPoint: statt bezierPathWithOvalInRect.

Die Methodendefinition ist wie zu verwenden: -

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

dass CGPoint ist die Argumente (Input) für die beiden Parameter sind.

Sie müssen auch den Startpunkt mit moveToPoint: vor dem Aufruf addQuadCurveToPoint, die als aktueller Punkt fungieren wird (Wie Sie sehen können, ist ihr Startpunkt als Parameter in der Methode).

In Ihrem Fall müssen Sie

1> x, y als Ausgangspunkt

2> x + Breite und y + Höhe als Endpunkt

Sie Winkel nicht hier brauchen oder Sie können Ihre Logik implementieren, um die Winkel zu verwenden. Ich lade ein Bild hoch, um die Sache klarzustellen.

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

+0

Eine quadratische Bezier-Kurve reicht nicht aus. Vielleicht können Sie Kontrollpunkte für eine kubische Bezierkurve so berechnen, dass eine Ellipse mit den gegebenen Eigenschaften gezeichnet wird.Ohne die Mathematik, die benötigt wird, um die gegebene Information in eine Bezierkurve zu übersetzen, beantwortet dies die Frage nicht. – thundersteele

+0

Eigentlich denke ich, wenn Sie den Pfad explizit (dh NICHT mit Clipping) zeichnen wollen, brauchen Sie die parametrische Gleichung für die Elipse. Dann müssen Sie eine Reihe von kurzen Segmenten (quadratisch oder kubisch oder sogar linear) machen, die die Elipse approximieren. Clipping ist besser. – samson

+1

Dies ist ein großer Techotopia: http://www.techotopia.com/index.php/An_iPhone_Graphics_Drawing_Tutorial_using_Quartz_2D#Drawing_an_Ellipse_or_Circle – Aardvark

3

Diese Kategorie wird Ihnen helfen.

#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

Große Kategorie !!! Nur um es perfekt zu machen, sollte der erste Punkt, zu dem eine Zeile hinzugefügt wird, nicht den Startpunkt enthalten, der firstEllipsePoint im obigen Code ist. Also sollte die For-Anweisung sein für (CGFlotwinkel = startAngle + angleStep; angle

+0

@RungeZhai: ist wahr, fertig! – kanobius

+0

Die EllipsePointForAngle scheint falsch zu sein, oder es gibt eine Diskrepanz, die für die von mir verwendete Methode unterschiedlich ist. Wenn der Winkel um das Oval zunimmt, sieht es aus, als ob es leicht vor und zurück versetzt wäre. Dies wird teilweise dadurch verursacht, dass die Breite und Höhe der Ellipse nicht berücksichtigt werden, was wichtig ist und sich von der Suche nach einem Punkt auf einem Kreis von einem Winkel unterscheidet. – VagueExplanation

Verwandte Themen