Nouvelle série dans l’apprentissage des PythonParts, étudions la modélisation d’un objet 3D : un poteau en béton armé.

1) Script Interface

Dans cet exemple nous allons mettre en place les premiers champs nécessaires pour la modélisation de notre poteau.

Avant tout chose, il faut renseigner la liaison avec notre script principal dans une balise Element :

<?xml version= »1.0″ encoding= »utf-8″?>

<Element>

<Script>
<Name>APIHub\objects_3D.py</Name>
<Title>Objects3D</Title>
<Version>1.0</Version>
</Script>

</Element>

 

Je vais ensuite créer ma première page :

<Page>

<Name>Page1</Name>
<Text>Général</Text>

</Page>

A noter : les pages constituent les onglets dans la palette Allplan

Je place un champ de saisie pour la désignation de mon poteau.

Je souhaite que son nom soit bien visible dans la palette et qu’il soit directement assigné dans la liste des attributs.

<Parameter>
<Name>ColumnId</Name>
<Text>Repère</Text>
<Value>P01</Value>
<ValueType>Attribute</ValueType>
<AttributeId>18222</AttributeId>
<FontFaceCode>1</FontFaceCode>
</Parameter>

A noter :

  • avec la valeur 1 pour FontFaceCode, le texte d’information s’affiche en gras (plus de détails ici) ;
  • en choisissant un ValueType égal à Attribute ainsi que l’ID souhaité (ici 18222), je place la valeur du champ dans l’attribut Référence).

Point important dans la conception d’un poteau en béton armé, j’indique la classe de béton qui sera utilisée :

 <Parameter>
<Name>ConcreteGrade</Name>
<Text>Classe de béton</Text>
<Value>-1</Value>
<ValueType>ReinfConcreteGrade</ValueType>
</Parameter>

A noter : avec Value égal à -1, Allplan se calera à la valeur par défaut depuis les options générales.

Je vais maintenant saisir les informations géométriques de mon poteau que je place dans un expander pour plus de clarté :

 <Parameter>
<Name>GeometryExpander</Name>
<Text>Géométrie</Text>
<ValueType>Expander</ValueType>
</Parameter>

Vient alors le choix de la forme du poteau (rectangulaire ou circulaire) :

<Parameter>
<Name>ChoiceRadioGroup</Name>
<Text>Forme :</Text>
<Value>rectangle</Value>
<ValueType>RadioButtonGroup</ValueType>

 

<Parameter>
<Name>ChoiceRectColumn</Name>
<Text>rectangulaire</Text>
<Value>rectangle</Value>
<ValueType>RadioButton</ValueType>
</Parameter>

 

<Parameter>
<Name>ChoiceCircColumn</Name>
<Text>circulaire</Text>
<Value>circle</Value>
<ValueType>RadioButton</ValueType>
</Parameter>

 

</Parameter>

A noter : je choisis d’utiliser un RadioBouton pour sélectionner la forme avec l’option rectangulaire mise par défaut

puis ses dimensions :

<Parameter>
<Name>ColumnLength</Name>
<Text>Longueur</Text>
<FontFaceCode>4</FontFaceCode>
<Value>400.0</Value>
<ValueType>Length</ValueType>
<Visible>ChoiceRadioGroup == « rectangle »</Visible>
</Parameter>

 

<Parameter>
<Name>ColumnThick</Name>
<Text>Largeur</Text>
<FontFaceCode>4</FontFaceCode>
<Value>400.0</Value>
<ValueType>Length</ValueType>
<Visible>ChoiceRadioGroup == « rectangle »</Visible>
</Parameter>

<Parameter>
<Name>ColumnRadius</Name>
<Text>Rayon</Text>
<FontFaceCode>4</FontFaceCode>
<Value>300.0</Value>
<ValueType>Length</ValueType>
<Visible>ChoiceRadioGroup == « circle »</Visible>
</Parameter>

