File Geodatabase API => OGC

https://github.com/geobabbler/FgdbExtensions
GeoJSONまでは可能

あとは参考にして→WKB自作しとくか
https://postgis.net/docs/ST_GeomFromGeoJSON.html
で読み込むなりでArcGISなくともSFA Geometryにできる。

下記のようにGeoJSONからWKBも参考にはなるがZMとか対応は自分でする必要あり。
https://github.com/gksource/GeoJSON.Net.Contrib.EF

FileGeodatabaseAPI自体は下記からダウンロード可能
https://github.com/Esri/file-geodatabase-api

一致する「C++再頒布 可能パッケージ」がありゃ動き
.NETのラッピング付きでサンプルもついてる。
.NET Core用に.NET StandardでNugetにあげてくれればいうことないけど。。

カテゴリー: 開発, 設計 | タグ: , | File Geodatabase API => OGC はコメントを受け付けていません

“the ESRI flag”

https://postgis.net/docs/ST_IsValidDetail.html

Consider self-intersecting rings forming holes as valid. This is also know as “the ESRI flag”. Note that this is against the OGC model.

ジオメトリの修正
https://pro.arcgis.com/ja/pro-app/tool-reference/data-management/repair-geometry.htm

OGCのジオメトリの持ち方とESRIの持ち方は違うので注意。
ArcPyでWKTとかとってもST_MakeValidとかMakeValid通すのがよさげ。

カテゴリー: 開発, 設計 | タグ: , | “the ESRI flag” はコメントを受け付けていません

Project呼び出しの速度差

都度、Projectとset_OutputSpatialReferenceの差。
まあ誤差。

Project:79309
set_OutputSpatialReference:78258

using (ComReleaser com = new ComReleaser())
{ 
	IMapDocument mapDoc = new MapDocumentClass();
	com.ManageLifetime(mapDoc);

	mapDoc.Open(@"c:\jpn.mxd");
	int loopcount = 100;

	var map = mapDoc.get_Map(0);
	var featureLayer = (IFeatureLayer)map.get_Layer(0);
	var fc = featureLayer.FeatureClass;

	IQueryFilter qFilter = new QueryFilterClass();
	com.ManageLifetime(qFilter);
	qFilter.WhereClause = "1 = 1";


	IFeature feature = null;
	IFeatureCursor cursor = null;//fc.Search(qFilter, true);
	//com.ManageLifetime(cursor);

	Type t = Type.GetTypeFromProgID("esriGeometry.SpatialReferenceEnvironment");
	ISpatialReferenceFactory srFactory = (ISpatialReferenceFactory)Activator.CreateInstance(t);

	var utm54srCode = ESRI.ArcGIS.Geometry.esriSRProjCS4Type.esriSRProjCS_JGD2000_UTM_Zone_54N;
	var sr = srFactory.CreateProjectedCoordinateSystem((int)utm54srCode);

	var spWatch = new Stopwatch();
	spWatch.Start();

	for (int i = 0; i < loopcount; i++)
	{
		spWatch.Stop();
		ComReleaser.ReleaseCOMObject(cursor);
		cursor = fc.Search(qFilter, true);
		spWatch.Start();

		while ((feature = cursor.NextFeature()) != null)
		{
			var geom = feature.Shape;
			geom.Project(sr);
		
			Marshal.FinalReleaseComObject(geom);
		}
	}

	spWatch.Stop();
	Console.WriteLine("Project:{0}", spWatch.ElapsedMilliseconds);


	qFilter.set_OutputSpatialReference(fc.ShapeFieldName, sr);

	Marshal.FinalReleaseComObject(cursor);
	cursor =null; //fc.Search(qFilter, true);
	//com.ManageLifetime(cursor);

	spWatch.Restart();

	for (int i = 0; i < loopcount; i++)
	{
		spWatch.Stop();
		ComReleaser.FinalReleaseComObject(cursor);
		cursor = fc.Search(qFilter, true);
		spWatch.Start();
		while ((feature = cursor.NextFeature()) != null)
		{
			var geom = feature.Shape;
			//geom.Project(sr);
		
			Marshal.FinalReleaseComObject(geom);
		}
	}

	spWatch.Stop();
	Console.WriteLine("set_OutputSpatialReference:{0}", spWatch.ElapsedMilliseconds);
}
カテゴリー: 開発 | タグ: | Project呼び出しの速度差 はコメントを受け付けていません

