changeset 1797:013dec434a84

creation of segment or circle measures
author Sebastien Jodogne <s.jodogne@gmail.com>
date Thu, 20 May 2021 10:35:25 +0200
parents 20a0aba0ede5
children 41f3872bd7d2
files Applications/Samples/Sdl/SingleFrameViewer/SdlSimpleViewer.cpp OrthancStone/Sources/Scene2D/Internals/MacroLayerRenderer.cpp OrthancStone/Sources/Scene2D/MacroSceneLayer.cpp OrthancStone/Sources/Scene2D/MacroSceneLayer.h
diffstat 4 files changed, 224 insertions(+), 33 deletions(-) [+]
line wrap: on
line diff
--- a/Applications/Samples/Sdl/SingleFrameViewer/SdlSimpleViewer.cpp	Wed May 19 18:59:45 2021 +0200
+++ b/Applications/Samples/Sdl/SingleFrameViewer/SdlSimpleViewer.cpp	Thu May 20 10:35:25 2021 +0200
@@ -171,16 +171,14 @@
       Measure(AnnotationsOverlay& that) :
         that_(that)
       {
+        that.AddMeasure(this);
       }
       
       virtual ~Measure()
       {
         for (Primitives::iterator it = primitives_.begin(); it != primitives_.end(); ++it)
         {
-          assert(*it != NULL);
-          assert(that_.primitives_.find(*it) != that_.primitives_.end());
-          that_.primitives_.erase(*it);
-          delete *it;
+          that_.DeletePrimitive(*it);
         }
       }
 
@@ -612,16 +610,27 @@
     class Text : public Primitive
     {
     private:
+      AnnotationsOverlay&              that_;
       bool                             first_;
-      size_t                           sublayer_;
+      size_t                           subLayer_;
       std::unique_ptr<TextSceneLayer>  content_;
 
     public:
-      Text(Measure& parentMeasure) :
+      Text(AnnotationsOverlay& that,
+           Measure& parentMeasure) :
         Primitive(parentMeasure, 2),
+        that_(that),
         first_(true)
       {
       }
+
+      virtual ~Text()
+      {
+        if (content_.get() != NULL)
+        {
+          that_.TagSubLayerToRemove(subLayer_);
+        }
+      }
       
       void SetContent(const TextSceneLayer& content)
       {
@@ -651,12 +660,12 @@
           
           if (first_)
           {
-            sublayer_ = macro.AddLayer(layer.release());
+            subLayer_ = macro.AddLayer(layer.release());
             first_ = false;
           }
           else
           {
-            macro.UpdateLayer(sublayer_, layer.release());
+            macro.UpdateLayer(subLayer_, layer.release());
           }
         }
       }
@@ -766,12 +775,17 @@
         handle1_(AddTypedPrimitive<Handle>(new Handle(*this, p1))),
         handle2_(AddTypedPrimitive<Handle>(new Handle(*this, p2))),
         segment_(AddTypedPrimitive<Segment>(new Segment(*this, p1, p2))),
-        label_(AddTypedPrimitive<Text>(new Text(*this)))
+        label_(AddTypedPrimitive<Text>(new Text(that, *this)))
       {
         label_.SetColor(Color(255, 0, 0));
         UpdateLabel();
       }
 