A noter : la disposition va évoluer suivant le choix utilisateur, longueur et largeur pour un poteau rectangulaire et le rayon pour un poteau circulaire.

Je peux maintenant saisir la hauteur de mon objet, paramètre indépendant de la forme désirée :

<Parameter>
<Name>ColumnHeight</Name>
<Text>Hauteur</Text>
<FontFaceCode>4</FontFaceCode>
<Value>2500.0</Value>
<ValueType>Length</ValueType>
</Parameter>

A l’instar des précédents exemples, je vais personnaliser le rendu de mon poteau en proposant également une hachure ou un remplissage.

Je crée mon expander :

<Parameter>
<Name>FormatExpander</Name>
<Text>Format</Text>
<ValueType>Expander</ValueType>

</Parameter>

puis les options générales de rendu (layer, couleur, etc…..) avec le choix d’utiliser les paramètres courants :

<Parameter>
<Name>UseGlobalProperties</Name>
<Text>Utiliser les paramètres courants</Text>
<Value>True</Value>
<ValueType>CheckBox</ValueType>
</Parameter>

 

<Parameter>
<Name>CommonProperties</Name>
<Text></Text>
<Value></Value>
<ValueType>CommonProperties</ValueType>
<Visible>UseGlobalProperties == False</Visible>
</Parameter>

A noter : par défaut Allplan gardera les options en cours mais, si l’on décoche la case, l’ensemble des propriétés de rendu sera personnalisable par l’utilisateur

Je propose ensuite les autres paramètres de rendu avec tout d’abord les hachures :

<Parameter>
<Name>HatchCheckBox</Name>
<Text>Hachurage</Text>
<Value>False</Value>
<ValueType>CheckBox</ValueType>
</Parameter>

 

<Parameter>
<Name>HatchStyle</Name>
<Text>Style d’hachurage</Text>
<Value>-1</Value>
<ValueType>Hatch</ValueType>
<Visible>HatchCheckBox == True</Visible>
</Parameter>

puis le remplissage :

<Parameter>
<Name>FillCheckBox</Name>
<Text>Remplissage</Text>
<Value>False</Value>
<ValueType>CheckBox</ValueType>
</Parameter>

 

<Parameter>
<Name>FillColor</Name>
<Text>Couleur du remplissage</Text>
<Value>-1</Value>
<ValueType>Color</ValueType>
<Visible>FillCheckBox == True</Visible>
</Parameter>

Dans Allplan, j’obtiens :

Enfin, je vais préparer dans un autre onglet les choix pour annoter mon poteau avec les mêmes réglages vus dans les exemples 2D :

<Page>

<Name>Page2</Name>
<Text>Annotation</Text>

 

<Parameter>

<Name>ShowTextCheckBox</Name>
<Text>Afficher la légende</Text>
<Value>False</Value>

<ValueType>CheckBox</ValueType>

</Parameter>

 

<Parameter>

<Name>TextExpander</Name>

<Text>Format</Text>

<ValueType>Expander</ValueType>
<Visible>ShowTextCheckBox == True</Visible>

 

<Parameter>
<Name>TextCommonProperties</Name>
<Text></Text>
<Value></Value>
<ValueType>CommonProperties</ValueType>
</Parameter>

 

<Parameter>
<Name>TextSeparator</Name>
<ValueType>Separator</ValueType>
</Parameter>

 

<Parameter>
<Name>TextHeight</Name>
<Text>Hauteur</Text>
<Value>4</Value>
<ValueType>Length</ValueType>
</Parameter>

 

<Parameter>
<Name>TextAlignment</Name>
<Text>Alignement</Text>
<Value>Aligner à Gauche</Value>
<ValueList>Aligner à Gauche|Centrer|Aligner à Droite</ValueList>
<ValueType>StringComboBox</ValueType>
</Parameter>

 

