comparison Sources/StructureSet.cpp @ 35:ee3bc8f7df5b

reorganization
author Sebastien Jodogne <s.jodogne@gmail.com>
date Thu, 04 Apr 2024 20:37:08 +0200
parents
children
comparison
equal deleted inserted replaced
34:bee2017f3088 35:ee3bc8f7df5b
1 /**
2 * SPDX-FileCopyrightText: 2023-2024 Sebastien Jodogne, UCLouvain, Belgium
3 * SPDX-License-Identifier: GPL-3.0-or-later
4 */
5
6 /**
7 * STL plugin for Orthanc
8 * Copyright (C) 2023-2024 Sebastien Jodogne, UCLouvain, Belgium
9 *
10 * This program is free software: you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License as
12 * published by the Free Software Foundation, either version 3 of the
13 * License, or (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 **/
23
24
25 #include "StructureSet.h"
26
27 #include "STLToolbox.h"
28
29 #include <OrthancException.h>
30
31 #include <dcmtk/dcmdata/dcdeftag.h>
32 #include <dcmtk/dcmdata/dcfilefo.h>
33
34
35 StructureSet::StructureSet(Orthanc::ParsedDicomFile& dicom) :
36 hasFrameOfReferenceUid_(false)
37 {
38 DcmDataset& dataset = *dicom.GetDcmtkObject().getDataset();
39 patientId_ = STLToolbox::GetStringValue(dataset, DCM_PatientID);
40 studyInstanceUid_ = STLToolbox::GetStringValue(dataset, DCM_StudyInstanceUID);
41 seriesInstanceUid_ = STLToolbox::GetStringValue(dataset, DCM_SeriesInstanceUID);
42 sopInstanceUid_ = STLToolbox::GetStringValue(dataset, DCM_SOPInstanceUID);
43
44 DcmSequenceOfItems* frame = NULL;
45 if (!dataset.findAndGetSequence(DCM_ReferencedFrameOfReferenceSequence, frame).good() ||
46 frame == NULL)
47 {
48 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat);
49 }
50
51 if (frame->card() == 1)
52 {
53 const char* v = NULL;
54 if (frame->getItem(0)->findAndGetString(DCM_FrameOfReferenceUID, v).good() &&
55 v != NULL)
56 {
57 hasFrameOfReferenceUid_ = true;
58 frameOfReferenceUid_.assign(v);
59 }
60 }
61
62 DcmSequenceOfItems* rois = NULL;
63 if (!dataset.findAndGetSequence(DCM_ROIContourSequence, rois).good() ||
64 rois == NULL)
65 {
66 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat);
67 }
68
69 std::vector<DcmSequenceOfItems*> contours(rois->card());
70 size_t countPolygons = 0;
71
72 for (unsigned long i = 0; i < rois->card(); i++)
73 {
74 DcmSequenceOfItems* contour = NULL;
75 if (!rois->getItem(i)->findAndGetSequence(DCM_ContourSequence, contour).good() ||
76 contour == NULL)
77 {
78 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat);
79 }
80 else
81 {
82 contours[i] = contour;
83 countPolygons += contour->card();
84 }
85 }
86
87 polygons_.resize(countPolygons);
88
89 size_t pos = 0;
90 for (unsigned long i = 0; i < contours.size(); i++)
91 {
92 for (unsigned long j = 0; j < contours[i]->card(); j++, pos++)
93 {
94 polygons_[pos] = new StructurePolygon(dicom, i, j);
95 }
96 }
97
98 assert(pos == countPolygons);
99 }
100
101
102 StructureSet::~StructureSet()
103 {
104 for (size_t i = 0; i < polygons_.size(); i++)
105 {
106 assert(polygons_[i] != NULL);
107 delete polygons_[i];
108 }
109 }
110
111
112 std::string StructureSet::HashStudy() const
113 {
114 Orthanc::DicomInstanceHasher hasher(patientId_, studyInstanceUid_, seriesInstanceUid_, sopInstanceUid_);
115 return hasher.HashStudy();
116 }
117
118
119 const StructurePolygon& StructureSet::GetPolygon(size_t i) const
120 {
121 if (i >= polygons_.size())
122 {
123 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
124 }
125 else
126 {
127 assert(polygons_[i] != NULL);
128 return *polygons_[i];
129 }
130 }
131
132
133 const std::string& StructureSet::GetFrameOfReferenceUid() const
134 {
135 if (hasFrameOfReferenceUid_)
136 {
137 return frameOfReferenceUid_;
138 }
139 else
140 {
141 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
142 }
143 }
144
145
146 void StructureSet::ListStructuresNames(std::set<std::string>& target,
147 Orthanc::ParsedDicomFile& source)
148 {
149 target.clear();
150
151 DcmSequenceOfItems* sequence = NULL;
152 if (!source.GetDcmtkObject().getDataset()->findAndGetSequence(DCM_StructureSetROISequence, sequence).good() ||
153 sequence == NULL)
154 {
155 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat);
156 }
157
158 for (unsigned long i = 0; i < sequence->card(); i++)
159 {
160 DcmItem* item = sequence->getItem(i);
161 if (item == NULL)
162 {
163 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat);
164 }
165 else
166 {
167 target.insert(STLToolbox::GetStringValue(*item, DCM_ROIName));
168 }
169 }
170 }