Beispiel #1
0
        private AffineMesh AddCube(AffineMesh context, ImageSource Source, ImageSource Source2, AffinePoint TopLocation)
        {
            var a = new AffineMesh();


            // front
            AddCubeFace(a, Source, Source2,
                        new AffinePoint(-100, -100, 100),
                        new AffinePoint(100, -100, 100),
                        new AffinePoint(-100, 100, 100),
                        new AffinePoint(100, 100, 100)
                        );

            // right
            AddCubeFace(a, Source, Source2,
                        new AffinePoint(100, -100, 100),
                        new AffinePoint(100, -100, -100),
                        new AffinePoint(100, 100, 100),
                        new AffinePoint(100, 100, -100)
                        );

            // left
            AddCubeFace(a, Source, Source2,
                        new AffinePoint(-100, -100, 100),
                        new AffinePoint(-100, -100, -100),
                        new AffinePoint(-100, 100, 100),
                        new AffinePoint(-100, 100, -100)
                        );

            // back
            AddCubeFace(a, Source, Source2,
                        new AffinePoint(-100, -100, -100),
                        new AffinePoint(100, -100, -100),
                        new AffinePoint(-100, 100, -100),
                        new AffinePoint(100, 100, -100)
                        );

            // top
            AddCubeFace(a, Source, Source2,
                        new AffinePoint(-100, 100, -100),
                        new AffinePoint(100, 100, -100),
                        new AffinePoint(-100, 100, 100),
                        new AffinePoint(100, 100, 100)
                        );

            var _a = a.ToTranslation(new AffinePoint(TopLocation.X * 200, TopLocation.Z * 200, TopLocation.Y * 200));

            context.Meshes.Add(
                _a
                );

            return(_a);
        }
        private void AddCube(AffineMesh a, AffinePoint Offset = null)
        {
            // front
            AddCubeFace(a, "front",
                        new AffinePoint(-100, -100, 100) + Offset,
                        new AffinePoint(100, -100, 100) + Offset,
                        new AffinePoint(-100, 100, 100) + Offset,
                        new AffinePoint(100, 100, 100) + Offset
                        );

            // right
            AddCubeFace18(a, "right",
                          new AffinePoint(100, -100, 100) + Offset,
                          new AffinePoint(100, -100, -100) + Offset,
                          new AffinePoint(100, 100, 100) + Offset,
                          new AffinePoint(100, 100, -100) + Offset
                          );

            // left
            AddCubeFace18(a, "left",
                          new AffinePoint(-100, -100, 100) + Offset,
                          new AffinePoint(-100, -100, -100) + Offset,
                          new AffinePoint(-100, 100, 100) + Offset,
                          new AffinePoint(-100, 100, -100) + Offset
                          );

            // back
            AddCubeFace18(a, "back",
                          new AffinePoint(-100, -100, -100) + Offset,
                          new AffinePoint(100, -100, -100) + Offset,
                          new AffinePoint(-100, 100, -100) + Offset,
                          new AffinePoint(100, 100, -100) + Offset
                          );

            // top
            AddCubeFace18(a, "top",
                          new AffinePoint(-100, 100, -100) + Offset,
                          new AffinePoint(100, 100, -100) + Offset,
                          new AffinePoint(-100, 100, 100) + Offset,
                          new AffinePoint(100, 100, 100) + Offset
                          );

            // bottom
            AddCubeFace18(a, "bottom",
                          new AffinePoint(-100, -100, -100) + Offset,
                          new AffinePoint(100, -100, -100) + Offset,
                          new AffinePoint(-100, -100, 100) + Offset,
                          new AffinePoint(100, -100, 100) + Offset
                          );
        }
Beispiel #3
0
        private void Show(AffineMesh _a)
        {
            ShowCounter++;
            double Zoom = 0.2;

            // js: 130
            // as: 70
            // c#: 30

            // simple z sort
            // js: 63
            // as: 28
            // c#: 27

            // js: 61
            // as: 26

            // n.Vertecies = v.OrderBy(k => k.Center.Z).ToList();
            foreach (var k in _a.GetCombinedVertices().OrderBy(k => k.Center.Z))
            //foreach (var k in _a.GetSortedCombinedVertices())
            {
                if (k != null)
                {
                    k.Element.Orphanize();
                    k.Element.AttachTo(AffineContent);


                    k.Element.RenderTransform = new AffineTransform
                    {
                        Left   = 0,
                        Top    = 0,
                        Width  = k.ElementWidth,
                        Height = k.ElementHeight,

                        X1 = k.B.X * Zoom + Width / 2,
                        Y1 = k.B.Y * Zoom + Height / 2,

                        X2 = k.C.X * Zoom + Width / 2,
                        Y2 = k.C.Y * Zoom + Height / 2,

                        X3 = k.A.X * Zoom + Width / 2,
                        Y3 = k.A.Y * Zoom + Height / 2,
                    };
                }
                //((Action<AffineVertex>)k.Tag)(k);
            }
        }
