comparison OrthancStone/Sources/Scene2D/AnnotationsSceneLayer.cpp @ 1980:0aac8f552d89

added pixel probe to the Stone Web viewer toolbar
author Sebastien Jodogne <s.jodogne@gmail.com>
date Sun, 30 Oct 2022 10:26:32 +0100
parents b31e494e34c5
children c074c75cf416
comparison
equal deleted inserted replaced
1979:b31e494e34c5 1980:0aac8f552d89
232 }; 232 };
233 233
234 234
235 class AnnotationsSceneLayer::Handle : public GeometricPrimitive 235 class AnnotationsSceneLayer::Handle : public GeometricPrimitive
236 { 236 {
237 public:
238 enum Shape {
239 Shape_Square,
240 Shape_CrossedSquare
241 };
242
237 private: 243 private:
244 Shape shape_;
238 ScenePoint2D center_; 245 ScenePoint2D center_;
239 ScenePoint2D delta_; 246 ScenePoint2D delta_;
240 247
248 void AddChain(PolylineSceneLayer& polyline,
249 const PolylineSceneLayer::Chain& chain) const
250 {
251 if (IsHover())
252 {
253 polyline.AddChain(chain, true /* closed */, GetHoverColor());
254 }
255 else
256 {
257 polyline.AddChain(chain, true /* closed */, GetColor());
258 }
259 }
260
261 void AddRectangle(PolylineSceneLayer& polyline,
262 double x1,
263 double y1,
264 double x2,
265 double y2)
266 {
267 PolylineSceneLayer::Chain chain;
268 chain.resize(4);
269 chain[0] = ScenePoint2D(x1, y1);
270 chain[1] = ScenePoint2D(x2, y1);
271 chain[2] = ScenePoint2D(x2, y2);
272 chain[3] = ScenePoint2D(x1, y2);
273 AddChain(polyline, chain);
274 }
275
276 void AddCross(PolylineSceneLayer& polyline,
277 double x1,
278 double y1,
279 double x2,
280 double y2)
281 {
282 const double halfX = (x1 + x2) / 2.0;
283 const double halfY = (y1 + y2) / 2.0;
284
285 PolylineSceneLayer::Chain chain;
286 chain.resize(2);
287
288 chain[0] = ScenePoint2D(x1, halfY);
289 chain[1] = ScenePoint2D(x2, halfY);
290 AddChain(polyline, chain);
291
292 chain[0] = ScenePoint2D(halfX, y1);
293 chain[1] = ScenePoint2D(halfX, y2);
294 AddChain(polyline, chain);
295 }
296
241 public: 297 public:
242 explicit Handle(Annotation& parentAnnotation, 298 explicit Handle(Annotation& parentAnnotation,
299 Shape shape,
243 const ScenePoint2D& center) : 300 const ScenePoint2D& center) :
244 GeometricPrimitive(parentAnnotation, 0), // Highest priority 301 GeometricPrimitive(parentAnnotation, 0), // Highest priority
302 shape_(shape),
245 center_(center), 303 center_(center),
246 delta_(0, 0) 304 delta_(0, 0)
247 { 305 {
248 } 306 }
249 307
270 const double zoom = scene.GetSceneToCanvasTransform().ComputeZoom(); 328 const double zoom = scene.GetSceneToCanvasTransform().ComputeZoom();
271 329
272 double dx = (center_.GetX() + delta_.GetX() - p.GetX()) * zoom; 330 double dx = (center_.GetX() + delta_.GetX() - p.GetX()) * zoom;
273 double dy = (center_.GetY() + delta_.GetY() - p.GetY()) * zoom; 331 double dy = (center_.GetY() + delta_.GetY() - p.GetY()) * zoom;
274 332
275 return (std::abs(dx) <= HANDLE_SIZE / 2.0 && 333 switch (shape_)
276 std::abs(dy) <= HANDLE_SIZE / 2.0); 334 {
335 case Shape_Square:
336 case Shape_CrossedSquare:
337 return (std::abs(dx) <= HANDLE_SIZE / 2.0 &&
338 std::abs(dy) <= HANDLE_SIZE / 2.0);
339
340 default:
341 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented);
342 }
277 } 343 }
278 344
279 virtual void RenderPolylineLayer(PolylineSceneLayer& polyline, 345 virtual void RenderPolylineLayer(PolylineSceneLayer& polyline,
280 const Scene2D& scene) ORTHANC_OVERRIDE 346 const Scene2D& scene) ORTHANC_OVERRIDE
281 { 347 {
285 double x1 = center_.GetX() + delta_.GetX() - (HANDLE_SIZE / 2.0) / zoom; 351 double x1 = center_.GetX() + delta_.GetX() - (HANDLE_SIZE / 2.0) / zoom;
286 double y1 = center_.GetY() + delta_.GetY() - (HANDLE_SIZE / 2.0) / zoom; 352 double y1 = center_.GetY() + delta_.GetY() - (HANDLE_SIZE / 2.0) / zoom;
287 double x2 = center_.GetX() + delta_.GetX() + (HANDLE_SIZE / 2.0) / zoom; 353 double x2 = center_.GetX() + delta_.GetX() + (HANDLE_SIZE / 2.0) / zoom;
288 double y2 = center_.GetY() + delta_.GetY() + (HANDLE_SIZE / 2.0) / zoom; 354 double y2 = center_.GetY() + delta_.GetY() + (HANDLE_SIZE / 2.0) / zoom;
289 355
290 PolylineSceneLayer::Chain chain; 356 switch (shape_)
291 chain.reserve(4); 357 {
292 chain.push_back(ScenePoint2D(x1, y1)); 358 case Shape_Square:
293 chain.push_back(ScenePoint2D(x2, y1)); 359 AddRectangle(polyline, x1, y1, x2, y2);
294 chain.push_back(ScenePoint2D(x2, y2)); 360 break;
295 chain.push_back(ScenePoint2D(x1, y2)); 361
296 362 case Shape_CrossedSquare:
297 if (IsHover()) 363 AddRectangle(polyline, x1, y1, x2, y2);
298 { 364 AddCross(polyline, x1, y1, x2, y2);
299 polyline.AddChain(chain, true /* closed */, GetHoverColor()); 365 break;
300 } 366
301 else 367 default:
302 { 368 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented);
303 polyline.AddChain(chain, true /* closed */, GetColor());
304 } 369 }
305 } 370 }
306 371
307 virtual void RenderOtherLayers(MacroSceneLayer& macro, 372 virtual void RenderOtherLayers(MacroSceneLayer& macro,
308 const Scene2D& scene) ORTHANC_OVERRIDE 373 const Scene2D& scene) ORTHANC_OVERRIDE
375 440
376 virtual void RenderPolylineLayer(PolylineSceneLayer& polyline, 441 virtual void RenderPolylineLayer(PolylineSceneLayer& polyline,
377 const Scene2D& scene) ORTHANC_OVERRIDE 442 const Scene2D& scene) ORTHANC_OVERRIDE
378 { 443 {
379 PolylineSceneLayer::Chain chain; 444 PolylineSceneLayer::Chain chain;
380 chain.reserve(2); 445 chain.resize(2);
381 chain.push_back(p1_ + delta_); 446 chain[0] = p1_ + delta_;
382 chain.push_back(p2_ + delta_); 447 chain[1] = p2_ + delta_;
383 448
384 if (IsHover()) 449 if (IsHover())
385 { 450 {
386 polyline.AddChain(chain, false /* closed */, GetHoverColor()); 451 polyline.AddChain(chain, false /* closed */, GetHoverColor());
387 } 452 }
478 const double radius = ScenePoint2D::DistancePtPt(middle, p1_); 543 const double radius = ScenePoint2D::DistancePtPt(middle, p1_);
479 544
480 double increment = 2.0 * PI / static_cast<double>(NUM_SEGMENTS - 1); 545 double increment = 2.0 * PI / static_cast<double>(NUM_SEGMENTS - 1);
481 546
482 PolylineSceneLayer::Chain chain; 547 PolylineSceneLayer::Chain chain;
483 chain.reserve(NUM_SEGMENTS); 548 chain.resize(NUM_SEGMENTS);
484 549
485 double theta = 0; 550 double theta = 0;
486 for (unsigned int i = 0; i < NUM_SEGMENTS; i++) 551 for (unsigned int i = 0; i < NUM_SEGMENTS; i++)
487 { 552 {
488 chain.push_back(ScenePoint2D(delta_.GetX() + middle.GetX() + radius * cos(theta), 553 chain[i] = ScenePoint2D(delta_.GetX() + middle.GetX() + radius * cos(theta),
489 delta_.GetY() + middle.GetY() + radius * sin(theta))); 554 delta_.GetY() + middle.GetY() + radius * sin(theta));
490 theta += increment; 555 theta += increment;
491 } 556 }
492 557
493 if (IsHover()) 558 if (IsHover())
494 { 559 {
615 ComputeAngles(fullAngle, startAngle, endAngle); 680 ComputeAngles(fullAngle, startAngle, endAngle);
616 681
617 double increment = fullAngle / static_cast<double>(NUM_SEGMENTS - 1); 682 double increment = fullAngle / static_cast<double>(NUM_SEGMENTS - 1);
618 683
619 PolylineSceneLayer::Chain chain; 684 PolylineSceneLayer::Chain chain;
620 chain.reserve(NUM_SEGMENTS); 685 chain.resize(NUM_SEGMENTS);
621 686
622 double theta = startAngle; 687 double theta = startAngle;
623 for (unsigned int i = 0; i < NUM_SEGMENTS; i++) 688 for (unsigned int i = 0; i < NUM_SEGMENTS; i++)
624 { 689 {
625 chain.push_back(ScenePoint2D(middle_.GetX() + radius * cos(theta), 690 chain[i] = ScenePoint2D(middle_.GetX() + radius * cos(theta),
626 middle_.GetY() + radius * sin(theta))); 691 middle_.GetY() + radius * sin(theta));
627 theta += increment; 692 theta += increment;
628 } 693 }
629 694
630 if (IsHover()) 695 if (IsHover())
631 { 696 {
879 bool showLabel, 944 bool showLabel,
880 const ScenePoint2D& p1, 945 const ScenePoint2D& p1,
881 const ScenePoint2D& p2) : 946 const ScenePoint2D& p2) :
882 Annotation(that, units), 947 Annotation(that, units),
883 showLabel_(showLabel), 948 showLabel_(showLabel),
884 handle1_(AddTypedPrimitive<Handle>(new Handle(*this, p1))), 949 handle1_(AddTypedPrimitive<Handle>(new Handle(*this, Handle::Shape_Square, p1))),
885 handle2_(AddTypedPrimitive<Handle>(new Handle(*this, p2))), 950 handle2_(AddTypedPrimitive<Handle>(new Handle(*this, Handle::Shape_Square, p2))),
886 segment_(AddTypedPrimitive<Segment>(new Segment(*this, p1, p2))), 951 segment_(AddTypedPrimitive<Segment>(new Segment(*this, p1, p2))),
887 label_(AddTypedPrimitive<Text>(new Text(that, *this))) 952 label_(AddTypedPrimitive<Text>(new Text(that, *this)))
888 { 953 {
889 label_.SetColor(COLOR_TEXT); 954 label_.SetColor(COLOR_TEXT);
890 UpdateLabel(); 955 UpdateLabel();
1033 char buf[64]; 1098 char buf[64];
1034 1099
1035 switch (image.GetFormat()) 1100 switch (image.GetFormat())
1036 { 1101 {
1037 case Orthanc::PixelFormat_Float32: 1102 case Orthanc::PixelFormat_Float32:
1038 sprintf(buf, "%.01f\n", Orthanc::ImageTraits<Orthanc::PixelFormat_Float32>::GetFloatPixel( 1103 sprintf(buf, "(%d,%d): %.01f", x, y, Orthanc::ImageTraits<Orthanc::PixelFormat_Float32>::GetFloatPixel(
1039 image, static_cast<unsigned int>(x), static_cast<unsigned int>(y))); 1104 image, static_cast<unsigned int>(x), static_cast<unsigned int>(y)));
1040 break; 1105 break;
1041 1106
1042 case Orthanc::PixelFormat_RGB24: 1107 case Orthanc::PixelFormat_RGB24:
1043 { 1108 {
1044 Orthanc::PixelTraits<Orthanc::PixelFormat_RGB24>::PixelType pixel; 1109 Orthanc::PixelTraits<Orthanc::PixelFormat_RGB24>::PixelType pixel;
1045 Orthanc::ImageTraits<Orthanc::PixelFormat_RGB24>::GetPixel( 1110 Orthanc::ImageTraits<Orthanc::PixelFormat_RGB24>::GetPixel(
1046 pixel, image, static_cast<unsigned int>(x), static_cast<unsigned int>(y)); 1111 pixel, image, static_cast<unsigned int>(x), static_cast<unsigned int>(y));
1047 sprintf(buf, "(%d,%d,%d)\n", pixel.red_, pixel.green_, pixel.blue_); 1112 sprintf(buf, "(%d,%d): (%d,%d,%d)", x, y, pixel.red_, pixel.green_, pixel.blue_);
1048 break; 1113 break;
1049 } 1114 }
1050 1115
1051 default: 1116 default:
1052 break; 1117 break;
1065 PixelProbeAnnotation(AnnotationsSceneLayer& that, 1130 PixelProbeAnnotation(AnnotationsSceneLayer& that,
1066 Units units, 1131 Units units,
1067 const ScenePoint2D& p, 1132 const ScenePoint2D& p,
1068 int probedLayer) : 1133 int probedLayer) :
1069 ProbingAnnotation(that, units, probedLayer), 1134 ProbingAnnotation(that, units, probedLayer),
1070 handle_(AddTypedPrimitive<Handle>(new Handle(*this, p))), 1135 handle_(AddTypedPrimitive<Handle>(new Handle(*this, Handle::Shape_CrossedSquare, p))),
1071 label_(AddTypedPrimitive<Text>(new Text(that, *this))) 1136 label_(AddTypedPrimitive<Text>(new Text(that, *this)))
1072 { 1137 {
1073 TextSceneLayer content; 1138 TextSceneLayer content;
1074 content.SetPosition(handle_.GetCenter().GetX(), handle_.GetCenter().GetY()); 1139 content.SetPosition(handle_.GetCenter().GetX(), handle_.GetCenter().GetY());
1075 content.SetAnchor(BitmapAnchor_CenterLeft); 1140 content.SetAnchor(BitmapAnchor_CenterLeft);
1168 Units units, 1233 Units units,
1169 const ScenePoint2D& start, 1234 const ScenePoint2D& start,
1170 const ScenePoint2D& middle, 1235 const ScenePoint2D& middle,
1171 const ScenePoint2D& end) : 1236 const ScenePoint2D& end) :
1172 Annotation(that, units), 1237 Annotation(that, units),
1173 startHandle_(AddTypedPrimitive<Handle>(new Handle(*this, start))), 1238 startHandle_(AddTypedPrimitive<Handle>(new Handle(*this, Handle::Shape_Square, start))),
1174 middleHandle_(AddTypedPrimitive<Handle>(new Handle(*this, middle))), 1239 middleHandle_(AddTypedPrimitive<Handle>(new Handle(*this, Handle::Shape_Square, middle))),
1175 endHandle_(AddTypedPrimitive<Handle>(new Handle(*this, end))), 1240 endHandle_(AddTypedPrimitive<Handle>(new Handle(*this, Handle::Shape_Square, end))),
1176 segment1_(AddTypedPrimitive<Segment>(new Segment(*this, start, middle))), 1241 segment1_(AddTypedPrimitive<Segment>(new Segment(*this, start, middle))),
1177 segment2_(AddTypedPrimitive<Segment>(new Segment(*this, middle, end))), 1242 segment2_(AddTypedPrimitive<Segment>(new Segment(*this, middle, end))),
1178 arc_(AddTypedPrimitive<Arc>(new Arc(*this, start, middle, end))), 1243 arc_(AddTypedPrimitive<Arc>(new Arc(*this, start, middle, end))),
1179 label_(AddTypedPrimitive<Text>(new Text(that, *this))) 1244 label_(AddTypedPrimitive<Text>(new Text(that, *this)))
1180 { 1245 {
1338 CircleAnnotation(AnnotationsSceneLayer& that, 1403 CircleAnnotation(AnnotationsSceneLayer& that,
1339 Units units, 1404 Units units,
1340 const ScenePoint2D& p1, 1405 const ScenePoint2D& p1,
1341 const ScenePoint2D& p2) : 1406 const ScenePoint2D& p2) :
1342 Annotation(that, units), 1407 Annotation(that, units),
1343 handle1_(AddTypedPrimitive<Handle>(new Handle(*this, p1))), 1408 handle1_(AddTypedPrimitive<Handle>(new Handle(*this, Handle::Shape_Square, p1))),
1344 handle2_(AddTypedPrimitive<Handle>(new Handle(*this, p2))), 1409 handle2_(AddTypedPrimitive<Handle>(new Handle(*this, Handle::Shape_Square, p2))),
1345 segment_(AddTypedPrimitive<Segment>(new Segment(*this, p1, p2))), 1410 segment_(AddTypedPrimitive<Segment>(new Segment(*this, p1, p2))),
1346 circle_(AddTypedPrimitive<Circle>(new Circle(*this, p1, p2))), 1411 circle_(AddTypedPrimitive<Circle>(new Circle(*this, p1, p2))),
1347 label_(AddTypedPrimitive<Text>(new Text(that, *this))) 1412 label_(AddTypedPrimitive<Text>(new Text(that, *this)))
1348 { 1413 {
1349 label_.SetColor(COLOR_TEXT); 1414 label_.SetColor(COLOR_TEXT);