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 }