Commit c6716dee authored by David Thompson's avatar David Thompson Committed by Kitware Robot
Browse files

Merge topic 'pv-items'

83f6362c

 ParaView widgets in SMTK again, for the very first time.
Acked-by: Kitware Robot's avatarKitware Robot <kwrobot@kitware.com>
Acked-by: T.J. Corona's avatarT.J. Corona <tj.corona@kitware.com>
Merge-request: !1252
parents 02679683 83f6362c
Pipeline #122184 failed with stage
in 0 seconds
## ParaView-widget controls for SMTK attribute items
SMTK now makes some initial widgets (ParaView's box, plane, sphere,
and spline widgets) available for controlling values of items in
an SMTK attribute.
By adding an `ItemViews` section to an attribute's view and
setting the item's `Type` attribute to the proper string (one
of `Box`, `Plane`, `Sphere`, or `Spline`), the item will be
shown using a ParaView widget (and associated 3-d editor) when
the attribute is loaded into modelbuilder or paraview.
For example:
```xml
<?xml version="1.0" encoding="utf-8" ?>
<SMTK_AttributeResource Version="3">
<Definitions>
<AttDef Type="Example">
<ItemDefinitions>
<Double Name="bbox" NumberOfRequiredValues="6">
</Double>
</ItemDefinitions>
</AttDef>
</Definitions>
<Attributes>
<Att Name="Demo" Type="Example">
<Items>
<Double Name="bbox">
<Values>
<Val Ith="0">0.0</Val>
<Val Ith="1">0.05</Val>
<Val Ith="2">0.0</Val>
<Val Ith="3">0.05</Val>
<Val Ith="4">0.0</Val>
<Val Ith="5">0.125</Val>
</Values>
</Double>
</Items>
</Att>
</Attributes>
<Views>
<View Type="Group" Title="Sample" TopLevel="true">
<Views>
<View Title="Example"/>
</Views>
</View>
<View Type="Instanced" Title="Example">
<InstancedAttributes>
<Att Type="Example" Name="Demo">
<ItemViews>
<View Item="bbox" Type="Box"/>
</ItemViews>
</Att>
</InstancedAttributes>
</View>
</Views>
</SMTK_AttributeResource>
```
At this time, the widget⟷item connection is one-way; the item is updated
by the widget, but changes to the item outside of editing done using the
widget does not update the widget.
The latter cannot work until operations or some other signaling mechanism
exists to inform SMTK when changes are made to attribute item-values.
A limitation of the current implementation is that changes to the active
view do not affect which view the widget resides in.
In the longer term, this functionality may be expanded to other
ParaView widgets and provide a more flexible mapping between values
in SMTK items and their representative widget values.
For example, the XML above assumes the bounding box values
are stored as a single DoubleItem with 6 required values.
However, it is also common to think of a box as specified by
2 corner points (i.e., a GroupItem with 2 DoubleItem children)
or as a center point and a vector of lengths along each axis.
By accepting more options in the XML, we will allow a mapping
between the widget and items to be specified.
Finally, note that the box widget will only initialize its representation
with values from the SMTK item if they are non-default (or if
no default exists).
Similarly, the plane widget uses a default size for its widget which
is very inflexible.
We plan to extend this capability by accepting more XML attributes
in the AttributeItemInfo's Component entry that specify how to obtain
initial values from model components currently loaded into
modelbuilder/paraview.
### Developer changes
The new classes include:
+ `pqSMTKAttributeItemWidget` — a base class for all paraview-widget items; it inherits qtItem.
+ `pqSMTKBoxItemWidget` — a subclass of pqSMTKAttributeItemWidget that realizes a box widget.
+ `pqSMTKPlaneItemWidget` — a subclass of pqSMTKAttributeItemWidget that realizes a plane widget.
+ `pqSMTKSphereItemWidget` — a subclass of pqSMTKAttributeItemWidget that realizes a sphere widget.
+ `pqSMTKSplineItemWidget` — a subclass of pqSMTKAttributeItemWidget that realizes a spline widget.
The `pqSMTKAppComponentsAutoStart` class's initializer now
calls `qtSMTKUtilities::registerItemConstructor` to register
each concrete widget class above as a `qtItem` subclass.
Once the plugin is loaded, any attributes displayed in the
attribute panel or operation panel may request, e.g., the box
widget with `Type="Box"` as shown above.
......@@ -16,4 +16,4 @@ additional functionality.
qt.rst
vtk.rst
paraview.rst
paraview/index.rst
Anatomy of ParaView
-------------------
In order to use SMTK within ParaView, it is important to understand
some of ParaView's design.
A core premise of ParaView is that the user interface will frequently
be a separate process from rendering and I/O tasks, as these must be
run in a distributed-memory parallel environment.
Thus, ParaView has a client process and 1 or more server processes.
Even when running in serial (i.e., non-parallel) mode, ParaView makes a
distinction between tasks run on the client and the server(s).
ParaView's design has the client create and manage objects on the server.
Nearly all objects on the server are subclasses of vtkObject and thus can
be managed using wrappings created by VTK (similar to Python wrappers).
These wrappers are called client-server wrappers and allow ParaView to
serialize, deserialize, and remotely invoke methods on server-side objects.
Nearly all objects on the server have a matching instance on each server process.
For example, if the client creates a file-reader and an actor to display data from the file,
it will instruct each server to create a reader and an actor; and have each server attach the
reader and actor — even though some of the servers' readers may not have data for that
actor to display because the data is unevenly distributed.
This pattern simplifies the work the client must do,
however it also means that server-side objects should rarely (if ever)
(1) send signals to the client or
(2) perform blocking operations based on their local data;
the reason for this is that,
(1) if every server process sent a signal when an action was performed, a large
number of servers would quickly overwhelm the client and
(2) since each server process holds a different portion of the data,
not every server process would block at the same time which can lead to deadlocks
and race conditions.
So, although there are infrequent exceptions,
be aware that ParaView takes great care to initiate all actions on the client,
even when it seems that the server should do so.
Integration with SMTK
---------------------
In ParaView, there are 3 types of objects that SMTK frequently interacts with:
* Subclasses of vtkObject which live on each server process and are "wrapped"
by C++ code that allows remote invocation of their methods across the
client-server (CS) connection each server maintains with either the rank-0
server or the client.
Several SMTK classes have instances owned by a "wrapper" class that inherits
from vtkObject to make this communication possible.
* Subclasses of vtkSMProxy, which live on the client process.
Subclasses specific to SMTK are only required when the client needs to expose
methods to manage SMTK data on the server that cannot be handled by
ParaView's client-server wrapping. For example, methods that take non-primitive
objects, such as pointers to SMTK classes as input, since these methods
cannot be CS-wrapped.
* Subclasses of pqProxy, which live on the client process and reference
an instance of vtkSMKProxy (or its subclasses).
Subclasses specific to SMTK exist to expose Qt signals and slots related to
SMTK. If Qt is not required, then you should subclass vtkSMProxy instead.
ParaView
========
SMTK provides ParaView plugins that, in concert with the VTK extensions, allow users to
load models and meshes in ParaView; perform selections and filtering on model entities;
run operations on models; and set attribute values by interacting with 3-D widgets.
These plugins form the core of the ModelBuilder application (version 6 and later).
.. toctree::
:maxdepth: 3
anatomy.rst
plugins.rst
lifecycle.rst
representations.rst
panels.rst
widgets.rst
ParaView
========
SMTK provides ParaView plugins that, in concert with the VTK extensions, allow users to
load models and meshes in ParaView; perform selections and filtering on model entities;
and even run operations on models.
These plugins form the core of the ModelBuilder application (version 5 and later).
In ParaView, there are 3 types of objects that SMTK frequently interacts with:
* Subclasses of vtkObject which live on each server process and are "wrapped"
by C++ code that allows remote invocation of their methods across the
client-server (CS) connection each server maintains with either the rank-0
server or the client.
Several SMTK classes have instances owned by a "wrapper" class that inherits
from vtkObject to make this communication possible.
* Subclasses of vtkSMProxy, which live on the client process.
Subclasses specific to SMTK are only required when the client needs to expose
methods to manage SMTK data on the server that cannot be handled by
ParaView's client-server wrapping. For example, methods that take non-primitive
objects, such as pointers to SMTK classes as input, since these methods
cannot be CS-wrapped.
* Subclasses of pqProxy, which live on the client process and reference
an instance of vtkSMKProxy (or its subclasses).
Subclasses specific to SMTK exist to expose Qt signals and slots related to
SMTK. If Qt is not required, then you should subclass vtkSMProxy instead.
Plugins
-------
Some notes about the plugins:
* the server directory (which holds source for the smtkPVServerExtPlugin plugin) is
for code that can be built without Qt and will reside — at least in part — on the server.
Some client-side proxy classes (that do not use Qt) whose counterparts
reside on the server are also included in this plugin.
This is where the model (and eventually mesh) sources and their representations reside.
Note that the representations display the *SMTK* selection, not the *ParaView* selection,
although the two selections are generally kept in sync.
Besides dealing with SMTK selections in a consistent way,
the model representation uses a glyph mapper to draw instance prototype geometry at all
instance placement points.
* the appcomponents plugin is dependent on the server plugin
for the VTK-wrapped and CS-wrapped objects that it
creates proxies for on the client.
Many of the components in this plugin are ParaView "behaviors."
A behavior is a QObject subclass that customizes the user interface of
ParaView. In this case:
* the :smtk:`pqSMTKBehavior` creates instances of :smtk:`vtkSMTKWrapper` objects
on the server and manages them via :smtk:`vtkSMSMTKWrapperProxy` objects on the client.
Each wrapper exposes an :smtk:`smtk::resource::Manager`, an :smtk:`smtk::operation::Manager`,
and an :smtk:`smtk::view::Selection` to server-side VTK classes (such as the resource
readers and representations).
* the :smtk:`pqSMTKSelectionFilterBehavior` adds a toolbar to ParaView allowing users to
specify what types of resource components they want to select.
It then installs a filter onto an SMTK selection manager to force the selection to match
the specification.
* the :smtk:`pqSMTKResourcePanel` class adds a panel to ParaView that shows the resources
and components available.
* the :smtk:`pqSMTKColorByToolBar` class adds a tool bar to ParaView that allows users
to choose how model entities should be colored (e.g., by their assigned color, by the
assigned color of the volume they bound, by field values such as simulation results).
Lifecycle
---------
......
Panels
------
SMTK provides several panels for use in ParaView-based applications
* a resource tree panel that displays a configurable hierarchy of resources and their components.
* an attribute panel that displays and edits attribute resources.
* an operation panel that displays and edits operation parameters.
Plugins
-------
Some notes about the plugins:
* the server directory (which holds source for the smtkPVServerExtPlugin plugin) is
for code that can be built without Qt and will reside — at least in part — on the server.
Some client-side proxy classes (that do not use Qt) whose counterparts
reside on the server are also included in this plugin.
This is where the model (and eventually mesh) sources and their representations reside.
Note that the representations display the *SMTK* selection, not the *ParaView* selection,
although the two selections are generally kept in sync.
Besides dealing with SMTK selections in a consistent way,
the model representation uses a glyph mapper to draw instance prototype geometry at all
instance placement points.
* the appcomponents plugin is dependent on the server plugin
for the VTK-wrapped and CS-wrapped objects that it
creates proxies for on the client.
Many of the components in this plugin are ParaView "behaviors."
A behavior is a QObject subclass that customizes the user interface of
ParaView. In this case:
* the :smtk:`pqSMTKBehavior` creates instances of :smtk:`vtkSMTKWrapper` objects
on the server and manages them via :smtk:`vtkSMSMTKWrapperProxy` objects on the client.
Each wrapper exposes an :smtk:`smtk::resource::Manager`, an :smtk:`smtk::operation::Manager`,
and an :smtk:`smtk::view::Selection` to server-side VTK classes (such as the resource
readers and representations).
* the :smtk:`pqSMTKSelectionFilterBehavior` adds a toolbar to ParaView allowing users to
specify what types of resource components they want to select.
It then installs a filter onto an SMTK selection manager to force the selection to match
the specification.
* the :smtk:`pqSMTKResourcePanel` class adds a panel to ParaView that shows the resources
and components available.
* the :smtk:`pqSMTKColorByToolBar` class adds a tool bar to ParaView that allows users
to choose how model entities should be colored (e.g., by their assigned color, by the
assigned color of the volume they bound, by field values such as simulation results).
Representations
---------------
In ParaView, each view that a user creates may display datasets in the pipeline
via a representation.
Formally, a representation is a vtkAlgorithm subclass that adapts data
for rendering based on the type of view:
a spreadsheet view uses a different algorithm to prepare data for display
than a 3-D render-view.
Besides adaptations for different view types,
representations may adapt different types of input datasets.
SMTK provides representations that adapt models, meshes, and
other resources for display in 3-D render views.
Widgets
-------
SMTK provides special widgets for interacting with
model and mesh resources inside ParaView.
These qtItem subclasses may be used by specifying
them in an attribute's View configuration.
Point
^^^^^
The :smtk:`pqSMTKPointItemWidget` can be attached to an SMTK Double item
with 3 entries: the x, y, and z coordinates of a point in world coordinates.
Line
^^^^
The :smtk:`pqSMTKLineItemWidget` can be attached to an SMTK Group item
2 Double children holding 3 values each. Each Double item specifies
one line endpoint's coordinates.
In the item's view configuration, specify Point1 and Point2 attributes
naming the names of the Group's children that represent these points.
Plane
^^^^^
The :smtk:`pqSMTKPlaneItemWidget` can be attached to an SMTK Group item
with 2 Double children holding 3 values each:
one specifying an Origin point and
the other specifying a Normal vector.
Box
^^^
The :smtk:`pqSMTKBoxItemWidget` can be attached to an SMTK Double item
with 6 entries in the order (xmin, xmax, ymin, ymax, zmin, zmaz).
Sphere
^^^^^^
The :smtk:`pqSMTKSphereItemWidget` can be attached to an SMTK Group holding
a Double item with 3 values representing the Center of
a sphere and another Double item with a single value
representing the Radius.
Spline
^^^^^^
The :smtk:`pqSMTKSplineItemWidget` may represent a polyline or a cardinal spline,
depending on whether its View configuration has a `Polyline`
attribute set to true or not.
The widget must be attached to an SMTK Group holding
a Double item with 6 or more values representing the
3-D coordinates of handle points and an Int item
interpreted as a boolean that indicates whether the
curve should be a closed loop or an open segment.
......@@ -32,9 +32,9 @@ set(PQComponentsSrcs
pqSMTKNewResourceBehavior.cxx
pqSMTKOperationPanel.cxx
pqSMTKRegisterImportersBehavior.cxx
pqSMTKResource.cxx
pqSMTKSaveResourceBehavior.cxx
pqSMTKSelectionFilterBehavior.cxx
pqSMTKResource.cxx
pqSMTKWrapper.cxx
pqSMTKResourcePanel.cxx
)
......@@ -51,9 +51,9 @@ set(PQComponentsHeaders
pqSMTKNewResourceBehavior.h
pqSMTKOperationPanel.h
pqSMTKRegisterImportersBehavior.h
pqSMTKResource.h
pqSMTKSaveResourceBehavior.h
pqSMTKSelectionFilterBehavior.h
pqSMTKResource.h
pqSMTKWrapper.h
pqSMTKResourcePanel.h
)
......
......@@ -1720,6 +1720,49 @@
</ProxyGroup>
<ProxyGroup name="smtk_widgets">
<!-- Point widget -->
<Proxy name="SMTKHandleWidget"
base_proxygroup="3d_widgets"
base_proxyname="HandleWidget"
>
<DoubleVectorProperty name = "WorldPosition"
command = "SetWorldPosition"
argument_is_array="1"
default_values='0 0 0'
number_of_elements="3">
</DoubleVectorProperty>
<PropertyGroup panel_widget="InteractiveHandle" label="Handle">
<Property function="WorldPosition" name="WorldPosition" />
</PropertyGroup>
</Proxy>
<!-- Line widget -->
<Proxy name="SMTKLineWidget"
base_proxygroup="3d_widgets"
base_proxyname="LineWidget2"
>
<DoubleVectorProperty name = "WorldPosition1"
command = "SetPoint1WorldPosition"
argument_is_array="1"
default_values='0 0 0'
number_of_elements="3">
</DoubleVectorProperty>
<DoubleVectorProperty name = "WorldPosition2"
command = "SetPoint1WorldPosition"
argument_is_array="1"
default_values='0 0 0'
number_of_elements="3">
</DoubleVectorProperty>
<PropertyGroup panel_widget="InteractiveLine" label="Line">
<Property function="Point1WorldPosition" name="WorldPosition1" />
<Property function="Point2WorldPosition" name="WorldPosition2" />
</PropertyGroup>
</Proxy>
</ProxyGroup>
<ProxyGroup name="settings">
<SettingsProxy name="SMTKSettings" label="Sim Pre-processing"
......
......@@ -3,26 +3,38 @@ find_package(Qt5 REQUIRED COMPONENTS Core Widgets)
# set up sources to build
set(PQWidgetsSrcs
pqGenerateContoursDialog.cxx
pqSMTKAttributeItemWidget.cxx
pqSMTKBoxItemWidget.cxx
pqSMTKLineItemWidget.cxx
pqSMTKPlaneItemWidget.cxx
pqSMTKPointItemWidget.cxx
pqSMTKSphereItemWidget.cxx
pqSMTKSplineItemWidget.cxx
qtArcWidget.cxx
qtInteractionWidget.cxx
qtLineWidget.cxx
)
set(PQWidgetsUIs
qtArcWidget.ui
qtLineWidget.ui
qtGenerateContoursDialog.ui
)
set(PQWidgetsMocHeaders
pqGenerateContoursDialog.h
pqSMTKAttributeItemWidget.h
pqSMTKBoxItemWidget.h
pqSMTKLineItemWidget.h
pqSMTKPlaneItemWidget.h
pqSMTKPointItemWidget.h
pqSMTKSphereItemWidget.h
pqSMTKSplineItemWidget.h
qtArcWidget.h
qtInteractionWidget.h
qtLineWidget.h
)
set(PQWidgetsHeaders
${PQWidgetsMocHeaders}
pqSMTKAttributeItemWidgetP.h
)
#install the headers
......@@ -51,11 +63,54 @@ target_link_libraries(smtkPQWidgetsExt LINK_PUBLIC
pqApplicationComponents
vtkPVServerManagerRendering
smtkCore
smtkQtExt
Qt5::Core
Qt5::Widgets
)
)
smtk_export_header(smtkPQWidgetsExt Exports.h)
#install the library and exports the library when used from a build tree
smtk_install_library(smtkPQWidgetsExt)
set(PQWidgetsPluginHdrs
pqSMTKWidgetsAutoStart.h
)
set(PQWidgetsPluginSrcs
pqSMTKWidgetsAutoStart.cxx
)
add_paraview_auto_start(PLUGIN_AUTOSTART_IFACES PLUGIN_AUTOSTART_IFACE_SRCS
CLASS_NAME pqSMTKWidgetsAutoStart
STARTUP startup
SHUTDOWN shutdown
)
pv_qt_wrap_cpp(PLUGIN_MOC_SRCS ${PQWidgetsPluginHdrs})
add_paraview_plugin(
smtkPQWidgetsPlugin "1.0"
GUI_INTERFACES
${PLUGIN_ACTION_IFACES}
${PLUGIN_AUTOSTART_IFACES}
${PLUGIN_PROXY_IFACES}
${PLUGIN_DOCK_IFACES}
GUI_SOURCES
${PQWidgetsPluginHdrs}
${PQWidgetsPluginSrcs}
${PLUGIN_MOC_SRCS}
${PLUGIN_ACTION_IFACE_SRCS}
${PLUGIN_AUTOSTART_IFACE_SRCS}
${PLUGIN_PROXY_IFACE_SRCS}
${PLUGIN_DOCK_IFACES_SRCS}
)
set(SMTK_PLUGINS "${SMTK_PLUGINS};smtkPQWidgetsPlugin" CACHE INTERNAL "")
target_link_libraries(smtkPQWidgetsPlugin
LINK_PUBLIC
smtkPQWidgetsExt
)
smtk_export_header(smtkPQWidgetsPlugin PluginExports.h)
#install the library and exports the library when used from a build tree
smtk_install_library(smtkPQWidgetsPlugin)
//=========================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
//
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//=========================================================================
#include "smtk/extension/paraview/widgets/pqSMTKAttributeItemWidget.h"
#include "smtk/extension/paraview/widgets/pqSMTKAttributeItemWidgetP.h"
#include "smtk/attribute/Attribute.h"
#include "smtk/attribute/ValueItem.h"
#include "smtk/attribute/ValueItemDefinition.h"
#include "smtk/model/EntityRef.h"
#include "smtk/io/Logger.h"
#include "pqActiveObjects.h"
#include "pqApplicationCore.h"
#include "pqBoxPropertyWidget.h"
#include "pqDataRepresentation.h"
#include "pqImplicitPlanePropertyWidget.h"
#include "pqObjectBuilder.h"
#include "pqPipelineSource.h"
#include "pqServer.h"
#include "pqSpherePropertyWidget.h"
#include "vtkPVXMLElement.h"
#include "vtkSMNewWidgetRepresentationProxy.h"
#include "vtkSMProperty.h"
#include "vtkSMPropertyGroup.h"
#include "vtkSMPropertyHelper.h"
#include "vtkSMProxy.h"
using namespace smtk::attribute;
using qtItem = smtk::extension::qtItem;
pqSMTKAttributeItemWidget::OverrideWhen pqSMTKAttributeItemWidget::OverrideWhenConvert(
const std::string& str)
{
if (str == "Never" || str == "never")
{
return OverrideWhen::Never;
}
return OverrideWhen::Unset;
}
std::string pqSMTKAttributeItemWidget::OverrideWhenConvert(OverrideWhen val)
{
switch (val)
{
case OverrideWhen::Unset:
return "Unset";
break;
case OverrideWhen::Never:
return "Never";
break;
default:
break;
}
return "Invalid";
}