changeset 1983:20fa913272b7

drawing rectangle probe
author Sebastien Jodogne <s.jodogne@gmail.com>
date Mon, 31 Oct 2022 12:32:47 +0100
parents ba45e1b0812a
children 187a261d7ae2
files OrthancStone/Sources/Scene2D/AnnotationsSceneLayer.cpp OrthancStone/Sources/Scene2D/AnnotationsSceneLayer.h
diffstat 2 files changed, 384 insertions(+), 64 deletions(-) [+]
line wrap: on
line diff
--- a/OrthancStone/Sources/Scene2D/AnnotationsSceneLayer.cpp	Mon Oct 31 08:55:14 2022 +0100
+++ b/OrthancStone/Sources/Scene2D/AnnotationsSceneLayer.cpp	Mon Oct 31 12:32:47 2022 +0100
@@ -55,6 +55,7 @@
 static const char* const VALUE_MILLIMETERS = "millimeters";
 static const char* const VALUE_PIXELS = "pixels";
 static const char* const VALUE_PIXEL_PROBE = "pixel-probe";
+static const char* const VALUE_RECTANGLE_PROBE = "rectangle-probe";
 
 #if 0
 static OrthancStone::Color COLOR_PRIMITIVES(192, 192, 192);
@@ -201,6 +202,11 @@
       }
     }
 
+    AnnotationsSceneLayer& GetParentLayer() const
+    {
+      return that_;
+    }
+
     Units GetUnits() const
     {
       return units_;
@@ -228,6 +234,10 @@
       return *primitive;
     }
 
+    virtual unsigned int GetHandlesCount() const = 0;
+
+    virtual Handle& GetHandle(unsigned int index) const = 0;
+
     virtual void SignalMove(GeometricPrimitive& primitive,
                             const Scene2D& scene) = 0;
 
@@ -287,6 +297,14 @@
       delta_ = ScenePoint2D(0, 0);
     }
 
+    void SetCenter(double x,
+                   double y)
+    {
+      SetModified(true);
+      center_ = ScenePoint2D(x, y);
+      delta_ = ScenePoint2D(0, 0);
+    }
+
     ScenePoint2D GetCenter() const
     {
       return center_ + delta_;
@@ -387,6 +405,18 @@
     {
     }
 
+    Segment(Annotation& parentAnnotation,
+            double x1,
+            double y1,
+            double x2,
+            double y2) :
+      GeometricPrimitive(parentAnnotation, 1),  // Can only be selected if no handle matches
+      p1_(x1, y1),
+      p2_(x2, y2),
+      delta_(0, 0)
+    {
+    }
+
     void SetPosition(const ScenePoint2D& p1,
                      const ScenePoint2D& p2)
     {
@@ -396,6 +426,17 @@
       delta_ = ScenePoint2D(0, 0);
     }
 
+    void SetPosition(double x1,
+                     double y1,
+                     double x2,
+                     double y2)
+    {
+      SetModified(true);
+      p1_ = ScenePoint2D(x1, y1);
+      p2_ = ScenePoint2D(x2, y2);
+      delta_ = ScenePoint2D(0, 0);
+    }
+
     ScenePoint2D GetPosition1() const
     {
       return p1_ + delta_;
@@ -506,7 +547,8 @@
         
       const double radius = ScenePoint2D::DistancePtPt(center, p1_);
 
-      polyline.AddCircle(center, radius, GetActiveColor(), NUM_SEGMENTS);
+      polyline.AddCircle(center.GetX() + delta_.GetX(), center.GetY() + delta_.GetY(),
+                         radius, GetActiveColor(), NUM_SEGMENTS);
     }
       
     virtual void RenderOtherLayers(MacroSceneLayer& macro,
@@ -879,14 +921,24 @@
       UpdateLabel();
     }
 
-    Handle& GetHandle1() const
+    virtual unsigned int GetHandlesCount() const ORTHANC_OVERRIDE
     {
-      return handle1_;
+      return 2;
     }
 
-    Handle& GetHandle2() const
+    virtual Handle& GetHandle(unsigned int index) const ORTHANC_OVERRIDE
     {
-      return handle2_;
+      switch (index)
+      {
+        case 0:
+          return handle1_;
+
+        case 1:
+          return handle2_;
+
+        default:
+          throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
+      }
     }
 
     virtual void SignalMove(GeometricPrimitive& primitive,
@@ -902,6 +954,10 @@
         handle1_.SetCenter(segment_.GetPosition1());
         handle2_.SetCenter(segment_.GetPosition2());
       }
+      else
+      {
+        throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented);
+      }
         
       UpdateLabel();
     }
