Drawing Polygons
poly() draws any shape you can list points for — triangles, pentagons, stars, and the curved,
angled eyebrows that make a robot face expressive. It is the one drawing command that can point in
a direction, which is exactly why the eyebrow lab reaches for it.
1 | |
point_array is a MicroPython array('h', [x0, y0, x1, y1, ...]) of signed shorts. The 'h'
matters: the OLED kit used array('B') — unsigned bytes, maximum 255 — which still fits this
screen, but signed shorts let the offsets go negative, and negative offsets are what let you
write a shape around its own center instead of from a corner.
How the Fill Works
This driver has no poly() of its own, so shapes.poly() fills polygons itself using a
scanline fill: for each row, find where the shape's edges cross it, sort the crossings, and
fill between them in pairs.
Open lib/shapes.py and read it. It is the same algorithm every 2-D graphics library on earth
uses, and it fits on one screen.
One Array, Four Positions
Every shape below is written once, as offsets from a center point, and then placed by moving that center. Change the anchor and the shape moves; change the array and the shape changes. Keeping those two ideas separate is most of what makes drawing code readable.
Sample Program Code
Four shapes, each drawn filled on one side and outlined on the other so you can compare them.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | |
Here's what that program draws on the display:

Notice the middle row is three shapes wide and the outer rows are two. That is the circle deciding your layout for you — the screen is widest across its middle, so that is where the most shapes fit.
Filled or Outlined Costs Different Amounts
This is worth knowing before you start drawing brows. A filled polygon sends one hline() per row
it covers. An outline sends one line() per edge. Which one is cheaper depends entirely on the
shape:
| Shape | Filled cost | Outline cost |
|---|---|---|
| A short, wide eyebrow (12 rows, 6 edges) | 12 runs | 6 angled walks |
| A tall star (48 rows, 10 edges) | 48 runs | 10 angled walks |
| A big filled pentagon | grows with area | grows with perimeter |
An Outlined Brow Reads as a Scratch
Try drawing an eyebrow with NO_FILL and you get a thin wire frame that looks like a scuff on the glass. Filled polygons are what make brows read as brows on a screen this size.
Things to Try
- Add a point to
STARand see what happens. Scanline fill does not care how many points you give it, or whether the shape is convex — but it does assume the outline does not cross itself. - Make it cross itself on purpose and look at the result. The pattern you get is not a bug in your code; it is what "inside" means when a shape overlaps itself.
- Time the filled star against the outlined one with
ticks_us(). Predict which is faster first, then find out whether the shape or your intuition was in charge. - Turn a triangle into an eyebrow. Squash
TRIANGLEflat — change the ±22 and ±16 to ±4 and ±20 — and put it above an eye. You have just built the eyebrow lab.
References
- Eyebrows — where
poly()becomes the most expressive tool on the face - Drawing Lines — the straight-line version of the same idea, and its limits
- MicroPython array Documentation — what
array('h', ...)actually builds