MBTiles Viewer


ArcGIS Runtime WPFでMBTiles Viewerを作成 (Basic – 無料版でも動く)

確認テストデータは下記でダウンロード
http://projects.bryanmcbride.com/ol_mbtiles/

※Download the MBTiles sqlite database fileのリンク先ファイル

MBTileViewer

NugetでSystem.Data.SQLiteを入れている。

Install-Package System.Data.SQLite

コードは下記

レイヤ実装

using ESRI.ArcGIS.Client;
using ESRI.ArcGIS.Client.Geometry;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SQLite;
using System.Diagnostics;
using System.IO;
using System.Windows.Media;
using System.Windows.Media.Imaging;

namespace MBTileViewer.Layers
{
  public class MBTileLayer : 
    TiledLayer //, 
    //IDisposable
  {
    SQLiteConnection m_Con = null;

    public MBTileLayer(string path)
    {
      this.m_Con = new SQLiteConnection("Data Source=" + path + ";Version=3;");
      this.m_Con.Open();

      //http://services.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer
      TileInfo info = new TileInfo();
      info.Height = 256;
      info.Width = 256;
      info.Origin = new MapPoint(-20037508.342787, 20037508.342787);
      List<Lod> lods = new List<Lod>();
      double res = 156543.033928 * 2;
      for (int i = 0; i < 19; i++)
      {
        Lod lod = new Lod();
        lod.Resolution = res / 2;
        res = lod.Resolution;

        lods.Add(lod);
      }//end loop
      info.Lods = lods.ToArray();

      //http://help.arcgis.com/en/arcgisserver/10.0/help/arcgis_server_dotnet_help/index.html#/Designing_a_map_to_overlay_ArcGIS_Online_services_Google_Maps_and_Bing_Maps/009300001571000000/
      //WGS 1984 Web Mercator (Auxiliary Sphere) WKID 102100
      info.SpatialReference = new SpatialReference(102100);

      this.TileInfo = info;
      this.SpatialReference = info.SpatialReference;
      this.FullExtent = new Envelope(-20037507.0671618, -19971868.8804086, 20037507.0671618, 19971868.8804086);
      this.FullExtent.SpatialReference = info.SpatialReference;

      this.Initialize();
      this.IsInitialized = true;
    }

    protected override void GetTileSource(int level, int row, int col, Action<ImageSource> onComplete)
    {
      var con = this.m_Con;
      using (var cmd = con.CreateCommand())
      {
        int gRow = (int)((Math.Pow(2, level) - 1) - row);

        cmd.CommandType = CommandType.Text;
        cmd.CommandText = "SELECT tile_data FROM tiles WHERE zoom_level=@1 AND tile_row=@2 AND tile_column=@3";

        Debug.WriteLine(cmd.CommandText);
        Debug.WriteLine("L={0} C={1} R={2}", level, row, col);

        var param1 = cmd.CreateParameter();
        var param2 = cmd.CreateParameter();
        var param3 = cmd.CreateParameter();
        param1.ParameterName = "@1";
        param2.ParameterName = "@2";
        param3.ParameterName = "@3";

        param1.Value = level;
        param2.Value = gRow;
        param3.Value = col;

        cmd.Parameters.Add(param1);
        cmd.Parameters.Add(param2);
        cmd.Parameters.Add(param3);

        byte[] imgData = null;
        using (var reader = cmd.ExecuteReader())
        {
          if (!reader.HasRows ||
              !reader.Read() ||
              !(reader[0] is byte[]))
          {
            onComplete(null);
            return;
          }
          imgData = (byte[])reader[0];

          BitmapImage biImg = new BitmapImage();
          MemoryStream ms = new MemoryStream(imgData);
          biImg.BeginInit();
          biImg.StreamSource = ms;
          biImg.EndInit();

          onComplete((ImageSource)biImg);
        }//end reader

      }//end cmd

    }//end metho

    public override Envelope FullExtent
    {
      get
      {
        return base.FullExtent;
      }
      protected set
      {
        base.FullExtent = value;
      }
    }
  }//end class
}//end namespace

XAML UI定義

<Window x:Class="MBTileViewer.MainWindow"
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:esri="http://schemas.esri.com/arcgis/client/2009"
        Title="MainWindow" Height="350" Width="525">
  <Grid>
    <esri:Map x:Name="_map" UseAcceleratedDisplay="False">
      <!-- ArcGIS Online Tiled Basemap Layer -->
      <esri:ArcGISTiledMapServiceLayer ID="World Topo Map" 
                       Url="http://services.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer"/>
    </esri:Map>
    <Menu VerticalAlignment="Top" >
      <MenuItem Header="ファイル">
        <MenuItem x:Name="fileOpen" Header="開く" />
        <MenuItem x:Name="clearLayer" Header="クリア" />
        <MenuItem x:Name="exit" Header="終了" />
      </MenuItem>
    </Menu>
  </Grid>
</Window>

CS UI 実装

using ESRI.ArcGIS.Client;
using MBTileViewer.Layers;
using Microsoft.Win32;
using System.Collections.Generic;
using System.Windows;

namespace MBTileViewer
{

  public partial class MainWindow : Window
  {
    public MainWindow()
    {
      // License setting and ArcGIS Runtime initialization is done in Application.xaml.cs.

      InitializeComponent();

      this.fileOpen.Click += onFileOpenClick;
      this.clearLayer.Click += onClearLayerClick;
      this.exit.Click += onExitClick;
    }

    void onFileOpenClick(object sender, RoutedEventArgs e)
    {
      OpenFileDialog openDig = new OpenFileDialog();
      openDig.Filter = "マップボックス タイル ファイル(*.mbtiles;*.db)|*.mbtiles;*.db|すべてのファイル(*.*)|*.*";
      openDig.Title = "タイルをc1-28552?択";
      var res = openDig.ShowDialog();
      if (res == null || !res.HasValue || !res.Value)
        return;

      MBTileLayer mbLayer = new MBTileLayer(openDig.FileName);
      this._map.Layers.Add(mbLayer);

    }//end method

    void onClearLayerClick(object sender, RoutedEventArgs e)
    {
      Map map = this._map;
      List<MBTileLayer> delLayers = new List<MBTileLayer>();
      foreach (var layer in map.Layers)
      {
        if (layer is MBTileLayer)
        {
          delLayers.Add((MBTileLayer)layer);
        }//end if
      }//end loop レイヤ
      foreach (var del in delLayers)
      {
        map.Layers.Remove(del);
      }//end loop レイヤ
      delLayers.Clear();
      delLayers = null;

    }//end method

    void onExitClick(object sender, RoutedEventArgs e)
    {
      this.Close();
    }//end method

  }//end class
}//end method
カテゴリー: 開発 タグ: , パーマリンク