changeset 346:c2e040ea8fbe am-2

rotation transform
author Sebastien Jodogne <s.jodogne@gmail.com>
date Mon, 22 Oct 2018 19:40:36 +0200
parents 55438b1ca317
children cd65103c9172
files Applications/Samples/SingleFrameEditorApplication.h Framework/Toolbox/ImageGeometry.cpp Framework/Toolbox/OrthancApiClient.h Framework/Toolbox/OrthancSlicesLoader.cpp
diffstat 4 files changed, 106 insertions(+), 48 deletions(-) [+]
line wrap: on
line diff
--- a/Applications/Samples/SingleFrameEditorApplication.h	Mon Oct 22 17:02:34 2018 +0200
+++ b/Applications/Samples/SingleFrameEditorApplication.h	Mon Oct 22 19:40:36 2018 +0200
@@ -67,36 +67,48 @@
       double        pixelSpacingY_;
       double        panX_;
       double        panY_;
+      double        angle_;
 
 
-      void UpdateTransform()
+      static Matrix CreateOffsetMatrix(double dx,
+                                       double dy)
       {
-        transform_ = LinearAlgebra::IdentityMatrix(3);
+        Matrix m = LinearAlgebra::IdentityMatrix(3);
+        m(0, 2) = dx;
+        m(1, 2) = dy;
+        return m;
+      }
+      
 
-        transform_(0, 0) = pixelSpacingX_;
-        transform_(1, 1) = pixelSpacingY_;
-        transform_(0, 2) = panX_;
-        transform_(1, 2) = panY_;
-        
-#if 0
-        double a = 10.0 / 180.0 * boost::math::constants::pi<double>();
+      static Matrix CreateScalingMatrix(double sx,
+                                        double sy)
+      {
+        Matrix m = LinearAlgebra::IdentityMatrix(3);
+        m(0, 0) = sx;
+        m(1, 1) = sy;
+        return m;
+      }
+      
+
+      static Matrix CreateRotationMatrix(double angle)
+      {
         Matrix m;
-        const double v[] = { cos(a), -sin(a), 0,
-                             sin(a), cos(a), 0,
+        const double v[] = { cos(angle), -sin(angle), 0,
+                             sin(angle), cos(angle), 0,
                              0, 0, 1 };
         LinearAlgebra::FillMatrix(m, 3, 3, v);
-        transform_ = LinearAlgebra::Product(m, transform_);
-#endif
+        return m;
       }
+      
 
-
-      void MapImageToScene(double& x,
-                           double& y) const
+      static void ApplyTransform(double& x /* inout */,
+                                 double& y /* inout */,
+                                 const Matrix& transform)
       {
         Vector p;
         LinearAlgebra::AssignVector(p, x, y, 1);
 
-        Vector q = LinearAlgebra::Product(transform_, p);
+        Vector q = LinearAlgebra::Product(transform, p);
 
         if (!LinearAlgebra::IsNear(q[2], 1.0))
         {
@@ -110,11 +122,26 @@
       }
       
       
+      void UpdateTransform()
+      {
+        transform_ = CreateScalingMatrix(pixelSpacingX_, pixelSpacingY_);
+
+        double centerX = static_cast<double>(width_) / 2.0;
+        double centerY = static_cast<double>(height_) / 2.0;
+        ApplyTransform(centerX, centerY, transform_);
+
+        transform_ = LinearAlgebra::Product(
+        CreateOffsetMatrix(panX_ + centerX, panY_ + centerY),
+          CreateRotationMatrix(angle_),
+          CreateOffsetMatrix(-centerX, -centerY), transform_);
+      }
+
+
       void AddToExtent(Extent2D& extent,
                        double x,
                        double y) const
       {
-        MapImageToScene(x, y);
+        ApplyTransform(x, y, transform_);
         extent.AddPoint(x, y);
       }
       
@@ -129,7 +156,8 @@
         pixelSpacingX_(1),
         pixelSpacingY_(1),
         panX_(0),
-        panY_(0)
+        panY_(0),
+        angle_(45.0 / 180.0 * boost::math::constants::pi<double>())
       {
         UpdateTransform();
       }
@@ -176,6 +204,17 @@
         }
       }
 
+      void SetAngle(double angle)
+      {
+        angle_ = angle;
+        UpdateTransform();
+      }
+
+      double GetAngle() const
+      {
+        return angle_;
+      }
+
       bool IsVisible() const
       {
         return visible_;
@@ -200,6 +239,8 @@
         hasSize_ = true;
         width_ = width;
         height_ = height;
+
+        UpdateTransform();
       }
 
 
@@ -333,27 +374,27 @@
         double x, y;
         x = dx;
         y = dy;
