async void triangleButtonClick()
        {
            ModelVisual3D Triangle;

            this.MainViewPort.Children.Add(Triangle = Get3DTriangle());
            this.MainViewPort.Children.Add(BouncingRectangle.CreatePlane());
            ModelVisual3D modelVisual3D = new ModelVisual3D();

            modelVisual3D.Content = EnvironmentLight;
            this.MainViewPort.Children.Add(modelVisual3D);
            Camera.FarPlaneDistance  = 100;
            Camera.NearPlaneDistance = 1;
            this.MainViewPort.Camera = Camera;
            while (true)
            {
                //for(int i=0;i<60;i++)
                //{
                //    await Task.Delay(10);
                //    EnvironmentLight.Direction = new Vector3D(Math.Cos(Math.PI * 2 * i / 60), Math.Sin(Math.PI * 2 * i / 60), -1);
                //}
                for (int i = 0; i < 60 * 4; i++)
                {
                    await Task.Delay(10);

                    var v = Triangle.Transform.Value;
                    v.Rotate(new Quaternion(new Vector3D(0, 0, 1), 360 * 0.5 / 60));// = new RotateTransform3D(new AxisAngleRotation3D());
                    Triangle.Transform = new MatrixTransform3D(v);
                }
                break;
            }
            Draw();
        }
        int Simulate(BouncingRectangle t, Parameter v)
        {
            //System.Diagnostics.Debug.WriteLine($"Simulate(h={v.height},a={v.angle},r={v.WHratio}){{w={Math.Sin(Math.Atan(v.WHratio))*2},h={Math.Cos(Math.Atan(v.WHratio)) * 2}}}");
            t.Reset(Math.Sin(Math.Atan(v.WHratio)) * 2, Math.Cos(Math.Atan(v.WHratio)) * 2, false);
            var ans = t.Start(v.height, v.angle / 180 * Math.PI, false).Result;

            //System.Diagnostics.Debug.WriteLine("OK");
            return(ans);
        }
 int Query(BouncingRectangle t, Parameter v)
 {
     return(Simulate(t, v));
     //lock (dict)
     //{
     //    if (!dict.ContainsKey(v))
     //    {
     //        if (dict.Count >= maxDictSize) dict.Remove(dict.ElementAt(rand.Next(dict.Count)).Key);
     //        dict.Add(v, Simulate(v));
     //    }
     //    return dict[v];
     //}
 }
        private async void IMGmap_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            if (br != null)
            {
                if (br.GetType() == typeof(BouncingHexagon))
                {
                    (br as BouncingHexagon).Cancel();
                }
                else
                {
                    (br as BouncingRectangle).Cancel();
                }
                br = null;
            }
            var p = new Func <Point, Point>(_ => new Point(_.X / IMGmap.ActualWidth, _.Y / IMGmap.ActualHeight))(e.GetPosition(IMGmap));

            currentValue.x   = minValue.x * (1 - p.X) + maxValue.x * p.X;
            currentValue.y   = minValue.y * (1 - p.Y) + maxValue.y * p.Y;
            LBstatus.Content = currentValue.ToString();
            this.MainViewPort.Children.Clear();
            this.MainViewPort.Children.Add(BouncingRectangle.CreatePlane());
            this.MainViewPort.Children.Add(new ModelVisual3D {
                Content = EnvironmentLight
            });
            System.Threading.Thread.CurrentThread.Priority = System.Threading.ThreadPriority.Highest;
            if (simulateHexagon)
            {
                br = new BouncingHexagon(currentValue.WHratio, 1, true);
                this.MainViewPort.Children.Add(new ModelVisual3D {
                    Content = (br as BouncingHexagon).model
                });
                await(br as BouncingHexagon).Start(currentValue.height, currentValue.angle / 180 * Math.PI);
            }
            else
            {
                br = new BouncingRectangle(Math.Sin(Math.Atan(currentValue.WHratio)) * 2, Math.Cos(Math.Atan(currentValue.WHratio)) * 2, true);
                this.MainViewPort.Children.Add(new ModelVisual3D {
                    Content = (br as BouncingRectangle).model
                });
                await(br as BouncingRectangle).Start(currentValue.height, currentValue.angle / 180 * Math.PI);
            }
            //System.Diagnostics.Debug.WriteLine("OK");
        }