<Parameter>
<Name>TextOrigin</Name>
<Text> </Text>
<Value>Point3D(0, -1000, 0)</Value>
<ValueType>Point3D</ValueType>
<Visible>False</Visible>
</Parameter>

 

</Parameter>

</Page>

La mise en place d’une légende a été étudiée dans ce chapitre, je vous invite à le relire pour plus de détails sur cette partie.

Ici j’ai complété avec un autre champ CommonProperties dédié au texte (pour son layer, couleur, …)

Voici le fichier complet :

2) Script Principal

Je commence par importer les différents modules nécessaires à la bonne exécution du script :

import math

 

import NemAll_Python_BaseElements as BaseElements
import NemAll_Python_BasisElements as BasisElements
import NemAll_Python_Geometry as Geometry
import NemAll_Python_IFW_ElementAdapter as ElementAdapter
import NemAll_Python_IFW_Input as IFWInput

 

from BuildingElement import BuildingElement
from BuildingElementAttributeList import BuildingElementAttributeList
from CreateElementResult import CreateElementResult
from PythonPartUtil import PythonPartUtil

 

from HandlePropertiesService import HandlePropertiesService
from HandleDirection import HandleDirection
from HandleParameterData import HandleParameterData
from HandleParameterType import HandleParameterType
from HandleProperties import HandleProperties

A noter : j’insère dès à présent le module math

Les 2 fonctions check_allplan_version et move_handle sont identiques aux exemples précédents, je ne reviens pas ici sur leur fonctionnement pour aller regarder directement create_element.

Je commence par initialiser mon PythonPart  avec notamment sa liste d’objets à créer (model_ele_list), ses poignées (handle_list) ainsi que la liste de ses attributs (attr_list) :

model_ele_list = []
handle_list = []

 

attr_list = BuildingElementAttributeList()
pyp_util = PythonPartUtil()

Je récupère ensuite les informations de mon objet 3D depuis la palette Allplan, avec d’abord le repère :

column_id = build_ele.ColumnId.value

la classe de béton :

column_concrete_gr_value = build_ele.ConcreteGrade.value

A noter : Allplan renvoie la valeur de la classe sous forme d’un entier (C25/30 => 4 par exemple), il nous faut donc mettre en place un dictionnaire pour associer cet entier à son équivalent en texte :

concrete_grade_dict = {1: ‘C12/15’,
                2: ‘C16/20’,
                3: ‘C20/25’,
                4: ‘C25/30’,
                5: ‘C30/37’,
                6: ‘C35/45’,
                7: ‘C40/50’,
                8: ‘C45/55’,
                9: ‘C50/60’,
                10: ‘C55/67’,
                11: ‘C60/75’,
                12: ‘C70/85’,
                13: ‘C80/95’,
                14: ‘C90/105’,
                15: ‘C100/115’,
                }
column_concrete_gr = concrete_grade_dict[column_concrete_gr_value]

Je récupère l’information sur la forme souhaitée :

choice = build_ele.ChoiceRadioGroup.value

les dimensions saisies :

column_length = build_ele.ColumnLength.value
column_thickness = build_ele.ColumnThick.value
column_radius = build_ele.ColumnRadius.value
column_height = build_ele.ColumnHeight.value

ainsi que le propriétés de rendu :

if build_ele.UseGlobalProperties.value:
        com_prop = BaseElements.CommonProperties()
        com_prop.GetGlobalProperties()
else:
        com_prop = build_ele.CommonProperties.value

le hachurage :

has_hatch = build_ele.HatchCheckBox.value
hatch_prop = BasisElements.HatchingProperties()
hatch_prop.HatchID = build_ele.HatchStyle.value

et le remplissage :

has_fill = build_ele.FillCheckBox.value
fill_prop = BasisElements.FillingProperties()
fill_prop.FirstColor = BaseElements.GetColorById(build_ele.FillColor.value)

Comme vu auparavant, le style de texte pour la légende :

is_showing_annotation = build_ele.ShowTextCheckBox.value

 

