changeset 1789:462d7a0e064e

added line measures to sdl single frame viewer sample
author Sebastien Jodogne <s.jodogne@gmail.com>
date Mon, 17 May 2021 11:55:21 +0200
parents 4fd065ad1fc0
children b325761e0bd3
files Applications/Samples/Sdl/SingleFrameViewer/SdlSimpleViewer.cpp Applications/Samples/Sdl/SingleFrameViewer/SdlSimpleViewerApplication.h OrthancStone/Sources/Scene2DViewport/LineMeasureTool.cpp OrthancStone/Sources/Scene2DViewport/MeasureTool.cpp OrthancStone/Sources/Scene2DViewport/MeasureTool.h OrthancStone/Sources/Scene2DViewport/UndoStack.h OrthancStone/Sources/Scene2DViewport/ViewportController.h
diffstat 7 files changed, 149 insertions(+), 61 deletions(-) [+]
line wrap: on
line diff
--- a/Applications/Samples/Sdl/SingleFrameViewer/SdlSimpleViewer.cpp	Sat May 15 12:17:17 2021 +0200
+++ b/Applications/Samples/Sdl/SingleFrameViewer/SdlSimpleViewer.cpp	Mon May 17 11:55:21 2021 +0200
@@ -24,12 +24,15 @@
 #include "../../Common/SampleHelpers.h"
 
 #include "../../../../OrthancStone/Sources/Loaders/GenericLoadersContext.h"
+#include "../../../../OrthancStone/Sources/Scene2DViewport/LineMeasureTool.h"
+#include "../../../../OrthancStone/Sources/Scene2DViewport/UndoStack.h"
 #include "../../../../OrthancStone/Sources/StoneEnumerations.h"
 #include "../../../../OrthancStone/Sources/StoneException.h"
 #include "../../../../OrthancStone/Sources/StoneInitialization.h"
 #include "../../../../OrthancStone/Sources/Viewport/DefaultViewportInteractor.h"
 #include "../../../Platforms/Sdl/SdlViewport.h"
 
+#include <EmbeddedResources.h>
 #include <Compatibility.h>  // For std::unique_ptr<>
 #include <OrthancException.h>
 
@@ -65,6 +68,17 @@
 
   std::cout << desc << std::endl;
 
