Exemple #1
0
        public override void Render(Graphics graphics, Map map)
        {

            Extent extent = new Extent(map.Envelope.Min.X, map.Envelope.Min.Y, map.Envelope.Max.X, map.Envelope.Max.Y);
            int level = BruTile.Utilities.GetNearestLevel(_source.Schema.Resolutions, map.PixelSize);
            IList<TileInfo> tiles = _source.Schema.GetTilesInView(extent, level);

            foreach (TileInfo info in tiles)
            {
                if (_bitmaps.Find(info.Index) != null)
                {
                    ThreadPool.QueueUserWorkItem(OnMapNewtileAvailableHelper, new object[]{info,_bitmaps.Find(info.Index)});   
                }
                else if (_fileCache != null && _fileCache.Exists(info.Index))
                {
                    Bitmap img = GetImageFromFileCache(info) as Bitmap;
                    _bitmaps.Add(info.Index, img);
                    ThreadPool.QueueUserWorkItem(OnMapNewtileAvailableHelper, new object[] { info, img });
                }
                else
                {
                    ThreadPool.QueueUserWorkItem(GetTileOnThread, new object[] { _source.Provider, info, _bitmaps });
                }
            }

        }
        private static void GetRecursive(IDictionary<TileIndex, IFeature> resultTiles, ITileSchema schema,
            ITileCache<Feature> cache, Extent extent, IList<KeyValuePair<string, Resolution>> resolutions, int resolutionIndex)
        {
            if (resolutionIndex < 0 || resolutionIndex >= resolutions.Count)
                return;

            var tiles = schema.GetTileInfos(extent, resolutions[resolutionIndex].Key);

            foreach (var tileInfo in tiles)
            {
                var feature = cache.Find(tileInfo.Index);

                if (feature == null)
                {
                    // only continue the recursive search if this tile is within the extent
                    if (tileInfo.Extent.Intersects(extent))
                    {
                        GetRecursive(resultTiles, schema, cache, tileInfo.Extent.Intersect(extent), resolutions, resolutionIndex - 1);
                    }
                }
                else
                {
                    resultTiles[tileInfo.Index] = feature;
                }
            }
        }
Exemple #3
0
        public IEnumerable<IFeature> FetchTiles(BoundingBox boundingBox, double resolution)
        {
            var extent = new Extent(boundingBox.Min.X, boundingBox.Min.Y, boundingBox.Max.X, boundingBox.Max.Y);
            var levelId = BruTile.Utilities.GetNearestLevel(_source.Schema.Resolutions, resolution);
            var infos = _source.Schema.GetTileInfos(extent, levelId).ToList();

            ICollection<WaitHandle> waitHandles = new List<WaitHandle>();
                        
            foreach (TileInfo info in infos)    
            {
                if (_bitmaps.Find(info.Index) != null) continue;
                if (_queue.Contains(info.Index)) continue;
                var waitHandle = new AutoResetEvent(false);
                waitHandles.Add(waitHandle);
                _queue.Add(info.Index);
                ThreadPool.QueueUserWorkItem(GetTileOnThread, new object[] { _source, info, _bitmaps, waitHandle });
            }

            WaitHandle.WaitAll(waitHandles.ToArray());
            
            IFeatures features = new Features();
            foreach (TileInfo info in infos)
            {
                byte[] bitmap = _bitmaps.Find(info.Index);
                if (bitmap == null) continue;
                IRaster raster = new Raster(new MemoryStream(bitmap), new BoundingBox(info.Extent.MinX, info.Extent.MinY, info.Extent.MaxX, info.Extent.MaxY));
                IFeature feature = features.New();
                feature.Geometry = raster;
                features.Add(feature);
            }
            return features;
        }
Exemple #4
0
        /// <summary>
        /// Creates an instance of this class using some tile source configuration.
        /// </summary>
        /// <param name="configuration">The tile source configuration. If the configuration
        /// hasn't been initialized yet, <see cref="IConfiguration.Initialize"/> will
        /// be called.</param>
        /// <exception cref="ArgumentNullException">Thrown when <paramref name="configuration"/>
        /// is <c>null</c>.</exception>
        /// <exception cref="CannotFindTileSourceException">Thrown when <paramref name="configuration"/>
        /// is not initialized and during initialization no tile source can be found.</exception>
        /// <exception cref="CannotCreateTileCacheException">Thrown when <paramref name="configuration"/>
        /// is not initialized and during initialization a critical error prevents the creation
        ///  of the persistent tile cache.</exception>
        /// <exception cref="CannotReceiveTilesException">Thrown when <paramref name="configuration"/>
        /// is not initialized and during initialization no tiles can be received from the tile source.</exception>
        public BruTileLayer(IConfiguration configuration)
        {
            if (configuration == null)
            {
                throw new ArgumentNullException(nameof(configuration));
            }

            if (!configuration.Initialized)
            {
                configuration.Initialize();
            }

            this.configuration = configuration;

            ITileSchema tileSchema = configuration.TileSchema;

            sourceProjection = GetTileSourceProjectionInfo(tileSchema.Srs);

            Projection = sourceProjection;
            BruTileExtent extent = tileSchema.Extent;

            MyExtent = new DotSpatialExtent(extent.MinX, extent.MinY, extent.MaxX, extent.MaxY);

            IsVisible = true;

            tileFetcher = configuration.TileFetcher;
            tileFetcher.TileReceived += HandleTileReceived;
            tileFetcher.QueueEmpty   += HandleQueueEmpty;

            // Set the wrap mode
            imageAttributes = new ImageAttributes();
            imageAttributes.SetWrapMode(WrapMode.TileFlipXY);
        }
        public UnProjected()
        {
            var resolutions = new[] { 
                                        0.703125, 0.3515625, 0.17578125, 0.087890625,
                                        0.0439453125, 0.02197265625, 0.010986328125, 0.0054931640625,
                                        0.00274658203125, 0.001373291015625, 0.0006866455078125, 3.4332275390625e-4,
                                        1.71661376953125e-4, 8.58306884765625e-5, 4.291534423828125e-5,
                                    };

            var count = 0;
            foreach (var resolution in resolutions)
            {
                Resolutions.Add(new Resolution { Id = count.ToString(CultureInfo.InvariantCulture), UnitsPerPixel = resolution });
                count++;
            }
            Height = 256;
            Width = 256;
            Extent = new Extent(-180, -90, 180, 90);
            OriginX = -180;
            OriginY = -90;
            Name = "UnProjected";
            Format = "image/png";
            Axis = AxisDirection.Normal;
            Srs = "EPSG:4326";
        }
        private static void DrawRecursive(Graphics graphics, ITileSchema schema, IViewport viewport, 
            MemoryCache<Feature> cache, Extent extent, int level)
        {
            var tileInfos = schema.GetTilesInView(extent, level);

            foreach (TileInfo info in tileInfos)
            {
                var feature = cache.Find(info.Index);
                if (feature == null)
                {
                    if (level > 0) DrawRecursive(graphics, schema, viewport, cache, info.Extent.Intersect(extent), level - 1);
                }
                else
                {
                    var image = ((IRaster)feature.Geometry).Data;
                    RectangleF dest = WorldToView(info.Extent, viewport);
                    dest = RoundToPixel(dest);
                    RectangleF clip = WorldToView(extent, viewport);
                    clip = RoundToPixel(clip);

                    if (!Contains(clip, dest))
                    {
                        clip = Intersect(clip, dest);
                        if (clip.IsEmpty) continue;
                        DrawImage(graphics, new Bitmap(image), dest, clip);
                    }
                    else
                    {
                        //Not using a clip at all sometimes performs better than using screenwide clip.
                        DrawImage(graphics, new Bitmap(image), dest);
                    }
                }
            }
        }
