Portage CPython du moteur pyRevit. Pavage par bandes, glissement leftmost-fit, 8 combinaisons, mélange de systèmes. Objectif n°1 : reproduire exactement les golden numbers du legacy.
Chaque système a un rectangle d'emprise (entraxe × profondeur) et une largeur d'allée de desserte.
| Système | Entraxe | Profondeur | Allée | Vélos/empr. | Emprise |
|---|---|---|---|---|---|
| Râtelier perpendiculaire | 0,75 m |
2,00 m |
1,80 m |
1 | 0,75 × 2,00 m |
| Resserré | 0,60 m |
2,00 m |
1,80 m |
1 | 0,60 × 2,00 m |
| Longitudinal sol | 0,75 m |
2,00 m |
0,90 m |
1 | 0,75 × 2,00 m |
| Double étage | 0,60 m |
2,00 m |
2,65 m |
2 | 0,60 × 2,00 m |
| Arceau | 1,00 m |
2,00 m |
1,80 m |
2 | 1,00 × 2,00 m |
Transformer un polygone quelconque en un problème de pavage 1D, bande par bande.
On tourne tous les sommets du polygone par l'angle principal θ. Dans ce repère, les rangées sont horizontales (axe s) et les bandes s'empilent verticalement (axe t).
On calcule le rectangle englobant du polygone dans le repère local : [s_min, s_max] × [t_min, t_max]. C'est l'espace maximal disponible.
À partir de t_min, on empile les bandes de bas en haut. Chaque bande a une épaisseur = profondeur (× 2 si double) + allée. Les bandes ne se chevauchent jamais.
Pour chaque bande, on remplit la rangée par le glissement leftmost-fit (voir ci-dessous). On ne place une emprise que si ses 4 coins sont à l'intérieur du polygone.
Un algorithme glouton simple mais optimal pour une rangée à système fixé.
On part de s_min et on avance par pas d'entraxe le long de la rangée.
Pour chaque position candidate, on vérifie que les 4 coins de l'emprise sont à l'intérieur du polygone et hors des zones interdites (dégagements de porte, poteaux).
Si l'emprise est valide, on la place et on avance de entraxe. Sinon, on avance d'un petit pas (0,01 m) et on réessaie.
Ce glissement est optimal pour une rangée à système fixé : il est démontrable qu'aucune autre disposition de gauche à droite ne place plus d'emprises (argument d'échange).
2 orientations × 2 sens de balayage × 2 côtés de départ = 8 candidats. Le meilleur est retenu.
| Paramètre | Option A | Option B | Impact |
|---|---|---|---|
| Orientation | θ |
θ + π/2 |
Rangées parallèles ou perpendiculaires au mur dominant |
| Sens de balayage | t croissant ↑ | t décroissant ↓ | Où commence l'empilement des bandes |
| Côté de départ | s croissant → | s décroissant ← | Où commence le remplissage de chaque rangée |
Les 8 combinaisons sont évaluées et celle qui produit le maximum de vélos est retenue. En cas d'égalité, on préfère celle qui laisse le plus de surface libre (pour la circulation M4).
Chaque bande peut utiliser un système différent. On garde le meilleur.
Pour chaque bande, on teste tous les systèmes autorisés et on garde celui qui place le plus de vélos :
Hystérésis 5% — Pour éviter les oscillations quand deux systèmes donnent des résultats proches, un nouveau système ne remplace le précédent que s'il apporte au moins 5% de vélos en plus. Cela stabilise les résultats sur les pièces limites.
Sur la pièce 46 en mode « mix perpendiculaire + longitudinal » :
2,50 × 1,00 m peut être réservé pour les vélos cargo, longtails ou triporteurs. Il est placé avant le pavage par bandes et exclu de la zone de remplissage. Le constructeur s'adapte automatiquement à l'espace restant.| Paramètre | Valeur | Source |
|---|---|---|
| Longueur | 2,50 m | Arrêté du 30 juin 2022, art. 5 |
| Largeur | 1,00 m | Arrêté du 30 juin 2022, art. 5 |
| Position | Près d'une porte | Facilité de manœuvre |
Pour les pièces non rectangulaires, on décompose en zones traitables séparément.
On cherche le plus grand rectangle inscrit dans le polygone via un algorithme d'histogramme :
Après extraction du plus grand rectangle, les zones résiduelles (les « branches » du L ou du T) sont traitées séparément :
Après chaque implantation, le validateur parcourt toutes les paires d'emprises et vérifie :
Ce test est exécuté à chaque run du pipeline et fait partie des 53 tests unitaires.
Le M2 CPython doit produire exactement les mêmes résultats que le moteur pyRevit legacy.
| Pièce | Système | Legacy | M2 | Δ | Statut |
|---|---|---|---|---|---|
| 46 | Râtelier | 22 | 22 | 0 | ✓ Parité |
| 46 | Mix perp+longi | 22 | 22 | 0 | ✓ Parité |
| 46 | Resserré | 29 | 29 | 0 | ✓ Parité |
| 47 | Râtelier | 10 | 10 | 0 | ✓ Parité |
| 47 | Mix perp+longi | 12 | 12 | 0 | ✓ Parité |
| 47 | Resserré | 14 | 14 | 0 | ✓ Parité |
| 48 | Râtelier | 10 | 10 | 0 | ✓ Parité |
| 48 | Mix perp+longi | 11 | 11 | 0 | ✓ Parité |
| 48 | Resserré | 14 | 14 | 0 | ✓ Parité |
Pavage par bandes + leftmost-fit. Produit une implantation valide par construction.
8 combinaisons exhaustives. Mélange de systèmes par bande.
L/T via plus grand rectangle inscrit. Gère les pièces non rectangulaires.
Golden numbers reproduits à l'identique. Base de confiance pour M3→M5.