Click here to Skip to main content
15,885,244 members
Articles / Desktop Programming / XAML

Zeroing the Center of a CompositeTransform

Rate me:
Please Sign up or sign in to vote.
3.00/5 (1 vote)
8 Oct 2019CPOL3 min read 2K  
Zeroing the center of a CompositeTransform

Sometimes, it is useful to convert a transformation with a non-zero center point to an equivalent transformation with a zero center point. If you find you have a need for this, then maybe this post will be helpful.

Posts in this series:

Consider this diagram:

Cp

In the above drawing, the green rectangle is translated Tx=80, Ty=60, and rotated R=40° about the center Cx=100, and Cy=30. The goal of this post is to come up with an equivalent transformation with a center point of Cx=0, Cy=0.

The first step is to apply only the translation of Tx=80, Ty=60 and see where that gets us. The result of that is the blue rectangle.

The next step is to apply the rotation of R=40° about the center at Cx=0, Cy=0. The result of that is the red rectangle.

Our last step is to adjust the translation of Tx and Ty to move point B to point G. That is, if we know Bx, By, Gx, and Gy then the new translation is:

  • \( Tx = 80 + Gx – Bx \)
  • \( Ty = 80 + Gy – By \)

This will require a bit of trigonometry.

Point C is the center point of the rotation of the blue and green rectangles. The distance from C to B is the same as the distance from C to G. That is, the distance CB = CG. For simplicity, we will call this distance d. Clearly:

  • \( d = \sqrt{Cx^2 + Cy^2} \)

Now let’s imagine point C is at 0,0 (but let’s keep the original values of Cx=100 and Cy=30 for the rest of the calculations). If that is the case, then:

  • \( Bx = -Cx \)
  • \( By = -Cy \)
  • \( Gx = \cos(g).d \)
  • \( Gy = \sin(g).d \)

Once we determine the angles b and g, we are done. Determining the first angle b is easy:

  • \( b = \text{atan2}(-Cy,-Cx) \)

The second angle g is even easier:

  • g = b + R.

So let’s work this problem through:

  • \( d = \sqrt{Cx^2 + Cy^2} = \sqrt{100^2 + 30^2} = 104.4 \)
  • \( b = \text{atan2}(-Cy,-Cx) = \text{atan2}(-30,-100) = -163.3° \)
  • \( g = b + R = -163.3° + 40° = -123.3° \)
  • \(Bx = -Cx = -100 \)
  • \( By = -Cy = -30 \)
  • \(Gx = Cos(g) * d = \cos(-123.3°) * 104.4 = -57.3\)
  • \(Gy = Sin(g) * d = \sin(-123.3°) * 104.4 = -87.3\)
  • \(Tx = Tx + Gx -Bx = 80 + (-57.3) - (-100) = 122.7\)
  • \(Ty = Ty + Gy -By = 60 + (-87.3) - (-30) = 2.7\)

Here is an overlay of the before (green) and after (blue) transformations:

image 2

Here is the XAML that overlays both transformations:

ZeroCtrPtExample.xaml

XML
<Page
				    x:Class="PanViewDemoApp.ZeroCtrPtExample"
				    IsTabStop="false"
				    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
				    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
				    xmlns:local="using:PanViewDemoApp"
				    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
				    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
				    mc:Ignorable="d"
				    FontSize="16">
				    <Canvas>
				        <Border
				            Height="120"
				            Width="200"
				            Background="LightGreen">
				            <Border.RenderTransform>
				                <CompositeTransform
				                    x:Name="M"
				                    TranslateX="80"
				                    TranslateY="60"
				                    Rotation="40"
				                    CenterX="100"
				                    CenterY="30" />
				            </Border.RenderTransform>
				            <TextBlock
				                Margin="3"
				                Foreground="Green">Tx=80 Ty=60<LineBreak />
                                R=40<LineBreak />Cx=100 Cy=30</TextBlock>
				        </Border>
				        <Border
				            Height="120"
				            Width="200"
				            BorderThickness="3"
				            BorderBrush="Blue">
				            <Border.RenderTransform>
				                <CompositeTransform
				                    x:Name="N"
				                    TranslateX="122.7"
				                    TranslateY="2.7"
				                    Rotation="40" />
				            </Border.RenderTransform>
				            <TextBlock
				                VerticalAlignment="Bottom"
				                Foreground="Blue"
				                Margin="3">Tx=122.7 Ty=2.7<LineBreak />
                                R=40<LineBreak />Cx=0 Cy=0</TextBlock>
				        </Border>
				    </Canvas>
				</Page>

Here is some C# code that performs the zeroing of the center point of a transformation:

TransformExtensions.cs

C#
static void InternalZeroCenterPoint(ICompositeTransform t)
				{
				    var d = Math.Sqrt(t.CenterX * t.CenterX + t.CenterY * t.CenterY);
				    var b = Math.Atan2(-t.CenterY, -t.CenterX);
				    var g = b + t.Rotation * Math.PI / 180;
				    var Bx = -t.CenterX;
				    var By = -t.CenterY;
				    var Gx = Math.Cos(g) * d;
				    var Gy = Math.Sin(g) * d;
				    t.TranslateX += Gx - Bx;
				    t.TranslateY += Gy - By;
				    t.CenterX = 0;
				    t.CenterY = 0;
				}

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) LECO Corporation
United States United States
John Hauck has been developing software professionally since 1981, and focused on Windows-based development since 1988. For the past 17 years John has been working at LECO, a scientific laboratory instrument company, where he manages software development. John also served as the manager of software development at Zenith Data Systems, as the Vice President of software development at TechSmith, as the lead medical records developer at Instrument Makar, as the MSU student who developed the time and attendance system for Dart container, and as the high school kid who wrote the manufacturing control system at Wohlert. John loves the Lord, his wife, their three kids, and sailing on Lake Michigan.

Comments and Discussions

 
-- There are no messages in this forum --