inkscape.voronoi/README.md
2026-09-30 22:23:25 +02:00

210 lines
10 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Remplissage Voronoï — extension Inkscape
<table>
<tr>
<td width="50%" valign="top">
<img src="docs/exemple.png" alt="Rectangle, cercle, forme courbe, forme trouée et ellipse remplis d'un motif de Voronoï : cellules blanches séparées par un filet noir de largeur constante, cadre le long du contour" width="420">
</td>
<td valign="top">
Extension Inkscape 1.x qui remplit une forme avec un motif de Voronoï : des
germes sont répartis sur la forme, chaque cellule est rétrécie pour laisser
entre deux cellules voisines un **filet de largeur constante et paramétrable**,
puis découpée par le contour. Le résultat est un chemin unique — la forme
percée par les cellules — prêt pour la découpe laser, le vinyle, la gravure ou
l'impression, ou bien une cellule par chemin pour la mise en couleur.
</td>
</tr>
</table>
## Sommaire
- [Fonctionnalités](#fonctionnalités)
- [Installation](#installation)
- [Utilisation](#utilisation)
- [Paramètres](#paramètres)
- [Structure du projet](#structure-du-projet)
- [Développement](#développement)
## Fonctionnalités
- Formes acceptées : chemins, rectangles, cercles, ellipses, polygones et
polylignes, y compris dans des groupes sélectionnés ; les trous suivent la
règle pair-impair. Le texte doit d'abord être converti en chemin.
- Trois dispositions des germes : aléatoire homogène (Poisson, cellules
organiques de taille voisine), aléatoire pur, grille hexagonale avec
irrégularité réglable (0 % = nid d'abeille parfait). Graine aléatoire
reproductible.
- Filet exact : deux cellules voisines sont séparées exactement de la largeur
demandée ; option de cadre de même largeur le long du contour, y compris
autour des trous et dans les creux des formes concaves.
- Cellules arrondies : rayon de coin fixe, ou arrondi proportionnel à la taille
de chaque cellule, jusqu'à des cellules presque circulaires (100 %).
- Sortie : le filet (un seul chemin en remplissage pair-impair), les cellules
(un chemin plein par cellule), ou les deux ; couleurs réglables.
- SVG propre : résultat dans un groupe nommé placé juste au-dessus de la forme,
sans `transform` sur les chemins, transformations des groupes parents gérées.
- Calcul en Python pur (index spatial) : quelques centaines de cellules en une
fraction de seconde ; au-delà de 20 000 cellules, l'extension demande
d'agrandir les cellules.
- Interface traduite en français et en anglais, selon la langue d'Inkscape
(anglais pour toute autre langue).
- Script de déploiement Windows.
## Installation
Aucune dépendance externe : l'extension utilise `inkex`, fourni avec Inkscape.
### Windows (script)
Inkscape fermé, dans PowerShell :
```powershell
.\deploy.ps1 # installe ou met à jour
.\deploy.ps1 -Uninstall # désinstalle
.\deploy.ps1 -Force # déploie même si Inkscape est ouvert
```
Le script copie les fichiers dans `%APPDATA%\inkscape\extensions\VoronoiFill`.
### Manuelle
Copier dans un sous-dossier du répertoire des extensions utilisateur :
- `voronoi_fill.inx`, `voronoi_fill.py`, `voronoi_core.py` ;
- `images/parameters_en.png` ;
- le dossier `locale/`.
| Système | Répertoire des extensions |
| ------- | -------------------------------------------------- |
| Windows | `%APPDATA%\inkscape\extensions` |
| Linux | `~/.config/inkscape/extensions` |
| macOS | `~/Library/Application Support/org.inkscape.Inkscape/config/inkscape/extensions` |
Redémarrer Inkscape ensuite.
## Utilisation
1. Sélectionner une ou plusieurs formes fermées (ou des groupes).
2. Menu **Extensions > AlexDesign > Remplissage Voronoï…**
(**Extensions > AlexDesign > Voronoi Fill…** en anglais).
3. Régler le motif et le filet, cocher **Aperçu en direct** si besoin, puis
**Appliquer**.
Le résultat est placé dans un groupe « Remplissage Voronoï » juste au-dessus
de chaque forme ; l'original est conservé sauf si l'option est décochée.
### Conseils
| Symptôme | Réglage |
| -------- | ------- |
| Motif trop dense, calcul lent | Augmenter la taille des cellules. |
| Motif qui ne plaît pas | Changer la graine aléatoire. |
| Cellules très inégales | Choisir « Aléatoire homogène » ou la grille hexagonale. |
| Nid d'abeille trop régulier | Monter l'irrégularité (grille hexagonale). |
| Petits éclats le long du contour | Ils sont supprimés s'ils sont plus fins que la moitié du filet ; sinon réduire la taille des cellules ou changer de graine. |
| Filet trop anguleux pour la découpe | Donner un rayon aux coins des cellules. |
| Cellules plus rondes, aspect organique | Monter l'arrondi des cellules (50 à 100 %). |
## Paramètres
![Schéma des paramètres](docs/parametres.png)
| Paramètre | Défaut | Rôle |
| --------- | ------ | ---- |
| **Disposition des cellules** | Aléatoire homogène | Placement des germes : aléatoire homogène (Poisson), aléatoire pur, grille hexagonale. |
| **Taille des cellules** | 10 | Distance moyenne entre les centres de deux cellules voisines. |
| **Irrégularité** | 30 % | Grille hexagonale seulement : déplacement aléatoire des germes, en % d'une demi-cellule. |
| **Graine aléatoire** | 1 | Change le motif sans changer les réglages. |
| **Unité** | mm | Unité des longueurs (mm, cm, px, pt, in). |
| **Largeur du filet** | 1 | Écart entre deux cellules voisines ; doit rester inférieure à la taille des cellules. |
| **Filet le long du contour** | coché | Les cellules restent à une largeur de filet du bord : un cadre borde la forme. |
| **Rayon des coins des cellules** | 0 | Arrondit les coins de toutes les cellules d'une même longueur (pas ceux créés par le contour). |
| **Arrondi des cellules** | 0 % | Arrondit chaque cellule en proportion de sa taille (rayon inscrit) ; 100 % = presque un disque. Le plus grand de l'arrondi et du rayon des coins s'applique. |
| **Résultat** | Filet | Filet (un chemin), cellules (un chemin chacune), ou les deux. |
| **Couleur du filet** | noir | Remplissage du filet. |
| **Couleur des cellules** | gris | Remplissage des cellules. |
| **Conserver la forme d'origine** | coché | Décoché, la forme source est supprimée. |
## Structure du projet
```text
voronoi_fill.inx Boîte de dialogue (onglets Motif, Filet, Aide), textes anglais
voronoi_fill.py Couche inkex : sélection, unités, aplatissement, écriture SVG
voronoi_core.py Calcul pur (germes, Voronoï, découpe, filet), sans inkex
i18n.py Extraction / mise à jour / compilation des traductions
po/ Catalogues voronoi_fill.pot, en.po, fr.po
locale/ Catalogues compilés (.mo), déployés
images/parameters_en.png Schéma de l'onglet « Aide » (déployé)
docs/schema_parametres.py Générateur du schéma (fr pour le README, en pour la boîte)
docs/parametres.png Schéma du README
docs/exemple.png Exemple de rendu
tests/data/shapes.svg Formes d'exemple des tests de bout en bout
test_voronoi_fill.py Tests pytest
deploy.ps1 Déploiement / désinstallation Windows
```
API de `voronoi_core` (points `(x, y)`, y vers le bas ; une région est une
liste d'anneaux lue en pair-impair) :
| Fonction | Rôle |
| -------- | ---- |
| `fill_shape(rings, cell_size, net_width, distribution, irregularity, seed, border, corner_radius, roundness, tolerance, max_cells, min_area, min_thickness)` | Cellules rétrécies qui remplissent la région ; liste de régions. Lève `FillError`. |
| `net_rings(shape_rings, cells)` | Filet : anneaux de la forme + anneaux des cellules (pair-impair). |
| `make_points(distribution, bbox, size, irregularity, seed)` | Germes `random`, `poisson` ou `hexagonal`. |
| `voronoi_cells(points, bbox, gap)` | Cellule convexe de chaque germe, rétrécie de `gap/2` de chaque côté. |
| `round_cell(poly, corner_radius, roundness, tolerance)` | Arrondit une cellule (érosion puis dilatation), sans déborder. |
| `erode_convex(poly, radius)`, `inradius(poly)` | Érosion exacte d'un convexe, rayon du disque inscrit. |
| `round_convex(poly, radius, tolerance)` | Dilate un convexe avec coins en arcs. |
| `clip_convex(region, convex, inside)` | Intersection ou différence d'une région pair-impair et d'un convexe. |
| `erode_near_boundary(piece, region, radius, tolerance)` | Retire d'un morceau ce qui est à moins de `radius` du bord de la région. |
| `Region(rings)` | Région indexée : `edges_in(box)`, `contains(point)`. |
| `clean_rings`, `ring_area`, `region_area`, `point_in_rings`, `bbox_of` | Utilitaires géométriques. |
| `rings_to_d`, `polylines_to_d`, `parse_color` | Données `d` SVG, couleur Inkscape → CSS. |
## Développement
```powershell
python -m venv .venv
.venv\Scripts\activate
pip install pytest lxml tinycss2 cssselect2 cssselect
python -m pytest -q
```
Sans `inkex` : **40 tests passés, 6 ignorés** (bout en bout). Avec `inkex` :
```powershell
$env:PYTHONPATH = 'C:\Program Files\Inkscape\share\inkscape\extensions'
python -m pytest -q # 46 tests passés
```
Les tests couvrent la découpe par un convexe (formes concaves, trous, contacts
dégénérés), les cellules (partition, écart exact, hexagones réguliers, arrondi), les
germes (distance de Poisson, densités comparables, graine reproductible), le
remplissage (cadre à distance du contour, filet = forme − cellules), l'extension
de bout en bout (groupes transformés, sorties, erreurs) et la complétude des
traductions et la cohérence `.inx` ↔ arguments.
### Traductions
```powershell
python i18n.py # extrait, met à jour po/*.po, compile locale/*.mo
```
Après modification d'un texte (`.inx` ou `_("...")` dans un `.py`) : lancer
`python i18n.py`, compléter les `msgstr` vides de `po/fr.po`, relancer.
`en.po` se remplit tout seul. Pour ajouter une langue, l'ajouter à
`LANGUAGES` dans `i18n.py`, relancer, traduire le nouveau `.po`.
### Schéma des paramètres
```powershell
python docs/schema_parametres.py # fr → docs/parametres.png (1400 px)
# en → images/parameters_en.png (900 px)
```
Le schéma est dessiné avec les fonctions de `voronoi_core` et exporté par
`C:\Program Files\Inkscape\bin\inkscape.com`. La version anglaise est affichée
aux 3/4 dans l'onglet « Aide », Inkscape ne traduisant pas le chemin d'une image.