Mercurial > hg > orthanc-stone
comparison Applications/Samples/Sdl/SingleFrameViewer/SdlSimpleViewer.cpp @ 1799:1125793d82d3
serialization of annotations
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Thu, 20 May 2021 11:49:21 +0200 |
parents | 41f3872bd7d2 |
children | 2c0497d61a5d |
comparison
equal
deleted
inserted
replaced
1798:41f3872bd7d2 | 1799:1125793d82d3 |
---|---|
49 | 49 |
50 #include <boost/math/constants/constants.hpp> | 50 #include <boost/math/constants/constants.hpp> |
51 | 51 |
52 static const double HANDLE_SIZE = 10.0; | 52 static const double HANDLE_SIZE = 10.0; |
53 static const double PI = boost::math::constants::pi<double>(); | 53 static const double PI = boost::math::constants::pi<double>(); |
54 | 54 |
55 static const char* const KEY_ANNOTATIONS = "annotations"; | |
56 static const char* const KEY_TYPE = "type"; | |
57 static const char* const KEY_X1 = "x1"; | |
58 static const char* const KEY_Y1 = "y1"; | |
59 static const char* const KEY_X2 = "x2"; | |
60 static const char* const KEY_Y2 = "y2"; | |
61 static const char* const KEY_X3 = "x3"; | |
62 static const char* const KEY_Y3 = "y3"; | |
63 | |
64 static const char* const VALUE_ANGLE = "angle"; | |
65 static const char* const VALUE_CIRCLE = "circle"; | |
66 static const char* const VALUE_SEGMENT = "segment"; | |
67 | |
68 | |
55 namespace OrthancStone | 69 namespace OrthancStone |
56 { | 70 { |
57 class AnnotationsOverlay : public boost::noncopyable | 71 class AnnotationsOverlay : public boost::noncopyable |
58 { | 72 { |
59 public: | 73 public: |
66 Tool_Circle, | 80 Tool_Circle, |
67 Tool_Erase | 81 Tool_Erase |
68 }; | 82 }; |
69 | 83 |
70 private: | 84 private: |
71 class Measure; | 85 class Annotation; |
72 | 86 |
73 class Primitive : public boost::noncopyable | 87 class Primitive : public boost::noncopyable |
74 { | 88 { |
75 private: | 89 private: |
76 bool modified_; | 90 bool modified_; |
77 Measure& parentMeasure_; | 91 Annotation& parentAnnotation_; |
78 Color color_; | 92 Color color_; |
79 Color hoverColor_; | 93 Color hoverColor_; |
80 bool isHover_; | 94 bool isHover_; |
81 int depth_; | 95 int depth_; |
82 | 96 |
83 public: | 97 public: |
84 Primitive(Measure& parentMeasure, | 98 Primitive(Annotation& parentAnnotation, |
85 int depth) : | 99 int depth) : |
86 modified_(true), | 100 modified_(true), |
87 parentMeasure_(parentMeasure), | 101 parentAnnotation_(parentAnnotation), |
88 color_(192, 192, 192), | 102 color_(192, 192, 192), |
89 hoverColor_(0, 255, 0), | 103 hoverColor_(0, 255, 0), |
90 isHover_(false), | 104 isHover_(false), |
91 depth_(depth) | 105 depth_(depth) |
92 { | 106 { |
94 | 108 |
95 virtual ~Primitive() | 109 virtual ~Primitive() |
96 { | 110 { |
97 } | 111 } |
98 | 112 |
99 Measure& GetParentMeasure() const | 113 Annotation& GetParentAnnotation() const |
100 { | 114 { |
101 return parentMeasure_; | 115 return parentAnnotation_; |
102 } | 116 } |
103 | 117 |
104 int GetDepth() const | 118 int GetDepth() const |
105 { | 119 { |
106 return depth_; | 120 return depth_; |
167 | 181 |
168 virtual void MoveDone(const ScenePoint2D& delta) = 0; | 182 virtual void MoveDone(const ScenePoint2D& delta) = 0; |
169 }; | 183 }; |
170 | 184 |
171 | 185 |
172 class Measure : public boost::noncopyable | 186 class Annotation : public boost::noncopyable |
173 { | 187 { |
174 private: | 188 private: |
175 typedef std::list<Primitive*> Primitives; | 189 typedef std::list<Primitive*> Primitives; |
176 | 190 |
177 AnnotationsOverlay& that_; | 191 AnnotationsOverlay& that_; |
178 Primitives primitives_; | 192 Primitives primitives_; |
179 | 193 |
180 public: | 194 public: |
181 Measure(AnnotationsOverlay& that) : | 195 Annotation(AnnotationsOverlay& that) : |
182 that_(that) | 196 that_(that) |
183 { | 197 { |
184 that.AddMeasure(this); | 198 that.AddAnnotation(this); |
185 } | 199 } |
186 | 200 |
187 virtual ~Measure() | 201 virtual ~Annotation() |
188 { | 202 { |
189 for (Primitives::iterator it = primitives_.begin(); it != primitives_.end(); ++it) | 203 for (Primitives::iterator it = primitives_.begin(); it != primitives_.end(); ++it) |
190 { | 204 { |
191 that_.DeletePrimitive(*it); | 205 that_.DeletePrimitive(*it); |
192 } | 206 } |
213 AddPrimitive(primitive); | 227 AddPrimitive(primitive); |
214 return *primitive; | 228 return *primitive; |
215 } | 229 } |
216 | 230 |
217 virtual void SignalMove(Primitive& primitive) = 0; | 231 virtual void SignalMove(Primitive& primitive) = 0; |
232 | |
233 virtual void Serialize(Json::Value& target) = 0; | |
218 }; | 234 }; |
219 | 235 |
220 | 236 |
221 class Handle : public Primitive | 237 class Handle : public Primitive |
222 { | 238 { |
223 private: | 239 private: |
224 ScenePoint2D center_; | 240 ScenePoint2D center_; |
225 ScenePoint2D delta_; | 241 ScenePoint2D delta_; |
226 | 242 |
227 public: | 243 public: |
228 explicit Handle(Measure& parentMeasure, | 244 explicit Handle(Annotation& parentAnnotation, |
229 const ScenePoint2D& center) : | 245 const ScenePoint2D& center) : |
230 Primitive(parentMeasure, 0), // Highest priority | 246 Primitive(parentAnnotation, 0), // Highest priority |
231 center_(center), | 247 center_(center), |
232 delta_(0, 0) | 248 delta_(0, 0) |
233 { | 249 { |
234 } | 250 } |
235 | 251 |
297 | 313 |
298 virtual void MovePreview(const ScenePoint2D& delta) ORTHANC_OVERRIDE | 314 virtual void MovePreview(const ScenePoint2D& delta) ORTHANC_OVERRIDE |
299 { | 315 { |
300 SetModified(true); | 316 SetModified(true); |
301 delta_ = delta; | 317 delta_ = delta; |
302 GetParentMeasure().SignalMove(*this); | 318 GetParentAnnotation().SignalMove(*this); |
303 } | 319 } |
304 | 320 |
305 virtual void MoveDone(const ScenePoint2D& delta) ORTHANC_OVERRIDE | 321 virtual void MoveDone(const ScenePoint2D& delta) ORTHANC_OVERRIDE |
306 { | 322 { |
307 SetModified(true); | 323 SetModified(true); |
308 center_ = center_ + delta; | 324 center_ = center_ + delta; |
309 delta_ = ScenePoint2D(0, 0); | 325 delta_ = ScenePoint2D(0, 0); |
310 GetParentMeasure().SignalMove(*this); | 326 GetParentAnnotation().SignalMove(*this); |
311 } | 327 } |
312 }; | 328 }; |
313 | 329 |
314 | 330 |
315 class Segment : public Primitive | 331 class Segment : public Primitive |
318 ScenePoint2D p1_; | 334 ScenePoint2D p1_; |
319 ScenePoint2D p2_; | 335 ScenePoint2D p2_; |
320 ScenePoint2D delta_; | 336 ScenePoint2D delta_; |
321 | 337 |
322 public: | 338 public: |
323 Segment(Measure& parentMeasure, | 339 Segment(Annotation& parentAnnotation, |
324 const ScenePoint2D& p1, | 340 const ScenePoint2D& p1, |
325 const ScenePoint2D& p2) : | 341 const ScenePoint2D& p2) : |
326 Primitive(parentMeasure, 1), // Can only be selected if no handle matches | 342 Primitive(parentAnnotation, 1), // Can only be selected if no handle matches |
327 p1_(p1), | 343 p1_(p1), |
328 p2_(p2), | 344 p2_(p2), |
329 delta_(0, 0) | 345 delta_(0, 0) |
330 { | 346 { |
331 } | 347 } |
382 | 398 |
383 virtual void MovePreview(const ScenePoint2D& delta) ORTHANC_OVERRIDE | 399 virtual void MovePreview(const ScenePoint2D& delta) ORTHANC_OVERRIDE |
384 { | 400 { |
385 SetModified(true); | 401 SetModified(true); |
386 delta_ = delta; | 402 delta_ = delta; |
387 GetParentMeasure().SignalMove(*this); | 403 GetParentAnnotation().SignalMove(*this); |
388 } | 404 } |
389 | 405 |
390 virtual void MoveDone(const ScenePoint2D& delta) ORTHANC_OVERRIDE | 406 virtual void MoveDone(const ScenePoint2D& delta) ORTHANC_OVERRIDE |
391 { | 407 { |
392 SetModified(true); | 408 SetModified(true); |
393 p1_ = p1_ + delta; | 409 p1_ = p1_ + delta; |
394 p2_ = p2_ + delta; | 410 p2_ = p2_ + delta; |
395 delta_ = ScenePoint2D(0, 0); | 411 delta_ = ScenePoint2D(0, 0); |
396 GetParentMeasure().SignalMove(*this); | 412 GetParentAnnotation().SignalMove(*this); |
397 } | 413 } |
398 }; | 414 }; |
399 | 415 |
400 | 416 |
401 class Circle : public Primitive | 417 class Circle : public Primitive |
403 private: | 419 private: |
404 ScenePoint2D p1_; | 420 ScenePoint2D p1_; |
405 ScenePoint2D p2_; | 421 ScenePoint2D p2_; |
406 | 422 |
407 public: | 423 public: |
408 Circle(Measure& parentMeasure, | 424 Circle(Annotation& parentAnnotation, |
409 const ScenePoint2D& p1, | 425 const ScenePoint2D& p1, |
410 const ScenePoint2D& p2) : | 426 const ScenePoint2D& p2) : |
411 Primitive(parentMeasure, 2), | 427 Primitive(parentAnnotation, 2), |
412 p1_(p1), | 428 p1_(p1), |
413 p2_(p2) | 429 p2_(p2) |
414 { | 430 { |
415 } | 431 } |
416 | 432 |
522 fullAngle -= 2.0 * PI; | 538 fullAngle -= 2.0 * PI; |
523 } | 539 } |
524 } | 540 } |
525 | 541 |
526 public: | 542 public: |
527 Arc(Measure& parentMeasure, | 543 Arc(Annotation& parentAnnotation, |
528 const ScenePoint2D& start, | 544 const ScenePoint2D& start, |
529 const ScenePoint2D& middle, | 545 const ScenePoint2D& middle, |
530 const ScenePoint2D& end) : | 546 const ScenePoint2D& end) : |
531 Primitive(parentMeasure, 2), | 547 Primitive(parentAnnotation, 2), |
532 start_(start), | 548 start_(start), |
533 middle_(middle), | 549 middle_(middle), |
534 end_(end), | 550 end_(end), |
535 radius_(20) | 551 radius_(20) |
536 { | 552 { |
625 size_t subLayer_; | 641 size_t subLayer_; |
626 std::unique_ptr<TextSceneLayer> content_; | 642 std::unique_ptr<TextSceneLayer> content_; |
627 | 643 |
628 public: | 644 public: |
629 Text(AnnotationsOverlay& that, | 645 Text(AnnotationsOverlay& that, |
630 Measure& parentMeasure) : | 646 Annotation& parentAnnotation) : |
631 Primitive(parentMeasure, 2), | 647 Primitive(parentAnnotation, 2), |
632 that_(that), | 648 that_(that), |
633 first_(true) | 649 first_(true) |
634 { | 650 { |
635 } | 651 } |
636 | 652 |
736 primitive_.MoveDone(ScenePoint2D(0, 0)); | 752 primitive_.MoveDone(ScenePoint2D(0, 0)); |
737 } | 753 } |
738 }; | 754 }; |
739 | 755 |
740 | 756 |
741 class SegmentMeasure : public Measure | 757 class SegmentAnnotation : public Annotation |
742 { | 758 { |
743 private: | 759 private: |
744 bool showLabel_; | 760 bool showLabel_; |
745 Handle& handle1_; | 761 Handle& handle1_; |
746 Handle& handle2_; | 762 Handle& handle2_; |
780 label_.SetContent(content); | 796 label_.SetContent(content); |
781 } | 797 } |
782 } | 798 } |
783 | 799 |
784 public: | 800 public: |
785 SegmentMeasure(AnnotationsOverlay& that, | 801 SegmentAnnotation(AnnotationsOverlay& that, |
786 bool showLabel, | 802 bool showLabel, |
787 const ScenePoint2D& p1, | 803 const ScenePoint2D& p1, |
788 const ScenePoint2D& p2) : | 804 const ScenePoint2D& p2) : |
789 Measure(that), | 805 Annotation(that), |
790 showLabel_(showLabel), | 806 showLabel_(showLabel), |
791 handle1_(AddTypedPrimitive<Handle>(new Handle(*this, p1))), | 807 handle1_(AddTypedPrimitive<Handle>(new Handle(*this, p1))), |
792 handle2_(AddTypedPrimitive<Handle>(new Handle(*this, p2))), | 808 handle2_(AddTypedPrimitive<Handle>(new Handle(*this, p2))), |
793 segment_(AddTypedPrimitive<Segment>(new Segment(*this, p1, p2))), | 809 segment_(AddTypedPrimitive<Segment>(new Segment(*this, p1, p2))), |
794 label_(AddTypedPrimitive<Text>(new Text(that, *this))) | 810 label_(AddTypedPrimitive<Text>(new Text(that, *this))) |
820 handle2_.SetCenter(segment_.GetPosition2()); | 836 handle2_.SetCenter(segment_.GetPosition2()); |
821 } | 837 } |
822 | 838 |
823 UpdateLabel(); | 839 UpdateLabel(); |
824 } | 840 } |
841 | |
842 virtual void Serialize(Json::Value& target) ORTHANC_OVERRIDE | |
843 { | |
844 target = Json::objectValue; | |
845 target[KEY_TYPE] = VALUE_SEGMENT; | |
846 target[KEY_X1] = handle1_.GetCenter().GetX(); | |
847 target[KEY_Y1] = handle1_.GetCenter().GetY(); | |
848 target[KEY_X2] = handle2_.GetCenter().GetX(); | |
849 target[KEY_Y2] = handle2_.GetCenter().GetY(); | |
850 } | |
825 }; | 851 }; |
826 | 852 |
827 | 853 |
828 class AngleMeasure : public Measure | 854 class AngleAnnotation : public Annotation |
829 { | 855 { |
830 private: | 856 private: |
831 Handle& startHandle_; | 857 Handle& startHandle_; |
832 Handle& middleHandle_; | 858 Handle& middleHandle_; |
833 Handle& endHandle_; | 859 Handle& endHandle_; |
865 | 891 |
866 label_.SetContent(content); | 892 label_.SetContent(content); |
867 } | 893 } |
868 | 894 |
869 public: | 895 public: |
870 AngleMeasure(AnnotationsOverlay& that, | 896 AngleAnnotation(AnnotationsOverlay& that, |
871 const ScenePoint2D& start, | 897 const ScenePoint2D& start, |
872 const ScenePoint2D& middle, | 898 const ScenePoint2D& middle, |
873 const ScenePoint2D& end) : | 899 const ScenePoint2D& end) : |
874 Measure(that), | 900 Annotation(that), |
875 startHandle_(AddTypedPrimitive<Handle>(new Handle(*this, start))), | 901 startHandle_(AddTypedPrimitive<Handle>(new Handle(*this, start))), |
876 middleHandle_(AddTypedPrimitive<Handle>(new Handle(*this, middle))), | 902 middleHandle_(AddTypedPrimitive<Handle>(new Handle(*this, middle))), |
877 endHandle_(AddTypedPrimitive<Handle>(new Handle(*this, end))), | 903 endHandle_(AddTypedPrimitive<Handle>(new Handle(*this, end))), |
878 segment1_(AddTypedPrimitive<Segment>(new Segment(*this, start, middle))), | 904 segment1_(AddTypedPrimitive<Segment>(new Segment(*this, start, middle))), |
879 segment2_(AddTypedPrimitive<Segment>(new Segment(*this, middle, end))), | 905 segment2_(AddTypedPrimitive<Segment>(new Segment(*this, middle, end))), |
924 arc_.SetEnd(segment2_.GetPosition2()); | 950 arc_.SetEnd(segment2_.GetPosition2()); |
925 } | 951 } |
926 | 952 |
927 UpdateLabel(); | 953 UpdateLabel(); |
928 } | 954 } |
955 | |
956 virtual void Serialize(Json::Value& target) ORTHANC_OVERRIDE | |
957 { | |
958 target = Json::objectValue; | |
959 target[KEY_TYPE] = VALUE_ANGLE; | |
960 target[KEY_X1] = startHandle_.GetCenter().GetX(); | |
961 target[KEY_Y1] = startHandle_.GetCenter().GetY(); | |
962 target[KEY_X2] = middleHandle_.GetCenter().GetX(); | |
963 target[KEY_Y2] = middleHandle_.GetCenter().GetY(); | |
964 target[KEY_X3] = endHandle_.GetCenter().GetX(); | |
965 target[KEY_Y3] = endHandle_.GetCenter().GetY(); | |
966 } | |
929 }; | 967 }; |
930 | 968 |
931 | 969 |
932 class CircleMeasure : public Measure | 970 class CircleAnnotation : public Annotation |
933 { | 971 { |
934 private: | 972 private: |
935 Handle& handle1_; | 973 Handle& handle1_; |
936 Handle& handle2_; | 974 Handle& handle2_; |
937 Segment& segment_; | 975 Segment& segment_; |
975 | 1013 |
976 label_.SetContent(content); | 1014 label_.SetContent(content); |
977 } | 1015 } |
978 | 1016 |
979 public: | 1017 public: |
980 CircleMeasure(AnnotationsOverlay& that, | 1018 CircleAnnotation(AnnotationsOverlay& that, |
981 const ScenePoint2D& p1, | 1019 const ScenePoint2D& p1, |
982 const ScenePoint2D& p2) : | 1020 const ScenePoint2D& p2) : |
983 Measure(that), | 1021 Annotation(that), |
984 handle1_(AddTypedPrimitive<Handle>(new Handle(*this, p1))), | 1022 handle1_(AddTypedPrimitive<Handle>(new Handle(*this, p1))), |
985 handle2_(AddTypedPrimitive<Handle>(new Handle(*this, p2))), | 1023 handle2_(AddTypedPrimitive<Handle>(new Handle(*this, p2))), |
986 segment_(AddTypedPrimitive<Segment>(new Segment(*this, p1, p2))), | 1024 segment_(AddTypedPrimitive<Segment>(new Segment(*this, p1, p2))), |
987 circle_(AddTypedPrimitive<Circle>(new Circle(*this, p1, p2))), | 1025 circle_(AddTypedPrimitive<Circle>(new Circle(*this, p1, p2))), |
988 label_(AddTypedPrimitive<Text>(new Text(that, *this))) | 1026 label_(AddTypedPrimitive<Text>(new Text(that, *this))) |
1011 circle_.SetPosition(segment_.GetPosition1(), segment_.GetPosition2()); | 1049 circle_.SetPosition(segment_.GetPosition1(), segment_.GetPosition2()); |
1012 } | 1050 } |
1013 | 1051 |
1014 UpdateLabel(); | 1052 UpdateLabel(); |
1015 } | 1053 } |
1054 | |
1055 virtual void Serialize(Json::Value& target) ORTHANC_OVERRIDE | |
1056 { | |
1057 target = Json::objectValue; | |
1058 target[KEY_TYPE] = VALUE_CIRCLE; | |
1059 target[KEY_X1] = handle1_.GetCenter().GetX(); | |
1060 target[KEY_Y1] = handle1_.GetCenter().GetY(); | |
1061 target[KEY_X2] = handle2_.GetCenter().GetX(); | |
1062 target[KEY_Y2] = handle2_.GetCenter().GetY(); | |
1063 } | |
1016 }; | 1064 }; |
1017 | 1065 |
1018 | 1066 |
1019 class CreateSegmentOrCircleTracker : public IFlexiblePointerTracker | 1067 class CreateSegmentOrCircleTracker : public IFlexiblePointerTracker |
1020 { | 1068 { |
1021 private: | 1069 private: |
1022 AnnotationsOverlay& that_; | 1070 AnnotationsOverlay& that_; |
1023 Measure* measure_; | 1071 Annotation* annotation_; |
1024 AffineTransform2D canvasToScene_; | 1072 AffineTransform2D canvasToScene_; |
1025 Handle* handle2_; | 1073 Handle* handle2_; |
1026 | 1074 |
1027 public: | 1075 public: |
1028 CreateSegmentOrCircleTracker(AnnotationsOverlay& that, | 1076 CreateSegmentOrCircleTracker(AnnotationsOverlay& that, |
1029 bool isCircle, | 1077 bool isCircle, |
1030 const ScenePoint2D& sceneClick, | 1078 const ScenePoint2D& sceneClick, |
1031 const AffineTransform2D& canvasToScene) : | 1079 const AffineTransform2D& canvasToScene) : |
1032 that_(that), | 1080 that_(that), |
1033 measure_(NULL), | 1081 annotation_(NULL), |
1034 canvasToScene_(canvasToScene), | 1082 canvasToScene_(canvasToScene), |
1035 handle2_(NULL) | 1083 handle2_(NULL) |
1036 { | 1084 { |
1037 if (isCircle) | 1085 if (isCircle) |
1038 { | 1086 { |
1039 measure_ = new CircleMeasure(that, sceneClick, sceneClick); | 1087 annotation_ = new CircleAnnotation(that, sceneClick, sceneClick); |
1040 handle2_ = &dynamic_cast<CircleMeasure*>(measure_)->GetHandle2(); | 1088 handle2_ = &dynamic_cast<CircleAnnotation*>(annotation_)->GetHandle2(); |
1041 } | 1089 } |
1042 else | 1090 else |
1043 { | 1091 { |
1044 measure_ = new SegmentMeasure(that, true /* show label */, sceneClick, sceneClick); | 1092 annotation_ = new SegmentAnnotation(that, true /* show label */, sceneClick, sceneClick); |
1045 handle2_ = &dynamic_cast<SegmentMeasure*>(measure_)->GetHandle2(); | 1093 handle2_ = &dynamic_cast<SegmentAnnotation*>(annotation_)->GetHandle2(); |
1046 } | 1094 } |
1047 | 1095 |
1048 assert(measure_ != NULL && | 1096 assert(annotation_ != NULL && |
1049 handle2_ != NULL); | 1097 handle2_ != NULL); |
1050 } | 1098 } |
1051 | 1099 |
1052 virtual void PointerMove(const PointerEvent& event) ORTHANC_OVERRIDE | 1100 virtual void PointerMove(const PointerEvent& event) ORTHANC_OVERRIDE |
1053 { | 1101 { |
1054 if (measure_ != NULL) | 1102 if (annotation_ != NULL) |
1055 { | 1103 { |
1056 assert(handle2_ != NULL); | 1104 assert(handle2_ != NULL); |
1057 handle2_->SetCenter(event.GetMainPosition().Apply(canvasToScene_)); | 1105 handle2_->SetCenter(event.GetMainPosition().Apply(canvasToScene_)); |
1058 measure_->SignalMove(*handle2_); | 1106 annotation_->SignalMove(*handle2_); |
1059 } | 1107 } |
1060 } | 1108 } |
1061 | 1109 |
1062 virtual void PointerUp(const PointerEvent& event) ORTHANC_OVERRIDE | 1110 virtual void PointerUp(const PointerEvent& event) ORTHANC_OVERRIDE |
1063 { | 1111 { |
1064 measure_ = NULL; // IsAlive() becomes false | 1112 annotation_ = NULL; // IsAlive() becomes false |
1065 } | 1113 } |
1066 | 1114 |
1067 virtual void PointerDown(const PointerEvent& event) ORTHANC_OVERRIDE | 1115 virtual void PointerDown(const PointerEvent& event) ORTHANC_OVERRIDE |
1068 { | 1116 { |
1069 } | 1117 } |
1070 | 1118 |
1071 virtual bool IsAlive() const ORTHANC_OVERRIDE | 1119 virtual bool IsAlive() const ORTHANC_OVERRIDE |
1072 { | 1120 { |
1073 return (measure_ != NULL); | 1121 return (annotation_ != NULL); |
1074 } | 1122 } |
1075 | 1123 |
1076 virtual void Cancel() ORTHANC_OVERRIDE | 1124 virtual void Cancel() ORTHANC_OVERRIDE |
1077 { | 1125 { |
1078 if (measure_ != NULL) | 1126 if (annotation_ != NULL) |
1079 { | 1127 { |
1080 that_.DeleteMeasure(measure_); | 1128 that_.DeleteAnnotation(annotation_); |
1081 measure_ = NULL; | 1129 annotation_ = NULL; |
1082 } | 1130 } |
1083 } | 1131 } |
1084 }; | 1132 }; |
1085 | 1133 |
1086 | 1134 |
1087 class CreateAngleTracker : public IFlexiblePointerTracker | 1135 class CreateAngleTracker : public IFlexiblePointerTracker |
1088 { | 1136 { |
1089 private: | 1137 private: |
1090 AnnotationsOverlay& that_; | 1138 AnnotationsOverlay& that_; |
1091 SegmentMeasure* segment_; | 1139 SegmentAnnotation* segment_; |
1092 AngleMeasure* angle_; | 1140 AngleAnnotation* angle_; |
1093 AffineTransform2D canvasToScene_; | 1141 AffineTransform2D canvasToScene_; |
1094 | 1142 |
1095 public: | 1143 public: |
1096 CreateAngleTracker(AnnotationsOverlay& that, | 1144 CreateAngleTracker(AnnotationsOverlay& that, |
1097 const ScenePoint2D& sceneClick, | 1145 const ScenePoint2D& sceneClick, |
1099 that_(that), | 1147 that_(that), |
1100 segment_(NULL), | 1148 segment_(NULL), |
1101 angle_(NULL), | 1149 angle_(NULL), |
1102 canvasToScene_(canvasToScene) | 1150 canvasToScene_(canvasToScene) |
1103 { | 1151 { |
1104 segment_ = new SegmentMeasure(that, false /* no length label */, sceneClick, sceneClick); | 1152 segment_ = new SegmentAnnotation(that, false /* no length label */, sceneClick, sceneClick); |
1105 } | 1153 } |
1106 | 1154 |
1107 virtual void PointerMove(const PointerEvent& event) ORTHANC_OVERRIDE | 1155 virtual void PointerMove(const PointerEvent& event) ORTHANC_OVERRIDE |
1108 { | 1156 { |
1109 if (segment_ != NULL) | 1157 if (segment_ != NULL) |
1123 { | 1171 { |
1124 if (segment_ != NULL) | 1172 if (segment_ != NULL) |
1125 { | 1173 { |
1126 // End of first step: The first segment is available, now create the angle | 1174 // End of first step: The first segment is available, now create the angle |
1127 | 1175 |
1128 angle_ = new AngleMeasure(that_, segment_->GetHandle1().GetCenter(), | 1176 angle_ = new AngleAnnotation(that_, segment_->GetHandle1().GetCenter(), |
1129 segment_->GetHandle2().GetCenter(), | 1177 segment_->GetHandle2().GetCenter(), |
1130 segment_->GetHandle2().GetCenter()); | 1178 segment_->GetHandle2().GetCenter()); |
1131 | 1179 |
1132 that_.DeleteMeasure(segment_); | 1180 that_.DeleteAnnotation(segment_); |
1133 segment_ = NULL; | 1181 segment_ = NULL; |
1134 } | 1182 } |
1135 else | 1183 else |
1136 { | 1184 { |
1137 angle_ = NULL; // IsAlive() becomes false | 1185 angle_ = NULL; // IsAlive() becomes false |
1150 | 1198 |
1151 virtual void Cancel() ORTHANC_OVERRIDE | 1199 virtual void Cancel() ORTHANC_OVERRIDE |
1152 { | 1200 { |
1153 if (segment_ != NULL) | 1201 if (segment_ != NULL) |
1154 { | 1202 { |
1155 that_.DeleteMeasure(segment_); | 1203 that_.DeleteAnnotation(segment_); |
1156 segment_ = NULL; | 1204 segment_ = NULL; |
1157 } | 1205 } |
1158 | 1206 |
1159 if (angle_ != NULL) | 1207 if (angle_ != NULL) |
1160 { | 1208 { |
1161 that_.DeleteMeasure(angle_); | 1209 that_.DeleteAnnotation(angle_); |
1162 angle_ = NULL; | 1210 angle_ = NULL; |
1163 } | 1211 } |
1164 } | 1212 } |
1165 }; | 1213 }; |
1166 | 1214 |
1195 { | 1243 { |
1196 } | 1244 } |
1197 }; | 1245 }; |
1198 | 1246 |
1199 | 1247 |
1200 typedef std::set<Primitive*> Primitives; | 1248 typedef std::set<Primitive*> Primitives; |
1201 typedef std::set<Measure*> Measures; | 1249 typedef std::set<Annotation*> Annotations; |
1202 typedef std::set<size_t> SubLayers; | 1250 typedef std::set<size_t> SubLayers; |
1203 | 1251 |
1204 Tool activeTool_; | 1252 Tool activeTool_; |
1205 size_t macroLayerIndex_; | 1253 size_t macroLayerIndex_; |
1206 size_t polylineSubLayer_; | 1254 size_t polylineSubLayer_; |
1207 Primitives primitives_; | 1255 Primitives primitives_; |
1208 Measures measures_; | 1256 Annotations annotations_; |
1209 SubLayers subLayersToRemove_; | 1257 SubLayers subLayersToRemove_; |
1210 | 1258 |
1211 void AddMeasure(Measure* measure) | 1259 void AddAnnotation(Annotation* annotation) |
1212 { | 1260 { |
1213 assert(measure != NULL); | 1261 assert(annotation != NULL); |
1214 assert(measures_.find(measure) == measures_.end()); | 1262 assert(annotations_.find(annotation) == annotations_.end()); |
1215 measures_.insert(measure); | 1263 annotations_.insert(annotation); |
1216 } | 1264 } |
1217 | 1265 |
1218 void DeleteMeasure(Measure* measure) | 1266 void DeleteAnnotation(Annotation* annotation) |
1219 { | 1267 { |
1220 if (measure != NULL) | 1268 if (annotation != NULL) |
1221 { | 1269 { |
1222 assert(measures_.find(measure) != measures_.end()); | 1270 assert(annotations_.find(annotation) != annotations_.end()); |
1223 measures_.erase(measure); | 1271 annotations_.erase(annotation); |
1224 delete measure; | 1272 delete annotation; |
1225 } | 1273 } |
1226 } | 1274 } |
1227 | 1275 |
1228 void DeletePrimitive(Primitive* primitive) | 1276 void DeletePrimitive(Primitive* primitive) |
1229 { | 1277 { |
1245 AnnotationsOverlay(size_t macroLayerIndex) : | 1293 AnnotationsOverlay(size_t macroLayerIndex) : |
1246 activeTool_(Tool_Edit), | 1294 activeTool_(Tool_Edit), |
1247 macroLayerIndex_(macroLayerIndex), | 1295 macroLayerIndex_(macroLayerIndex), |
1248 polylineSubLayer_(0) // dummy initialization | 1296 polylineSubLayer_(0) // dummy initialization |
1249 { | 1297 { |
1250 measures_.insert(new SegmentMeasure(*this, true /* show label */, ScenePoint2D(0, 0), ScenePoint2D(100, 100))); | 1298 annotations_.insert(new SegmentAnnotation(*this, true /* show label */, ScenePoint2D(0, 0), ScenePoint2D(100, 100))); |
1251 measures_.insert(new AngleMeasure(*this, ScenePoint2D(100, 50), ScenePoint2D(150, 40), ScenePoint2D(200, 50))); | 1299 annotations_.insert(new AngleAnnotation(*this, ScenePoint2D(100, 50), ScenePoint2D(150, 40), ScenePoint2D(200, 50))); |
1252 measures_.insert(new CircleMeasure(*this, ScenePoint2D(50, 200), ScenePoint2D(100, 250))); | 1300 annotations_.insert(new CircleAnnotation(*this, ScenePoint2D(50, 200), ScenePoint2D(100, 250))); |
1253 } | 1301 } |
1254 | 1302 |
1255 ~AnnotationsOverlay() | 1303 ~AnnotationsOverlay() |
1256 { | 1304 { |
1257 for (Measures::iterator it = measures_.begin(); it != measures_.end(); ++it) | 1305 Clear(); |
1306 } | |
1307 | |
1308 void Clear() | |
1309 { | |
1310 for (Annotations::iterator it = annotations_.begin(); it != annotations_.end(); ++it) | |
1258 { | 1311 { |
1259 assert(*it != NULL); | 1312 assert(*it != NULL); |
1260 delete *it; | 1313 delete *it; |
1261 } | 1314 } |
1262 | 1315 |
1263 measures_.clear(); | 1316 annotations_.clear(); |
1264 } | 1317 } |
1265 | 1318 |
1266 void SetActiveTool(Tool tool) | 1319 void SetActiveTool(Tool tool) |
1267 { | 1320 { |
1268 activeTool_ = tool; | 1321 activeTool_ = tool; |
1390 | 1443 |
1391 if (bestHit != NULL) | 1444 if (bestHit != NULL) |
1392 { | 1445 { |
1393 if (activeTool_ == Tool_Erase) | 1446 if (activeTool_ == Tool_Erase) |
1394 { | 1447 { |
1395 DeleteMeasure(&bestHit->GetParentMeasure()); | 1448 DeleteAnnotation(&bestHit->GetParentAnnotation()); |
1396 return new EraseTracker; | 1449 return new EraseTracker; |
1397 } | 1450 } |
1398 else | 1451 else |
1399 { | 1452 { |
1400 return new EditPrimitiveTracker(*bestHit, s, scene.GetCanvasToSceneTransform()); | 1453 return new EditPrimitiveTracker(*bestHit, s, scene.GetCanvasToSceneTransform()); |
1417 return NULL; | 1470 return NULL; |
1418 } | 1471 } |
1419 } | 1472 } |
1420 } | 1473 } |
1421 } | 1474 } |
1475 | |
1476 | |
1477 void Serialize(Json::Value& target) const | |
1478 { | |
1479 Json::Value annotations = Json::arrayValue; | |
1480 | |
1481 for (Annotations::const_iterator it = annotations_.begin(); it != annotations_.end(); ++it) | |
1482 { | |
1483 assert(*it != NULL); | |
1484 | |
1485 Json::Value item; | |
1486 (*it)->Serialize(item); | |
1487 annotations.append(item); | |
1488 } | |
1489 | |
1490 target = Json::objectValue; | |
1491 target[KEY_ANNOTATIONS] = annotations; | |
1492 } | |
1422 }; | 1493 }; |
1423 } | 1494 } |
1424 #endif | 1495 #endif |
1425 | 1496 |
1426 | 1497 |
1450 ; | 1521 ; |
1451 | 1522 |
1452 std::cout << desc << std::endl; | 1523 std::cout << desc << std::endl; |
1453 | 1524 |
1454 std::cout << std::endl << "Keyboard shorcuts:" << std::endl | 1525 std::cout << std::endl << "Keyboard shorcuts:" << std::endl |
1455 << " a\tEnable/disable the angle measure tool" << std::endl | 1526 << " a\tEnable/disable the angle annotation tool" << std::endl |
1456 << " f\tToggle fullscreen display" << std::endl | 1527 << " f\tToggle fullscreen display" << std::endl |
1457 << " l\tEnable/disable the line measure tool" << std::endl | 1528 << " l\tEnable/disable the line annotation tool" << std::endl |
1458 << " q\tExit" << std::endl | 1529 << " q\tExit" << std::endl |
1459 << " r\tRedo the last edit to the measure tools" << std::endl | 1530 << " r\tRedo the last edit to the annotation tools" << std::endl |
1460 << " s\tFit the viewpoint to the image" << std::endl | 1531 << " s\tFit the viewpoint to the image" << std::endl |
1461 << " u\tUndo the last edit to the measure tools" << std::endl | 1532 << " u\tUndo the last edit to the annotation tools" << std::endl |
1462 << std::endl << "Mouse buttons:" << std::endl | 1533 << std::endl << "Mouse buttons:" << std::endl |
1463 << " left \tChange windowing, or edit measure" << std::endl | 1534 << " left \tChange windowing, or edit annotation" << std::endl |
1464 << " center\tMove the viewpoint, or edit measure" << std::endl | 1535 << " center\tMove the viewpoint, or edit annotation" << std::endl |
1465 << " right \tZoom, or edit measure" << std::endl | 1536 << " right \tZoom, or edit annotation" << std::endl |
1466 << std::endl; | 1537 << std::endl; |
1467 | 1538 |
1468 po::variables_map vm; | 1539 po::variables_map vm; |
1469 try | 1540 try |
1470 { | 1541 { |
1550 std::string font; | 1621 std::string font; |
1551 Orthanc::EmbeddedResources::GetFileResource(font, Orthanc::EmbeddedResources::UBUNTU_FONT); | 1622 Orthanc::EmbeddedResources::GetFileResource(font, Orthanc::EmbeddedResources::UBUNTU_FONT); |
1552 | 1623 |
1553 std::unique_ptr<OrthancStone::IViewport::ILock> lock(viewport->Lock()); | 1624 std::unique_ptr<OrthancStone::IViewport::ILock> lock(viewport->Lock()); |
1554 lock->GetCompositor().SetFont(0, font, 16, Orthanc::Encoding_Latin1); | 1625 lock->GetCompositor().SetFont(0, font, 16, Orthanc::Encoding_Latin1); |
1555 lock->GetController().SetUndoStack(undoStack); | 1626 //lock->GetController().SetUndoStack(undoStack); |
1556 } | 1627 } |
1557 | 1628 |
1558 ActiveTool activeTool = ActiveTool_None; | 1629 ActiveTool activeTool = ActiveTool_None; |
1559 | 1630 |
1560 boost::shared_ptr<OrthancStone::LineMeasureTool> lineMeasureTool(OrthancStone::LineMeasureTool::Create(viewport)); | 1631 boost::shared_ptr<OrthancStone::LineMeasureTool> lineMeasureTool(OrthancStone::LineMeasureTool::Create(viewport)); |
1565 bool angleMeasureFirst = true; | 1636 bool angleMeasureFirst = true; |
1566 angleMeasureTool->Disable(); | 1637 angleMeasureTool->Disable(); |
1567 | 1638 |
1568 OrthancStone::AnnotationsOverlay overlay(10); | 1639 OrthancStone::AnnotationsOverlay overlay(10); |
1569 overlay.SetActiveTool(OrthancStone::AnnotationsOverlay::Tool_Angle); | 1640 overlay.SetActiveTool(OrthancStone::AnnotationsOverlay::Tool_Angle); |
1641 | |
1642 { | |
1643 Json::Value v; | |
1644 overlay.Serialize(v); | |
1645 std::cout << v.toStyledString() << std::endl; | |
1646 } | |
1570 | 1647 |
1571 boost::shared_ptr<SdlSimpleViewerApplication> application( | 1648 boost::shared_ptr<SdlSimpleViewerApplication> application( |
1572 SdlSimpleViewerApplication::Create(context, viewport)); | 1649 SdlSimpleViewerApplication::Create(context, viewport)); |
1573 | 1650 |
1574 OrthancStone::DicomSource source; | 1651 OrthancStone::DicomSource source; |
1728 { | 1805 { |
1729 case SDL_MOUSEBUTTONDOWN: | 1806 case SDL_MOUSEBUTTONDOWN: |
1730 { | 1807 { |
1731 boost::shared_ptr<OrthancStone::IFlexiblePointerTracker> t; | 1808 boost::shared_ptr<OrthancStone::IFlexiblePointerTracker> t; |
1732 | 1809 |
1733 t.reset(overlay.CreateTracker(p.GetMainPosition(), lock->GetController().GetScene())); | 1810 if (p.GetMouseButton() == OrthancStone::MouseButton_Left) |
1811 { | |
1812 t.reset(overlay.CreateTracker(p.GetMainPosition(), lock->GetController().GetScene())); | |
1813 } | |
1814 | |
1734 if (t.get() == NULL) | 1815 if (t.get() == NULL) |
1735 { | 1816 { |
1736 switch (activeTool) | 1817 switch (activeTool) |
1737 { | 1818 { |
1738 case ActiveTool_Angle: | 1819 case ActiveTool_Angle: |