方向性

https://community.esri.com/ideas/12258

http://www.esri.com/about/events/uc/get-involved/q-and-a#id=1233
ArcGIS Serverは単独で存在しえないしPortal
ProはHosted以外管理しない方向

ユーザ=課金対象なのでブラウザアプリで完全公開以外はArcGIS使えないかな。。使い方的に。
自治体とかのデータ公開とかならDesktop + Onlineとかで良いかもしれんけど。
それ以外つらいよね。

使い方的には
ArcGIS DesktopないしPro / QGIS
OpenLayers /Leaflet.js とGeoServer/UMN MapServerを使い分けかな。

カテゴリー: 設計, 動向 | タグ: | 方向性 はコメントを受け付けていません

座標系お気に入り

ArcGISの座標系のお気に入り( User Profileに入るやつ )にPRJファイルを入れるコード。
昔はどこかにprjファイルが居た気がするけどいない & [地理座標]-[アジア]-みたいに選んでいたがイライラするので。

#!/usr/bin/python
# -*- coding: utf-8 -*-

import arcpy
import os
import codecs
import re

"""
出力対象パスを取得
%appdata%\ESRI\Desktop10.4\ArcMap\Coordinate Systems
Desktop10.4はバージョン次第
"""
def getCoordsPath():
  app_data_path = os.getenv('APPDATA')

  # バージョン取得
  arc_version = arcpy.GetInstallInfo()['Version']

  # 10.4.1などマイナーバージョンがついていたら10.4などに直す
  v_re = re.compile(r"(\d+)\.(\d+)\.(\d+)")
  m = v_re.match(arc_version)
  if m:
    arc_version = str(m.group(1)) + '.' + str(m.group(2))

  # ユーザディレクトリの取得
  pathBase = '{0}\\ESRI\\Desktop{1}\\ArcMap\\Coordinate Systems'.format(app_data_path, arc_version)
  return pathBase

"""
arcpy.SpatialReferenceをファイルに書出し
"""
def exportSpatialReference( sr, fileName):
  # 今一つ意味不明だが '文字' を "文字" にしとかないと読めないことがあるc1-225?
  with open(fileName, 'w') as prj_file:
    prj_file.write(sr.exportToString().replace("'", '"'))

"""
存在しなければディレクトリを作成
"""
def createDirIfNotExist(targetDir):
  if not os.path.isdir(targetDir):
    os.makedirs(targetDir)

"""
公共測量座標系の登録
"""
def createCS19( base_wkid, post_name, targetDir):
  for i in range(19):
    sr = arcpy.SpatialReference(base_wkid + i)
  
    fileName = os.path.join( targetDir, u'平面直角座標系_第' + str(i+1).zfill(2) + u'系(' + post_name + ').prj' )
    exportSpatialReference( sr, fileName )


