Sign in to follow this  
Kram

Simple issue with 2D translation and scale

Recommended Posts

I really dont know why I cannot get my head around this, but I have the need to animate a X and Y translation and an X and Y scale at the same time. What Im after is to be able to pick a position on the scree, and a certain zoom factor (say 5) and have my application scale and translate so that my spot I picked is exactly centered in the screen. But Im having trouble because doesnt the zoom factor effect the destination point? My calculations dont seem to be working... Any help here would be greatly appreciated! Mark

Share this post


Link to post
Share on other sites
I think we won't be able to help much without a little code.
The usual order is scale -> rotate -> translate. Did you use this order to scale and translate your picture?

Unless you define otherwise, the origin around which a picture is scaled is 0,0 [may depend on the framework you're using]. So when you first translate your pic to 10,10 and then scale it by 2, the pic would be scaled up by 2x and located at position 20,20 [{ 10,10 } * 2]. If you scale it at first and then translate, the pic would be scaled up by 2x and located at 20,20. Then subtract half of the width and height * size, and the pic center should be at the wanted position.

Hope I could help.

Share this post


Link to post
Share on other sites
Hi YoYoFreakCJ,

Thanks for the thoughts, I never really gave much thought as to the ordering of what I was doing.

But my issue here is that im using WPF, and it has its own Animation classes that do interpolation between values such as "From 0,0 translate to 10,10 over 1 second".

In order to scale and translate, I have created 4 animations, one for the X and Y of the translation and scale.

So these animations run at the same time, which gives the effect of the translate and the zoom. It does not run using an update loop approach.

So you can see my issue...

Honestly I don't have much code, (I'm not at work now, but I can supply some code if required tomorrow sometime).

Maybe if we took an example:

I have a Canvas element Canvas_Root (which is a container element) that holds a custom control Control_A.

Canvas_Root has properties called ScaleTransform and TranlateTransform which I manipulate through code to change its scale (which also scales its children, and hence Control_A) and its translation.

If Control_A resides at position x:50 and y:250 and the screen is 1024x768

I want to calculate the translation for Canvas_Root so that after the translation and the scale, the center position of Control_A is smack bang in the center of the screen.

Something just to mention as well, WPF has 2 ways of transforming its elements.

1. By a group of transforms (scale, translate, skew, rotate)
2. By a matrix (M11, M12, M21, M22, OffsetX and OffsetY)

If an implementation using one of these two techniques is easier/better Im open to implementation that as well.

Share this post


Link to post
Share on other sites
here is the maths that I have so far (that I have pieced together from web samples):


const double zoomTo = 15;

//get the rendered bounds of the control that I want to zoom in and pan on.
var bounds = TransformToAncestor(FindProductsCanvasParent(this)).TransformBounds(new Rect(0, 0, ActualWidth, ActualHeight));

//get the center point of the control to zoom in on.
//I.e. zoom in on the center point of the control
var centerPoint = new Point(bounds.TopLeft.X + (bounds.Width / 2), bounds.TopLeft.Y + (bounds.Height / 2));

//-----------------------------
//HONESTLY, I dont really understand why we do the Inverse of a transform matrix here...
//-----------------------------
ZoomInAndPan(newScale, ParentCanvas.RenderTransform.Inverse.Transform(destinationPoint), destinationPoint);

public void ZoomInAndPan(double zoomTo, Point matchPosition, Point physicalPosition)
{
var group = (CanvasToManipulate.RenderTransform as TransformGroup);

var zoomTransform = group.Children[0] as ScaleTransform;
var translateTransform = group.Children[3] as TranslateTransform;

double finalXPosition = -1 * (matchPosition.X * zoomTo - physicalPosition.X);
double finalYPosition = -1 * (matchPosition.Y * zoomTo - physicalPosition.Y);

var animTranslateX = CreateZoomAnimation(finalXPosition);
var animTranslateY = CreateZoomAnimation(finalYPosition);

var animZoomX = CreateZoomAnimation(zoomTo);
var animZoomY = CreateZoomAnimation(zoomTo);

translateTransform.BeginAnimation(TranslateTransform.XProperty, animTranslateX);
translateTransform.BeginAnimation(TranslateTransform.YProperty, animTranslateY);

zoomTransform.BeginAnimation(ScaleTransform.ScaleXProperty, animZoomX);
zoomTransform.BeginAnimation(ScaleTransform.ScaleYProperty, animZoomY);
}



But this is wrong, becuse it does not calculate the correct X/Y translation in order to move the control into the center of the screen

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this