In this activity we will build the following compass graphic:
The compass is a complicated graphic, we cannot approach it as a single problem: we have to decompose it in simpler graphics.
We will decompose the compass in three big components: the needle, the housing and the dial. Each of these components can and should be further decomposed!
Let's start by building the compass' needle, which should look something like this:
Since the bottom part is just a repetition of the top part, of a different color, we should adopt refactoring and extract the part that repeats in a simpler function to be reused: for example a function that generates half of a needle.
half_needle FunctionThe half_needle function should return an isosceles triangle of the wanted height and color,
rotated vertically like the following one:
The top angle of the triangle should measure 13 degrees.
If you want, you can import and use the isosceles_triangle function from the
Triangles
activity using your toolbox.
needle FunctionA needle is composed by a red half-needle and a white one, on top of two slightly smaller black half-needles, with a small black circle overlayed on top.
The thickness of the black outline should measure height / 30,
and the diameter of the black circle should measure height / 20.
If you want, you can import and use the circle function from the
Circles
activity using your toolbox, you will find it useful further it in this activity!
The housing of a compass is the container that holds the internal components of the compass, such as the magnetic needle.
In our case this is what the housing will look like:
The housing itself is a fairly complex graphic: we should decompose it into smaller problems!
We are going to decompose the housing in three parts: the compass rose, the background (which contains the compass rose), and the needle (which we have already implemented).
compass_rose FunctionWe are going to build an approximation of a compass rose, like the following one:
As you can see it is not a perfect compass rose, but in this activity it's not needed since the needle is going to be overlayed on top of the center!
The thickness of the black outline should measure diameter / 80,
where diameter is the total diameter of the rose.
You can and should use the half_needle function you implemented before!
housing_background FunctionThe background of the housing should look something like this:
Here you will find the circle function very useful!
The thickness of the line should measure diameter / 200,
and the diameter of the internal ring should measure diameter / 2.
The thickness of the white part of the ring, should measure line_thickness * 3.
Use the compass_rose function you just implemented, to generate the compass rose contained in the ring!
housing FunctionThe housing should combine the housing_background function and the needle_function.
The housing function takes the total diameter of the housing,
and the angle at which the needle should be rotated, clock-wise.
The height of the needle should measure diameter * 0.9.
Let's now build the final component of the compass: the dial.
As you can see the dial graphic is very complex!
We are going to decompose it into three simpler graphics: the segments, the numbers and the cardinal points. Then, the three sould be all overlayed on top of a black circular background.
dial_segments FunctionLet's start with the segments of the dial. There should be 360 white segments, with a slighty longer segment for angles representing multiples of five.
The width of the longer segment should measure diameter / 20, and it's thickness should meassure 1 / 20 times its width.
The shorter segment should have a width of 1 / 3 of the longer segment's, and the same thickness.
You can use transparent rectangles to move the segments to form the outer part of a circle.
Use pin and compose.
dial_numbers FunctionNext, let's implement the dial_numbers function that should return the following graphic:
Use the pytamaro text function to generate the numbers.
It takes a string as parameter content, therefore you will have to convert integer numbers to a string. For the font, use "Roboto Condensed".
To convert integers to strings you can use the python function str(integer_value), in the following way:
x = 7 # x has type `int`
y = str(7) # y has type `str`, and value "7"The numbers should have font "Ubuntu Condensed", and points (size) of diameter / 15.
The numbers 80, 100, 260, and 280 should have a smaller size of 0.6 times the bigger number's size.
The spots for numbers 0 and 180 should be left empty!
Use transparent rectangles again, to move the text on the outer part of a circle.
cardinal_points FunctionThe cardinal_points function should generate the following graphic:
The font of the text is "Roboto Condensed", and the size of E, W, and S should measure diameter / 15.
The size of the N should be 1.4 times more.
Use transparent rectangles again, to move the text on the outer part of a circle.
Notice that the letters are not rotated, whereas the numbers were!
dial FunctionLet's generate a dial by composing the segments together with the numbers and the cardinal points, on top of a black circular background.
The cardinal points' and the numbers' diameter should measure 0.9 of the total diameter.
Use the following functions you implemented before: dial_segments, dial_numbers, and cardinal_points.
Finally, it's time to compose the final compass!
The compass function should generate a compass with the given diameter,
with the needle oriented according to the given needle_angle.
The housing should measure 3 / 4 of the compass.
Use the housing function you implemented, with the dial function.
This activity has been created by LuCE Research Lab and is licensed under CC BY-SA 4.0.
Compass

PyTamaro is a project created by the Lugano Computing Education Research Lab at the Software Institute of USI
Privacy Policy • Platform Version 51af85f (Tue, 18 Nov 2025 10:59:34 GMT)