diff OrthancStone/Sources/Scene2D/AnnotationsSceneLayer.cpp @ 1975:5a434f5889f8

starting pixel probe
author Sebastien Jodogne <s.jodogne@gmail.com>
date Sat, 29 Oct 2022 11:57:00 +0200
parents 9c0adcc8feec
children d71acf30970a
line wrap: on
line diff
--- a/OrthancStone/Sources/Scene2D/AnnotationsSceneLayer.cpp	Fri Oct 28 17:58:59 2022 +0200
+++ b/OrthancStone/Sources/Scene2D/AnnotationsSceneLayer.cpp	Sat Oct 29 11:57:00 2022 +0200
@@ -26,6 +26,7 @@
 #include "MacroSceneLayer.h"
 #include "PolylineSceneLayer.h"
 #include "TextSceneLayer.h"
+#include "TextureBaseSceneLayer.h"  // TODO REMOVE
 
 #include <OrthancException.h>
 
@@ -37,6 +38,8 @@
 
 static const char* const KEY_ANNOTATIONS = "annotations";
 static const char* const KEY_TYPE = "type";
+static const char* const KEY_X = "x";
+static const char* const KEY_Y = "y";
 static const char* const KEY_X1 = "x1";
 static const char* const KEY_Y1 = "y1";
 static const char* const KEY_X2 = "x2";
@@ -50,6 +53,7 @@
 static const char* const VALUE_SEGMENT = "segment";
 static const char* const VALUE_MILLIMETERS = "millimeters";
 static const char* const VALUE_PIXELS = "pixels";
+static const char* const VALUE_PIXEL_PROBE = "pixel-probe";
 
 #if 0
 static OrthancStone::Color COLOR_PRIMITIVES(192, 192, 192);
@@ -157,9 +161,11 @@
     virtual void RenderOtherLayers(MacroSceneLayer& macro,
                                    const Scene2D& scene) = 0;
 
-    virtual void MovePreview(const ScenePoint2D& delta) = 0;
+    virtual void MovePreview(const ScenePoint2D& delta,
+                             const Scene2D& scene) = 0;
 
-    virtual void MoveDone(const ScenePoint2D& delta) = 0;
+    virtual void MoveDone(const ScenePoint2D& delta,
+                          const Scene2D& scene) = 0;
   };
     
 
@@ -216,7 +222,8 @@
       return *primitive;
     }
 
-    virtual void SignalMove(GeometricPrimitive& primitive) = 0;
+    virtual void SignalMove(GeometricPrimitive& primitive,
+                            const Scene2D& scene) = 0;
 
     virtual void Serialize(Json::Value& target) = 0;
   };
@@ -299,19 +306,21 @@
     {
     }
 
-    virtual void MovePreview(const ScenePoint2D& delta) ORTHANC_OVERRIDE
+    virtual void MovePreview(const ScenePoint2D& delta,
+                             const Scene2D& scene) ORTHANC_OVERRIDE
     {
       SetModified(true);
       delta_ = delta;
-      GetParentAnnotation().SignalMove(*this);
+      GetParentAnnotation().SignalMove(*this, scene);
     }
 
-    virtual void MoveDone(const ScenePoint2D& delta) ORTHANC_OVERRIDE
+    virtual void MoveDone(const ScenePoint2D& delta,
+                          const Scene2D& scene) ORTHANC_OVERRIDE
     {
       SetModified(true);
       center_ = center_ + delta;
       delta_ = ScenePoint2D(0, 0);
-      GetParentAnnotation().SignalMove(*this);
+      GetParentAnnotation().SignalMove(*this, scene);
     }
   };
 
@@ -384,20 +393,22 @@
     {
     }
 
-    virtual void MovePreview(const ScenePoint2D& delta) ORTHANC_OVERRIDE
+    virtual void MovePreview(const ScenePoint2D& delta,
+                             const Scene2D& scene) ORTHANC_OVERRIDE
     {
       SetModified(true);
       delta_ = delta;
-      GetParentAnnotation().SignalMove(*this);
+      GetParentAnnotation().SignalMove(*this, scene);
     }
 
-    virtual void MoveDone(const ScenePoint2D& delta) ORTHANC_OVERRIDE
+    virtual void MoveDone(const ScenePoint2D& delta,
+                          const Scene2D& scene) ORTHANC_OVERRIDE
     {
       SetModified(true);
       p1_ = p1_ + delta;
       p2_ = p2_ + delta;
       delta_ = ScenePoint2D(0, 0);
-      GetParentAnnotation().SignalMove(*this);
+      GetParentAnnotation().SignalMove(*this, scene);
     }
   };
 