"""
メインロジック
"""
def main():

  pathBase = getCoordsPath()
  print pathBase

  #----------------------------------------#
  #-------------    TOKYO    --------------#
  targetDir = os.path.join( pathBase, 'TOKYO' )
  #存在しなければTOKYOディレクトリを作成
  createDirIfNotExist(targetDir)

  sr = arcpy.SpatialReference(4301)
  fileName = os.path.join( targetDir, u'日本測地系(TOKYO).prj' )

  exportSpatialReference(sr, fileName)
  # 19座標系作成
  createCS19(30161, u'TOKYO', targetDir)

  #----------------------------------------#

  #----------------------------------------#
  #------------    JGD2000    -------------#
  targetDir = os.path.join( pathBase, 'JGD2000' )
  #存在しなければTOKYOディレクトリを作成
  createDirIfNotExist(targetDir)

  sr = arcpy.SpatialReference(4612)
  fileName = os.path.join( targetDir, u'日本測地系(JGD2000).prj' )

  exportSpatialReference(sr, fileName)
  # 19座標系作成
  createCS19(2443, u'JGD2000', targetDir)
  
  #----------------------------------------#

  #----------------------------------------#
  #------------    JGD2011    -------------#
  targetDir = os.path.join( pathBase, 'JGD2011' )
  #存在しなければTOKYOディレクトリを作成
  createDirIfNotExist(targetDir)

  sr = arcpy.SpatialReference(6668)
  fileName = os.path.join( targetDir, u'日本測地系(JGD2011).prj' )

  exportSpatialReference(sr, fileName)
  # 19座標系作成
  createCS19(6669, u'JGD2011', targetDir)
  
  #----------------------------------------#

  
  #----------------------------------------#
  #------------    WGS1984    -------------#

  targetDir = os.path.join( pathBase, 'WGS1984' )
  #存在しなければTOKYOディレクトリを作成
  createDirIfNotExist(targetDir)

  sr = arcpy.SpatialReference(3857)
  fileName = os.path.join( targetDir, u'WGS84 web mercator (auxiliary sphere).prj' )
  exportSpatialReference(sr, fileName)

  sr = arcpy.SpatialReference(4326)
  fileName = os.path.join( targetDir, u'WGS84.prj' )
  exportSpatialReference(sr, fileName)

  #----------------------------------------#

# メインロジックの呼び出し
if __name__ == '__main__':
    main()
カテゴリー: 開発環境 | タグ: , | 座標系お気に入り はコメントを受け付けていません

IMapServer

arcobjectsでローカルMSDからIMapServer作成の例
レンダリングエンジン違うらしいのでExportImageは通常より多少早いはず。
初期化遅いけども。。。

#!/usr/bin/env python
# -*- coding: cp932 -*-

import sys
import os
import arcpy

def main(argv):

  #sys.exit
  #文字列を指定すると、標準エラー出力に引数の内容を表示しつつプロセスの戻り値は0以外(正常ではない終了の値)になる
  if len(argv) != 2:
    sys.exit("Usage: %s <mxd path> <out msd path>" % sys.argv[0])
  if not os.path.exists(argv[0]):
    sys.exit('ERROR: file %s was not found!' % argv[0])

  #print argv[0]
  msddoc = argv[1]

  mapdoc = arcpy.mapping.MapDocument(argv[0])
  analysis = arcpy.mapping.AnalyzeForMSD(mapdoc)
  errs = analysis['errors']
  if (errs != {}):
    errmsg = "Analyzer Errors:"
    for k in errs.keys():
      errmsg += '\n\t' + k[0]

    sys.exit(errmsg)
  
  arcpy.mapping.ConvertToMSD(mapdoc, msddoc)


if __name__ == "__main__":
    main(sys.argv[1:])
using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;


using ESRI.ArcGIS;
using ESRI.ArcGIS.Carto;
using esri = ESRI.ArcGIS.Geometry;


class MapServiceUtil : IDisposable
{
  private string _mxdPath = null;

  private string _msdPath = null;


  private string _pythonPath = null;

  private IMapServer _mapServer;


  /// <summary>
  /// コンストラクタ
  /// </summary>
  /// <param name="mxdPaht"></param>
  public MapServiceUtil(string mxdPath)
  {
    var runtimes = RuntimeManager.InstalledRuntimes;
    var pythonPath = @"C:\Python27\ArcGISx64" + RuntimeManager.ActiveRuntime.Version.ToString() + @"\python.exe";

    this.init(mxdPath, pythonPath);
  }

  /// <summary>
  /// コンストラクタ
  /// </summary>
  /// <param name="mxdPath"></param>
  /// <param name="pythonPath"></param>
  public MapServiceUtil(string mxdPath, string pythonPath)
  {
    this.init(mxdPath, pythonPath);
  }

  /// <summary>
  /// 初期化
  /// </summary>
  /// <param name="mxdPath"></param>
  /// <param name="pythonPath"></param>
  private void init(string mxdPath, string pythonPath)
  {
    this._mxdPath = mxdPath;
    this._pythonPath = pythonPath;
    //MXDからMSDへ変換
    this.convertMXDToMSD();
    //マップサービスのセットアップ
    this.setupMapServer();
  }

