Mercurial > hg > orthanc-stone
comparison OrthancStone/Sources/Scene2D/AnnotationsSceneLayer.cpp @ 1821:36430d73e36c
introducing measure units in AnnotationsSceneLayer
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Wed, 26 May 2021 14:02:12 +0200 |
parents | fe402c678d18 |
children | 781e9fc8925e |
comparison
equal
deleted
inserted
replaced
1820:5baaad557d58 | 1821:36430d73e36c |
---|---|
40 static const char* const KEY_Y1 = "y1"; | 40 static const char* const KEY_Y1 = "y1"; |
41 static const char* const KEY_X2 = "x2"; | 41 static const char* const KEY_X2 = "x2"; |
42 static const char* const KEY_Y2 = "y2"; | 42 static const char* const KEY_Y2 = "y2"; |
43 static const char* const KEY_X3 = "x3"; | 43 static const char* const KEY_X3 = "x3"; |
44 static const char* const KEY_Y3 = "y3"; | 44 static const char* const KEY_Y3 = "y3"; |
45 static const char* const KEY_UNITS = "units"; | |
45 | 46 |
46 static const char* const VALUE_ANGLE = "angle"; | 47 static const char* const VALUE_ANGLE = "angle"; |
47 static const char* const VALUE_CIRCLE = "circle"; | 48 static const char* const VALUE_CIRCLE = "circle"; |
48 static const char* const VALUE_SEGMENT = "segment"; | 49 static const char* const VALUE_SEGMENT = "segment"; |
50 static const char* const VALUE_MILLIMETERS = "millimeters"; | |
51 static const char* const VALUE_PIXELS = "pixels"; | |
49 | 52 |
50 #if 0 | 53 #if 0 |
51 static OrthancStone::Color COLOR_PRIMITIVES(192, 192, 192); | 54 static OrthancStone::Color COLOR_PRIMITIVES(192, 192, 192); |
52 static OrthancStone::Color COLOR_HOVER(0, 255, 0); | 55 static OrthancStone::Color COLOR_HOVER(0, 255, 0); |
53 static OrthancStone::Color COLOR_TEXT(255, 0, 0); | 56 static OrthancStone::Color COLOR_TEXT(255, 0, 0); |
164 private: | 167 private: |
165 typedef std::list<GeometricPrimitive*> GeometricPrimitives; | 168 typedef std::list<GeometricPrimitive*> GeometricPrimitives; |
166 | 169 |
167 AnnotationsSceneLayer& that_; | 170 AnnotationsSceneLayer& that_; |
168 GeometricPrimitives primitives_; | 171 GeometricPrimitives primitives_; |
172 Units units_; | |
169 | 173 |
170 public: | 174 public: |
171 explicit Annotation(AnnotationsSceneLayer& that) : | 175 explicit Annotation(AnnotationsSceneLayer& that, |
172 that_(that) | 176 Units units) : |
177 that_(that), | |
178 units_(units) | |
173 { | 179 { |
174 that.AddAnnotation(this); | 180 that.AddAnnotation(this); |
175 } | 181 } |
176 | 182 |
177 virtual ~Annotation() | 183 virtual ~Annotation() |
178 { | 184 { |
179 for (GeometricPrimitives::iterator it = primitives_.begin(); it != primitives_.end(); ++it) | 185 for (GeometricPrimitives::iterator it = primitives_.begin(); it != primitives_.end(); ++it) |
180 { | 186 { |
181 that_.DeletePrimitive(*it); | 187 that_.DeletePrimitive(*it); |
182 } | 188 } |
189 } | |
190 | |
191 Units GetUnits() const | |
192 { | |
193 return units_; | |
183 } | 194 } |
184 | 195 |
185 GeometricPrimitive* AddPrimitive(GeometricPrimitive* primitive) | 196 GeometricPrimitive* AddPrimitive(GeometricPrimitive* primitive) |
186 { | 197 { |
187 if (primitive == NULL) | 198 if (primitive == NULL) |
770 content.SetBorder(10); | 781 content.SetBorder(10); |
771 | 782 |
772 double dx = x1 - x2; | 783 double dx = x1 - x2; |
773 double dy = y1 - y2; | 784 double dy = y1 - y2; |
774 char buf[32]; | 785 char buf[32]; |
775 sprintf(buf, "%0.2f cm", sqrt(dx * dx + dy * dy) / 10.0); | 786 |
787 switch (GetUnits()) | |
788 { | |
789 case Units_Millimeters: | |
790 sprintf(buf, "%0.2f cm", sqrt(dx * dx + dy * dy) / 10.0); | |
791 break; | |
792 | |
793 case Units_Pixels: | |
794 sprintf(buf, "%0.1f px", sqrt(dx * dx + dy * dy)); | |
795 break; | |
796 | |
797 default: | |
798 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); | |
799 } | |
800 | |
776 content.SetText(buf); | 801 content.SetText(buf); |
777 | 802 |
778 label_.SetContent(content); | 803 label_.SetContent(content); |
779 } | 804 } |
780 } | 805 } |
781 | 806 |
782 public: | 807 public: |
783 SegmentAnnotation(AnnotationsSceneLayer& that, | 808 SegmentAnnotation(AnnotationsSceneLayer& that, |
809 Units units, | |
784 bool showLabel, | 810 bool showLabel, |
785 const ScenePoint2D& p1, | 811 const ScenePoint2D& p1, |
786 const ScenePoint2D& p2) : | 812 const ScenePoint2D& p2) : |
787 Annotation(that), | 813 Annotation(that, units), |
788 showLabel_(showLabel), | 814 showLabel_(showLabel), |
789 handle1_(AddTypedPrimitive<Handle>(new Handle(*this, p1))), | 815 handle1_(AddTypedPrimitive<Handle>(new Handle(*this, p1))), |
790 handle2_(AddTypedPrimitive<Handle>(new Handle(*this, p2))), | 816 handle2_(AddTypedPrimitive<Handle>(new Handle(*this, p2))), |
791 segment_(AddTypedPrimitive<Segment>(new Segment(*this, p1, p2))), | 817 segment_(AddTypedPrimitive<Segment>(new Segment(*this, p1, p2))), |
792 label_(AddTypedPrimitive<Text>(new Text(that, *this))) | 818 label_(AddTypedPrimitive<Text>(new Text(that, *this))) |
830 target[KEY_X2] = handle2_.GetCenter().GetX(); | 856 target[KEY_X2] = handle2_.GetCenter().GetX(); |
831 target[KEY_Y2] = handle2_.GetCenter().GetY(); | 857 target[KEY_Y2] = handle2_.GetCenter().GetY(); |
832 } | 858 } |
833 | 859 |
834 static void Unserialize(AnnotationsSceneLayer& target, | 860 static void Unserialize(AnnotationsSceneLayer& target, |
861 Units units, | |
835 const Json::Value& source) | 862 const Json::Value& source) |
836 { | 863 { |
837 if (source.isMember(KEY_X1) && | 864 if (source.isMember(KEY_X1) && |
838 source.isMember(KEY_Y1) && | 865 source.isMember(KEY_Y1) && |
839 source.isMember(KEY_X2) && | 866 source.isMember(KEY_X2) && |
841 source[KEY_X1].isNumeric() && | 868 source[KEY_X1].isNumeric() && |
842 source[KEY_Y1].isNumeric() && | 869 source[KEY_Y1].isNumeric() && |
843 source[KEY_X2].isNumeric() && | 870 source[KEY_X2].isNumeric() && |
844 source[KEY_Y2].isNumeric()) | 871 source[KEY_Y2].isNumeric()) |
845 { | 872 { |
846 new SegmentAnnotation(target, true, | 873 new SegmentAnnotation(target, units, true, |
847 ScenePoint2D(source[KEY_X1].asDouble(), source[KEY_Y1].asDouble()), | 874 ScenePoint2D(source[KEY_X1].asDouble(), source[KEY_Y1].asDouble()), |
848 ScenePoint2D(source[KEY_X2].asDouble(), source[KEY_Y2].asDouble())); | 875 ScenePoint2D(source[KEY_X2].asDouble(), source[KEY_Y2].asDouble())); |
849 } | 876 } |
850 else | 877 else |
851 { | 878 { |
896 label_.SetContent(content); | 923 label_.SetContent(content); |
897 } | 924 } |
898 | 925 |
899 public: | 926 public: |
900 AngleAnnotation(AnnotationsSceneLayer& that, | 927 AngleAnnotation(AnnotationsSceneLayer& that, |
928 Units units, | |
901 const ScenePoint2D& start, | 929 const ScenePoint2D& start, |
902 const ScenePoint2D& middle, | 930 const ScenePoint2D& middle, |
903 const ScenePoint2D& end) : | 931 const ScenePoint2D& end) : |
904 Annotation(that), | 932 Annotation(that, units), |
905 startHandle_(AddTypedPrimitive<Handle>(new Handle(*this, start))), | 933 startHandle_(AddTypedPrimitive<Handle>(new Handle(*this, start))), |
906 middleHandle_(AddTypedPrimitive<Handle>(new Handle(*this, middle))), | 934 middleHandle_(AddTypedPrimitive<Handle>(new Handle(*this, middle))), |
907 endHandle_(AddTypedPrimitive<Handle>(new Handle(*this, end))), | 935 endHandle_(AddTypedPrimitive<Handle>(new Handle(*this, end))), |
908 segment1_(AddTypedPrimitive<Segment>(new Segment(*this, start, middle))), | 936 segment1_(AddTypedPrimitive<Segment>(new Segment(*this, start, middle))), |
909 segment2_(AddTypedPrimitive<Segment>(new Segment(*this, middle, end))), | 937 segment2_(AddTypedPrimitive<Segment>(new Segment(*this, middle, end))), |
968 target[KEY_X3] = endHandle_.GetCenter().GetX(); | 996 target[KEY_X3] = endHandle_.GetCenter().GetX(); |
969 target[KEY_Y3] = endHandle_.GetCenter().GetY(); | 997 target[KEY_Y3] = endHandle_.GetCenter().GetY(); |
970 } | 998 } |
971 | 999 |
972 static void Unserialize(AnnotationsSceneLayer& target, | 1000 static void Unserialize(AnnotationsSceneLayer& target, |
1001 Units units, | |
973 const Json::Value& source) | 1002 const Json::Value& source) |
974 { | 1003 { |
975 if (source.isMember(KEY_X1) && | 1004 if (source.isMember(KEY_X1) && |
976 source.isMember(KEY_Y1) && | 1005 source.isMember(KEY_Y1) && |
977 source.isMember(KEY_X2) && | 1006 source.isMember(KEY_X2) && |
983 source[KEY_X2].isNumeric() && | 1012 source[KEY_X2].isNumeric() && |
984 source[KEY_Y2].isNumeric() && | 1013 source[KEY_Y2].isNumeric() && |
985 source[KEY_X3].isNumeric() && | 1014 source[KEY_X3].isNumeric() && |
986 source[KEY_Y3].isNumeric()) | 1015 source[KEY_Y3].isNumeric()) |
987 { | 1016 { |
988 new AngleAnnotation(target, | 1017 new AngleAnnotation(target, units, |
989 ScenePoint2D(source[KEY_X1].asDouble(), source[KEY_Y1].asDouble()), | 1018 ScenePoint2D(source[KEY_X1].asDouble(), source[KEY_Y1].asDouble()), |
990 ScenePoint2D(source[KEY_X2].asDouble(), source[KEY_Y2].asDouble()), | 1019 ScenePoint2D(source[KEY_X2].asDouble(), source[KEY_Y2].asDouble()), |
991 ScenePoint2D(source[KEY_X3].asDouble(), source[KEY_Y3].asDouble())); | 1020 ScenePoint2D(source[KEY_X3].asDouble(), source[KEY_Y3].asDouble())); |
992 } | 1021 } |
993 else | 1022 else |
1034 double diameter = sqrt(dx * dx + dy * dy); // in millimeters | 1063 double diameter = sqrt(dx * dx + dy * dy); // in millimeters |
1035 | 1064 |
1036 double area = PI * diameter * diameter / 4.0; | 1065 double area = PI * diameter * diameter / 4.0; |
1037 | 1066 |
1038 char buf[32]; | 1067 char buf[32]; |
1039 sprintf(buf, "%0.2f cm\n%0.2f cm%c%c", | 1068 |
1040 diameter / 10.0, | 1069 switch (GetUnits()) |
1041 area / 100.0, | 1070 { |
1042 0xc2, 0xb2 /* two bytes corresponding to two power in UTF-8 */); | 1071 case Units_Millimeters: |
1072 sprintf(buf, "%0.2f cm\n%0.2f cm%c%c", | |
1073 diameter / 10.0, | |
1074 area / 100.0, | |
1075 0xc2, 0xb2 /* two bytes corresponding to two power in UTF-8 */); | |
1076 break; | |
1077 | |
1078 case Units_Pixels: | |
1079 // Don't report area (pixel-times-pixel is a strange unit) | |
1080 sprintf(buf, "%0.1f px", diameter); | |
1081 break; | |
1082 | |
1083 default: | |
1084 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); | |
1085 } | |
1086 | |
1043 content.SetText(buf); | 1087 content.SetText(buf); |
1044 | 1088 |
1045 label_.SetContent(content); | 1089 label_.SetContent(content); |
1046 } | 1090 } |
1047 | 1091 |
1048 public: | 1092 public: |
1049 CircleAnnotation(AnnotationsSceneLayer& that, | 1093 CircleAnnotation(AnnotationsSceneLayer& that, |
1094 Units units, | |
1050 const ScenePoint2D& p1, | 1095 const ScenePoint2D& p1, |
1051 const ScenePoint2D& p2) : | 1096 const ScenePoint2D& p2) : |
1052 Annotation(that), | 1097 Annotation(that, units), |
1053 handle1_(AddTypedPrimitive<Handle>(new Handle(*this, p1))), | 1098 handle1_(AddTypedPrimitive<Handle>(new Handle(*this, p1))), |
1054 handle2_(AddTypedPrimitive<Handle>(new Handle(*this, p2))), | 1099 handle2_(AddTypedPrimitive<Handle>(new Handle(*this, p2))), |
1055 segment_(AddTypedPrimitive<Segment>(new Segment(*this, p1, p2))), | 1100 segment_(AddTypedPrimitive<Segment>(new Segment(*this, p1, p2))), |
1056 circle_(AddTypedPrimitive<Circle>(new Circle(*this, p1, p2))), | 1101 circle_(AddTypedPrimitive<Circle>(new Circle(*this, p1, p2))), |
1057 label_(AddTypedPrimitive<Text>(new Text(that, *this))) | 1102 label_(AddTypedPrimitive<Text>(new Text(that, *this))) |
1092 target[KEY_X2] = handle2_.GetCenter().GetX(); | 1137 target[KEY_X2] = handle2_.GetCenter().GetX(); |
1093 target[KEY_Y2] = handle2_.GetCenter().GetY(); | 1138 target[KEY_Y2] = handle2_.GetCenter().GetY(); |
1094 } | 1139 } |
1095 | 1140 |
1096 static void Unserialize(AnnotationsSceneLayer& target, | 1141 static void Unserialize(AnnotationsSceneLayer& target, |
1142 Units units, | |
1097 const Json::Value& source) | 1143 const Json::Value& source) |
1098 { | 1144 { |
1099 if (source.isMember(KEY_X1) && | 1145 if (source.isMember(KEY_X1) && |
1100 source.isMember(KEY_Y1) && | 1146 source.isMember(KEY_Y1) && |
1101 source.isMember(KEY_X2) && | 1147 source.isMember(KEY_X2) && |
1103 source[KEY_X1].isNumeric() && | 1149 source[KEY_X1].isNumeric() && |
1104 source[KEY_Y1].isNumeric() && | 1150 source[KEY_Y1].isNumeric() && |
1105 source[KEY_X2].isNumeric() && | 1151 source[KEY_X2].isNumeric() && |
1106 source[KEY_Y2].isNumeric()) | 1152 source[KEY_Y2].isNumeric()) |
1107 { | 1153 { |
1108 new CircleAnnotation(target, | 1154 new CircleAnnotation(target, units, |
1109 ScenePoint2D(source[KEY_X1].asDouble(), source[KEY_Y1].asDouble()), | 1155 ScenePoint2D(source[KEY_X1].asDouble(), source[KEY_Y1].asDouble()), |
1110 ScenePoint2D(source[KEY_X2].asDouble(), source[KEY_Y2].asDouble())); | 1156 ScenePoint2D(source[KEY_X2].asDouble(), source[KEY_Y2].asDouble())); |
1111 } | 1157 } |
1112 else | 1158 else |
1113 { | 1159 { |
1125 AffineTransform2D canvasToScene_; | 1171 AffineTransform2D canvasToScene_; |
1126 Handle* handle2_; | 1172 Handle* handle2_; |
1127 | 1173 |
1128 public: | 1174 public: |
1129 CreateSegmentOrCircleTracker(AnnotationsSceneLayer& that, | 1175 CreateSegmentOrCircleTracker(AnnotationsSceneLayer& that, |
1176 Units units, | |
1130 bool isCircle, | 1177 bool isCircle, |
1131 const ScenePoint2D& sceneClick, | 1178 const ScenePoint2D& sceneClick, |
1132 const AffineTransform2D& canvasToScene) : | 1179 const AffineTransform2D& canvasToScene) : |
1133 that_(that), | 1180 that_(that), |
1134 annotation_(NULL), | 1181 annotation_(NULL), |
1135 canvasToScene_(canvasToScene), | 1182 canvasToScene_(canvasToScene), |
1136 handle2_(NULL) | 1183 handle2_(NULL) |
1137 { | 1184 { |
1138 if (isCircle) | 1185 if (isCircle) |
1139 { | 1186 { |
1140 annotation_ = new CircleAnnotation(that, sceneClick, sceneClick); | 1187 annotation_ = new CircleAnnotation(that, units, sceneClick, sceneClick); |
1141 handle2_ = &dynamic_cast<CircleAnnotation*>(annotation_)->GetHandle2(); | 1188 handle2_ = &dynamic_cast<CircleAnnotation*>(annotation_)->GetHandle2(); |
1142 } | 1189 } |
1143 else | 1190 else |
1144 { | 1191 { |
1145 annotation_ = new SegmentAnnotation(that, true /* show label */, sceneClick, sceneClick); | 1192 annotation_ = new SegmentAnnotation(that, units, true /* show label */, sceneClick, sceneClick); |
1146 handle2_ = &dynamic_cast<SegmentAnnotation*>(annotation_)->GetHandle2(); | 1193 handle2_ = &dynamic_cast<SegmentAnnotation*>(annotation_)->GetHandle2(); |
1147 } | 1194 } |
1148 | 1195 |
1149 assert(annotation_ != NULL && | 1196 assert(annotation_ != NULL && |
1150 handle2_ != NULL); | 1197 handle2_ != NULL); |
1197 AngleAnnotation* angle_; | 1244 AngleAnnotation* angle_; |
1198 AffineTransform2D canvasToScene_; | 1245 AffineTransform2D canvasToScene_; |
1199 | 1246 |
1200 public: | 1247 public: |
1201 CreateAngleTracker(AnnotationsSceneLayer& that, | 1248 CreateAngleTracker(AnnotationsSceneLayer& that, |
1249 Units units, | |
1202 const ScenePoint2D& sceneClick, | 1250 const ScenePoint2D& sceneClick, |
1203 const AffineTransform2D& canvasToScene) : | 1251 const AffineTransform2D& canvasToScene) : |
1204 that_(that), | 1252 that_(that), |
1205 segment_(NULL), | 1253 segment_(NULL), |
1206 angle_(NULL), | 1254 angle_(NULL), |
1207 canvasToScene_(canvasToScene) | 1255 canvasToScene_(canvasToScene) |
1208 { | 1256 { |
1209 segment_ = new SegmentAnnotation(that, false /* no length label */, sceneClick, sceneClick); | 1257 segment_ = new SegmentAnnotation(that, units, false /* no length label */, sceneClick, sceneClick); |
1210 } | 1258 } |
1211 | 1259 |
1212 virtual void PointerMove(const PointerEvent& event) ORTHANC_OVERRIDE | 1260 virtual void PointerMove(const PointerEvent& event) ORTHANC_OVERRIDE |
1213 { | 1261 { |
1214 if (segment_ != NULL) | 1262 if (segment_ != NULL) |
1230 { | 1278 { |
1231 if (segment_ != NULL) | 1279 if (segment_ != NULL) |
1232 { | 1280 { |
1233 // End of first step: The first segment is available, now create the angle | 1281 // End of first step: The first segment is available, now create the angle |
1234 | 1282 |
1235 angle_ = new AngleAnnotation(that_, segment_->GetHandle1().GetCenter(), | 1283 angle_ = new AngleAnnotation(that_, segment_->GetUnits(), segment_->GetHandle1().GetCenter(), |
1236 segment_->GetHandle2().GetCenter(), | 1284 segment_->GetHandle2().GetCenter(), |
1237 segment_->GetHandle2().GetCenter()); | 1285 segment_->GetHandle2().GetCenter()); |
1238 | 1286 |
1239 that_.DeleteAnnotation(segment_); | 1287 that_.DeleteAnnotation(segment_); |
1240 segment_ = NULL; | 1288 segment_ = NULL; |
1346 | 1394 |
1347 | 1395 |
1348 AnnotationsSceneLayer::AnnotationsSceneLayer(size_t macroLayerIndex) : | 1396 AnnotationsSceneLayer::AnnotationsSceneLayer(size_t macroLayerIndex) : |
1349 activeTool_(Tool_Edit), | 1397 activeTool_(Tool_Edit), |
1350 macroLayerIndex_(macroLayerIndex), | 1398 macroLayerIndex_(macroLayerIndex), |
1351 polylineSubLayer_(0) // dummy initialization | 1399 polylineSubLayer_(0), // dummy initialization |
1400 units_(Units_Pixels) | |
1352 { | 1401 { |
1353 } | 1402 } |
1354 | 1403 |
1355 | 1404 |
1356 void AnnotationsSceneLayer::Clear() | 1405 void AnnotationsSceneLayer::Clear() |
1364 annotations_.clear(); | 1413 annotations_.clear(); |
1365 | 1414 |
1366 ClearHover(); | 1415 ClearHover(); |
1367 } | 1416 } |
1368 | 1417 |
1418 | |
1419 void AnnotationsSceneLayer::SetUnits(Units units) | |
1420 { | |
1421 if (units_ != units) | |
1422 { | |
1423 Clear(); | |
1424 units_ = units; | |
1425 } | |
1426 } | |
1427 | |
1369 | 1428 |
1370 void AnnotationsSceneLayer::AddSegmentAnnotation(const ScenePoint2D& p1, | 1429 void AnnotationsSceneLayer::AddSegmentAnnotation(const ScenePoint2D& p1, |
1371 const ScenePoint2D& p2) | 1430 const ScenePoint2D& p2) |
1372 { | 1431 { |
1373 annotations_.insert(new SegmentAnnotation(*this, true /* show label */, p1, p2)); | 1432 annotations_.insert(new SegmentAnnotation(*this, units_, true /* show label */, p1, p2)); |
1374 } | 1433 } |
1375 | 1434 |
1376 | 1435 |
1377 void AnnotationsSceneLayer::AddCircleAnnotation(const ScenePoint2D& p1, | 1436 void AnnotationsSceneLayer::AddCircleAnnotation(const ScenePoint2D& p1, |
1378 const ScenePoint2D& p2) | 1437 const ScenePoint2D& p2) |
1379 { | 1438 { |
1380 annotations_.insert(new CircleAnnotation(*this, p1, p2)); | 1439 annotations_.insert(new CircleAnnotation(*this, units_, p1, p2)); |
1381 } | 1440 } |
1382 | 1441 |
1383 | 1442 |
1384 void AnnotationsSceneLayer::AddAngleAnnotation(const ScenePoint2D& p1, | 1443 void AnnotationsSceneLayer::AddAngleAnnotation(const ScenePoint2D& p1, |
1385 const ScenePoint2D& p2, | 1444 const ScenePoint2D& p2, |
1386 const ScenePoint2D& p3) | 1445 const ScenePoint2D& p3) |
1387 { | 1446 { |
1388 annotations_.insert(new AngleAnnotation(*this, p1, p2, p3)); | 1447 annotations_.insert(new AngleAnnotation(*this, units_, p1, p2, p3)); |
1389 } | 1448 } |
1390 | 1449 |
1391 | 1450 |
1392 void AnnotationsSceneLayer::Render(Scene2D& scene) | 1451 void AnnotationsSceneLayer::Render(Scene2D& scene) |
1393 { | 1452 { |
1522 else | 1581 else |
1523 { | 1582 { |
1524 switch (activeTool_) | 1583 switch (activeTool_) |
1525 { | 1584 { |
1526 case Tool_Segment: | 1585 case Tool_Segment: |
1527 return new CreateSegmentOrCircleTracker(*this, false /* segment */, s, scene.GetCanvasToSceneTransform()); | 1586 return new CreateSegmentOrCircleTracker(*this, units_, false /* segment */, s, scene.GetCanvasToSceneTransform()); |
1528 | 1587 |
1529 case Tool_Circle: | 1588 case Tool_Circle: |
1530 return new CreateSegmentOrCircleTracker(*this, true /* circle */, s, scene.GetCanvasToSceneTransform()); | 1589 return new CreateSegmentOrCircleTracker(*this, units_, true /* circle */, s, scene.GetCanvasToSceneTransform()); |
1531 | 1590 |
1532 case Tool_Angle: | 1591 case Tool_Angle: |
1533 return new CreateAngleTracker(*this, s, scene.GetCanvasToSceneTransform()); | 1592 return new CreateAngleTracker(*this, units_, s, scene.GetCanvasToSceneTransform()); |
1534 | 1593 |
1535 default: | 1594 default: |
1536 return NULL; | 1595 return NULL; |
1537 } | 1596 } |
1538 } | 1597 } |
1553 annotations.append(item); | 1612 annotations.append(item); |
1554 } | 1613 } |
1555 | 1614 |
1556 target = Json::objectValue; | 1615 target = Json::objectValue; |
1557 target[KEY_ANNOTATIONS] = annotations; | 1616 target[KEY_ANNOTATIONS] = annotations; |
1617 | |
1618 switch (units_) | |
1619 { | |
1620 case Units_Millimeters: | |
1621 target[KEY_UNITS] = VALUE_MILLIMETERS; | |
1622 break; | |
1623 | |
1624 case Units_Pixels: | |
1625 target[KEY_UNITS] = VALUE_PIXELS; | |
1626 break; | |
1627 | |
1628 default: | |
1629 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); | |
1630 } | |
1558 } | 1631 } |
1559 | 1632 |
1560 | 1633 |
1561 void AnnotationsSceneLayer::Unserialize(const Json::Value& serialized) | 1634 void AnnotationsSceneLayer::Unserialize(const Json::Value& serialized) |
1562 { | 1635 { |
1563 Clear(); | 1636 Clear(); |
1564 | 1637 |
1565 if (serialized.type() != Json::objectValue || | 1638 if (serialized.type() != Json::objectValue || |
1566 !serialized.isMember(KEY_ANNOTATIONS) || | 1639 !serialized.isMember(KEY_ANNOTATIONS) || |
1567 serialized[KEY_ANNOTATIONS].type() != Json::arrayValue) | 1640 !serialized.isMember(KEY_UNITS) || |
1641 serialized[KEY_ANNOTATIONS].type() != Json::arrayValue || | |
1642 serialized[KEY_UNITS].type() != Json::stringValue) | |
1568 { | 1643 { |
1569 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat, "Cannot unserialize a set of annotations"); | 1644 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat, "Cannot unserialize a set of annotations"); |
1645 } | |
1646 | |
1647 const std::string& u = serialized[KEY_UNITS].asString(); | |
1648 | |
1649 if (u == VALUE_MILLIMETERS) | |
1650 { | |
1651 units_ = Units_Millimeters; | |
1652 } | |
1653 else if (u == VALUE_PIXELS) | |
1654 { | |
1655 units_ = Units_Pixels; | |
1656 } | |
1657 else | |
1658 { | |
1659 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat, "Unknown units: " + u); | |
1570 } | 1660 } |
1571 | 1661 |
1572 const Json::Value& annotations = serialized[KEY_ANNOTATIONS]; | 1662 const Json::Value& annotations = serialized[KEY_ANNOTATIONS]; |
1573 | 1663 |
1574 for (Json::Value::ArrayIndex i = 0; i < annotations.size(); i++) | 1664 for (Json::Value::ArrayIndex i = 0; i < annotations.size(); i++) |
1582 | 1672 |
1583 const std::string& type = annotations[i][KEY_TYPE].asString(); | 1673 const std::string& type = annotations[i][KEY_TYPE].asString(); |
1584 | 1674 |
1585 if (type == VALUE_ANGLE) | 1675 if (type == VALUE_ANGLE) |
1586 { | 1676 { |
1587 AngleAnnotation::Unserialize(*this, annotations[i]); | 1677 AngleAnnotation::Unserialize(*this, units_, annotations[i]); |
1588 } | 1678 } |
1589 else if (type == VALUE_CIRCLE) | 1679 else if (type == VALUE_CIRCLE) |
1590 { | 1680 { |
1591 CircleAnnotation::Unserialize(*this, annotations[i]); | 1681 CircleAnnotation::Unserialize(*this, units_, annotations[i]); |
1592 } | 1682 } |
1593 else if (type == VALUE_SEGMENT) | 1683 else if (type == VALUE_SEGMENT) |
1594 { | 1684 { |
1595 SegmentAnnotation::Unserialize(*this, annotations[i]); | 1685 SegmentAnnotation::Unserialize(*this, units_, annotations[i]); |
1596 } | 1686 } |
1597 else | 1687 else |
1598 { | 1688 { |
1599 LOG(ERROR) << "Cannot unserialize unknown type of annotation: " << type; | 1689 LOG(ERROR) << "Cannot unserialize unknown type of annotation: " << type; |
1600 } | 1690 } |