@@ -491,20 +502,22 @@
     {
     }
 
-    virtual void MovePreview(const ScenePoint2D& delta) ORTHANC_OVERRIDE
+    virtual void MovePreview(const ScenePoint2D& delta,
+                             const Scene2D& scene) ORTHANC_OVERRIDE
     {
       SetModified(true);
       delta_ = delta;
-      GetParentAnnotation().SignalMove(*this);
+      GetParentAnnotation().SignalMove(*this, scene);
     }
 
-    virtual void MoveDone(const ScenePoint2D& delta) ORTHANC_OVERRIDE
+    virtual void MoveDone(const ScenePoint2D& delta,
+                          const Scene2D& scene) ORTHANC_OVERRIDE
     {
       SetModified(true);
       p1_ = p1_ + delta;
       p2_ = p2_ + delta;
       delta_ = ScenePoint2D(0, 0);
-      GetParentAnnotation().SignalMove(*this);
+      GetParentAnnotation().SignalMove(*this, scene);
     }
   };
 
@@ -626,12 +639,14 @@
     {
     }
 
-    virtual void MovePreview(const ScenePoint2D& delta) ORTHANC_OVERRIDE
+    virtual void MovePreview(const ScenePoint2D& delta,
+                             const Scene2D& scene) ORTHANC_OVERRIDE
     {
       throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);  // No hit is possible
     }
 
-    virtual void MoveDone(const ScenePoint2D& delta) ORTHANC_OVERRIDE
+    virtual void MoveDone(const ScenePoint2D& delta,
+                          const Scene2D& scene) ORTHANC_OVERRIDE
     {
       throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);  // No hit is possible
     }
@@ -702,12 +717,14 @@
       }
     }
 
-    virtual void MovePreview(const ScenePoint2D& delta) ORTHANC_OVERRIDE
+    virtual void MovePreview(const ScenePoint2D& delta,
+                             const Scene2D& scene) ORTHANC_OVERRIDE
     {
       throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);  // No hit is possible
     }
 
-    virtual void MoveDone(const ScenePoint2D& delta) ORTHANC_OVERRIDE
+    virtual void MoveDone(const ScenePoint2D& delta,
+                          const Scene2D& scene) ORTHANC_OVERRIDE
     {
       throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);  // No hit is possible
     }
@@ -739,14 +756,14 @@
     virtual void PointerMove(const PointerEvent& event,
                              const Scene2D& scene) ORTHANC_OVERRIDE
     {
-      primitive_.MovePreview(event.GetMainPosition().Apply(canvasToScene_) - sceneClick_);
+      primitive_.MovePreview(event.GetMainPosition().Apply(canvasToScene_) - sceneClick_, scene);
       that_.BroadcastMessage(AnnotationChangedMessage(that_));
     }
       
     virtual void PointerUp(const PointerEvent& event,
                            const Scene2D& scene) ORTHANC_OVERRIDE
     {
-      primitive_.MoveDone(event.GetMainPosition().Apply(canvasToScene_) - sceneClick_);
+      primitive_.MoveDone(event.GetMainPosition().Apply(canvasToScene_) - sceneClick_, scene);
       alive_ = false;
       that_.BroadcastMessage(AnnotationChangedMessage(that_));
     }
@@ -761,9 +778,10 @@
       return alive_;
     }
 
-    virtual void Cancel() ORTHANC_OVERRIDE
+    virtual void Cancel(const Scene2D& scene) ORTHANC_OVERRIDE
     {
-      primitive_.MoveDone(ScenePoint2D(0, 0));
+      //primitive_.MoveDone(ScenePoint2D(0, 0), scene);
+      primitive_.MoveDone(sceneClick_, scene);   // TODO Check this
     }
   };
 
@@ -852,7 +870,8 @@
       return handle2_;
     }
 
-    virtual void SignalMove(GeometricPrimitive& primitive) ORTHANC_OVERRIDE
+    virtual void SignalMove(GeometricPrimitive& primitive,
+                            const Scene2D& scene) ORTHANC_OVERRIDE
     {
       if (&primitive == &handle1_ ||
           &primitive == &handle2_)
@@ -903,6 +922,103 @@
   };
 
     
