comparison OrthancStone/Sources/Toolbox/DicomStructure2.h @ 1512:244ad1e4e76a

reorganization of folders
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 07 Jul 2020 16:21:02 +0200
parents Framework/Toolbox/DicomStructure2.h@2d8ab34c8c91
children 8563ea5d8ae4
comparison
equal deleted inserted replaced
1511:9dfeee74c1e6 1512:244ad1e4e76a
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-2020 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 #pragma once
22
23 #ifdef BGO_ENABLE_DICOMSTRUCTURESETLOADER2
24
25 #include "DicomStructurePolygon2.h"
26 #include "DicomStructureSetUtils.h"
27
28 namespace OrthancStone
29 {
30
31 /*
32 A structure has a color, a name, a set of slices..
33
34 Each slice is a polygon.
35 */
36 struct DicomStructure2
37 {
38 DicomStructure2() :
39 red_(0), green_(0), blue_(0), sliceThickness_(0), state_(Building) {}
40
41 void AddPolygon(const DicomStructurePolygon2& polygon);
42
43 /**
44 Once all polygons have been added, this method will determine:
45 - the slice orientation (through the normal vector)
46 - the spacing between slices (slice thickness)
47
48 it will also set up the info required to efficiently compute plane
49 intersections later on.
50 */
51 void ComputeDependentProperties();
52
53 /**
54 Being given a plane that is PARALLEL to the set of polygon structures, this
55 returns a pointer to the polygon located at that position (if it is closer
56 than thickness/2) or NULL if there is none.
57
58 TODO: use sorted vector to improve
59
60 DO NOT STORE THE RETURNED POINTER!
61 */
62 const DicomStructurePolygon2* GetPolygonClosestToSlice(const CoordinateSystem3D& plane) const;
63
64 Vector GetNormal() const;
65
66 Color GetColor() const
67 {
68 return Color(red_, green_, blue_);
69 }
70
71 bool IsValid() const
72 {
73 return state_ == Valid;
74 }
75
76 /**
77 This method is used to project the 3D structure on a 2D plane.
78
79 A structure is a stack of polygons, representing a volume.
80
81 We need to compute the intersection between this volume and the supplied
82 cutting plane (the "slice"). This is more than a cutting plane: it is also
83 a 2D-coordinate system (the plane has axes vectors)
84
85 The cutting plane is always parallel to the plane defined by two of the
86 world coordinate system axes.
87
88 The result is a set of closed polygons.
89
90 If the cut is parallel to the polygons, we pick the polygon closest to
91 the slice, project it on the slice and return it in slice coordinates.
92
93 If the cut is perpendicular to the polygons, for each polygon, we compute
94 the intersection between the cutting plane and the polygon slab (imaginary
95 volume created by extruding the polygon above and below its plane by
96 thickness/2) :
97 - each slab, intersected by the plane, gives a set of 0..* rectangles \
98 (only one if the polygon is convex)
99 - when doing this for the whole stack of slabs, we get a set of rectangles:
100 To compute these rectangles, for each polygon, we compute the intersection
101 between :
102 - the line defined by the intersection of the polygon plane and the cutting
103 plane
104 - the polygon itself
105 This yields 0 or 2*K points along the line C. These are turned into K
106 rectangles by taking two consecutive points along the line and extruding
107 this segment by sliceThickness/2 in the orientation of the polygon normal,
108 in both directions.
109
110 Then, once this list of rectangles is computed, we need to group the
111 connected rectangles together. Connected, here, means sharing at least part
112 of an edge --> union/find data structures and algorithm.
113 */
114 bool Project(std::vector< std::pair<Point2D, Point2D> >& polygons, const CoordinateSystem3D& plane) const;
115
116 std::string interpretation_;
117 std::string name_;
118 uint8_t red_;
119 uint8_t green_;
120 uint8_t blue_;
121
122 /** Internal */
123 const std::vector<DicomStructurePolygon2>& GetPolygons() const
124 {
125 return polygons_;
126 }
127
128 /** Internal */
129 double GetSliceThickness() const
130 {
131 return sliceThickness_;
132 }
133
134 private:
135 enum State
136 {
137 Building,
138 NormalComputed,
139 Valid, // When normal components AND slice thickness are computed
140 Invalid
141 };
142
143 void ComputeNormal();
144 void ComputeSliceThickness();
145
146 std::vector<DicomStructurePolygon2> polygons_;
147 Vector3D normal_;
148 double sliceThickness_;
149
150 /*
151 After creation (and while polygons are added), state is Building.
152 After ComputeDependentProperties() is called, state can either be
153 Valid or Invalid. In any case, the object becomes immutable.
154 */
155 State state_;
156 };
157 }
158
159 #endif
160 // BGO_ENABLE_DICOMSTRUCTURESETLOADER2
161