Debugging Graphics

planegcs includes an optional graphics feature that renders your sketch geometry to a Pillow (PIL) image. This is intended for quick visual debugging — not production-quality rendering.

Installation

Install the graphics extra:

pip install planegcs[graphics]

or:

uv add planegcs[graphics]

Basic Usage

from planegcs import Sketch, SolveStatus

s = Sketch()
p1 = s.add_fixed_point(0, 0)
p2 = s.add_point(5, 0)
p3 = s.add_point(2.5, 4)
l1 = s.add_line(p1, p2)
l2 = s.add_line(p2, p3)
s.add_line(p3, p1)
s.equal_length(l1, l2)

s.solve()

# Get a PIL Image object and show it in a GUI window
s.to_image().show()

The to_image() method automatically:

  • Calculates a bounding box around all geometry

  • Picks a sensible scale so the image is ~800 px on the longest axis

  • Adds padding around the edges

  • Flips the Y axis (sketch coordinates are math-style, images are screen-style)

Customising the Output

All parameters are optional keyword arguments:

img = s.to_image(
    width=1200,             # image width in pixels
    height=800,             # image height in pixels
    scale=50.0,             # pixels per sketch unit (overrides width/height)
    padding=20,             # border padding in pixels
    background="#1e1e2e",   # dark background
    line_color="#89b4fa",   # blue lines
    circle_color="#f38ba8", # pink circles
    arc_color="#fab387",    # orange arcs
    ellipse_color="#a6e3a1",# green ellipses
    point_color="#cdd6f4",  # light gray points
    line_width=3,           # stroke width
    point_radius=5,         # point dot size
)

Size and scale logic:

  • If scale is given, the image size is computed from the bounding box.

  • If width and height are given, geometry is fit inside.

  • If only width or only height is given, the other dimension is computed from the aspect ratio.

  • If nothing is given, the longest axis maps to ~800 px.

Supported Geometry

The following entity types are drawn:

  • Points — small filled dots

  • Lines — straight line segments

  • Circles — full circles

  • Arcs — partial circles (both CCW and CW arcs)

  • Ellipses — rendered as polylines, supporting arbitrary rotation

You can also call the function directly:

from planegcs.graphics import sketch_to_image

img = sketch_to_image(my_sketch, width=600)

Using with IPython (terminal)

When using IPython in a terminal that supports the kitty graphics protocol (e.g. kitty, WezTerm, Ghostty), you can display sketch images inline with ipython-icat.

Setup:

pip install ipython ipython-icat planegcs[graphics]

Load the extension and install to use for PIL graphics from within IPython:

%load_ext icat
%icat

Or add it to your IPython config:

python -m icat setup

Example session:

In [1]: from planegcs import Sketch, SolveStatus

In [2]: s = Sketch()

In [3]: p1 = s.add_fixed_point(0, 0)
   ...: p2 = s.add_point(5, 0)
   ...: p3 = s.add_point(2.5, 4)

In [4]: s.add_line(p1, p2)
   ...: s.add_line(p2, p3)
   ...: s.add_line(p3, p1)
Out[4]: 4

In [5]: s.equal_length(2, 3)
   ...: s.equal_length(3, 4)
   ...: s.horizontal(2)
   ...: s.set_p2p_distance(p1, p2, 5.0)
Out[5]: 4

In [6]: s.solve()
Out[6]: <SolveStatus.Success: 0>

In [7]: s.to_image()
Out[7]:  # <-- image displayed inline in your terminal!

The last line returns a PIL Image, which ipython-icat automatically renders in the terminal using the kitty graphics protocol.

Using with Jupyter Notebook

PIL images are displayed automatically in Jupyter notebooks. Just return the image as the last expression in a cell:

# In a Jupyter cell:
s.to_image()
# The image is displayed directly in the notebook output.

You can also use display() explicitly:

from IPython.display import display
display(s.to_image())

API Reference

planegcs.graphics.sketch_to_image(sketch: Sketch, *, width: int | None = None, height: int | None = None, scale: float | None = None, padding: int = 40, background: str = 'white', line_color: str = 'black', circle_color: str = 'blue', arc_color: str = 'red', ellipse_color: str = 'green', line_width: int = 2, point_radius: int = 3, point_color: str = 'gray') ImageModule.Image

Render sketch geometry into a PIL Image.

Parameters:
  • sketch – The sketch whose geometry will be drawn.

  • width – Desired image dimensions in pixels. If only one is given the other is computed from the bounding-box aspect ratio. Ignored when scale is provided.

  • height – Desired image dimensions in pixels. If only one is given the other is computed from the bounding-box aspect ratio. Ignored when scale is provided.

  • scale – Pixels per sketch unit. Overrides width / height.

  • padding – Blank border (in pixels) around the geometry on all sides.

  • background – Background colour (any PIL colour string).

  • line_color – Stroke / fill colours for each entity type.

  • circle_color – Stroke / fill colours for each entity type.

  • arc_color – Stroke / fill colours for each entity type.

  • ellipse_color – Stroke / fill colours for each entity type.

  • point_color – Stroke / fill colours for each entity type.

  • line_width – Stroke width in pixels for lines, circles, arcs, and ellipses.

  • point_radius – Radius of the filled dot drawn for each point entity.

Returns:

The rendered image.

Return type:

PIL.Image.Image

Raises:

ImportError – If Pillow is not installed.

Sketch.to_image(*, width: int | None = None, height: int | None = None, scale: float | None = None, padding: int = 40, background: str = 'white', line_color: str = 'black', circle_color: str = 'blue', arc_color: str = 'red', ellipse_color: str = 'green', line_width: int = 2, point_radius: int = 3, point_color: str = 'gray') object

Render the sketch geometry to a Pillow image.

This is a convenience wrapper around planegcs.graphics.sketch_to_image().

Requires the graphics extra:

pip install planegcs[graphics]

All keyword arguments are forwarded to sketch_to_image().

Returns:

A PIL.Image.Image showing the current sketch geometry.