# Remplissage découpe flexible — extension Inkscape
Rectangle, disque, chemin courbe, rectangle troué et ellipse remplis de lumières oblongues en quinconce 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)).
## 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//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/.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).