@@ -964,10 +1020,9 @@
 
   public:
     ProbingAnnotation(AnnotationsSceneLayer& that,
-                      Units units,
-                      int probedLayer) :
+                      Units units) :
       Annotation(that, units),
-      probedLayer_(probedLayer),
+      probedLayer_(that.GetProbedLayer()),
       probeChanged_(true),
       lastLayerRevision_(0)
     {
@@ -1053,9 +1108,8 @@
   public:
     PixelProbeAnnotation(AnnotationsSceneLayer& that,
                          Units units,
-                         const ScenePoint2D& p,
-                         int probedLayer) :
-      ProbingAnnotation(that, units, probedLayer),
+                         const ScenePoint2D& p) :
+      ProbingAnnotation(that, units),
       handle_(AddTypedPrimitive<Handle>(new Handle(*this, Handle::Shape_CrossedSquare, p))),
       label_(AddTypedPrimitive<Text>(new Text(that, *this)))
     {
@@ -1069,9 +1123,21 @@
       label_.SetColor(COLOR_TEXT);
     }
 
-    Handle& GetHandle() const
+    virtual unsigned int GetHandlesCount() const ORTHANC_OVERRIDE
+    {
+      return 1;
+    }
+
+    virtual Handle& GetHandle(unsigned int index) const ORTHANC_OVERRIDE
     {
-      return handle_;
+      if (index == 0)
+      {
+        return handle_;
+      }
+      else
+      {
+        throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
+      }
     }
 
     virtual void SignalMove(GeometricPrimitive& primitive,
@@ -1091,7 +1157,6 @@
 
     static void Unserialize(AnnotationsSceneLayer& target,
                             Units units,
-                            int probedLayer,
                             const Json::Value& source)
     {
       if (source.isMember(KEY_X) &&
@@ -1100,8 +1165,7 @@
           source[KEY_Y].isNumeric())
       {
         new PixelProbeAnnotation(target, units,
-                                 ScenePoint2D(source[KEY_X].asDouble(), source[KEY_Y].asDouble()),
-                                 probedLayer);
+                                 ScenePoint2D(source[KEY_X].asDouble(), source[KEY_Y].asDouble()));
       }
       else
       {
@@ -1171,9 +1235,27 @@
       UpdateLabel();
     }
 
-    Handle& GetEndHandle() const
+    virtual unsigned int GetHandlesCount() const ORTHANC_OVERRIDE
+    {
+      return 3;
+    }
+
+    virtual Handle& GetHandle(unsigned int index) const ORTHANC_OVERRIDE
     {
-      return endHandle_;
+      switch (index)
+      {
+        case 0:
+          return startHandle_;
+
+        case 1:
+          return middleHandle_;
+
+        case 2:
+          return endHandle_;
+
+        default:
+          throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
+      }
     }
 
     virtual void SignalMove(GeometricPrimitive& primitive,
@@ -1211,6 +1293,10 @@
         arc_.SetMiddle(segment2_.GetPosition1());
         arc_.SetEnd(segment2_.GetPosition2());
       }
+      else
+      {
+        throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented);
+      }
 
       UpdateLabel();
     }
@@ -1339,9 +1425,24 @@
       UpdateLabel();
     }
 
-    Handle& GetHandle2() const
+    virtual unsigned int GetHandlesCount() const ORTHANC_OVERRIDE
+    {
+      return 2;
+    }
+
+    virtual Handle& GetHandle(unsigned int index) const ORTHANC_OVERRIDE
     {
-      return handle2_;
+      switch (index)
+      {
+        case 0:
+          return handle1_;
+
+        case 1:
+          return handle2_;
+
+        default:
+          throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
+      }
     }
 
     virtual void SignalMove(GeometricPrimitive& primitive,
@@ -1365,6 +1466,10 @@
         handle2_.SetCenter(circle_.GetPosition2());
         segment_.SetPosition(circle_.GetPosition1(), circle_.GetPosition2());
       }