Exemple #7
0
 public bool Intersects(Extent box)
 {
     return !(
                 box.MinX > MaxX ||
                 box.MaxX < MinX ||
                 box.MinY > MaxY ||
                 box.MaxY < MinY);
 }
Exemple #8
0
 public Extent Intersect(Extent other) //TODO: check how to name this method.
 {
     return new Extent(
         Math.Max(MinX, other.MinX),
         Math.Max(MinY, other.MinY),
         Math.Min(MaxX, other.MaxX),
         Math.Min(MaxY, other.MaxY));
 }
Exemple #9
0
        public override void Render(Graphics graphics, Map map)
        {

            Extent extent = new Extent(map.Envelope.Min.X, map.Envelope.Min.Y, map.Envelope.Max.X, map.Envelope.Max.Y);
            int level = BruTile.Utilities.GetNearestLevel(_source.Schema.Resolutions, map.PixelSize);
            IList<TileInfo> tiles = _source.Schema.GetTilesInView(extent, level);

            //Abort previous running Threads
            lock (threadList)
            {
                foreach (BackgroundWorker t in threadList)
                {
                    if (t.IsBusy)
                    {
                        t.CancelAsync();
                    }
                }
                threadList.Clear();
            }

            foreach (TileInfo info in tiles)
            {
                if (_bitmaps.Find(info.Index) != null)
                {
                    //ThreadPool.QueueUserWorkItem(OnMapNewtileAvailableHelper, new object[] { info, _bitmaps.Find(info.Index) });
                    //draws directly the bitmap
                    BoundingBox bb = new BoundingBox(info.Extent.MinX, info.Extent.MinY, info.Extent.MaxX, info.Extent.MaxY);
                    HandleMapNewTileAvaliable(map,graphics, bb, _bitmaps.Find(info.Index), _source.Schema.Width, _source.Schema.Height, _imageAttributes);
                }
                else if (_fileCache != null && _fileCache.Exists(info.Index))
                {
                    
                    Bitmap img = GetImageFromFileCache(info) as Bitmap;
                    _bitmaps.Add(info.Index, img);
                    
                    //ThreadPool.QueueUserWorkItem(OnMapNewtileAvailableHelper, new object[] { info, img });
                    //draws directly the bitmap
                    BoundingBox bb = new BoundingBox(info.Extent.MinX, info.Extent.MinY, info.Extent.MaxX, info.Extent.MaxY);
                    HandleMapNewTileAvaliable(map, graphics, bb, _bitmaps.Find(info.Index), _source.Schema.Width, _source.Schema.Height, _imageAttributes);
                }
                else
                {
                    BackgroundWorker b = new BackgroundWorker();
                    b.WorkerSupportsCancellation = true;
                    b.DoWork += new DoWorkEventHandler(b_DoWork);
                    b.RunWorkerAsync(new object[] { _source.Provider, info, _bitmaps, true });
                    //Thread t = new Thread(new ParameterizedThreadStart(GetTileOnThread));
                    //t.Name = info.ToString();
                    //t.IsBackground = true;
                    //t.Start();
                    lock (threadList)
                    {
                        threadList.Add(b);
                    }
                }
            }

        }
Exemple #10
0
 private static TileRange WorldToTileInvertedY(Extent extent, int level, ITileSchema schema)
 {
     var resolution = schema.Resolutions[level];
     var tileWorldUnits = resolution.UnitsPerPixel * schema.Width;
     var firstCol = (int)Math.Floor((extent.MinX - schema.OriginX) / tileWorldUnits);
     var firstRow = (int)Math.Floor((-extent.MaxY + schema.OriginY) / tileWorldUnits);
     var lastCol = (int)Math.Ceiling((extent.MaxX - schema.OriginX) / tileWorldUnits);
     var lastRow = (int)Math.Ceiling((-extent.MinY + schema.OriginY) / tileWorldUnits);
     return new TileRange(firstCol, firstRow, lastCol - firstCol, lastRow - firstRow);
 }
Exemple #11
0
 private static TileRange WorldToTileNormal(Extent extent, string levelId, ITileSchema schema)
 {
     var resolution = schema.Resolutions[levelId];
     var tileWorldUnits = resolution.UnitsPerPixel * schema.GetTileWidth(levelId);
     var firstCol = (int)Math.Floor((extent.MinX - schema.GetOriginX(levelId)) / tileWorldUnits);
     var firstRow = (int)Math.Floor((extent.MinY - schema.GetOriginY(levelId)) / tileWorldUnits);
     var lastCol = (int)Math.Ceiling((extent.MaxX - schema.GetOriginX(levelId)) / tileWorldUnits);
     var lastRow = (int)Math.Ceiling((extent.MaxY - schema.GetOriginY(levelId)) / tileWorldUnits);
     return new TileRange(firstCol, firstRow, lastCol - firstCol, lastRow - firstRow);
 }
