private TransformerControl CreateTransformer(TextBox t1, int gw, int gh, int gx, int gy) { var RB = new Rectangle { Width = gw, Height = gh, Fill = Brushes.Red, Opacity = 0.1, Cursor = Cursors.Hand, }.AttachTo(this).MoveTo(gx, gy); var GB = new Rectangle { Width = gw, Height = gh, Fill = Brushes.Green, Opacity = 0.1, Cursor = Cursors.Hand, }.AttachTo(this).MoveTo(gx, gy); var g0 = new Rectangle { Width = gw, Height = gh, Fill = Brushes.Purple, Opacity = 0.2 }.AttachTo(this.Shadow).MoveTo(gx, gy); var g1 = new Image { Width = gw, Height = gh, Source = new Avalon.Images.d().Source, Opacity = 0.7, }.AttachTo(this).MoveTo(gx, gy); var g2 = new Image { Width = gw, Height = gh, Source = new Avalon.Images.d().Source, Opacity = 0.7, }.AttachTo(this).MoveTo(gx, gy); var R = new Rectangle { Width = 8, Height = 8, Fill = Brushes.Red, Cursor = Cursors.Hand, RenderTransform = new TranslateTransform(-4, -4) }.AttachTo(this).MoveTo(gx, gy); var G = new Rectangle { Width = 8, Height = 8, Fill = Brushes.Green, Cursor = Cursors.Hand, RenderTransform = new TranslateTransform(-4, -4) }.AttachTo(this).MoveTo(gx, gy); var M = new Rectangle { Width = 8, Height = 8, Fill = Brushes.Magenta, Cursor = Cursors.Hand, RenderTransform = new TranslateTransform(-4, -4) }.AttachTo(this).MoveTo(gx, gy); var Y = new Rectangle { Width = 8, Height = 8, Fill = Brushes.Yellow, Cursor = Cursors.Hand, RenderTransform = new TranslateTransform(-4, -4) }.AttachTo(this).MoveTo(gx, gy); var Orange = new Rectangle { Width = 8, Height = 8, Fill = Brushes.Orange, Cursor = Cursors.Hand, RenderTransform = new TranslateTransform(-4, -4) }.AttachTo(this).MoveTo(gx + gw / 2, gy + gh / 2 - 8); // rotation origin var Black = new Rectangle { Width = 8, Height = 8, Fill = Brushes.Black, Cursor = Cursors.Hand, RenderTransform = new TranslateTransform(-4, -4) }.AttachTo(this).MoveTo(gx + gw / 2, gy + gh / 2); // rotation handler var White = new Rectangle { Width = 8, Height = 8, Fill = Brushes.White, Cursor = Cursors.Hand, RenderTransform = new TranslateTransform(-4, -4) }.AttachTo(this).MoveTo(gx + gw, gy + gh / 2); var OrangeSelfAverage = true; Action Update = delegate { var w = new StringBuilder(); w.AppendLine("Magneta:"); w.AppendLine(ApplyMatrix(RB, GB, R, G, M, g2, gx, gy, gw, gh)); w.AppendLine("Yellow:"); w.AppendLine(ApplyMatrix(RB, GB, R, G, Y, g1, gx, gy, gw, gh)); if (t1 != null) t1.Text = w.ToString(); if (OrangeSelfAverage) { var args = new[] { new { x = Canvas.GetLeft(R), y = Canvas.GetTop(R) }, new { x = Canvas.GetLeft(G), y = Canvas.GetTop(G) }, new { x = Canvas.GetLeft(M), y = Canvas.GetTop(M) }, new { x = Canvas.GetLeft(Y), y = Canvas.GetTop(Y) } }; var _x = args.Average(k => k.x); var _y = args.Average(k => k.y); Orange.MoveTo( _x, _y - 8 ); } }; Action Reset = delegate { M.MoveTo(gx, gy); R.MoveTo(gx + gw, gy); G.MoveTo(gx, gy + gh); Y.MoveTo(gx + gw, gy + gh); }; AsMovableByMouse(R, Update); AsMovableByMouse(G, Update); AsMovableByMouse(M, Update); AsMovableByMouse(Y, Update); var RotationInfo = new { x = 0.0, y = 0.0 }; RotationInfo = null; Action UpdateRotation = delegate { var p = new { White = new { x = Canvas.GetLeft(White), y = Canvas.GetTop(White) }, Black = new { x = Canvas.GetLeft(Black), y = Canvas.GetTop(Black) }, R = new { x = Canvas.GetLeft(R), y = Canvas.GetTop(R) }, G = new { x = Canvas.GetLeft(G), y = Canvas.GetTop(G) }, M = new { x = Canvas.GetLeft(M), y = Canvas.GetTop(M) }, Y = new { x = Canvas.GetLeft(Y), y = Canvas.GetTop(Y) } }; if (RotationInfo == null) { RotationInfo = p.White; return; } // we now need // - previous distance and rotation // - current distance and rotation var q = new { o = new { x = RotationInfo.x - p.Black.x, y = RotationInfo.y - p.Black.y }, n = new { x = p.White.x - p.Black.x, y = p.White.y - p.Black.y }, R = new { x = p.Black.x - p.R.x, y = p.Black.y - p.R.y }, G = new { x = p.Black.x - p.G.x, y = p.Black.y - p.G.y }, M = new { x = p.Black.x - p.M.x, y = p.Black.y - p.M.y }, Y = new { x = p.Black.x - p.Y.x, y = p.Black.y - p.Y.y }, }; Func<double, double, double> GetLength = (x, y) => { return new vec2(x, y).Length; }; var a = new { o = new { z = GetLength(q.o.x, q.o.y), a = new Point(q.o.x, q.o.y).GetRotation() }, n = new { z = GetLength(q.n.x, q.n.y), a = new Point(q.n.x, q.n.y).GetRotation() }, R = new { z = -GetLength(q.R.x, q.R.y), a = new Point(q.R.x, q.R.y).GetRotation() }, G = new { z = -GetLength(q.G.x, q.G.y), a = new Point(q.G.x, q.G.y).GetRotation() }, M = new { z = -GetLength(q.M.x, q.M.y), a = new Point(q.M.x, q.M.y).GetRotation() }, Y = new { z = -GetLength(q.Y.x, q.Y.y), a = new Point(q.Y.x, q.Y.y).GetRotation() }, }; var n = new { z = a.n.z / a.o.z, a = a.n.a - a.o.a }; if (n.z == 1) if (n.a == 0) { RotationInfo = p.White; return; } R.MoveTo( p.Black.x + Math.Cos(a.R.a + n.a) * a.R.z * n.z, p.Black.y + Math.Sin(a.R.a + n.a) * a.R.z * n.z ); G.MoveTo( p.Black.x + Math.Cos(a.G.a + n.a) * a.G.z * n.z, p.Black.y + Math.Sin(a.G.a + n.a) * a.G.z * n.z ); M.MoveTo( p.Black.x + Math.Cos(a.M.a + n.a) * a.M.z * n.z, p.Black.y + Math.Sin(a.M.a + n.a) * a.M.z * n.z ); Y.MoveTo( p.Black.x + Math.Cos(a.Y.a + n.a) * a.Y.z * n.z, p.Black.y + Math.Sin(a.Y.a + n.a) * a.Y.z * n.z ); Update(); RotationInfo = p.White; }; AsMovableByMouse(Black, null); AsMovableByMouse(White, UpdateRotation); var TranslationInfo = new { x = 0.0, y = 0.0 }; TranslationInfo = null; Action ShowVisuals = delegate { g0.Show(); GB.Show(); RB.Show(); Orange.Opacity = 1; var e = new[] { M, R, G, Y, White, Black }; foreach (var k in e) { k.Show(); k.BringToFront(); } }; Action UpdateTranslation = delegate { ShowVisuals(); var p = new { Orange = new { x = Canvas.GetLeft(Orange), y = Canvas.GetTop(Orange) }, White = new { x = Canvas.GetLeft(White), y = Canvas.GetTop(White) }, Black = new { x = Canvas.GetLeft(Black), y = Canvas.GetTop(Black) }, R = new { x = Canvas.GetLeft(R), y = Canvas.GetTop(R) }, G = new { x = Canvas.GetLeft(G), y = Canvas.GetTop(G) }, M = new { x = Canvas.GetLeft(M), y = Canvas.GetTop(M) }, Y = new { x = Canvas.GetLeft(Y), y = Canvas.GetTop(Y) } }; if (TranslationInfo == null) { TranslationInfo = p.Orange; return; } var q = new { x = p.Orange.x - TranslationInfo.x, y = p.Orange.y - TranslationInfo.y, }; if (q.x == 0) if (q.y == 0) { TranslationInfo = p.Orange; return; } RotationInfo = null; R.MoveTo(p.R.x + q.x, p.R.y + q.y); G.MoveTo(p.G.x + q.x, p.G.y + q.y); Y.MoveTo(p.Y.x + q.x, p.Y.y + q.y); M.MoveTo(p.M.x + q.x, p.M.y + q.y); Black.MoveTo(p.Black.x + q.x, p.Black.y + q.y); White.MoveTo(p.White.x + q.x, p.White.y + q.y); Update(); TranslationInfo = p.Orange; }; var OrangeDrag = AsMovableByMouse(Orange, UpdateTranslation); OrangeDrag.Enter = () => OrangeSelfAverage = false; OrangeDrag.Exit = () => OrangeSelfAverage = true; Reset(); UpdateRotation(); Update(); var rr = new TransformerControl { SetOpacity = Opacity => { g1.Opacity = Opacity; g2.Opacity = Opacity; }, SetSource = src => { g1.Source = src; g2.Source = src; }, HideMirror = delegate { Y.Opacity = 0.2; g1.Hide(); }, HideVisuals = delegate { g0.Hide(); GB.Hide(); RB.Hide(); Orange.Opacity = 0.05; var e = new[] { M, R, G, Y, White, Black }; foreach (var k in e) { k.Hide(); } }, SetBounds = args => { var e = new[] { M, R, G, Y }; for (int i = 0; i < args.Length; i++) { e[i].MoveTo(args[i].X, args[i].Y); } var _x = args.Average(k => k.X); var _y = args.Average(k => k.Y); Orange.MoveTo( _x, _y - 8 ); RotationInfo = null; Update(); }, //g2 = g2 }; return rr; }