MatrixTransform an Image
-
24 aprilie 2012 12:15

I have a BitmapImage. Within that image, I have 2 reference points, R1 and R2. I also know the width and height.
On my DrawingContext, I have 2 destination points, D1 and D2. I want to draw my image so that R1 and R2 match D1 and D2 and the image gets squeezed/expanded and rotated as needed.
I guess I would do dc.PushTransform() with MatrixTransform before doing dc.DrawImage()... Any ideas how? Thanks.
DNS for Windows Azure dnsazure.com
Toate mesajele
-
24 aprilie 2012 13:15Moderator
"I guess I would do dc.PushTransform() with MatrixTransform"
Well yes but this is probably easier to understand if you use a transform group instead of building a MatrixTransform directly. Here's an example:
TransformGroup transform = new TransformGroup(); Point r1 = new Point(0, image.Height / 2.0); Point r2 = new Point(image.Width, image.Height / 2.0); Point d1 = new Point(20, 150); // some random D1/D2 coords Point d2 = new Point(80, 70); Vector v1 = r2 - r1; Vector v2 = d2 - d1; transform.Children.Add(new TranslateTransform(-r1.X, -r1.Y)); // change the origin to R1 transform.Children.Add(new ScaleTransform(v2.Length / v1.Length, 1.0)); // scale along X axis transform.Children.Add(new RotateTransform(Vector.AngleBetween(v1, v2))); // rotate to match the direction of D1-D2 transform.Children.Add(new TranslateTransform(d1.X, d1.Y)); // finally move the image to D1 dc.PushTransform(transform); dc.DrawImage(image, new Rect(0, 0, image.Width, image.Height)); dc.Pop();
Note that scaling is done only along the X axis, it's not possible to scale along Y without additional points.- Marcat ca răspuns de Tan SilliksaarMVP 24 aprilie 2012 13:43
-
24 aprilie 2012 13:44Wow, thanks, you made my day.
DNS for Windows Azure dnsazure.com
-
29 aprilie 2012 08:42
Thanks Mike this really helps. Can I have a follow up question?

Question 1: Instead of having R1 and R2 as reference points, but having R'1 and R'2. Should I use translate R'1 to R1 first, then translate back D'1 to D1?
Question 2: If I have an additional point (R'3), may I know how can I do the Scale along Y also?
(R'1 R'2 and R'3 are some points inside the image instead of on the edge of the image)
-
30 aprilie 2012 03:01
I have a known BitmapImage (width=400, height=100). Inside this image, I have 2 known reference points, R'1 (100,50) and R'2 (300,50). Also, I know R0 (0,0).
(R'1 R'2 and R'3 are some points inside the image instead of on the edge of the image)
On my DrawingContext, I have 2 destinations points, D'1 (300,300) and D'2 (400,400). I want to draw my image so that R'1 and R'2 match D'1 and D'2 and the image gets squeezed/expanded and rotated as needed. However, I don't know D0.
I tried the code suggested by Mike. However, the image doesn't render correctly
http://social.msdn.microsoft.com/Forums/en/wpf/thread/fffe1f6b-70c9-4ae8-9690-aad171fecef1
TransformGroup transform = new TransformGroup(); //Point r1 = new Point(0, image.Height / 2.0); //Point r2 = new Point(image.Width, image.Height / 2.0); Point r1 = new Point(100, 50); Point r2 = new Point(300, 50); Point d1 = new Point(300, 300); Point d2 = new Point(400, 400); Vector v1 = r2 - r1; Vector v2 = d2 - d1;
transform.Children.Add(new TranslateTransform(-r1.X, -r1.Y)); // change the origin to R1 transform.Children.Add(new ScaleTransform(v2.Length / v1.Length, 1.0)); // scale along X axis transform.Children.Add(new RotateTransform(Vector.AngleBetween(v1, v2))); // rotate to match the direction of D1-D2 transform.Children.Add(new TranslateTransform(d1.X, d1.Y)); // finally move the image to D1 dc.PushTransform(transform); dc.DrawImage(image, new Rect(0, 0, // d0 image.Width, image.Height)); // this doesn't render correctly
dc.DrawEllipse(new SolidColorBrush(Color.FromArgb(255, 0, 0, 0)), null, d1, thickness, thickness); // this renders correctly
dc.DrawEllipse(new SolidColorBrush(Color.FromArgb(255, 0, 0, 0)), null, d2, thickness, thickness); // this renders correctlydc.Pop();
Questions 2: If I have an additional point (R'3) (200,10) , may I know how can I do the Scale along Y also?
Questions 3: Which topic/book should I look into if I want to know more about this regarding do some AR using WPF? (DirectX, XNA ??)
Thank you very much.
- Editat de sHirakawa 30 aprilie 2012 03:02
- Editat de sHirakawa 30 aprilie 2012 03:11
- Îmbinat de Annabella LuoModerator 8 mai 2012 09:34
-
30 aprilie 2012 07:46Moderator
1: nope, you don't need an additional translation.
2: for this we can use the distance between the R3/D3 points and the R1R2/D1D2 lines do determine the y scaling factor. Here's an update for the relevant part of the code:
Point r1 = new Point(51, 28); Point r2 = new Point(177, 28); Point r3 = new Point(111, 7); Point d1 = new Point(335, 118); Point d2 = new Point(395, 60); Point d3 = new Point(345, 75); Vector vr21 = r2 - r1; Vector vd21 = d2 - d1; Vector vr31 = r3 - r1; Vector vd31 = d3 - d1; double y1 = Vector.CrossProduct(vr31, vr21) / vr21.Length; double y2 = Vector.CrossProduct(vd31, vd21) / vd21.Length; transform.Children.Add(new TranslateTransform(-r1.X, -r1.Y)); transform.Children.Add(new ScaleTransform(vd21.Length / vr21.Length, y2 / y1)); transform.Children.Add(new RotateTransform(Vector.AngleBetween(vr21, vd21))); transform.Children.Add(new TranslateTransform(d1.X, d1.Y));The use of vector cross product may need some explanation: in 2D the cross product of 2 vectors v1 and v2 happens to be equal to sin(t) * v1.Length * v2.Length. If you build a right triangle by projecting the point D3 on the line D1D2 you get that the point-line distance is sin(t) * D3D1.Length where t is the angle between D3D1 and D2D1. In the end the point-line distance can be expressed as cross(D3D1, D2D1) / D2D1.Length = sin(t) * D3D1.Length * D2D1.Length / D2D1.Length = sin(t) * D3D1.Length. -
4 mai 2012 09:52
Maybe you can go back to consult Mike Dones to get a quick responce due to this is the result of you guys talking, right?