Getting at Clusters

This section demonstrates how to create, access, and modify clusters and their elements on 3D objects. All of the code in this section belongs to one large script, but is presented in modules according to usage. The topics covered include:

Example: Accessing the cluster’s elements, parent, and type

Example: Create a cluster

Example: Find the cluster in the scene

Example: Add points to the cluster

Example: Remove points from the cluster

Example: Copying clusters

Example: Deleting clusters

Example: Accessing the clusters elements, parent, and type

A lot of the tasks when working with cluster involve using the cluster’s elements. You can access the elements through the SubComponent object (Cluster.CreateSubComponent). From there, you can access the 3D object that is parenting the cluster (SubComponent.Parent3DObject).

 

You can also access the elements through the Cluster.Elements property, which returns the collection of geometry indices as a ClusterElementCollection.

This function prints the name of the cluster’s parent, which elements it contains, and the type of elements it contains. The other examples in this section also refer to this function.

Function printClusterInfo( in_cluster )
   ' Make sure the inbound object is a valid cluster
   If TypeName( in_cluster ) = "Cluster" Then
       ' Get the cluster's elements
       Set oMembers = in_cluster.CreateSubComponent
       aIndices = oMembers.ElementArray

       ' Format its values
       sElementData = ""
       For i = 0 To UBound( aIndices )
          sElementData = sElementData & ", " & in_cluster.Type 
                                & "[" & aIndices(i) & "]"
       Next 
       sElementData = vbTab & vbTab & Right( sElementData, Len(sElementData)-2 )

       ' Print them out
       LogMessage "Current cluster contains these element(s) under the '" _
              & oMembers.Parent3DObject.Name & "' object:" & vbLf _
              & sElementData & vbLf
       LogMessage "=========================================================="

       printClusterInfo = True
   Else
       LogMessage "Object is not a valid cluster."
       printClusterInfo = False
   End If
End Function

Example: Create a cluster

This example demonstrates how to create a cluster (using the object model) from a 3D object (in this case, a grid).

 

This code snippet uses the printClusterInfo() function described in Example: Accessing the cluster’s elements, parent, and type.

After you create the grid, you can add a point (vertex) cluster on it using the Geometry.AddCluster method. Notice that you have to create the cluster on the Geometry object, not directly on the grid.

   ' Create the grid
   Set oGrid = ActiveSceneRoot.AddGeometry( "Grid", "MeshSurface", "wall" )

   ' You can use an array variable to save the point indices 
   aPointsForCluster = Array( 21,22,31,40,41 )

   ' The indices used in this method correspond to the indexing order of the 
   ' element for the 3D object
   Set oCluster = oGrid.ActivePrimitive.Geometry.AddCluster( _
                                siVertexCluster, _
                                "wallpaper", _
                                aPointsForCluster _
                            )

The printClusterInfo(oCluster) function displays the following message in the History Log of the Script Editor at this point:

'INFO : "Current cluster contains these element(s) under the 'wall' object:
       'pnt[21], pnt[22], pnt[31], pnt[40], pnt[41]
'"
'INFO : "=========================================================="

Example: Find the cluster in the scene

This step is not necessary if you have already created a cluster, but is provided simply as a demonstration of finding an existing cluster in the scene assuming you know only that you want the point cluster on a polymsh grid object.

 

This code snippet follows the one in Example: Create a cluster and uses the printClusterInfo() function described in Example: Accessing the cluster’s elements, parent, and type.

Just to make it interesting, let's add a couple more clusters.

   ' Add an edge cluster to the grid
   aEdgesForCluster = Array( 28,31,47,50,66 )
   Set oECls = oGrid.ActivePrimitive.Geometry.AddCluster( _
                                siEdgeCluster, _
                                "paint", _
                                aEdgesForCluster _
                              )

The printClusterInfo(oECls) function displays the following message in the History Log of the Script Editor at this point:

'INFO : "Current cluster contains these element(s) under the 'wall' object:
       'edge[28], edge[31], edge[47], edge[50], edge[66]
'"
'INFO : "=========================================================="

This piece of code adds a cube and makes another point cluster on it. Notice how you can use either an array variable or pass an array directly to the argument.

   ' Create a cube and add another point cluster to it
   Set oCube = ActiveSceneRoot.AddGeometry( "Cube", "MeshSurface", "chair" )
   Set oPCls = oCube.ActivePrimitive.Geometry.AddCluster( _
                                siVertexCluster, _
                                "seat", _
                                Array( 1,3,5,7 ) _
                              )

The printClusterInfo(oPCls) function displays the following message in the History Log of the Script Editor at this point:

'INFO : "Current cluster contains these element(s) under the 'chair' object:
       'pnt[1], pnt[3], pnt[5], pnt[7]
'"
'INFO : "=========================================================="

