The iTools are easy to use interactively (O.K., easy once you learn some of the conventions and jargon). But they also have the ability to be extended and controlled programmatically. I have given a couple examples of extending an iTool with new operations ([data operation](http://michaelgalloy.com/2006/05/01/creating-an-itool-data-operation.html), [general operation](http://michaelgalloy.com/2006/06/20/creating-an-itool-generalized-operation.html)). I'll post more extending iTools visualizations, file readers/writers, manipulators, user interface services, and custom user interfaces in the weeks to follow. But programmatically controlling an iTool is both fairly easy and extremely useful, especially in situations where a visualization needs to be created which further needs to be explored interactively.
Here is the [source](http://michaelgalloy.com/demos/itools/mg_isosurfaces_demo.pro) and [documentation](http://michaelgalloy.com/demos/itools/mg_isosurfaces_demo.html) for the demo.
An iTool's object reference is necessary to do most actions with a tool. Analogous to direct graphics, after an iTool is created it is the "current tool." So to create an iVolume tool and get its object reference:
id = itGetCurrent(tool=otool)
Now `id` holds the string identifier of the tool and `otool` holds the object reference of the tool.
One of the most useful methods on the tool object is `findIdentifiers`. This searches through the identifiers of all the components of the iTool (though is can be limited, as it is here, to a subset of all components). Here the visualizations are searched for the volume visualization just created:
vol_id = otool->findIdentifiers('*DATA SPACE/VOLUME*', $
ovol = otool->getByIdentifier(vol_id)
Then given the identifier, the `getByIdentifier` gets the object reference of the component. For components of a tool, object references are necessary for "low level" operations and identifiers are needed for "high level" operations. For example, properties of a component can be changed using either an identifier or an object reference for the component. If the identifier is used (as an argument of `IDLitTool::doSetProperty`) then the changing of the property is automatically placed in the undo/redo system. If the object reference is used directly (with its `setProperty` method), then the property is changed, but nothing else is done.
The heart of the routine is in the creation of the isosurfaces:
for i = 0, n_elements(isovalues) - 1 do begin
result = otool->doAction(iso_op_id)
The one trick demonstrated in this example is that operations always operate on the current selection and creating an isosurface will automatically select the isosurface itself upon completion. So after the first isosurface is created, you must explicitly select the original volume data before making another isosurface.
The `ITPROPERTYREPORT` routine called at the end is an example program contained in the documentation of the iTools (in the `examples/doc/itools/` directory). It can be a handy tool when exploring, developing, and debugging iTools code.