+      else
+      {
+        throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented);
+      }
         
       UpdateLabel();
     }
@@ -1408,38 +1513,237 @@
   };
 
     
-  class AnnotationsSceneLayer::CreateSegmentOrCircleTracker : public IFlexiblePointerTracker
+  class AnnotationsSceneLayer::RectangleProbeAnnotation : public ProbingAnnotation
   {
   private:
-    AnnotationsSceneLayer&  that_;
-    Annotation*             annotation_;
-    AffineTransform2D       canvasToScene_;
-    Handle*                 handle2_;
-      
-  public:
-    CreateSegmentOrCircleTracker(AnnotationsSceneLayer& that,
-                                 Units units,
-                                 bool isCircle,
-                                 const ScenePoint2D& sceneClick,
-                                 const AffineTransform2D& canvasToScene) :
-      that_(that),
-      annotation_(NULL),
-      canvasToScene_(canvasToScene),
-      handle2_(NULL)
+    Handle&   handle1_;
+    Handle&   handle2_;
+    Segment&  segment1_;
+    Segment&  segment2_;
+    Segment&  segment3_;
+    Segment&  segment4_;
+    Text&     label_;
+
+    void UpdateLabel()
     {
-      if (isCircle)
+      TextSceneLayer content;
+
+      const double x1 = handle1_.GetCenter().GetX();
+      const double y1 = handle1_.GetCenter().GetY();
+      const double x2 = handle2_.GetCenter().GetX();
+      const double y2 = handle2_.GetCenter().GetY();
+        
+      // Put the label to the right of the right-most handle
+      //const double y = std::min(y1, y2);
+      const double y = (y1 + y2) / 2.0;
+      if (x1 < x2)
       {
-        annotation_ = new CircleAnnotation(that, units, sceneClick, sceneClick);
-        handle2_ = &dynamic_cast<CircleAnnotation*>(annotation_)->GetHandle2();
+        content.SetPosition(x2, y);
       }
       else
       {
-        annotation_ = new SegmentAnnotation(that, units, true /* show label */, sceneClick, sceneClick);
-        handle2_ = &dynamic_cast<SegmentAnnotation*>(annotation_)->GetHandle2();
+        content.SetPosition(x1, y);
+      }
+
+      content.SetAnchor(BitmapAnchor_CenterLeft);
+      content.SetBorder(10);
+
+      const double area = std::abs(x1 - x2) * std::abs(y1 - y2);
+        
+      char buf[32];
+
+      switch (GetUnits())
+      {
+        case Units_Millimeters:
+          sprintf(buf, "%0.2f cm%c%c",
+                  area / 100.0,
+                  0xc2, 0xb2 /* two bytes corresponding to two power in UTF-8 */);
+          break;
+
+        case Units_Pixels:
+          // Don't report area (pixel-times-pixel is a strange unit)
+          sprintf(buf, "hello");
+          break;
+          
+        default:
+          throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented);
+      }
+
+      content.SetText(buf);
+
+      label_.SetContent(content);
+    }
+    
+  protected:
+    virtual void UpdateProbeForLayer(const ISceneLayer& layer) ORTHANC_OVERRIDE
+    {
+      // TODO
+    }
+    
+  public:
+    RectangleProbeAnnotation(AnnotationsSceneLayer& that,
+                             Units units,
+                             const ScenePoint2D& p1,
+                             const ScenePoint2D& p2) :
+      ProbingAnnotation(that, units),
+      handle1_(AddTypedPrimitive<Handle>(new Handle(*this, Handle::Shape_Square, p1))),
+      handle2_(AddTypedPrimitive<Handle>(new Handle(*this, Handle::Shape_Square, p2))),
+      segment1_(AddTypedPrimitive<Segment>(new Segment(*this, p1.GetX(), p1.GetY(), p2.GetX(), p1.GetY()))),
+      segment2_(AddTypedPrimitive<Segment>(new Segment(*this, p2.GetX(), p1.GetY(), p2.GetX(), p2.GetY()))),
+      segment3_(AddTypedPrimitive<Segment>(new Segment(*this, p2.GetX(), p2.GetY(), p1.GetX(), p2.GetY()))),
+      segment4_(AddTypedPrimitive<Segment>(new Segment(*this, p1.GetX(), p2.GetY(), p1.GetX(), p1.GetY()))),
+      label_(AddTypedPrimitive<Text>(new Text(that, *this)))
+    {
+      label_.SetColor(COLOR_TEXT);
+      UpdateLabel();
+    }
+
+    virtual unsigned int GetHandlesCount() const ORTHANC_OVERRIDE
+    {
+      return 2;
+    }
+
+    virtual Handle& GetHandle(unsigned int index) const ORTHANC_OVERRIDE
+    {
+      switch (index)
+      {
+        case 0:
+          return handle1_;
+
+        case 1:
+          return handle2_;
+
+        default:
+          throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
+      }
+    }
+
+    virtual void SignalMove(GeometricPrimitive& primitive,
+                            const Scene2D& scene) ORTHANC_OVERRIDE
+    {
+      if (&primitive == &handle1_ ||
+          &primitive == &handle2_)
+      {
+        const double x1 = handle1_.GetCenter().GetX();
+        const double y1 = handle1_.GetCenter().GetY();
+        const double x2 = handle2_.GetCenter().GetX();
+        const double y2 = handle2_.GetCenter().GetY();
+        segment1_.SetPosition(x1, y1, x2, y1);
+        segment2_.SetPosition(x2, y1, x2, y2);
+        segment3_.SetPosition(x2, y2, x1, y2);
+        segment4_.SetPosition(x1, y2, x1, y1);
       }
-        
+      else if (&primitive == &segment1_)
+      {
+        const double x1 = segment1_.GetPosition1().GetX();
+        const double y1 = segment1_.GetPosition1().GetY();
+        const double x2 = segment1_.GetPosition2().GetX();
+        const double y2 = handle2_.GetCenter().GetY();
+        handle1_.SetCenter(x1, y1);
+        handle2_.SetCenter(x2, y2);
+        segment2_.SetPosition(x2, y1, x2, y2);
+        segment3_.SetPosition(x2, y2, x1, y2);
+        segment4_.SetPosition(x1, y2, x1, y1);
+      }
+      else if (&primitive == &segment2_)
+      {
+        const double x1 = handle1_.GetCenter().GetX();
+        const double y1 = segment2_.GetPosition1().GetY();
+        const double x2 = segment2_.GetPosition2().GetX();
+        const double y2 = segment2_.GetPosition2().GetY();
+        handle1_.SetCenter(x1, y1);
+        handle2_.SetCenter(x2, y2);
+        segment1_.SetPosition(x1, y1, x2, y1);
+        segment3_.SetPosition(x2, y2, x1, y2);
+        segment4_.SetPosition(x1, y2, x1, y1);
+      }
+      else if (&primitive == &segment3_)
+      {
+        const double x1 = segment3_.GetPosition2().GetX();
+        const double y1 = handle1_.GetCenter().GetY();
+        const double x2 = segment3_.GetPosition1().GetX();
+        const double y2 = segment3_.GetPosition2().GetY();
+        handle1_.SetCenter(x1, y1);
+        handle2_.SetCenter(x2, y2);
+        segment1_.SetPosition(x1, y1, x2, y1);
+        segment2_.SetPosition(x2, y1, x2, y2);
+        segment4_.SetPosition(x1, y2, x1, y1);
+      }
+      else if (&primitive == &segment4_)
+      {
+        const double x1 = segment4_.GetPosition2().GetX();
+        const double y1 = segment4_.GetPosition2().GetY();
+        const double x2 = handle2_.GetCenter().GetX();
+        const double y2 = segment4_.GetPosition1().GetY();
+        handle1_.SetCenter(x1, y1);
+        handle2_.SetCenter(x2, y2);
+        segment1_.SetPosition(x1, y1, x2, y1);
+        segment2_.SetPosition(x2, y1, x2, y2);
+        segment3_.SetPosition(x2, y2, x1, y2);
+      }
+      else
+      {
+        throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented);
+      }
+      
+      UpdateLabel();
+    }
+
+    virtual void UpdateProbe(const Scene2D& scene) ORTHANC_OVERRIDE
+    {
+    }
+
+    virtual void Serialize(Json::Value& target) ORTHANC_OVERRIDE
+    {
+      target = Json::objectValue;
+      target[KEY_TYPE] = VALUE_RECTANGLE_PROBE;
+      target[KEY_X1] = handle1_.GetCenter().GetX();
+      target[KEY_Y1] = handle1_.GetCenter().GetY();
+      target[KEY_X2] = handle2_.GetCenter().GetX();
+      target[KEY_Y2] = handle2_.GetCenter().GetY();
+    }
+
+    static void Unserialize(AnnotationsSceneLayer& target,
+                            Units units,
+                            const Json::Value& source)
+    {
+      if (source.isMember(KEY_X1) &&
+          source.isMember(KEY_Y1) &&
+          source.isMember(KEY_X2) &&
+          source.isMember(KEY_Y2) &&
+          source[KEY_X1].isNumeric() &&
+          source[KEY_Y1].isNumeric() &&
+          source[KEY_X2].isNumeric() &&
+          source[KEY_Y2].isNumeric())
+      {
+        new RectangleProbeAnnotation(target, units,
+                                     ScenePoint2D(source[KEY_X1].asDouble(), source[KEY_Y1].asDouble()),
+                                     ScenePoint2D(source[KEY_X2].asDouble(), source[KEY_Y2].asDouble()));
+      }
+      else
+      {
+        throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat, "Cannot unserialize a rectangle probe annotation");
+      }
+    }
+  };
+
+  
+  class AnnotationsSceneLayer::CreateTwoHandlesTracker : public IFlexiblePointerTracker
+  {
+  private:
+    AnnotationsSceneLayer&  layer_;
+    Annotation*             annotation_;
+    AffineTransform2D       canvasToScene_;
+      
+  public:
+    CreateTwoHandlesTracker(Annotation& annotation,
+                            const AffineTransform2D& canvasToScene) :
+      layer_(annotation.GetParentLayer()),
+      annotation_(&annotation),
+      canvasToScene_(canvasToScene)
+    {
       assert(annotation_ != NULL &&
-             handle2_ != NULL);
+             annotation_->GetHandlesCount() >= 2);
     }
 
     virtual void PointerMove(const PointerEvent& event,
@@ -1447,11 +1751,10 @@
     {
       if (annotation_ != NULL)
       {
-        assert(handle2_ != NULL);
-        handle2_->SetCenter(event.GetMainPosition().Apply(canvasToScene_));
-        annotation_->SignalMove(*handle2_, scene);
+        annotation_->GetHandle(1).SetCenter(event.GetMainPosition().Apply(canvasToScene_));
+        annotation_->SignalMove(annotation_->GetHandle(1), scene);
 
-        that_.BroadcastMessage(AnnotationChangedMessage(that_));
+        layer_.BroadcastMessage(AnnotationChangedMessage(layer_));
       }
     }
       
@@ -1460,7 +1763,7 @@
     {
       annotation_ = NULL;  // IsAlive() becomes false
 
-      that_.BroadcastMessage(AnnotationAddedMessage(that_));
+      layer_.BroadcastMessage(AnnotationAddedMessage(layer_));
     }
 
     virtual void PointerDown(const PointerEvent& event,
@@ -1477,7 +1780,7 @@
     {
       if (annotation_ != NULL)
       {
-        that_.DeleteAnnotation(annotation_);
+        layer_.DeleteAnnotation(annotation_);
         annotation_ = NULL;
       }
     }
@@ -1510,15 +1813,15 @@
     {
       if (segment_ != NULL)
       {
-        segment_->GetHandle2().SetCenter(event.GetMainPosition().Apply(canvasToScene_));
-        segment_->SignalMove(segment_->GetHandle2(), scene);
+        segment_->GetHandle(1).SetCenter(event.GetMainPosition().Apply(canvasToScene_));
+        segment_->SignalMove(segment_->GetHandle(1), scene);
         that_.BroadcastMessage(AnnotationChangedMessage(that_));
       }
 
       if (angle_ != NULL)
       {
-        angle_->GetEndHandle().SetCenter(event.GetMainPosition().Apply(canvasToScene_));
-        angle_->SignalMove(angle_->GetEndHandle(), scene);
+        angle_->GetHandle(2).SetCenter(event.GetMainPosition().Apply(canvasToScene_));
+        angle_->SignalMove(angle_->GetHandle(2), scene);
         that_.BroadcastMessage(AnnotationChangedMessage(that_));
       }
     }
@@ -1530,9 +1833,9 @@
       {
         // End of first step: The first segment is available, now create the angle
 
-        angle_ = new AngleAnnotation(that_, segment_->GetUnits(), segment_->GetHandle1().GetCenter(),
-                                     segment_->GetHandle2().GetCenter(),
-                                     segment_->GetHandle2().GetCenter());
+        angle_ = new AngleAnnotation(that_, segment_->GetUnits(), segment_->GetHandle(0).GetCenter(),
+                                     segment_->GetHandle(1).GetCenter(),
+                                     segment_->GetHandle(1).GetCenter());
           
         that_.DeleteAnnotation(segment_);
         segment_ = NULL;
@@ -1581,10 +1884,9 @@
     CreatePixelProbeTracker(AnnotationsSceneLayer& that,
                             Units units,
                             const ScenePoint2D& sceneClick,
-                            const Scene2D& scene,
-                            int probedLayer)
+                            const Scene2D& scene)
     {
-      PixelProbeAnnotation* annotation = new PixelProbeAnnotation(that, units, sceneClick, probedLayer);
+      PixelProbeAnnotation* annotation = new PixelProbeAnnotation(that, units, sceneClick);
       annotation->UpdateProbe(scene);
       that.BroadcastMessage(AnnotationAddedMessage(that));
     }
@@ -1889,16 +2191,28 @@
         switch (activeTool_)
         {
           case Tool_Segment:
-            return new CreateSegmentOrCircleTracker(*this, units_, false /* segment */, s, scene.GetCanvasToSceneTransform());
+          {
+            Annotation* annotation = new SegmentAnnotation(*this, units_, true /* show label */, s, s);
+            return new CreateTwoHandlesTracker(*annotation, scene.GetCanvasToSceneTransform());
+          }
 
           case Tool_Circle:
-            return new CreateSegmentOrCircleTracker(*this, units_, true /* circle */, s, scene.GetCanvasToSceneTransform());
+          {
+            Annotation* annotation = new CircleAnnotation(*this, units_, s, s);
+            return new CreateTwoHandlesTracker(*annotation, scene.GetCanvasToSceneTransform());
+          }
 
           case Tool_Angle:
             return new CreateAngleTracker(*this, units_, s, scene.GetCanvasToSceneTransform());
 
           case Tool_PixelProbe:
-            return new CreatePixelProbeTracker(*this, units_, s, scene, probedLayer_);
+            return new CreatePixelProbeTracker(*this, units_, s, scene);
+
+          case Tool_RectangleProbe:
+          {
+            Annotation* annotation = new RectangleProbeAnnotation(*this, units_, s, s);
+            return new CreateTwoHandlesTracker(*annotation, scene.GetCanvasToSceneTransform());
+          }
 
           default:
             return NULL;
@@ -1995,7 +2309,11 @@
       }
       else if (type == VALUE_PIXEL_PROBE)
       {
-        PixelProbeAnnotation::Unserialize(*this, units_, probedLayer_, annotations[i]);
+        PixelProbeAnnotation::Unserialize(*this, units_, annotations[i]);
+      }
+      else if (type == VALUE_RECTANGLE_PROBE)
+      {
+        RectangleProbeAnnotation::Unserialize(*this, units_, annotations[i]);
       }
       else
       {
--- a/OrthancStone/Sources/Scene2D/AnnotationsSceneLayer.h	Mon Oct 31 08:55:14 2022 +0100
+++ b/OrthancStone/Sources/Scene2D/AnnotationsSceneLayer.h	Mon Oct 31 12:32:47 2022 +0100
@@ -62,11 +62,13 @@
     class SegmentAnnotation;
     class AngleAnnotation;
     class CircleAnnotation;
+    class RectangleProbeAnnotation;
     
     class EditPrimitiveTracker;
-    class CreateSegmentOrCircleTracker;
+    class CreateTwoHandlesTracker;
     class CreateAngleTracker;
     class CreatePixelProbeTracker;
+    class CreateRectangleProbeTracker;
     class RemoveTracker;
 
     typedef std::set<GeometricPrimitive*>  GeometricPrimitives;