ArcGISで動的タイル生成


動的にタイル生成しながら描画する方法
ArcGISでタイルを作成する方法

画像は自分で描画して、随時DBに格納するようなことができるが、まあ初回の人が遅いので要件として許容されるか次第か。

コードは下記

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

public class CookerLayer : ILayer
{
  private string m_Name = "CookerLayer";

  private double m_MinScale = 0;
  private double m_MaxScale = 0;

  private bool m_Visible = true;

  private IEnvelope m_AOI = null;

  private ISpatialReference m_SpRef = null;

  private IMapCooker2 m_Cooker = null;

  private IMap m_Map = null;

  public CookerLayer(string mxdPath)
  {
    IMap map = null;
    using (ComReleaser com = new ComReleaser())
    {
      IMapDocument mapDoc = new MapDocumentClass();
      com.ManageLifetime(mapDoc);//解放予約

      mapDoc.Open(mxdPath, null);

      map = mapDoc.get_Map(0);
      this.m_AOI = ((IActiveView)map).FullExtent;
      //base.ManageLifetime(this.m_AOI);//TODO:解放予約

      mapDoc.Close();
    }//end com
    this.m_Map = map;
    //base.ManageLifetime(this.m_Map);//TODO:解放予約

    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);//TODO:解放予約
    IEnvelope envelope = (IEnvelope)this.readFromXML(cdiPath);
    //base.ManageLifetime(envelope);//TODO:解放予約
    ICacheDatasetInfo cacheDatasetInfo = new CacheDatasetInfoClass();
    //base.ManageLifetime(cacheDatasetInfo);//TODO:解放予約
    cacheDatasetInfo.Extent = envelope;

    IMapCooker2 mapCooker = new MapCookerClass();
    //base.ManageLifetime(mapCooker);//TODO:解放予約

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

    ((IMapCooker3)mapCooker).CacheStorageInfo.StorageFormat = esriMapCacheStorageFormat.esriMapCacheStorageModeCompact;

    mapCooker.Extent = envelope;
    mapCooker.Path = tempDir;

    mapCooker.Antialiasing = true;
    //mapCooker.CacheOnDemand = true;

    this.m_Cooker = mapCooker;
  }//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

  //-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-
  #region ILayer メンバ
  //-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-

  public void Draw(esriDrawPhase drawPhase, IDisplay display, ITrackCancel trackCancel)
  {
    using (ComReleaser com = new ComReleaser())
    {
      IMapCooker2 mapCooker = this.m_Cooker;
      IMap map = this.m_Map;
      List<int> lods = new List<int>(2);
      int lastLevel = int.MinValue;
      for (int i = 0; i < mapCooker.TileCacheInfo.LODInfos.Count; i++)
      {
        var lod = mapCooker.TileCacheInfo.LODInfos.get_Element(i);
        lastLevel = lod.LevelID;

        if (lod.Scale < display.DisplayTransformation.ScaleRatio)
        {
          lods.Add(lod.LevelID);
          if (lod.LevelID > 0)
            lods.Add(lod.LevelID - 1);
          break;
        }//end if
      }//end loop レベル詳細
      if (lods.Count < 1 && lastLevel != int.MinValue)
      {
        lods.Add(lastLevel);
        lods.Add(lastLevel - 1);
      }

      IGeometry updateGeom = null;
      if (display is IScreenInvalidate)
      {
        updateGeom = ((IScreenInvalidate)display).InvalidArea as IGeometry;
      }
      if (updateGeom == null)
      {
        updateGeom = display.DisplayTransformation.VisibleBounds;
      }

      //空間参照が異なる場合はセット
      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();
        com.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の指定が不正です。");

      mapCooker.UpdateByGeometry(map, null, display, updateGeom, longArray, esriMapCacheUpdateMode.esriMapCacheUpdateRecreateAll, trackCancel);

      this.m_Cooker.Draw(null, display, trackCancel);
    }
  }//end if

  public IEnvelope AreaOfInterest
  {
    get { return this.m_AOI; }
  }

  public double MaximumScale
  {
    get
    {
      return this.m_MaxScale;
    }
    set
    {
      this.m_MaxScale = value;
    }
  }

  public double MinimumScale
  {
    get
    {
      return this.m_MinScale;
    }
    set
    {
      this.m_MinScale = value;
    }
  }

  public string Name
  {
    get
    {
      return this.m_Name;
    }
    set
    {
      this.m_Name = value;
    }
  }

  public bool Cached
  {
    get
    {
      return false;
    }
    set
    {

    }
  }

  public bool ShowTips
  {
    get
    {
      return false;
    }
    set
    {
      //value;
    }
  }

  public ISpatialReference SpatialReference
  {
    set { this.m_SpRef = value; }
  }

  public int SupportedDrawPhases
  {
    get { return (int)esriDrawPhase.esriDPGeography; }
  }

  public bool Valid
  {
    get { return true; }
  }

  public bool Visible
  {
    get
    {
      return this.m_Visible;
    }
    set
    {
      this.m_Visible = value;
    }
  }

  public string get_TipText(double x, double y, double Tolerance)
  {
    return null;
  }//end method

  //-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-
  #endregion ILayer メンバ
  //-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-
}//end class
カテゴリー: 開発 タグ: パーマリンク