text_com_prop = BaseElements.CommonProperties()
text_com_prop = build_ele.TextCommonProperties.value

 

text_dict = {« Aligner à Gauche » : BasisElements.TextAlignment.eLeftMiddle,
        « Centrer » : BasisElements.TextAlignment.eMiddleMiddle,
        « Aligner à Droite » : BasisElements.TextAlignment.eRightMiddle
        }

 

text_prop = BasisElements.TextProperties()
text_prop.Height = text_prop.Width = build_ele.TextHeight.value
text_prop.Alignment = text_dict[build_ele.TextAlignment.value]

 

text_origin = build_ele.TextOrigin.value

A noter : là aussi, j’utilise un dictionnaire pour faire le lien entre une saisie utilisateur (une chaîne de caractère) et un paramètre d’alignement.

Je crée mon PythonPart et je renvoie l’ensemble de mon objet :

model_ele_list = pyp_util.create_pythonpart(build_ele)

 

return CreateElementResult(model_ele_list, handle_list)

Je quitte temporairement ma fonction create_element afin de préparer mes classes.

En effet nous avons déjà évoqué la puissance de la POO (Programmation Orientée Objet) et là encore cette technique va nous aider grandement dans notre code…

  • Classe Objects3D

Je commence par définir ma classe mère Objects3D avec notamment les fonctions dont j’aurais besoin :

  1. calcul des dimensions pour les attributs ;
  2. création de la géométrie ;
  3. création du contour de remplissage/hachurage ;
  4. ajout au rendu d’Allplan.

class Objects3D:

 

def __init__(self, object_prop):
        self.object_prop = object_prop
        self.geo = None

 

def calcul_dimensions(self):
        pass

 

def create_geo(self):
        pass

 

def create_hatch_geo(self):
        pass

 

def add_view(self):
        object_3d = BasisElements.ModelElement3D(self.object_prop, self.geo)

 

return object_3d

  • Classe Handle

Dito l’exemple précédent, je mets en place une classe pour mes futures poignées :

class Handle:

 

def __init__(self,
        handle_id,
        handle_point,
        ref_point,
        handle_param_data,
        handle_move_dir,
        handle_info_text):

 

self.handle_id = handle_id
self.handle_point = handle_point
self.ref_point = ref_point
self.handle_param_data = handle_param_data
self.handle_move_dir = handle_move_dir
self.handle_info_text = handle_info_text

  • Classe Cuboid

Hypothèse par défaut dans la forme de mon poteau, je prépare avec une classe enfant mon poteau rectangulaire.

class Cuboid(Objects3D):

def __init__(self,
        object_prop,
        column_length,
        column_thick,
        column_height):

Objects3D.__init__(self, object_prop)

self.column_length = column_length
self.column_thick = column_thick
self.column_height = column_height
self.name_dim = f »{round(column_length / 10)}x{round(column_thick / 10)} »

A noter : name_dim sera un des champs utilisés pour la légende rappelant ici la longueur et la largeur (en cm)

sans oublier la configuration des poignées (ici 3 pour la longueur, la largeur et la hauteur) :

self.handles_prop = [Handle(« ColumnLengthHandle »,
        Geometry.Point3D(self.column_length, 0, 0),
        Geometry.Point3D(),
        « ColumnLength« ,
        HandleDirection.X_DIR,
        « Longueur »
        ),
        Handle(« ColumnThickHandle »,
        Geometry.Point3D(self.column_length, self.column_thick, 0),
        Geometry.Point3D(self.column_length, 0, 0),
        « ColumnThick« ,
        HandleDirection.Y_DIR,
        « Largeur »
        ),
        Handle(« ColumnHeightHandle »,
        Geometry.Point3D(0, 0, self.column_height),
        Geometry.Point3D(),
        « ColumnHeight« ,
        HandleDirection.Z_DIR,
        « Hauteur »
        )
]

