As discussed in Section 1.1.5 and elsewhere, a MechModel provides a number of predefined child components for storing particles, rigid bodies, springs, constraints, and other components. However, applications are not required to store their components in these containers, and may instead create any sort of component arrangement desired.
For example, suppose that one wishes to create a biomechanical model of both the right and left human arms, consisting of bones, point-to-point muscles, and joints. The standard containers supplied by MechModel would require that all the components be placed within the following containers:
Instead of this, one may wish to set up a more appropriate component hierarchy, such as
To do this, the application build() method can create the necessary hierarchy and then populate it with whatever components are desired. Before simulation begins (or whenever the model structure is changed), the MechModel will recursively traverse the component hierarchy and update whatever internal structures are needed to run the simulation.
The generic class ComponentList can be used as a container for model components of a specific type. It can be created using a declaration of the form
where Type is the class type of the components and name is the name for the container. Once the container is created, it should be added to the MechModel (or another internal container) and populated with child components of the specified type. For example,
creates two containers named "parts" and "frames" for storing components of type Particle and Frame, respectively, and adds them to a MechModel referenced by mech.
In addition to ComponentList, applications may use several "specialty" container types which are subclasses of ComponentList:
A subclass of ComponentList, that has its own set of render properties which can be inherited by its children. This can be useful for compartmentalizing render behavior. Note that it is not necessary to store renderable components in a RenderableComponentList; components stored in a ComponentList will be rendered too.
A RenderableComponentList that is optimized for rendering points, and also contains its own pointDamping property that can be inherited by its children.
A RenderableComponentList designed for storing point-based springs. It contains a material property that specifies a default axial material that can be used by its children.
A PointSpringList that is optimized for rendering two-point axial springs.
If necessary, it is relatively easy to define one’s own customized list by subclassing one of the other list types. One of the main reasons for doing so, as suggested above, is to supply default properties to be inherited by the list’s descendants.
A component list which declares ModelComponent as its type can be used to store any type of component, including other component lists. This allows the creation of arbitrary component hierarchies. Generally eitherComponentList<ModelComponent> or RenderableComponentList<ModelComponent> are best suited to implement hierarchical groupings.
A simple example showing an arrangement of balls and springs formed into a net is defined in
artisynth.demos.tutorial.NetDemo
The build() method and some of the supporting definitions for this example are shown below.
The build() method begins by creating a MechModel in the usual way (lines 29-30). It then creates a net composed of a set of balls arranged as a uniform grid in the x-y plane, connected by a set of green colored springs running parallel to the y axis and a set of blue colored springs running parallel to the x axis. These are arranged into a component hierarchy of the form
using containers created at lines 37-42. The balls are then created and added to balls (lines 45-56), the springs are created and added to greenSprings and blueSprings (lines 59-71), and the containers are added to the MechModel at lines 74-77. The balls along the edges parallel to the y axis are fixed. Render properties are set at lines 80-83, with the colors for greenSprings and blueSprings being explicitly set to dark green and blue.
MechModel, along with other classes derived from ModelBase, enforces reference containment. That means that all components referenced by components within a MechModel must themselves be contained within the MechModel. This condition is checked whenever a component is added directly to a MechModel or one of its ancestors. This means that the components must be added to the MechModel in an order that ensures any referenced components are already present. For example, in the NetDemo example above, adding the particle list after the spring list would generate an error.
To run this example in ArtiSynth, select All demos > tutorial > NetDemo from the Models menu. The model should load and initially appear as in Figure 4.20. Running the model will cause the net to fall and sway under gravity. When the ArtiSynth navigation panel is opened and expanded, the component hierarchy will appear as in Figure 4.21. While the standard MechModel containers are still present, they are not displayed by default because they are empty.
In addition to MechModel, application-defined containers can be added to any model that inherits from ModelBase. This includes RootModel and FemModel. However, at the present time, components added to such containers won’t do anything, other than be rendered in the viewer if they are Renderable.
It is sometimes useful to create groupings of model components in a manner that is both independent of their primary location within the model component hierarchy and also represented in the component hierarchy. However, it is not possible to do this using the ComponentList described in Section 4.8.1, since model components may only belong on one ComponentList (or more generally, one CompositeComponent) at a time.
Instead, one can use a ReferenceList, which contains references to a set of components of a particular type. Reference lists can be created with the constructors
ReferenceList() |
Create an unnamed list. |
ReferenceList(String name) |
Create a named list. |
Their definition is parameterized by the type of model component that they are intended to reference. For example, a reference list for components of type MeshComponent can be created and populated using the code fragment
To create a list that can accept any type of model component, simply parameterize it using ModelComponent:
Reference lists can be managed using the following methods, where C is the list’s component type:
ReferenceComp addReference (C comp) |
Add a reference for comp. |
void addReference (Collection<C> comps) |
Add references for each component in comps. |
int numReferences() |
Get the number of references. |
C getReference (int idx) |
Get the idx-th referenced component. |
void getReferences (Collection<C> comps) |
Gets all referenced components. |
boolean containsReference (C comp) |
Check if comp is referenced. |
int indexOfReference (C comp) |
Get the index of the reference to comp. |
boolean removeReference (C comp) |
Remove first reference to comp. |
boolean removeReferences (Collection<C> comps) |
Remove all references to the components in comps. |
void removeAllReferences () |
Remove all references. |
Internally, reference lists are implemented as component lists containing collections of ReferenceComp components that encapsulate each component reference. (The addReference() method returns the ReferenceComp that it creates for the added reference).
Unlike with component lists, a reference list may contain multiple references to the same component.
An application’s code base is of coarse free to create arbitrary collections of components using Java arrays or the various Collection classes defined in java.util. As indicated above, the purpose of a reference list is to incorporate such a collection into the component hierarchy, where it can be accessed from the navigation panel and will persist if the model is saved and reloaded.
An extension to the NetDemo example of Section 4.8.2 that creates reference lists for subsets of the green and blue springs is defined in
artisynth.demos.tutorial.NetDemoWithRefs
The build() method is shown below:
Since the model is a subclass of NetDemo, the build() method begins
by creating the components of NetDemo with a call to super.build()
(line 2). Reference lists are then created to hold the green and blue springs
located in the middle of the net (lines 8-15). Each of these spring sets is
defined by indices with respect to the primary lists greenSprings and blueSprings. The lists are then added to the MechModel as direct subcomponents (lines 16-17).
Within the navigation panel, each component of a reference list is displayed as
-> path/to/reference
so that the referenced components are easy to locate. Selecting a reference in the panel selects the referenced component. Figure 4.22 shows NetDemoWithRefs with the navigation panel expanded to show the references for middleGreenSprings and three of the springs selected.