Beispiel #4
0
        private void AddCubeFace(AffineMesh a, ImageSource Source, ImageSource Source2, AffinePoint A, AffinePoint B, AffinePoint C, AffinePoint D)
        {
            var v1 =
                new AffineVertex
            {
                A = A,
                B = B,
                C = C,

                Element = new Image
                {
                    Width  = 100,
                    Height = 100,
                    Source = Source
                }.AttachTo(AffineContent),
                ElementWidth  = 100,
                ElementHeight = 100
            };



            a.Vertecies.Add(v1);

            var v2 =
                new AffineVertex
            {
                A = D,
                B = C,
                C = B,

                Element = new Image
                {
                    Width  = 100,
                    Height = 100,
                    Source = Source2
                }.AttachTo(AffineContent),
                ElementWidth  = 100,
                ElementHeight = 100
            };



            a.Vertecies.Add(v2);
        }
Beispiel #5
0
        private void AddCubeFace(AffineMesh a, string t, AffinePoint A, AffinePoint B, AffinePoint C, AffinePoint D)
        {
            var v1 =
                new AffineVertex
            {
                A = A,
                B = B,
                C = C,

                Element = new Avalon.Images._17
                {
                    Width  = 100,
                    Height = 100,
                }.AttachTo(AffineContent),
                ElementWidth  = 100,
                ElementHeight = 100
            };

            a.Vertecies.Add(v1);

            var v2 =
                new AffineVertex
            {
                A = D,
                B = C,
                C = B,

                Element = new Avalon.Images._17g
                {
                    Width  = 100,
                    Height = 100,
                }.AttachTo(AffineContent),
                ElementWidth  = 100,
                ElementHeight = 100
            };



            a.Vertecies.Add(v2);
        }
