Trajectory Pipeline =================== The architecture of the trajectory pipeline is illustrated below: .. _fig_trajectory_pipeline: .. figure:: ./figs/trajectory_pipeline.webp :figwidth: 100 % :align: left :alt: A schematic of the trajectory pipeline. 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.: .. code-block:: cpp MPointSourceFactory::getInstance()->registerPointGeneratingInterface(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 a ``QStringList``. .. 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 a ``MFloatPerTrajectoryVertexSupplement``. * ``MFloatPerTrajectorySource``: Provides a ``MFloatPerTrajectorySupplement``. 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.