26 févr. 2023

[Dynamo += Python] API Revit, ajouter une méthode

 



Et si on ajoutait une méthode à une classe de l'API Revit ?

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

Il arrive parfois que les méthodes inclus dans l'API ne répondent pas à nos besoins, on a alors plusieurs solutions en Python

  • Ajouter de fonction python  
  • Passer par un Décorateur 
  • Construire une librairie dll avec des méthodes d'extension (C#)
  • Ajouter de classe Python avec qui hérite d'une .Net classe (Surcharge d'un constructeur .Net)
Dans cet article, nous allons nous intéresser sur ce dernier point

Pour créer une classe qui hérite d'un Type, nous avons obligatoirement besoin d'une Classe dans l'API qui possède un constructeur

Les constructeurs .NET peuvent être surchargés. Pour appeler une surcharge de constructeur de type de base spécifique, nous devons définir une méthode __new__ et appeler __new__ sur le type de base .NET

Important
Pour Python3 (IronPython3 ou PythonNet3) il faudra utiliser directement la méthode suivante dans la méthode d'initialisation  __init__ 
super().__init__()

Au travers de cette nouvelle classe héritée, nous allons ajouter 3 méthodes pour l'exemple :

  • SignedAngleTo 🠊 méthode qui retourne l'angle signé (positif ou négatif) entre 2 vecteurs
  • SquareRoot 🠊 méthode qui retourne un vecteur avec les coordonnées mis au carré 
  • Parse 🠊 méthode statique qui retourne le vecteur suivant analyse d'un texte au format "0, 0, 0"



import clr
import sys

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

class Vector3(DB.XYZ):
	# for IronPython2
	#def __new__(cls, x, y, z):
	#	return super(cls).__new__(cls, x, y, z)

	def __init__(self, x, y, z):
		super().__init__() # For Python3 (Ironpython3 or PythonNet3)
		self._x = x
		self._y = y
		self._z = z
		
	def SignedAngleTo(self, v2):
		angle = self.AngleTo(v2)
		n = 1 if self.CrossProduct(v2).Z > 0 else -1
		return angle * n
		
	def SquareRoot(self):
		return self.__class__(self._x ** 2, self._y ** 2, self._z ** 2)
		
	@staticmethod
	def Parse(value_txt):
		args_v = [float(v) for v in value_txt.split(",")]
		return Vector3(*args_v)
		
v1 = Vector3(2, 4, 2)
v1 = v1.SquareRoot()
v2 = Vector3.Parse("1, 1, 2")
s_angle = v1.SignedAngleTo(v2)


v3 = v1.Add(v2) # or v1 + v2
v4 = v2.DotProduct(v3)

OUT = s_angle, v1, v2, v3, v4, v1.GetType(), isinstance(v1, XYZ), isinstance(v1, Vector3)




Cette méthode est compatible avec les 2 moteurs Python. 

Comme on peut le voir, le type de l'objet retourné hérite bien du type DB.XYZ avec toutes les méthodes et propriétés de cette Classe en plus de celles que nous avons rajoutées.

C'est vraiment dommage que l'API Dynamo ProtoGeometry ne possède pas de classe avec des constructeurs 😢


  • Ressources

https://ironpython.net/documentation/dotnet/dotnet.html#calling-base-constructor





0 commentaires:

Enregistrer un commentaire