-        MapImageToScene(x, y);
+        ApplyTransform(x, y, transform_);
         cairo_move_to(cr, x, y);
 
         x = dx + dwidth;
         y = dy;
-        MapImageToScene(x, y);
+        ApplyTransform(x, y, transform_);
         cairo_line_to(cr, x, y);
 
         x = dx + dwidth;
         y = dy + dheight;
-        MapImageToScene(x, y);
+        ApplyTransform(x, y, transform_);
         cairo_line_to(cr, x, y);
 
         x = dx;
         y = dy + dheight;
-        MapImageToScene(x, y);
+        ApplyTransform(x, y, transform_);
         cairo_line_to(cr, x, y);
 
         x = dx;
         y = dy;
-        MapImageToScene(x, y);
+        ApplyTransform(x, y, transform_);
         cairo_line_to(cr, x, y);
 
         cairo_stroke(cr);
@@ -607,6 +648,20 @@
       hasSelection_ = true;
       selectedBitmap_ = bitmap;
     }
+
+
+    bool GetSelectedBitmap(size_t& bitmap) const
+    {
+      if (hasSelection_)
+      {
+        bitmap = selectedBitmap_;
+        return true;
+      }
+      else
+      {
+        return false;
+      }
+    }
     
     
     virtual ~BitmapStack()
