comparison OrthancStone/Resources/Graveyard/RTStructTentativeReimplementation-BGO/DicomStructure2.h @ 1908:affde38b84de

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