title: Problems when scaling and translating image on canvas
body: <p>At work we built a complex application using C#/WPF and the MVVM pattern. In the application we have a canvas. On that canvas we display an image at the center of the canvas. We want to be able to scale and translate the image. We can specify a scale factor to scale all elements on the canvas. To apply transformations to the image we bound a TransformGroup to the RenderTransform property of the image in XAML. The TransformGroup is built in the view model by first adding the ScaleTransform followed by the TranslateTransform. </p>
  
  <p>The transformations are specified that way:</p>
  
  <pre class="lang-cs prettyprint-override"><code>// View model
  // Global fileds
  private ScaleTransform scaleTransform = new ScaleTransform(1, 1);
  private TranslateTransform translateTransform = new TranslateTransform(0, 0);
  private Vector totalShift = new Vector(0, 0);
  
  ...
  
  public void ApplyTransformations() {
      scaleTransform.ScaleX = scaleFactor;
      scaleTransform.ScaleY = scaleFactor;
  
      translateTransform.X = canvasCenter.X - imageWidth / 2;
      translateTransform.Y = canvasCenter.Y - imageHeight / 2;
  }
  </code></pre>
  
  <p>Now we are able to scale the image properly when changing the scale factor.</p>
  
  <p>To enable translation of the image we put the image into a Thumb. The thumb provides a DragDelta event that gives us the shift in x and y direction. This shift is added to totalShift each time we drag the thumb. The following method is part of the view model and is called by the DragDelta event handler in the code behind of the view.</p>
  
  <pre class="lang-cs prettyprint-override"><code>public void addShift(double horizontal, double vertical) {
      totalShift.X += horizontal;
      totalShift.Y += vertical;
  }
  </code></pre>
  
  <p>ApplyTransformations() is modified like this:</p>
  
  <pre class="lang-cs prettyprint-override"><code>private double prevScaleFactor = 0;
  
  public void ApplyTransformations() {
      double oldCenterX = scaleTransform.CenterX;
      double oldCenterY = scaleTransform.CenterY;
  
      scaleTransform.CenterX = -totalShift.X;
      scaleTransform.CenterY = -totalShift.Y;
  
      translateTransform.X = (canvasCenter.X - imageWidth / 2) + (scaleTransform.CenterX - oldCenterX) * prevScaleFactor;
      translateTransform.Y = (canvasCenter.Y - imageHeight / 2) + (scaleTransform.CenterY - oldCenterY) * prevScaleFactor;
  
      scaleTransform.ScaleX = scaleFactor;
      scaleTransform.ScaleY = scaleFactor;
  
      prevScaleFactor = scaleFactor;
  }
  </code></pre>
  
  <p>The problem:
  Let's say scaleFactor is 1.5 and we dragged the image 100 px in x direction. When we execute ApplyTransformation() the image is not shifted 100 px in x direction but only 100 / 1.5 = 66.67 px. This means that the shift is scaled before it is applied.</p>
  
  <p>How can we achieve this? Any help is appreciated. Thanks in advance.</p>
  
  <p><strong>Edit:</strong>
  The TransformGroup is built that way:</p>
  
  <pre class="lang-cs prettyprint-override"><code>private TransformGroup _transform = new TransformGroup();
  public TransformGroup Transform {
      get {
          _transformGroup.Children.Clear();
          _transformGroup.Children.Add(scaleTransform);
          _transformGroup.Children.Add(translateTransform);
      }
  }
  </code></pre>
  
  <p>If i do it this way the problem described above occures.</p>
  
  <p><strong>Edit 2</strong></p>
  
  <p>I've created a <a href="https://1drv.ms/f/s!AreFTln1GEWNa4p4xYKaVIDKwJU" rel="nofollow noreferrer">MCVE</a>, so you can run it and see the problem. Change the scale factor to a value not equal to 1.0. Then drag the black canvas with your mouse away from the red point (center point) and change the scale factor again. Now the black canvas seems to jump a bit.</p>