@@ -691,7 +746,7 @@
     
     void OnTagsReceived(const OrthancApiClient::BinaryResponseReadyMessage& message)
     {
-      size_t index = dynamic_cast<Orthanc::SingleValueObject<size_t>*>(message.Payload)->GetValue();
+        size_t index = dynamic_cast<Orthanc::SingleValueObject<size_t>*>(message.Payload.get())->GetValue();
       
       printf("JSON received: [%s] (%ld bytes) for bitmap %ld\n",
              message.Uri.c_str(), message.AnswerSize, index);
@@ -720,7 +775,7 @@
 
     void OnFrameReceived(const OrthancApiClient::BinaryResponseReadyMessage& message)
     {
-      size_t index = dynamic_cast<Orthanc::SingleValueObject<size_t>*>(message.Payload)->GetValue();
+        size_t index = dynamic_cast<Orthanc::SingleValueObject<size_t>*>(message.Payload.get())->GetValue();
       
       printf("Frame received: [%s] (%ld bytes) for bitmap %ld\n",
              message.Uri.c_str(), message.AnswerSize, index);
@@ -945,12 +1000,23 @@
       if (button == MouseButton_Left)
       {
         size_t bitmap;
+
         if (stack_.LookupBitmap(bitmap, x, y))
         {
           printf("CLICK on bitmap %ld\n", bitmap);
-          stack_.Select(bitmap);
-          return new MoveBitmapTracker(stack_, bitmap, x, y,
-                                       (modifiers & KeyboardModifiers_Shift));
+
+          size_t selected;
+          if (stack_.GetSelectedBitmap(selected) &&
+              bitmap == selected)
+          {
+            return new MoveBitmapTracker(stack_, bitmap, x, y,
+                                         (modifiers & KeyboardModifiers_Shift));
+          }
+          else
+          {
+            stack_.Select(bitmap);
+            return NULL;
+          }
         }
         else
         {
--- a/Framework/Toolbox/ImageGeometry.cpp	Mon Oct 22 17:02:34 2018 +0200
+++ b/Framework/Toolbox/ImageGeometry.cpp	Mon Oct 22 19:40:36 2018 +0200
@@ -152,10 +152,6 @@
       {
         *p = value;
       }
-      else
-      {
-        Reader::Traits::SetZero(*p);
-      }
 
       if (HasOffsetX)
       {
@@ -435,10 +431,6 @@
           { 
             reader.GetValue(*p, sourceX, sourceY);
           }
-          else
-          {
-            Reader::Traits::SetZero(*p);
-          }
 
           p++;
         }
--- a/Framework/Toolbox/OrthancApiClient.h	Mon Oct 22 17:02:34 2018 +0200
+++ b/Framework/Toolbox/OrthancApiClient.h	Mon Oct 22 19:40:36 2018 +0200
@@ -39,7 +39,7 @@
     {
       Json::Value   Response;
       std::string   Uri;
-      Orthanc::IDynamicObject*  Payload;
+      std::auto_ptr<Orthanc::IDynamicObject>  Payload;
 
       JsonResponseReadyMessage(const std::string& uri,
                                const Json::Value& response,
@@ -55,7 +55,7 @@
     struct EmptyResponseReadyMessage : public BaseMessage<MessageType_OrthancApi_GenericEmptyResponse_Ready>
     {
       std::string   Uri;
-      Orthanc::IDynamicObject*  Payload;
+      std::auto_ptr<Orthanc::IDynamicObject>  Payload;
 
       EmptyResponseReadyMessage(const std::string& uri,
                                 Orthanc::IDynamicObject*  payload = NULL)
@@ -69,7 +69,7 @@
     struct HttpErrorMessage : public BaseMessage<MessageType_OrthancApi_GenericHttpError_Ready>
     {
       std::string   Uri;
-      Orthanc::IDynamicObject*  Payload;
+      std::auto_ptr<Orthanc::IDynamicObject>  Payload;
 
       HttpErrorMessage(const std::string& uri,
                        Orthanc::IDynamicObject*  payload = NULL)
@@ -85,7 +85,7 @@
       const void* Answer;
       size_t AnswerSize;
       std::string   Uri;
-      Orthanc::IDynamicObject*  Payload;
+      std::auto_ptr<Orthanc::IDynamicObject>  Payload;
 
       BinaryResponseReadyMessage(const std::string& uri,
                                  const void* answer,
--- a/Framework/Toolbox/OrthancSlicesLoader.cpp	Mon Oct 22 17:02:34 2018 +0200
+++ b/Framework/Toolbox/OrthancSlicesLoader.cpp	Mon Oct 22 19:40:36 2018 +0200
@@ -276,7 +276,7 @@
   void OrthancSlicesLoader::ParseInstanceGeometry(const OrthancApiClient::JsonResponseReadyMessage& message)
   {
     Json::Value tags = message.Response;
-    const std::string& instanceId = dynamic_cast<OrthancSlicesLoader::Operation*>(message.Payload)->GetInstanceId();
+    const std::string& instanceId = dynamic_cast<OrthancSlicesLoader::Operation*>(message.Payload.get())->GetInstanceId();
 
     OrthancPlugins::FullOrthancDataset dataset(tags);
     
@@ -313,8 +313,8 @@
   void OrthancSlicesLoader::ParseFrameGeometry(const OrthancApiClient::JsonResponseReadyMessage& message)
   {
     Json::Value tags = message.Response;
-    const std::string& instanceId = dynamic_cast<OrthancSlicesLoader::Operation*>(message.Payload)->GetInstanceId();
-    unsigned int frame = dynamic_cast<OrthancSlicesLoader::Operation*>(message.Payload)->GetFrame();
+    const std::string& instanceId = dynamic_cast<OrthancSlicesLoader::Operation*>(message.Payload.get())->GetInstanceId();
+    unsigned int frame = dynamic_cast<OrthancSlicesLoader::Operation*>(message.Payload.get())->GetFrame();
 
     OrthancPlugins::FullOrthancDataset dataset(tags);
     
@@ -340,7 +340,7 @@
   
   void OrthancSlicesLoader::ParseSliceImagePng(const OrthancApiClient::BinaryResponseReadyMessage& message)
   {
-    const Operation& operation = dynamic_cast<const OrthancSlicesLoader::Operation&>(*message.Payload);
+    const Operation& operation = dynamic_cast<const OrthancSlicesLoader::Operation&>(*message.Payload.get());
     boost::shared_ptr<Orthanc::ImageAccessor>  image;
     
     try
@@ -380,7 +380,7 @@
   
   void OrthancSlicesLoader::ParseSliceImagePam(const OrthancApiClient::BinaryResponseReadyMessage& message)
   {
-    const Operation& operation = dynamic_cast<const OrthancSlicesLoader::Operation&>(*message.Payload);
+    const Operation& operation = dynamic_cast<const OrthancSlicesLoader::Operation&>(*message.Payload.get());
     boost::shared_ptr<Orthanc::ImageAccessor>  image;
 
     try
@@ -421,7 +421,7 @@
 
   void OrthancSlicesLoader::ParseSliceImageJpeg(const OrthancApiClient::JsonResponseReadyMessage& message)
   {
-    const Operation& operation = dynamic_cast<const OrthancSlicesLoader::Operation&>(*message.Payload);
+    const Operation& operation = dynamic_cast<const OrthancSlicesLoader::Operation&>(*message.Payload.get());
 
     Json::Value encoded = message.Response;
     if (encoded.type() != Json::objectValue ||
@@ -594,7 +594,7 @@
   
   void OrthancSlicesLoader::ParseSliceRawImage(const OrthancApiClient::BinaryResponseReadyMessage& message)
   {
-    const Operation& operation = dynamic_cast<const OrthancSlicesLoader::Operation&>(*message.Payload);
+    const Operation& operation = dynamic_cast<const OrthancSlicesLoader::Operation&>(*message.Payload.get());
     Orthanc::GzipCompressor compressor;
     
     std::string raw;