Ensuite je lance le calcul des différentes dimensions à rentrer dans les futurs attributs avec calcul_dimensions.

Pour plus de flexibilité, je concatène les résultats dans un tuple :

def calcul_dimensions(self):
length = self.column_length * 1e-3
thickness = self.column_thick * 1e-3
radius = 0
height = self.column_height * 1e-3
surface = length * thickness
volume = surface * height

 

return (length, thickness, radius, height, surface, volume)

A noter :

  • mon poteau étant de forme rectangulaire, je spécifie ici une valeur de rayon égale à 0 ;
  • je fais attention aux unités, en effet le champ length dans la palette renvoie des valeurs en mm.

Je génère la géométrie de mon poteau avec create_geo en utilisant CreateCuboid:

def create_geo(self):

 

placement = Geometry.AxisPlacement3D(Geometry.Point3D(),
                      Geometry.Vector3D(1, 0, 0),
                      Geometry.Vector3D(0, 0, 1)
                        )
self.geo = Geometry.BRep3D.CreateCuboid(placement,
                self.column_length,
                self.column_thick,
                self.column_height
                )

A noter : on retrouve bien nos 3 dimensions clés (longueur, largeur et hauteur) placées suivant un axe bien défini

Vient ensuite le contour de mon remplissage ou hachurage grâce à CreateRectangle :

def create_hatch_geo(self):

 

hatch_geo = Geometry.Polygon2D.CreateRectangle(Geometry.Point2D(),
                        Geometry.Point2D(self.column_length, self.column_thick)
                        )

 

return hatch_geo

A noter : de nouveau on note nos 2 dimensions clés (longueur et largeur) pour la création du contour

  • Classe Cylinder

Seconde hypothèse pour mon poteau, voici la classe enfant pour la forme circulaire.

Comme précédemment je pars de ma classe mère et j’adapte mon cas :

class Cylinder(Objects3D):

 

def __init__(self,
        object_prop,
        column_rad,
        column_height):

Objects3D.__init__(self, object_prop)
self.name_dim = f »Ø{round(column_rad / 10)} »
self.column_radius = column_rad
self.column_height = column_height

avec mes poignées (une pour le rayon et une autre pour la hauteur) :

 self.handles_prop = [Handle(« ColumnRadiusHandle »,
        Geometry.Point3D(self.column_radius, 0, 0),
        Geometry.Point3D(),
        « ColumnRadius« ,
        HandleDirection.X_DIR,
        « Rayon »
        ),
        Handle(« ColumnHeightHandle »,
        Geometry.Point3D(0, 0, self.column_height),
        Geometry.Point3D(),
        « ColumnHeight« ,
        HandleDirection.Z_DIR,
        « Hauteur »
        )
        ]

Je calcule les valeurs des attributs géométriques :

def calcul_dimensions(self):
length = 0
thickness = 0
radius = self.column_radius * 1e-3
height = self.column_height * 1e-3
surface = math.pi * radius ** 2
volume = surface * height

 

return (length, thickness, radius, height, surface, volume)

A noter :

  • mon poteau étant de forme cylindrique, je spécifie ici une valeur de longueur et largeur à 0 ;
  • je fais toujours attention aux unités, le champ length dans la palette renvoie des valeurs en mm.

Je crée mon volume avec Cylinder3D :

def create_geo(self):

 

placement = Geometry.AxisPlacement3D(Geometry.Point3D(),
                                Geometry.Vector3D(1, 0, 0),
                                Geometry.Vector3D(0, 0, 1)
                                )

 

self.geo = Geometry.Cylinder3D(placement,
                                self.column_radius,
                                self.column_radius,
                                Geometry.Point3D(0, 0, self.column_height)
                                )

A noter : on retrouve bien nos 2 dimensions clés : le rayon (appelé 2 fois pour le grand et le petit rayon du cylindre) et un point 3D allant chercher la hauteur. Là encore le tout est positionné sur un axe bien défini

