ArcGISでタイルを作成する方法


ArcGIS for ServerがあればGUIで出来るがない場合はAPIのみとなるよう。

公式サンプル
http://help.arcgis.com/en/sdk/10.0/arcobjects_net/conceptualhelp/index.html#//000100000mmm000000

APIリファレンス
http://resources.arcgis.com/en/help/arcobjects-net/componenthelp/index.html#/IMapCooker2_Interface/001200000861000000/
DrawメソッドやCacheOnDemandプロパティがあるので動的生成も出来そうな雰囲気。
[Available with ArcGIS Engine, ArcGIS Desktop, and ArcGIS Server]

サンプルが使い勝手悪そうなので適当にまとめてみた。

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using ESRI.ArcGIS.ADF;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Display;
using ESRI.ArcGIS.esriSystem;
using ESRI.ArcGIS.Geometry;
using sysIO = System.IO;

public class MapCookerUtil : DisposableBase
{
  private IMapCooker2 m_Cooker = null;

  public MapCookerUtil()
  {
    string tempDir = sysIO.Path.GetTempPath();
    tempDir = sysIO.Path.Combine(tempDir, Guid.NewGuid().ToString());

    if (!sysIO.Directory.Exists(tempDir))
    {
      sysIO.Directory.CreateDirectory(tempDir);
    }
    Debug.Print("一時ディレクトリ:{0}", tempDir);

    ///設定ファイル読み込み
    const string CONF_PATH = @"conf\conf.xml";
    const string CONF_CDI_PATH = @"conf\conf.cdi";

    Assembly asm = Assembly.GetExecutingAssembly();
    string dirBase = sysIO.Path.GetDirectoryName(asm.Location);

    string confPath = sysIO.Path.Combine(dirBase, CONF_PATH);
    string cdiPath = sysIO.Path.Combine(dirBase, CONF_CDI_PATH);

    if (!sysIO.File.Exists(confPath) || !sysIO.File.Exists(cdiPath))
    {
      throw new sysIO.FileNotFoundException(confPath + Environment.NewLine + cdiPath + Environment.NewLine + "が見つかりません。");
    }//end if

    string confCp = sysIO.Path.Combine(tempDir, sysIO.Path.GetFileName(confPath));
    string cdiCp = sysIO.Path.Combine(tempDir, sysIO.Path.GetFileName(cdiPath));
    //ファイルコピー
    sysIO.File.Copy(confPath, confCp);
    sysIO.File.Copy(cdiPath, cdiCp);

    ICacheInfo cacheInfo = (ICacheInfo)this.readFromXML(confPath);
    base.ManageLifetime(cacheInfo);//解放をマーク
    IEnvelope envelope = (IEnvelope)this.readFromXML(cdiPath);
    base.ManageLifetime(envelope);//解放をマーク
    ICacheDatasetInfo cacheDatasetInfo = new CacheDatasetInfoClass();
    base.ManageLifetime(cacheDatasetInfo);//解放をマーク
    cacheDatasetInfo.Extent = envelope;

    IMapCooker2 mapCooker = new MapCookerClass();
    base.ManageLifetime(mapCooker);//解放をマーク

    //変数をセット
    mapCooker.TileCacheInfo = cacheInfo.TileCacheInfo;
    mapCooker.TileImageInfo = cacheInfo.TileImageInfo;
    ((IMapCooker3)mapCooker).CacheDatasetInfo = cacheDatasetInfo;
    ((IMapCooker3)mapCooker).CacheStorageInfo = ((ICacheInfo2)cacheInfo).CacheStorageInfo;
    mapCooker.Extent = envelope;
    mapCooker.Path = tempDir;

    mapCooker.Antialiasing = true;

    this.m_Cooker = mapCooker;
  }

  public void Excute(IMap map, IGeometry updateGeom, List<int> lods)
  {
    using (ComReleaser com = new ComReleaser())
    {
      IMapCooker2 mapCooker = this.m_Cooker;
      lock (map)
      {
        //空間参照が異なる場合はセット
        if (map.SpatialReference.FactoryCode != mapCooker.TileCacheInfo.SpatialReference.FactoryCode)
        {
          map.SpatialReference = mapCooker.TileCacheInfo.SpatialReference;
        }
        if (updateGeom.SpatialReference == null)
        {
          updateGeom.SpatialReference = map.SpatialReference;
        }
        if (updateGeom.SpatialReference.FactoryCode != map.SpatialReference.FactoryCode)
        {
          updateGeom = (IGeometry)((IClone)updateGeom).Clone();
          base.ManageLifetime(updateGeom);
          updateGeom.Project(map.SpatialReference);
        }
      }

      ILongArray longArray = new LongArrayClass();
      com.ManageLifetime(longArray);//解放をマーク

      ILODInfos lodInfos = mapCooker.TileCacheInfo.LODInfos;
      for (int i = 0; i < lodInfos.Count; i++)
      {
        ILODInfo lod = lodInfos.get_Element(i);
        if (lods == null || lods.Count < 1)
        {
          longArray.Add(lod.LevelID);
        }
        else if (lods.Contains(lod.LevelID))
        {
          longArray.Add(lod.LevelID);
        }//end if
      }//end loop
      if (longArray.Count < 1)
        throw new ArgumentException("Lodの指定が不正です。");

      IDisplay display = new SimpleDisplayClass();
      com.ManageLifetime(display);//解放をマーク
      display.DisplayTransformation.SpatialReference = ((IActiveView)map).ScreenDisplay.DisplayTransformation.SpatialReference;
      display.DisplayTransformation.Units = ((IActiveView)map).ScreenDisplay.DisplayTransformation.Units;
      display.DisplayTransformation.ZoomResolution = ((IActiveView)map).ScreenDisplay.DisplayTransformation.ZoomResolution;

      display.DisplayTransformation.Bounds = ((IActiveView)map).ScreenDisplay.DisplayTransformation.Bounds;
      display.DisplayTransformation.ReferenceScale = ((IActiveView)map).ScreenDisplay.DisplayTransformation.ReferenceScale;

      //IDisplay display = ((IActiveView)map).ScreenDisplay; 

      mapCooker.UpdateByGeometry(map, null, display, updateGeom, longArray, esriMapCacheUpdateMode.esriMapCacheUpdateRecreateAll, null);
    }
  }//end method

  /// <summary>
  /// 
  /// </summary>
  /// <param name="filePath"></param>
  /// <returns></returns>
  private object readFromXML(string filePath)
  {
    using (ComReleaser com = new ComReleaser())
    {
      IXMLStream xmlStream = new XMLStreamClass();
      com.ManageLifetime(xmlStream);//解放をマーク
      xmlStream.LoadFromFile(filePath);
      xmlStream.Reset();

      IXMLReader xmlReader = new XMLReaderClass();
      com.ManageLifetime(xmlReader);//解放をマーク
      xmlReader.ReadFrom(xmlStream as IStream);
      IXMLSerializer xmlSerializer = new XMLSerializerClass();
      com.ManageLifetime(xmlSerializer);//解放をマーク

      return xmlSerializer.ReadObject(xmlReader, null, null);
    }//end com
  }//end method
}//end class
カテゴリー: 開発 タグ: パーマリンク