9 juin 2022

[Dynamo += Python] Courbe d'un raccord (en Arc)

 




Comment obtenir facilement la courbe d'un raccord (en Arc) CDC ou de canalisation ?

if this article is not in your language, use the Google Translate widget (bottom of page for Mobile version) ⬈

Pour extraire la courbe d'un raccord (raccord en Arc)  on peut passer par l'analyse de la géométrie, mais voici une autre façon utilisant moins de ressources.

Pour tracer un arc, il faut minimum 3 paramètres. 
L'objectif ici est de retrouver au moins 3 paramètres par analyse des connecteurs :
- la localisation des connecteurs
- les vecteurs normaux aux extrémités de l'élément

Ainsi par projection, on peut retrouver/calculer le centre de l'arc (lignes rouges ci-dessous)


Première Bonne nouvelle ! On a accès aux systèmes de coordonnées de chaque connecteur via l'API Revit


  • Via l'API Dynamo (ProtoGeometry)


Autre bonne nouvelle, pas besoin de tracer une quelconque projection, l'opération est facilitée avec l'API Dynamo (ProtoGeometry) via la méthode
 Arc.ByStartPointEndPointStartTangent()


Le code Python


import clr
import sys
import System
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
import Autodesk.DesignScript.Geometry as DS

#import Revit API
clr.AddReference('RevitAPI')
import Autodesk
from Autodesk.Revit.DB import *
import Autodesk.Revit.DB as DB

clr.AddReference('RevitNodes')
import Revit
clr.ImportExtensions(Revit.GeometryConversion)
clr.ImportExtensions(Revit.Elements)

#import transactionManager and DocumentManager (RevitServices is specific to Dynamo)
clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
doc = DocumentManager.Instance.CurrentDBDocument
	
def get_curve_fitting(elem):
	"""
	return the arc geometry an the length
	"""
	if hasattr(elem, "MEPModel"):
		conSet = elem.MEPModel.ConnectorManager.Connectors
		if conSet.Size == 2:
			pair_sys_origin = [[con.CoordinateSystem, con.Origin] for con in conSet]
			pta = pair_sys_origin[0][1].ToPoint()
			ptb = pair_sys_origin[1][1].ToPoint()
			vector = pair_sys_origin[0][0].BasisZ.Negate().ToVector()
			arc = DS.Arc.ByStartPointEndPointStartTangent(pta, ptb, vector)
			return arc, arc.Length
		else:
			return "The fitting have more than 2 connectors", None
	return "The Element is not a fitting", None

toList = lambda x : x if hasattr(x, '__iter__') else [x]

#Preparing input from dynamo to revit
fitting = UnwrapElement(IN[0])

OUT = get_curve_fitting(fitting)  

Résultat avec un raccord de canalisation et une courbure de chemin de câble 
(courbe bleu pour les débutants)







  • Via l'équation Sagitta

Si vous ne disposez pas de l'API Dynamo voici une autre méthode en utilisant la formule de l'équation sagitta

La sagitta est utilisée en géométrie des cercles pour calculer la hauteur d'une corde par rapport à l'arc correspondant dans un cercle.

La sagitta 𝑠  est définie comme la distance entre le milieu de la corde d'un cercle et l'arc du cercle à cet endroit.





Le code Python

import clr
import sys
import System
from System import Math

#import Revit API
clr.AddReference('RevitAPI')
import Autodesk
from Autodesk.Revit.DB import *
import Autodesk.Revit.DB as DB

clr.AddReference('RevitNodes')
import Revit
clr.ImportExtensions(Revit.GeometryConversion)

#import transactionManager and DocumentManager (RevitServices is specific to Dynamo)
clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
doc = DocumentManager.Instance.CurrentDBDocument
    
def get_curve_fitting2(elem):
    """
    return the arc geometry
    """
    if hasattr(elem, "MEPModel"):
        conSet = elem.MEPModel.ConnectorManager.Connectors
        if conSet.Size == 2:
            pair_sys_origin = [[con.CoordinateSystem, con.Origin] for con in conSet]
            ptA = pair_sys_origin[0][1]
            ptB = pair_sys_origin[1][1]
            normalA = pair_sys_origin[0][0].BasisX
            normalB = pair_sys_origin[1][0].BasisX
            # create Unbound lines
            lineBoundA = Line.CreateUnbound(ptA, normalA)
            lineBoundB = Line.CreateUnbound(ptB, normalB)
            # compute intersection -> center
            out_IntersectionResultArray = clr.Reference[IntersectionResultArray]()
            result = lineBoundA.Intersect(lineBoundB, out_IntersectionResultArray)
            if result == SetComparisonResult.Overlap:
                center = out_IntersectionResultArray.Value[0].XYZPoint 
                radius = ptA.DistanceTo(center)
                # compute the chord and the middle of chord
                chord = Line.CreateBound(ptA, ptB)
                mid_chord = (ptA + ptB) / 2.0
                distance = ptA.DistanceTo(ptB)
                # compute sagitta
                sagitta = radius - Math.Sqrt(radius**2 - (distance / 2)**2)
                # translate the middle point on the chord with sagitta
                vector_sagitta = (mid_chord  - center).Normalize().Multiply(sagitta)
                pointOnArc = mid_chord + vector_sagitta
                return  Arc.Create(ptA, ptB, pointOnArc)
                    
    return None
      
fitting = UnwrapElement(IN[0])
db_Arc = get_curve_fitting2(fitting)
ds_Arc_for_check = db_Arc.ToProtoType()
OUT = db_Arc, ds_Arc_for_check 

0 commentaires:

Enregistrer un commentaire