Proposal: Generalize SMTK’s model resource
Many of our projects have models that do not need a full boundary representation (B-Rep) data structure like the half-edge or winged-edge models. Rather than abuse the B-Rep model by accepting incomplete or invalid models, we should have a more strict B-Rep model but provide some alternative that exposes concepts like vertices, edges, and faces without orientation or sense. Also, we would like to have conceptual models that can embody higher-level entities. For example, the Reactor Geometry Generator (RGG) session models nuclear reactor cores as a series of assemblies of rods, pins, and ducts. Anatomical models might model tissues, organs, and the (mechanical, chemical, functional) relationships between them.
These use cases generalize into the need for an abstract, multipartite graph-based model resource class and potentially a domain-specific language to specify use cases in terms of this graph-based model:
- components of the resource are graph nodes
- relationships between components are graph edges.
By defining the problem in terms of a graph, we can concisely describe many different models. Components are characterized by their storage and relationships are characterized by the types of components they connect and constraints on those connections (e.g., limits on the number of edges of a given type connecting components).
Desirable features
- A resource type should be allowed to restrict node and edge types to a fixed set or allow extensions at run time, but as much type-safety as possible should be guaranteed at compile time.
- Nodes are blobs of model storage owned by a resource and rather uninteresting (to SMTK) except that they are referenced weakly by edges.
- Edges are owned by the resource just like nodes. They are directed (unidirectional), meaning that they link an originating node to a target node. They may programmatically or at run-time constrain the type of nodes at each endpoint.
- Introspection of the allowable node and edge types allows user interfaces to present intuitive displays and controls of the model.
Prototype implementation
A prototype of what this resource might look like is here:
https://gitlab.kitware.com/dcthomp/smtk/tree/graph-model/smtk/graph
If you build this branch, you can run a simple test like so:
./bin/UnitTests_smtk_graph_testing_cxx TestGraphResource
and you should see this output (with different hash codes and roles, but otherwise identical):
Created smtk::brep::Resource
Node types
smtk::brep::Vertex 4495210551
smtk::brep::VertexUse 4495210658
Edge types
smtk::brep::VertexUsedBy 4495210707 role 200243411
smtk::brep::VertexSense 4495210792 role 200243496
Discussion
Some open questions:
- Ideally, while the prototype provides compile-time type safety, we will want to allow run-time, user-defined models. For example, see this extended version of the B-Rep model from the simple test above, encoded as JSON which we might like to consume at run-time. How would programmable types provide unique roles for edges and type information for nodes and edges? Perhaps via the property system? Special subclasses that provide their own
index()
andtypeName()
methods? - What is needed for our Python interface to allow custom resource, component (node), and relationship (edge) types defined in Python to interoperate with this class.
- There are situations where we also want to store data on edges of the graph. Links do not provide a way to do this. An example of this need would be sense/orientation information on edges connecting cells to their use-records in a B-Rep model based on the graph-model resource.
- How should editing of the graph be accomplished?
- Is there a good way to enforce editing of the model to occur only inside operations? (For example, we might make objects that edit the graph construct-able only with an
Operation::Key
instance.) - Is there a way to introduce checkpointing and make undo-redo automatic?
- Is there a good way to enforce editing of the model to occur only inside operations? (For example, we might make objects that edit the graph construct-able only with an
- The prototype does not address serialization/deserialization. The hash codes based on type index vary from run to run, so string names must be used but the data structure does not index by name.