fw4spl
writer/tid/Measurement.cpp
1 /* ***** BEGIN LICENSE BLOCK *****
2  * FW4SPL - Copyright (C) IRCAD, 2009-2018.
3  * Distributed under the terms of the GNU Lesser General Public License (LGPL) as
4  * published by the Free Software Foundation.
5  * ****** END LICENSE BLOCK ****** */
6 
7 #include "fwGdcmIO/writer/tid/Measurement.hpp"
8 
9 #include "fwGdcmIO/container/DicomCodedAttribute.hpp"
10 #include "fwGdcmIO/container/sr/DicomSRCodeNode.hpp"
11 #include "fwGdcmIO/container/sr/DicomSRImageNode.hpp"
12 #include "fwGdcmIO/container/sr/DicomSRNumNode.hpp"
13 #include "fwGdcmIO/container/sr/DicomSRSCoord3DNode.hpp"
14 #include "fwGdcmIO/container/sr/DicomSRSCoordNode.hpp"
15 #include "fwGdcmIO/container/sr/DicomSRTextNode.hpp"
16 #include "fwGdcmIO/container/sr/DicomSRUIDRefNode.hpp"
17 #include "fwGdcmIO/helper/DicomDataTools.hpp"
18 
19 #include <fwData/PointList.hpp>
20 #include <fwData/String.hpp>
21 #include <fwData/Vector.hpp>
22 
23 #include <fwDataTools/fieldHelper/Image.hpp>
24 
25 #include <fwMedData/Series.hpp>
26 #include <fwMedData/types.hpp>
27 
28 #include <fwTools/Stringizer.hpp>
29 
30 #include <boost/algorithm/string/split.hpp>
31 
32 #include <sstream>
33 
34 namespace fwGdcmIO
35 {
36 namespace writer
37 {
38 namespace tid
39 {
40 
41 //------------------------------------------------------------------------------
42 
43 Measurement::Measurement(const SPTR(::gdcm::Writer)& writer,
44  const SPTR(::fwGdcmIO::container::DicomInstance)& instance,
45  const ::fwData::Image::csptr& image) :
46  ::fwGdcmIO::writer::tid::TemplateID< ::fwData::Image >(writer, instance, image)
47 {
48 }
49 
50 //------------------------------------------------------------------------------
51 
53 {
54 }
55 
56 //------------------------------------------------------------------------------
57 
59  bool useSCoord3D)
60 {
61  ::fwData::Vector::sptr distanceVector =
63  if (distanceVector)
64  {
65  unsigned int id = 1;
66  for(::fwData::Object::sptr object : distanceVector->getContainer())
67  {
68  ::fwData::PointList::sptr pointList = ::fwData::PointList::dynamicCast(object);
69  if(pointList)
70  {
71  this->createMeasurement(parent, pointList, id++, useSCoord3D);
72  }
73  }
74  }
75 }
76 
77 //------------------------------------------------------------------------------
78 
80  const ::fwData::PointList::csptr& pointList,
81  unsigned int id,
82  bool useSCoord3D)
83 {
84  const ::fwData::Point::sptr point1 = pointList->getPoints()[0];
85  const ::fwData::Point::sptr point2 = pointList->getPoints()[1];
86 
87  double coordinates[6];
88  coordinates[0] = point1->getCoord()[0];
89  coordinates[1] = point1->getCoord()[1];
90  coordinates[2] = point1->getCoord()[2];
91  coordinates[3] = point2->getCoord()[0];
92  coordinates[4] = point2->getCoord()[1];
93  coordinates[5] = point2->getCoord()[2];
94 
95  const double distance = sqrt( (coordinates[0] - coordinates[3]) * (coordinates[0] - coordinates[3]) +
96  (coordinates[1] - coordinates[4]) * (coordinates[1] - coordinates[4]) +
97  (coordinates[2] - coordinates[5]) * (coordinates[2] - coordinates[5]) );
98 
99  // Retrieve Frame Numbers
100  const std::size_t frameNumber1 = ::fwGdcmIO::helper::DicomDataTools::convertPointToFrameNumber(m_object, point1);
101 
102  // Create Measurement Node
104  std::make_shared< ::fwGdcmIO::container::sr::DicomSRNumNode >(
105  ::fwGdcmIO::container::DicomCodedAttribute("121206", "DCM", "Distance"), "CONTAINS", distance,
106  ::fwGdcmIO::container::DicomCodedAttribute("mm", "UCUM", "millimeter", "1.4"));
107  parent->addSubNode(numNode);
108 
109  if(useSCoord3D)
110  {
111  // Create SCoord Node
112  const float scoord[] = {
113  static_cast<float>(point1->getCoord()[0]),
114  static_cast<float>(point1->getCoord()[1]),
115  static_cast<float>(point1->getCoord()[2]),
116  static_cast<float>(point2->getCoord()[0]),
117  static_cast<float>(point2->getCoord()[1]),
118  static_cast<float>(point2->getCoord()[2])
119  };
120  std::vector<float> scoordVector(scoord, scoord + 6);
122  std::make_shared< ::fwGdcmIO::container::sr::DicomSRSCoord3DNode >(
123  ::fwGdcmIO::container::DicomCodedAttribute("121230", "DCM", "Path"),
124  "INFERRED FROM", "POLYLINE", scoordVector, m_instance->getSOPInstanceUIDContainer()[0]);
125  numNode->addSubNode(scoordNode);
126  }
127  else
128  {
129  SLM_ASSERT("Unable to save a 3D distance using a SCOORD object.",
131 
132  // Create SCoord Node
133  const float scoord[] = {
134  static_cast<float>(point1->getCoord()[0]),
135  static_cast<float>(point1->getCoord()[1]),
136  static_cast<float>(point2->getCoord()[0]),
137  static_cast<float>(point2->getCoord()[1])
138  };
139  std::vector<float> scoordVector(scoord, scoord + 4);
141  std::make_shared< ::fwGdcmIO::container::sr::DicomSRSCoordNode >(
142  ::fwGdcmIO::container::DicomCodedAttribute("121230", "DCM", "Path"),
143  "INFERRED FROM", "POLYLINE", scoordVector);
144  numNode->addSubNode(scoordNode);
145 
146  // Create Image Node
148  std::make_shared< ::fwGdcmIO::container::sr::DicomSRImageNode >(
149  ::fwGdcmIO::container::DicomCodedAttribute(), "SELECTED FROM", m_instance->getSOPClassUID(),
150  m_instance->getSOPInstanceUIDContainer()[frameNumber1-1], frameNumber1);
151  scoordNode->addSubNode(imageNode);
152  }
153 
154 }
155 
156 //------------------------------------------------------------------------------
157 
158 } // namespace tid
159 } // namespace writer
160 } // namespace fwGdcmIO
#define SPTR(_cls_)
std::shared_ptr< const ::fwData::Image > m_object
FW4SPL Object.
virtual FWGDCMIO_API void createNodes(const std::shared_ptr< ::fwGdcmIO::container::sr::DicomSRNode > &parent, bool useSCoord3D=true)
Create nodes according to the template.
This class defines a DICOM SOP instance. It is useful during the whole writing process. This class allows to share data between module writers.
This class defines an IMAGE node in a SR document.
TemplateID base class used to write templates.
The namespace fwGdcmIO contains reader, writer and helper for dicom data.
This class defines a node in a SR document.
Definition: DicomSRNode.hpp:27
This class defines a vector of objects.
This class represents a DICOM basic coded entry. It stores the four mains attributes : Code Value...
std::shared_ptr< ::fwGdcmIO::container::DicomInstance > m_instance
DICOM Instance.
#define SLM_ASSERT(message, cond)
work like &#39;assert&#39; from &#39;cassert&#39;, with in addition a message logged by spylog (with FATAL loglevel) ...
Definition: spyLog.hpp:308
This class defines a SCOORD node in a SR document.
This class defines a NUM node in a SR document.
void createMeasurement(const std::shared_ptr< ::fwGdcmIO::container::sr::DicomSRNode > &parent, const std::shared_ptr< const ::fwData::PointList > &pointList, unsigned int id, bool useSCoord3D)
Create a measurement node.
FWGDCMIO_API void addSubNode(const std::shared_ptr< DicomSRNode > &node)
Add a sub node.
Definition: DicomSRNode.cpp:37
Contains the representation of the data objects used in the framework.
This class defines a SCOORD3D node in a SR document.
FWGDCMIO_API Measurement(const std::shared_ptr< ::gdcm::Writer > &writer, const std::shared_ptr< ::fwGdcmIO::container::DicomInstance > &instance, const ::fwData::Image::csptr &image)
Constructor.
static FWGDCMIO_API std::size_t convertPointToFrameNumber(const ::fwData::Image::csptr &image, const ::fwData::Point::csptr &point)
Convert a 3D point to the closest frame number index.
virtual FWGDCMIO_API ~Measurement()
Destructor.