There is nothing like a fresh crispy Knowledge Base Nugget on Monday morning. Today's is extra crispy. How do you select multiple objects in the Model Manager with Python? How do you use GPSE API calls and macros together. And...How do you create dynamic Python statements to build and call macros?...all in one Knowledge Base Article? Sounds like a lot....and before we sink our teeth in...
What's a GPSE API you ask? GPSE (pronounced "gypsy") is our acronym for the Geomagic Python Scripting Environment, and API is the industry standard acronym for Application Programming Interface....together they mean using Python to drive our technology.
This week's nugget stems from a growing number of calls asking, "How do I select multiple models with Python for commands like Merge?" In upcoming releases we will be exposing high level commands (such as Merge, Global Registration, and others) that require a selection of multiple models as input. We will also expose the ability within the GPSE to select multple models in support of these commands. Until that time recorded macros (e.g., geo.merge_objects) and the geo.select_objects macro can be used.
So how do you write a macro call that uses multiple model names or model IDs when the model's names or IDs are unknown at the time the script is written? One way is to use dynamic statement creation. In Python you can dynamically (at runtime) create variables or build and run whatever Python code you like. In our case we build a geo.select_objects macro call (i.e., geo.select_objects( 1, 0, 3, "pts_01", "pts_02", "pts_03") ) that selects any number of similar point models in the Model Manager and then the script "runs" it with the Python exec statement. What are the parameters for geo.select_objects? How do I create dynamic macro calls? Read on...and have a great week!
A: Selecting multiple objects of the same type (points, scans, polygons, etc.) is required for commands such as Merge, Wrap, and Global Registration.
Manually you can select objects in the Model Manager by clicking the left mouse button (LMB) while holding down the Control or Shift Key; the same way one would in a Windows file browser. The GUI or Ribbon command Select->Data->Select All->Objects could also be used. One important note is that depending on two conditions 1) whether all of the models (objects) in the Model Manager are the same type or not, and 2) a model is already selected or not, this command will behave in different manners.
If all the models are of a single type and nothing is selected. Pressing Select All Objects will select all the Top Level objects in the Model Manager. Such as all the scans.
If there is a mixed collection of data such as points, scans, and polygons, and nothing is selected, Select All Objects will do nothing.
If there is a either a mix or uniform collection of model types in the Model Manager and one of them is selected (highlighted). Select All Objects will select all of the objects of that particular type.
Why go to this level of detail? Simply because Select All Objects' behavior will depend on the environment in which it is invoked. When recording a Python macro, the actual text that is recorded is:
What it selects is solely based on the current Model Manager's state. So using this geo. macro inline within a Python script can be an effective way to easily select multiple objects in the open file if the right conditions are met and consistent for the repetitive runs of the script.
In order to have more control over the selection the geo.select_objects macro can be used. The official definition of this macro (followed by a few examples) is:
# geo.select_objects( int selectionType, string phaseName, int selectionCount, [unicodeString or int]selections, ...] )
# selectionType - sets the selections parameter type that is passed, it can be either:
# 0 = the model's ID(s) is passed in the selections parameter
# 1 = the model's name(s) is passed in the selections parameter
# phaseName - chooses the model type ( Note: The term "Phase" of the model has been deprecated )
# "Point" or 0 = Point Model
# "Scan" or 1 = Scan Data or Ordered Point Model
# "Polygon" or 3 = Polygon Model
# "Fashion" = Parametric Surfacing Model (Studio Only)
# "Curve" or 4 = Curve or Sketch Model
# "Shape" or 5 = Exact Surfacing Model (Studio Only)
# "CAD" or 6 = CAD Model
# "World" or 8 = The World Model
# selectionCount - is the number of selection references (this value and the number of references provided in the selections parameter must be equal)
# 0 = Clears the current model selection (not the model's point, polygon, or surface selections)
# 1 = Selects the model by the name or ID provided
# 2 or more = Selects the models by their names or ID's provided
# selections - is the model name(s) or ID(s) to be selected, which type is determined by the selectionType parameter
# IDs are int
# names are Unicode strings (as seen in the Model Manager)
# Clear the current selection (either is valid)
# geo.select_objects ( 0, 0, 0 )
# geo.select_objects ( 1, "", 0 )
# Select the World Object
# geo.select_objects ( 0, 8, 1, 0 )
# Select the first polygon model in the Model Manager
# geo.select_objects ( 0, "Polygon", 1, 0 )
# (Note: multiple model selection is not allowed in this way, that is: geo.select_objects( 0, "Polygon", 3, 0 ) will return an error
# Select the Point models named 'Scan 001' and 'Scan 002' in the Model Manager
# geo.select_objects ( 1, 1, 2, "Scan 001", "Scan 002" )
# Select the Point models of a given model ID
# geo.select_objects ( 0, "Points", 2, 123, 17 )
# geo.select_objects ( 0, "Points", 1, 5 )
Used in concert with the Python API (or rather within the GPSE, Geomagic Python Scripting Environment) complete control over what is selected can be achieved when limiting 'multiple selections' to the same type of model. This type-based limitation is designed into the application so as not to allow sending mixed data sets to commands that support multiple selections as input ( e.g., Merge, Combine, etc.)
In the example below all the models in the model manager (including the World) are examined. If the model has points as it's data type we concatenate the model names into a string and also store the number of them so both data can then be passed as the selections and selectionCount parameters (respectfully) in the geo.select_objects call.
This example also shows the ability to run recorded Python geo. macros "inline" or as-recorded within a Python script (e.g., geo.select_objects( 0, 0, 0 )), and the creation of a macro call dynamically, inserting expandable Python code and variables, and executing it with Python's exec command at runtime: exec 'geo.select_objects( 1, "Point", %d, %s )' % ( numPtObj, str(pointObjectNames)). Note: You could also use Python's lists or queues and embed them using their own techniques.)
for m in geoappall.execStrings: exec m in globals(), locals()
# clear the active model selection
geo.select_objects( 0, 0, 0 )
# Get a list of all models in this file.
models = geoapp.getModels()
if models != None:
pointObjectNames = ""
numPtObj = 0
# Iterate through list of models
for model in models:
print "model = " + model.name
# get points
points = geoapp.getPoints(model)
if points != None:
if numPtObj == 0:
pointObjectNames = "\"" + model.name + ""\""""
pointObjectNames = pointObjectNames + ""