Proposal: Interactive Previews of Operations
As we develop geometric algorithms, it is becoming more important to show users the potential outcome of an operation visually. To do this interactively, there are several challenges:
Design Issues
- to maintain interactivity, generation of previews (which may take substantial time) should run in a background thread, not the GUI thread (so we prefer to make previews “launch-able” in the same way as the main operation);
- resource locking may prevent multiple previews from being simultaneously computed (and this can waste resources and prevent any previews in some cases), so there is a strong desire for cancel-able preview generation;
- there are several alternatives for where the preview geometry might live:
- on the input resource (but this would write-lock it during preview)
- on the input operation specification (but this would write-lock it during preview, preventing user editing of parameters during preview generation)
- on an attribute resource owned by the operation panel (this would require the operation’s preview method accept a “foreign” resource)
- the operation panel does not (and arguably should not) destroy parameters just because the user decides to abandon editing one operation temporarily in favor of another (which has implications for the paraview pipeline used to display previews);
- previews for different operations will need to control the display properties of their geometry and the operation-input’s geometry in different ways.
Proposed Design
- Add an
smtk::operation::Operation::preview(smtk::attribute::Resource::Ptr previewGeom)
method to the Operation class. Alternatively, we could alter Operation::operate()
to accept a preview attribute as input and add bool Operation::supportsPreviews()
so operations would not be required to generate previews.
- Add a way for the operation launcher to
- cancel any running preview tasks for a given operation and
- invoke the
preview(...)
method, whose attribute resource will be passed to the launcher by the operation panel and will be write-locked.
- Make the operation panel create a pqPipelineResource for displaying preview geometry, attached to an attribute resource (call it PreviewResource) owned by the panel.
- Create an attribute in PreviewResource with items that the operation’s preview method can use to signal what components/resources should be hidden or rendered differently (say in wireframe mode) during preview.
- Hide PreviewResource when an operation is not being edited (i.e., when the operation is running or completed and no parameters have been changed; this is usually when the “Apply” button is disabled in the operation panel).
- Show the PreviewResource’s geometry (and adjust other pipeline object visibility) when a preview becomes available.
Discussion
This design should allow previews to be generated when it is computationally feasible while avoiding deadlocks in the GUI for large data. However, it does hinge on the ability of launchers to be able to cancel a preview operation. Otherwise, if a user clicked “Apply” while a long-running preview was being generated, the operation could not be run (due to the required write-lock on the input resources) until the preview completed.
This design should accommodate both operations that provide previews and those that do not (because they are difficult, or the operation does not have a visual component, or the operation’s effect is well-understood). Because the preview resource would be independent of the operation-specification’s native attribute resource, users could continue to adjust parameters in the GUI while a preview is being generated — although doing so would cancel the running preview and queue a new preview computation.
Alternative approach
One alternative to the approach above is to write custom 3-D widgets and embed them in custom attribute views (for the operation parameters) or custom item views (for items in the operation parameters). Using this approach would require fewer changes to SMTK’s core, but would place a large burden on developers of operations.
Pros
- Custom views/item-views can add not just previews but interaction to the operation setup; users might interact directly with the preview geometry.
- The code to generate the preview geometry would live outside of the operation; scripts would not need the preview geometry feature.
Cons
- The development time required to implement 3-D widgets is significant. Each new widget requires: a widget class to handle interactions, a representation class to render geometry, a subclass of pqInteractivePropertyWidget to tie the VTK widget parameters to paraview proxy parameters, and a qtItem subclass to tie SMTK attribute(s)/item(s) to paraview proxy parameters. A fifth class (subclassing vtkImplicitFunction) is sometimes required but would probably not be needed for most preview geometry.
- The code to generate the preview geometry would live outside of the operation, but a lot of the geometry generated might need to share code with the actual operation.
You have the separation of code to generate a preview from the operation itself as a Con, but I see it as a Pro. smtk::operation::Operation
already has an unwieldy API. I would be reluctant to add to it, especially for an optional feature that will require a chunk of work to implement for each operation.
I listed it under both Pros and Cons for that reason.
I don’t want to make Operation any bulkier than it needs to be, but I don’t want to impose the huge development burden of widgets on every operation subclass. I seem to recall you complaining about writing a new widget class not too long ago .
I think there’s a way to change Operation to allow more interactivity without making it more complex. But it would be different, since the Specification and Result would need to be separate per invocation in order to allow parallel background runs as users edit parameters. Then the changes to accommodate preview geometry are mainly on the GUI side (checking to see if an operation has attached geometry to its Result).
I think there’s a way to change Operation to allow more interactivity without making it more complex. But it would be different, since the Specification and Result would need to be separate per invocation in order to allow parallel background runs as users edit parameters.
Parameters and Results already are separate per invocation. Does that suffice for your idea?
Yes, I recall that my complaint was that the process was convoluted and not well documented. Perhaps if we have to write a bunch of them the process for doing so will be cleaned up .
- I do not believe they (Parameters, Results) are in separate Resources. Can they be modified safely in concurrent threads?
- For Results, thread-safety within a Resource might enough for concurrent preview generation, but unless we do something complicated for ParaView, all of those results’ preview geometry would be rendered simultaneously unless they are in separate Resources.
- For Parameters, if users are changing Operation::Specification values while a preview is being generated, it could lead to inconsistent results or crashes. So, each preview needs a copy of the input attribute(s) for the operation.
I do not think the process will ever be feasible, no matter how well-documented, to support a large number of preview widgets. If we are allowed to redesign the widget infrastructure in VTK and ParaView, then it could be made simple. Unless the meshing SBIR gets funded, I don’t see that happening.
They can be modified safely in concurrent threads. Better stated: there is code that assumes they can be modified safely in concurrent threads, and there have been efforts to ensure that they can be modified safely in concurrent threads.