Exemple #12
0
        public void DrawRegions(MapArgs args, List <DotSpatial.Data.Extent> regions, bool selected)
        {
            BruTile.Extent extent    = ToBrutileExtent(args.GeographicExtents);
            var            pixelSize = extent.Width / args.ImageRectangle.Width;

            var level = Utilities.GetNearestLevel(TileSource.Schema.Resolutions, pixelSize);
            var tiles = TileSource.Schema.GetTileInfos(extent, level);

            IList <WaitHandle> waitHandles = new List <WaitHandle>();

            foreach (TileInfo info in tiles)
            {
                if (TileCache.Find(info.Index) != null)
                {
                    continue;
                }
                AutoResetEvent waitHandle = new AutoResetEvent(false);
                waitHandles.Add(waitHandle);
                ThreadPool.QueueUserWorkItem(GetTileOnThread, new object[] { TileSource, info, TileCache, waitHandle });
            }

            foreach (WaitHandle handle in waitHandles)
            {
                handle.WaitOne();
            }

            foreach (TileInfo info in tiles)
            {
                using (Image bitmap = System.Drawing.Image.FromStream(new MemoryStream(TileCache.Find(info.Index))))
                {
                    PointF min = args.ProjToPixel(new Coordinate(info.Extent.MinX, info.Extent.MinY));
                    PointF max = args.ProjToPixel(new Coordinate(info.Extent.MaxX, info.Extent.MaxY));

                    min = new PointF((float)Math.Round(min.X), (float)Math.Round(min.Y));
                    max = new PointF((float)Math.Round(max.X), (float)Math.Round(max.Y));

                    ColorMatrix matrix = new ColorMatrix {
                        Matrix33 = 0.45f
                    };                                                         // Symbolizer.Opacity
                    using (var attributes = new ImageAttributes())
                    {
                        attributes.SetColorMatrix(matrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);
                        args.Device.DrawImage(bitmap
                                              , new Rectangle((int)min.X, (int)max.Y, (int)(max.X - min.X), (int)(min.Y - max.Y))
                                              , 0
                                              , 0
                                              , TileSource.Schema.GetTileWidth(info.Index.Level)
                                              , TileSource.Schema.GetTileHeight(info.Index.Level)
                                              , GraphicsUnit.Pixel
                                              , attributes);
                    }
                }
            }
        }
Exemple #13
0
 public static TileRange WorldToTile(Extent extent, int level, ITileSchema schema)
 {
     switch (schema.Axis)
     {
         case AxisDirection.Normal:
             return WorldToTileNormal(extent, level, schema);
         case AxisDirection.InvertedY:
             return WorldToTileInvertedY(extent, level, schema);
         default:
             throw new Exception("Axis type was not found");
     }
 }
Exemple #14
0
 public static TileRange WorldToTile(Extent extent, string levelId, ITileSchema schema)
 {
     switch (schema.YAxis)
     {
         case YAxis.TMS:
             return WorldToTileNormal(extent, levelId, schema);
         case YAxis.OSM:
             return WorldToTileInvertedY(extent, levelId, schema);
         default:
             throw new Exception("YAxis type was not found");
     }
 }
 public static void GetRecursive(IDictionary<TileIndex, IFeature> resultTiles, ITileSchema schema,
     ITileCache<Feature> cache, Extent extent, string levelId)
 {
     // to improve performance, convert the resolutions to a list so they can be walked up by
     // simply decrementing an index when the level index needs to change
     var resolutions = schema.Resolutions.OrderByDescending(pair => pair.Value.UnitsPerPixel).ToList();
     for (int i = 0; i < resolutions.Count; i++)
     {
         if (levelId == resolutions[i].Key)
         {
             GetRecursive(resultTiles, schema, cache, extent, resolutions, i);
             break;
         }
     }
 }
 public static void WriteWorldFile(string f, Extent extent, ITileSchema schema)
 {
     using (var sw = new StreamWriter(f))
     {
         var resX = (extent.MaxX - extent.MinX) / schema.GetTileWidth("0");
         var resY = (extent.MaxY - extent.MinY) / schema.GetTileHeight("0");
         sw.WriteLine(resX.ToString(CultureInfo.InvariantCulture));
         sw.WriteLine("0");
         sw.WriteLine("0");
         sw.WriteLine((resY * -1).ToString(CultureInfo.InvariantCulture));
         sw.WriteLine(extent.MinX.ToString(CultureInfo.InvariantCulture));
         sw.WriteLine(extent.MaxY.ToString(CultureInfo.InvariantCulture));
         sw.Close();
     }
 }
        public void Fetch(Extent newExtent, double newResolution)
        {
            var levelId = Utilities.GetNearestLevel(_tileSource.Schema.Resolutions, newResolution);
            var tilesWanted = GetTilesWanted(_tileSource.Schema, newExtent, levelId);
            var tilesMissing = GetTilesMissing(tilesWanted, _fileCache);
            var stp = new SmartThreadPool(1000, 5);

            foreach (var info in tilesMissing)
            {
                // for debugging
                if(!async)
                    Fetch(info);
                else
                {
                    stp.QueueWorkItem(GetTileOnThread, new object[] { info });
                }
            }
        }
Exemple #18
0
        public WmsTileSchema(string name, BruTile.Extent extent, string srs, string format, int tileSize, double highestResUnitsPerPixel, AxisDirection axis)
        {
            // Make us a new extent that is square
            double minx, miny, maxx, maxy, size;
            if (extent.Width > extent.Height)
            {
                minx = extent.MinX;
                maxx = extent.MaxX;
                size = maxx - minx;
                miny = extent.MinY;
                maxy = miny + size;

            }
            else
            {
                miny = extent.MinY;
                maxy = extent.MaxY;
                size = maxy - miny;
                minx = extent.MinX;
                maxx = minx + size;
            }
            int count = 0;
            double unitsPerPixel = size / tileSize;
            do
            {
                Resolutions[count.ToString(CultureInfo.InvariantCulture)] = new Resolution {Id = count.ToString(CultureInfo.InvariantCulture), UnitsPerPixel = unitsPerPixel};
                count++;
                //Resolutions.Add(unitsPerPixel);
                unitsPerPixel /= 2;
            } while (unitsPerPixel > highestResUnitsPerPixel);
            BruTile.Extent myExtent = new BruTile.Extent(minx, miny, maxx, maxy);
            //Extent myExtent = extent;
            Width = tileSize;
            Height = tileSize;
            Extent = myExtent;
            OriginX = myExtent.MinX;
            OriginY = myExtent.MinY;
            Name = name;
            Format = format;
            Axis = axis;
            Srs = srs;
        }
Exemple #19
0
        public IList<TileInfo> GetTilesWanted(ITileSchema schema, Extent extent, int level)
        {
            IList<TileInfo> infos = new List<TileInfo>();
            // Iterating through all levels from current to zero. If lower levels are
            // not availeble the renderer can fall back on higher level tiles. 
            var levels = schema.Resolutions.Keys.Where(k => k <= level).OrderByDescending(x => x);

            foreach (var lvl in levels)
            {
                var infosOfLevel = schema.GetTilesInView(extent, lvl);
                infosOfLevel = SortByPriority(infosOfLevel, extent.CenterX, extent.CenterY);

                foreach (TileInfo info in infosOfLevel)
                {
                    if ((info.Index.Row >= 0) && (info.Index.Col >= 0)) infos.Add(info);
                }
            }

            return infos;
        }