Beispiel #6
0
        private void CreateContent(int sandcount, int cubecount, bool rotor)
        {
            var t = new TextBox
            {
                FontSize        = 10,
                Text            = "powered by jsc",
                BorderThickness = new Thickness(0),
                Foreground      = 0xffffffff.ToSolidColorBrush(),
                Background      = Brushes.Transparent,
                IsReadOnly      = true,
                Width           = Width
            }.MoveTo(8, 8).AttachTo(InfoContent);

            if (rotor)
            {
                t.MoveTo(8, 32);
            }

            var a = new AffineMesh();


            var _17  = new Avalon.Images._17().Source;
            var _17g = new Avalon.Images._17g().Source;
            var _18  = new Avalon.Images._18().Source;
            var _18g = new Avalon.Images._18g().Source;



            for (int cubex = -cubecount; cubex < cubecount; cubex++)
            {
                AddCube(a, _18, _18g, new AffinePoint(-1 + cubex * 4, -1, 0));
                AddCube(a, _18, _18g, new AffinePoint(-1 + cubex * 4, 1, 0));

                AddCube(a, _18, _18g, new AffinePoint(1 + cubex * 4, -1, 0));
                AddCube(a, _18, _18g, new AffinePoint(1 + cubex * 4, 1, 0));

                AddCube(a, _17, _17g, new AffinePoint(-1 + cubex * 4, -1, 1));
                AddCube(a, _17, _17g, new AffinePoint(-1 + cubex * 4, 1, 1));

                AddCube(a, _17, _17g, new AffinePoint(1 + cubex * 4, -1, 1));
                AddCube(a, _17, _17g, new AffinePoint(1 + cubex * 4, 1, 1));
            }


            var top = default(AffineMesh);

            if (rotor)
            {
                top = AddCube(a, _18, _18g, new AffinePoint(0, 0, 2));
            }

            var topdef = top;

            if (!rotor)
            {
                for (int ix = -sandcount; ix <= sandcount; ix++)
                {
                    for (int iy = -sandcount; iy <= sandcount; iy++)
                    {
                        AddCubeFace(a,
                                    new Avalon.Images.sandv().Source,
                                    new Avalon.Images.sandv().Source,
                                    new AffinePoint(-100 + ix * 200, -100, -100 + iy * 200),
                                    new AffinePoint(100 + ix * 200, -100, -100 + iy * 200),
                                    new AffinePoint(-100 + ix * 200, -100, 100 + iy * 200),
                                    new AffinePoint(100 + ix * 200, -100, 100 + iy * 200)
                                    );
                    }
                }
            }



            //z			a = a.ToZoom(0.5);


            //a = a.ToZoom(0.8);
            //a = a.ToZoom(1.2);

            var _a       = a;
            var Rotation = new AffineRotation
            {
                XY = (180 + 22).DegreesToRadians(),
                YZ = -22.DegreesToRadians(),
                XZ = 45.DegreesToRadians()
            };

            var MouseOffset0 = 0.0;
            var MouseOffset1 = 0.0;
            var MouseOffset2 = 0.0;

            var MouseMode = 0;

            this.MouseLeftButtonUp +=
                delegate
            {
                MouseMode++;
            };

            this.MouseMove +=
                (sender, args) =>
            {
                var pp = args.GetPosition(this);

                if ((MouseMode % 4) == 1)
                {
                    MouseOffset1 = pp.X;
                    Rotation     = new AffineRotation
                    {
                        XZ = Rotation.XZ,
                        YZ = Rotation.YZ,

                        XY = 0.01 * (pp.X - MouseOffset0) * 2,
                    };
                }

                if ((MouseMode % 4) == 2)
                {
                    MouseOffset2 = pp.X;
                    Rotation     = new AffineRotation
                    {
                        XY = Rotation.XY,
                        YZ = Rotation.YZ,


                        XZ = 0.01 * (pp.X - MouseOffset1) * 2,
                    };
                }

                if ((MouseMode % 4) == 3)
                {
                    MouseOffset0 = pp.X;
                    Rotation     = new AffineRotation
                    {
                        XY = Rotation.XY,
                        XZ = Rotation.XZ,

                        YZ = 0.01 * (pp.X - MouseOffset2) * 2,
                    };
                }
            };


            Action <int> nextframe = null;

            var sw2 = new Stopwatch();

            sw2.Start();

            nextframe =
                c =>
            {
                sw2.Stop();

                var sw = new Stopwatch();

                sw.Start();

                if (top != null)
                {
                    a.Meshes.Remove(top);

                    top = topdef.ToTranslation(
                        new AffinePoint(0, -200 * 3, 0)
                        ).ToRotation(
                        new AffineRotation {
                        XZ = 0.01 * c
                    }
                        ).ToTranslation(
                        new AffinePoint(0, 200 * 3, 0)
                        );

                    a.Meshes.Add(top);
                }



                // rotate floor

                if (rotor)
                {
                    _a = a.ToZoom(0.5).ToRotation(Rotation);
                    Show(_a);
                }
                else
                if (c == 1)
                {
                    _a = a.ToZoom(0.5).ToRotation(Rotation);
                    Show(_a);
                }

                sw.Stop();

                t.Text = new
                {
                    rotor,
                    ShowCounter,
                    XY       = Rotation.XY.RadiansToDegrees() % 360,
                    YZ       = Rotation.YZ.RadiansToDegrees() % 360,
                    XZ       = Rotation.XZ.RadiansToDegrees() % 360,
                    Renderer = sw.ElapsedMilliseconds + "ms",
                    Other    = sw2.ElapsedMilliseconds + "ms"
                }.ToString();

                sw2 = new Stopwatch();
                //sw2.Reset();
                sw2.Start();
                1.AtDelay(() => nextframe(c + 1));

                //this.UpdateLayout();
            }
            ;

            1.AtDelay(() => nextframe(0));
        }
        public void InitializeContent()
        {
            var DefaultWidth  = Convert.ToInt32(Width);
            var DefaultHeight = Convert.ToInt32(Height);

            this.ClipToBounds = true;

            new[] {
                Colors.Black,
                Colors.Blue,
                Colors.Black
            }.ToGradient(DefaultHeight / 2).Select(
                (c, i) =>
                new Rectangle
            {
                Fill   = new SolidColorBrush(c),
                Width  = DefaultWidth,
                Height = 3,
            }.MoveTo(0, i * 2).AttachTo(this)
                ).ToArray();

            var logo = new Avalon.Images.white_jsc().AttachTo(this);

            logo.MoveTo(
                DefaultWidth - Avalon.Images.white_jsc.ImageDefaultWidth,
                DefaultHeight - Avalon.Images.white_jsc.ImageDefaultHeight
                );

            this.SizeChanged +=
                delegate
            {
                logo.MoveTo(
                    this.Width - Avalon.Images.white_jsc.ImageDefaultWidth,
                    this.Height - Avalon.Images.white_jsc.ImageDefaultHeight
                    );
            };

            var t = new TextBox
            {
                FontSize        = 10,
                Text            = "powered by jsc",
                BorderThickness = new Thickness(0),
                Foreground      = 0xffffffff.ToSolidColorBrush(),
                Background      = Brushes.Transparent,
                IsReadOnly      = true,
                Width           = DefaultWidth
            }.MoveTo(8, 8).AttachTo(this);

            #region Initialize
            AffineContent = new Canvas
            {
            }.AttachTo(this);



            InfoContent = new Canvas
            {
            }.AttachTo(this);



            var a = new AffineMesh();



            for (int i = -5; i <= 5; i++)
            {
                if (Math.Abs(i) > 1)
                {
                    AddCube(a, new AffinePoint(210 * i, 0, 0));
                    AddCube(a, new AffinePoint(0, 210 * i, 0));
                    AddCube(a, new AffinePoint(0, 0, 210 * i));
                }
            }

            // AddCubeFace(a, "back",
            //    new AffinePoint(-100, -100, -100),
            //    new AffinePoint(100, -100, -100),
            //    new AffinePoint(-100, 100, -100),
            //    new AffinePoint(100, 100, -100)
            //);


            //a = a.ToZoom(new AffineZoom { X = 2 });


            //a = a.ToZoom(0.8);
            //a = a.ToZoom(1.2);

            var pp = new Point();

            // while jsc initializes local structs it does not do that for fields
            pp = new Point(0, 0);

            var pp_XZ = 0.0;

            Action Update =
                delegate
            {
                var Rotation = new AffineRotation
                {
                    XY = 0.01 * pp.X * 0.5,
                    YZ = 0.02 * pp.X * 0.5,
                    XZ = 0.03 * pp.X * 0.5 + pp_XZ
                };

                t.Text = new
                {
                    XY = Rotation.XZ.RadiansToDegrees(),
                    YZ = Rotation.YZ.RadiansToDegrees(),
                    XZ = Rotation.XZ.RadiansToDegrees()
                }.ToString();

                // rotate floor
                var _a = a.ToZoom(0.2 * (DefaultHeight / 2 + pp.Y) / (DefaultHeight)).ToRotation(Rotation);



                foreach (var k in _a.Vertecies)
                {
                    k.Element.Orphanize();
                    k.Element.AttachTo(AffineContent);
                    k.Element.RenderTransform = new AffineTransform
                    {
                        Left   = 0,
                        Top    = 0,
                        Width  = k.ElementWidth,
                        Height = k.ElementHeight,

                        X1 = k.B.X + DefaultWidth / 2,
                        Y1 = k.B.Y + DefaultHeight / 2,

                        X2 = k.C.X + DefaultWidth / 2,
                        Y2 = k.C.Y + DefaultHeight / 2,

                        X3 = k.A.X + DefaultWidth / 2,
                        Y3 = k.A.Y + DefaultHeight / 2,
                    };

                    //((Action<AffineVertex>)k.Tag)(k);
                }
            };

            this.MouseMove +=
                (sender, args) =>
            {
                pp = args.GetPosition(this);

                Update();
            }
            ;
            #endregion


            var tt = new DispatcherTimer();

            tt.Tick +=
                delegate
            {
                pp_XZ += 0.02;
                Update();
            };

            tt.Interval = TimeSpan.FromMilliseconds(1000 / 30);

            tt.Start();
        }
        private void AddCubeFace18(
            AffineMesh a, string t, AffinePoint A, AffinePoint B, AffinePoint C, AffinePoint D)
        {
            var v1 =
                new AffineVertex
            {
                A = A,
                B = B,
                C = C,

                Element = new Avalon.Images._18
                {
                    Width  = 100,
                    Height = 100,
                }.AttachTo(AffineContent),
                ElementWidth  = 100,
                ElementHeight = 100
            };

            //var t1 = new TextBox { Text = t, Foreground = Brushes.Blue }.AttachTo(InfoContent);

            //v1.Tag = new Action<AffineVertex>(
            //    k =>
            //    {
            //        t1.Text = t + " " + Convert.ToInt32(k.Center.Z);
            //        t1.MoveTo(k.Center.X + DefaultWidth / 2, k.Center.Y + DefaultHeight / 2);

            //    }
            //);

            a.Add(v1);

            //var v2 =
            //    new AffineVertex
            //    {
            //        A = D,
            //        B = C,
            //        C = B,

            //        Element = new Avalon.Images._18.AffineTriangle2
            //        {
            //            Width = 100,
            //            Height = 100,
            //        }.AttachTo(AffineContent),
            //        ElementWidth = 100,
            //        ElementHeight = 100
            //    };

            ////v2.Element.Opacity = 0.5;

            ////var t2 = new TextBox { Text = t }.AttachTo(InfoContent);

            ////v2.Tag = new Action<AffineVertex>(
            ////    k =>
            ////    {
            ////        t2.Text = t + " " + Convert.ToInt32(k.Center.Z);
            ////        t2.MoveTo(k.Center.X + DefaultWidth / 2, k.Center.Y + DefaultHeight / 2);

            ////    }
            ////);

            //a.Add(v2);
        }
        void InitializeContent()
        {
            //new[] {
            //    Colors.Black,
            //    Colors.Blue,
            //    Colors.Black
            //}.ToGradient(Convert.ToInt32( Height) / 2).Select(
            //    (c, i) =>
            //        new Rectangle
            //        {
            //            Fill = new SolidColorBrush(c),
            //            Width = Width,
            //            Height = 3,
            //        }.MoveTo(0, i * 2).AttachTo(this)
            //).ToArray();



            //var help = new Image
            //{
            //    Source = (KnownAssets.Path.Assets + "/help.png").ToSource()
            //}.AttachTo(this);

            //help.Opacity = 0;

            var img = new Avalon.Images.jsc().MoveTo(Width - 128, Height - 128).AttachTo(this);

            var t = new TextBox
            {
                FontSize        = 10,
                Text            = "powered by jsc",
                BorderThickness = new Thickness(0),
                Foreground      = 0xffffffff.ToSolidColorBrush(),
                Background      = Brushes.Transparent,
                IsReadOnly      = true,
                Width           = Width
            }.MoveTo(8, 8).AttachTo(this);



            AffineContent = new Canvas
            {
            }.AttachTo(this);



            InfoContent = new Canvas
            {
            }.AttachTo(this);



            var a = new AffineMesh();



            // front
            AddCubeFace(a, "front",
                        new AffinePoint(-100, -100, 100),
                        new AffinePoint(100, -100, 100),
                        new AffinePoint(-100, 100, 100),
                        new AffinePoint(100, 100, 100)
                        );

            // right
            AddCubeFace(a, "right",
                        new AffinePoint(100, -100, 100),
                        new AffinePoint(100, -100, -100),
                        new AffinePoint(100, 100, 100),
                        new AffinePoint(100, 100, -100)
                        );

            // left
            AddCubeFace(a, "left",
                        new AffinePoint(-100, -100, 100),
                        new AffinePoint(-100, -100, -100),
                        new AffinePoint(-100, 100, 100),
                        new AffinePoint(-100, 100, -100)
                        );

            // back
            AddCubeFace(a, "back",
                        new AffinePoint(-100, -100, -100),
                        new AffinePoint(100, -100, -100),
                        new AffinePoint(-100, 100, -100),
                        new AffinePoint(100, 100, -100)
                        );

            // top
            AddCubeFace(a, "top",
                        new AffinePoint(-100, 100, -100),
                        new AffinePoint(100, 100, -100),
                        new AffinePoint(-100, 100, 100),
                        new AffinePoint(100, 100, 100)
                        );

            // bottom
            AddCubeFace(a, "bottom",
                        new AffinePoint(-100, -100, -100),
                        new AffinePoint(100, -100, -100),
                        new AffinePoint(-100, -100, 100),
                        new AffinePoint(100, -100, 100)
                        );

            // AddCubeFace(a, "back",
            //    new AffinePoint(-100, -100, -100),
            //    new AffinePoint(100, -100, -100),
            //    new AffinePoint(-100, 100, -100),
            //    new AffinePoint(100, 100, -100)
            //);


            //a = a.ToZoom(new AffineZoom { X = 2 });


            //a = a.ToZoom(0.8);
            //a = a.ToZoom(1.2);

            var    pp_X   = 0.0;
            var    pp     = new Point(Width / 2, Height / 2);
            Action Update =
                () =>
            {
                var Rotation = new AffineRotation
                {
                    XY = 0.01 * pp.X * 0.5,
                    YZ = 0.02 * pp.X * 0.5,
                    XZ = 0.03 * pp.X * 0.5 + pp_X
                };

                t.Text = new
                {
                    XY = Rotation.XZ.RadiansToDegrees(),
                    YZ = Rotation.YZ.RadiansToDegrees(),
                    XZ = Rotation.XZ.RadiansToDegrees()
                }.ToString();

                // rotate floor
                var _a = a.ToZoom((Height / 2 + pp.Y) / (Height)).ToRotation(Rotation);



                foreach (var k in _a.Vertecies)
                {
                    k.Element.Orphanize();
                    k.Element.AttachTo(AffineContent);
                    k.Element.RenderTransform = new AffineTransform
                    {
                        Left   = 0,
                        Top    = 0,
                        Width  = k.ElementWidth,
                        Height = k.ElementHeight,

                        X1 = k.B.X + Width / 2,
                        Y1 = k.B.Y + Height / 2,

                        X2 = k.C.X + Width / 2,
                        Y2 = k.C.Y + Height / 2,

                        X3 = k.A.X + Width / 2,
                        Y3 = k.A.Y + Height / 2,
                    };

                    //((Action<AffineVertex>)k.Tag)(k);
                }
            };

            this.MouseMove +=
                (sender, args) =>
            {
                pp = args.GetPosition(this);

                Update();
            };

            var tt = new DispatcherTimer();

            tt.Tick +=
                delegate
            {
                pp_X += 0.02;
                Update();
            };

            tt.Interval = TimeSpan.FromMilliseconds(1000 / 30);
            tt.Start();
        }
