changeset 1978:95449b0e064a

pixel probe is working
author Sebastien Jodogne <s.jodogne@gmail.com>
date Sat, 29 Oct 2022 16:56:16 +0200
parents ba971d9082d3
children b31e494e34c5
files Applications/StoneWebViewer/WebAssembly/StoneWebViewer.cpp OrthancStone/Sources/Scene2D/AnnotationsSceneLayer.cpp OrthancStone/Sources/Scene2D/AnnotationsSceneLayer.h
diffstat 3 files changed, 102 insertions(+), 36 deletions(-) [+]
line wrap: on
line diff
--- a/Applications/StoneWebViewer/WebAssembly/StoneWebViewer.cpp	Sat Oct 29 16:31:09 2022 +0200
+++ b/Applications/StoneWebViewer/WebAssembly/StoneWebViewer.cpp	Sat Oct 29 16:56:16 2022 +0200
@@ -3213,7 +3213,7 @@
               break;
               
             case WebViewerAction_CreateSegment:
-              viewer_.stoneAnnotations_->SetActiveTool(OrthancStone::AnnotationsSceneLayer::Tool_PixelProbe);
+              viewer_.stoneAnnotations_->SetActiveTool(OrthancStone::AnnotationsSceneLayer::Tool_Segment);
               break;
 
             case WebViewerAction_RemoveMeasure:
--- a/OrthancStone/Sources/Scene2D/AnnotationsSceneLayer.cpp	Sat Oct 29 16:31:09 2022 +0200
+++ b/OrthancStone/Sources/Scene2D/AnnotationsSceneLayer.cpp	Sat Oct 29 16:56:16 2022 +0200
@@ -28,6 +28,7 @@
 #include "TextSceneLayer.h"
 #include "TextureBaseSceneLayer.h"  // TODO REMOVE
 
+#include <Images/ImageTraits.h>
 #include <OrthancException.h>
 
 #include <boost/math/constants/constants.hpp>
@@ -955,20 +956,113 @@
   };
 
 