Exemple #20
0
        public IList<TileInfo> GetTilesWanted(ITileSchema schema, Extent extent, string levelId)
        {
            var infos = new List<TileInfo>();
            // Iterating through all levels from current to zero. If lower levels are
            // not available the renderer can fall back on higher level tiles.
            var resolution = schema.Resolutions[levelId].UnitsPerPixel;
            var levels = schema.Resolutions.Where(k => k.Value.UnitsPerPixel >= resolution).OrderBy(x => x.Value.UnitsPerPixel).ToList();

            foreach (var level in levels)
            {
                var tileInfos = schema.GetTileInfos(extent, level.Key).OrderBy(
                    t => Algorithms.Distance(extent.CenterX, extent.CenterY, t.Extent.CenterX, t.Extent.CenterY));

                foreach (TileInfo info in tileInfos.Where(info => (info.Index.Row >= 0) && (info.Index.Col >= 0)))
                {
                    infos.Add(info);
                }
            }

            return infos;
        }
Exemple #21
0
        public IEnumerable<TileInfo> GetTilesInView(Extent extent, int level)
        {
            TileRange range = TileTransform.WorldToTile(extent, level, this);

            for (int x = range.FirstCol; x < range.FirstCol + range.ColCount; x++)
            {
                for (int y = range.FirstRow; y < range.FirstRow + range.RowCount; y++)
                {
                    var info = new TileInfo
                        {
                            Extent = TileTransform.TileToWorld(new TileRange(x, y), level, this),
                            Index = new TileIndex(x, y, level)
                        };

                    if (WithinSchemaExtent(Extent, info.Extent))
                    {
                        yield return info;
                    }
                }
            }
        }
        public IList<TileInfo> GetTilesWanted(ITileSchema schema, Extent extent, int level)
        {
            //line below only works properly of this instance is always called with the the resolutions. Think of something better
            if (preFetchLayers == null) preFetchLayers = GetPreFetchLevels(0, schema.Resolutions.Count - 1);

            IList<TileInfo> infos = new List<TileInfo>();
            // Iterating through all levels from current to zero. If lower levels are
            // not availeble the renderer can fall back on higher level tiles. 
            while (level >= 0)
            {
                ////////if (!preFetchLayers.Contains(level)) continue;
                var infosOfLevel = schema.GetTilesInView(extent, level);
                infosOfLevel = PrioritizeTiles(infosOfLevel, extent.CenterX, extent.CenterY);

                foreach (TileInfo info in infosOfLevel)
                {
                    if ((info.Index.Row >= 0) && (info.Index.Col >= 0)) infos.Add(info);
                }
                level--;
            }

            return infos;
        }
Exemple #23
0
        public TerrainNode(TerrainNode parent, Quadrant quad, LatLon bl, LatLon tl, LatLon tr, LatLon br)
        {
            Parent = parent;
            Quadrant = quad;

            corners = new LatLon[4]
            {
                bl, tl, tr, br
            };

            latLonExtents = new Extent(BL.Longitude, BL.Latitude, TR.Longitude, TR.Latitude);

            var mercBL = RenderWGS84.ToGoogleBing(BL.Longitude, BL.Latitude);
            var mercTR = RenderWGS84.ToGoogleBing(TR.Longitude, TR.Latitude);
            meterExtents = new Extent(mercBL.X, mercBL.Y, mercTR.X, mercTR.Y);

            center = LatLon.Average(corners);
            splitDepth = 0;

            Vector3D[] transformed = transformCorners();
            this.aabb = BoundingBox.FromPoints(transformed.Select(vec => vec.ToVector3()).ToArray());
            generateSplitBox();
        }
Exemple #24
0
        public IList<TileInfo> GetTilesWanted(ITileSchema schema, Extent extent, string levelId)
        {
            IList<TileInfo> infos = new List<TileInfo>();
            // Iterating through all levels from current to zero. If lower levels are
            // not availeble the renderer can fall back on higher level tiles.
            var resolution = schema.Resolutions[levelId].UnitsPerPixel;
            var levels = schema.Resolutions.Where(k => resolution <= k.Value.UnitsPerPixel).OrderByDescending(x => x.Value.UnitsPerPixel);

            //var levelCount = levels.Count();
            foreach (var level in levels)
            {
                var tileInfos = schema.GetTilesInView(extent, level.Key);
                tileInfos = SortByPriority(tileInfos, extent.CenterX, extent.CenterY);

                //var count = infosOfLevel.Count();
                foreach (var info in tileInfos)
                {
                    if ((info.Index.Row >= 0) && (info.Index.Col >= 0)) infos.Add(info);
                }
            }

            return infos;
        }
Exemple #25
0
        public bool Equals(Extent extent)
        {
            if (MinX != extent.MinX)
            {
                return false;
            }

            if (MinY != extent.MinY)
            {
                return false;
            }

            if (MaxX != extent.MaxX)
            {
                return false;
            }

            if (MaxY != extent.MaxY)
            {
                return false;
            }

            return true;
        }
 public IList<TileInfo> GetTilesWanted(ITileSchema schema, Extent extent, string levelId)
 {
     return schema.GetTilesInView(extent, (levelId)).ToList();
 }
Exemple #27
0
        /// <summary>
        /// Returns a List of TileInfos that cover the provided extent.
        /// </summary>
        public IEnumerable <TileInfo> GetTileInfos(Extent extent, double unitsPerPixel)
        {
            var level = Utilities.GetNearestLevel(Resolutions, unitsPerPixel);

            return(GetTileInfos(extent, level));
        }
Exemple #28
0
    private Texture2D[] Process(ITileSource source,
                                //IRequest request = null,
                                string levelId = null)
    {
        int levelId_int = -1;

        if (!string.IsNullOrEmpty(levelId))
        {
            if (!int.TryParse(levelId, out levelId_int))
            {
                Debug.LogErrorFormat("Could not parse levelId {0}", levelId);
            }
        }
        IEnumerable <TileInfo> tileInfos = null;
        var extent = new BruTile.Extent(-20037508, -20037508, 20037508, 20037508);

        if (levelId_int != -1)
        {
            tileInfos = source.Schema.GetTileInfos(extent, levelId);
        }
        else
        {
            const int screenWidthInPixels = 400; // The width of the map on screen in pixels
            var       unitsPerPixel       = extent.Width / screenWidthInPixels;
            tileInfos = source.Schema.GetTileInfos(extent, unitsPerPixel);
        }

        var tiles    = new Dictionary <BruTile.TileInfo, byte[]>();
        var tileUris = new Dictionary <BruTile.TileInfo, Uri>();
        int count    = 0;

        foreach (var tileInfo in tileInfos)
        {
            try
            {
                tiles[tileInfo] = source.GetTile(tileInfo);
                //if (request != null)
                //    tileUris[tileInfo] = request.GetUri(tileInfo);
            }
            catch (HttpRequestException e)
            {
                Debug.LogException(e);
            }
            ++count;
        }
        var textureTest = new Texture2D[count];
        int i           = 0;

        foreach (var kvp in tiles)
        {
            var tileInfo = kvp.Key;
            var bytes    = kvp.Value;
            if (bytes == null)
            {
                continue;
            }

            int width  = source.Schema.GetTileWidth(tileInfo.Index.Level);
            int height = source.Schema.GetTileHeight(tileInfo.Index.Level);
            if (source.Schema.Format.ToLower().EndsWith("png"))
            {
                textureTest[i] = Load_PNG_or_JPG(width, height, bytes);
            }
            else if (source.Schema.Format.ToLower().EndsWith("jpg") || source.Schema.Format.ToLower().EndsWith("jpeg"))
            {
                textureTest[i] = Load_PNG_or_JPG(width, height, bytes);
            }
            ++i;
        }

        if (VerboseLogging)
        {
            PrintTiles(ref tiles);
        }

        return(textureTest);
    }
