inkscape.decoupeFlexible/README.md
2026-10-01 15:21:24 +02:00

231 lines
13 KiB
Markdown

# Remplissage découpe flexible — extension Inkscape
<table>
<tr>
<td width="50%" valign="top">
<img src="docs/exemple.png" alt="Rectangle, disque, chemin courbe, rectangle troué et ellipse remplis de lumières oblongues en quinconce" width="420">
</td>
<td valign="top">
Extension Inkscape 1.x qui remplit les formes sélectionnées avec un motif de
**découpe flexible** (*living hinge*) : des lumières oblongues rangées en
colonnes décalées en quinconce. Une fois le motif découpé au laser, le panneau
(contreplaqué, MDF, acrylique…) se plie autour d'un axe parallèle aux lumières.
Près du bord et autour des trous, les lumières sont raccourcies et ré-arrondies
pour rester à la marge demandée, comme sur le motif d'origine
([doc/Patern.jpg](doc/Patern.jpg)). Un mode aléatoire tire la longueur de
chaque lumière au hasard, du trou rond à la lumière entière
([doc/patern2.jpg](doc/patern2.jpg)).
</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
- Remplit rectangles, cercles, ellipses, polygones et chemins, y compris les
formes trouées (règle pair-impair) et les formes rangées dans des groupes ou
des calques transformés. Textes, images et clones sont ignorés.
- Lumières à bouts arrondis tracées avec de vrais arcs de cercle (pas de
polylignes), toutes réunies en **un seul chemin** par forme.
- Lumières raccourcies au bord : elles s'arrêtent à la marge, gardent leurs
bouts ronds et disparaissent sous une longueur minimale réglable.
- **Longueurs aléatoires** en option : chaque lumière prend une longueur au
hasard entre un minimum et la longueur réglée, pont et pas constants.
Chaque colonne est remplie d'une marge à l'autre : une lumière commence pile
en haut, une autre finit pile en bas, toutes les colonnes débutent et
s'arrêtent donc au même niveau. Le tirage est reproductible (graine) : mêmes
réglages, même motif.
- Décalage des colonnes réglable (50 % = quinconce) et motif orientable à
n'importe quel angle.
- Longueurs saisies en mm, cm, px, pt ou pouces.
- Interface traduite en français et en anglais, selon la langue d'Inkscape
(anglais pour toute autre langue).
- Script de déploiement et de désinstallation pour Windows.
## Installation
Aucune dépendance externe : l'extension utilise `inkex`, fourni avec Inkscape.
### Windows
Inkscape fermé, depuis le dossier du projet :
```powershell
.\deploy.ps1 # copie dans %APPDATA%\inkscape\extensions\livingHinge
.\deploy.ps1 -Uninstall # supprime l'extension
.\deploy.ps1 -Force # déploie même si Inkscape est ouvert
```
### Manuelle
Copier dans un sous-dossier du répertoire des extensions utilisateur, en
conservant l'arborescence :
```text
living_hinge.inx
living_hinge.py
living_hinge_core.py
images/parameters_en.png
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 : les extensions ne sont lues qu'au démarrage.
## Utilisation
1. Dessiner la zone à assouplir (rectangle, ellipse ou chemin fermé) et la
sélectionner. Plusieurs formes peuvent être traitées d'un coup.
2. Ouvrir **Extensions > AlexDesign > Remplissage découpe flexible…**
(*Living Hinge Fill…*).
3. Régler le motif dans l'onglet « Motif », les longueurs aléatoires dans
l'onglet « Aléatoire », la marge et le trait dans l'onglet « Remplissage » ;
cocher « Aperçu en direct » pour voir le résultat.
4. Appliquer : les lumières sont ajoutées dans un groupe « Découpe flexible »
placé juste au-dessus de la forme, centrées sur elle.
Avec « Longueurs de lumières aléatoires » coché :
![Formes remplies de lumières de longueurs aléatoires](docs/exemple-aleatoire.png)
### Conseils
| Symptôme | Réglage |
| ------------------------------------------ | ----------------------------------------------------------- |
| Le panneau casse en pliant | Augmenter le pont et le pas des colonnes |
| Le panneau est trop raide | Allonger les lumières, réduire le pont ou le pas |
| Le pli doit être horizontal | Angle du motif à 90° |
| Petits trous ronds le long du bord | Augmenter la longueur minimale d'une lumière raccourcie |
| Le tirage aléatoire ne plaît pas | Changer la graine du hasard |
| Trop de petits trous ronds en mode aléatoire | Augmenter la plus courte lumière aléatoire |
| « forme(s) trop petite(s) » | Réduire la largeur des lumières, la longueur minimale ou la marge |
| Découpe d'un simple trait plutôt que d'une lumière | Réduire la largeur au trait de coupe du laser (0,1 à 0,2 mm) |
## Paramètres
![Schéma des paramètres](docs/parametres.png)
| Paramètre | Défaut | Rôle |
| ------------------------------------------------------ | ------ | -------------------------------------------------------------------------------------- |
| Longueur d'une lumière | 20 | Longueur hors tout d'une lumière entière, bouts arrondis compris |
| Largeur d'une lumière | 3 | Largeur de la lumière ; le rayon des bouts en est la moitié |
| Pont (matière entre deux lumières d'une colonne) | 2 | Matière laissée entre deux lumières qui se suivent dans une colonne |
| Pas des colonnes (entraxe) | 5 | Distance entre les axes de deux colonnes voisines (supérieure à la largeur) |
| Unité | mm | Unité de toutes les longueurs : mm, cm, px, pt, in |
| Décalage des colonnes impaires (% de longueur + pont) | 50 | 50 % = quinconce ; 0 % = colonnes alignées |
| Angle du motif (°, 0 = lumières verticales) | 0 | Rotation du motif, sens anti-horaire |
| Longueurs de lumières aléatoires | non | Tire la longueur de chaque lumière au hasard, colonnes remplies d'une marge à l'autre ; décalage et longueur minimale ne servent plus |
| Plus courte lumière aléatoire | 3 | Borne basse du tirage (au moins la largeur, soit un trou rond) ; la borne haute est la longueur d'une lumière |
| Graine du hasard | 1 | Même graine, même motif ; la changer donne un autre tirage |
| Marge entre les lumières et le bord | 2 | Distance minimale entre une lumière et le contour ou un trou |
| Longueur minimale d'une lumière raccourcie | 6 | Sous cette longueur, une lumière raccourcie par le bord est supprimée |
| Couleur du trait | noir | Couleur des lumières |
| Épaisseur du trait | 0,2 | Épaisseur du trait, dans l'unité choisie |
| Conserver la forme d'origine | oui | Décoché, la forme remplie est supprimée et seul le motif reste |
## Structure du projet
```text
living_hinge.inx Boîte de dialogue (textes source en anglais)
living_hinge.py Couche inkex : sélection, unités, écriture SVG
living_hinge_core.py Calcul du motif, sans inkex
i18n.py Extraction / mise à jour / compilation des traductions
po/ livinghinge.pot, en.po, fr.po
locale/<langue>/LC_MESSAGES/ livinghinge.mo (générés, déployés)
images/parameters_en.png Schéma de l'onglet « Aide » (déployé)
doc/Patern.jpg, patern2.jpg Motifs d'origine (régulier, aléatoire)
docs/schema_parametres.py Générateur du schéma (fr pour le README, en pour le dialogue)
docs/parametres.png Schéma du README
docs/exemple.png Rendu de l'extension sur les formes d'exemple
docs/exemple-aleatoire.png Même rendu, longueurs aléatoires
tests/data/shapes.svg Formes d'exemple des tests de bout en bout
test_living_hinge.py Tests pytest
deploy.ps1 Déploiement / désinstallation Windows
```
### API de `living_hinge_core`
Un contour (`rings`) est une liste d'anneaux de points `(x, y)`, trous en
pair-impair, axe y vers le bas. Une lumière est le couple `(p0, p1)` des centres
de ses deux bouts arrondis.
| Fonction | Rôle |
| ------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------- |
| `hinge_slots(rings, length, width, bridge, pitch, stagger=50, angle=0, margin=0, min_length=0, random_min=None, seed=0)` | Lumières du motif qui remplit le contour ; `random_min` active les longueurs aléatoires |
| `regular_spans(low, high, origin, length, bridge)` | Lumières `(début, longueur)` d'une colonne régulière |
| `random_spans(low, high, shortest, longest, bridge, rng)` | Lumières `(début, longueur)` aléatoires qui remplissent exactement `[low, high]` |
| `clear_intervals(rings, x, clearance=0)` | Portions de la verticale `x` situées dans le contour, à `clearance` du bord |
| `slots_to_d(slots, radius, precision=4)` | Données `d` SVG : un sous-chemin fermé par lumière, bouts en arcs |
| `slot_outline(slot, radius, segments=16)` | Contour d'une lumière en polyligne fermée |
| `slot_length(slot, width)` | Longueur hors tout d'une lumière |
| `rotate(point, angle, center=(0, 0))` | Rotation d'un point, sens anti-horaire à l'écran |
| `bounding_box(rings)` | Boîte englobante d'un contour |
| `parse_color(value)` | Couleur Inkscape (entier RGBA) → `(#rrggbb, opacité)` |
| `polylines_to_d(polylines, precision=4)` | Données `d` SVG d'une liste de polylignes |
## Développement
```powershell
python -m venv .venv
.venv\Scripts\pip install pytest
python -m pytest -q
```
Résultat attendu : **27 tests passés, 9 ignorés** (les tests de bout en bout
demandent `inkex`). Avec le `inkex` d'Inkscape :
```powershell
pip install lxml tinycss2 cssselect2 cssselect
$env:PYTHONPATH = 'C:\Program Files\Inkscape\share\inkscape\extensions'
python -m pytest -q # 36 tests passés
```
Les tests couvrent le noyau (intervalles libres, respect de la marge et des
trous, pont, pas, quinconce, angle, longueur minimale, longueurs aléatoires reproductibles et colonnes remplies d'une marge à l'autre,
entrées dégénérées,
tracé en arcs), l'extension de bout en bout (formes, groupes transformés,
unités, mode aléatoire, messages d'erreur, couleur, suppression de l'original) et la cohérence
des traductions et du `.inx` (arguments, valeurs par défaut, images).
### Traductions
Les textes source sont en anglais dans `living_hinge.inx` et dans les `_("…")`
de `living_hinge.py`.
```powershell
python i18n.py # extract + update + compile ; liste les msgstr manquants
```
Après modification d'un texte : lancer `python i18n.py`, compléter les `msgstr`
vides de `po/fr.po`, relancer `python i18n.py`. Ne jamais modifier les `.mo` à
la main. Pour ajouter une langue : l'ajouter à `LANGUAGES` dans `i18n.py`, puis
traduire le `po/<langue>.po` créé.
### Schéma des paramètres
```powershell
python docs/schema_parametres.py # les deux versions
python docs/schema_parametres.py fr # docs/parametres.png (1400 px, README)
python docs/schema_parametres.py en # images/parameters_en.png (900 px, onglet « Aide »)
```
Le schéma est dessiné avec les fonctions du noyau, il reste donc fidèle au
rendu. L'export PNG passe par `inkscape.com` (le raccourci `inkscape` rend la
main avant la fin de l'export).