+      Handle& GetHandle2() const
+      {
+        return handle2_;
+      }
+
       virtual void SignalMove(Primitive& primitive) ORTHANC_OVERRIDE
       {
         if (&primitive == &handle1_ ||
@@ -843,7 +857,7 @@
         segment1_(AddTypedPrimitive<Segment>(new Segment(*this, start, middle))),
         segment2_(AddTypedPrimitive<Segment>(new Segment(*this, middle, end))),
         arc_(AddTypedPrimitive<Arc>(new Arc(*this, start, middle, end))),
-        label_(AddTypedPrimitive<Text>(new Text(*this)))
+        label_(AddTypedPrimitive<Text>(new Text(that, *this)))
       {
         label_.SetColor(Color(255, 0, 0));
         UpdateLabel();
@@ -945,12 +959,17 @@
         handle2_(AddTypedPrimitive<Handle>(new Handle(*this, p2))),
         segment_(AddTypedPrimitive<Segment>(new Segment(*this, p1, p2))),
         circle_(AddTypedPrimitive<Circle>(new Circle(*this, p1, p2))),
-        label_(AddTypedPrimitive<Text>(new Text(*this)))
+        label_(AddTypedPrimitive<Text>(new Text(that, *this)))
       {
         label_.SetColor(Color(255, 0, 0));
         UpdateLabel();
       }
 
+      Handle& GetHandle2() const
+      {
+        return handle2_;
+      }
+
       virtual void SignalMove(Primitive& primitive) ORTHANC_OVERRIDE
       {
         if (&primitive == &handle1_ ||
@@ -971,18 +990,121 @@
     };
 
     
+    class CreateSegmentOrCircleTracker : public IFlexiblePointerTracker
+    {
+    private:
+      AnnotationsOverlay&  that_;
+      Measure*             measure_;
+      AffineTransform2D    canvasToScene_;
+      Handle*              handle2_;
+      
+    public:
+      CreateSegmentOrCircleTracker(AnnotationsOverlay& that,
+                                   bool isCircle,
+                                   const ScenePoint2D& sceneClick,
+                                   const AffineTransform2D& canvasToScene) :
+        that_(that),
+        measure_(NULL),
+        canvasToScene_(canvasToScene),
+        handle2_(NULL)
+      {
+        if (isCircle)
+        {
+          measure_ = new CircleMeasure(that, sceneClick, sceneClick);
+          handle2_ = &dynamic_cast<CircleMeasure*>(measure_)->GetHandle2();
+        }
+        else
+        {
+          measure_ = new SegmentMeasure(that, sceneClick, sceneClick);
+          handle2_ = &dynamic_cast<SegmentMeasure*>(measure_)->GetHandle2();
+        }
+        
+        assert(measure_ != NULL &&
+               handle2_ != NULL);
+      }
+
+      virtual void PointerMove(const PointerEvent& event) ORTHANC_OVERRIDE
+      {
+        if (measure_ != NULL)
+        {
+          assert(handle2_ != NULL);
+          handle2_->SetCenter(event.GetMainPosition().Apply(canvasToScene_));
+          measure_->SignalMove(*handle2_);
+        }
+      }
+      
+      virtual void PointerUp(const PointerEvent& event) ORTHANC_OVERRIDE
+      {
+        measure_ = NULL;  // IsAlive() becomes false
+      }
+
+      virtual void PointerDown(const PointerEvent& event) ORTHANC_OVERRIDE
+      {
+      }
+
+      virtual bool IsAlive() const ORTHANC_OVERRIDE
+      {
+        return (measure_ != NULL);
+      }
+
+      virtual void Cancel() ORTHANC_OVERRIDE
+      {
+        if (measure_ != NULL)
+        {
+          that_.DeleteMeasure(measure_);
+          measure_ = NULL;
+        }
+      }
+    };
+
+
     typedef std::set<Primitive*>  Primitives;
     typedef std::set<Measure*>    Measures;
+    typedef std::set<size_t>      SubLayers;
 
     size_t      macroLayerIndex_;
-    size_t      polylineSublayer_;
+    size_t      polylineSubLayer_;
     Primitives  primitives_;
     Measures    measures_;
+    SubLayers   subLayersToRemove_;
+
+    void AddMeasure(Measure* measure)
+    {
+      assert(measure != NULL);
+      assert(measures_.find(measure) == measures_.end());
+      measures_.insert(measure);
+    }
+
+    void DeleteMeasure(Measure* measure)
+    {
+      if (measure != NULL)
+      {
+        assert(measures_.find(measure) != measures_.end());
+        measures_.erase(measure);
+        delete measure;
+      }
+    }
+
+    void DeletePrimitive(Primitive* primitive)
+    {
+      if (primitive != NULL)
+      {
+        assert(primitives_.find(primitive) != primitives_.end());
+        primitives_.erase(primitive);
+        delete primitive;
+      }
+    }
+
+    void TagSubLayerToRemove(size_t subLayerIndex)
+    {
+      assert(subLayersToRemove_.find(subLayerIndex) == subLayersToRemove_.end());
+      subLayersToRemove_.insert(subLayerIndex);
+    }
     
   public:
     AnnotationsOverlay(size_t macroLayerIndex) :
       macroLayerIndex_(macroLayerIndex),
-      polylineSublayer_(0)  // dummy initialization
+      polylineSubLayer_(0)  // dummy initialization
     {
       measures_.insert(new SegmentMeasure(*this, ScenePoint2D(0, 0), ScenePoint2D(100, 100)));
       measures_.insert(new AngleMeasure(*this, ScenePoint2D(100, 50), ScenePoint2D(150, 40), ScenePoint2D(200, 50)));
@@ -1011,9 +1133,17 @@
       else
       {
         macro = &dynamic_cast<MacroSceneLayer&>(scene.SetLayer(macroLayerIndex_, new MacroSceneLayer));
-        polylineSublayer_ = macro->AddLayer(new PolylineSceneLayer);
+        polylineSubLayer_ = macro->AddLayer(new PolylineSceneLayer);
       }
 
+      for (SubLayers::const_iterator it = subLayersToRemove_.begin(); it != subLayersToRemove_.end(); ++it)
+      {
+        assert(macro->HasLayer(*it));
+        macro->DeleteLayer(*it);
+      }
+
+      subLayersToRemove_.clear();
+
       std::unique_ptr<PolylineSceneLayer> polyline(new PolylineSceneLayer);
 
       for (Primitives::iterator it = primitives_.begin(); it != primitives_.end(); ++it)
@@ -1030,7 +1160,7 @@
         }
       }
 
-      macro->UpdateLayer(polylineSublayer_, polyline.release());
+      macro->UpdateLayer(polylineSubLayer_, polyline.release());
     }
 
     bool ClearHover()
@@ -1095,6 +1225,11 @@
         }
       }
 
