# Remplissage motif rubans ondulés — extension Inkscape
Cinq formes (rectangle, cercle, chemin courbe, rectangle troué, ellipse) remplies du motif de rubans ondulés Extension Inkscape 1.x qui remplit les formes sélectionnées d'un motif de tapisserie : un fond de traits verticaux traversé par des rubans en S, rangés en quinconce et penchant tour à tour à droite et à gauche, ce qui donne un effet de tressage. Le motif reproduit le modèle [`doc/patern.jpg`](doc/patern.jpg) ; il est découpé le long du contour de chaque forme, trous compris, et livré sous la forme d'un seul chemin sans remplissage, prêt pour la gravure, le traçage ou la découpe.
## 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, chemins et groupes (toutes les formes d'un groupe sont remplies ensemble) ; les textes, images et clones sont ignorés (convertir un texte avec **Chemin > Objet en chemin**). - Respecte les trous d'un chemin (règle pair-impair) et les transformations des formes et de leurs groupes parents. - Motif entièrement réglable : pas des traits, nombre de traits par ruban, décalage, hauteur et rayon de l'onde, quinconce, rotation. - Origine du motif au centre de chaque forme, ou à l'origine du document pour un motif continu d'une forme à l'autre. - SVG propre : un groupe par forme, contenant un seul chemin ; les traits qui se suivent sont soudés en tracés continus. - Rapide : une page A3 au pas de 1 mm (environ 110 000 points) se calcule en 3 secondes environ. - 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 Fermer Inkscape, puis dans PowerShell, depuis le dossier du projet : ```powershell .\deploy.ps1 # installe dans %APPDATA%\inkscape\extensions\wavyRibbonFill .\deploy.ps1 -Uninstall # désinstalle .\deploy.ps1 -Force # installe même si Inkscape est ouvert ``` ### Installation manuelle Copier dans un sous-dossier du dossier des extensions utilisateur d'Inkscape : - `wavy_ribbon_fill.inx`, `wavy_ribbon_fill.py`, `wavy_ribbon_fill_core.py` ; - le dossier `images/` (schéma de l'onglet « Aide ») ; - le dossier `locale/` (traductions compilées). | Système | Dossier 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. Sélectionner une ou plusieurs formes fermées. 2. Ouvrir **Extensions > AlexDesign > Remplissage motif rubans ondulés…** (*Wavy Ribbon Pattern Fill*). 3. Régler le motif (onglet « Motif ») et son rendu (onglet « Remplissage ») ; cocher « Aperçu en direct » pour voir le résultat. 4. Valider avec **Appliquer**. Chaque forme reçoit un groupe « Motif rubans ondulés », placé juste au-dessus d'elle, qui contient un seul chemin sans remplissage. ### Conseils - **Motif trop dense ou trop lâche** : changer le pas des traits ; tout le motif suit, les autres réglages étant comptés en pas. - **Rubans plus larges** : augmenter le nombre de traits par ruban, et le pas des colonnes d'autant. - **Ondes plus douces** : augmenter la hauteur d'onde et le rayon de virage (le rayon est limité à la moitié de la hauteur). - **Traits coupés entre deux rubans** : les rubans se chevauchent ; augmenter le pas des colonnes ou le pas des rangées. - **Motif qui doit se raccorder entre plusieurs formes** : choisir l'origine « Origine du document ». - **Message « demanderait plus de 3000 traits »** : augmenter le pas des traits. ## Paramètres ![Schéma des paramètres](docs/parametres.png) | Paramètre | Défaut | Rôle | | ---------------------------- | ------- | -------------------------------------------------------------------------------------- | | Pas des traits | 2 mm | Distance entre deux traits voisins ; unité de toutes les autres dimensions du motif. | | Unité | mm | Unité du pas et de l'épaisseur du trait (mm, cm, px, pt, in). | | Traits par ruban | 5 | Nombre de traits d'un ruban ; sa largeur vaut (traits − 1) pas. | | Décalage du ruban (pas) | 6 | Déplacement latéral d'un ruban le long de son onde (nombre entier de pas). | | Hauteur d'onde (pas) | 7 | Hauteur sur laquelle un trait passe de sa position basse à sa position haute. | | Rayon de virage (pas) | 2,8 | Rayon des deux virages d'une onde, limité à la moitié de la hauteur ; 0 = traits droits. | | Décalage des traits (pas) | 1 | Décalage vertical d'un trait du ruban au suivant ; 0 resserre le ruban dans l'oblique. | | Pas des colonnes (pas) | 8 | Décalage latéral d'une rangée de rubans à la suivante ; période = 2 pas de colonne. | | Pas des rangées (pas) | 7,75 | Distance verticale d'une rangée à la suivante, qui penche de l'autre côté. | | Rotation du motif (°) | 0 | Tourne le motif autour de son origine, sens horaire. | | Origine du motif | Centre de chaque forme | Ou origine du document : motif continu d'une forme à l'autre. | | Épaisseur du trait | 0,25 | Dans l'unité choisie. | | Couleur du trait | noir | Couleur et opacité du chemin produit. | | Conserver la forme d'origine | oui | Décocher pour ne garder que le motif. | Les valeurs par défaut reproduisent les proportions du modèle `doc/patern.jpg`. ## Structure du projet ```text wavy_ribbon_fill.inx Boîte de dialogue (textes source en anglais) wavy_ribbon_fill.py Couche inkex : sélection, unités, écriture SVG wavy_ribbon_fill_core.py Calcul du motif, sans inkex i18n.py Chaîne de traduction (extract / update / compile) po/ Modèle .pot et catalogues en.po, fr.po locale/ Catalogues compilés .mo (déployés) images/parameters_en.png Schéma de l'onglet « Aide » (déployé) doc/patern.jpg Modèle du motif 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 Exemple de résultat (README) tests/data/shapes.svg Formes d'exemple pour les tests de bout en bout test_wavy_ribbon_fill.py Tests pytest deploy.ps1 Déploiement / désinstallation Windows site/ Page de présentation (hors dépôt, publiée par site/deploy.ps1) ``` ### API du noyau (`wavy_ribbon_fill_core.py`) Les contours sont des listes d'anneaux (listes de points, trous en pair-impair), dans le repère SVG (y vers le bas). `shift`, `height`, `radius`, `stagger`, `columns` et `rows` sont exprimés en nombre de pas. | Fonction | Rôle | | --------------------------------------------------------------- | -------------------------------------------------------------------- | | `fill_polylines(rings, spacing, lines, shift, height, radius, stagger, columns, rows, angle, origin)` | Motif découpé par le contour, rotation comprise : liste de polylignes. | | `RibbonPattern(spacing, …, origin)` | Géométrie du motif pour un jeu de réglages. | | `RibbonPattern.fill(rings)` | Polylignes du motif (traits du fond et rubans) dans le contour. | | `RibbonPattern.pieces(bounds)` | Rubans dont l'onde touche une boîte englobante. | | `RibbonPattern.piece_curves(piece)` | Les traits d'un ruban, du bas vers le haut. | | `RibbonPattern.piece_region(piece, inset)` | Polygone couvert par l'onde d'un ruban. | | `RibbonPattern.hidden_interval(piece, index)` | Hauteur sur laquelle un trait du fond passe sous un ruban. | | `wave_profile(shift, height, radius, tolerance)` | Profil en S d'un trait : arc, droite, arc. | | `EdgeIndex(rings)` : `inside(x, y)`, `crossings(p, q)`, `clip(polyline, keep_inside)` | Découpe de polylignes par un contour. | | `join_polylines(polylines)` | Soude les polylignes bout à bout et retire les points alignés. | | `subtract_intervals(intervals, holes)` | Différence d'intervalles (traits du fond masqués). | | `rotate_points(points, angle, center)`, `rings_bounds(rings)` | Rotation (sens horaire à l'écran) et boîte englobante. | | `parse_color(value)`, `polylines_to_d(polylines)` | Couleur Inkscape → CSS et opacité ; polylignes → données `d`. | ## Développement ```powershell python -m venv .venv .venv\Scripts\Activate.ps1 pip install pytest python -m pytest -q ``` Sans `inkex`, les tests de bout en bout sont ignorés : **31 réussis, 9 ignorés**. Avec `inkex` (celui d'Inkscape), **40 réussis** : ```powershell pip install lxml tinycss2 cssselect2 cssselect $env:PYTHONPATH = 'C:\Program Files\Inkscape\share\inkscape\extensions' python -m pytest -q ``` Les tests couvrent le noyau (profil de l'onde, découpe, trous, périodicité, miroir, rotation, chevauchement des rubans, entrées vides ou invalides), l'extension de bout en bout (formes courbes, trous, groupe transformé, unités, couleur) et la cohérence entre le `.inx`, les arguments Python, le schéma et les traductions. ### Traductions Les textes source (`.inx` et appels `_()` des `.py`) sont en anglais. ```powershell python i18n.py # extract + update + compile ; liste les chaînes à traduire python i18n.py extract # po/wavyribbonfill.pot python i18n.py update # reporte le modèle dans po/en.po et po/fr.po python i18n.py compile # locale//LC_MESSAGES/wavyribbonfill.mo ``` Après toute modification d'un texte : lancer `python i18n.py`, compléter les `msgstr` vides de `po/fr.po`, relancer `python i18n.py` (`en.po` se remplit tout seul). Ne jamais modifier les `.mo`. Pour ajouter une langue, l'ajouter à `LANGUAGES` dans `i18n.py` et traduire le nouveau `po/.po`. ### 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 réel. L'export PNG passe par `inkscape.com`. La version anglaise sert à la boîte de dialogue, Inkscape ne traduisant pas le chemin d'une image ; elle y est affichée aux 3/4 de sa taille (675 × 617).