+  std::cout << std::endl << "Keyboard shorcuts:" << std::endl
+            << "  f\tToggle fullscreen display" << std::endl
+            << "  l\tEnable/disable the line measure tool" << std::endl
+            << "  q\tExit" << std::endl
+            << "  s\tFit the viewpoint to the image" << std::endl
+            << std::endl << "Mouse buttons:" << std::endl
+            << "  left  \tChange windowing, or edit measure" << std::endl
+            << "  center\tMove the viewpoint, or move measure" << std::endl
+            << "  right \tZoom, or move measure" << std::endl
+            << std::endl;
+
   po::variables_map vm;
   try
   {
@@ -127,6 +141,8 @@
         OrthancStone::SdlCairoViewport::Create("Stone of Orthanc", 800, 600);
 #endif
 
+      boost::shared_ptr<OrthancStone::UndoStack> undoStack(new OrthancStone::UndoStack);
+
       OrthancStone::GenericLoadersContext context(1, 4, 1);
 
       Orthanc::WebServiceParameters orthancWebService;
@@ -136,6 +152,19 @@
       context.StartOracle();
 
       {
+        {
+          std::string font;
+          Orthanc::EmbeddedResources::GetFileResource(font, Orthanc::EmbeddedResources::UBUNTU_FONT);
+          
+          std::unique_ptr<OrthancStone::IViewport::ILock> lock(viewport->Lock());
+          lock->GetCompositor().SetFont(0, font, 16, Orthanc::Encoding_Latin1);
+          lock->GetController().SetUndoStack(undoStack);
+        }
+
+        boost::shared_ptr<OrthancStone::LineMeasureTool> lineMeasureTool(OrthancStone::LineMeasureTool::Create(viewport));
+        bool lineMeasureFirst = true;
+        bool lineMeasureEnabled = false;
+        lineMeasureTool->Disable();
 
         boost::shared_ptr<SdlSimpleViewerApplication> application(
           SdlSimpleViewerApplication::Create(context, viewport));
@@ -185,20 +214,46 @@
               {
                 switch (event.key.keysym.sym)
                 {
-                case SDLK_f:
-                  viewport->ToggleMaximize();
-                  break;
+                  case SDLK_f:
+                    viewport->ToggleMaximize();
+                    break;
+
+                  case SDLK_s:
+                    application->FitContent();
+                    break;
+
+                  case SDLK_q:
+                    stop = true;
+                    break;
 
-                case SDLK_s:
-                  application->FitContent();
-                  break;
+                  case SDLK_l:
+                    if (lineMeasureEnabled)
+                    {
+                      lineMeasureTool->Disable();
+                      lineMeasureEnabled = false;
+                    }
+                    else
+                    {
+                      if (lineMeasureFirst)
+                      {
+                        std::unique_ptr<OrthancStone::IViewport::ILock> lock(viewport->Lock());
+                        OrthancStone::Extent2D extent;
+                        lock->GetController().GetScene().GetBoundingBox(extent);
+                        if (!extent.IsEmpty())
+                        {
+                          OrthancStone::ScenePoint2D p(extent.GetCenterX(), extent.GetCenterY());
+                          lineMeasureTool->Set(p, p);
+                        }
+                        lineMeasureFirst = false;
+                      }
+                      
+                      lineMeasureTool->Enable();
+                      lineMeasureEnabled = true;
+                    }
+                    break;
 
-                case SDLK_q:
-                  stop = true;
-                  break;
-
-                default:
-                  break;
+                  default:
+                    break;
                 }
               }
               else if (event.type == SDL_MOUSEBUTTONDOWN ||
@@ -214,27 +269,42 @@
 
                   switch (event.type)
                   {
-                  case SDL_MOUSEBUTTONDOWN:
-                    lock->GetController().HandleMousePress(interactor, p,
-                                                           lock->GetCompositor().GetCanvasWidth(),
-                                                           lock->GetCompositor().GetCanvasHeight());
-                    lock->Invalidate();
-                    break;
-
-                  case SDL_MOUSEMOTION:
-                    if (lock->GetController().HandleMouseMove(p))
+                    case SDL_MOUSEBUTTONDOWN:
                     {
+                      boost::shared_ptr<OrthancStone::IFlexiblePointerTracker> t;
+                      if (lineMeasureEnabled)
+                      {
+                        t = lineMeasureTool->CreateEditionTracker(p);
+                      }
+                      
+                      if (t.get() != NULL)
+                      {
+                        lock->GetController().AcquireActiveTracker(t);
+                      }
+                      else
+                      {
+                        lock->GetController().HandleMousePress(interactor, p,
+                                                               lock->GetCompositor().GetCanvasWidth(),
+                                                               lock->GetCompositor().GetCanvasHeight());
+                      }
                       lock->Invalidate();
+                      break;
                     }
-                    break;
 
-                  case SDL_MOUSEBUTTONUP:
-                    lock->GetController().HandleMouseRelease(p);
-                    lock->Invalidate();
-                    break;
+                    case SDL_MOUSEMOTION:
+                      if (lock->GetController().HandleMouseMove(p))
+                      {
+                        lock->Invalidate();
+                      }
+                      break;
 
-                  default:
-                    throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
+                    case SDL_MOUSEBUTTONUP:
+                      lock->GetController().HandleMouseRelease(p);
+                      lock->Invalidate();
+                      break;
+
+                    default:
+                      throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
                   }
                 }
               }
--- a/Applications/Samples/Sdl/SingleFrameViewer/SdlSimpleViewerApplication.h	Sat May 15 12:17:17 2021 +0200
+++ b/Applications/Samples/Sdl/SingleFrameViewer/SdlSimpleViewerApplication.h	Mon May 17 11:55:21 2021 +0200
@@ -123,6 +123,8 @@
     std::unique_ptr<TextureBaseSceneLayer> layer(
       message.GetInstanceParameters().CreateTexture(message.GetImage()));
     layer->SetLinearInterpolation(true);
+    layer->SetPixelSpacing(message.GetInstanceParameters().GetPixelSpacingX(),
+                           message.GetInstanceParameters().GetPixelSpacingY());
 
     {
       std::unique_ptr<IViewport::ILock> lock(viewport_->Lock());
--- a/OrthancStone/Sources/Scene2DViewport/LineMeasureTool.cpp	Sat May 15 12:17:17 2021 +0200
+++ b/OrthancStone/Sources/Scene2DViewport/LineMeasureTool.cpp	Mon May 17 11:55:21 2021 +0200
@@ -118,30 +118,33 @@
   LineMeasureTool::LineHighlightArea LineMeasureTool::LineHitTest(ScenePoint2D p)
   {
     std::unique_ptr<IViewport::ILock> lock(GetViewportLock());
-    ViewportController& controller = lock->GetController();
-    const Scene2D& scene = controller.GetScene();
+    if (lock.get() != NULL)
+    {
+      ViewportController& controller = lock->GetController();
+      const Scene2D& scene = controller.GetScene();
 
-    const double pixelToScene = scene.GetCanvasToSceneTransform().ComputeZoom();
-    const double SQUARED_HIT_TEST_MAX_DISTANCE_SCENE_COORD = 
-      pixelToScene * HIT_TEST_MAX_DISTANCE_CANVAS_COORD * 
-      pixelToScene * HIT_TEST_MAX_DISTANCE_CANVAS_COORD;
+      const double pixelToScene = scene.GetCanvasToSceneTransform().ComputeZoom();
+      const double SQUARED_HIT_TEST_MAX_DISTANCE_SCENE_COORD = 
+        pixelToScene * HIT_TEST_MAX_DISTANCE_CANVAS_COORD * 
+        pixelToScene * HIT_TEST_MAX_DISTANCE_CANVAS_COORD;
 
-    const double sqDistanceFromStart = 
-      ScenePoint2D::SquaredDistancePtPt(p, start_);
+      const double sqDistanceFromStart = 
+        ScenePoint2D::SquaredDistancePtPt(p, start_);
     
-    if (sqDistanceFromStart <= SQUARED_HIT_TEST_MAX_DISTANCE_SCENE_COORD)
-      return LineHighlightArea_Start;
+      if (sqDistanceFromStart <= SQUARED_HIT_TEST_MAX_DISTANCE_SCENE_COORD)
+        return LineHighlightArea_Start;
     
-    const double sqDistanceFromEnd = ScenePoint2D::SquaredDistancePtPt(p, end_);
+      const double sqDistanceFromEnd = ScenePoint2D::SquaredDistancePtPt(p, end_);
 
-    if (sqDistanceFromEnd <= SQUARED_HIT_TEST_MAX_DISTANCE_SCENE_COORD)
-      return LineHighlightArea_End;
+      if (sqDistanceFromEnd <= SQUARED_HIT_TEST_MAX_DISTANCE_SCENE_COORD)
+        return LineHighlightArea_End;
 
-    const double sqDistanceFromPtSegment = 
-      ScenePoint2D::SquaredDistancePtSegment(start_, end_, p);
+      const double sqDistanceFromPtSegment = 
+        ScenePoint2D::SquaredDistancePtSegment(start_, end_, p);
     
-    if (sqDistanceFromPtSegment <= SQUARED_HIT_TEST_MAX_DISTANCE_SCENE_COORD)
-      return LineHighlightArea_Segment;
+      if (sqDistanceFromPtSegment <= SQUARED_HIT_TEST_MAX_DISTANCE_SCENE_COORD)
+        return LineHighlightArea_Segment;
+    }
 
     return LineHighlightArea_None;
   }
@@ -154,18 +157,25 @@
   boost::shared_ptr<IFlexiblePointerTracker> LineMeasureTool::CreateEditionTracker(const PointerEvent& e)
   {
     std::unique_ptr<IViewport::ILock> lock(GetViewportLock());
-    ViewportController& controller = lock->GetController();
-    const Scene2D& scene = controller.GetScene();
+    if (lock.get() != NULL)
+    {
+      ViewportController& controller = lock->GetController();
+      const Scene2D& scene = controller.GetScene();
 
-    ScenePoint2D scenePos = e.GetMainPosition().Apply(
-      scene.GetCanvasToSceneTransform());
+      ScenePoint2D scenePos = e.GetMainPosition().Apply(
+        scene.GetCanvasToSceneTransform());
 
-    if (!HitTest(scenePos))
-      return boost::shared_ptr<IFlexiblePointerTracker>();
+      if (!HitTest(scenePos))
+        return boost::shared_ptr<IFlexiblePointerTracker>();
 
-    boost::shared_ptr<EditLineMeasureTracker> editLineMeasureTracker(
-      new EditLineMeasureTracker(shared_from_this(), viewport_, e));
-    return editLineMeasureTracker;
+      boost::shared_ptr<EditLineMeasureTracker> editLineMeasureTracker(
+        new EditLineMeasureTracker(shared_from_this(), viewport_, e));
+      return editLineMeasureTracker;
+    }
+    else
+    {
+      return NULL;
+    }
   }
 
   boost::shared_ptr<MeasureToolMemento> LineMeasureTool::GetMemento() const
--- a/OrthancStone/Sources/Scene2DViewport/MeasureTool.cpp	Sat May 15 12:17:17 2021 +0200
+++ b/OrthancStone/Sources/Scene2DViewport/MeasureTool.cpp	Mon May 17 11:55:21 2021 +0200
@@ -76,11 +76,13 @@
   void MeasureTool::PostConstructor()
   {
     std::unique_ptr<IViewport::ILock> lock(GetViewportLock());
-    ViewportController& controller = lock->GetController();
 
-    Register<ViewportController::SceneTransformChanged>(
-      controller, 
-      &MeasureTool::OnSceneTransformChanged);
+    if (lock.get() != NULL)
+    {
+      Register<ViewportController::SceneTransformChanged>(
+        lock->GetController(), 
+        &MeasureTool::OnSceneTransformChanged);
+    }
   }
 
   bool MeasureTool::IsSceneAlive() const
--- a/OrthancStone/Sources/Scene2DViewport/MeasureTool.h	Sat May 15 12:17:17 2021 +0200
+++ b/OrthancStone/Sources/Scene2DViewport/MeasureTool.h	Mon May 17 11:55:21 2021 +0200
@@ -156,7 +156,7 @@
     virtual std::string GetDescription() = 0;
   };
 
-  class MeasureToolMemento
+  class MeasureToolMemento : public boost::noncopyable
   {
   public:
     virtual ~MeasureToolMemento()
--- a/OrthancStone/Sources/Scene2DViewport/UndoStack.h	Sat May 15 12:17:17 2021 +0200
+++ b/OrthancStone/Sources/Scene2DViewport/UndoStack.h	Mon May 17 11:55:21 2021 +0200
@@ -21,6 +21,7 @@
 
 #pragma once
 
+#include <boost/noncopyable.hpp>
 #include <boost/shared_ptr.hpp>
 
 #include <vector>
@@ -29,7 +30,7 @@
 {
   class MeasureCommand;
 
-  class UndoStack
+  class UndoStack : public boost::noncopyable
   {
   public:
     UndoStack();
--- a/OrthancStone/Sources/Scene2DViewport/ViewportController.h	Sat May 15 12:17:17 2021 +0200
+++ b/OrthancStone/Sources/Scene2DViewport/ViewportController.h	Mon May 17 11:55:21 2021 +0200
@@ -139,7 +139,10 @@
     With this method, the object takes ownership of the supplied tracker and
     updates it according to user interaction
     */
-    void AcquireActiveTracker(IFlexiblePointerTracker* tracker);
+    void AcquireActiveTracker(const boost::shared_ptr<IFlexiblePointerTracker>& tracker)
+    {
+      activeTracker_ = tracker;
+    }
 
     /** Forwarded to the underlying scene */
     AffineTransform2D GetCanvasToSceneTransform() const;