(core): rework SExtractObj
Description
SExtractObj is used to get references of sub-objects in an XML configuration. In the Tuto08GenericScene for instance, it is used to get the image from an image series:
<service uid="extractImageSrv" type="sight::module::data::SExtractObj" >
<inout key="source" uid="imageSeries" >
<extract from="@image" />
</inout>
<out group="target" >
<key uid="image" />
</out>
</service>
However, it is problematic because it relies on object reflection, thus on the library camp, which is deprecated since Sight 21. We want to remove it asap (see #786 (closed)).
Proposal
To overcome this, we think it is simpler to have specific services for each data type. Actually, we have very few cases and treating them individually would not be such a pain. It might even be easier to use at the end.
In the Sight repository here are the different cases we can find:
- imageSeries -> image
- cameraSeries -> camera1, camera2, extrinsicMatrix
- seriesDB -> series (imageSeries, modelSeries, cameraSeries, ...)
- modelSeries -> mesh
That means we would have four different services instead of one. They should all be part of sight::module::data
.
Each service should be developed with its unit tests. A minimal unit test sample is provided on the branch module-unittest-sample (with sight 21 it is no longer required to have a profile to unit tests modules). Just remind that modules can not be linked with, so you can only work with interfaces and factories.
In the end, the service SExtractObj must be removed and its occurrences in XML files should be replaced by the new services.
In the following sections, implementation details are given for each service.
module::core::data::SGetImage
An ImageSeries only contains one image. So the XML configuration is fairly simple:
<service uid="..." type="sight::module::data::SGetImage" >
<inout key="imageSeries" uid="..." />
<out key="image" uid="..." />
</service>
where:
- imageSeries is a
sight::data::ImageSeries
- image is a
sight::data::Image
module::core::data::SGetSeries
Since a series DB can store an infinite number of series, we must explicitly provide an index to indicate which element we want to extract.
<service uid="..." type="sight::module::data::SGetSeries" >
<inout key="seriesDB" uid="..."/>
<out group="series" >
<key index="4" uid="..." />
<key index="2" uid="..." />
</out>
</service>
where:
- seriesDB is a
sight::data::SeriesDB
- series group data are
sight::data::Series
module::core::data::SGetCamera
Since a camera series can have an infinite number of cameras and extrinsic matrices, we must explicitly provide an index to indicate which element we want to extract.
<service uid="..." type="sight::module::data::SGetCamera" >
<inout key="cameraSeries" uid="..."/>
<out group="camera" >
<key index="0" uid="..." />
<key index="1" uid="..." />
</out>
<out group="extrinsic" >
<key index="1" uid="..." />
</out>
</service>
where:
- cameraSeries is a
sight::data::CameraSeries
- camera group data are
sight::data::Camera
- extrinsic matrix data are
sight::data::Matrix4
module::core::data::SGetMesh
The last service configuration will be a bit more complex. Indeed, we already have a service that can extract meshes from a model given their type. Here is its current configuration:
<service uid="..." type="sight::module::data::SExtractMeshByType" >
<inout key="source" uid="...">
<extract type="organ1" />
<extract type="organ2" matching="(.*)surface(.*)"/>
</inout>
<out group="target">
<key uid="..."/>
<key uid="..."/>
</out>
</service>
We could simply make it a bit more generic. We should:
- add the possibility to set an index instead of a type
- simplify the configuration to match the layout of the other 3 services, by putting the parameters in the out group, and setting more meaningful key names.
- rename the service to
SGetMesh
At the end, we should have a configuration that looks like:
<service uid="..." type="sight::module::data::SGetMesh" >
<inout key="modelSeries" uid="..." />
<out group="mesh">
<key index="3" uid="..."/>
<key type="organ1" uid="..."/>
<key type="organ2" matching="(.*)surface(.*)" uid="..."/>
</out>
</service>
where:
- modelSeries is a
sight::data::ModelSeries
- mesh group data are
sight::data::Mesh
Outcomes
This might be clearer to use. It was not really easy to understand how to write a "camp path". At above all, this is one more step on our way to get rid of camp.
Development plan
The issues was split in four implementation tickets to make the review easier:
When everything is done, SExtractObj
can be removed.