Trajectory Pipeline
The architecture of the trajectory pipeline is illustrated below:

Fig. 34 Trajectory pipeline schematic.
Point Generating Sources
The MPointGeneratorSource
generates a list of points packed into a
MPoints
data item, managed in memory. It requests a
MPointGeneratorInterface
to generate the points. The horizontal
cross-section and vertical cross-section actors implement this interface
and provide the necessary methods for point generation based on the
actor’s current state and user interface.
To implement a custom point source, have the class inherit from
MPointGeneratorInterface
and implement the following abstract methods:
QString getPointGeneratingSourceBaseRequestKeys()
: Generates a clear, identifiable string based on its current state (e.g., current slice position) and user interface. This string should consistently yield the same set of generated points in the subsequent method.MPoints* generatePointsFromString(const QString&)
: Generates the data item containing the list of points based on the provided request string.
Register the interface with MPointSourceFactory
in the constructor, e.g.:
MPointSourceFactory::getInstance()->registerPointGeneratingInterface<MPointGeneratorInterfaceSettings>(this);
The template argument must be a class inheriting from
MPointGeneratorInterfaceSettings
, containing the user interface settings.
Remember to deregister the interface upon deletion. Use
MPointSourceFactory::showCreationDialog()
to display a dialog
allowing the user to select a point generation interface from the registered ones.
Point Filters
Point filters inherit from MPointFilter
and accept a MPoints
data
item as input, returning an altered MPoints
data item. Each filter
has a MPointSource
as its parent, which may be either a
MPointGeneratorSource
or another MPointFilter
.
To create a new point filter, inherit from MPointFilter
, implement
the necessary methods and functionality, and register it in the
MPointFilterFactory::MPointFilterFactory()
constructor. You need to
implement:
produceData()
: Contains the filtering heuristic.getFilterName()
: Returns the general display name of the filter.getBaseRequestKeys()
: Returns the base keys for data requests as aQStringList
.Note
The keys returned should be unique for the filter type, not for specific instances. Met.3D generates unique identifiers for data requests from these base keys, allowing multiple instances of the same filter in one pipeline without conflicts. Met.3D manages registered filters and assigns unique request identifiers for them, e.g., by appending
_1
to the filter’s base request identifier.
Like point sources, a user interface class inheriting from
MPointFilterSettings
is required to describe the UI and handle
settings for the filter. Refer to existing filters for examples.
Trajectory Sources
Precomputed trajectories are loaded via MTrajectoryReader
, while
on-the-fly computed trajectories are generated through
MTrajectoryComputationSource
. The computation process is encapsulated
in the MTrajectoryComputation
class. Trajectory sources return a
MTrajectories
data item, containing the vertex data of the trajectories
along with some metadata.
Trajectory Filters
As shown in the schematic above, trajectory filters are connected downstream
to the trajectory source. A MTrajectoryFilter
processes input from both
MTrajectoryDataSource
(the trajectories) and
MTrajectorySelectionSource
(the trajectory selection), returning a
trajectory selection. These filters can:
Discard entire trajectories.
Discard segments of trajectories.
Currently implemented trajectory filters include:
Trajectory ascent and descent filter,
Trajectory bounding box filter,
Trajectory thin-out filter.
Single Point Filter
The MSingleTimeTrajectoryFilter
extracts single time position data from
the trajectories, used for rendering spheres at points in time selected in
the user interface. It returns a MWritableTrajectorySelection
, but
specifically includes only subsets of trajectories with length 1.
Normals Source
The MTrajectoryNormalsSource
computes normal directions along all
trajectories, essential for accurate rendering and shading. The returned
data item is a MTrajectoryNormals
.
Note
Normal directions depend on the vertical scale of the scene. Thus,
normals must be computed separately for each scene, resulting
in an additional layer of lists within the MTrajectoryNormals
data item: normals per scene view.
Auxiliary Data Sources
Additional data can be computed and included in the trajectory collection, either for individual vertices or entire trajectories. These supplementary data sources include:
MFloatPerTrajectoryVertexSource
: Provides aMFloatPerTrajectoryVertexSupplement
.MFloatPerTrajectorySource
: Provides aMFloatPerTrajectorySupplement
.
The MAuxiliaryVariableTrajectorySource
generates per-vertex data based
on auxiliary data fields, enabling trajectory rendering with these fields.
Alternatively, the MDeltaPressurePerTrajectorySource
demonstrates the
float per trajectory source by calculating the maximum pressure change
along a trajectory within a specified time interval.
The Trajectory Pipeline Barrier
The MTrajectoryPipelineManager
has dual responsibilities: it controls
the pipeline, ensuring proper connections between elements (filters, etc.),
and it adds new sources and filters as requested. It switches the pipeline
structure when changing from a precomputed source to a computational source and
vice versa.
Additionally, it functions as a data source gateway for all requested
trajectory data, including norms, auxiliary fields, single time positions, etc.
In its produceData()
, it does not perform calculations directly but
aggregates data from all upstream sources in the diagram, encapsulating them
in a MTrajectoryDataCollection
and returning this collection. This
approach informs the requester only after all computations are complete.
Note
Due to the current state of memory management in Met.3D, the
MTrajectoryPipelineManager
holds no “real” data; instead, the
MTrajectoryDataCollection
contains references to other data items.
It is crucial to ensure that the memory manager does not delete
upstream data items before the MTrajectoryDataCollection
is deleted.
This is currently achieved by not releasing data items in the
produceData()
method, thus retaining one additional reference
to the depended items. Once the data item is deleted in the destructor,
it releases those references, allowing their deletion.
The Trajectory Dispatcher
The MTrajectoryRequestDispatcher
manages the trajectory pipelines. Each
point source is linked to a dedicated pipeline, allowing efficient caching
of computation results. When a point source changes, only the points for that
source are used to recompute the corresponding trajectories.
Similar to the pipeline, it serves as a barrier, holding references to both the pipeline and the associated data item references to collections returned by the pipelines.