  /// <summary>
  /// MXDからMSDへ変換
  /// </summary>
  private void convertMXDToMSD()
  {
    var mxdfile = this._mxdPath;
    var asm = System.Reflection.Assembly.GetExecutingAssembly();

    var dir = Path.GetDirectoryName(asm.Location);

    var scriptFile = Path.Combine(dir, "mxd2msd.py");
    var msdfile = Path.Combine(Path.GetDirectoryName(mxdfile), Path.GetFileNameWithoutExtension(mxdfile) + ".msd");
    this._msdPath = msdfile;

    ProcessStartInfo start = new ProcessStartInfo();
    start.FileName = this._pythonPath;
    start.Arguments = "\"" + string.Join("\" \"", new string[] { scriptFile, mxdfile, msdfile }) + "\"";
    start.UseShellExecute = false;
    start.RedirectStandardOutput = true;
    start.RedirectStandardInput = false;

    start.CreateNoWindow = true;

    using (Process process = Process.Start(start))
    {
      using (StreamReader reader = process.StandardOutput)
      {
        string result = reader.ReadToEnd();
        Console.Write(result);
      }

      process.WaitForExit();
      if (process.ExitCode != 0)
        throw new Exception("MSD変換ミス");
    }

  }

  /// <summary>
  /// マップサービス設定
  /// </summary>
  private void setupMapServer()
  {
    var msdfile = this._msdPath;

    IMapServer mapServer = Activator.CreateInstance(Type.GetTypeFromProgID("esriCartoX.MapServerX")) as IMapServer;
    IMapServerInit2 mapServerInit = (IMapServerInit2)mapServer;
    mapServerInit.PhysicalOutputDirectory = System.IO.Path.GetTempPath();
    mapServerInit.VirtualOutputDirectory = System.IO.Path.GetTempPath();

    mapServerInit.Connect(msdfile);
    this._mapServer = mapServer;
  }//end method

  /// <summary>
  /// かくにん
  /// </summary>
  public void Test()
  {
    var width = 800;
    var height = 600;

    var mapServer = this._mapServer;

    var mapInfo = (IMapServerInfo)mapServer.GetServerInfo(mapServer.DefaultMapName);
    var md = mapInfo.DefaultMapDescription;

    using (var com = new ESRI.ArcGIS.ADF.ComReleaser())
    {
      var it = new ImageTypeClass();
      com.ManageLifetime(it);

      it.Format = esriImageFormat.esriImagePNG32;
      it.ReturnType = esriImageReturnType.esriImageReturnMimeData;

      var imgDesplay = new ImageDisplayClass();
      com.ManageLifetime(imgDesplay);

      imgDesplay.Width = width;
      imgDesplay.Height = height;


      var imgDescription = new ImageDescriptionClass();
      com.ManageLifetime(imgDescription);

      imgDescription.Display = imgDesplay;
      imgDescription.Type = it;

      var mapExtent = new MapExtentClass();
      com.ManageLifetime(mapExtent);

      var env = new esri.EnvelopeClass();
      com.ManageLifetime(env);

      env.PutCoords(132.453504843, 34.387393538, 132.458544541, 34.391243506);
      mapExtent.IMapExtent_Extent = env;

      md.MapArea = mapExtent;

      var mapImg = mapServer.ExportMapImage(md, imgDescription);
      using (var mem = new MemoryStream(mapImg.MimeData))
      using (var img = System.Drawing.Bitmap.FromStream(mem))
      {
        img.Save(@"C:\temp\mapserver.png");
      }
    }
  }


  //----------------------------------------------------
  #region IDisposable Support
  private bool disposedValue = false; // 重複する呼び出しを検出するには

  protected virtual void Dispose(bool disposing)
  {
    if (!disposedValue)
    {
      if (disposing)
      {
        // TODO: マネージ状態を破棄します (マネージ オブジェクト)。
      }

      // TODO: アンマネージ リソース (アンマネージ オブジェクト) を解放し、下のファイナライザーをオーバーライドします。
      // TODO: 大きなフィールドを null に設定します。
      if (this._mapServer == null)
      {
        Marshal.FinalReleaseComObject(this._mapServer);
        this._mapServer = null;
      }

      disposedValue = true;
    }
  }

