是什么导致了CGContextAddArc的这种边缘情况? [英] What is causing this edge condition with CGContextAddArc?

查看:84
本文介绍了是什么导致了CGContextAddArc的这种边缘情况?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我通过使用iOS Core Graphics在圆的周围绘制圆点弧来创建视图。计算点中心,将其存储在数组中,然后在显示到屏幕之前使用 CGContextAddArc 对其进行检索。我对用于绘制外围点的方法完全有信心,这些外围点可以如下所示:[A]轮廓线,[B]填充一种颜色,[C]交替填充和轮廓化,[D]填充五种颜色的序列。 / p>



但是,如果将中心点添加到数组中,则在周长上绘制的最后一个点的属性会发生变化。



最简单的方法来证明这种情况将绘制轮廓点,并加上[E]小中心点[F]大中心点和[G]两个中心点;在每种情况下,预计大小中心的小点和大点都将填充为绿色。使用[H]时,两个中心点的轮廓都未填充时也会出现问题。





我已经学习Core Graphics了一个月,需要帮助来确定导致这种情况的边缘条件。我真的很欢迎有经验的核心图形程序员的见解。



这里是实现代码;首先,初始化视图设置的方法。

 -(void)ViewSettings_WaitView {
ectors = 80; //边界
上的点数=扇区;

uberRadius = 52; //大圆周长
dotRadius = 4; //大圆周长上的圆点半径
dotsFilled = FALSE; //用颜色或轮廓填充每个颜色
oneColour = FALSE; //每种颜色或一种颜色
AlternativeDots = FALSE; //交替填充并勾勒出轮廓

ringDot = 64; // 64:显示0:隐藏
ringDotFilled = TRUE; //填充或概述
centerDot = 26; // 26:显示0:隐藏
centerDotFilled = FALSE; //填写或概述

[self centerReference]; //将弧形图设置为从12点的位置开始
[self selectZone]; //模拟在GlobalView中选择的5种颜色中的
}

绘制这些图像的代码

 -(void)drawCircle {
context = UIGraphicsGetCurrentContext(); //获取图形上下文
CGContextSetLineWidth(context,0.5); //设置圆的外部线宽

dotPosition = CGPointMake(uberX,uberY); //环形点和中心点的中心点

//创建环形点(较大的中心点)

if(ringDot!= 0){
iOSCircle * newCircle = [[iOSCircle alloc] init]; //创建一个新的iOSCircle对象
newCircle.circleRadius = ringDot; // ringDot半径
newCircle.circleCentre = dotPosition; //将ringDot放在框架
上[totalCircles addObject:newCircle]; //添加到数组Array
[self setNeedsDisplay]; //更新视图

NSLog(@ ringDot已添加:%@ radius:%f,NSStringFromCGPoint(dotPosition),ringDot);
}

//创建中心点(较小的中心点)

if(centreDot!= 0){
iOSCircle * newCircle = [[iOSCircle alloc] init]; //创建一个新的iOSCircle对象
newCircle.circleRadius = centreDot; // ringDot半径
newCircle.circleCentre = dotPosition; //将ringDot放在框架
上[totalCircles addObject:newCircle]; //添加到数组Array
[self setNeedsDisplay]; //更新视图

NSLog(@添加的centreDot:%@半径:%f,NSStringFromCGPoint(dotPosition),centerDot);
}

//创建扇区点(在圆弧的外围)

for(dotCount = 1; dotCount< limit + 1; dotCount ++)
{
iOSCircle * newCircle = [[iOSCircle alloc] init]; //创建一个新的iOSCircle对象
newCircle.circleRadius = dotRadius;

[self newCentre]; //为每个扇形点

dotPosition = CGPointMake(x,y)创建一个新的x和y点; //创建每个扇形点
newCircle.circleCentre = dotPosition; //将每个点放在框架
上[totalCircles addObject:newCircle]; //添加到数组Array
[self setNeedsDisplay]; //更新视图

NSLog(@ Dot%i%@,dotCount,NSStringFromCGPoint(dotPosition));
}

dotCount = 1;
for(iOSCircle * circle in totalCircles){//遍历数组并获取点尺寸
CGContextAddArc(context,circle.circleCentre.x,circle.circleCentre.y,circle.circleRadius,0.0,M_PI * 2.0,是);

[self renderSectorDots]; //渲染点以查看

dotCount ++;

}
if(ringDot!= 0){
NSLog(@ add ringDot%@ radius:%f,NSStringFromCGPoint(dotPosition),ringDot);

[self renderRingDot];
}
if(centreDot!= 0){
NSLog(@ add centerDot%@ radius:%f,NSStringFromCGPoint(dotPosition),centreDot);

[self renderCentreDot];
}
}