-  class AnnotationsSceneLayer::PixelProbeAnnotation : public Annotation
+  // Use this class to avoid unnecessary probing if neither the scene,
+  // nor the probe, has changed
+  class AnnotationsSceneLayer::ProbingAnnotation : public Annotation
   {
   private:
     int       probedLayer_;
+    bool      probeChanged_;
+    uint64_t  lastLayerRevision_;
+
+  protected:
+    virtual void UpdateProbeForLayer(const ISceneLayer& layer) = 0;
+
+    void TagProbeAsChanged()
+    {
+      probeChanged_ = true;
+    }
+
+  public:
+    ProbingAnnotation(AnnotationsSceneLayer& that,
+                      Units units,
+                      int probedLayer) :
+      Annotation(that, units),
+      probedLayer_(probedLayer),
+      probeChanged_(true),
+      lastLayerRevision_(0)
+    {
+    }
+
+    virtual void UpdateProbe(const Scene2D& scene) ORTHANC_OVERRIDE
+    {
+      if (scene.HasLayer(probedLayer_))
+      {
+        const ISceneLayer& layer = scene.GetLayer(probedLayer_);
+        if (probeChanged_ ||
+            layer.GetRevision() != lastLayerRevision_)
+        {
+          UpdateProbeForLayer(layer);
+          probeChanged_ = false;
+          lastLayerRevision_ = layer.GetRevision();
+        }
+      }
+    }
+  };
+
+    
+  class AnnotationsSceneLayer::PixelProbeAnnotation : public ProbingAnnotation
+  {
+  private:
     Handle&   handle_;
     Text&     label_;
 
+  protected:
+    virtual void UpdateProbeForLayer(const ISceneLayer& layer) ORTHANC_OVERRIDE
+    {
+      if (layer.GetType() == ISceneLayer::Type_FloatTexture ||
+          layer.GetType() == ISceneLayer::Type_ColorTexture)
+      {
+        const TextureBaseSceneLayer& texture = dynamic_cast<const TextureBaseSceneLayer&>(layer);
+        const AffineTransform2D sceneToTexture = AffineTransform2D::Invert(texture.GetTransform());
+
+        double sceneX = handle_.GetCenter().GetX();
+        double sceneY = handle_.GetCenter().GetY();
+        sceneToTexture.Apply(sceneX, sceneY);
+          
+        int x = static_cast<int>(std::floor(sceneX));
+        int y = static_cast<int>(std::floor(sceneY));
+
+        const Orthanc::ImageAccessor& image = texture.GetTexture();
+        
+        if (x >= 0 &&
+            y >= 0 &&
+            x < static_cast<int>(image.GetWidth()) &&
+            y < static_cast<int>(image.GetHeight()))
+        {
+          char buf[64];
+
+          switch (image.GetFormat())
+          {
+            case Orthanc::PixelFormat_Float32:
+              sprintf(buf, "%.01f\n", Orthanc::ImageTraits<Orthanc::PixelFormat_Float32>::GetFloatPixel(
+                        image, static_cast<unsigned int>(x), static_cast<unsigned int>(y)));
+              break;
+
+            case Orthanc::PixelFormat_RGB24:
+            {
+              Orthanc::PixelTraits<Orthanc::PixelFormat_RGB24>::PixelType pixel;
+              Orthanc::ImageTraits<Orthanc::PixelFormat_RGB24>::GetPixel(
+                pixel, image, static_cast<unsigned int>(x), static_cast<unsigned int>(y));
+              sprintf(buf, "(%d,%d,%d)\n", pixel.red_, pixel.green_, pixel.blue_);
+              break;
+            }
+
+            default:
+              break;
+          }
+          
+          label_.SetText(buf);
+        }            
+      }
+    }
+
   public:
     PixelProbeAnnotation(AnnotationsSceneLayer& that,
                          Units units,
                          const ScenePoint2D& p,
                          int probedLayer) :
-      Annotation(that, units),
-      probedLayer_(probedLayer),
+      ProbingAnnotation(that, units, probedLayer),
       handle_(AddTypedPrimitive<Handle>(new Handle(*this, p))),
       label_(AddTypedPrimitive<Text>(new Text(that, *this)))
     {
@@ -991,32 +1085,7 @@
                             const Scene2D& scene) ORTHANC_OVERRIDE
     {
       label_.SetPosition(handle_.GetCenter().GetX(), handle_.GetCenter().GetY());
-    }
-
-    virtual void UpdateProbe(const Scene2D& scene) ORTHANC_OVERRIDE
-    {
-      if (scene.HasLayer(probedLayer_))
-      {
-        const ISceneLayer& layer = scene.GetLayer(probedLayer_);
-        if (layer.GetType() == ISceneLayer::Type_FloatTexture ||
-            layer.GetType() == ISceneLayer::Type_ColorTexture)
-        {
-          const TextureBaseSceneLayer& texture = dynamic_cast<TextureBaseSceneLayer&>(scene.GetLayer(probedLayer_));
-          const AffineTransform2D sceneToTexture = AffineTransform2D::Invert(texture.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", texture.GetTexture().GetWidth(), texture.GetTexture().GetHeight(),
-                  textureX, textureY);
-          label_.SetText(buf);
-        }
-      }
+      TagProbeAsChanged();
     }
 
     virtual void Serialize(Json::Value& target) ORTHANC_OVERRIDE
@@ -1515,19 +1584,16 @@
 
   class AnnotationsSceneLayer::CreatePixelProbeTracker : public IFlexiblePointerTracker
   {
-  private:
-    AnnotationsSceneLayer&  that_;
-
   public:
     CreatePixelProbeTracker(AnnotationsSceneLayer& that,
                             Units units,
                             const ScenePoint2D& sceneClick,
                             const Scene2D& scene,
-                            int probedLayer) :
-      that_(that)
+                            int probedLayer)
     {
       PixelProbeAnnotation* annotation = new PixelProbeAnnotation(that, units, sceneClick, probedLayer);
       annotation->UpdateProbe(scene);
+      that.BroadcastMessage(AnnotationAddedMessage(that));
     }
 
     virtual void PointerMove(const PointerEvent& event,
@@ -1538,7 +1604,6 @@
     virtual void PointerUp(const PointerEvent& event,
                            const Scene2D& scene) ORTHANC_OVERRIDE
     {
-      that_.BroadcastMessage(AnnotationAddedMessage(that_));
     }
 
     virtual void PointerDown(const PointerEvent& event,
--- a/OrthancStone/Sources/Scene2D/AnnotationsSceneLayer.h	Sat Oct 29 16:31:09 2022 +0200
+++ b/OrthancStone/Sources/Scene2D/AnnotationsSceneLayer.h	Sat Oct 29 16:56:16 2022 +0200
@@ -54,6 +54,7 @@
     class Text;
 
     class Annotation;
+    class ProbingAnnotation;
     class PixelProbeAnnotation;
     class SegmentAnnotation;
     class AngleAnnotation;