Programming with .NET - Generalhttp://forums.silverlight.net//17.aspx/1?Programming+with+NET+GeneralGeneral discussions around authoring Silverlight .NET applications.Mon, 01 Jan 0001 00:00:00 -050017134135http://forums.silverlight.net//p/51139/134135.aspx/1?matrix+Pan+and+Zoommatrix Pan and Zoom <p>Discovered a strange translation occurring on centered zoom (zoom&lt;&gt;1) after a pan.<br> The goal is to zoom always on a constant point of the screen, presented by a red circle. Pan is controlled with arrow keys, zoom - with key plus(&#43;) or minus(-).<br> Everything works fine, except when scaling with zoom &lt;&gt;1 after a pan. Cannot figure out where this one-time translation comes from... Before and after this event panning and zooming work as expected.<br> Here is the code. What am I missing ? <br> </p> <p>&nbsp;&lt;UserControl x:Class=&quot;ZoPanNS.ZoPan&quot;<br> &nbsp;&nbsp;&nbsp; xmlns=&quot;http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot; <br> &nbsp;&nbsp;&nbsp; xmlns:x=&quot;http://schemas.microsoft.com/winfx/2006/xaml&quot; <br> &nbsp;&nbsp;&nbsp; Width=&quot;600&quot; Height=&quot;600&quot;&gt;<br> &nbsp;&nbsp;&nbsp; &lt;Canvas Background=&quot;White&quot;&gt;<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Ellipse Canvas.Left=&quot;200&quot; Canvas.Top=&quot;200&quot; Canvas.ZIndex=&quot;2&quot; <br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Width=&quot;12&quot; Height=&quot;12&quot; Stroke=&quot;Red&quot; StrokeThickness=&quot;2&quot; Fill=&quot;Transparent&quot; /&gt;<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;TextBlock x:Name=&quot;TxtB&quot; Canvas.Left=&quot;0&quot; Canvas.Top=&quot;0&quot; Canvas.ZIndex=&quot;2&quot; <br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Width=&quot;200&quot; Height=&quot;20&quot; Text=&quot;click here to start&quot; /&gt;<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Canvas x:Name=&quot;cMoved&quot; Background=&quot;PaleGreen&quot; Canvas.Left=&quot;100&quot; Canvas.Top=&quot;100&quot; <br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Width=&quot;200&quot; Height=&quot;200&quot; RenderTransformOrigin=&quot;0,0&quot;&gt;<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Rectangle Canvas.Left=&quot;0&quot; Canvas.Top=&quot;0&quot;<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Width=&quot;200&quot; Height=&quot;200&quot; Stroke=&quot;DarkCyan&quot; StrokeThickness=&quot;2&quot; Fill=&quot;Wheat&quot; /&gt;<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Ellipse x:Name=&quot;Ccircle&quot; Canvas.Left=&quot;100&quot; Canvas.Top=&quot;100&quot; <br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Width=&quot;7&quot; Height=&quot;7&quot; Stroke=&quot;Green&quot; StrokeThickness=&quot;2&quot; Fill=&quot;Green&quot; /&gt;<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/Canvas&gt;<br> &nbsp;&nbsp;&nbsp; &lt;/Canvas&gt;<br> &lt;/UserControl&gt;<br> <br> using System;<br> using System.Windows;<br> using System.Windows.Controls;<br> using System.Windows.Input;<br> using System.Windows.Media;<br> using System.Windows.Shapes;<br> <br> namespace ZoPanNS<br> {<br> &nbsp;&nbsp;&nbsp; public partial class ZoPan : UserControl<br> &nbsp;&nbsp;&nbsp; {<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; double Xstep = 40, Ystep = 40, Zstep = 0.2;<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; double CenterX=100, CenterY=100;<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private MatrixTransform _matrixTransform = new MatrixTransform();<br> <br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public ZoPan()<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; InitializeComponent();<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.Loaded &#43;= new RoutedEventHandler(Page_Loaded);<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private void Page_Loaded(object o, EventArgs e)<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cMoved.RenderTransform = _matrixTransform;<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cMoved.RenderTransformOrigin = new Point(.5, .5); //center<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.KeyDown &#43;= new KeyEventHandler(page_KeyDown);<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private void page_KeyDown(object sender, KeyEventArgs e)<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Matrix matrix = _matrixTransform.Matrix;<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; switch (e.Key)<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case Key.Left:<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CenterX &#43;= Xstep;<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Ccircle.SetValue(Canvas.LeftProperty, CenterX);<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; matrix.OffsetX -= Xstep * matrix.M11;<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case Key.Right:<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CenterX -= Xstep;<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Ccircle.SetValue(Canvas.LeftProperty, CenterX);<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; matrix.OffsetX &#43;= Xstep * matrix.M11;<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case Key.Up:<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CenterY &#43;= Ystep;<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Ccircle.SetValue(Canvas.TopProperty, CenterY);<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; matrix.OffsetY -= Ystep * matrix.M22;<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case Key.Down:<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CenterY -= Ystep;<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Ccircle.SetValue(Canvas.TopProperty, CenterY);<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; matrix.OffsetY &#43;= Ystep * matrix.M22;<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br> <br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case Key.Add:<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; matrix.M11 &#43;= Zstep;<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; matrix.M22 = matrix.M11;<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cMoved.RenderTransformOrigin = new Point(<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CenterX / cMoved.ActualWidth, CenterY / cMoved.ActualHeight);<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br> <br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case Key.Subtract:<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; matrix.M11 -= Zstep;<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; matrix.M22 = matrix.M11;<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cMoved.RenderTransformOrigin = new Point(<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CenterX / cMoved.ActualWidth, CenterY / cMoved.ActualHeight);<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; default:<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return;<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; _matrixTransform.Matrix = matrix;<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; TxtB.Text = &quot;zoom=&quot; &#43; matrix.M11.ToString(&quot;0.0&quot;)<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#43; &quot; cX=&quot; &#43; CenterX.ToString(&quot;0.0&quot;)<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#43; &quot; oX=&quot; &#43; matrix.OffsetX.ToString(&quot;0.0&quot;)<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#43; &quot; rX=&quot; &#43; cMoved.RenderTransformOrigin.X.ToString(&quot;0.0&quot;)<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br> &nbsp;&nbsp;&nbsp; }<br> }</p> 2008-11-19T17:03:52-05:00143332http://forums.silverlight.net//p/51139/143332.aspx/1?Re+matrix+Pan+and+ZoomRe: matrix Pan and Zoom <p>I think your math is slightly off because you are using CenterX/Y for two different things: (a) to position the Circle and (b) to determine the center of rotation.</p> <p>Note that the position (Canvas.Left/Top)&nbsp;of the Ellipse refers to the upper left corner of its bounding rectangle - not to its center, hence the translation.</p> <p>Thanks, Stefan Wick</p> 2008-12-06T05:04:40-05:00143557http://forums.silverlight.net//p/51139/143557.aspx/1?Re+matrix+Pan+and+ZoomRe: matrix Pan and Zoom <p>Yes - &quot;using CenterX/Y for two different things: (a) to position the Circle and (b) to determine the center of scaling&quot; - what is wrong with that ?<br> Yes - &quot;(Canvas.Left/Top) of the Ellipse refers to the upper left corner of its bounding rectangle - not to its center&quot; - but these couple of pixels are not part of the problem.</p> <p>Here is how to reproduce the translation:<br> The program starts with a yellow square with a green and red circles in the middle. Click on the page to begin. Hit the Up-arrow key twice to pan the square, then &#43; key four times to zoom it. So far so good - pan and zoom are working ok. Now hit the Down-arrow key four times, then the &#43; key once - and <b>watch the translation happen</b>. If you continue zooming with &#43; or -, the square is correctly scaled with the green circle as center. But the green and red circle are not aligned anymore.<br> The goal is to have these two aligned at all times with every zoom centered at them. In other words - have a constant zoom center on the screen regardless of pan operations.<br> If someone can present a code to do this simple task, I promise to retire humbly, not to be seen again [H]<br> </p> 2008-12-06T23:29:40-05:00143618http://forums.silverlight.net//p/51139/143618.aspx/1?Re+matrix+Pan+and+ZoomRe: matrix Pan and Zoom <p>I fixed up your sample and uploaded the working version here (source code is attached to the post). The task gets a lot easier (at least my mind) when you seperate out the Scale vs. Translate transforms.</p> <p><a href="http://blogs.msdn.com/swick/pages/pan-zoom-example.aspx">http://blogs.msdn.com/swick/pages/pan-zoom-example.aspx</a></p> <p>(note that I have changed the keys to use PageUp/Down since that was easier on my keyboard :-))</p> <p>Thanks, Stefan Wick</p> 2008-12-07T04:42:35-05:00166091http://forums.silverlight.net//p/51139/166091.aspx/1?Re+matrix+Pan+and+ZoomRe: matrix Pan and Zoom I want to create zoom and pan system that all shape stroke always is 1 pixel width (hairline). Do you have any idea?<br> 2009-01-26T17:09:23-05:00