Dernière étape pour cette classe enfant, le contour de remplissage :

def create_hatch_geo(self):

line = Geometry.Line3D(0, 0, 0, self.column_radius, 0, 0)

 

angle = Geometry.Angle()
angle.Deg = 10
rotation_axis = Geometry.Line3D(Geometry.Point3D(),
                                        Geometry.Point3D(0, 0, 1)
                                        )
transformation_matrix = Geometry.Matrix3D()

hatch_geo = Geometry.Polygon2D()

 

for i in range(36):
        transformation_matrix.SetRotation(rotation_axis, angle)
        line = Geometry.Transform(line, transformation_matrix)
        hatch_geo += Geometry.Point2D(line.EndPoint.X, line.EndPoint.Y)

 

hatch_geo += hatch_geo.StartPoint

 

return hatch_geo

A noter :

La fonction HatchingElement que nous utiliserons nécessite un polygone, il nous faut donc le construire depuis le rayon.

Le principe est simple : je définis une ligne de construction avec comme longueur le rayon, j’ajoute à mon polygone l’extrémité de ma ligne en lui appliquant dans une boucle une rotation de 10° à chaque fois.

Je n’oublie pas de bien clore mon polygone en revenant sur mon point initial.

  • Fonction create_element

Toutes mes classes sont prêtes, il ne reste plus qu’à finaliser ma fonction create_element.

Je construis mon poteau en appelant la classe souhaitée :

if choice == « rectangle »:
        my_column = Cuboid(com_prop, column_length, column_thickness, column_height)
else:
        my_column = Cylinder(com_prop, column_radius, column_height)

 

my_column.create_geo()

Je l’ajoute à mon document Allplan :

pyp_util.add_pythonpart_view_2d3d(my_column.add_view())

Je crée mes poignées :

for item in my_column.handles_prop:
        handle = HandleProperties(item.handle_id,
                item.handle_point,
                item.ref_point,
                [HandleParameterData(item.handle_param_data, HandleParameterType.POINT_DISTANCE)],
                item.handle_move_dir
                )
        handle.info_text = item.handle_info_text
        handle_list.append(handle)

A noter : la création des poignées ayant déjà été vues dans des exemples précédents, je ne redétaille pas ici cette commande

Arrive ensuite la légende :

if is_showing_annotation:
        text = f »{column_id} {my_column.name_dim} »
        if column_concrete_gr_value > 4:
              text += f »\n{column_concrete_gr} »
        origin = Geometry.Point2D(text_origin)
        pyp_util.add_pythonpart_view_2d(BasisElements.TextElement(text_com_prop, text_prop, text, origin))

        text_handle = HandleProperties(« Text »,
                text_origin,
                Geometry.Point3D(),
                [HandleParameterData(« TextOrigin », HandleParameterType.POINT, False)],
                HandleDirection.XYZ_DIR
                )

        text_handle.handle_type = IFWInput.ElementHandleType.HANDLE_SQUARE_RED
        text_handle.info_text = « Origine du texte »

 

        handle_list.append(text_handle)

A noter :

La légende apparaît si la case est cochée.

Elle commence par le repère du poteau suivi de ses dimensions. Si le béton est de classe améliorée (> C25/30), on l’indique également.
Enfin, on définit un point d’accroche pour déplacer l’annotation si besoin.

On ajoute les hachures avec HatchingElement :

if has_hatch:
pyp_util.add_pythonpart_view_2d(BasisElements.HatchingElement(com_prop, hatch_prop, my_column.create_hatch_geo()))

Ainsi que le remplissage avec FillingElement :

if has_fill:
pyp_util.add_pythonpart_view_2d(BasisElements.FillingElement(com_prop, fill_prop, my_column.create_hatch_geo()))

A noter : si la condition est validée, on va générer une hachure ou un remplissage avec leurs propriétés respectives et le contour créé dans la classe enfant