渲染中心点的方法(环形点是

 -(void)renderCentreDot {
switch(centreDotFilled){
情况1:
colourIndex = selectedZone;
[self whatColour];
休息时间;
默认值:
[self dotOutline];
休息时间;
}
}

-(void)whatColour {
switch(colourIndex){
情况1:
//用青色
[self paintCyan];
休息时间;
情况2:
//用红色
填充圆圈[self paintRed];
休息时间;
情况3:
//用黄色
填充圆圈[self paintYellow];
休息时间;
情况4:
//用洋红色
填充圆圈[self paintMagenta];
休息时间;
情况5:
//用绿色
填充圆圈[self paintGreen];
休息时间;
默认值:
休息时间;
}
}

-(void)dotOutline {
CGContextStrokePath(context); //仅绘制外线
}

-(void)paintGreen {
CGContextSetFillColorWithColor(context,[[UIColor greenColor] CGColor]);
CGContextDrawPath(context,kCGPathFillStroke); //用外线颜色填充
}

最后是计算新中心的方法扇区点

 -(void)newCentre {
dotAngle = dotAngle + uberAngle;
x = uberX +(uberRadius * 2 * cos(dotAngle));
y = uberY +(uberRadius * 2 * sin(dotAngle));
// NSLog(@%i%f%f%f,dotCount,dotAngle,endAngle,uberAngle);
}

以及初始化中心参数并从12点钟位置开始绘制的方法

 -(void)centreReference {

uberX = 160;
uberY = 240;
uberAngle =(2.0 * PI)/扇区;

dotAngle = PI * -0.5; //在三点之前开始绘制0.5 PI弧度
endAngle = PI * 1.5; // 3点后停止绘制1.5 PI弧度

NSLog(@%f%f%f%f,uberX,ringY,uberRadius,uberAngle);

}

解决方案

您有80个外圆和0、1或2个内圆。所有这些圆都存储在名为 totalCircles 的单个数组中,内部圆存储在数组的前面。因此,如果您有两个内圆,则 totalCircles 有82个元素。



问题是您只在绘制前80个圈子:两个内部圈子和78个外部圈子。



然后,您尝试填充一个内部圈子,但尝试填充第79个外部圈子。



换句话说,您正在失去对哪个圆圈的了解。






尝试通过以下方式构造代码:



您已经有了一个 iOSCircle对象,这很好。此圆形对象还应包含其颜色并具有绘制自身的功能:

  @interface圆:NSObject 
@财产(非原子)CGPoint中心;
@属性(非原子)CGFloat半径;
属性(非原子性,强)UIColor *颜色;
-(无效)提款;
@end

抽奖方法绘制圆形,并选择填充颜色(如果已设置):

 -(void)draw 
{
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextAddArc(ctx,self.centre.x,self.centre.y等)
if(self.color)
{
[self.color setFill] ;
CGContextDrawPath(ctx,kCGPathFillStroke);
}
else
{
CGContextStrokePath(ctx);
}
}

您应该有一个生成圆形数组的方法对象。这将创建80个外部圆,以及可选的内部圆。



您的主绘制方法就这么简单:

 -(void)drawCircle 
{
NSArray * circle = [self generateCircles];
表示(圆圈*圆圈)
{
[Circle draw];
}
}


I created a view by drawing an arc of dots around the perimeter of a circle using iOS Core Graphics. Dot centres are calculated, stored in an array and retrieved using CGContextAddArc before being rendered to screen. I have every confidence in methods used to draw perimeter dots which may be [A] outlined, [B] filled with one colour, [C] alternately filled and outlined, and [D] filled with a sequence of five colours as shown.

However if centre dots are added to the array the properties of the last dots drawn on the perimeter change.

The simplest way to demonstrate this condition is to draw perimeter dots outlined with the addition of [E] the small centred dot [F] the large centred dot and [G] both centred dots; in each case, both small and large centred dots are expected to be filled green. With [H] there is also a problem when both centred dots are outlined not filled.

I have been learning Core Graphics for a month and need help to identify the edge condition that causes this. I would really welcome the insights of a more experienced core graphics programmer. Thanks.

Here is the implementation code; firstly, the method to initialise view settings.

- (void)ViewSettings_WaitView {
    sectors         = 80;   // number of dots on perimeter
    limit           = sectors;

    uberRadius      = 52;   // radius of large circle perimeter
    dotRadius       = 4;    // radius of dots on large circle perimeter
    dotsFilled      = FALSE;    // fill every with colour or outline
    oneColour       = FALSE;    // every colour or one colour
    alternateDots   = FALSE;    // alternately filled and outlined

    ringDot         = 64;   // 64:show 0:hide
    ringDotFilled   = TRUE; // fill or outlined    
    centreDot       = 26;       // 26:show 0:hide
    centreDotFilled = FALSE;    // fill or outlined

    [self centreReference];     // set up arc drawing to start from 12 o'clock position
    [self selectZone];          // emulate 1-of-5 colours selected in GlobalView
} 

And here is the code that draws these images

- (void)drawCircle                  {
    context          = UIGraphicsGetCurrentContext();          // Get the Graphics Context
    CGContextSetLineWidth(context, 0.5);                       // Set the circle outerline-width

    dotPosition                    = CGPointMake(uberX,uberY); // centre point for ring dot and centre dot

    // create ring dot (larger centre dot)

    if (ringDot     != 0) {
        iOSCircle *newCircle       = [[iOSCircle alloc] init]; // Create a new iOSCircle Object
        newCircle.circleRadius     = ringDot;                  // ringDot radius
        newCircle.circleCentre     = dotPosition;              // place ringDot on the frame
        [totalCircles addObject:newCircle];                    // add to the circle Array
        [self setNeedsDisplay];                                // update the view

        NSLog(@"ringDot added:%@ radius: %f", NSStringFromCGPoint(dotPosition), ringDot);
    }

    // create centre dot (smaller centre dot)

    if (centreDot    != 0) {
        iOSCircle *newCircle       = [[iOSCircle alloc] init]; // Create a new iOSCircle Object
        newCircle.circleRadius     = centreDot;                // ringDot radius
        newCircle.circleCentre     = dotPosition;              // place ringDot on the frame
        [totalCircles addObject:newCircle];                    // add to the circle Array
        [self setNeedsDisplay];                                // update the view

        NSLog(@"centreDot added:%@ radius: %f", NSStringFromCGPoint(dotPosition), centreDot);
    }

    // create sector dots (on perimeter of the arc)

    for (dotCount   = 1; dotCount < limit+1; dotCount++)
    {
        iOSCircle *newCircle    = [[iOSCircle alloc] init];    // Create a new iOSCircle Object
        newCircle.circleRadius  = dotRadius;

            [self newCentre];                                  // create a new x and y point for each sector dot

        dotPosition             = CGPointMake(x,y);            // create each sector dot
        newCircle.circleCentre  = dotPosition;                 // place each dot on the frame
            [totalCircles addObject:newCircle];                // add to the circle Array
            [self setNeedsDisplay];                            // update the view

        NSLog(@"Dot %i %@", dotCount, NSStringFromCGPoint(dotPosition));
    }

    dotCount = 1;
    for (iOSCircle *circle in totalCircles) {                  // Loop through array and retrieve dot dimensions
        CGContextAddArc(context, circle.circleCentre.x, circle.circleCentre.y, circle.circleRadius, 0.0, M_PI * 2.0, YES);

            [self renderSectorDots];                           // render dots to view

    dotCount++;

    }    
    if (ringDot    != 0) {
        NSLog(@"add ringDot %@ radius: %f", NSStringFromCGPoint(dotPosition), ringDot);

        [self renderRingDot];
    }
    if (centreDot    != 0) {
        NSLog(@"add centreDot %@ radius: %f", NSStringFromCGPoint(dotPosition), centreDot);

        [self renderCentreDot];
    }
} 

And the methods for rendering centre dot (ring dot is similar)

- (void)renderCentreDot {
    switch (centreDotFilled) {
        case 1:
            colourIndex = selectedZone;
            [self whatColour];
            break;
        default:
            [self dotOutline];
            break;
    }
} 

- (void)whatColour {
    switch (colourIndex) {
        case 1:
            // Fill the circle with cyan
            [self paintCyan];
            break;
        case 2:
            // Fill the circle with red
            [self paintRed];
            break;
        case 3:
            // Fill the circle with yellow
            [self paintYellow];
            break;
        case 4:
            // Fill the circle with magenta
            [self paintMagenta];
            break;
        case 5:
            // Fill the circle with green
            [self paintGreen];
            break;
        default:
            break;
    }
}

- (void)dotOutline {
    CGContextStrokePath(context);                     // draw outerline only
} 

- (void)paintGreen {
    CGContextSetFillColorWithColor(context, [[UIColor greenColor] CGColor]);
    CGContextDrawPath(context, kCGPathFillStroke);    // fill with outerline-colour
    }

And finally the method for calculating new centres for the sector dots

- (void)newCentre  {
    dotAngle    = dotAngle + uberAngle;
    x           = uberX + (uberRadius * 2 * cos(dotAngle));
    y           = uberY + (uberRadius * 2 * sin(dotAngle));    
//    NSLog(@"%i %f %f %f", dotCount, dotAngle, endAngle, uberAngle);
}

and a method to initialise centre parameters and start drawing from 12 o'clock position

- (void)centreReference { 

    uberX     = 160; 
    uberY     = 240; 
    uberAngle = (2.0 * PI) / sectors; 

    dotAngle  = PI * -0.5;             // start drawing 0.5 PI radians before 3 o'clock
    endAngle  = PI * 1.5;              // stop drawing 1.5 PI radians after 3 o'clock 

    NSLog(@"%f %f %f %f", uberX, ringY, uberRadius, uberAngle); 

}

解决方案

You have 80 outer circles and 0, 1, or 2 inner circles. All of these circles are stored in a single array called totalCircles, and the inner circles are stored at the front of the array. So if you have two inner circles, totalCircles has 82 elements.

The problem is that you're only drawing the first 80 circles: two inner circles and 78 outer circles.

Then you attempt to fill in one of the inner circles, but instead fill in the 79th outer circle.

In other words, you're losing track of which circles are which.


Try structuring your code in the following way:

You already have a "iOSCircle" object, which is good. This circle object should also contain its color and have the ability to draw itself:

@interface Circle : NSObject
@property (nonatomic) CGPoint centre;
@property (nonatomic) CGFloat radius;
@property (nonatomic, strong) UIColor* color;
- (void)draw;
@end

The -draw method draws the circle, optionally filling the color if it is set:

- (void)draw
{
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    CGContextAddArc(ctx, self.centre.x, self.centre.y, etc...)
    if (self.color)
    {
        [self.color setFill];
        CGContextDrawPath(ctx, kCGPathFillStroke);
    }
    else
    {
        CGContextStrokePath(ctx);
    }
}

You should have a method that generates an array of circle objects. This will create the 80 outer circles, and optionally the inner circles. This will also assign a color to each circle.

Your main drawing method then as simple as this:

- (void)drawCircle
{
    NSArray* circles = [self generateCircles];
    for (Circle* circle in circles)
    {
        [circle draw];
    }
}

这篇关于是什么导致了CGContextAddArc的这种边缘情况?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