We will build more complex objects on Allplan software, but first at all a word about Object Oriented Programming (OOP)…

1) Object Oriented Programming

Object Oriented Programming (called OOP) is a way of organizing your code. It allows us to create entities called objects that we can manipulate.

With OOP, an object is an instance of a class, which is a data structure defining the attributes (variables) and methods (functions) associated with that object.

Objects can interact with each other by exchanging messages, allowing for simplified communication and modular code organization.

OOP thus makes it possible to create more flexible, maintainable and scalable programs by encapsulating complexity, facilitating code reuse and promoting modularity.

Python is a programming language perfectly adapted to OOP, now let’s see how to adapt our code…

2) GUI Script

Our work will mainly concern the Python code, so there are no major changes on the .pyp file except for the link with the main script :

<Script>
<Name>APIHub\objects_2D.py</Name>
<Title>Objects2D</Title>
<Version>1.0</Version>
</Script>

my variable for line’s length has been named correctly for the next examples :

 <Parameter>
<Name>LineLength</Name>
<Text>Longueur</Text>
<FontFaceCode>4</FontFaceCode>
<Value>1000.0</Value>
<ValueType>Length</ValueType>
</Parameter>

Please note : I have inserted the FontFaceCode field which allows to customize the text (here 4 underlines the text)

You can look at this page for more informations.

Here is the complete source code :

3) Main Script

  • Import modules

Like any Python file, we start by import all the modules necessary for the proper script’s execution :

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

 

from BuildingElement import BuildingElement
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

  • Check Allplan Version

No change for the basic function check_allplan_version, by default all versions of Allplan are allowed :

def check_allplan_version(build_ele, version):

 

# Support all versions
return True

  • Use Handles

Ditto for the “listening” of the handles, no change :

def move_handle(build_ele, handle_prop, input_pnt, doc):

 

HandlePropertiesService.update_property_value(build_ele, handle_prop, input_pnt)

return create_element(build_ele, doc)

  • Create elements

As seen previously, create_element is the 2nd required function for standards PythonParts.

I declare my objects’ list as well as my handles’ list which I also return at the end of the function :

def create_element(build_ele, doc):

 

model_ele_list = []
handle_list = []

return CreateElementResult(model_ele_list, handle_list)

Then I declare my variable that will be used to create PythonParts : pyp_util.

I also assign my elements’ list to this function :

pyp_util = PythonPartUtil()

# Create pythonpart
model_ele_list = pyp_util.create_pythonpart(build_ele)

As in the previous examples, I get the different parameters from the Allplan’s palette :

# Extract palette parameter values
line_length = build_ele.LineLength.value

 

 # Define common properties
if build_ele.UseGlobalProperties.value:
com_prop = BaseElements.CommonProperties()
com_prop.GetGlobalProperties()
else:
com_prop = build_ele.CommonProperties.value

Please note : previously, the condition was set up for a personalized rendering of our object.

  • Parent Class : Objects2D

This class will be generic to all our 2D objects, so I will use it as a parent class.

I set it the following variables : rendering properties then, I initialize the geometry of my object: self.geo.

class Objects2D:

 

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

I prepare my function to generate my object’s geometry.

This function will depend on my object (line, rectangle, circle, …), so I leave it empty in my parent class.

def create_geo(self):
pass

Please note : in Python language, functions must have at least one instruction, so I place pass which has a null value.

Next comes creating the render of my object using the common properties (pen, color, etc.) and the object’s geometry :

def add_view(self):
object_2d = BasisElements.ModelElement2D(self.object_2d_prop, self.geo)
return object_2d

Before reviewing the handle’s implementation, here is a reminder on the syntax :

# Create the handles
handle = HandleProperties(

“LineLengthHandle”, # handle id
Geometry.Point3D(line_length, 0, 0), # handle point
Geometry.Point3D(), # reference point
[HandleParameterData(“LineLength”, HandleParameterType.POINT_DISTANCE)], # parameter id from the palette
HandleDirection.X_DIR # handle direction

)

handle.info_text = “Longueur” # text visible in Allplan
handle_list.append(handle)

We have 6 variables assigned for an unknown number of handles.

So I’m going to create a Handle class for managing these.

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

Please note : we find all of our variables explicitly named.

  • Child Class : Line2D

Directly linked to Object2D, we are going to create a Line2D class which will inherit all its properties, it’s called a child class.

class Line2D(Objects2D):

def __init__(self, object_2d_prop, line_length):
Objects2D.__init__(self, object_2d_prop)

 

self.line_length = line_length

 

self.handles_prop = [Handle(« LineLengthHandle »,
Geometry.Point3D(self.line_length, 0, 0),
Geometry.Point3D(),
« LineLength »,
HandleDirection.X_DIR,
« Longueur »
)
]

Please note :

  • Line2D takes all the Object2D variables and I complete with the line’s length : line_length.
  • we find our 6 variables specific to the line’s handle.

Then I generate my line’s geometry by overwriting my create_geo function :

 def create_geo(self):
self.geo = Geometry.Line2D(0, 0, self.line_length, 0)

  • Functions Call

Last step, I go back to my create_element function to call everything I need to create my object (here a line) :

  • geometry creation ;
  • rendered in plan view ;
  • creation of the handles.

As all these steps have been properly prepared in the classes, the syntax is just :

  • Geometry Creation

# Create 2D object
object_2d = Line2D(com_prop, line_length)
object_2d.create_geo()

  • Rendered

# Add object to view
pyp_util.add_pythonpart_view_2d(object_2d.add_view())

  • Creation of the Handles

# Create the handles
for item in object_2d.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)

Please note : we currently don’t know how many handles have to be created. Indeed, it will depend on the future object to be created.

So I prepare a loop with for…in for all the handle instances I need and then I add them to the list of my handles.

Here is the complete source code :

In this chapter, we have seen how to prepare our code in OOP with, in particular, parent class and child class management.

In the next article, this organization will make sense with the implementation of other 2D objects to create.

0 Comments

Submit a Comment

Objects3D V2.0

Next step for the modeling of our PythonPart “Reinforced Concrete Column”, today let's see how to configure the anchors of our 3D object. By anchoring I am particularly thinking of 2 types :...

Objects3D V1.0

New series in the PythonParts learning journey, let's delve into the modeling of a 3D object : a reinforced concrete column.1) GUI ScriptIn this example, we will set up the initial fields required...

Objects2D V3.0

Last step for this PythonParts example, I'll show you how to set up a legend for our object. This should include the following information : my object's name ; the name of a characteristic geometric...

Objects2D V2.0

In the previous article, we saw how to prepare our code in OOP, today let's see how to exploit its potential with this new example. Indeed, we are going to complete our PythonPart in order to...

HelloWorld V3.0

Last step for our HelloWorld script, we will see how to customize the rendering of our object.1) GUI ScriptBack in our palette, I first create a chapter to dissociate the geometric controls from...

HelloWorld V2.0

Previously, we learned how to create an object (a line with fixed length) via the PythonParts API. Today I'm going to show you how to set up handles for our HelloWorld script...1) GUI ScriptThe...

HelloWorld V1.0

HelloWorld is traditionally written to provide an example of a programming language. We will be no exception here with our first script's writing. The goal is simple, create a line with fixed...

Structure of PythonParts

Allplan is installed, your IDE is ready... perfect, let's see in detail how PythonParts work.1) Files' DescriptionTo work, a PythonPart needs at least 2 files : GUI File The interface file...

Introduction

In this series of articles, we'll study the editing of scripts in the Python programming language for the Allplan software.To allow you to follow these tutorials properly, I'm going to make a few...