GCC Code Coverage Report


./
File: libs/io/dicom/writer/tid/measurement.cpp
Date: 2025-01-21 16:21:04
Lines:
0/67
0.0%
Functions:
0/4
0.0%
Branches:
0/136
0.0%

Line Branch Exec Source
1 /************************************************************************
2 *
3 * Copyright (C) 2009-2023 IRCAD France
4 * Copyright (C) 2012-2018 IHU Strasbourg
5 *
6 * This file is part of Sight.
7 *
8 * Sight is free software: you can redistribute it and/or modify it under
9 * the terms of the GNU Lesser General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * Sight is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with Sight. If not, see <https://www.gnu.org/licenses/>.
20 *
21 ***********************************************************************/
22
23 #include "io/dicom/writer/tid/measurement.hpp"
24
25 #include "io/dicom/container/dicom_coded_attribute.hpp"
26 #include "io/dicom/container/sr/dicom_sr_code_node.hpp"
27 #include "io/dicom/container/sr/dicom_sr_image_node.hpp"
28 #include "io/dicom/container/sr/dicom_sr_num_node.hpp"
29 #include "io/dicom/container/sr/dicom_sr_text_node.hpp"
30 #include "io/dicom/container/sr/dicom_srs_coord3dnode.hpp"
31 #include "io/dicom/container/sr/dicom_srs_coord_node.hpp"
32 #include "io/dicom/container/sr/dicom_sruid_ref_node.hpp"
33 #include "io/dicom/helper/dicom_data_tools.hpp"
34
35 #include <data/helper/medical_image.hpp>
36 #include <data/point_list.hpp>
37 #include <data/series.hpp>
38 #include <data/string.hpp>
39 #include <data/types.hpp>
40 #include <data/vector.hpp>
41
42 #include <boost/algorithm/string/split.hpp>
43
44 #include <sstream>
45
46 namespace sight::io::dicom::writer::tid
47 {
48
49 //------------------------------------------------------------------------------
50
51 measurement::measurement(
52 const SPTR(gdcm::Writer)& _writer,
53 const SPTR(io::dicom::container::dicom_instance)& _instance,
54 const data::image::csptr& _image
55 ) :
56 io::dicom::writer::tid::template_id<data::image>(_writer, _instance, _image)
57 {
58 }
59
60 //------------------------------------------------------------------------------
61
62 measurement::~measurement()
63 = default;
64
65 //------------------------------------------------------------------------------
66
67 void measurement::create_nodes(
68 const SPTR(io::dicom::container::sr::dicom_sr_node)& _parent,
69 bool _use_s_coord_3d
70 )
71 {
72 data::vector::sptr distance_vector = data::helper::medical_image::get_distances(*m_object);
73 if(distance_vector)
74 {
75 unsigned int id = 1;
76 for(const data::object::sptr& object : *distance_vector)
77 {
78 data::point_list::sptr point_list = std::dynamic_pointer_cast<data::point_list>(object);
79 if(point_list)
80 {
81 this->create_measurement(_parent, point_list, id++, _use_s_coord_3d);
82 }
83 }
84 }
85 }
86
87 //------------------------------------------------------------------------------
88
89 void measurement::create_measurement(
90 const SPTR(io::dicom::container::sr::dicom_sr_node)& _parent,
91 const data::point_list::csptr& _point_list,
92 unsigned int /*id*/,
93 bool _use_s_coord_3d
94 )
95 {
96 const data::point::sptr point1 = _point_list->get_points()[0];
97 const data::point::sptr point2 = _point_list->get_points()[1];
98
99 std::array coordinates {
100 point1->get_coord()[0],
101 point1->get_coord()[1],
102 point1->get_coord()[2],
103 point2->get_coord()[0],
104 point2->get_coord()[1],
105 point2->get_coord()[2]
106 };
107
108 const double distance = sqrt(
109 (coordinates[0] - coordinates[3]) * (coordinates[0] - coordinates[3])
110 + (coordinates[1] - coordinates[4]) * (coordinates[1] - coordinates[4])
111 + (coordinates[2] - coordinates[5]) * (coordinates[2] - coordinates[5])
112 );
113
114 // Retrieve Frame Numbers
115 const std::size_t frame_number1 = io::dicom::helper::dicom_data_tools::convert_point_to_frame_number(
116 m_object,
117 point1
118 );
119
120 // Create Measurement Node
121 // cspell: ignore UCUM
122 SPTR(io::dicom::container::sr::dicom_sr_num_node) num_node =
123 std::make_shared<io::dicom::container::sr::dicom_sr_num_node>(
124 io::dicom::container::dicom_coded_attribute("121206", "DCM", "Distance"),
125 "CONTAINS",
126 distance,
127 io::dicom::container::dicom_coded_attribute("mm", "UCUM", "millimeter", "1.4")
128 );
129 _parent->add_sub_node(num_node);
130
131 if(_use_s_coord_3d)
132 {
133 // Create SCoord Node
134 std::vector<float> scoord_vector {
135 static_cast<float>(point1->get_coord()[0]),
136 static_cast<float>(point1->get_coord()[1]),
137 static_cast<float>(point1->get_coord()[2]),
138 static_cast<float>(point2->get_coord()[0]),
139 static_cast<float>(point2->get_coord()[1]),
140 static_cast<float>(point2->get_coord()[2])
141 };
142 SPTR(io::dicom::container::sr::dicom_srs_coord3_d_node) scoord_node =
143 std::make_shared<io::dicom::container::sr::dicom_srs_coord3_d_node>(
144 io::dicom::container::dicom_coded_attribute("121230", "DCM", "Path"),
145 "INFERRED FROM",
146 "POLYLINE",
147 scoord_vector,
148 m_instance->get_sop_instance_uid_container()[0]
149 );
150 num_node->add_sub_node(scoord_node);
151 }
152 else
153 {
154 SIGHT_ASSERT(
155 "Unable to save a 3D distance using a SCOORD object.",
156 frame_number1 == io::dicom::helper::dicom_data_tools::convert_point_to_frame_number(m_object, point2)
157 );
158
159 // Create SCoord Node
160 std::vector<float> scoord_vector {
161 static_cast<float>(point1->get_coord()[0]),
162 static_cast<float>(point1->get_coord()[1]),
163 static_cast<float>(point2->get_coord()[0]),
164 static_cast<float>(point2->get_coord()[1])
165 };
166 SPTR(io::dicom::container::sr::dicom_srs_coord_node) scoord_node =
167 std::make_shared<io::dicom::container::sr::dicom_srs_coord_node>(
168 io::dicom::container::dicom_coded_attribute("121230", "DCM", "Path"),
169 "INFERRED FROM",
170 "POLYLINE",
171 scoord_vector
172 );
173 num_node->add_sub_node(scoord_node);
174
175 // Create Image Node
176 SPTR(io::dicom::container::sr::dicom_sr_image_node) image_node =
177 std::make_shared<io::dicom::container::sr::dicom_sr_image_node>(
178 io::dicom::container::dicom_coded_attribute(),
179 "SELECTED FROM",
180 m_instance->get_sop_class_uid(),
181 m_instance->get_sop_instance_uid_container()[frame_number1 - 1],
182 int(frame_number1)
183 );
184 scoord_node->add_sub_node(image_node);
185 }
186 }
187
188 //------------------------------------------------------------------------------
189
190 } // namespace sight::io::dicom::writer::tid
191