Exemple #29
0
        public Extent GetExtentOfTilesInView(Extent extent, int level)
        {
            TileRange range = _axis.WorldToTile(extent, level, this);

            return(_axis.TileToWorld(range, level, this));
        }
        public override void Draw(esriDrawPhase drawPhase, IDisplay display, ITrackCancel trackCancel)
        {
            switch (drawPhase)
            {
                case esriDrawPhase.esriDPGeography:
                    if (Valid)
                    {
                        if (Visible)
                        {
                                Logger.Debug("Draw event Layer name: " + Name);
                                var activeView = (IActiveView)_map;
                                var clipEnvelope = display.ClipEnvelope;
                                Logger.Debug("Layer spatial reference: " + SpatialReference.FactoryCode);
                                Logger.Debug("Map spatial reference: " + _map.SpatialReference.FactoryCode);
                                var mapWidth = activeView.ExportFrame.right;
                                var resolution = clipEnvelope.GetMapResolution(mapWidth);
                                var ext = new Extent(clipEnvelope.XMin, clipEnvelope.YMin, clipEnvelope.XMax, clipEnvelope.YMax);
                                //_fetcher.ViewChanged(ext, resolution);
                                _simplefilefetcher.Fetch(ext,resolution);
                                var level = Utilities.GetNearestLevel(_tileSource.Schema.Resolutions, resolution);
                                var tileInfos = _tileSource.Schema.GetTilesInView(ext, level);
                                tileInfos = SortByPriority(tileInfos, ext.CenterX, ext.CenterY);

                                foreach (var tileInfo in tileInfos)
                                {
                                    var tile = _fileCache.Find(tileInfo.Index);
                                    if (tile != null)
                                    {
                                        var filename = _fileCache.GetFileName(tileInfo.Index);
                                        DrawRaster(filename, display);
                                    }
                                }

                        }
                    }
                    break;
                case esriDrawPhase.esriDPAnnotation:
                    break;
            }
        }
Exemple #31
0
        public static Extent GetExtentOfTilesInView(ITileSchema schema, Extent extent, string levelId)
        {
            var range = TileTransform.WorldToTile(extent, levelId, schema);

            return(TileTransform.TileToWorld(range, levelId, schema));
        }
Exemple #32
0
 public Extent GetExtentOfTilesInView(Extent extent, string levelId)
 {
     return(GetExtentOfTilesInView(this, extent, levelId));
 }
        public IFeatures FetchTiles(BoundingBox boundingBox, double resolution)
        {
            Extent extent = new Extent(boundingBox.Min.X, boundingBox.Min.Y, boundingBox.Max.X, boundingBox.Max.Y);
            int level = BruTile.Utilities.GetNearestLevel(source.Schema.Resolutions, resolution);
            IList<TileInfo> tiles = source.Schema.GetTilesInView(extent, level);

            ICollection<WaitHandle> waitHandles = new List<WaitHandle>();
                        
            foreach (TileInfo info in tiles)    
            {
                if (bitmaps.Find(info.Index) != null) continue;
                if (queue.Contains(info.Index)) continue;
                AutoResetEvent waitHandle = new AutoResetEvent(false);
                waitHandles.Add(waitHandle);
                queue.Add(info.Index);

                Thread thread = new Thread(GetTileOnThread);
                thread.Start(new object[] { source.Provider, info, bitmaps, waitHandle });
                //!!!ThreadPool.QueueUserWorkItem(GetTileOnThread, new object[] { source.Provider, info, bitmaps, waitHandle });
            }

            //foreach (WaitHandle handle in waitHandles)
            //    handle.WaitOne();

            IFeatures features = new Features();
            foreach (TileInfo info in tiles)
            {
                byte[] bitmap = bitmaps.Find(info.Index);
                if (bitmap == null) continue;
                IRaster raster = new Raster(bitmap, new BoundingBox(info.Extent.MinX, info.Extent.MinY, info.Extent.MaxX, info.Extent.MaxY));
                IFeature feature = features.New();
                feature.Geometry = raster;
                features.Add(feature);
            }
            return features;
        }
Exemple #34
0
        private static void DoWork(object sender, DoWorkEventArgs e)
        {
            //Esto quedo obsoleto si no vamos a usar Azure

            /*
             * storageAccount = CloudStorageAccount.Parse("DefaultEndpointsProtocol=http;AccountName=guardianes;AccountKey=vlG2nCfujtarq9++4+Qh21vZvD6c9+PUfNqR/9o+yc7AXifypGBVeEYgSRBMRx9AhLGoIcGJkgSqypduaaBnxw==");
             * blobClient = storageAccount.CreateCloudBlobClient();
             * if (includeHexagon)
             * {
             *  container = blobClient.GetContainerReference("demand");
             * }
             * else
             * {
             *  container = blobClient.GetContainerReference("minigame");
             * }
             * */

            //Encoder
            jgpEncoder = GetEncoder(ImageFormat.Jpeg);
            System.Drawing.Imaging.Encoder myEncoder = System.Drawing.Imaging.Encoder.Quality;
            myEncoderParameters = new EncoderParameters(1);

            EncoderParameter myEncoderParameter = new EncoderParameter(myEncoder, 100L);

            myEncoderParameters.Param[0] = myEncoderParameter;

            List <string> hexCodes = new List <string>();

            if (string.IsNullOrEmpty(_geoHexKey))
            {
                hexCodes = landRepository.GetVerifiedLandsGeoHexCodes(0, includeHexagon);
            }
            else
            {
                hexCodes.Add(_geoHexKey);
            }

            foreach (var geohex in hexCodes)
            {
                string baseurl = landRepository.GetImageBaseUrl(true, geohex);
                string newurl  = landRepository.GetImageBaseUrl(false, geohex);

                var zone = GeoHex.Decode(geohex);

                var sphericalCoordinates = ConvertHexCoordinates(zone.getHexCoords());

                var top    = sphericalCoordinates.Max(s => s.Y);
                var bottom = sphericalCoordinates.Min(s => s.Y);
                var left   = sphericalCoordinates.Min(s => s.X);
                var right  = sphericalCoordinates.Max(s => s.X);

                var extent = new BruTile.Extent(left, bottom, right, top);

                var schema = new SphericalMercatorWorldSchema();
                schema.Extent = extent;

                var tiles = schema.GetTilesInView(extent, 13);

                var newTop    = tiles.Max(s => s.Extent.MaxY);
                var newBottom = tiles.Min(s => s.Extent.MinY);
                var newLeft   = tiles.Min(s => s.Extent.MinX);
                var newRight  = tiles.Max(s => s.Extent.MaxX);

                int[] cols    = tiles.OrderBy(t => t.Index.Col).ThenByDescending(t => t.Index.Row).Select(t => t.Index.Col).Distinct().ToArray();
                int[] rows    = tiles.OrderBy(t => t.Index.Col).ThenByDescending(t => t.Index.Row).Select(t => t.Index.Row).Distinct().ToArray();
                int   width   = 256 * cols.Length;
                int   height  = 256 * rows.Length;
                float hexLeft = (float)(((left - newLeft) * width) / (newRight - newLeft));
                float hexTop  = (float)(((top - newTop) * height) / (newBottom - newTop));

                CreateCanvas(baseurl, geohex, tiles, width, height, hexLeft, hexTop, cols, rows, true);
                CreateCanvas(newurl, geohex, tiles, width, height, hexLeft, hexTop, cols, rows, false);
            }
        }
Exemple #35
0
 private static double GetFirstXRelativeToOrigin(Extent extent, double originX)
 {
     return(extent.MinX - originX);
 }
Exemple #36
0
        public Extent GetExtentOfTilesInView(Extent extent, int level)
        {
            TileRange range = WorldToTile(extent, level);

            return(TileToWorld(range, level));
        }
Exemple #37
0
        private void Process(ITileSource source, Extent extent,
                             out Dictionary <BruTile.TileInfo, byte[]> tiles,
                             //IRequest request = null,
                             string levelId = null)
        {
            int levelId_int = -1;

            if (!string.IsNullOrEmpty(levelId))
            {
                if (!int.TryParse(levelId, out levelId_int))
                {
                    Debug.LogErrorFormat("Could not parse levelId {0}", levelId);
                }
            }
            IEnumerable <TileInfo> tileInfos = null;

            if (extent == null)
            {
                extent = new BruTile.Extent(-20037508, -20037508, 20037508, 20037508);
            }
            if (levelId_int != -1)
            {
                tileInfos = source.Schema.GetTileInfos(extent, levelId);
            }
            else
            {
                const int screenWidthInPixels = 400; // The width of the map on screen in pixels
                var       unitsPerPixel       = extent.Width / screenWidthInPixels;
                tileInfos = source.Schema.GetTileInfos(extent, unitsPerPixel);
            }

            tiles = new Dictionary <BruTile.TileInfo, byte[]>();
            //var tileUris = new Dictionary<BruTile.TileInfo, Uri>();
            int count = 0;

            foreach (var tileInfo in tileInfos)
            {
                try
                {
                    tiles[tileInfo] = source.GetTile(tileInfo);
                    //if (request != null)
                    //    tileUris[tileInfo] = request.GetUri(tileInfo);
                }
                catch (HttpRequestException e)
                {
                    Debug.LogException(e);
                }
                ++count;
            }
            //int i = 0;
            //foreach (var kvp in tiles)
            //{
            //    var tileInfo = kvp.Key;
            //    var bytes = kvp.Value;
            //    if (bytes == null)
            //        continue;

            //    //int width = source.Schema.GetTileWidth(tileInfo.Index.Level);
            //    //int height = source.Schema.GetTileHeight(tileInfo.Index.Level);
            //    ++i;
            //}

            if (VerboseLogging)
            {
                PrintTiles(ref tiles);
            }
        }
Exemple #38
0
 private static double GetFirstYRelativeToOrigin(YAxis yAxis, Extent extent, double originY)
 {
     return((yAxis == YAxis.TMS) ? extent.MinY - originY : -extent.MaxY + originY);
 }
Exemple #39
0
        /// <summary>
        /// Renders the layer
        /// </summary>
        /// <param name="graphics">Graphics object reference</param>
        /// <param name="map">Map which is rendered</param>
        public override void Render(Graphics graphics, Map map)
        {
            if (!map.Size.IsEmpty && map.Size.Width > 0 && map.Size.Height > 0)
            {
                var bmp = new Bitmap(map.Size.Width, map.Size.Height, PixelFormat.Format32bppArgb);
                
                using (var g = Graphics.FromImage(bmp))
                {
                    g.InterpolationMode = InterpolationMode;
                    g.Transform = graphics.Transform.Clone();

                    var extent = new Extent(map.Envelope.MinX, map.Envelope.MinY, 
                                            map.Envelope.MaxX, map.Envelope.MaxY);
                    var level = BruTile.Utilities.GetNearestLevel(_source.Schema.Resolutions, map.PixelSize);
                    var tiles = new List<TileInfo>(_source.Schema.GetTilesInView(extent, level));
                    var tileWidth = _source.Schema.GetTileWidth(level);
                    var tileHeight = _source.Schema.GetTileWidth(level);

                    IList<WaitHandle> waitHandles = new List<WaitHandle>();
                    var toRender = new Dictionary<TileIndex, Bitmap>();
                    var takenFromCache = new Dictionary<TileIndex,bool>();
                    foreach (TileInfo info in tiles)
                    {
                        var image = _bitmaps.Find(info.Index);
                        if (image != null)
                        {
                            toRender.Add(info.Index, image);
                            takenFromCache.Add(info.Index,true);
                            continue;
                        }
                        if (_fileCache != null && _fileCache.Exists(info.Index))
                        {
                            _bitmaps.Add(info.Index, GetImageFromFileCache(info) as Bitmap);
                            toRender.Add(info.Index, _bitmaps.Find(info.Index));
                            takenFromCache.Add(info.Index,true);
                            continue;
                        }

                        var waitHandle = new AutoResetEvent(false);
                        waitHandles.Add(waitHandle);
                        ThreadPool.QueueUserWorkItem(GetTileOnThread,
                                                     new object[] { _source.Provider, info, toRender, waitHandle, true });
                    }

                    foreach (var handle in waitHandles)
                        handle.WaitOne();

                    using (var ia = new ImageAttributes())
                    {
                        if (!_transparentColor.IsEmpty)
                            ia.SetColorKey(_transparentColor, _transparentColor);
#if !PocketPC
                        ia.SetWrapMode(WrapMode.TileFlipXY);
#endif

                        foreach (var info in tiles)
                        {
                            if (!toRender.ContainsKey(info.Index))
                                continue;

                            var bitmap = toRender[info.Index];//_bitmaps.Find(info.Index);
                            if (bitmap == null) continue;

                            var min = map.WorldToImage(new Coordinate(info.Extent.MinX, info.Extent.MinY));
                            var max = map.WorldToImage(new Coordinate(info.Extent.MaxX, info.Extent.MaxY));

                            min = new PointF((float) Math.Round(min.X), (float) Math.Round(min.Y));
                            max = new PointF((float) Math.Round(max.X), (float) Math.Round(max.Y));

                            try
                            {
                                g.DrawImage(bitmap,
                                            new Rectangle((int) min.X, (int) max.Y, (int) (max.X - min.X),
                                                          (int) (min.Y - max.Y)),
                                            0, 0, tileWidth, tileHeight,
                                            GraphicsUnit.Pixel,
                                            ia);
                            }
                            catch (Exception ee)
                            {
                                Logger.Error(ee.Message);
                            }

                        }
                    }

                    //Add rendered tiles to cache
                    foreach (var kvp in toRender)
                    {
                        if (takenFromCache.ContainsKey(kvp.Key) && !takenFromCache[kvp.Key])
                        {
                            _bitmaps.Add(kvp.Key, kvp.Value);
                        }
                    }

                    graphics.Transform = new Matrix();
                    graphics.DrawImageUnscaled(bmp, 0, 0);
                    graphics.Transform = g.Transform;
                }
            }
        }
 private static DsExtent FromBruTileExtent(BtExtent extent)
 {
     return(new DsExtent(extent.MinX, extent.MinY, extent.MaxX, extent.MaxY));
 }
Exemple #41
0
        /// <summary>
        /// Returns a List of TileInfos that cover the provided extent.
        /// </summary>
        public IList <TileInfo> GetTilesInView(Extent extent, double resolution)
        {
            int level = Utilities.GetNearestLevel(Resolutions, resolution);

            return(GetTilesInView(extent, level));
        }
Exemple #42
0
 public IEnumerable <TileInfo> GetTileInfos(Extent extent, string levelId)
 {
     return(GetTileInfos(this, extent, levelId));
 }
Exemple #43
0
        public bool Equals(Extent extent)
        {
            if (this.minX != extent.minX)
            {
                return false;
            }

            if (this.minY != extent.minY)
            {
                return false;
            }

            if (this.maxX != extent.maxX)
            {
                return false;
            }

            if (this.maxY != extent.maxY)
            {
                return false;
            }

            return true;
        }
        private List<TileInfo> GetTile()
        {
            var schema = _tileSource.Schema;
            IEnvelope pEnvelope = new EnvelopeClass();
            ISpatialReferenceFactory pSpatRefFact = new SpatialReferenceEnvironmentClass();
            pEnvelope.SpatialReference = pSpatRefFact.CreateGeographicCoordinateSystem(4326);
            pEnvelope.XMin = extent[0];
            pEnvelope.XMax = extent[2];
            pEnvelope.YMin = extent[1];
            pEnvelope.YMax = extent[3];

            var env = Projector.ProjectEnvelope(pEnvelope, schema.Srs);

            var mapWidth = 256 * num;
            var mapHeight = 256 * num;
            float resolution = (float)level;

            var centerPoint = env.GetCenterPoint();

            var transform = new Transform(centerPoint, resolution, mapWidth, mapHeight);
            Extent exte = new Extent(pEnvelope.XMin, pEnvelope.YMin, pEnvelope.XMax, pEnvelope.YMax);
            var level1 = Utilities.GetNearestLevel(schema.Resolutions, transform.Resolution);

            var tempExtent = new Extent(12597408.0986328, 2623556.09863281, 12629205.9013672, 2655353.90136719);
            var tiles = schema.GetTilesInView(tempExtent, 10);

            return tiles.ToList();
        }
Exemple #45
0
        public override void Render(Graphics graphics, Map map)
        {
            Bitmap bmp = new Bitmap(map.Size.Width, map.Size.Height, PixelFormat.Format32bppArgb);
            Graphics g = Graphics.FromImage(bmp);

            g.InterpolationMode = InterpolationMode;
            g.Transform = graphics.Transform.Clone();

            Extent extent = new Extent(map.Envelope.Min.X, map.Envelope.Min.Y, map.Envelope.Max.X, map.Envelope.Max.Y);
            int level = BruTile.Utilities.GetNearestLevel(_source.Schema.Resolutions, map.PixelSize);
            IList<TileInfo> tiles = _source.Schema.GetTilesInView(extent, level);
            
            IList<WaitHandle> waitHandles = new List<WaitHandle>();

            foreach (TileInfo info in tiles)
            {
                if (_bitmaps.Find(info.Index) != null) continue;
                AutoResetEvent waitHandle = new AutoResetEvent(false);
                waitHandles.Add(waitHandle);
                ThreadPool.QueueUserWorkItem(GetTileOnThread, new object[] { _source.Provider, info, _bitmaps, waitHandle });
            }

            foreach (WaitHandle handle in waitHandles)
                handle.WaitOne();

            foreach (TileInfo info in tiles)
            {
                Bitmap bitmap = _bitmaps.Find(info.Index);
                if (bitmap == null) continue;

                PointF min = map.WorldToImage(new Geometries.Point(info.Extent.MinX, info.Extent.MinY));
                PointF max = map.WorldToImage(new Geometries.Point(info.Extent.MaxX, info.Extent.MaxY));

                min = new PointF((float)Math.Round(min.X), (float)Math.Round(min.Y));
                max = new PointF((float)Math.Round(max.X), (float)Math.Round(max.Y));

                g.DrawImage(bitmap,
                    new Rectangle((int)min.X, (int)max.Y, (int)(max.X - min.X), (int)(min.Y - max.Y)),
                    0, 0, _source.Schema.Width, _source.Schema.Height,
                    GraphicsUnit.Pixel,
                    _imageAttributes);

            }

            graphics.Transform = new Matrix();
            graphics.DrawImageUnscaled(bmp, 0, 0);
            graphics.Transform = g.Transform;

            g.Dispose();
        }