Now the fun begins! This piece gets each object with mesh geometry in the scene and then gets the cluster collection from each using the Geometry.Clusters property. Make sure to trap as many potential errors as you can, since you may be working with empty or invalid objects at some point.

   ' Using the X3DObject.FindChildren method and specifying the mesh family
   ' (3rd argument) returns a collection of all polygon mesh objects that 
   ' appear in the hierarchy under the scene root. From there we can find
   ' which one matches our criteria.
   Set oAllObjects = ActiveSceneRoot.FindChildren( , , siMeshFamily )

   ' Loop through the collection to find any Point clusters
   For Each obj In oAllObjects
       ' Get all the clusters on the mesh  geometry as a collection
       Set oAllClusters = obj.ActivePrimitive.Geometry.Clusters

       ' Loop through the collection to find any Point clusters
       For Each cls In oAllClusters
          ' Only deal with point clusters
          If cls.Type = "pnt" Then
              ' Get the one whose parent = grid 
              Set oPoint = cls.CreateSubComponent
              Set oParent = oPoint.Parent3DObject

              ' If it matches, grab it & run
              If oParent.IsKindOf( "Grid" ) Then
                 Set oCluster = cls
                 Exit For
              End If 
          End If
       Next
   Next

Example: Add points to the cluster

This example demonstrates how to add points to an existing point cluster. In this case, you have to use a mixture of the object model and scripting commands.

 

This code snippet follows the one in Example: Find the cluster in the scene and uses the printClusterInfo() function described in Example: Accessing the cluster’s elements, parent, and type.

   ' Create a new SubComponent object so you can specify which elements to add. 
   Set oSubComp = oCluster.CreateSubComponent

   ' Use the SubComponent.AddElement method to add each point separately 
   ' to the subcomponent. 
   oSubComp.AddElement 23
   oSubComp.AddElement 29
   oSubComp.AddElement 33
   oSubComp.AddElement 39

   ' Add the subcomponent to the cluster using the SIAddToCluster command. 
   SIAddToCluster oCluster, oSubComp

The printClusterInfo(oCluster) function displays the following message in the History Log of the Script Editor at this point:

'INFO : "Current cluster contains these element(s) under the 'wall' object:
       'pnt[21],pnt[22],pnt[23],pnt[29],pnt[31],pnt[33],pnt[39],pnt[40],pnt[41]
'"
'INFO : "=========================================================="

Example: Remove points from the cluster

When you want to remove points (or any element) from a cluster, you have to use the SubComponent.RemoveElement method to clear the elements you want to keep from the SubComponent object and then use the SIRemoveFromCluster command to remove the leftover elements from the actual cluster.

 

This code snippet follows the one in Example: Add points to the cluster and uses the printClusterInfo() function described in Example: Accessing the cluster’s elements, parent, and type.

In this case, we want to remove points 22 and 40, so we have to remove "pnt[21,23,29,31,33,39,41]" from the subcomponent and then use it with SIRemoveFromCluster:

   ' Create a new SubComponent object to specify which elements to remove. 
   Set oSubComp = oCluster.CreateSubComponent

   ' Remove the elements you want to keep from the subcomponent
   oSubComp.RemoveElement 21
   oSubComp.RemoveElement 23
   oSubComp.RemoveElement 29
   oSubComp.RemoveElement 31
   oSubComp.RemoveElement 33
   oSubComp.RemoveElement 39
   oSubComp.RemoveElement 41

   ' Remove the specified subcomponent from the cluster
   SIRemoveFromCluster oCluster, oSubComp

The printClusterInfo(oCluster) function displays the following message in the History Log of the Script Editor at this point:

'INFO : "Current cluster contains these element(s) under the 'wall' object:
       'pnt[21], pnt[23], pnt[29], pnt[31], pnt[33], pnt[39], pnt[41]
'"
'INFO : "=========================================================="

Example: Copying clusters

When you want to copy an entire cluster from one object to another, you have to use the CopyCluster command

 

This code snippet follows the one in Example: Remove points from the cluster.

   '
   ' Copying clusters can only be done via the CopyCluster command. This example 
   ' demonstrates how to copy clusters between objects.
   Set oTarget = ActiveSceneRoot.AddGeometry( "Grid", "MeshSurface", "floor" )
   CopyCluster oCluster, oTarget 

   ' Now you have to find it in the scene again (since the CopyCluster command 
   ' doesn't return the newly created cluster). It's probably the first one in 
   ' the bunch.
   Set oNewCls = oTarget.ActivePrimitive.Geometry.Clusters(0)

The printClusterInfo(oCluster) function displays the following message in the History Log of the Script Editor at this point:

'INFO : "Current cluster contains these element(s) under the 'floor' object:
       'pnt[21], pnt[23], pnt[29], pnt[31], pnt[33], pnt[39], pnt[41]
'"
'INFO : "=========================================================="

Example: Deleting clusters

Now that you've created a copy of the cluster on the new object, delete the old one. For this you need to use the RemoveCluster command:

 

This code snippet follows the one in Example: Copying clusters.

   RemoveCluster oCluster


Autodesk Softimage v7.5