Table of Contents
VBA CATIA Part Design – HybridShapeFactory
In my last post we went through how to create geometrical sets, and how to navigate the documentation while writing code. In this post we will focus on creating basic wireframe using the HybridShapeFactory.
VBA Editor
There are lots of IDE Interactive Development Environments, sounds complex but its just an application that helps us write code. In reality if you have the documentation then you could use NotePad ++, Sublime Text, or another Text Editor. I use the VBA Editor that comes with CATIA, which also comes with most of the Microsoft Office products. This means once you understand how to write basic VBA you can do it with any of the Office products or other apps that provide VBA API. In addition you can write apps that talk to other apps for example you could write a Excel VBA app that talks to CATIA or a CATIA app that talks to Excel and PowerPoint.
To start the VBA Editor press Alt+F11 or Tools->Macro->Visual Basic Editor.
We should see a new Visual Basic Application Editor start. The first thing we have to do is create a new Macro Library, this is achieved by selecting File->Macro Libraries…
In the Macro Libraries Window select Create New Library, key in a Path into the Create a New VBA Project window, then select Ok and then Close.
In the VBA Editor we can now see the new Project.
Now we can Insert a New Module, this will store our code. We will investigate UserForm and Class Module’s another day.
Within the New Module lets start by adding in the standard default CATIA Main Sub-Routine.
Creating a New Part Document
Just as before in the last Post we want to create a new Part Document, but unlike the last post we want to only create a new PartDocument is the Current Active Document is not a PartDocument. So Lets Start of with the previous code.
Note:- In the Module within the VBA IDE just type in Sub CATMain and hit Enter. It will auto complete and add the End Sub automatically.
Sub CATMain() Dim ioCATIA As Application Set ioCATIA = CATIA Dim ioDocuments As Documents Set ioDocuments = CATIA.Documents Dim ioPartDocument As PartDocument Set ioPartDocument = ioDocuments.Add("Part") End Sub
In the IDE we can just hit the Green Play button and the code will execute, and we will get a new PartDocument.
The problem is that every time we run the code we will get a new PartDocument. So lets address that first, if we look at the Application Objects Property’s and Methods we will find a Property called ActiveDocument. This will always return the ActiveDocument if there is one in the session. It doesn’t mean that its a PartDocument though it could be a Drawing or Product or something else.
It get around this we will equate a PartDocument object to the ActiveDocument, and then trap the error. If there is an error we know the Active Document is not a PartDocument and if there is no error then we know that the ActiveDocument is a PartDocument. To do this we will use two statements: On Error Resume Next, and On Error Goto 0.
On Error Resume Next, tells the compiler that if any line after this causes an Error ignore it and continue tot he next line.
On Error Goto 0, tells the compiler to stop ignoring Errors and reset the Error Code to 0, i.e. no error.
Sub CATMain() Dim ioCATIA As Application Set ioCATIA = CATIA On Error Resume Next Dim ioPartDocument As PartDocument Set ioPartDocument = ioCATIA.ActiveDocument On Error Goto 0 End Sub
We can now check the state of the Error handler by checking if the current Error Number is not Zero. If this is the case we will create a new PartDocument otherwise we know that we have successfully equated our variable PartDocument to an Active PartDocument in the session.
Sub CATMain() Dim ioCATIA As Application Set ioCATIA = CATIA On Error Resume Next Dim ioPartDocument As PartDocument Set ioPartDocument = ioCATIA.ActiveDocument If (Err.Number <> 0) Then Set ioPartDocument = ioCATIA.Documents.Add("Part") End If On Error GoTo 0 End Sub
Adding a New Geometrical Set
Similar to this we want to create a new geometrical set only if one does not already exist, that called “Points”. First we have to navigate to the Part object and then to the HybridBodies object, this can be seen in the last post.
Sub CATMain() Dim ioCATIA As Application Set ioCATIA = CATIA On Error Resume Next Dim ioPartDocument As PartDocument Set ioPartDocument = ioCATIA.ActiveDocument If (Err.Number <> 0) Then Set ioPartDocument = ioCATIA.Documents.Add("Part") End If On Error GoTo 0 Dim ioPart As Part Set ioPart = ioPartDocument.Part Dim ioHybridBodies As HybridBodies Set ioHybridBodies = ioPart.HybridBodies End Sub
We can use the same trick as before, by turning off the Error Handler trying to get a Geometrical Set called “Points” and then checking for an Error. If an Error occurs we know we need to create the Geometrical Set, other wise we know that our variable will be equated to an existing Geometrical Set called “Points”. Then we will reset the Error Handler and carry on.
Dim ioPart As Part Set ioPart = ioPartDocument.Part Dim ioHybridBodies As HybridBodies Set ioHybridBodies = ioPart.HybridBodies On Error Resume Next Dim ioHybridBody As HybridBody Set ioHybridBody = ioHybridBodies.Item("Points") If (Err.Number <> 0) Then Set ioHybridBody = ioHybridBodies.Add() ioHybridBody.Name = "Points" End If On Error GoTo 0 End Sub
HybridShapeFactory
Within the Automartion.chm within the PartDocument object we can see all of the objects that can be navigated within the PartDocument. One of these objects is an Abstract Object called Factory and below this we can see associated to this are thee Factories: ShapeFactory, HybridShapeFactory and InstanceFactory. We don’t have to Navigate across an Abstract object this just shows us the Generic type that can be equated to anyone of the three Factory’s, this is why it’s called an Abstract object.
So lets start of by navigating down to the HybridShapeFactory.
If (Err.Number <> 0) Then Set ioHybridBody = ioHybridBodies.Add() ioHybridBody.Name = "Points" End If On Error GoTo 0 Dim ioHybridShapeFactory As HybridShapeFactory Set ioHybridShapeFactory = ioPart.HybridShapeFactory End Sub
If we look at the Automation.chm and navigate into the HybridShapeFactory object we can see all of the Property’s and Methods and there are a lot. We can see that we can create nearly every type of wireframe element, but we will start of with Points, specifically PointCoordinate.
Again if we navigate into the hyperlink for this object, we can see that it is a Function and it returns a HybridShapePointCorrd object, and it requires three inputs for X, Y, and Z as Type Double. Double is just a numeric value.
Since its a Function and returns a specific object type we must declare a variable of this type (HybridShapePointCoord) just as before and then we can equate it by using the AddNewPointCoord method shown in the documentation.
On Error GoTo 0 Dim ioHybridShapeFactory As HybridShapeFactory Set ioHybridShapeFactory = ioPart.HybridShapeFactory Dim ioHybridShapePointCoord As HybridShapePointCoord Set ioHybridShapePointCoord = ioHybridShapeFactory.AddNewPointCoord(10, 20, 30) End Sub
However if we run this code, the point does not show in the specification tree. That’s understandable we haven’t told it where in the specification tree it should go. First its advisable to Compute the new HybridShape and then add it to the Specification Tree, this way we don’t have to do an Update of the complete Part, but i will still show you how to do that.
The Compute method is hidden away at the MechModInterfaces.HybridShape object, so lets select on the Hyperlink at the Top of the HybridShapePointCoord documentation.
Here we can see the Compute Method, so again lets select the Hyperlink to view the documentation on the method.
This Method is just a Sub routine, and it does not require any inputs, so we can just simply call it to pre-update compute the hybridshape.
Dim ioHybridShapeFactory As HybridShapeFactory Set ioHybridShapeFactory = ioPart.HybridShapeFactory Dim ioHybridShapePointCoord As HybridShapePointCoord Set ioHybridShapePointCoord = ioHybridShapeFactory.AddNewPointCoord(10, 20, 30) ioHybridShapePointCoord.Compute End Sub
Now that’s out of the way we can add the point to the Specification tree, this is done by using a method associated to the HybridBody object AppendHybridShape. Let’s select the Methods Hyperlink to see if there is an example.
The Method is a Sub-Routine so it does not return anything we can simply use it. However, we have to pass the HybridShape that we want to append to the method.
Now the Point will display correctly in the specification tree within the geometrical set earlier created.
Dim ioHybridShapePointCoord As HybridShapePointCoord Set ioHybridShapePointCoord = ioHybridShapeFactory.AddNewPointCoord(10, 20, 30) ioHybridShapePointCoord.Compute ioHybridBody.AppendHybridShape ioHybridShapePointCoord End Sub
If the part requires an update, then we can use the Update method which is found on the Part object. However, this should not be necessary since the point was pre-computed.
Dim ioHybridShapePointCoord As HybridShapePointCoord Set ioHybridShapePointCoord = ioHybridShapeFactory.AddNewPointCoord(10, 20, 30) ioHybridShapePointCoord.Compute ioHybridBody.AppendHybridShape ioHybridShapePointCoord ioPart.Update End Sub
Importing Points From a CSV File
In the last post we read a text file and created a geometrical set structure. This time we will read a text file and create points and place them in the correct geometrical set.
Our file will have the following structure.
Geometrical Set Parent, Geometrical Set, X , Y , Z , Point Name.
So lets begin.
Based on the last post we know how to read a file, so lets get that code implemented.
Sub CATMain() Dim ioCATIA As Application Set ioCATIA = CATIA On Error Resume Next Dim ioPartDocument As PartDocument Set ioPartDocument = ioCATIA.ActiveDocument If (Err.Number <> 0) Then Set ioPartDocument = ioCATIA.Documents.Add("Part") End If On Error GoTo 0 Dim ioPart As Part Set ioPart = ioPartDocument.Part Dim ioHybridBodies As HybridBodies Set ioHybridBodies = ioPart.HybridBodies 'Dim ioFileSystem As FileSystem Dim ioFileSystem As Variant Set ioFileSystem = ioCATIA.FileSystem Dim ioFile As File Set ioFile = ioFileSystem.GetFile("C:\Users\ma_je\Documents\GeoSetFile.txt") Dim ioTextStream As TextStream Set ioTextStream = ioFile.OpenAsTextStream("ForReading") Dim ioHybridBody As HybridBody Do While ioTextStream.AtEndOfStream = False Dim ioLineString As String ioLineString = ioTextStream.ReadLine Loop ioTextStream.Close End Sub
Now we have the basic layout lets look at what the text file could look like.
First we will spit the comma separated string into an array.
Do While ioTextStream.AtEndOfStream = False Dim ioLineString As String ioLineString = ioTextStream.ReadLine Dim ioArray() As String ioArray = Split(ioLineString, ",") Loop
Just as before we will use a Dictionary to keep track of the Geometrical Sets, so lets add that to the top of the VBA.
Sub CATMain() Dim dict As Scripting.Dictionary Set dict = New Scripting.Dictionary
Now we can work on the core logic, lets start of with the Geometrical Set logic. First we will check to see if the value of the Parental Geometrical Set is NULL. If it is then we have to add the New Geometrical Set tot he Root of the Part otherwise we will ahve to get the Parent Geometrical Set from the dictionary.
Do While ioTextStream.AtEndOfStream = False Dim ioLineString As String ioLineString = ioTextStream.ReadLine Dim ioArray() As String ioArray = Split(ioLineString, ",") If (ioArray(0) = "NULL") Then Else End If Loop
Just as before in the last Post we will directly add the New HybridBody if the Parental Geometrical Set is NULL. Otherwise we will get the Parental Geometrical Set from the Dictionary and then Create the New HybridBody within the Parental Geometrical Set.
Do While ioTextStream.AtEndOfStream = False Dim ioLineString As String ioLineString = ioTextStream.ReadLine Dim ioArray() As String ioArray = Split(ioLineString, ",") If (ioArray(0) = "NULL") Then Set ioHybridBody = ioHybridBodies.Add() dict.Add ioArray(1), ioHybridBody Else Dim ioParentGeoSet As HybridBody Set ioParentGeoSet = dict.Item(ioArray(0)) If (dict.Exists(ioArray(1)) = False) Then Set ioHybridBody = ioParentGeoSet.HybridBodies.Add() dict.Add ioArray(1), ioHybridBody Else Set ioHybridBody = dict.Item(ioArray(1)) End If End If ioHybridBody.Name = ioArray(1) Loop ioTextStream.Close End Sub
Now we have the Geometrical Set Code taken care of we can create the point, first lets create an object for the HybridShapeFactory, and well do this before we get into the loop.
Dim ioTextStream As TextStream Set ioTextStream = ioFile.OpenAsTextStream("ForReading") Dim ioHybridBody As HybridBody Dim ioHybridShaoeFactory As HybridShapeFactory Set ioHybridShaoeFactory = ioPart.HybridShapeFactory Do While ioTextStream.AtEndOfStream = False
Finally, we will check the three parts of the Array that contain the X, Y, Z values, to ensure that they are all Not NULL. Then we will ahve to convert the String Values to Doubles this is done with the CDbl function which takes in a string and returns a Double value. Then we can use these variables of Type Double to create the Point as we did above.
ioHybridBody.Name = ioArray(1) If (ioArray(2) <> "NULL" And ioArray(3) <> "NULL" And ioArray(4) <> "NULL") Then Dim ioHybridShapePointCoord As HybridShapePointCoord Dim X, Y, Z As Double X = CDbl(ioArray(2)) Y = CDbl(ioArray(3)) Z = CDbl(ioArray(4)) Set ioHybridShapePointCoord = ioHybridShaoeFactory.AddNewPointCoord(X, Y, Z) ioHybridShapePointCoord.Name = ioArray(5) ioHybridShapePointCoord.Compute ioHybridBody.AppendHybridShape ioHybridShapePointCoord End If Loop ioTextStream.Close End Sub
Happy Coding.