+      if (tracker.get() == NULL)
+      {
+        tracker.reset(new CreateSegmentOrCircleTracker(*this, true /* circle */, s, scene.GetCanvasToSceneTransform()));
+      }
+
       return tracker.release();
     }
   };
--- a/OrthancStone/Sources/Scene2D/Internals/MacroLayerRenderer.cpp	Wed May 19 18:59:45 2021 +0200
+++ b/OrthancStone/Sources/Scene2D/Internals/MacroLayerRenderer.cpp	Thu May 20 10:35:25 2021 +0200
@@ -61,7 +61,10 @@
 
       for (size_t i = 0; i < macro.GetSize(); i++)
       {
-        renderers_.push_back(factory_.Create(macro.GetLayer(i)));
+        if (macro.HasLayer(i))
+        {
+          renderers_.push_back(factory_.Create(macro.GetLayer(i)));
+        }
       }
     }
   }
--- a/OrthancStone/Sources/Scene2D/MacroSceneLayer.cpp	Wed May 19 18:59:45 2021 +0200
+++ b/OrthancStone/Sources/Scene2D/MacroSceneLayer.cpp	Thu May 20 10:35:25 2021 +0200
@@ -24,16 +24,16 @@
 
 #include <OrthancException.h>
 
-#include <cassert>
-
 namespace OrthancStone
 {
   void MacroSceneLayer::Clear()
   {
     for (size_t i = 0; i < layers_.size(); i++)
     {
-      assert(layers_[i] != NULL);
-      delete layers_[i];
+      if (layers_[i] != NULL)
+      {
+        delete layers_[i];
+      }
     }
 
     layers_.clear();
@@ -49,6 +49,8 @@
     }
     else
     {
+      // TODO - Use recycling list from DeleteLayer()
+      
       size_t index = layers_.size();
       layers_.push_back(layer);
       BumpRevision();
@@ -70,8 +72,10 @@
     }
     else
     {
-      assert(layers_[index] != NULL);
-      delete layers_[index];
+      if (layers_[index] != NULL)
+      {
+        delete layers_[index];
+      }
 
       layers_[index] = layer;
       BumpRevision();
@@ -79,16 +83,52 @@
   }    
 
 
-  const ISceneLayer& MacroSceneLayer::GetLayer(size_t i) const
+  bool MacroSceneLayer::HasLayer(size_t index) const
   {
-    if (i >= layers_.size())
+    if (index >= layers_.size())
     {
       throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
     }
     else
     {
-      assert(layers_[i] != NULL);
-      return *layers_[i];
+      return (layers_[index] != NULL);
+    }
+  }
+  
+
+  void MacroSceneLayer::DeleteLayer(size_t index)
+  {
+    if (index >= layers_.size())
+    {
+      throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
+    }
+    else if (layers_[index] == NULL)
+    {
+      throw Orthanc::OrthancException(Orthanc::ErrorCode_InexistentItem);
+    }
+    else
+    {
+      // TODO - Add to a recycling list
+      
+      delete layers_[index];
+      layers_[index] = NULL;
+    }
+  }
+
+
+  const ISceneLayer& MacroSceneLayer::GetLayer(size_t index) const
+  {
+    if (index >= layers_.size())
+    {
+      throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
+    }
+    else if (layers_[index] == NULL)
+    {
+      throw Orthanc::OrthancException(Orthanc::ErrorCode_InexistentItem);
+    }
+    else
+    {
+      return *layers_[index];
     }
   }
 
@@ -99,10 +139,18 @@
 
     for (size_t i = 0; i < layers_.size(); i++)
     {
-      assert(layers_[i] != NULL);
-      copy->layers_.push_back(layers_[i]->Clone());
+      if (layers_[i] == NULL)
+      {
+        copy->layers_.push_back(NULL);
+      }
+      else
+      {
+        copy->layers_.push_back(layers_[i]->Clone());
+      }
     }
 
+    // TODO - Copy recycling list
+
     return copy.release();
   }
   
@@ -113,11 +161,12 @@
 
     for (size_t i = 0; i < layers_.size(); i++)
     {
-      assert(layers_[i] != NULL);
-
-      Extent2D subextent;
-      layers_[i]->GetBoundingBox(subextent);
-      target.Union(subextent);
+      if (layers_[i] != NULL)
+      {
+        Extent2D subextent;
+        layers_[i]->GetBoundingBox(subextent);
+        target.Union(subextent);
+      }
     }
   }
 }
--- a/OrthancStone/Sources/Scene2D/MacroSceneLayer.h	Wed May 19 18:59:45 2021 +0200
+++ b/OrthancStone/Sources/Scene2D/MacroSceneLayer.h	Thu May 20 10:35:25 2021 +0200
@@ -72,6 +72,10 @@
     void UpdateLayer(size_t index,
                      ISceneLayer* layer);  // takes ownership
 
+    bool HasLayer(size_t index) const;
+
+    void DeleteLayer(size_t index);
+
     const ISceneLayer& GetLayer(size_t i) const;
 
     virtual ISceneLayer* Clone() const ORTHANC_OVERRIDE;