  // TODO: 上の Dispose(bool disposing) にアンマネージ リソースを解放するコードが含まれる場合にのみ、ファイナライザーをオーバーライドします。
  // ~MapServiceUtil() {
  //   // このコードを変更しないでください。クリーンアップ コードを上の Dispose(bool disposing) に記述します。
  //   Dispose(false);
  // }

  // このコードは、破棄可能なパターンを正しく実装できるように追加されました。
  public void Dispose()
  {
    // このコードを変更しないでください。クリーンアップ コードを上の Dispose(bool disposing) に記述します。
    Dispose(true);
    // TODO: 上のファイナライザーがオーバーライドされる場合は、次の行のコメントを解除してください。
    // GC.SuppressFinalize(this);
  }
  #endregion IDisposable Support
  //----------------------------------------------------
}
カテゴリー: 開発, 設計 | タグ: | IMapServer はコメントを受け付けていません

NTv2で変換したくない

仕様読んでる人は今更だが。。

https://en.wikipedia.org/wiki/NTv2

ArcGISでTKY2JGDとかしたい場合、NTv2変換方式になるけどこれ日本用じゃないから
パラメータファイルが適用される領域じゃないから出来るだけ使いたくない。

JGD2000はパラメータ範囲外はそうそうないからまあまあとしても
( と言っても地域によって標準偏差で何十メートルもずれると分かってるものを使いたいかと言うと… )

JGD2011なんて適用範囲外/混在の場合のPatchJGDとの違いが資料に記載されていない。。。
確認してないけどToJGD2000と同様なら
適用範囲外で使えないし、そもそも線形だからPatchJGD相当作ったほうがマシ

日本用用意しろよな。。。

例えばTKY2JGD
http://vldb.gsi.go.jp/sokuchi/surveycalc/tky2jgd/main.html

24.4684858
123.0049406

緯度 24.473970028
経度 123.005393642

4301 TOKYO
4612 J2000

108108 Tokyo_To_JGD_2000_NTv2

OnlineProject
http://tasks.arcgisonline.com/arcgis/rest/services/Geometry/GeometryServer/project
?inSR=4301+&outSR=4612+&
geometries=123.005393642%2C24.473970028&
transformation=108108%09&transformForward=true&f=html

{“geometries”: [{
“x”: 123.00584657763541,
“y”: 24.479453696160668
}]}

平面直角座標でこれ..

X座標 -168668.7495 m
Y座標 -100822.1235 m

X座標 -168061.6804 m
Y座標 -100771.8398 m

ちなみにNTv2バイナリとアスキー変換
https://github.com/Esri/ntv2-file-routines/blob/master/README.md

カテゴリー: 開発, 設計 | タグ: | NTv2で変換したくない はコメントを受け付けていません

FindFieldとDictionary

一回あたりは大したことないけどやはり遅い。
FindField:10910
Dictionary:278

10,000,000

using (ComReleaser com = new ComReleaser())
{ 
	IMapDocument mapDoc = new MapDocumentClass();
	com.ManageLifetime(mapDoc);

	mapDoc.Open(@"c:\jpn.mxd");

	var map = mapDoc.get_Map(0);
	var featureLayer = (IFeatureLayer)map.get_Layer(0);
	var fc = featureLayer.FeatureClass;

	var loopCount = 10000000;
	var fieldName = "SIKUCHOSON";

	Dictionary<string,int> fieldMap = new Dictionary<string,int>(){
				{ fieldName, fc.FindField(fieldName) }
	};

	var spWatch = new Stopwatch();
	spWatch.Start();

	for (int i = 0; i < loopCount; i++)
	{
		var finx = fc.FindField(fieldName);
	}//end loop

	spWatch.Stop();
	Console.WriteLine("FindField:{0}", spWatch.ElapsedMilliseconds);
	spWatch.Restart();

	for (int i = 0; i < loopCount; i++)
	{
		var finx = fieldMap[fieldName];
	}//end loop

	spWatch.Stop();
	Console.WriteLine("Dictionary:{0}", spWatch.ElapsedMilliseconds);
}
カテゴリー: 開発 | タグ: | FindFieldとDictionary はコメントを受け付けていません

