public static Bathymetry Extract(string databaseFile, string extractionProgram, float selectedResolution, GeoRect region, PercentProgress progress = null)
        {
            if (progress != null)
            {
                progress.MaximumValue = 4;
                progress.Report(0);
            }

            var outputPath = Path.GetTempFileName();
            outputPath = outputPath.Remove(outputPath.Length - 4, 4);

            var outputDirectory = Path.GetDirectoryName(outputPath);
            var commandArgs = string.Format(" area \"{0}\" 0.05min 2.00min nearest 0 meters G {1} {2} {3} {4} {5:0.0##} YXZ=\"{6}\"", 
                databaseFile, region.South, region.West, region.North, region.East, selectedResolution, string.Format("{0}.yxz", Path.GetFileName(outputPath)));
            //extract the area and look for success or failure in the output string.

            if (progress != null) lock (progress) progress.Report(1);

            var result = NAVOExtractionProgram.Execute(extractionProgram, commandArgs, outputDirectory).Result;
            var resarray = result.Split('\n');
            foreach (var line in resarray.Where(line => line.Contains("ERROR"))) throw new ApplicationException("DigitalBathymetricDatabase: Error extracting requested area: " + line);

            if (progress != null) lock (progress) progress.Report(2);

            var bathymetry = Bathymetry.FromYXZ(Path.Combine(outputPath + ".yxz"), -1);
            bathymetry.Samples.TrimToNearestPoints(region);
            if (progress != null) lock (progress) progress.Report(3);

            File.Delete(outputPath + ".yxz");
            File.Delete(outputPath + ".yxz_SECURITY_README.txt");

            if (progress != null) lock (progress) progress.Report(4);
            return bathymetry;
        }
 public DbGeoRect(GeoRect geoRect)
 {
     North = geoRect.North;
     South = geoRect.South;
     East = geoRect.East;
     West = geoRect.West;
 }
 public void AreEqual()
 {
     var rect1 = new GeoRect(44, 41, -69, -72);
     var rect2 = new GeoRect(44, 41, -69, -72);
     var rect3 = new GeoRect(41, 44, -60, -70);
     Assert.IsTrue(rect1.Equals(rect2));
     Assert.IsFalse(rect1.Equals(rect3));
 }
 public void PropertyChangedTest()
 {
     var geoRect = new GeoRect(44, 41, -69, -72);
     Post.Cast<GeoRect, INotifyPropertyChanged>(geoRect).PropertyChanged += (s, e) => Console.WriteLine("PropertyChanged: {0}", e.PropertyName);
     var insideGeo = new Geo(42, -70);
     var outsideGeo = new Geo(0, 0);
     Assert.IsTrue(geoRect.Contains(insideGeo));
     Assert.IsFalse(geoRect.Contains(outsideGeo));
     Console.WriteLine("Setting North to 45");
     geoRect.North = 45;
 }
 public void StaticDensitySeed()
 {
     var geoRect = new GeoRect(1, -1, 1, -1);
     var bathymetry = new Bathymetry();
     bathymetry.Samples.Add(new Geo<float>(geoRect.Center.Latitude,geoRect.Center.Longitude,100));
     var list = Animat.Seed(new ScenarioSpecies{LatinName = "Orca orca", PopulationDensity = .2f}, geoRect,bathymetry);
     foreach (var animatLocation in list.Locations)
     {
         Assert.IsTrue(geoRect.Contains(animatLocation));
         Assert.IsTrue(animatLocation.Data < 100 && animatLocation.Data > 0);
     }
 }
 public OverlayLineSegments(GeoRect geoRect) : base(Colors.Black, 1f, LineStyle.Solid)
 {
     Segments = new List<OverlayLineSegment>();
     Add(geoRect.SouthWest);
     Add(geoRect.SouthEast);
     Add(geoRect.NorthEast);
     Add(geoRect.NorthWest);
     Add(geoRect.SouthWest);
     CreateSegments();
     ComputeBoundingBox();
     CheckForClosure();
     CheckCrossingSegments();
 }
        public void UnionGeo()
        {
            var baseRect = new GeoRect(43, 41, -69, -71);
            var containedWithin = new Geo(42, -70);
            var onWesternEdge = new Geo(42, -71);
            var onCorner = new Geo(43, -69);
            var outside = new Geo(44, -60);

            Assert.IsTrue(GeoRect.Union(baseRect,containedWithin).Equals(baseRect));
            Assert.IsTrue(GeoRect.Union(baseRect, onWesternEdge).Equals(baseRect));
            Assert.IsTrue(GeoRect.Union(baseRect, onCorner).Equals(baseRect));
            Assert.IsFalse(GeoRect.Union(baseRect,outside).Equals(baseRect));
            Assert.IsTrue(GeoRect.Union(baseRect,outside).Equals(new GeoRect(44,41,-60,-71)));
        }
        public ColorMapHelper(WarpedDataSource2D<double> field, Box2 regionBox, double minT, double maxT)
        {
            this.minT = minT;
            this.maxT = maxT;

            warpedField = field;

            if (regionBox != null)
            {
                this.tileBox = new GeoRect(
                    regionBox.MinCoordinate.X, regionBox.MinCoordinate.Y,
                    regionBox.MaxCoordinate.X - regionBox.MinCoordinate.X,
                    regionBox.MaxCoordinate.Y - regionBox.MinCoordinate.Y);
                this.regionBox = regionBox;
            }

            System.Windows.Point[,] grid = warpedField.Grid;

            Coordinate2D minCoordinate = new Coordinate2D(grid[0, 0].X, grid[0, 0].Y);
            Coordinate2D maxCoordinate = new Coordinate2D(grid[warpedField.Width - 1, warpedField.Height - 1].X, grid[warpedField.Width - 1, warpedField.Height - 1].Y);


            for (int j = 0; j < warpedField.Height; j++)
            {
                for (int i = 0; i < warpedField.Width; i++)
                {
                    if (grid[i, j].X < minCoordinate.X)
                        minCoordinate.X = grid[i, j].X;

                    if (grid[i, j].X > maxCoordinate.X)
                        maxCoordinate.X = grid[i, j].X;

                    if (grid[i, j].Y < minCoordinate.Y)
                        minCoordinate.Y = grid[i, j].Y;

                    if (grid[i, j].Y > maxCoordinate.Y)
                        maxCoordinate.Y = grid[i, j].Y;
                }
            }

            gridBox = new GeoRect(
                minCoordinate.X,
                minCoordinate.Y,
                maxCoordinate.X - minCoordinate.X,
                maxCoordinate.Y - minCoordinate.Y);

            palette = new LinearPalette(swm.Colors.Blue, swm.Colors.Green, swm.Colors.Red);
            workingTriangle = new RasterTriangle();
        }
        public void UnionRect()
        {
            var baseRect = new GeoRect(43, 41, -69, -71);
            var containedWithin = new GeoRect(42.5, 41.5, -69.5, -70.5);
            var alsoContained = new GeoRect(42.5, 41.5, -69.5, -70.5);
            var array = new[] { baseRect, containedWithin, alsoContained };
            Assert.IsTrue(GeoRect.Union(baseRect, containedWithin).Equals(baseRect));
            Assert.IsTrue(GeoRect.Union(array).Equals(baseRect));

            var disjoint = new GeoRect(44, 42, -72, -74);
            Assert.IsTrue(GeoRect.Union(baseRect,disjoint).Equals(new GeoRect(44,41,-69,-74)));

            var overlaps = new GeoRect(44, 42, -68, -70);
            Assert.IsTrue(GeoRect.Union(overlaps,baseRect).Equals(new GeoRect(44,41,-68,-71)));
        }
        public void ConstructionTest()
        {
            var rect1 = new GeoRect(44, 41, -69, -72);
            var rect2 = new GeoRect(44, 41, -69, -72);
            Assert.IsTrue(rect1.Equals(rect2));

            var rect3 = new GeoRect(rect1);
            Assert.IsTrue(rect1.Equals(rect3));

            var rect4 = new GeoRect(new List<Geo>
                                        {
                                            new Geo(44, -69),
                                            new Geo(41, -72),
                                        });
            Assert.IsTrue(rect1.Equals(rect4));
        }
        public static Animat Seed(ScenarioSpecies species, GeoRect geoRect, Bathymetry bathymetry)
        {
            var bounds = new GeoArray(geoRect.NorthWest, geoRect.NorthEast, geoRect.SouthEast, geoRect.SouthWest, geoRect.NorthWest);
            var result = new Animat { ScenarioSpecies = species };

            var area = bounds.Area;
            //Debug.WriteLine("Area: {0}",area);
            var population = (int)Math.Floor(area * species.PopulationDensity);
            for (var i = 0; i < population; i++)
            {
                var location = bounds.RandomLocationWithinPerimeter();
                var depth = bathymetry.Samples.GetNearestPoint(location).Data;
                if (depth < 0) result.Locations.Add(new Geo<float>(location.Latitude, location.Longitude, (float)(depth * Random.NextDouble())));
            }
            result.TotalAnimats = population;
            return result;
        }
 Location CreateLocation(string locationName, string comments, GeoRect geoRect)
 {
     var existing = (from l in Globals.MasterDatabaseService.Context.Locations
                     where l.Name == locationName
                     select l).FirstOrDefault();
     if (existing != null) throw new DuplicateNameException(String.Format("A location named {0} already exists, choose another name", locationName));
     var location = new Location
     {
         Name = locationName,
         Comments = comments,
         GeoRect = geoRect,
         LayerSettings = { IsChecked = true, LineOrSymbolSize = 5 }
     };
     Globals.MasterDatabaseService.Context.Locations.Local.Add(location);
     location.UpdateMapLayers();
     return location;
 }
 public async static Task<Animat> SeedAsyncWithout3MB(ScenarioSpecies species, GeoRect geoRect, Bathymetry bathymetry)
 {
     var bounds = new GeoArray(geoRect.NorthWest, geoRect.NorthEast, geoRect.SouthEast, geoRect.SouthWest, geoRect.NorthWest);
     var result = new Animat { ScenarioSpecies = species };
     
     var area = bounds.Area;
     //Debug.WriteLine("Area: {0}",area);
     var transformManyBlock = new TransformManyBlock<int, Geo<float>>(count =>
     {
         var geos = new List<Geo<float>>();
         for (var i = 0; i < count; i++)
         {
             var location = bounds.RandomLocationWithinPerimeter();
             var depth = bathymetry.Samples.GetNearestPointAsync(location).Result.Data;
             if (depth < -50) geos.Add(new Geo<float>(location.Latitude, location.Longitude, (float)(depth * Random.NextDouble())));
         }
         return geos;
     }, new ExecutionDataflowBlockOptions
     {
         TaskScheduler = TaskScheduler.Default,
         BoundedCapacity = -1,
         MaxDegreeOfParallelism = -1,
     });
     var bufferBlock = new BufferBlock<Geo<float>>();
     transformManyBlock.LinkTo(bufferBlock);
     var population = (int)Math.Round(area * species.PopulationDensity);
     result.TotalAnimats = population;
     const int blockSize = 100;
     while (population > 0)
     {
         transformManyBlock.Post(population > blockSize ? blockSize : population);
         population -= blockSize;
     }
     transformManyBlock.Complete();
     await transformManyBlock.Completion;
     IList<Geo<float>> animatGeos;
     if (bufferBlock.TryReceiveAll(out animatGeos))
         result.Locations.AddRange(animatGeos);
     return result;
 }
        public ColorMapHelper(NonUniformDataSource2D<double> field, Box2 regionBox, double minT, double maxT)
        {
            this.minT = minT;
            this.maxT = maxT;

            this.gridBox = new GeoRect(
                Math.Min(field.X[0], field.X[field.Width - 1]),
                Math.Min(field.Y[0], field.Y[field.Height - 1]),
                Math.Abs(field.X[field.Width - 1] - field.X[0]),
                Math.Abs(field.Y[field.Height - 1] - field.Y[0]));

            if (regionBox != null)
            {
                this.tileBox = new GeoRect(
                    regionBox.MinCoordinate.X, regionBox.MinCoordinate.Y,
                    regionBox.MaxCoordinate.X - regionBox.MinCoordinate.X,
                    regionBox.MaxCoordinate.Y - regionBox.MinCoordinate.Y);
            }

            palette = new LinearPalette(swm.Colors.Blue, swm.Colors.Green, swm.Colors.Red);

            this.field = field;
        }
        public static Sediment Extract(string bstDirectory, GeoRect region, float resolution, PercentProgress progress = null)
        {
            if (progress != null) lock (progress) progress.Report(0);

            var north = (float)Math.Round(region.North + 1);
            var south = (float)Math.Round(region.South - 1);
            var east = (float)Math.Round(region.East + 1);
            var west = (float)Math.Round(region.West - 1);

            if (progress != null) progress.MaximumValue = (((north - south) * (east - west)) + 3);
            var totalProgress = 0;

            var fileId = H5F.open(bstDirectory, H5F.OpenMode.ACC_RDONLY);
            var highResGroup = H5G.open(fileId, "0.10000/G/UNCLASSIFIED/");
            var lowResGroup = H5G.open(fileId, "5.00000/G/UNCLASSIFIED/");
            var dedupeList = new HashedArrayList<SedimentSample>();
            for (var lat = south; lat < north; lat++)
                for (var lon = west; lon < east; lon++)
                {
                    //var data = ReadDataset(highResGroup, 0.1, lowResGroup, 5.0, resolution, (int)lat, (int)lon);
                    var data = ReadDatasetHierarchical(highResGroup, 0.1, lowResGroup, 5.0, resolution, (int)lat, (int)lon);
                    if (data != null) dedupeList.AddAll(data);
                    if (progress != null) lock (progress) progress.Report(totalProgress++);
                }
            var sediment = new Sediment();
            if (progress != null) lock (progress) progress.Report(totalProgress++);
            sediment.Samples.AddRange(dedupeList);
            sediment.Samples.Sort();
            sediment.Samples.TrimToNearestPoints(region);
            if (progress != null) lock (progress) progress.Report(totalProgress++);
            if (lowResGroup != null) H5G.close(lowResGroup);
            if (highResGroup != null) H5G.close(highResGroup);
            H5F.close(fileId);
            if (progress != null) lock (progress) progress.Report(totalProgress);
            return sediment;
        }
        public RasterPatch2 GetTilePatch(PointSet pointSet, Box2 regionBox, double iconSize)
        {
            GeoRect tileBox = new GeoRect(
                regionBox.MinCoordinate.X,
                regionBox.MinCoordinate.Y,
                regionBox.MaxCoordinate.X - regionBox.MinCoordinate.X,
                regionBox.MaxCoordinate.Y - regionBox.MinCoordinate.Y);

            int width = 256;
            int height = 256;
            Bitmap resultBitmap = new Bitmap(width, height);
            Graphics graphics = Graphics.FromImage(resultBitmap);

            double minT = 0, maxT = 0, k;
            if (!Double.IsNaN(pointSet.MaxValue))
            {
                minT = pointSet.MinValue;
                maxT = pointSet.MaxValue;
                k = 1.0 / (maxT - minT);
            }
            else
                k = Double.NaN;

            ColorMatrix colorMatrix = new ColorMatrix();
            ImageAttributes imageAttributes = new ImageAttributes();


            for (int i = 0; i < pointSet.Data.Count; i++)
            {
                GeoRect workingRect = new GeoRect(
                            pointSet.Data[i].Longitude - iconSize / 2.0,
                            pointSet.Data[i].Latitude - iconSize / 2.0,
                            iconSize,
                            iconSize);

                if (GeoRect.IntersectionExist(workingRect, tileBox))
                {
                    int x0 = (int)(Math.Min(width, Math.Max(0, pointSet.Data[i].Longitude - iconSize / 2.0 - tileBox.Left) / tileBox.Width * width));
                    int y0 = (int)(Math.Min(height, Math.Max(0, tileBox.Top - pointSet.Data[i].Latitude - iconSize / 2.0) / tileBox.Height * height));

                    int x1 = (int)(Math.Min(width, Math.Max(0, pointSet.Data[i].Longitude + iconSize / 2.0 - tileBox.Left) / tileBox.Width * width));
                    int y1 = (int)(Math.Min(height, Math.Max(0, tileBox.Top - pointSet.Data[i].Latitude + iconSize / 2.0) / tileBox.Height * height));

                    double widthX = Math.Min(tileBox.Width, iconSize);
                    double heightY = Math.Min(tileBox.Height, iconSize);



                    lock (icon)
                    {
                        System.Windows.Media.Color tempColor = System.Windows.Media.Brushes.Red.Color;
                        if (!Double.IsNaN(k))
                        {
                            double hue = 270 * ((maxT - (double)pointSet.Data[i].Value) * k);
                            tempColor = new HsbColor(hue, 1, 1, 0.8).ToArgb();
                        }

                        colorMatrix.Matrix00 = (float)tempColor.R / 255f;
                        colorMatrix.Matrix11 = (float)tempColor.G / 255f;
                        colorMatrix.Matrix22 = (float)tempColor.B / 255f;


                        imageAttributes.SetColorMatrix(colorMatrix,
                                                ColorMatrixFlag.Default,
                                                ColorAdjustType.Bitmap);

                        int x2 = 0;
                        if (pointSet.Data[i].Longitude - iconSize / 2.0 < tileBox.Left)
                        {
                            x2 = icon.Width - (int)((double)(x1 - x0) * icon.Width / (widthX / tileBox.Width * width));
                        }

                        int y2 = 0;
                        if (tileBox.Top - pointSet.Data[i].Latitude - iconSize / 2.0 < 0)
                        {
                            y2 = icon.Height - (int)((double)(y1 - y0) * icon.Height / (heightY / tileBox.Height * height));
                        }

                        graphics.DrawImage(
                            icon,
                            new Rectangle(x0, y0, x1 - x0, y1 - y0),
                            x2,
                            y2,
                            (int)((double)(x1 - x0) * icon.Width / (widthX / tileBox.Width * width)),
                            (int)((double)(y1 - y0) * icon.Height / (heightY / tileBox.Height * height)),
                            GraphicsUnit.Pixel, imageAttributes);
                    }

                }
            }
            return new RasterPatch2(
                    regionBox,
                    resultBitmap,
                    Wgs84CoordinateReferenceSystem.Instance);
        }
        public ProbesDataSource(Guid guid, IDataSource2D<double> field, Host host)
            : base(guid)
        {
            // set up the Ontology, a description of the kind of data we contain.
            // See DataSource sample for more details.
            OntologySpecification o = this.Ontology.Edit();
            o.PrimitiveTypes.Create("RasterPatch", "GeoEntity", typeof(RasterPatch2));
            this.UpdateOntology(o);

            EntitySpecification entitySpec = new EntitySpecification(this.Ontology.EntityTypes["GeoEntity"]); // the default entity type
            entity = this.EntityAuthorityReference.EntityAuthority.CreateEntity(true, entitySpec);

            this.wfield = field;

            System.Windows.Point[,] grid = wfield.Grid;
            Coordinate2D minCoordinate = new Coordinate2D(grid[0, 0].X, grid[0, 0].Y);
            Coordinate2D maxCoordinate = new Coordinate2D(grid[field.Width - 1, field.Height - 1].X, grid[field.Width - 1, field.Height - 1].Y);


            for (int j = 0; j < field.Height; j++)
            {
                for (int i = 0; i < field.Width; i++)
                {
                    if (grid[i, j].X < minCoordinate.X)
                        minCoordinate.X = grid[i, j].X;

                    if (grid[i, j].X > maxCoordinate.X)
                        maxCoordinate.X = grid[i, j].X;

                    if (grid[i, j].Y < minCoordinate.Y)
                        minCoordinate.Y = grid[i, j].Y;

                    if (grid[i, j].Y > maxCoordinate.Y)
                        maxCoordinate.Y = grid[i, j].Y;
                }
            }

            gridBox = new GeoRect(
                minCoordinate.X,
                minCoordinate.Y,
                maxCoordinate.X - minCoordinate.X,
                maxCoordinate.Y - minCoordinate.Y);

            dataType = DSDataType.TwoDim;
            this.host = host;

            probesHelper = new ProbesHelper("ProbeSample.png", false);
        }
 public void ContainsGeo()
 {
     var baseRect = new GeoRect(43, 41, -69, -71);
     var containedWithin = new Geo(42, -70);
     Assert.IsTrue(baseRect.Contains(containedWithin));
 }
        public RasterPatch2 GetTilePatch(IDataSource2D<double> field, Box2 regionBox, double iconSize)
        {
            System.Windows.Point[,] grid = field.Grid;

            Coordinate2D minCoordinate = new Coordinate2D(grid[0, 0].X, grid[0, 0].Y);
            Coordinate2D maxCoordinate = new Coordinate2D(grid[field.Width - 1, field.Height - 1].X, grid[field.Width - 1, field.Height - 1].Y);


            for (int j = 0; j < field.Height; j++)
            {
                for (int i = 0; i < field.Width; i++)
                {
                    if (grid[i, j].X < minCoordinate.X)
                        minCoordinate.X = grid[i, j].X;

                    if (grid[i, j].X > maxCoordinate.X)
                        maxCoordinate.X = grid[i, j].X;

                    if (grid[i, j].Y < minCoordinate.Y)
                        minCoordinate.Y = grid[i, j].Y;

                    if (grid[i, j].Y > maxCoordinate.Y)
                        maxCoordinate.Y = grid[i, j].Y;
                }
            }

            GeoRect gridBox = new GeoRect(
                minCoordinate.X,
                minCoordinate.Y,
                maxCoordinate.X - minCoordinate.X,
                maxCoordinate.Y - minCoordinate.Y);

            GeoRect tileBox = new GeoRect(
                regionBox.MinCoordinate.X,
                regionBox.MinCoordinate.Y,
                regionBox.MaxCoordinate.X - regionBox.MinCoordinate.X,
                regionBox.MaxCoordinate.Y - regionBox.MinCoordinate.Y);

            GeoRect intersectionRect = GeoRect.Intersect(gridBox, tileBox);

            if (intersectionRect != null)
            {
                int width = 256;
                int height = 256;
                Bitmap resultBitmap = new Bitmap(width, height);
                Graphics graphics = Graphics.FromImage(resultBitmap);
                for (int i = 0; i < field.Width; i++)
                {
                    for (int j = 0; j < field.Height; j++)
                    {
                        GeoRect workingRect = new GeoRect(
                            field.Grid[i, j].X - iconSize / 2.0,
                            field.Grid[i, j].Y - iconSize / 2.0,
                            iconSize,
                            iconSize);
                        if (GeoRect.IntersectionExist(workingRect, intersectionRect))
                        {
                            int x0 = (int)(Math.Min(width, Math.Max(0, field.Grid[i, j].X - iconSize / 2.0 - tileBox.Left) / tileBox.Width * width));
                            int y0 = (int)(Math.Min(height, Math.Max(0, tileBox.Top - field.Grid[i, j].Y - iconSize / 2.0) / tileBox.Height * height));

                            int x1 = (int)(Math.Min(width, Math.Max(0, field.Grid[i, j].X + iconSize / 2.0 - tileBox.Left) / tileBox.Width * width));
                            int y1 = (int)(Math.Min(height, Math.Max(0, tileBox.Top - field.Grid[i, j].Y + iconSize / 2.0) / tileBox.Height * height));

                            double widthX = Math.Min(tileBox.Width, iconSize);
                            double heightY = Math.Min(tileBox.Height, iconSize);


                            lock (icon)
                            {
                                int x2 = 0;
                                if (field.Grid[i, j].X - iconSize / 2.0 < tileBox.Left)
                                {
                                    x2 = icon.Width - (int)((double)(x1 - x0) * icon.Width / (widthX / tileBox.Width * width));
                                }

                                int y2 = 0;
                                if (tileBox.Top - field.Grid[i, j].Y - iconSize / 2.0 < 0)
                                {
                                    y2 = icon.Height - (int)((double)(y1 - y0) * icon.Height / (heightY / tileBox.Height * height));
                                }

                                graphics.DrawImage(
                                    icon,
                                    new Rectangle(x0, y0, x1 - x0, y1 - y0),
                                    x2,
                                    y2,
                                    (int)((double)(x1 - x0) * icon.Width / (widthX / tileBox.Width * width)),
                                    (int)((double)(y1 - y0) * icon.Height / (heightY / tileBox.Height * height)),
                                    GraphicsUnit.Pixel);
                            }
                        }

                    }
                }
                return new RasterPatch2(
                    regionBox,
                    resultBitmap,
                    Wgs84CoordinateReferenceSystem.Instance);
            }
            else
            {
                return null;
            }
        }
        void AddPerimeter(Scenario scenario)
        {
            try
            {
                var locationGeoRect = (GeoRect)Scenario.Location.GeoRect;
                var initialGeoRect = new GeoRect((locationGeoRect.North + locationGeoRect.Center.Latitude) / 2,
                                                 (locationGeoRect.South + locationGeoRect.Center.Latitude) / 2,
                                                 (locationGeoRect.East + locationGeoRect.Center.Longitude) / 2,
                                                 (locationGeoRect.West + locationGeoRect.Center.Longitude) / 2);
                MapViewModel.EditablePolygonOverlayViewModel.GeoArray = new GeoArray(initialGeoRect.NorthWest, initialGeoRect.NorthEast, initialGeoRect.SouthEast, initialGeoRect.SouthWest, initialGeoRect.NorthWest);
                MapViewModel.EditablePolygonOverlayViewModel.IsVisible = true;
                MapViewModel.EditablePolygonOverlayViewModel.LocationBounds = locationGeoRect;
                MapViewModel.EditablePolygonOverlayViewModel.AreCrossingSegmentsAllowed = false;

                Globals.VisualizerService.ShowWindow("CreateOrEditPerimeterView",
                                       new CreateOrEditPerimeterViewModel { EditablePolygonOverlayViewModel = MapViewModel.EditablePolygonOverlayViewModel, PerimeterName = "New perimeter", DialogTitle = "Create perimeter" },
                                       true,
                                       (sender, args) =>
                                       {
                                           MapViewModel.EditablePolygonOverlayViewModel.IsVisible = false;
                                           var vm = (CreateOrEditPerimeterViewModel)args.State;
                                           if (vm.IsCanceled) return;
                                           Perimeter perimeter = MapViewModel.EditablePolygonOverlayViewModel.GeoArray;
                                           perimeter.Name = vm.PerimeterName;
                                           perimeter.Scenario = Scenario;
                                           Scenario.Perimeters.Add(perimeter);
                                           perimeter.UpdateMapLayers();
                                           perimeter.LayerSettings.IsChecked = true;
                                       });
                OnPropertyChanged("IsSaveScenarioCommandEnabled");
            }
            catch (Exception e) { Globals.MessageBoxService.ShowError(e.Message); }
        }
 public void ContainsRect()
 {
     var baseRect = new GeoRect(43, 41, -69, -71);
     var containedWithin = new GeoRect(42.5, 41.5, -69.5, -70.5);
     Assert.IsTrue(baseRect.Contains(containedWithin));
 }
 void SetMapExtent(GeoRect geoRect) { CurrentExtent = geoRect; }
        public async static Task<Animat> SeedAsync(ScenarioSpecies species, GeoRect geoRect, Bathymetry bathymetry)
        {
            var yxzFileName = Path.Combine(Path.GetTempPath(), Path.GetFileNameWithoutExtension(Path.GetRandomFileName()) + ".txt");
            bathymetry.ToYXZ(yxzFileName, -1);
            var mbs = new C3mbs();
            mbsRESULT mbsResult;
            if (mbsRESULT.OK != (mbsResult = mbs.SetOutputDirectory(Path.GetTempPath())))
                throw new AnimatInterfaceMMBSException("SetOutputDirectory Error:" + mbs.ResultToTc(mbsResult));
            var config = mbs.GetConfiguration();
            config.enabled = false;             // binary output enabled/disabled
            config.durationLess = true;         // make sure we're in durationless mode.
            mbs.SetConfiguration(config);
            mbsResult = mbs.LoadBathymetryFromTextFile(yxzFileName);
            if (mbsRESULT.OK != mbsResult) throw new AnimatInterfaceMMBSException("Bathymetry failed to load: " + mbs.ResultToTc(mbsResult));
            mbsResult = mbs.AddSpecies(species.SpeciesDefinitionFilePath);
            if (mbsRESULT.OK != mbsResult) throw new AnimatInterfaceMMBSException(string.Format("C3mbs::AddSpecies FATAL error {0} for species {1}", mbs.ResultToTc(mbsResult), species.SpeciesDefinitionFilePath));

            var bounds = new GeoArray(geoRect.NorthWest, geoRect.NorthEast, geoRect.SouthEast, geoRect.SouthWest, geoRect.NorthWest);
            var result = new Animat { ScenarioSpecies = species };
            
            var area = bounds.Area;
            //Debug.WriteLine("Area: {0}",area);
            var transformManyBlock = new TransformManyBlock<int, Geo<float>>(count =>
            {
                var geos = new List<Geo<float>>();
                for (var i = 0; i < count; i++)
                {
                    var location = bounds.RandomLocationWithinPerimeter();
                    var depth = bathymetry.Samples.GetNearestPointAsync(location).Result.Data;
                    mbsRESULT retval;
                    lock (mbs) retval = mbs.AddIndividualAnimat(0, new mbsPosition { latitude = location.Latitude, longitude = location.Longitude, depth = 0 });
                    if (mbsRESULT.OK == retval) geos.Add(new Geo<float>(location.Latitude, location.Longitude, (float)(depth * Random.NextDouble())));
                }
                return geos;
            }, new ExecutionDataflowBlockOptions
            {
                TaskScheduler = TaskScheduler.Default,
                BoundedCapacity = -1,
                MaxDegreeOfParallelism = -1,
            });
            var bufferBlock = new BufferBlock<Geo<float>>();
            transformManyBlock.LinkTo(bufferBlock);
            var population = (int)Math.Round(area * species.PopulationDensity);
            result.TotalAnimats = population;
            const int blockSize = 100;
            while (population > 0)
            {
                transformManyBlock.Post(population > blockSize ? blockSize : population);
                population -= blockSize;
            }
            transformManyBlock.Complete();
            await transformManyBlock.Completion;
            //mbsResult = mbs.InitializeRun();
            //if (mbsRESULT.OK == mbsResult) while (mbsRUNSTATE.INITIALIZING == mbs.GetRunState()) Thread.Sleep(1);
            //else throw new AnimatInterfaceMMBSException("C3mbs::Initialize FATAL error " + mbs.ResultToTc(mbsResult));
            mbsResult = mbs.FinishRun();
            if (mbsRESULT.OK != mbsResult) throw new AnimatInterfaceMMBSException("C3mbs::FinishRun FATAL error " + mbs.ResultToTc(mbsResult));

            IList<Geo<float>> animatGeos;
            if (bufferBlock.TryReceiveAll(out animatGeos))
                result.Locations.AddRange(animatGeos);
            return result;
        }
        public async static Task<BottomLoss> ExtractAsync(GeoRect region, [NotNull]string hfblExePath, [NotNull]string lfblExePath, IProgress<string> currentState = null, IProgress<float> progress = null)
        {
            if (progress != null) lock (progress) progress.Report(0f);
            if (currentState != null) lock (currentState) currentState.Report("Importing bottom loss data");

            var locations = new List<Geo>();
            var north = (float)Math.Ceiling(region.North);
            var south = (float)Math.Floor(region.South);
            var east = (float)Math.Ceiling(region.East);
            var west = (float)Math.Floor(region.West);

            for (var lat = south; lat < north; lat += 0.25f)
                for (var lon = west; lon < east; lon += 0.25f)
                    locations.Add(new Geo(lat, lon));
            var progressStep = 100f / ((locations.Count * 2) + 1);
            var totalProgress = 0f;
            var useLFBL = !string.IsNullOrEmpty(lfblExePath);
            var useHFBL = !string.IsNullOrEmpty(hfblExePath);
            var totalPointsRequested = 0;
            var totalPointsProcessed = 0;
            var transformBlock = new TransformBlock<Geo, BottomLossSample>(async location =>
                {
                    BottomLossSample curPoint = null;
                    if (useLFBL)
                    {
                        var process = Process.Start(new ProcessStartInfo
                        {
                            Arguments = ExtractorArgument(true, location, lfblExePath, hfblExePath),
                            FileName = lfblExePath,
                            RedirectStandardInput = false,
                            RedirectStandardOutput = true,
                            RedirectStandardError = true,
                            UseShellExecute = false,
                            CreateNoWindow = true,
                            WorkingDirectory = Path.GetDirectoryName(lfblExePath),
                        });
                        //process.PriorityClass = ProcessPriorityClass.Normal;
                        while (!process.HasExited) await Task.Delay(50);
                        if (progress != null) lock (progress) progress.Report(totalProgress += progressStep);
                        //var stderr = process.StandardError.ReadToEnd();
                        curPoint = ParseLowFrequencyOutput(process.StandardOutput);
                        //Debug.WriteLine(string.Format("Low frequency output: {0}", process.StandardOutput.ReadToEnd()));
                    }
                    if (useHFBL)
                    {
                        var process = Process.Start(new ProcessStartInfo
                        {
                            Arguments = ExtractorArgument(false, location, lfblExePath, hfblExePath),
                            FileName = hfblExePath,
                            RedirectStandardInput = false,
                            RedirectStandardOutput = true,
                            RedirectStandardError = true,
                            UseShellExecute = false,
                            CreateNoWindow = true,
                            WorkingDirectory = Path.GetDirectoryName(hfblExePath),
                        });
                        //process.PriorityClass = ProcessPriorityClass.Normal;
                        while (!process.HasExited) await Task.Delay(50);
                        if (progress != null) lock (progress) progress.Report(totalProgress += progressStep);
                        //var stderr = process.StandardError.ReadToEnd();
                        curPoint = ParseHighFrequencyOutput(process.StandardOutput, curPoint);
                        //Debug.WriteLine(string.Format("High frequency output: {0}", process.StandardOutput.ReadToEnd()));
                    }
                    Interlocked.Increment(ref totalPointsProcessed);
                    if (totalPointsProcessed % 1000 == 0) Debug.WriteLine("{0} BottomLossDatabase: {1:0.0}% complete", DateTime.Now, ((float)totalPointsProcessed / (float) totalPointsRequested) * 100);
                    return curPoint;
                },
                new ExecutionDataflowBlockOptions
                {
                    TaskScheduler = TaskScheduler.Default,
                    MaxDegreeOfParallelism = 4,
                });

            var bottomLoss = new BottomLoss();
            foreach (var location in locations)
            {
                transformBlock.Post(location);
                totalPointsRequested++;
            }

            var batchBlock = new BatchBlock<BottomLossSample>(locations.Count);
            transformBlock.LinkTo(batchBlock);

            transformBlock.Complete();
            await transformBlock.Completion;
            bottomLoss.Samples.AddRange(batchBlock.Receive().Where(data => data != null).ToList());
            if (progress != null) lock (progress) progress.Report(totalProgress += progressStep);
            return bottomLoss;
        }
 public static BottomLoss Extract(GeoRect region, [NotNull]string hfblExePath, [NotNull]string lfblExePath, IProgress<string> currentState = null, IProgress<float> progress = null)
 {
     var result = ExtractAsync(region, hfblExePath, lfblExePath, currentState, progress);
     return result.Result;
 }
        public void Inflations()
       {
           var rect = new GeoRect(44, 41, -69, -72);
           var nw = new Geo(rect.North, rect.West,true);
           var se = new Geo(rect.South, rect.East,true);

           var kmToInflate = 10.0f;

           nw = nw.Offset(Geo.KilometersToRadians(Math.Sqrt(2) * kmToInflate), Geo.DegreesToRadians(315));
           se = se.Offset(Geo.KilometersToRadians(Math.Sqrt(2) * kmToInflate), Geo.DegreesToRadians(135));

           var rect1 = new GeoRect(nw.Latitude,se.Latitude,se.Longitude,nw.Longitude);

           var inflatedRect = GeoRect.Inflate(rect, kmToInflate);
           Assert.IsTrue(rect1.Equals(inflatedRect));
       }
        void ExpandOverlayHandler()
        {
            var originalBufferSize = 0f;
            if (!string.IsNullOrEmpty(SelectedOverlayDescriptor.Metadata.OverlayFilename))
            {
                originalBufferSize = SelectedOverlayDescriptor.Metadata.BufferZoneSize;
                SelectedOverlayDescriptor = (NAEMOOverlayDescriptor)NAEMOOverlayDescriptors[SelectedOverlayDescriptor.Metadata.OverlayFilename];
            }
            if (!IsOverlayFileSelected) return;
            var vm = new OverlayExpandViewModel(SelectedOverlayDescriptor.Metadata) {BufferSize = originalBufferSize};
            var result = _visualizerService.ShowDialog("OverlayExpandView", vm);
            if ((!result.HasValue) || (!result.Value)) return;
            
            var curOverlay = SelectedOverlayDescriptor.Data;
            //var limits = (Limits)(new GeoRect(curOverlay.Shapes[0].EarthCoordinates));
            var limits = new Limits(ConvexHull.Create(curOverlay.Shapes[0].EarthCoordinates, true));
            var expandedLimits = limits.CreateExpandedLimit(vm.BufferSize);  //in km.
            var boundingBox = new GeoRect(expandedLimits.GeoPointList);
            var coordinateList = expandedLimits.GeoPointList.Select(geo => new EarthCoordinate(geo)).ToList();
            var testShape = new OverlayLineSegments(coordinateList.ToArray(), Colors.Black);

            if (!testShape.IsUsableAsPerimeter) coordinateList = ConvexHull.Create(coordinateList, true);

            NAEMOOverlayDescriptors.CreateNewOverlay(SelectedRangeComplexDescriptor.Data.Name, vm.OverlayName, coordinateList, boundingBox, vm.BufferSize, Path.GetFileNameWithoutExtension(SelectedOverlayDescriptor.DataFilename));
            SelectedOverlayDescriptor = (NAEMOOverlayDescriptor)NAEMOOverlayDescriptors[vm.OverlayName];
        }
 void NewBathymetryHandler()
 {
     var vm = new BathymetryExtractionViewModel(Path.GetFileNameWithoutExtension(SelectedOverlayDescriptor.DataFilename), new GeoRect(SelectedOverlayDescriptor.Data.Shapes[0].BoundingBox));
     var result = _visualizerService.ShowDialog("BathymetryExtractionView", vm);
     if ((!result.HasValue) || (!result.Value)) return;
     var extractionArea = new GeoRect(SelectedOverlayDescriptor.Data.Shapes[0].BoundingBox);
     var tempPath = Path.GetTempPath().Remove(Path.GetTempPath().Length - 1);
     if (!Directory.Exists(tempPath)) Directory.CreateDirectory(tempPath);
     var destinationPath = Path.Combine(Globals.AppSettings.ScenarioDataDirectory, SelectedRangeComplexDescriptor.Data.Name, "Bathymetry");
     var destinationFile = vm.BathymetryName + ".txt";
     var bathymetryExtractor = new DBDBBackgroundExtractor
     {
             WorkerSupportsCancellation = false,
             ExtractionArea = extractionArea,
             NAVOConfiguration = Globals.AppSettings.NAVOConfiguration,
             DestinationPath = destinationPath,
             UseExpandedExtractionArea = false,
             SelectedResolution = vm.SelectedResolution,
             SaveAsFilename = destinationFile,
             TaskName = "Bathymetry data extraction",
     };
     bathymetryExtractor.RunWorkerCompleted += (s, e) => Task.Factory.StartNew(() =>
     {
         Bathymetry bathymetry;
         var bathymetryFilePath = Path.Combine(destinationPath, bathymetryExtractor.SaveAsFilename);
         var metadata = NAEMOBathymetryMetadata.FromBathymetryFile(bathymetryFilePath, out bathymetry);
         metadata.OverlayFilename = vm.OverlayName;
         metadata.Bounds = vm.BoundingBox;
         metadata.Save();
         var bathymetryDescriptor = new NAEMOBathymetryDescriptor {DataFilename = bathymetryFilePath, Metadata = metadata};
         NAEMOBathymetryDescriptors.Add(new KeyValuePair<string, NAEMOBathymetryDescriptor>(vm.BathymetryName, bathymetryDescriptor));
         NAEMOBathymetryDescriptors.Sort();
         SelectedBathymetryDescriptor = bathymetryDescriptor;
     });
     BackgroundTaskAggregator.TaskName = "Bathymetry data extraction";
     BackgroundTaskAggregator.BackgroundTasks.Add(bathymetryExtractor);
 }
        void NewEnvironmentHandler()
        {
            var overlayName = Path.GetFileNameWithoutExtension(SelectedOverlayDescriptor.DataFilename);
            var bathymetryName = Path.GetFileNameWithoutExtension(SelectedBathymetryDescriptor.DataFilename);
            var vm = new EnvironmentExtractionViewModel(overlayName, bathymetryName);
            var result = _visualizerService.ShowDialog("EnvironmentExtractionView", vm);
            if ((!result.HasValue) || (!result.Value)) return;
            var bathymetry = SelectedBathymetryDescriptor.Data;
            var maxDepth = new EarthCoordinate<float>(bathymetry.Minimum, Math.Abs(bathymetry.Minimum.Data));
            var extractionArea = new GeoRect(SelectedOverlayDescriptor.Data.Shapes[0].BoundingBox);
            var tempPath = Path.GetTempPath().Remove(Path.GetTempPath().Length - 1);
            if (!Directory.Exists(tempPath)) Directory.CreateDirectory(tempPath);

            var assemblyLocation = Assembly.GetCallingAssembly().Location;
            var extractionPath = Path.GetDirectoryName(assemblyLocation);
            if (extractionPath == null) throw new ApplicationException("Extraction path can't be null!");

            var gdemExtractionProgramPath = Path.Combine(extractionPath, "ImportGDEM.exe");
            var gdemRequiredSupportFiles = new List<string>
            {
                    Path.Combine(extractionPath, "netcdf.dll"),
                    Path.Combine(extractionPath, "NetCDF_Wrapper.dll")
            };

            var extendedMonthlySoundSpeeds = new SoundSpeed();
            var extendedAndAveragedSoundSpeeds = new SoundSpeed();
            var monthlyTemperature = new SoundSpeed();
            var monthlySalinity = new SoundSpeed();

            var soundSpeedExtractors = new List<GDEMBackgroundExtractor>();

            var selectedTimePeriods = vm.EnvironmentDescriptors.Select(t => t.TimePeriod).ToList();
            var requiredMonths = selectedTimePeriods.Select(Globals.AppSettings.NAVOConfiguration.MonthsInTimePeriod).ToList();
            var allMonths = new List<NAVOTimePeriod>();
            foreach (var curPeriod in requiredMonths) allMonths.AddRange(curPeriod);
            var uniqueMonths = allMonths.Distinct().ToList();
            uniqueMonths.Sort();
            var environmentPath = Path.Combine(Globals.AppSettings.ScenarioDataDirectory, SelectedRangeComplexDescriptor.Data.Name, "Environment");
            BackgroundTaskAggregator = new BackgroundTaskAggregator();

            var naemoEnvironmentExporters = selectedTimePeriods.Select(t => new CASSBackgroundExporter
            {
                    WorkerSupportsCancellation = false,
                    BathymetryFileName = Path.GetFileName(SelectedBathymetryDescriptor.DataFilename),
                    OverlayFileName = Path.GetFileName(SelectedOverlayDescriptor.DataFilename),
                    TimePeriod = t,
                    ExtractionArea = extractionArea,
                    NAVOConfiguration = Globals.AppSettings.NAVOConfiguration,
                    DestinationPath = Path.Combine(environmentPath, vm.EnvironmentDescriptors.Find(descriptor => descriptor.TimePeriod == t).EnvironmentName + ".dat"),
                    UseExpandedExtractionArea = false,
                    TaskName = "Export NAEMO environment for " + t,
            }).ToList();
            foreach (var exporter in naemoEnvironmentExporters)
            {
                exporter.RunWorkerCompleted += (s, e) =>
                {
                    var curExporter = (CASSBackgroundExporter)s;
                    var metadataFilename = NAEMOMetadataBase.MetadataFilename(curExporter.DestinationPath);
                    var metadata = new NAEMOEnvironmentMetadata
                    {
                            BathymetryName = Path.GetFileNameWithoutExtension(curExporter.BathymetryFileName),
                            OverlayFilename = Path.GetFileNameWithoutExtension(curExporter.OverlayFileName),
                            TimePeriod = curExporter.TimePeriod,
                            Bounds = extractionArea,
                            Filename = metadataFilename,
                    };
                    metadata.Save();
                    var environmentDescriptor = new NAEMOEnvironmentDescriptor { DataFilename = curExporter.DestinationPath, Metadata = metadata };
                    lock (NAEMOEnvironmentDescriptors)
                    {
                        NAEMOEnvironmentDescriptors.Add(new KeyValuePair<string, NAEMOEnvironmentDescriptor>(Path.GetFileNameWithoutExtension(curExporter.DestinationPath),
                                                                                                             environmentDescriptor));
                        NAEMOBathymetryDescriptors.Sort();
                        SelectedEnvironmentDescriptor = environmentDescriptor;
                    }
                };
            }

            var windExtractor = new SMGCBackgroundExtractor
            {
                    WorkerSupportsCancellation = false,
                    ExtractionArea = extractionArea,
                    SelectedTimePeriods = selectedTimePeriods,
                    NAVOConfiguration = Globals.AppSettings.NAVOConfiguration,
                    UseExpandedExtractionArea = false,
                    TaskName = "Wind data extraction",
            };
            BackgroundTaskAggregator.BackgroundTasks.Add(windExtractor);
            windExtractor.RunWorkerCompleted += (s, e) => { foreach (var naemo in naemoEnvironmentExporters) naemo.Wind = ((SMGCBackgroundExtractor)s).Wind; };

            // Create a sediment extractor
            var sedimentExtractor = new BSTBackgroundExtractor
            {
                    WorkerSupportsCancellation = false,
                    ExtractionArea = extractionArea,
                    NAVOConfiguration = Globals.AppSettings.NAVOConfiguration,
                    UseExpandedExtractionArea = false,
                    TaskName = "Sediment data extraction",
            };
            BackgroundTaskAggregator.BackgroundTasks.Add(sedimentExtractor);
            sedimentExtractor.RunWorkerCompleted += (s, e) => { foreach (var naemo in naemoEnvironmentExporters) naemo.Sediment = ((BSTBackgroundExtractor)s).Sediment; };

            //var temperatureAndSalinityFileWriter = new TemperatureAndSalinityFileWriter
            //{
            //        WorkerSupportsCancellation = false,
            //        DestinationPath = tempPath,
            //        TaskName = "Save soundspeed data"
            //};
            var averagers = selectedTimePeriods.Select(timePeriod => new SoundSpeedBackgroundAverager
            {
                    WorkerSupportsCancellation = false,
                    TimePeriod = timePeriod,
                    ExtractionArea = extractionArea,
                    NAVOConfiguration = Globals.AppSettings.NAVOConfiguration,
                    UseExpandedExtractionArea = false,
                    TaskName = "Calculate extended sound speeds for " + timePeriod,
            }).ToList();

            foreach (var month in uniqueMonths)
            {
                var soundSpeedExtractor = new GDEMBackgroundExtractor
                {
                        WorkerSupportsCancellation = false,
                        TimePeriod = month,
                        ExtractionArea = extractionArea,
                        NAVOConfiguration = Globals.AppSettings.NAVOConfiguration,
                        DestinationPath = tempPath,
                        UseExpandedExtractionArea = false,
                        ExtractionProgramPath = gdemExtractionProgramPath,
                        RequiredSupportFiles = gdemRequiredSupportFiles,
                        MaxDepth = maxDepth,
                };
                soundSpeedExtractor.RunWorkerCompleted += (sender, e) =>
                {
                    var extractor = (GDEMBackgroundExtractor)sender;
                    monthlyTemperature.SoundSpeedFields.Add(extractor.TemperatureField);
                    monthlySalinity.SoundSpeedFields.Add(extractor.SalinityField);
                    extendedMonthlySoundSpeeds.SoundSpeedFields.Add(extractor.ExtendedSoundSpeedField);
                    //Console.WriteLine("soundspeed extractor for {0} complete. {1} extractors are still busy", extractor.TimePeriod, soundSpeedExtractors.Where(s => s.IsBusy).Count());
                    if (soundSpeedExtractors.Any(ssfExtractor => ssfExtractor.IsBusy)) return;
                    //temperatureAndSalinityFileWriter.Temperature = monthlyTemperature;
                    //temperatureAndSalinityFileWriter.Salinity = monthlySalinity;
                    foreach (var averager in averagers) averager.ExtendedMonthlySoundSpeeds = extendedMonthlySoundSpeeds;
                };
                soundSpeedExtractors.Add(soundSpeedExtractor);
                BackgroundTaskAggregator.BackgroundTasks.Add(soundSpeedExtractor);
            }
            //BackgroundTaskAggregator.BackgroundTasks.Add(temperatureAndSalinityFileWriter);
            foreach (var averager in averagers)
            {
                BackgroundTaskAggregator.BackgroundTasks.Add(averager);
                averager.RunWorkerCompleted += (sender, e) =>
                {
                    var avg = (SoundSpeedBackgroundAverager)sender;
                    extendedAndAveragedSoundSpeeds.SoundSpeedFields.Add(avg.ExtendedAverageSoundSpeedField);
                    if (averagers.Any(a => a.IsBusy)) return;
                    foreach (var naemo in naemoEnvironmentExporters) naemo.ExtendedAndAveragedSoundSpeeds = extendedAndAveragedSoundSpeeds;
                };
            }
            foreach (var naemo in naemoEnvironmentExporters)
                BackgroundTaskAggregator.BackgroundTasks.Add(naemo);
            BackgroundTaskAggregator.TaskName = "Environmental data extraction";
        }
        public RasterPatch2 GetWarpedTilePatch()
        {
            int width = 256;
            int height = 256;

            GeoRect intersectionRect = GeoRect.Intersect(gridBox, tileBox);

            if (intersectionRect != null)
            {
                PixelArray plane = new PixelArray(width, height);
                GeoRect workingRect;

                // Get data and min/max.
                double[,] data = warpedField.Data;
                double minT, maxT;


                MathHelper.GetMaxMin(data, out maxT, out minT);

                this.minT = minT;
                this.maxT = maxT;
                
                double k = 1.0 / (maxT - minT);

                System.Windows.Point[,] grid = warpedField.Grid;
                for (int i = 0; i < warpedField.Width - 1; i++)
                {
                    for (int j = 0; j < warpedField.Height - 1; j++)
                    {
                        workingRect = new GeoRect(
                            new System.Windows.Point(grid[i, j].X, grid[i, j].Y),
                            new System.Windows.Point(grid[i + 1, j].X, grid[i + 1, j].Y),
                            new System.Windows.Point(grid[i, j + 1].X, grid[i, j + 1].Y));

                        if (GeoRect.IntersectionExist(workingRect, intersectionRect))
                        {
                            System.Windows.Media.Color color = palette.GetColor((data[i, j] - minT) * k);
                            workingTriangle.Point1 = new VertexPositionColor2D(
                                new System.Drawing.Point(
                                    (int)((grid[i, j].X - tileBox.Left) * width / tileBox.Width),
                                    (int)(height - (grid[i, j].Y - tileBox.Bottom) * height / tileBox.Height)),
                                    color);
                            
                            color = palette.GetColor((data[i + 1, j] - minT) * k);
                            workingTriangle.Point2 = new VertexPositionColor2D(
                                new System.Drawing.Point(
                                    (int)((grid[i + 1, j].X - tileBox.Left) * width / tileBox.Width),
                                    (int)(height - (grid[i + 1, j].Y - tileBox.Bottom) * height / tileBox.Height)),
                                    color);
                            
                            color = palette.GetColor((data[i, j + 1] - minT) * k);
                            workingTriangle.Point3 = new VertexPositionColor2D(
                                new System.Drawing.Point(
                                    (int)((grid[i, j + 1].X - tileBox.Left) * width / tileBox.Width),
                                    (int)(height - (grid[i, j + 1].Y - tileBox.Bottom) * height / tileBox.Height)),
                                    color);
                            
                            workingTriangle.FillGouraud(plane);

                        }

                        workingRect = new GeoRect(
                            new System.Windows.Point(grid[i + 1, j].X, grid[i + 1, j].Y),
                            new System.Windows.Point(grid[i, j + 1].X, grid[i, j + 1].Y),
                            new System.Windows.Point(grid[i + 1, j + 1].X, grid[i + 1, j + 1].Y));

                        if (GeoRect.IntersectionExist(workingRect, intersectionRect))
                        {
                            System.Windows.Media.Color color = palette.GetColor((data[i + 1, j] - minT) * k);
                            workingTriangle.Point1 = new VertexPositionColor2D(
                                new System.Drawing.Point(
                                    (int)((grid[i + 1, j].X - tileBox.Left) * width / tileBox.Width),
                                    (int)(height - (grid[i + 1, j].Y - tileBox.Bottom) * height / tileBox.Height)),
                                    color);
                            
                            color = palette.GetColor((data[i, j + 1] - minT) * k);
                            workingTriangle.Point2 = new VertexPositionColor2D(
                                new System.Drawing.Point(
                                    (int)((grid[i, j + 1].X - tileBox.Left) * width / tileBox.Width),
                                    (int)(height - (grid[i, j + 1].Y - tileBox.Bottom) * height / tileBox.Height)),
                                    color);
                            
                            color = palette.GetColor((data[i + 1, j + 1] - minT) * k);
                            workingTriangle.Point3 = new VertexPositionColor2D(
                                new System.Drawing.Point(
                                    (int)((grid[i + 1, j + 1].X - tileBox.Left) * width / tileBox.Width),
                                    (int)(height - (grid[i + 1, j + 1].Y - tileBox.Bottom) * height / tileBox.Height)),
                                    color);
                            
                            workingTriangle.FillGouraud(plane);

                        }

                    }
                }

                const int bitsPerPixel = 32;
                int stride = width * ((bitsPerPixel + 7) / 8);
                int arraySize = stride * height;
                byte[] pixels = new byte[arraySize];
                int index = 0;

                for (int i = 0; i < height; i++)
                {
                    for (int j = 0; j < width; j++)
                    {
                        pixels[index++] = plane.Pixels[j, i].B;
                        pixels[index++] = plane.Pixels[j, i].G;
                        pixels[index++] = plane.Pixels[j, i].R;
                        pixels[index++] = plane.Pixels[j, i].A;

                    }
                }

                RasterPatch2 patch = new RasterPatch2(
                    regionBox,
                    pixels,
                    PatchPixelFormat.Format32bppArgb,
                    width,
                    height,
                    stride,
                    Wgs84CoordinateReferenceSystem.Instance);

                return patch;
            }
            else
            {
                return null;
            }
        }