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 cluster’s 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