CGContextStrokeRectWithWidth with inner rounding? - quartz-2d

I'm drawing a rounded rectangle on iOS.
This rectangle has an image background which I am clipping with a bezier path and I am then drawing a stroke with a width of two pixels inside it.
My issue is that the stroke has sharp edges on the inside instead of seemingly following the rounded rect path.
Here's a screenshot where I have increased the white colour to show the issue I'm dealing with.
Here's my code:
CGContextRef context = UIGraphicsGetCurrentContext();
CGPathRef strokeRect = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:2].CGPath;
CGContextAddPath(context, strokeRect);
CGContextClip(context);
// draw background
[[UIImage imageNamed:#"background.png"] drawInRect:rect];
// draw stroke
CGContextSetRGBStrokeColor(context, 1.0, 1.0, 1.0, 0.1);
CGContextStrokeRectWithWidth(context, rect, 2);

I think what you're going to have to do is clip the context on the inside with the corner radius and fill the context with 10% white.

Related

cairomm draw single pixel

I've a simple boolean matrix I want to see it as an Image. I am using Cairomm. In documentations I see how to draw a line, curve, arc. But I just want to put black and white color to each pixels. Not getting any docs on pixel access. This is what I copied from examples. though I want a monochrome image. Not FORMAT_ARGB32
Cairo::RefPtr<Cairo::ImageSurface> surface = Cairo::ImageSurface::create(Cairo::FORMAT_ARGB32, matrix.cols(), matrix.rows());
Cairo::RefPtr<Cairo::Context> context = Cairo::Context::create(surface);
right now I am drawing an 1 pixel line
context->set_antialias(Cairo::ANTIALIAS_NONE);
context->save(); // save the state of the context
context->set_source_rgb(1.0, 1.0, 1.0);
context->paint(); // fill image with the color
context->restore(); // color is back to black now
context->set_source_rgb(0.0, 0.0, 0.0);
context->set_line_width(1.0);
context->move_to(1.0, 1.0);
context->line_to(2.0, 2.0);
context->stroke();
Is this okay or there is something like context->draw(row, col, color) ?
An ImageSurface has a get_data() method. Together with flush() (before modifying data directly) and mark_dirty() (afterwards), you can use this to modify the pixel data directly and set individual pixels.
http://cairographics.org/documentation/cairomm/reference/classCairo_1_1ImageSurface.html#a94ba52fe4a201579c8a5541717822bdb

Draw smooth Bezier curve with cocos2d-x

It may be a duplicate with this question,
but I don't know how to apply this approach in my app, and which method I should use in cocos2d-x to draw a Bezier curve. My app should allow users to draw lines and curves when they touch the canvas. How can I achieve that?
From Cocos2dx v3.3 you can use DrawNode to draw Bezier curves. Check the DrawPrimitivesTest.cpp, it is very easy to use.
This is only a sample script taken from the above mentioned file. You can use it anywhere in your Scene:
auto draw = DrawNode::create();
addChild(draw, 10);
auto s = Director::getInstance()->getWinSize();
draw->drawQuadBezier(Vec2(0, s.height), Vec2(s.width/2, s.height/2), Vec2(s.width, s.height), 50, Color4F(CCRANDOM_0_1(), CCRANDOM_0_1(), CCRANDOM_0_1(), 0.5));
draw->drawCubicBezier(VisibleRect::center(), Vec2(VisibleRect::center().x+30,VisibleRect::center().y+50), Vec2(VisibleRect::center().x+60,VisibleRect::center().y-50),VisibleRect::right(),100, Color4F(CCRANDOM_0_1(), CCRANDOM_0_1(), CCRANDOM_0_1(), 0.5));
in CCDrawPrimitives.cpp file.
You can use this method.
ccDrawCubicBezier
ccDrawQuadBezier
-MyClass::draw() {
glLineWidth(4.0f);
ccPointSize(4);
//Draw a blue quadratic bezier curve
ccDrawColor4B(0, 0, 255, 255);
ccDrawQuadBezier(ccp(90,0), ccp(200, 70), ccp(350,0), 12);
//Draw cubic red bezier curve
ccDrawColor4B(255, 0, 0, 255);
ccDrawCubicBezier(ccp(100,100), ccp(300,150), ccp(250,50), ccp(350,100), 12);
//Restore original values
glLineWidth(1);
ccDrawColor4B(255,255,255,255);
ccPointSize(1);
}
Every time you move your touch positions, ccTouchesMoved method is called as you may know.
You can control the curve shape using the method and member variables.

DirectX stretched pixels

I am just starting off with directX and have run into a problem with stretched pixels. When I create the window and all the directX goodies I use two variables, width and height. For most testing I have them set to 800x600. When I draw a square on the screen it looks stretched.
However when I set the resoltion to 600x600
it looks normal and square. This led me to conclude that it was some sort of pixel stretching. In directX how do I fix this, and make the pixels square.
float aspectRatio = bufferWidth / bufferHeight;
That is completely normal. Once you project into normalized screen space, coordinates go from -1.0 to 1.0 (left to right) and -1.0 to 1.0 (bottom to top). You can see that both directions on the screen have the same range of values. This means that if you draw a square on the screen with equal height and width, it will be aspectRatio times greater in width than height. This explains the good behaviour at 600x600 but a problem at 800x600.(aspectRatio of 1.33)
If you really want a square, what you can do is simply divide the width by your aspect ratio which in your case is 800/600 (1.33) to get a polygon of equal width and height.
You may want to set your viewport according to your window size.
For example:
// Setup the viewport for rendering.
viewport.Width = (float)screenWidth;
viewport.Height = (float)screenHeight;
viewport.MinDepth = 0.0f;
viewport.MaxDepth = 1.0f;
viewport.TopLeftX = 0.0f;
viewport.TopLeftY = 0.0f;
// Create the viewport.
m_deviceContext->RSSetViewports(1, &viewport);
You can check on Rastertek Tutorials for more details.

Draw percentage of circle outline

In OpenGL, how can I draw a given percentage of the outline of a circle? And how can I control the thickness of that outline?
Example: If the percentage is 100, then the outline of a full circle should be drawn. If the percentage is 50, the outline of half a circle should be drawn.
I've tried the following, but the problem there is that it completes the lineloop, leading to a line connecting the startpoint and endpoint of the circle outline. Additionally, it does not seam to let me change the thickness of the outline.
glBegin(GL_LINE_LOOP);
for (int i=0; i < (360/10*percent/10); i++) {
float degInRad = i*DEG2RAD;
glVertex2f(a+cos(degInRad)*r,b+sin(degInRad)*r);
}
glEnd();
I am tempted to just make my circle up of GL_POINTS, but I was wondering if there is a better way?
Replace GL_LINE_LOOP with GL_LINE_STRIP, this way the last and first vertices aren't connected. Use the glLineWidth() function to define your line thickness.

Is gluLookAt together with glFrustum distorting the rendering?

I am wondering if gluLookAt together with glFrustum is distorting the rendered picture.
This is how a scene is rendered:
And here's the code that rendered it.
InitCamera is called once and should, as I understand it now, set up a matrix so as if I looked from a position 2 units above and 3 units in front of the origin towards the origin. Also glFrustum is used in order to create a perspective`.
void InitCamera() {
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt (
0, 2 , 3,
0, 0 , 0,
0, 1 , - 0
);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum (- 1, 1,
- 1, 1,
1,1000.0);
glMatrixMode(GL_MODELVIEW);
}
Then TheScene is what actually draws the picture:
void TheScene() {
glClear(
GL_COLOR_BUFFER_BIT |
GL_DEPTH_BUFFER_BIT
);
glMatrixMode(GL_MODELVIEW);
// Draw red circle around origin and radius 2 units:
glColor3d(1,0,0);
glBegin(GL_LINE_LOOP);
for (double i = 0; i<=2 * M_PI; i+=M_PI / 20.0) {
glVertex3d(std::sin(i) * 2.0, 0, std::cos(i) * 2.0);
}
glEnd();
// draw green sphere at origin:
glColor3d(0,1,0);
glutSolidSphere(0.2,128, 128);
// draw pink sphere a bit away
glPushMatrix();
glColor3d(1,0,1);
glTranslated(8, 3, -10);
glutSolidSphere(0.8, 128, 128);
glPopMatrix();
SwapBuffers(hDC_opengl);
}
The red ball should be drawn in the origin and at the center of the red circle around it. But looking at it just feels wierd, and gives me the imprssion that the green ball is not in the center at all.
Also, the pink ball should, imho, be drawn as a perfect circle, not as an ellipse.
So, am I wrong, and the picture is drawn correctly, or am I setting up something wrong?
Your expectations are simply wrong
The perspective projection of a 3d circle (if the circle is fully visible) is an ellipse, however the projection of the center of the circle is NOT in general the center of the ellipse.
The outline of the perspective projection of a sphere is in general a conic section i.e. can be a circle, an ellipse, a parabola or an hyperbola depending on the position of viewpoint, projection plane and sphere in 3D. The reason is that the outline of the sphere can be imagined as a cone starting from the viewpoint and touching the sphere being intersected with the projection plane.
Of course if you're looking at a circle with a perfectly perpendicular camera the center of the circle will be projected to the center of the circle projection. In the same manner if your camera is pointing exactly to a sphere the sphere outline will be a circle, but those are special cases, not the general case.
These differences between the centers are more evident with strong perspective (wide angle) cameras. With a parallel projection instead this apparent distortion is absent (i.e. the projection of the center of a circle is exactly the center of the projection of the circle).
To see the green sphere in the centre of the screen with a perfect circle around it you need to change the camera location like so:
gluLookAt (
0, 3, 0,
0, 0, 0,
0, 0, 1
);
Not sure what's causing the distortion of the purple sphere though.
The perspective is correct, it just looks distorted because that's how things fell together here.
try this for gluLookAt, and play around a bit more.:
gluLookAt (
0, 2 , 10,
0, 0 , 0,
0, 1 , 0
);
The way I tried it out was with a setup that allows me to adjust the position and view direction with the mouse, so you get real time motion. Your scene looks fine when I move around. If you want I can get you the complete code so you can do that too, but it's a bit more than I want to shove into an answer here.