+  class AnnotationsSceneLayer::PixelProbeAnnotation : public Annotation
+  {
+  private:
+    int       probedLayer_;
+    Handle&   handle_;
+    Text&     label_;
+
+    void UpdateLabel(const Scene2D& scene)
+    {
+      TextSceneLayer content;
+
+      content.SetPosition(handle_.GetCenter().GetX(), handle_.GetCenter().GetY());
+      content.SetAnchor(BitmapAnchor_CenterLeft);
+      content.SetBorder(10);
+
+      if (scene.HasLayer(probedLayer_))
+      {
+        const TextureBaseSceneLayer& layer = dynamic_cast<TextureBaseSceneLayer&>(scene.GetLayer(probedLayer_));
+        const AffineTransform2D sceneToTexture = AffineTransform2D::Invert(layer.GetTransform());
+
+        double x = handle_.GetCenter().GetX();
+        double y = handle_.GetCenter().GetY();
+        sceneToTexture.Apply(x, y);
+        
+        int textureX = static_cast<int>(std::floor(x));
+        int textureY = static_cast<int>(std::floor(y));
+        
+        char buf[64];
+        sprintf(buf, "Hello %d x %d / (%d,%d)\n", layer.GetTexture().GetWidth(), layer.GetTexture().GetHeight(),
+                textureX, textureY);
+        content.SetText(buf);
+      }
+      else
+      {
+        content.SetText("????");
+      }
+
+      label_.SetContent(content);
+    }
+
+  public:
+    PixelProbeAnnotation(AnnotationsSceneLayer& that,
+                         Units units,
+                         const ScenePoint2D& p,
+                         const Scene2D& scene,
+                         int probedLayer) :
+      Annotation(that, units),
+      probedLayer_(probedLayer),
+      handle_(AddTypedPrimitive<Handle>(new Handle(*this, p))),
+      label_(AddTypedPrimitive<Text>(new Text(that, *this)))
+    {
+      label_.SetColor(COLOR_TEXT);
+      UpdateLabel(scene);
+    }
+
+    Handle& GetHandle() const
+    {
+      return handle_;
+    }
+
+    virtual void SignalMove(GeometricPrimitive& primitive,
+                            const Scene2D& scene) ORTHANC_OVERRIDE
+    {
+      UpdateLabel(scene);
+    }
+
+    virtual void Serialize(Json::Value& target) ORTHANC_OVERRIDE
+    {
+      target = Json::objectValue;
+      target[KEY_TYPE] = VALUE_PIXEL_PROBE;
+      target[KEY_X] = handle_.GetCenter().GetX();
+      target[KEY_Y] = handle_.GetCenter().GetY();
+    }
+
+    static void Unserialize(AnnotationsSceneLayer& target,
+                            Units units,
+                            int probedLayer,
+                            const Json::Value& source)
+    {
+      if (source.isMember(KEY_X) &&
+          source.isMember(KEY_Y) &&
+          source[KEY_X].isNumeric() &&
+          source[KEY_Y].isNumeric())
+      {
+        Scene2D dummyScene;  // TODO
+        new PixelProbeAnnotation(target, units,
+                                 ScenePoint2D(source[KEY_X].asDouble(), source[KEY_Y].asDouble()),
+                                 dummyScene, probedLayer);
+      }
+      else
+      {
+        throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat, "Cannot unserialize a pixel probe");
+      }
+    }
+  };
+
+    
   class AnnotationsSceneLayer::AngleAnnotation : public Annotation
   {
   private:
@@ -968,7 +1084,8 @@
       return endHandle_;
     }
 
