Skip to content

recipe: pyclipper 1.4.0#107

Merged
ndonkoHenri merged 4 commits into
mainfrom
machine/pyclipper
Jul 15, 2026
Merged

recipe: pyclipper 1.4.0#107
ndonkoHenri merged 4 commits into
mainfrom
machine/pyclipper

Conversation

@ndonkoHenri

@ndonkoHenri ndonkoHenri commented Jul 15, 2026

Copy link
Copy Markdown

Adds a pyclipper recipe (android & iOS) — polygon clipping/offsetting (Cython bindings over the vendored Angus Johnson Clipper library).

Closes flet-dev/flet#6685

Shape

Minimal Cython recipe, PyPI sdist, zero patches. The extension is C++ (language="c++" over the bundled Clipper sources), so on Android it needs libc++_shared.so at runtime — one Jinja-gated host dep on flet-libcpp-shared. iOS links the system libc++, so no host dep there.

Consumer notes (usage & recommendations)

pyclipper is a small, self-contained geometry library — polygon clipping (intersection/union/difference) and offsetting (dilate/erode). It's the polygon-math dependency RapidOCR uses for text-box postprocessing (the "unclip" step), but it's equally usable on its own.

Add it to your app's dependencies:

dependencies = [
    "flet",
    "pyclipper",
]

Example:

import flet as ft
import flet.canvas as cv
import pyclipper


def main(page: ft.Page):
    page.title = "pyclipper demo"

    subj = [[80, 40], [220, 40], [220, 160], [80, 160]]  # blue square
    clip = [[150, 10], [270, 10], [270, 130], [150, 130]]  # green square

    pc = pyclipper.Pyclipper()
    pc.AddPath(clip, pyclipper.PT_CLIP, True)
    pc.AddPath(subj, pyclipper.PT_SUBJECT, True)
    result = pc.Execute(pyclipper.CT_INTERSECTION)[0]  # red overlap

    def edges(poly, color, w):
        ring = poly + [poly[0]]  # close the loop
        return [
            cv.Line(
                x1=a[0],
                y1=a[1],
                x2=b[0],
                y2=b[1],
                paint=ft.Paint(color=color, stroke_width=w),
            )
            for a, b in zip(ring, ring[1:])
        ]

    page.add(
        ft.Text("blue ∩ green = red — computed by pyclipper on-device"),
        cv.Canvas(
            shapes=edges(subj, ft.Colors.BLUE, 2)
            + edges(clip, ft.Colors.GREEN, 2)
            + edges(result, ft.Colors.RED, 4),
            width=300,
            height=200,
        ),
    )


ft.run(main)

Good to know:

  • Integer coordinates. Clipper works in integer space. For float geometry, scale up with pyclipper.scale_to_clipper(...) before adding paths and back with scale_from_clipper(...) after — the standard fixed-point dance every real caller does.
  • Pure compute, no assets, offline. No config/cache/model directories, no network, nothing to wire into Flet storage. Operations are fast C++; typical OCR-postprocessing workloads won't need a background thread, though you can push heavy batch geometry to page.run_thread(...) if it ever blocks the UI.
  • Both platforms, all standard ABIs — no architecture restrictions.

Cython C++ extension over the vendored Angus Johnson Clipper library —
self-contained sdist, zero patches; android gets the usual
flet-libcpp-shared host dep for the C++ runtime. ~130KB wheels, full
6-slice matrix green first try.

This is a groundwork recipe for OCR: rapidocr's only missing native dep
besides onnxruntime (text-box intersection/unclip postprocessing); also
used by easyocr forks and doctr. Tests cover Pyclipper clipping,
PyclipperOffset dilation (the rapidocr unclip step), and the
scale_to/from_clipper fixed-point helpers.
…_pythons=none footgun, pypi verify with - -> _ filename [skip ci]
@ndonkoHenri
ndonkoHenri merged commit 7025b9b into main Jul 15, 2026
15 of 16 checks passed
@ndonkoHenri
ndonkoHenri deleted the machine/pyclipper branch July 15, 2026 13:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant