Quelques solutions pour regrouper efficacement des lignes parallèles dans Dynamo avec Python
Après un
premier article sur le sujet, je vous propose ici deux autres approches complémentaires – plus
performantes et plus élégantes – pour regrouper des lignes parallèles dans
Dynamo.
L'une s'appuie sur une fonction récursive, l'autre exploite la
puissance de LINQ via PythonNet3 ou IronPython.
- Solution par fonction récursive et produit vectoriel
Je vous renvoie également quelques articles précédents concernant les
opérations vectorielles.
https://voltadynabim.blogspot.com/2021/02/dynamo-python-operationvecteurs.html
https://voltadynabim.blogspot.com/2024/12/dynamo-python-la-similarite-cosinus.html
code (compatible avec tous les moteurs Python)
import sys
import clr
import System
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
import time
def group_parallal_lines(lines, n=0):
"""
group parallal curves
"""
if len(lines) == 0 or n > 900:
return []
group = [lines.pop(0)]
idx_group = []
vectA = group[0].Direction.Normalized()
for idx, line in enumerate(lines):
vectB = line.Direction.Normalized()
if abs(vectA.Cross(vectB).Length) < 0.01 :
group.append(line)
idx_group.append(idx)
rest = [l for idx, l in enumerate(lines) if idx not in idx_group]
return [group] + group_parallal_lines(rest, n+1)
ds_lines = IN[0]
final_group = []
t1 = time.time()
groups = group_parallal_lines(ds_lines)
elapse_time = time.time() - t1
OUT = f"{elapse_time=:.2f}s", groups
- Solution avec LINQ et sérialisation de l'orientation des lignes
GroupBy
(LINQ) avec comme clé une représentation bi-vectorielle représentant la
direction des lignes (sérialisation de la direction/orientation).
code (compatible seulement avec IronPython3 et PythonNet3)
import sys
import clr
import System
from System import Array
from System.Collections.Generic import List, IList, Dictionary
clr.AddReference('ProtoGeometry')
import Autodesk.DesignScript.Geometry as DS
from Autodesk.DesignScript.Geometry import *
clr.AddReference('System.Drawing')
import System.Drawing
clr.AddReference("System.Core")
clr.ImportExtensions(System.Linq)
clr.AddReference('GeometryColor')
from Modifiers import GeometryColor
clr.AddReference('DSCoreNodes')
import DSCore
from DSCore import Color as DSColor
import time
def bi_direction_representation(line):
v1 = line.Direction.Normalized()
v2 = v1.Reverse()
lst_vect = sorted([v1, v2], key = lambda v : (v.X, v.Y, v.Z))
vect_repr = "|".join([f"Vect({v.X:.2f},{v.Y:.2f},{v.Z:.2f})" for v in lst_vect])
return vect_repr.replace("-0.00", "0.00")
ds_lines = List[DS.Curve](IN[0])
check_lines_color = []
# colors for check result
color_values = System.Enum.GetValues[System.Drawing.KnownColor]()
color_values = [c for idx, c in enumerate(color_values) if 0.45 < System.Drawing.Color.FromKnownColor(c).GetBrightness() < 0.65]
color_values.reverse()
t1 = time.time()
groups = ds_lines.GroupBy[DS.Curve, System.String](System.Func[DS.Curve, System.String](
lambda c : bi_direction_representation(c)))\
.Select(System.Func[System.Object, System.Object](lambda x : x.ToList()))\
.ToList()
elapse_time = time.time() - t1
#
# check the results adding colors
for group_curves, color_value in zip(groups, color_values):
color_to_apply = System.Drawing.Color.FromKnownColor(color_value)
ds_color = DSColor.ByARGB(color_to_apply.R,
color_to_apply.G,
color_to_apply.B,
0)
for line in group_curves:
check_lines_color.append(GeometryColor.ByGeometryColor(line, ds_color))
OUT = f"{elapse_time=:.2f}s", groups, check_lines_color
- Résultats
Méthode | Temps d'exécution | Nombre d'éléments traités |
---|---|---|
Recursive Function | 6.22 s | 26 400 lignes |
LINQ + bi-representation | 0.98 s | 26 400 lignes |
0 commentaires:
Enregistrer un commentaire