-    virtual void SignalMove(GeometricPrimitive& primitive) ORTHANC_OVERRIDE
+    virtual void SignalMove(GeometricPrimitive& primitive,
+                            const Scene2D& scene) ORTHANC_OVERRIDE
     {
       if (&primitive == &startHandle_)
       {
@@ -1131,7 +1248,8 @@
       return handle2_;
     }
 
-    virtual void SignalMove(GeometricPrimitive& primitive) ORTHANC_OVERRIDE
+    virtual void SignalMove(GeometricPrimitive& primitive,
+                            const Scene2D& scene) ORTHANC_OVERRIDE
     {
       if (&primitive == &handle1_ ||
           &primitive == &handle2_)
@@ -1231,7 +1349,7 @@
       {
         assert(handle2_ != NULL);
         handle2_->SetCenter(event.GetMainPosition().Apply(canvasToScene_));
-        annotation_->SignalMove(*handle2_);
+        annotation_->SignalMove(*handle2_, scene);
 
         that_.BroadcastMessage(AnnotationChangedMessage(that_));
       }
@@ -1255,7 +1373,7 @@
       return (annotation_ != NULL);
     }
 
-    virtual void Cancel() ORTHANC_OVERRIDE
+    virtual void Cancel(const Scene2D& scene) ORTHANC_OVERRIDE
     {
       if (annotation_ != NULL)
       {
@@ -1293,14 +1411,14 @@
       if (segment_ != NULL)
       {
         segment_->GetHandle2().SetCenter(event.GetMainPosition().Apply(canvasToScene_));
-        segment_->SignalMove(segment_->GetHandle2());
+        segment_->SignalMove(segment_->GetHandle2(), scene);
         that_.BroadcastMessage(AnnotationChangedMessage(that_));
       }
 
       if (angle_ != NULL)
       {
         angle_->GetEndHandle().SetCenter(event.GetMainPosition().Apply(canvasToScene_));
-        angle_->SignalMove(angle_->GetEndHandle());
+        angle_->SignalMove(angle_->GetEndHandle(), scene);
         that_.BroadcastMessage(AnnotationChangedMessage(that_));
       }
     }
@@ -1340,7 +1458,7 @@
               angle_ != NULL);
     }
 
-    virtual void Cancel() ORTHANC_OVERRIDE
+    virtual void Cancel(const Scene2D& scene) ORTHANC_OVERRIDE
     {
       if (segment_ != NULL)
       {
@@ -1357,6 +1475,49 @@
   };
 
 
+  class AnnotationsSceneLayer::CreatePixelProbeTracker : public IFlexiblePointerTracker
+  {
+  private:
+    AnnotationsSceneLayer&  that_;
+
+  public:
+    CreatePixelProbeTracker(AnnotationsSceneLayer& that,
+                            Units units,
+                            const ScenePoint2D& sceneClick,
+                            const Scene2D& scene,
+                            int probedLayer) :
+      that_(that)
+    {
+      new PixelProbeAnnotation(that, units, sceneClick, scene, probedLayer);
+    }
+
+    virtual void PointerMove(const PointerEvent& event,
+                             const Scene2D& scene) ORTHANC_OVERRIDE
+    {
+    }
+      
+    virtual void PointerUp(const PointerEvent& event,
+                           const Scene2D& scene) ORTHANC_OVERRIDE
+    {
+      that_.BroadcastMessage(AnnotationAddedMessage(that_));
+    }
+
+    virtual void PointerDown(const PointerEvent& event,
+                             const Scene2D& scene) ORTHANC_OVERRIDE
+    {
+    }
+
+    virtual bool IsAlive() const ORTHANC_OVERRIDE
+    {
+      return false;
+    }
+
+    virtual void Cancel(const Scene2D& scene) ORTHANC_OVERRIDE
+    {
+    }
+  };
+
+
   // Dummy tracker that is only used for deletion, in order to warn
   // the caller that the mouse action was taken into consideration
   class AnnotationsSceneLayer::RemoveTracker : public IFlexiblePointerTracker
@@ -1386,7 +1547,7 @@
       return false;
     }
 
-    virtual void Cancel() ORTHANC_OVERRIDE
+    virtual void Cancel(const Scene2D& scene) ORTHANC_OVERRIDE
     {
     }
   };
@@ -1433,7 +1594,8 @@
     activeTool_(Tool_Edit),
     macroLayerIndex_(macroLayerIndex),
     polylineSubLayer_(0),  // dummy initialization
-    units_(Units_Pixels)
+    units_(Units_Pixels),
+    probedLayer_(0)
   {
   }
     
@@ -1631,6 +1793,9 @@
           case Tool_Angle:
             return new CreateAngleTracker(*this, units_, s, scene.GetCanvasToSceneTransform());
 
+          case Tool_PixelProbe:
+            return new CreatePixelProbeTracker(*this, units_, s, scene, probedLayer_);
+
           default:
             return NULL;
         }
@@ -1724,6 +1889,10 @@
       {
         SegmentAnnotation::Unserialize(*this, units_, annotations[i]);
       }
+      else if (type == VALUE_PIXEL_PROBE)
+      {
+        PixelProbeAnnotation::Unserialize(*this, units_, probedLayer_, annotations[i]);
+      }
       else
       {
         LOG(ERROR) << "Cannot unserialize unknown type of annotation: " << type;