i'm using box2d for the first time, and i've set up my shapes via the hello world tutorial.
I am creating a box as so:
b2BodyDef bodyDef;
bodyDef.type = b2_kinematicBody;
bodyDef.position.Set(7.0f, 7.0f);
bodyDef.angle = 0;
m_body = m_world->CreateBody(&bodyDef);
b2PolygonShape shape;
shape.SetAsBox(1.5f, 0.5f);
b2FixtureDef fixtureDef;
fixtureDef.shape = &shape;
fixtureDef.density = 1.0f;
m_body->CreateFixture(&fixtureDef);
Now I am ready to render this box, so I call:
b2Vec2 pos = m_body->GetPosition();
At this point, I need to call m_renderTarget->SetTransform() using the values of pos, but I can't figure out how to render the box correctly. I have tried:
m_renderTarget->SetTransform(D2D1::Matrix3x2F::Translation(pos.x * 30, pos.y * 30));
m_renderTarget->DrawRectangle(D2D1::RectF(0.0f, 0.0f, 3.0f * 30.0f, 1.0f * 30.0f), m_brush);
And the circle:
bodyDef.type = b2_dynamicBody;
bodyDef.position.Set(7.0f, 1.0f);
m_circleBody = m_world->CreateBody(&bodyDef);
b2CircleShape circleShape;
circleShape.m_p.Set(0.0f, 0.0f);
circleShape.m_radius = 0.5f;
fixtureDef.shape = &circleShape;
m_circleBody->CreateFixture(&fixtureDef);
And to render the circle:
b2Vec2 circlePos = m_circleBody->GetPosition();
mpRenderTarget->SetTransform(D2D1::Matrix3x2F::Translation(circlePos.x * 30.0f, circlePos.y * 30.0f));
mpRenderTarget->DrawEllipse(D2D1::Ellipse(D2D1::Point2F(0.0f, 0.0f), 30.0f, 30.0f), m_brush);
You aren't drawing your rectangle properly centered. The rectangle's center is the top left.
m_renderTarget->DrawRectangle(D2D1::RectF(0.0f, 0.0f, 3.0f * 30.0f, 1.0f * 30.0f), m_brush);
In order to center it properly, you should have Left = -Right, Top = -Bottom like so
m_renderTarget->DrawRectangle(D2D1::RectF(-1.5 * 30.f, -0.5 * 30.f, 1.5f * 30.0f, 0.5f * 30.0f), m_brush);
Here's a diagram explaining why centering is important:
Physically you represent both shapes properly, but graphically you unknowingly added an offset to the rectangle. Also, your scale is off: you assume 1 = 30 pixels for the rectangle, and 0.5 = 30 pixels for the circle. Consistency is key in simulations, so you should lower your D2D1::Ellipse's radii to 15 each.
Related
CGContextDrawRadialGradient produces a very visible ‘cross’ at the centre of the gradient:
Code (reduced):
- (void)drawRect:(NSRect)dirtyRect {
CGContextRef context = [[NSGraphicsContext currentContext] graphicsPort];
size_t numberOfGradientLocations = 2;
CGFloat startRadius = 0.0f;
CGFloat endRadius = 30.0f;
CGPoint centre = CGPointMake(floorf(self.bounds.size.width / 2), floorf(self.bounds.size.height / 2));
CGFloat gradientColours[8] = {0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f};
CGFloat gradientLocations[2] = {0.0f, 1.0f};
CGColorSpaceRef colourspace = CGColorSpaceCreateDeviceRGB();
CGGradientRef gradient = CGGradientCreateWithColorComponents(colourspace, gradientColours, gradientLocations, numberOfGradientLocations);
CGContextDrawRadialGradient(context, gradient, centre, startRadius, centre, endRadius, kCGGradientDrawsBeforeStartLocation);
}
This happens on both macOS and iOS. Meanwhile, the same kind of gradient renders perfectly in WebKit with CSS (so it’s not some ‘bad display’ issue).
What am I doing wrong? Is there a known way around this?
Here's what I get on iOS; I used the iPhone 7 Plus simulator at 100% so as to make every pixel visible, and it seems completely smooth:
EDIT After some experimentation, I suspect you're seeing a moiré effect caused by misalignment between points and pixels.
I'm new to core graphics and I'm struggling with a simple task of putting a sweeping circle inside a square. The outcome I got looks like this:
The circle won't appear at the center of the square, and the size of the circle appears much smaller than I specified.
Below is my drawRect method for drawing the circle. I have put the printed-out variable values while debugging in the comments for your convenience. I also printed out the value passed to initWithFrame: frame=(0 0; 256 256). The frame is the orange square you see in the picture.
- (void)drawRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
CGFloat midX = CGRectGetMidX(self.bounds); // bounds = (0 0; 256 256); midX = 128
CGFloat midY = CGRectGetMidY(self.bounds); // midY = 128
CGFloat radius = midY - 4; // radius = 124
// Outer grey pie
[endColor setFill];
CGContextMoveToPoint(context, midX, midY); // move to center
CGContextAddEllipseInRect(context, CGRectMake(midX - radius, midY - radius, radius * 2, radius * 2)); // adds a circle of radius = square_side_length - 4
CGContextFillPath(context); // fill the circle above with grey
// Show the clock
NSTimeInterval seconds = [[NSDate date] timeIntervalSince1970];
CGFloat mod = fmod(seconds, self.period);
CGFloat percent = mod / self.period;
[fillColor setFill];
CGFloat start = -M_PI_2;
CGFloat end = 2 * M_PI;
CGFloat sweep = end * percent + start;
CGContextMoveToPoint(context, midX, midY);
CGContextAddArc(context, midX, midY, radius, start, sweep, 0); // radius = square_side_length - 24
CGContextFillPath(context);
// Innermost white pie
radius -= 50; // radius = square_side_length - 54
[bgColor setFill]; // white
CGContextMoveToPoint(context, midX, midY);
CGContextAddEllipseInRect(context, CGRectMake(midX - radius, midY - radius, radius * 2, radius * 2));
CGContextFillPath(context);
}
And below is the code that adds the clock to its superview:
clock = [[ProgressClock alloc] initWithFrame:self.clockHolder.bounds // bounds=[0 0; 256 256]
period:[TOTPGenerator defaultPeriod]
bgColor:[UIColor whiteColor]
strokeColor:[UIColor colorWithWhite:0 alpha:0.2]
fillColor:[UIColor blueColor]
endColor:[UIColor grayColor]
shade:NO];
[self.clockHolder addSubview:clock];
Can anyone spot the mistake I made? Thanks in advance.
Thanks a lot to #originaluser2's comment, I have fixed this issue simply by moving the clock presenting logic from viewDidLoad to viewDidAppear and the clock showed up perfectly. There was nothing wrong with the drawing code I posted; however the auto-layout initialization and the animation of my clock happened in a sequence that gave my drawing canvas a wrong frame. By putting the drawing logic in viewDidAppear, we are guaranteed that all the auto-layout setup has been completed, thus frames are fixed, before continue onto drawing the circle.
I'm in the process of creating a custom 'star' control in that you would be able to pass a float into the control as the rating i.e. 2.5, and 2.5 out of 5 stars would be coloured red and the rest, gray.
I'm drawing the stars using a UIBezierPath with 5 points and this is working perfectly. However, as I am using floats, I need to make sure that the decimals are taken into account. I thought that the best way to accomplish this would be by clipping the bezier path to a proportion of the final width, however, this method doesn't seem to have any effect on the drawing itself; the stars are drawn as normal, not taking into account the decimals.
As you probably expected me to say, I have indeed only just started dabbling in CoreGraphics and would like an explanation as to why my method doesn't work and a method to fix it, in order to help with my progression through the framework.
Look forward to hearing some responses!
- (void)drawStarsWithRating:(float)rating maxRating:(float)maxRating yOrigin:(CGFloat)yOrigin inContext:(CGContextRef)context {
float width = MKRGlyphSize;
CGFloat xCenter = MKRLeftBorderPadding + (0.5 * width);
CGFloat yCenter = yOrigin + (0.5 * width);
double r = width / 2.0;
float flip = -1.0;
for (NSUInteger i = 0; i < maxRating; i++) {
CGContextSaveGState(context);
if (i < rating) {
if (self.selected) {
CGContextSetFillColorWithColor(context, RGB(125, 212, 67).CGColor);
}
else {
CGContextSetFillColorWithColor(context, RGB(215, 35, 32).CGColor);
}
}
else {
if (self.selected) {
CGContextSetFillColorWithColor(context, [UIColor whiteColor].CGColor);
}
else {
CGContextSetFillColorWithColor(context, RGB(178, 178, 178).CGColor);
}
}
double theta = 2.0 * M_PI * (2.0 / 5.0);
UIBezierPath *bezier = [UIBezierPath bezierPath];
[bezier moveToPoint:CGPointMake(xCenter, r * flip + yCenter)];
for (NSUInteger k = 1; k < 5; k++) {
float x = r * sin(k * theta);
float y = r * cos(k * theta);
[bezier addLineToPoint:CGPointMake(x + xCenter, y * flip + yCenter)];
}
[bezier setLineWidth:1.0f];
[bezier setLineJoinStyle:kCGLineJoinMiter];
[bezier closePath];
[bezier fill];
if (rating - floorf(rating) > 0) {
CGRect clipRect = CGRectMake(xCenter, yOrigin, width * (rating - floorf(rating)), width);
CGContextClipToRect(context, clipRect);
}
xCenter += width;
CGContextRestoreGState(context);
}
}
One problem I noticed is that you [fill] the path only once. this means for fractional stars you would've only seen one half of the star and not the other half. In the code below, each star is filled with white, and then if any portion of the star is within the rating, then it is filled again with blue.
I also noticed that the clipping rectangle you were using started its X at xCenter instead instead of the lefthand side of the star.
I also adjusted the math a bit to calculate the % filled for each star more consistently.
- (void)drawStarsWithRating:(float)rating maxRating:(float)maxRating yOrigin:(CGFloat)yOrigin inContext:(CGContextRef)context {
float width = MKRGlyphSize;
CGFloat xCenter = MKRLeftBorderPadding + (0.5 * width);
CGFloat yCenter = yOrigin + (0.5 * width);
double r = width / 2.0;
float flip = -1.0;
for (NSUInteger i = 0; i < maxRating; i++) {
CGContextSaveGState(context);
// for clarity, i removed the colors from the top
// and ignore selected state. i use blue/white
// colors hard coded below
//
// you can easily change those colors just as you
// had before
// create star path
double theta = 2.0 * M_PI * (2.0 / 5.0);
UIBezierPath *bezier = [UIBezierPath bezierPath];
[bezier moveToPoint:CGPointMake(xCenter, r * flip + yCenter)];
for (NSUInteger k = 1; k < 5; k++) {
float x = r * sin(k * theta);
float y = r * cos(k * theta);
[bezier addLineToPoint:CGPointMake(x + xCenter, y * flip + yCenter)];
}
[bezier setLineWidth:1.0f];
[bezier setLineJoinStyle:kCGLineJoinMiter];
[bezier closePath];
// fill background of star with white
[[UIColor whiteColor] setFill];
[bezier fill];
// calculate the percentage of this star
// that we should fill
CGFloat currStar = i;
CGFloat percentOfStar;
if(rating > currStar){
// at least some of the star should be filled
percentOfStar = rating - currStar > 0 ? rating - currStar : 0;
percentOfStar = percentOfStar > 1 ? 1 : percentOfStar;
}else{
// none of the star should be filled
percentOfStar = 0;
}
if (percentOfStar) {
// if we need at least a little filling, then clip to that % of the star
// notice (xCenter - .5*width) to align the clipRect to the left side of
// the star.
// now fill the selected portion of the star with blue
CGRect clipRect = CGRectMake(xCenter - .5*width, yOrigin, width * (percentOfStar), width);
CGContextClipToRect(context, clipRect);
[[UIColor blueColor] setFill];
[bezier fill];
}
xCenter += width;
CGContextRestoreGState(context);
}
}
You could do it slightly differently:
fill the background of your view with the background color
Use the percentOfStar to create a rectangle path that reflects the rating.
Use the star path to clip.
My goal is to take a pattern like this
and draw it repeatedly along a circular path to produce something similar to this image:
I found several code examples in other questions and an full demo project here but the result is this:
I think the difference between the two images is obvious, but I find it hard to describe (pardon my lack of graphics vocabulary). The result seems to be tiling without the desired rotation/deformation of the pattern. I think I can live with the lack of deformation, but the rotation is key. I think that perhaps the draw callback could/should be modified to include a rotation, but can't figure out how to retrieve/determine the angle at the point of the callback.
I considered an approach where I manually deformed/rotated the image and drew it several times around a centerpoint to achieve the effect I want, but I believe that CoreGraphics could do it with more efficiency and with less code.
Any suggestions about how to achieve the result I want would be appreciated.
Here is the relevant code from the ChalkCircle project:
const float kPatternWidth = 8;
const float kPatternHeight = 8;
void DrawPatternCellCallback(void *info, CGContextRef cgContext)
{
UIImage *patternImage = [UIImage imageNamed:#"chalk_brush.png"];
CGContextDrawImage(cgContext, CGRectMake(0, 0, kPatternWidth, kPatternHeight), patternImage.CGImage);
}
- (void)drawRect:(CGRect)rect {
float startDeg = 0; // where to start drawing
float endDeg = 360; // where to stop drawing
int x = self.center.x;
int y = self.center.y;
int radius = (self.bounds.size.width > self.bounds.size.height ? self.bounds.size.height : self.bounds.size.width) / 2 * 0.8;
CGContextRef ctx = UIGraphicsGetCurrentContext();
const CGRect patternBounds = CGRectMake(0, 0, kPatternWidth, kPatternHeight);
const CGPatternCallbacks kPatternCallbacks = {0, DrawPatternCellCallback, NULL};
CGAffineTransform patternTransform = CGAffineTransformIdentity;
CGPatternRef strokePattern = CGPatternCreate(
NULL,
patternBounds,
patternTransform,
kPatternWidth, // horizontal spacing
kPatternHeight,// vertical spacing
kCGPatternTilingNoDistortion,
true,
&kPatternCallbacks);
CGFloat color1[] = {1.0, 1.0, 1.0, 1.0};
CGColorSpaceRef patternSpace = CGColorSpaceCreatePattern(NULL);
CGContextSetStrokeColorSpace(ctx, patternSpace);
CGContextSetStrokePattern(ctx, strokePattern, color1);
CGContextSetLineWidth(ctx, 4.0);
CGContextMoveToPoint(ctx, x, y - radius);
CGContextAddArc(ctx, x, y, radius, (startDeg-90)*M_PI/180.0, (endDeg-90)*M_PI/180.0, 0);
CGContextClosePath(ctx);
CGContextDrawPath(ctx, kCGPathStroke);
CGPatternRelease(strokePattern);
strokePattern = NULL;
CGColorSpaceRelease(patternSpace);
patternSpace = NULL;
}
.SOLUTION FROM SAM
I modified sam's solution to handle non-square patterns, center the result, and remove hard coded numbers by calculating them from the passed in image:
#define MAX_CIRCLE_DIAMETER 290.0f
#define OVERLAP 1.5f
-(void) drawInCircle:(UIImage *)patternImage
{
int numberOfImages = 12;
float diameter = (MAX_CIRCLE_DIAMETER * numberOfImages * patternImage.size.width) / ( (2.0 * M_PI * patternImage.size.height) + (numberOfImages * patternImage.size.width));
//get the radius, circumference and image size
CGRect replicatorFrame = CGRectMake((320-diameter)/2.0f, 60.0f, diameter, diameter);
float radius = diameter/2;
float circumference = M_PI * diameter;
float imageWidth = circumference/numberOfImages;
float imageHeight = imageWidth * patternImage.size.height / patternImage.size.width;
//create a replicator layer and add it to our view
CAReplicatorLayer *replicator = [CAReplicatorLayer layer];
replicator.frame = replicatorFrame;
[self.view.layer addSublayer:replicator];
//configure the replicator
replicator.instanceCount = numberOfImages;
//apply a rotation transform for each instance
CATransform3D transform = CATransform3DIdentity;
transform = CATransform3DRotate(transform, M_PI / (numberOfImages/2), 0, 0, 1);
replicator.instanceTransform = transform;
//create a sublayer and place it inside the replicator
CALayer *layer = [CALayer layer];
//the frame places the layer in the middle of the replicator layer and on the outside of
//the replicator layer so that the the size is accurate relative to the circumference
layer.frame = CGRectMake(radius - (imageWidth/2.0) - (OVERLAP/2.0), -imageHeight/2.0, imageWidth+OVERLAP, imageHeight);
layer.anchorPoint = CGPointMake(0.5, 1);
[replicator addSublayer:layer];
//apply a perspective transform to the layer
CATransform3D perspectiveTransform = CATransform3DIdentity;
perspectiveTransform.m34 = 1.0f / -radius;
perspectiveTransform = CATransform3DRotate(perspectiveTransform, (M_PI_4), -1, 0, 0);
layer.transform = perspectiveTransform;
//set the image as the layer's contents
layer.contents = (__bridge id)patternImage.CGImage;
}
Using Core Animation's replicator layer, I managed to create this result:
I think it's close to what your looking for. In this example all the images are square with a 3d X rotation applied to each of them.
#import <QuartzCore/QuartzCore.h>
//set the number of images and the diameter (width) of the circle
int numberOfImages = 30;
float diameter = 450.0f;
//get the radius, circumference and image size
float radius = diameter/2;
float circumference = M_PI * diameter;
float imageSize = circumference/numberOfImages;
//create a replicator layer and add it to our view
CAReplicatorLayer *replicator = [CAReplicatorLayer layer];
replicator.frame = CGRectMake(100.0f, 100.0f, diameter, diameter);
[self.view.layer addSublayer:replicator];
//configure the replicator
replicator.instanceCount = numberOfImages;
//apply a rotation transform for each instance
CATransform3D transform = CATransform3DIdentity;
transform = CATransform3DRotate(transform, M_PI / (numberOfImages/2), 0, 0, 1);
replicator.instanceTransform = transform;
//create a sublayer and place it inside the replicator
CALayer *layer = [CALayer layer];
//the frame places the layer in the middle of the replicator layer and on the outside of the replicator layer so that the the size is accurate relative to the circumference
layer.frame = CGRectMake(radius - (imageSize/2), -imageSize/2, imageSize, imageSize);
layer.anchorPoint = CGPointMake(0.5, 1);
[replicator addSublayer:layer];
//apply a perspective transofrm to the layer
CATransform3D perspectiveTransform = CATransform3DIdentity;
perspectiveTransform.m34 = 1.0f / -radius;
perspectiveTransform = CATransform3DRotate(perspectiveTransform, (M_PI_4), -1, 0, 0);
layer.transform = perspectiveTransform;
//set the image as the layer's contents
layer.contents = (__bridge id)[UIImage imageNamed:#"WCR3Q"].CGImage;
I am able to draw a square pixel by pixel as below
for(int i=0 ;i<drawbox.size.width/2;i++)
{
for (int j=0; j<drawbox.size.height/2; j++)
{
Point.y++;
NSLog(#"point:%f,%f",Point.x,Point.y);
}
Point.x++;
}
Here drawrect is CGRect and Point is the CGPoint I am using to draw pixel by pixel
I iterate over this and find a square to be made. This square is filled with each pixel so it just not draw a square with border but it includes all pixels within the square.
I want the same thing but for circle (filled circle's pixels).
How can I achieve this?
Override your drawRect with following code :
You need to take care of 5 things :
SIDE_WEITH = Width of Circle,
Color constants :
_r = Red
_g = Green
_b = Blue
_a = Alpha
And set Progress as per your need : _progress
That it.
- (void)drawRect:(CGRect)rect
{
[super drawRect:rect];
//// [image drawInRect:rect];
// find the radius and position for the largest circle that fits in the UIView's frame.
int radius, x, y;
int offset = SIDE_WEITH;
// in case the given frame is not square (oblong) we need to check and use the shortest side as our radius.
CGRect frame = self.frame;
if (frame.size.width > frame.size.height) {
radius = frame.size.height;
// we want our circle to be in the center of the frame.
int delta = frame.size.width - radius;
x = delta/2 - 1;
y = 0;
} else {
radius = frame.size.width;
int delta = frame.size.height - radius;
y = delta/2 - 1;
x = 0;
}
// store the largest circle's position and radius in class variable.
_outerCircleRect = CGRectMake(x, y, radius, radius);
// store the inner circles rect, this inner circle will have a radius 10pixels smaller than the outer circle.
// we want to the inner circle to be in the middle of the outer circle.
//_innerCircleRect = CGRectMake(x+offset, y+offset, radius-2*offset , radius-2*offset);
_innerCircleRect = CGRectMake(x+offset, y+offset, radius-2*offset , radius-2*offset);
// get the drawing canvas (CGContext):
CGContextRef context = UIGraphicsGetCurrentContext();
// save the context's previous state:
CGContextSaveGState(context);
// our custom drawing code will go here:
// Draw the gray background for our progress view:
// gradient properties:
CGGradientRef myGradient;
// You need tell Quartz your colour space (how you define colours), there are many colour spaces: RGBA, black&white...
CGColorSpaceRef myColorspace;
// the number of different colours
size_t num_locations = 3;
// the location of each colour change, these are between 0 and 1, zero is the first circle and 1 is the end circle, so 0.5 is in the middle.
CGFloat locations[3] = { 0.0, 0.5 ,1.0 };
// this is the colour components array, because we are using an RGBA system each colour has four components (four numbers associated with it).
CGFloat components[12] = {
0.4, 0.4, 0.4, 0.9, // Start colour
0.9, 0.9, 0.9, 1.0, // middle colour
0.4, 0.4, 0.4, 0.9
}; // End colour
myColorspace = CGColorSpaceCreateDeviceRGB();
myGradient = CGGradientCreateWithColorComponents (myColorspace, components,locations, num_locations);
// gradient start and end points
CGPoint myStartPoint, myEndPoint;
CGFloat myStartRadius, myEndRadius;
myStartPoint.x = _innerCircleRect.origin.x + _innerCircleRect.size.width/2;
myStartPoint.y = _innerCircleRect.origin.y + _innerCircleRect.size.width/2;
myEndPoint.x = _innerCircleRect.origin.x + _innerCircleRect.size.width/2;
myEndPoint.y = _innerCircleRect.origin.y + _innerCircleRect.size.width/2;
myStartRadius = _innerCircleRect.size.width/2 ;
myEndRadius = _outerCircleRect.size.width/2;
// draw the gradient.
/*CGContextDrawRadialGradient(context,
myGradient,
myStartPoint, myStartRadius, myEndPoint, myEndRadius, 0);
CGGradientRelease(myGradient);*/
// draw outline so that the edges are smooth:
// set line width
//CGContextSetLineWidth(context, 1);
// set the colour when drawing lines R,G,B,A. (we will set it to the same colour we used as the start and end point of our gradient )
/*CGContextSetRGBStrokeColor(context, 0.4,0.4,0.4,0.9);
// draw an ellipse in the provided rectangle
CGContextAddEllipseInRect(context, _outerCircleRect);
CGContextStrokePath(context);*/
/*CGContextAddEllipseInRect(context, _innerCircleRect);
CGContextStrokePath(context);*/
// Draw the progress:
// First clip the drawing area:
// save the context before clipping
CGContextSaveGState(context);
CGContextMoveToPoint(context,
_outerCircleRect.origin.x + _outerCircleRect.size.width/2, // move to the top center of the outer circle
_outerCircleRect.origin.y +1); // the Y is one more because we want to draw inside the bigger circles.
// add an arc relative to _progress
CGContextAddArc(context,
_outerCircleRect.origin.x + _outerCircleRect.size.width/2,
_outerCircleRect.origin.y + _outerCircleRect.size.width/2,
_outerCircleRect.size.width/2-1,
-M_PI/2,
(-M_PI/2 + _progress*2*M_PI), 0);
CGContextAddArc(context,
_outerCircleRect.origin.x + _outerCircleRect.size.width/2,
_outerCircleRect.origin.y + _outerCircleRect.size.width/2,
_outerCircleRect.size.width/2 - 9,
(-M_PI/2 + _progress*2*M_PI),
-M_PI/2, 1);
// use clode path to connect the last point in the path with the first point (to create a closed path)
CGContextClosePath(context);
// clip to the path stored in context
CGContextClip(context);
// Progress drawing code comes here:
// set the gradient colours based on class variables.
CGFloat components2[12] = { _r, _g, _b, _a, // Start color
((_r + 0.5 > 1) ? 1 : (_r+0.5) ) , ((_g + 0.5 > 1) ? 1 : (_g+0.5) ), ((_b + 0.5 > 1) ? 1 : (_b+0.5) ), ((_a + 0.5 > 1) ? 1 : (_a+0.5)),
_r, _g, _b, _a }; // End color
myGradient = CGGradientCreateWithColorComponents (myColorspace, components2,locations, num_locations);
myStartPoint.x = _innerCircleRect.origin.x + _innerCircleRect.size.width/2;
myStartPoint.y = _innerCircleRect.origin.y + _innerCircleRect.size.width/2;
myEndPoint.x = _innerCircleRect.origin.x + _innerCircleRect.size.width/2;
myEndPoint.y = _innerCircleRect.origin.y + _innerCircleRect.size.width/2;
// set the radias for start and endpoints a bit smaller, because we want to draw inside the outer circles.
myStartRadius = _innerCircleRect.size.width/2;
myEndRadius = _outerCircleRect.size.width/2;
CGContextDrawRadialGradient(context,
myGradient,
myStartPoint, myStartRadius, myEndPoint, myEndRadius, 0);
// release myGradient and myColorSpace
CGGradientRelease(myGradient);
CGColorSpaceRelease(myColorspace);
// draw circle on the outline to smooth it out.
CGContextSetRGBStrokeColor(context, _r,_g,_b,_a);
// draw an ellipse in the provided rectangle
CGContextAddEllipseInRect(context, _outerCircleRect);
CGContextStrokePath(context);
CGContextAddEllipseInRect(context, _innerCircleRect);
CGContextStrokePath(context);
//restore the context and remove the clipping area.
CGContextRestoreGState(context);
// restore the context's state when we are done with it:
CGContextRestoreGState(context);
/*CGPathRef circlePath = CGPathCreateMutable();
CGPathAddEllipseInRect(circlePath , NULL , rect);
CAShapeLayer *circle = [[CAShapeLayer alloc] init];
circle.path = circlePath;
circle.opacity = 0.5;
[self.imageView.layer addSublayer:circle];
CGPathRelease( circlePath );
[circle release];*/
}
for (int i=0; i<drawbox.size.width/2; i++) {
for (int j=(int)(-drawbox.size.height/4.0 * sqrt(1 - pow(4.0*i/drawbox.size.width - 1, 2)) + drawbox.size.height/4.0);
j<=(int)(drawbox.size.height/4.0 * sqrt(1 - pow(4.0*i/drawbox.size.width - 1, 2)) + drawbox.size.height/4.0);
j++)
{
Point.y++;
NSLog(#"point:%f,%f",Point.x,Point.y);
}
tStartPoint.x++;
}
This will draw an ellipse with the same center the rectangle has you drow in the question.