QueryLayer初期化

FeatureClass取得は通常のが早いかな。。。
GetQueryDescriptionが遅すぎる?

OpenQueryClass:73
QUERY:6231
SDE:4827

OpenQueryClass:34
QUERY:856
SDE:503

OpenFromString:225
GetQueryDescription:311
OpenQueryClass:37
QUERY:853
OpenFeatureClass:113
SDE:496

Stopwatch spWatch = new Stopwatch();
spWatch.Start();

// Build a connection string.
String[] connectionProps = 
{
    "dbclient=SQLServer", 
    "serverinstance=ほすとめい", 
    "database=でーたべーす", 
    "authentication_mode=DBMS",
    "user=ゆーざ",
    "password=ぱすわーど"
};

String connString = String.Join(";", connectionProps);


String[] connectionPropsSDE = 
{
    "dbclient=SQLServer", 
    "SERVER=ほすとめい", 
    "DATABASE=でーたべーす", 
    "INSTANCE=sde:sqlserver:ほすとめい",
    "user=ゆーざ",
    "password=ぱすわーど",
    "VERSION=dbo.DEFAULT"
};

string sde_connString = String.Join(";", connectionPropsSDE);

using (var com = new ComReleaser())
{
    var openWatch = new Stopwatch();
    openWatch.Start();

    int srid = 4612;

    Type t = Type.GetTypeFromProgID("esriGeometry.SpatialReferenceEnvironment");
    ISpatialReferenceFactory spRefFactory = (ISpatialReferenceFactory)Activator.CreateInstance(t);
    com.ManageLifetime(spRefFactory);

    ISpatialReference spref = spRefFactory.CreateGeographicCoordinateSystem((int)esriSRGeoCS3Type.esriSRGeoCS_JapanGeodeticDatum2000);

    Type factoryType = Type.GetTypeFromProgID("esriDataSourcesGDB.SqlWorkspaceFactory");
    IWorkspaceFactory2 workspaceFactory2 = (IWorkspaceFactory2)Activator.CreateInstance(factoryType);

    // Open the workspace.
    IWorkspace workspace = workspaceFactory2.OpenFromString(connString, 0);
    com.ManageLifetime(workspace);

    openWatch.Stop();
    Debug.Print("OpenFromString:{0}", spWatch.ElapsedMilliseconds);
    openWatch.Restart();


    ISqlWorkspace sqlWorkspace = (ISqlWorkspace)workspace;

    IQueryDescription queryDescription = sqlWorkspace.GetQueryDescription(
        "SELECT * FROM RND");
    com.ManageLifetime(queryDescription);
    

    //queryDescription.OIDFields = "OID";
    queryDescription.GeometryType = esriGeometryType.esriGeometryPolygon;
    queryDescription.Srid = srid.ToString();
    queryDescription.SpatialReference = spref;


    openWatch.Stop();
    Debug.Print("GetQueryDescription:{0}", spWatch.ElapsedMilliseconds);
    openWatch.Restart();


    IFeatureClass queryClass = (IFeatureClass)sqlWorkspace.OpenQueryClass("%RND", queryDescription);
    com.ManageLifetime(queryClass);

    openWatch.Stop();
    Debug.Print("OpenQueryClass:{0}", openWatch.ElapsedMilliseconds);

    //IGeoDataset geodataset = (IGeoDataset)queryClass;
    //Debug.Print("{0}", geodataset.Extent.XMax);
}
spWatch.Stop();
Debug.Print("QUERY:{0}", spWatch.ElapsedMilliseconds);
spWatch.Restart();

