Mercurial > hg > orthanc-stone
comparison Framework/Radiography/RadiographyMaskLayer.cpp @ 488:aede9b042cb7 am-touch-events
now using ImageProcessing::FillPolygon
author | am@osimis.io |
---|---|
date | Tue, 19 Feb 2019 11:40:14 +0100 |
parents | 159a465e27bd |
children | 77e0eb83ff63 |
comparison
equal
deleted
inserted
replaced
487:e4febcef669e | 488:aede9b042cb7 |
---|---|
48 double sceneY) const | 48 double sceneY) const |
49 { | 49 { |
50 return dicomLayer_.GetPixel(imageX, imageY, sceneX, sceneY); | 50 return dicomLayer_.GetPixel(imageX, imageY, sceneX, sceneY); |
51 } | 51 } |
52 | 52 |
53 | |
54 void ComputeMaskExtent(unsigned int& left, unsigned int& right, unsigned int& top, unsigned int& bottom, const std::vector<MaskPoint>& corners) | |
55 { | |
56 left = std::numeric_limits<unsigned int>::max(); | |
57 right = std::numeric_limits<unsigned int>::min(); | |
58 top = std::numeric_limits<unsigned int>::max(); | |
59 bottom = std::numeric_limits<unsigned int>::min(); | |
60 | |
61 for (size_t i = 0; i < corners.size(); i++) | |
62 { | |
63 const MaskPoint& p = corners[i]; | |
64 left = std::min(p.x, left); | |
65 right = std::max(p.x, right); | |
66 bottom = std::max(p.y, bottom); | |
67 top = std::min(p.y, top); | |
68 } | |
69 } | |
70 | |
71 std::string RadiographyMaskLayer::GetInstanceId() const | 53 std::string RadiographyMaskLayer::GetInstanceId() const |
72 { | 54 { |
73 return dicomLayer_.GetInstanceId(); | 55 return dicomLayer_.GetInstanceId(); |
74 } | 56 } |
75 | 57 |
76 void RadiographyMaskLayer::SetCorner(const MaskPoint& corner, size_t index) | 58 void RadiographyMaskLayer::SetCorner(const Orthanc::ImageProcessing::ImagePoint& corner, size_t index) |
77 { | 59 { |
78 if (index < corners_.size()) | 60 if (index < corners_.size()) |
79 corners_[index] = corner; | 61 corners_[index] = corner; |
80 else | 62 else |
81 corners_.push_back(corner); | 63 corners_.push_back(corner); |
82 invalidated_ = true; | 64 invalidated_ = true; |
83 } | 65 } |
84 | 66 |
85 void RadiographyMaskLayer::SetCorners(const std::vector<MaskPoint>& corners) | 67 void RadiographyMaskLayer::SetCorners(const std::vector<Orthanc::ImageProcessing::ImagePoint>& corners) |
86 { | 68 { |
87 corners_ = corners; | 69 corners_ = corners; |
88 invalidated_ = true; | 70 invalidated_ = true; |
89 } | 71 } |
90 | 72 |
144 } | 126 } |
145 } | 127 } |
146 | 128 |
147 void RadiographyMaskLayer::DrawMask() const | 129 void RadiographyMaskLayer::DrawMask() const |
148 { | 130 { |
149 unsigned int left; | |
150 unsigned int right; | |
151 unsigned int top; | |
152 unsigned int bottom; | |
153 | |
154 ComputeMaskExtent(left, right, top, bottom, corners_); | |
155 | |
156 // first fill the complete image | 131 // first fill the complete image |
157 Orthanc::ImageProcessing::Set(*mask_, OUT_MASK_VALUE); | 132 Orthanc::ImageProcessing::Set(*mask_, OUT_MASK_VALUE); |
158 | 133 |
159 { | 134 // fill mask |
160 // from http://alienryderflex.com/polygon_fill/ | 135 Orthanc::ImageProcessing::FillPolygon(*mask_, corners_, IN_MASK_VALUE); |
161 std::auto_ptr<int> raiiNodeX(new int(corners_.size())); | |
162 | 136 |
163 // convert all control points to double only once | |
164 std::vector<double> cpx; | |
165 std::vector<double> cpy; | |
166 int cpSize = corners_.size(); | |
167 for (size_t i = 0; i < corners_.size(); i++) | |
168 { | |
169 cpx.push_back((double)corners_[i].x); | |
170 cpy.push_back((double)corners_[i].y); | |
171 } | |
172 | |
173 std::vector<int> nodeX; | |
174 nodeX.resize(cpSize); | |
175 int nodes, pixelX, pixelY, i, j, swap ; | |
176 | |
177 // Loop through the rows of the image. | |
178 for (pixelY = (int)top; pixelY < (int)bottom; pixelY++) | |
179 { | |
180 double y = (double)pixelY; | |
181 // Build a list of nodes. | |
182 nodes = 0; | |
183 j = cpSize - 1; | |
184 | |
185 for (i = 0; i < cpSize; i++) | |
186 { | |
187 if ((cpy[i] < y && cpy[j] >= y) | |
188 || (cpy[j] < y && cpy[i] >= y)) | |
189 { | |
190 nodeX[nodes++]= (int)(cpx[i] + (y - cpy[i])/(cpy[j] - cpy[i]) *(cpx[j] - cpx[i])); | |
191 } | |
192 j=i; | |
193 } | |
194 | |
195 // Sort the nodes, via a simple “Bubble” sort. | |
196 i=0; | |
197 while (i < nodes-1) | |
198 { | |
199 if (nodeX[i] > nodeX[i+1]) | |
200 { | |
201 swap = nodeX[i]; | |
202 nodeX[i] = nodeX[i+1]; | |
203 nodeX[i+1] = swap; | |
204 if (i) | |
205 i--; | |
206 } | |
207 else | |
208 { | |
209 i++; | |
210 } | |
211 } | |
212 | |
213 unsigned char* row = reinterpret_cast<unsigned char*>(mask_->GetRow(pixelY)); | |
214 // Fill the pixels between node pairs. | |
215 for (i=0; i<nodes; i+=2) | |
216 { | |
217 if (nodeX[i ]>=(int)right) | |
218 break; | |
219 if (nodeX[i+1]>= (int)left) | |
220 { | |
221 if (nodeX[i ]< (int)left ) | |
222 nodeX[i ]=(int)left ; | |
223 if (nodeX[i+1]> (int)right) | |
224 nodeX[i+1]=(int)right; | |
225 for (pixelX = nodeX[i]; pixelX <= nodeX[i+1]; pixelX++) | |
226 { | |
227 *(row + pixelX) = IN_MASK_VALUE; | |
228 } | |
229 } | |
230 } | |
231 } | |
232 } | |
233 } | 137 } |
234 | 138 |
235 } | 139 } |