Exemple #46
0
        public static void Cache(TileDownloadOptions options, List <double[]> boundsList, BruTile.Web.HttpTileSource tileSource)
        {
            double[] originalBounds = new double[4] {
                double.MaxValue, double.MaxValue, double.MinValue, double.MinValue
            };                                                                                                              // In WGS1984, the total extent of all bounds

            List <TileInfo> tileInfos = new List <TileInfo>();

            foreach (double[] xy in boundsList)
            {
                if (xy[0] < originalBounds[0])
                {
                    originalBounds[0] = xy[0];
                }
                if (xy[1] < originalBounds[1])
                {
                    originalBounds[1] = xy[1];
                }
                if (xy[2] > originalBounds[2])
                {
                    originalBounds[2] = xy[2];
                }
                if (xy[3] > originalBounds[3])
                {
                    originalBounds[3] = xy[3];
                }

                ToMercator(ref xy[0], ref xy[1]);
                ToMercator(ref xy[2], ref xy[3]);

                // xy is now in SphericalMercator projection

                BruTile.Extent extent = new BruTile.Extent(xy[0], xy[1], xy[2], xy[3]);

                var curTileInfos = tileSource.Schema.GetTileInfos(extent, options.Level.ToString());

                foreach (var tileInfo in curTileInfos)
                {
                    TileInfo ti = tileInfos.Where(x => x.Index.Col == tileInfo.Index.Col && x.Index.Row == tileInfo.Index.Row && x.Index.Level == tileInfo.Index.Level).FirstOrDefault();

                    if (ti != null) // This tile is already in the list
                    {
                        continue;
                    }

                    tileInfos.Add(tileInfo);
                }
            }

            if (options.MaxAge.HasValue)
            {
                using (var db = new SQLite.SQLiteConnection(options.DBFilename))
                {
                    // Create the tables, so at least they will exist
                    db.CreateTable <MBTiles.Domain.metadata>();
                    db.CreateTable <MBTiles.Domain.tiles>();

                    for (int i = 0; i < tileInfos.Count; i++)
                    {
                        TileInfo tileInfo = tileInfos[i];

                        int tileLevel = int.Parse(tileInfo.Index.Level);
                        int tileRow   = OSMtoTMS(tileLevel, tileInfo.Index.Row);
                        MBTiles.Domain.tiles oldTile = db.Table <MBTiles.Domain.tiles>().Where(x => x.zoom_level == tileLevel && x.tile_column == tileInfo.Index.Col && x.tile_row == tileRow).FirstOrDefault();

                        if (oldTile != null && (DateTime.Now - oldTile.createDate) <= options.MaxAge.Value)
                        {
                            // This tile hasn't expired yet, so don't download it.
                            tileInfos.Remove(tileInfo);
                            i--;
                        }
                    }
                }
            }

            // Make sure we have any tiles left to download. If not, we are done!
            if (tileInfos.Count == 0)
            {
                return;
            }

            ConcurrentBag <LoadedTile> bag = new ConcurrentBag <LoadedTile>();

            using (System.Net.Http.HttpClient client = new System.Net.Http.HttpClient())
            {
                List <Task> fetchTasks = new List <Task>();
                foreach (var ti in tileInfos)
                {
                    fetchTasks.Add(Task.Run(async() => await FetchTile(ti, client, bag, options.UriFormat)));

                    if (fetchTasks.Count > 1) // Limit 2 to concurrent download threads
                    {
                        Task.WaitAll(fetchTasks.ToArray());
                        fetchTasks.Clear();
                    }
                }

                Task.WaitAll(fetchTasks.ToArray());
            }

            using (var db = new SQLite.SQLiteConnection(options.DBFilename))
            {
                db.CreateTable <MBTiles.Domain.metadata>();
                db.CreateTable <MBTiles.Domain.tiles>();

                var metaList = new List <MBTiles.Domain.metadata>();

                metaList.Add(new MBTiles.Domain.metadata {
                    name = "name", value = options.DBName
                });
                metaList.Add(new MBTiles.Domain.metadata {
                    name = "type", value = "baselayer"
                });
                metaList.Add(new MBTiles.Domain.metadata {
                    name = "version", value = "1"
                });
                metaList.Add(new MBTiles.Domain.metadata {
                    name = "description", value = options.DBDescription
                });
                metaList.Add(new MBTiles.Domain.metadata {
                    name = "format", value = bag.First().mimeType.Contains("/png") ? "png" : "jpg"
                });

                foreach (var meta in metaList)
                {
                    db.InsertOrReplace(meta);
                }

                // Expand the bounds
                var existingBounds = db.Table <MBTiles.Domain.metadata>().Where(x => x.name == "bounds").FirstOrDefault();
                if (existingBounds != null)
                {
                    var components     = existingBounds.value.Split(',');
                    var existingExtent = new double[4] {
                        double.Parse(components[0], NumberFormatInfo.InvariantInfo),
                        double.Parse(components[1], NumberFormatInfo.InvariantInfo),
                        double.Parse(components[2], NumberFormatInfo.InvariantInfo),
                        double.Parse(components[3], NumberFormatInfo.InvariantInfo)
                    };

                    if (originalBounds[0] < existingExtent[0])
                    {
                        existingExtent[0] = originalBounds[0];
                    }
                    if (originalBounds[1] < existingExtent[1])
                    {
                        existingExtent[1] = originalBounds[1];
                    }
                    if (originalBounds[2] > existingExtent[2])
                    {
                        existingExtent[2] = originalBounds[2];
                    }
                    if (originalBounds[3] > existingExtent[3])
                    {
                        existingExtent[3] = originalBounds[3];
                    }

                    existingExtent.CopyTo(originalBounds, 0);
                }

                db.InsertOrReplace(new MBTiles.Domain.metadata {
                    name = "bounds", value = String.Join(",", originalBounds)
                });

                foreach (var lt in bag)
                {
                    MBTiles.Domain.tiles tile = new MBTiles.Domain.tiles();
                    tile.zoom_level  = int.Parse(lt.ti.Index.Level);
                    tile.tile_column = lt.ti.Index.Col;
                    tile.tile_row    = lt.ti.Index.Row;
                    tile.tile_data   = lt.data;
                    tile.createDate  = DateTime.Now;

                    tile.tile_row = OSMtoTMS(tile.zoom_level, tile.tile_row);

                    MBTiles.Domain.tiles oldTile = db.Table <MBTiles.Domain.tiles>().Where(x => x.zoom_level == tile.zoom_level && x.tile_column == tile.tile_column && x.tile_row == tile.tile_row).FirstOrDefault();

                    if (oldTile != null)
                    {
                        tile.id = oldTile.id;
                        db.Update(tile);
                    }
                    else
                    {
                        db.Insert(tile);
                    }
                }
            }
        }