Tomas
New Member
Posts: 2
|
Post by Tomas on May 5, 2014 3:43:03 GMT -8
Is there some easy way to draw an arc, for example 270°, similar to gauge or as on following pictures? Circles are not a problem, but how to draw "multicolor strips on circle". One solution will be to use underlying bitmap and draw the needle over, but I want to show moving arc w/o needle.
|
|
|
Post by jamesbowman on May 5, 2014 13:18:57 GMT -8
So the easiest thing to do is just to use a bitmap - and of course the GPU is particularly good at drawing bitmaps. But here's my attempt to draw an arc using the graphics hardware. All page number references are to the Gameduino 2 book. It draws two circles - shown here in red and green - and these together make the ring. Then it draws a wedge (yellow) to 'cut out' the unwanted part of the arc. The real version draws into the alpha buffer (p. 159) so the drawn arc appears as: The wedge is drawn using a polygon (p. 150) with polar coordinates (p.136), oversized so that the wedges always cover up the circle. The starting and ending angles are in Furmans (p. 56). #define PAINT_ALPHA() GD.BlendFunc(ONE, ONE_MINUS_SRC_ALPHA) #define CLEAR_ALPHA() GD.BlendFunc(ZERO, ONE_MINUS_SRC_ALPHA)
// Draw an arc centered at (x,y) with inner radius r0, outer radius r1. // th0 and th1 are the starting and ending angles in Furmans. // x,y,r0 and r1 are subpixel coordinates (1/16ths of a pixel). // The arc itself is drawn into the destination alpha buffer for use in // later compositing operations.
static void arc(int x, int y, uint16_t th0, uint16_t th1, uint16_t r0, uint16_t r1) { GD.SaveContext();
GD.Begin(POINTS); PAINT_ALPHA(); GD.PointSize(r1); GD.Vertex2f(x, y);
CLEAR_ALPHA(); GD.PointSize(r0); GD.Vertex2f(x, y);
Poly po; po.begin(); po.v(x, y); int ra = r1 + (r1 >> 1); for (uint8_t d = 0; d <= 4; d++) { int rx, ry; GD.polar(rx, ry, ra, th1 + (((uint32_t)(uint16_t)(th0 - th1) * d) >> 2)); po.v(x + rx, y + ry); } po.draw(); GD.RestoreContext(); }
And here is the example code that draws this image: void loop() { GD.Clear(); arc(16 * 240, 16 * 137, 0x3000, 0xd000, 16 * 30, 16 * 60);
GD.BlendFunc(DST_ALPHA, ZERO); GD.Begin(RECTS); GD.Vertex2ii(0, 0); GD.Vertex2ii(480, 272);
GD.swap(); }
|
|
Tomas
New Member
Posts: 2
|
Post by Tomas on May 6, 2014 7:08:25 GMT -8
Really nice, thanks a lot James! I was already think about scissors to restrict drawing area or to “repaint” full-circle partially with black-box, but I totally forgot to use polygon. With this solution will be also start and end of the arc “smooth”. -Tomas
|
|
|
Post by jamesbowman on May 6, 2014 8:04:56 GMT -8
You are welcome. Yes, if you look closely at the arc you can see that the 'start' end 'end' edges are not smoothed - because they are actually polygon edges. After drawing the arc you might draw lines at the edges to smooth these out. Similarly for any subdivision lines within the arc. Draw the lines with CLEAR_ALPHA() to erase them from the arc. Of course, after all this work you do have a nice anti-aliased graphic. But another way with a similar amount of work is to create the graphic using code in a drawing system on the PC, and transfer a bitmap. My favorite for this is PyCairo, cairographics.org/pycairo/.
|
|