Beispiel #10
0
        void InitializeContent()
        {
            Colors.Blue.ToGradient(Colors.Red, Convert.ToInt32(Height) / 4).Select(
                (c, i) =>
                new Rectangle
            {
                Fill   = new SolidColorBrush(c),
                Width  = Width,
                Height = 4,
            }.MoveTo(0, i * 4).AttachTo(this)
                ).ToArray();



            //var help = new Image
            //{
            //    Source = (KnownAssets.Path.Assets + "/help.png").ToSource()
            //}.AttachTo(this);

            //help.Opacity = 0;

            var img = new Image
            {
                Source = new Avalon.Images.jsc().Source
            }.MoveTo(Width - 128, Height - 128).AttachTo(this);

            var t = new TextBox
            {
                FontSize        = 10,
                Text            = "powered by jsc",
                BorderThickness = new Thickness(0),
                Foreground      = 0xffffffff.ToSolidColorBrush(),
                Background      = Brushes.Transparent,
                IsReadOnly      = true,
                Width           = Width
            }.MoveTo(8, 8).AttachTo(this);



            //help.Opacity = 1;
            img.Opacity = 0.5;



            // cursor position calculations are not ready
            // for transofrmed elements.
            // we will provide a floor for those events...
            var shadow = new Rectangle
            {
                Width  = Width,
                Height = Height,

                Fill = Brushes.Black,
            }.AttachTo(this);

            var shadowa = shadow.ToAnimatedOpacity();

            shadowa.Opacity = 0;



            var a = new AffineMesh();

            Func <double, double, double, Brush, AffinePoint> a_Add =
                (X, Y, Z, Fill) =>
            {
                var p = new AffinePoint {
                    Z = Z, X = X, Y = Y
                };
                var h = new Rectangle {
                    Fill = Fill, Width = 4, Height = 4
                }.AttachTo(this);
                //var ht = new TextBox { }.AttachTo(this);

                var historysize = 64;
                var history     = new Queue <Rectangle>();

                Action <AffinePoint> p_Update =
                    pp =>
                {
                    if (history.Count > historysize)
                    {
                        history.Dequeue();
                    }

                    // -100 == 0.5
                    // 0 == 1
                    // +100 == 2

                    //var zoom = (pp.Z) / 1000;

                    var zoom = 0.5;

                    var pp_X = Width / 2 - 4 + pp.X * zoom;
                    var pp_Y = Height / 2 - 4 + pp.Y * zoom;
                    // Z is ignored here
                    // but could be used for sorting

                    h.MoveTo(pp_X, pp_Y);

                    //var hh = new Rectangle { Fill = Fill, Width = 4, Height = 4, Opacity = 1 }.MoveTo(pp_X, pp_Y).AttachTo(this);
                    //history.Enqueue(hh);

                    //foreach (var k in history.Select((c, i) => new { c, i }))
                    //{
                    //    k.c.Opacity = ((double)k.i / historysize) * 0.6;
                    //}

                    //ht.MoveTo(
                    //    DefaultWidth / 2 + pp.X - 4,
                    //    DefaultHeight / 2 + pp.Y + 4
                    //);

                    //ht.Text = new { pp.X, pp.Y, pp.Z }.ToString();
                };

                p.Tag = p_Update;

                a.Add(p);

                p_Update(p);

                return(p);
            };


            Enumerable.Range(0, 10).Select(X => a_Add(X * 10, 0, 0, Brushes.Red)).ToArray();
            Enumerable.Range(0, 10).Select(Y => a_Add(0, Y * 10, 0, Brushes.Blue)).ToArray();
            Enumerable.Range(0, 10).Select(Z => a_Add(0, 0, Z * 10, Brushes.GreenYellow)).ToArray();

            Enumerable.Range(0, 10).Select(X => a_Add(X * 10 + 100, 0, 0, Brushes.Red)).ToArray();
            Enumerable.Range(0, 10).Select(Y => a_Add(100, Y * 10, 0, Brushes.Blue)).ToArray();
            Enumerable.Range(0, 10).Select(Z => a_Add(100, 0, Z * 10, Brushes.GreenYellow)).ToArray();


            Enumerable.Range(0, 100).Select(X => a_Add(X * 10 + 200, 0, 0, Brushes.Red)).ToArray();
            Enumerable.Range(0, 10).Select(Y => a_Add(200, Y * 10, 0, Brushes.Blue)).ToArray();
            Enumerable.Range(0, 10).Select(Z => a_Add(200, 0, Z * 10, Brushes.GreenYellow)).ToArray();

            {
                var radius = 100;
                foreach (var i in Enumerable.Range(0, 90).Select(aa => (aa * 4).DegreesToRadians()))
                {
                    a_Add(Math.Cos(i) * radius, Math.Sin(i) * radius, 0, Brushes.GreenYellow);
                    a_Add(Math.Cos(i) * radius, 0, Math.Sin(i) * radius, Brushes.BlueViolet);
                    a_Add(0, Math.Cos(i) * radius, Math.Sin(i) * radius, Brushes.Magenta);
                }
            }

            {
                var radius = 200;
                foreach (var i in Enumerable.Range(0, 90).Select(aa => (aa * 4).DegreesToRadians()))
                {
                    a_Add(Math.Cos(i) * radius, Math.Sin(i) * radius, 0, Brushes.GreenYellow);
                    a_Add(Math.Cos(i) * radius, 0, Math.Sin(i) * radius, Brushes.BlueViolet);
                    a_Add(0, Math.Cos(i) * radius, Math.Sin(i) * radius, Brushes.Magenta);
                }
            }

            {
                var radius = 500;
                foreach (var i in Enumerable.Range(0, 90).Select(aa => (aa * 4).DegreesToRadians()))
                {
                    a_Add(Math.Cos(i) * radius, Math.Sin(i) * radius, 0, Brushes.GreenYellow);
                    a_Add(Math.Cos(i) * radius, 0, Math.Sin(i) * radius, Brushes.BlueViolet);
                    a_Add(0, Math.Cos(i) * radius, Math.Sin(i) * radius, Brushes.Magenta);
                }
            }

            a_Add(200, 0, 0, Brushes.BlueViolet);
            a_Add(0, 200, 0, Brushes.Yellow);
            a_Add(0, 0, 200, Brushes.Red);

            (1000 / 50).AtIntervalWithCounter(
                c =>
            {
                // rotate floor
                var _a = a.ToRotation(
                    new AffineRotation
                {
                    XY = 0.01,
                    YZ = 0.02,
                    XZ = 0.03
                }
                    );

                //var _a = a.ToRotation(0, 0.01);

                a = _a;

                //var _a = a.ToRotation(c * 0.01, c * 0.005);
                //var _a = a.ToRotation(c * 0.01, 0);

                foreach (var p in _a.Points)
                {
                    ((Action <AffinePoint>)p.Tag)(p);
                }
            }
                );
        }