814
|
1 /**
|
|
2 * Stone of Orthanc
|
|
3 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
|
|
4 * Department, University Hospital of Liege, Belgium
|
|
5 * Copyright (C) 2017-2019 Osimis S.A., Belgium
|
|
6 *
|
|
7 * This program is free software: you can redistribute it and/or
|
|
8 * modify it under the terms of the GNU Affero General Public License
|
|
9 * as published by the Free Software Foundation, either version 3 of
|
|
10 * the License, or (at your option) any later version.
|
|
11 *
|
|
12 * This program is distributed in the hope that it will be useful, but
|
|
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
15 * Affero General Public License for more details.
|
|
16 *
|
|
17 * You should have received a copy of the GNU Affero General Public License
|
|
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
19 **/
|
|
20
|
|
21
|
|
22 #include "DicomVolumeImageMPRSlicer.h"
|
|
23
|
|
24 #include <Core/OrthancException.h>
|
|
25
|
|
26 namespace OrthancStone
|
|
27 {
|
|
28 void DicomVolumeImageMPRSlicer::Slice::CheckValid() const
|
|
29 {
|
|
30 if (!valid_)
|
|
31 {
|
|
32 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
|
|
33 }
|
|
34 }
|
|
35
|
|
36
|
|
37 DicomVolumeImageMPRSlicer::Slice::Slice(const DicomVolumeImage& volume,
|
|
38 const CoordinateSystem3D& cuttingPlane) :
|
|
39 volume_(volume)
|
|
40 {
|
|
41 valid_ = (volume_.HasDicomParameters() &&
|
|
42 volume_.GetGeometry().DetectSlice(projection_, sliceIndex_, cuttingPlane));
|
|
43 }
|
|
44
|
|
45
|
|
46 VolumeProjection DicomVolumeImageMPRSlicer::Slice::GetProjection() const
|
|
47 {
|
|
48 CheckValid();
|
|
49 return projection_;
|
|
50 }
|
|
51
|
|
52
|
|
53 unsigned int DicomVolumeImageMPRSlicer::Slice::GetSliceIndex() const
|
|
54 {
|
|
55 CheckValid();
|
|
56 return sliceIndex_;
|
|
57 }
|
|
58
|
|
59 uint64_t DicomVolumeImageMPRSlicer::Slice::GetRevision()
|
|
60 {
|
|
61 CheckValid();
|
|
62 return GetRevisionInternal(projection_, sliceIndex_);
|
|
63 }
|
|
64
|
|
65
|
|
66 ISceneLayer* DicomVolumeImageMPRSlicer::Slice::CreateSceneLayer(const ILayerStyleConfigurator* configurator,
|
|
67 const CoordinateSystem3D& cuttingPlane)
|
|
68 {
|
|
69 CheckValid();
|
|
70
|
|
71 if (configurator == NULL)
|
|
72 {
|
|
73 throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer,
|
|
74 "A style configurator is mandatory for textures");
|
|
75 }
|
|
76
|
|
77 std::auto_ptr<TextureBaseSceneLayer> texture;
|
|
78
|
|
79 {
|
|
80 const DicomInstanceParameters& parameters = volume_.GetDicomParameters();
|
|
81 ImageBuffer3D::SliceReader reader(volume_.GetPixelData(), projection_, sliceIndex_);
|
|
82 texture.reset(dynamic_cast<TextureBaseSceneLayer*>
|
|
83 (configurator->CreateTextureFromDicom(reader.GetAccessor(), parameters)));
|
|
84 }
|
|
85
|
|
86 const CoordinateSystem3D& system = volume_.GetGeometry().GetProjectionGeometry(projection_);
|
|
87
|
|
88 double x0, y0, x1, y1;
|
|
89 cuttingPlane.ProjectPoint(x0, y0, system.GetOrigin());
|
|
90 cuttingPlane.ProjectPoint(x1, y1, system.GetOrigin() + system.GetAxisX());
|
|
91 texture->SetOrigin(x0, y0);
|
|
92
|
|
93 double dx = x1 - x0;
|
|
94 double dy = y1 - y0;
|
|
95 if (!LinearAlgebra::IsCloseToZero(dx) ||
|
|
96 !LinearAlgebra::IsCloseToZero(dy))
|
|
97 {
|
|
98 texture->SetAngle(atan2(dy, dx));
|
|
99 }
|
|
100
|
|
101 Vector tmp = volume_.GetGeometry().GetVoxelDimensions(projection_);
|
|
102 texture->SetPixelSpacing(tmp[0], tmp[1]);
|
|
103
|
|
104 return texture.release();
|
|
105 }
|
|
106
|
|
107
|
|
108 IVolumeSlicer::IExtractedSlice*
|
|
109 DicomVolumeImageMPRSlicer::ExtractSlice(const CoordinateSystem3D& cuttingPlane)
|
|
110 {
|
|
111 if (volume_->HasGeometry())
|
|
112 {
|
|
113 return new Slice(*volume_, cuttingPlane);
|
|
114 }
|
|
115 else
|
|
116 {
|
|
117 return new IVolumeSlicer::InvalidSlice;
|
|
118 }
|
|
119 }
|
|
120 }
|