using (var com = new ComReleaser())
{
    Type t = Type.GetTypeFromProgID("esriDataSourcesGDB.SdeWorkspaceFactory");
    IWorkspaceFactory2 workspaceFactory = (IWorkspaceFactory2)Activator.CreateInstance(t);
    var fw = (IFeatureWorkspace)workspaceFactory.OpenFromString(sde_connString, 0);

    var openWatch = new Stopwatch();
    openWatch.Start();

    var featureClass = fw.OpenFeatureClass("RND");

    openWatch.Stop();
    Debug.Print("OpenFeatureClass:{0}", openWatch.ElapsedMilliseconds);


}
spWatch.Stop();
Debug.Print("SDE:{0}", spWatch.ElapsedMilliseconds);
カテゴリー: 開発 | タグ: | QueryLayer初期化 はコメントを受け付けていません

IWkbとIGeometryFactoryの速度差

IWkb使う方が優位かも。

レイヤ:World Cities -esriGeometryPoint- 2539
IGeometryFactory:69
IWkb:48
レイヤ:Continents -esriGeometryPolygon- 8
IGeometryFactory:341
IWkb:337
レイヤ:World -esriGeometryPolygon- 72
IGeometryFactory:10
IWkb:9
var mxd = @"C:\Program Files (x86)\ArcGIS\DeveloperKit10.3\Samples\data\World\World.mxd";
using (ComReleaser com = new ComReleaser())
{
  var mapDoc = new MapDocumentClass();
  com.ManageLifetime(mapDoc);

  mapDoc.Open(mxd);
  var map = mapDoc.get_Map(0);
  com.ManageLifetime(map);


  UID uid = new UIDClass();
  com.ManageLifetime(uid);

  uid.Value = "{" + typeof(IFeatureLayer).GUID.ToString() + "}";

  IEnumLayer enumLayer = map.get_Layers(uid, true);
  com.ManageLifetime(enumLayer);

  IFeatureLayer layer = null;
  while ((layer = (IFeatureLayer)enumLayer.Next()) != null)
  {
    //var layer = map.get_Layer(0) as IFeatureLayer;
    com.ManageLifetime(layer);

    var fc = layer.FeatureClass;
    com.ManageLifetime(fc);

    Console.WriteLine("レイヤ:{0} -{1}- {2}", layer.Name, fc.ShapeType.ToString("G"), fc.FeatureCount(null));


    var spWatch = new System.Diagnostics.Stopwatch();
    spWatch.Start();

    var cursor = fc.Search(null, true);
    com.ManageLifetime(cursor);


    var geomFactory = (IGeometryFactory3)new GeometryEnvironmentClass();
    com.ManageLifetime(geomFactory);


    IFeature f = null;
    while ((f = cursor.NextFeature()) != null)
    {
      var data = (byte[])geomFactory.CreateWkbVariantFromGeometry(f.Shape);

      var sqlBytes = new System.Data.SqlTypes.SqlBytes(data);
      var sqlGeometry = Microsoft.SqlServer.Types.SqlGeometry.STGeomFromWKB(sqlBytes, 0);
    }//end feature loop

    var msg = string.Format("IGeometryFactory:{0}", spWatch.ElapsedMilliseconds);
    Console.WriteLine(msg);


    spWatch.Restart();
    cursor = fc.Search(null, true);
    com.ManageLifetime(cursor);
    f = null;

    while ((f = cursor.NextFeature()) != null)
    {
      IWkb wkb = (IWkb)f.Shape;
      int wkbSize = wkb.WkbSize;
      byte[] data = new byte[wkbSize];
      int byte_count = wkbSize;
      wkb.ExportToWkb(ref byte_count, out data[0]);


      if (byte_count != wkbSize)
        data = data.Take(byte_count).ToArray();

      var sqlBytes = new System.Data.SqlTypes.SqlBytes(data);
      var sqlGeometry = Microsoft.SqlServer.Types.SqlGeometry.STGeomFromWKB(sqlBytes, 0);
    }//end feature loop

    msg = string.Format("IWkb:{0}", spWatch.ElapsedMilliseconds);
    Console.WriteLine(msg);

  }//end layer loop
}//end com
カテゴリー: 開発 | タグ: | IWkbとIGeometryFactoryの速度差 はコメントを受け付けていません