public Task<UBitmap> Generate2D(PlanetContainer planetContainer, Action<float> callBack, bool UseFourThreads)
        {
            Init(planetContainer);

            var token = __CancellationTokenSource.Token;
            return Task<UBitmap>.Factory.StartNew(() =>
            {
                InWork = true;
                var bmp = (UseFourThreads ?
                    Generate2DInFourThreadsSync(planetContainer, callBack, token) :
                    Generate2DInOneThread(planetContainer, callBack, token));

                InWork = false;
                LastGenerationTime = (int)(DateTime.Now - __StartTime).TotalMilliseconds;
                return bmp;
            }, token);
        }
        public UBitmap Generate(PlanetContainer settings, CancellationToken token, int x, int y, int w, int h)
        {
            var pObject = settings.Container2D;

            return Generate(
                settings.Shema,
                settings.Algorithm,
                token,
                x,
                y,
                w,
                h,
                pObject.Width,
                pObject.Height,
                settings.Seeds,
                pObject.Projection,
                pObject.SeaLevel,
                pObject.Lng,
                pObject.Lat);
        }
        private void Import_Click(object sender, RoutedEventArgs e)
        {
            var filePath = WpfHelper.ShowLoadFileDialog(PlanetContainer.FILE_EXTENTION, PlanetContainer.FILE_DESCRIPTION);
            if (string.IsNullOrEmpty(filePath))
                return;

            try
            {
                Settings = JsonHelper.LoadFromFile<PlanetContainer>(filePath);
            }
            catch
            {
                this.ShowMessageAsync("Error", "Invalid file");
                Settings = new PlanetContainer();
            }
        }
        public MainWindow()
        {
            Settings = new PlanetContainer();

            __Instance = this;

            InitializeComponent();

            DataContext = this;

            __PlanetGenerator = new PlanetGenerator();
        }
 private void ListBoxContainer_OnMouseDoubleClick(object sender, MouseButtonEventArgs e)
 {
     Result = ListBoxContainer.SelectedItem as PlanetContainer;
     if (Result != null)
         Close();
 }
        public UBitmap Generate2DInFourThreadsSync(PlanetContainer planetContainer, Action<float> callBack, CancellationToken token)
        {
            const int CORES = 4;

            var container = planetContainer.Container2D;

            __StartTime = DateTime.Now;

            var genTasks = new Task[CORES];
            var bmps = new UColor[CORES][,];

            var pg = new PlanetGeneratorNative[CORES];

            var percents = new float[CORES];

            const int PICTURE_SHIFT = 2;

            var w = container.Width / 2 + PICTURE_SHIFT;
            var h = container.Height / 2 + PICTURE_SHIFT;

            var resultBitmap = new UColor[container.Width, container.Height];

            for (int i = 0; i < CORES; i++)
            {
                var index = i;
                genTasks[i] = new Task(() =>
                {
                    pg[index] = new PlanetGeneratorNative(AlgorithmType.Classic);

                    pg[index].OnProgressChange = p =>
                    {
                        percents[index] = p;

                        callBack?.Invoke(percents.Sum() / CORES);
                    };

                    var lx = w * (index / 2);
                    var ly = h * (index % 2);

                    if (lx > 0)
                        lx -= PICTURE_SHIFT;

                    if (ly > 0)
                        ly -= PICTURE_SHIFT;

                    var uBmp = pg[index].Generate(planetContainer, token, lx, ly, w, h);
                    if (token.IsCancellationRequested)
                        return;
                    var tmpBmp = uBmp.Map;
                    bmps[index] = tmpBmp;
                }, token);
            }

            for (int i = 0; i < CORES; i++)
                genTasks[i].Start();

            Task.WaitAll(genTasks);

            if (token.IsCancellationRequested)
                return null;

            for (int i = 0; i < CORES; i++)
            {
                var lw = w - PICTURE_SHIFT;
                var lh = h - PICTURE_SHIFT;

                var lx = (i / 2) * lw;
                var ly = (i % 2) * lh;

                var dx = lx > 0 ? PICTURE_SHIFT : 0;
                var dy = ly > 0 ? PICTURE_SHIFT : 0;

                for (int x = 0; x < lw; x++)
                    for (int y = 0; y < lh; y++)
                        resultBitmap[lx + x, ly + y] = bmps[i][x + dx, y + dy];
            }

            return new UBitmap(resultBitmap);
        }
        private void Init(PlanetContainer planetContainer)
        {
            if (planetContainer == null)
                throw new ArgumentNullException(nameof(planetContainer));
            if (InWork)
                throw new InvalidOperationException("generation just started");

            __CancellationTokenSource = new CancellationTokenSource();

            __StartTime = DateTime.Now;
            WasStoped = false;
        }
        private UBitmap Generate2DInOneThread(PlanetContainer planetContainer, Action<float> callBack, CancellationToken token)
        {
            var pc = planetContainer;
            var generator = new PlanetGeneratorNative(pc.Algorithm);

            generator.OnProgressChange += callBack;

            return generator.Generate(pc, token);
        }
        private void FillSphereOptimize(SphereModel model, PlanetContainer settings,
            Dictionary<int, List<RefTriengleOptimize>> triengles)
        {
            var container = settings.Container3D;
            var lastRank = container.RecursionLevel;

            var cc = new ColorContainer(settings.Shema.Layers[0], __NativeGenerator.GetAltRange());
            var optimazeLevel = container.OptimizePecent * 0.01f;
            var lastTriengles = triengles[lastRank];

            foreach (var triengle in lastTriengles)
                triengle.IsOk = true;

            var points = lastTriengles
                .SelectMany(e => e.Points)
                .Distinct();

            foreach (var pointIndex in points)
            {
                var p = model.Points[pointIndex];

                byte s;
                var alt = __NativeGenerator.GetAlt(p.X, p.Y, p.Z, 100, out s);

                if (alt > 0)
                    p *= (1 + (float)alt * container.LandscapeOver);
                else
                    p *= (1 + (float)alt * container.LandscapeUnder);

                var color = cc.GetColor(alt);

                model.Colors[pointIndex] = color;
                model.Points[pointIndex] = p;
            }

            var forProcess = lastTriengles;

            while (forProcess.Count > 0)
            {
                var nextWave = new List<RefTriengleOptimize>();

                foreach (var t in forProcess.Where(e => e.Parent != null && e.Rank > 2))
                {
                    if (t.Optimize(model, optimazeLevel))
                        nextWave.Add(t.Parent);
                }

                forProcess = nextWave;
            }

            var refResult = triengles
                .SelectMany(e => e.Value)
                .Where(e => e.IsOk).ToList();

            foreach (var t in refResult)
                t.FixLines(model);

            model.Triengles = refResult
                .Select(e => e.Triengle)
                .ToList();
        }
        private void FillSphere(SphereModel model, PlanetContainer settings)
        {
            var container = settings.Container3D;
            var cc = new ColorContainer(settings.Shema.Layers[0], __NativeGenerator.GetAltRange());
            var len = model.Points.Count;

            for (int i = 0; i < len; i++)
            {
                var p = model.Points[i];
                byte s;
                var alt = __NativeGenerator.GetAlt(p.X, p.Y, p.Z, 100, out s);

                if (alt > 0)
                    p *= (1 + (float)alt * container.LandscapeOver);
                else
                    p *= (1 + (float)alt * container.LandscapeUnder);

                var color = cc.GetColor(alt);

                model.Colors[i] = color;
                model.Points[i] = p;
            }
        }
        public Task<SphereModel> Generate3D(PlanetContainer planetContainer, Action<float> callBack)
        {
            Init(planetContainer);

            __NativeGenerator = new GClassic();
            __NativeGenerator.Initialize(planetContainer.Seeds[0], ShadeType.None);

            SphereModel model;

            var container = planetContainer.Container3D;

            var token = __CancellationTokenSource.Token;
            return Task<SphereModel>.Factory.StartNew(() =>
            {
                InWork = true;

                if (container.Optimize)
                {
                    var res = GetOptimizeSkeleton(container.RecursionLevel, token);

                    if (token.IsCancellationRequested)
                        return null;

                    model = res.Item1;

                    FillSphereOptimize(model, planetContainer, res.Item2);

                    model.RemoveUselessPoints();
                }
                else
                {
                    model = GetSkeletone(container.RecursionLevel, token);

                    if (token.IsCancellationRequested)
                        return null;

                    FillSphere(model, planetContainer);
                }

                InWork = false;
                LastGenerationTime = (int)(DateTime.Now - __StartTime).TotalMilliseconds;
                return model;
            }, token);
        }
        public static PlanetContainer GetDesert()
        {
            var result = new PlanetContainer { Name = "Desert" };

            var shema = new Shema();

            var layer = new ShemaLayer { Shade = ShadeType.OnlyLand, Level = 0 };

            layer.Add(0, new UColor(0xFFCD853F));
            layer.Add(250, new UColor(0xFFCD853F));
            layer.Add(500, new UColor(0xFFF4A460));
            layer.Add(627, new UColor(0xFF8B4513));
            layer.Add(1000, new UColor(0xFFDEB887));

            shema.Layers.Add(layer);

            layer = new ShemaLayer { Shade = ShadeType.None, Level = 1 };

            layer.Add(0, new UColor(0));
            layer.Add(400, new UColor(0x00FFFFFF));
            layer.Add(500, new UColor(0xD0FFDEAD));
            layer.Add(600, new UColor(0x00FFFFFF));
            layer.Add(700, new UColor(0xD0FFDEAD));
            layer.Add(800, new UColor(0x00FFFFFF));
            layer.Add(1000, new UColor(0));

            shema.Layers.Add(layer);

            result.Shema = shema;
            return result;
        }
        public static PlanetContainer GetSun()
        {
            var result = new PlanetContainer { Name = "Sun" };

            var shema = new Shema();

            var layer = new ShemaLayer { Shade = ShadeType.None, Level = 0 };

            layer.Add(0, new UColor(0xFFFF0000));
            layer.Add(1000, new UColor(0xFFFFFF00));

            shema.Layers.Add(layer);

            result.Shema = shema;

            return result;
        }
        public static PlanetContainer GetPandorica()
        {
            var result = new PlanetContainer { Name = "Pandorica" };

            var shema = new Shema();

            var layer = new ShemaLayer { Shade = ShadeType.OnlyLand, Level = 0 };

            layer.Add(0, new UColor(0xFF000000));
            layer.Add(0x80 * 5, new UColor(0xFF483D8B));
            layer.Add(0x87 * 5, new UColor(0xFF8470FF));
            layer.Add(0x9A * 5, new UColor(0xFFEEDD82));
            layer.Add(0xBD * 5, new UColor(0xFF6B8E23));
            layer.Add(0xFF * 5, new UColor(0xFF000000));

            shema.Layers.Add(layer);

            layer = new ShemaLayer { Shade = ShadeType.None, Level = 1 };

            layer.Add(0, new UColor(0));
            layer.Add(0x60 * 5, new UColor(0));
            layer.Add(0x61 * 5, new UColor(0x20FFFFFF));
            layer.Add(0x88 * 5, new UColor(0xB0FFFFFF));
            layer.Add(0x98 * 5, new UColor(0xB0FFFFFF));
            layer.Add(0xD0 * 5, new UColor(0x20FFFFFF));
            layer.Add(0xD1 * 5, new UColor(0));
            layer.Add(0xFF * 5, new UColor(0));

            shema.Layers.Add(layer);

            result.Shema = shema;

            return result;
        }
        public static PlanetContainer GetIce()
        {
            var result = new PlanetContainer { Name = "Ice" };

            var shema = new Shema();

            var layer = new ShemaLayer { Shade = ShadeType.OnlyLand, Level = 0 };

            layer.Add(0, new UColor(0xFF000000));
            layer.Add(0x30, new UColor(0xFF1A1BAF));
            layer.Add(0x60 * 5, new UColor(0xFF00BBFF));
            layer.Add(0x80 * 5, new UColor(0xFF0000FF));
            layer.Add(0x91 * 5, new UColor(0xFF000000));
            layer.Add(0xC0 * 5, new UColor(0xFF5C5C9C));
            layer.Add(0xFF * 5, new UColor(0xFF8FAFFF));

            shema.Layers.Add(layer);
            result.Shema = shema;
            return result;
        }