Skip to content

Using Lua scripts (Part 04): Drawing rectangles, circles and arcs

lasers edited this page Dec 26, 2018 · 5 revisions

Using Lua scripts (Part 4)


Drawing rectangles, circles and arcs

there are a few things that cairo can draw other than lines namely: 1. rectangles 2. arcs (and circles) 3. curves

rectangles

we could use lines as in the triangle to draw ourselves a rectangle, but cairo has the ability to draw rectangles built in so might as well use it cairo_rectangle (cr, x, y, width, height) the x,y coordinates are the top left corner of the rectangle

just like our triangle we can set up our shape like so

--settings
line_width=5
top_left_x=20
top_left_y=20
rec_width=100
rec_height=50
red=1
green=0
blue=0
alpha=1
--draw it
cairo_set_line_width (cr,line_width)
cairo_rectangle (cr,top_left_x,top_left_y,rec_width,rec_height)
cairo_set_source_rgba (cr,red,green,blue,alpha)

then use stroke to draw the outline cairo_stroke(cr) or cairo_fill(cr) to fill it in

or if you want the rectangle filled with one color and line in a different colors we would first fill with cairo_fill_preserve, then set our second color and draw our line with cairo_stroke

--settings
line_width=5
top_left_x=20
top_left_y=20
rec_width=100
rec_height=50
fill_red=1
fill_green=1
fill_blue=1
fill_alpha=1
line_red=1
line_green=0
line_blue=0
line_alpha=1
--draw it
cairo_set_line_width (cr,line_width)
cairo_rectangle (cr,top_left_x,top_left_y,rec_width,rec_height)
cairo_set_source_rgba (cr,fill_red,fill_green,fill_blue,fill_alpha)
cairo_fill_preserve (cr)
cairo_set_source_rgba (cr,line_red,line_green,line_blue,line_alpha)
cairo_stroke (cr)

NOTE with rectangles there is no point in setting line_cap like we did for lines as there are no "loose ends" to the rectangle there is also no need to use cairo_close_path, as it is closed automatically however setting how the lines join will affect the look of the rectangle when we use cairo_stroke

cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND)
cairo_stroke (cr)

will give rounded corners for example

line width, line join type and end cap type do not affect the fill command

arc and circles

there are 2 commands for arcs cairo_arc (cr,center_x,center_y,radius,start_angle,end_angle) and cairo_arc_negative (cr,center_x,center_y,radius,start_angle,end_angle)

cairo_arc draws the arc clockwise while cairo_arc_negative draws the arc anticlockwise

the first obstacle to drawing arcs is that you need to enter your start and end angles in radians rather than degrees. so we need to know how to convert between the two radians=degrees*(pi/180)

lua has a number of built in math functions and one of them, math.pi, gives you the value of pi

the other quirk about using the arc drawing command is that angle 0 isn't the top of the circle as you would expect

rather angle 0 is the rightmost point in the circle (which i would call 90 degrees)

these things don't matter if we only want to draw a complete circle, we just need the following

center_x=100
center_y=100
radius=50
start_angle=0
end_angle=2*math.pi--same thing as 360 degrees
cairo_arc (cr,center_x,center_y,radius,start_angle,end_angle)
cairo_stroke (cr)

NOTE whenever you use stroke to draw something you need to set a line_width. also with stroke, if you are going to see line ends then altering the line cap type will affect those ends. the other setting that can affect stroke is the line join type if creating a path from multiple elements arcs along with curves and lines can be all put together to form a single path in the example above you will also need to set color and alpha as before.

Change cairo_stroke to cairo_fill to fill the circle in or use the previously described method for fill and line. I wont necessarily put these setup lines, or all the available options, into code examples from now on.

BUT if we don't want a full circle then we need to worry about radians and setting angles to get an 1/4 circle, from the topmost point of the circle,clockwise to the rightmost point, we can do several things...

my code would look like this

center_x=100
center_y=100
radius=50
start_angle=0
end_angle=90
cairo_arc (cr,center_x,center_y,radius,(start_angle-90)*(math.pi/180),(end_angle-90)*(math.pi/180))
cairo_stroke (cr)

since i only want to enter angles as degrees i can put the conversion calculations into the arc command eg (start_angle-90)*(math.pi/180)

first i want the top of my circle to be 0 degrees (or 360 if you like) so i have to compensate for the arc command quirk by subtracting 90 degrees from the value i set then i need to convert to radians by multiplying by (math.pi/180)

cairo_stroke to get the line

this in the code:

cairo_close_path (cr)
cairo_stroke (cr)

will result in a straight line drawn from the end of the arc back to the beginning and cairo_fill(cr) instead of cairo_stroke would result in a filled in bump with a flat bottom

here is cairo_stroke without close_path, cairo_stroke with close path and cairo_fill

using arc or arc_negative so if you give cairo_arc a start angle of 270 and an end angle of 90 you get the top half of a circle you could also set start=270, end=450 (360+90) and get the same things or start=-90, end=90 and get the same thing

if you give cairo_arc_negative a start angle of 270 and an end angle of 90 you get the bottom half of a circle

this can be important for drawing paths, as you want your path to be a continuous progression (imagine drawing a line on some paper but not allowed to lift the pen). Also remember that using the close_path or fill commands (which close the path automatically) you draw a line from where you ended to where you started. You can get unexpected fill and stroke results if you piece together your path in a non continuous manner.

The other time you may want to use are or arc negative is to make a ring meter go one way or another while you could achieve the effect just using, for example, arc (which naturally draws in a clockwise direction) for both, you have to think a bit harder about the math to get the ring going in the opposite direction

curves

i'll leave curves for another time they can be quite tricky to set up and use

Clone this wiki locally