On regarde la mise en place des attributs en commençant par une nouveauté Allplan 2024 : les Ensembles d’Attributs (ici Poteau)

# Attribute set object @18358@

attr_list.add_attribute(18358, « Column »)

puis le Métier (ici 13 renvoie « Béton et béton armé »)

# Trade @209@
attr_list.add_attribute(209, 13)

mettre 0 au Statut retourne « Nouvelle construction »

# Statut @49@
attr_list.add_attribute(49, 0)

on indique que notre poteau sera Porteur

# Load bearing @573@
attr_list.add_attribute(573, 1)

vient ensuite la Classe de Béton

# Concrete grade @1905@
attr_list.add_attribute(1905, column_concrete_gr)

on renseigne l’ensemble des Propriétés Géométriques calculées dans les classes enfant

# Geometry
length, thickness, radius, height, surface, volume = my_column.calcul_dimensions()

 

attr_list.add_attribute(220, length)
attr_list.add_attribute(221, thickness)
attr_list.add_attribute(107, radius)
attr_list.add_attribute(222, height)
attr_list.add_attribute(293, surface)
attr_list.add_attribute(226, volume)

attr_list.add_attributes_from_parameters(build_ele)
pyp_util.add_attribute_list(attr_list)

A noter :

Ici, nous créons une liste d’attributs à assigner avec la commande add_attribute en spécifiant l’ID de l’attribut en question et sa valeur.

On rajoute ensuite les attributs indiqués depuis la palette et on injecte cet ensemble à notre PythonPart.

Voici le fichier complet :

Dans cet exemple, nous avons rappelé beaucoup de fonctions utilisées précédemment et utilisé une nouvelle fois la puissance de la POO.

Avec l’API PythonParts, nous voyons qu’Allplan nous propose pléthore de possibilités que nous continuerons d’approfondir tout au long de ce chapitre.

0 commentaires

Soumettre un commentaire

Objects3D V2.0

Nouvelle étape dans la modélisation de notre PythonPart "Poteau en Béton Armé", regardons aujourd'hui comment configurer les ancrages de notre objet 3D. Par ancrage je pense tout particulièrement à...

Objects2D V3.0

Dernière étape pour cet exemple de PythonParts, je vous propose de mettre en place une légende pour notre objet. Cette dernière devra reprendre les informations suivantes : le nom de mon objet ; le...

Objects2D V2.0

Dans le précédent article, nous avons vu comment préparer notre code en POO, voyons aujourd'hui comment en exploiter le potentiel avec ce nouvel exemple. En effet, nous allons compléter notre...

Objects2D V1.0

Nous allons commencer à construire des objets plus complexes sur Allplan, mais avant tout, un mot sur la Programmation Orientée Objet (POO)...1) Programmation Orientée ObjetLa Programmation Orientée...

HelloWorld V3.0

Dernière étape pour notre 1er exemple de script HelloWorld, nous allons maintenant voir comment personnaliser le rendu de notre objet.1) Script InterfaceDe retour dans notre palette, je vais tout...

HelloWorld V2.0

Dans l'article précédent, nous avons appris comment générer un objet (une ligne de longueur fixe) via l'API PythonParts. Aujourd'hui je vais vous montrer la mise en place de poignées pour notre...

HelloWorld V1.0

HelloWorld est par tradition écrit pour donner un exemple d'un langage de programmation. Nous ne ferons pas exception ici avec l'écriture de notre 1er script. Le but est simple, créer une ligne de...

Structure des PythonParts

Allplan est installé, votre IDE est prêt... parfait, voyons en détail le fonctionnement des PythonParts.1) Description des fichiersPour fonctionner, un PythonPart a besoin d'au moins 2 fichiers :...

Introduction

Dans cette série d'articles, nous allons étudier l'édition de scripts en langage de programmation Python pour le logiciel Allplan.Pour vous permettre de bien suivre ces tutoriels, je vais partir sur...