I couldn’t find any intelligent way to get the absolute position of an object that has transformations applied to it on a canvas, I decided to use a point and apply to it the same transformations of the object I am trying to track, then I will know when to do something to the object based on the coordinates of the point.
The problem begins when applying a rotation with the trigonometric formula and comparing it to the RotateTransform function. The objects not only don’t align, which would suggest they are not plotted in the same rules, like top/left of the object, and unless my glasses are very off, the circular trajectory seems to be distorted when computing it with the formula. I particularly don’t believe math stopped working exactly on my computer.
Look at the picture below, I plotted vertical/horizontal lines to indicate the center of the canvas, then create some ellipses rotated by increasingly 45 degrees, the blue ones with the RotateTransform and the red ones with trigonometric formula. Blue is correct, and red can be seen not only misaligned, but rotating at an unexpected rate.
The applied logic is:
- Loop accumulates the angle: 0, 45, 90…
- 3 points: center of the canvas, translated Y coordinate to a radius distance to the center, rotated point used to plot the red circles
- Blue circles use a TransformGroup with a TranslateTransform and a RotateTransform
XAML:
<Window x:Class="Angle.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Angle"
mc:Ignorable="d"
Title="MainWindow" Height="520" Width="520">
<Canvas Grid.Row ="0" x:Name="cv" Width="500" Height="500"></Canvas>
</Window>
C#:
using System.Windows;
using System.Windows.Media;
using System.Windows.Shapes;
namespace Angle
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
int increment = 45,
segments = 360 / increment;
double radius = 150.0,
angle = 0.0;
Point origin;
origin.X = cv.Width / 2;
origin.Y = cv.Height / 2;
Line verLine = new Line() { X1 = origin.X, X2 = origin.X, Y1 = 0, Y2 = cv.Height },
hrzLine = new Line() { X1 = 0, X2 = cv.Width, Y1 = origin.Y, Y2 = origin.Y };
verLine.Stroke = hrzLine.Stroke = Brushes.Black;
verLine.StrokeThickness = hrzLine.StrokeThickness = 1;
cv.Children.Add(verLine);
cv.Children.Add(hrzLine);
for (int i = 0; i < segments; i++)
{
Point translated, rotated;
Ellipse usingMath = new Ellipse() { Width = 20, Height = 20 },
usingTransform = new Ellipse() { Width = 20, Height = 20 };
translated.X = origin.X;
translated.Y = origin.Y + radius;
rotated.X = (Math.Cos(angle * Math.PI / 180) * (translated.X - origin.X) - Math.Sin(angle * Math.PI / 180) * (translated.Y - origin.Y) + origin.X);
rotated.Y = (Math.Sin(angle * Math.PI / 180) * (translated.X - origin.X) + Math.Cos(angle * Math.PI / 180) * (translated.Y - origin.Y) + origin.Y);
usingMath.RenderTransform = new TranslateTransform() { X = rotated.X, Y = rotated.Y };
TransformGroup transf = new TransformGroup();
transf.Children.Add(new TranslateTransform() { X = translated.X, Y = translated.Y });
transf.Children.Add(new RotateTransform() { Angle = angle, CenterX = origin.X, CenterY = origin.Y });
usingTransform.RenderTransform = transf;
usingMath.StrokeThickness = usingTransform.StrokeThickness = 4;
usingMath.Stroke = Brushes.Red;
usingTransform.Stroke = Brushes.Blue;
cv.Children.Add(usingMath);
cv.Children.Add(usingTransform);
angle += increment;
}
}
}
}
I have reviewed this over and over and there must be a blatant mistake somewhere or something I forgot to do, and maybe you can help me spot what is wrong?