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

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).

Tip

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).

Note

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[23], pnt[29], pnt[31], pnt[33], pnt[39], 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.

Note

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.

Note

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.

Note

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

Note

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:

Note

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

RemoveCluster oCluster