ArcObjectsを使用してGeoTransformationを選択しますか?


8

現在、ArcObjectsを使用してデスクトップアドインツールを構築しています。

  1. フィーチャクラスを選択するようユーザーに要求します
  2. フィーチャクラスをWebメルカトルに再投影します
  3. いくつかのジオプロセシングを実行します

フィーチャクラスの初期座標系は、多くの異なる地理的システムまたは投影システムの1つである可能性があります。その結果、必要に応じてユーザーにGeoTransformationも選択させる必要があります。明らかに、esriSRGeoTransformationType、esriSRGeoTransformation2Type、esriSRGeoTransformation3Typeの列挙で提供される変換の膨大なリストをユーザーに提示できます。しかし、それは膨大なリストになるでしょう。入力座標系と出力座標系に基づいてリストを絞り込みたいのですが、その絞り込み方法を理解できませんでした。

誰でもこれを行った経験がありますか?プロジェクトツールのUIがまさにこの絞り込み操作を行うので、何らかの方法が必要であることはわかっています。しかし、徹底的なインターネット検索にもかかわらず、私は方法を見つけることができません。

回答:


12

以下のc#コードを参照してください。(更新:リファクタリング)

using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using ESRI.ArcGIS.Geometry;
using System.Windows.Forms;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.Framework;

namespace HansenAddin
{
    public class PickGeoTransButton : ESRI.ArcGIS.Desktop.AddIns.Button
    {
        public PickGeoTransButton()
        {
        }

        protected override void OnClick()
        {
            try
            {
                // let user choose a transformation for projecting from featureclass's spatial ref
                // into the dataframe's spatial ref.
                var featClass = ((IFeatureLayer)ArcMap.Document.FocusMap.get_Layer(0)).FeatureClass;

                var fromSR = ((IGeoDataset)featClass).SpatialReference;
                var toSR = ArcMap.Document.FocusMap.SpatialReference;

                IGeoTransformation geoTrans;
                esriTransformDirection direction;
                ChooseGeotrans(fromSR, toSR, ArcMap.Application.hWnd, out geoTrans, out direction);
                if (geoTrans != null)
                {
                    MessageBox.Show(String.Format("{0} \n{1} \n{2} \n{3}", geoTrans.Name, fromSR.Name, toSR.Name, direction));
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        public static void ChooseGeotrans(ISpatialReference fromSR, ISpatialReference toSR, int hWnd,
            out IGeoTransformation geoTrans, out esriTransformDirection direction)
        {
            geoTrans = null;
            direction = esriTransformDirection.esriTransformForward;

            var list = GetTransformations(fromSR, toSR);
            if (list.Count == 0)
            {
                MessageBox.Show(String.Format("No geotransforms to go from {0} to {1}", fromSR.Name, toSR.Name));
                return;
            }
            IListDialog dlg = new ListDialogClass();
            foreach (IGeoTransformation gt in list)
                dlg.AddString(gt.Name);
            if (dlg.DoModal("Choose a Geotransformation", 0, hWnd))
            {
                geoTrans = list[dlg.Choice];
                direction = GetDir(geoTrans, fromSR, toSR);
            }
        }

        public static List<IGeoTransformation> GetTransformations(ISpatialReference fromSR, ISpatialReference toSR)
        {
            int fromFactcode = GetGCSFactoryCode(fromSR);
            int toFactcode = GetGCSFactoryCode(toSR);

            var outList = new List<IGeoTransformation>();
            // Use activator to instantiate arcobjects singletons ...
            var type = Type.GetTypeFromProgID("esriGeometry.SpatialReferenceEnvironment");
            var srf = Activator.CreateInstance(type) as ISpatialReferenceFactory2;

            var gtSet = srf.CreatePredefinedGeographicTransformations();
            gtSet.Reset();
            for (int i = 0; i < gtSet.Count; i++)
            {
                ISpatialReference fromGcsSR;
                ISpatialReference toGcsSR;
                var geoTrans = (IGeoTransformation)gtSet.Next();
                geoTrans.GetSpatialReferences(out fromGcsSR, out toGcsSR);
                if ((fromGcsSR.FactoryCode == fromFactcode && toGcsSR.FactoryCode == toFactcode) ||
                    (fromGcsSR.FactoryCode == toFactcode && toGcsSR.FactoryCode == fromFactcode))
                {
                    outList.Add(geoTrans);
                }
            }
            return outList;
        }
        private static esriTransformDirection GetDir(IGeoTransformation geoTrans, ISpatialReference sr1, ISpatialReference sr2)
        {
            int code1 = GetGCSFactoryCode(sr1);
            int code2 = GetGCSFactoryCode(sr2);
            ISpatialReference fromSR;
            ISpatialReference toSR;
            geoTrans.GetSpatialReferences(out fromSR, out toSR);
            if (fromSR.FactoryCode == code1 && toSR.FactoryCode == code2)
                return esriTransformDirection.esriTransformForward;
            else if (fromSR.FactoryCode == code2 && toSR.FactoryCode == code1)
                return esriTransformDirection.esriTransformReverse;
            else
                throw new Exception(String.Format("{0} does not support going between {1} and {2}",
                    geoTrans.Name, sr1.Name, sr2.Name));
        }

        private static int GetGCSFactoryCode(ISpatialReference sr)
        {
            if (sr is IProjectedCoordinateSystem)
                return ((IProjectedCoordinateSystem)sr).GeographicCoordinateSystem.FactoryCode;
            else if (sr is IGeographicCoordinateSystem)
                return ((IGeographicCoordinateSystem)sr).FactoryCode;
            else
                throw new Exception("unsupported spatialref type");
        }
        protected override void OnUpdate()
        {

        }

    }
}

どうもありがとう...かなり完璧に働いた。私はこの部分について疑問に思います:if ((fromGcsSR.FactoryCode == fromFactcode && toGcsSR.FactoryCode == toFactcode) || (fromGcsSR.FactoryCode == fromFactcode && toGcsSR.FactoryCode == toFactcode)) OR演算子の両側は同一です。
rgwozdz 2011

@rgwozdzうーん、そのコード行を修正しました。その行がエラーであることを考えると、それが完全に機能する理由に困惑しています。
カークカイケンダル、2011

2

GetDirメソッドの場合、2番目と3番目のパラメーターは、ソース座標系とターゲット座標系の基本地理座標系のファクトリーコードでなければなりません。投影座標系の場合、ISpatialReferenceインターフェイスは座標系のファクトリコードを提供しますが、基本的な地理座標系は提供しません。たとえば、NAD27ゾーン12は工場コード26712に相当し、基本地理座標系は4267(NAD27地理)です。geoTrans.GetSpatialReferences(out fromSR、out toSR)の「out」パラメーター。地理座標系の工場コードのみになります。

投影座標系オブジェクトを作成してから、そのベースgeogrを取得することにより、投影座標系のベース地理座標系を取得できます。coord sysファクトリコード。

以下のコードが役立つはずです。オブジェクトを正しく作成するには、元の座標系とターゲット座標系の整数を指定する必要があります。また、コードは、ソース/ターゲット座標系のタイプ(投影vs地理)が提供されていることを期待しています。

//Create Spatial Reference Factory

ISpatialReferenceFactory3 srFactory = new SpatialReferenceEnvironmentClass();
IProjectedCoordinateSystem3 pcsSource; 
IGeographicCoordinateSystem2 gcsSource; 
IProjectedCoordinateSystem3 pcsTarget; 
IGeographicCoordinateSystem2 gcsTarget;
ISpatialReference3 srSourceCoordSys;
ISpatialReference3 srTargetCoordSys;
int OriginalCoordSys;
int TargetCoordSys;

        int SourceGeographicBaseID = 0;
        int TargetGeographicBaseID = 0;

        //Define the source coordinate system
        if (OrigCoordSysType.ToUpper() == "PROJECTED")
        {
            pcsSource = (IProjectedCoordinateSystem3)srFactory.CreateProjectedCoordinateSystem(OriginalCoordSys);
            SourceGeographicBaseID = pcsSource.GeographicCoordinateSystem.FactoryCode;
            srSourceCoordSys = (ISpatialReference3)pcsSource;
        }
        else
        {
            gcsSource = (IGeographicCoordinateSystem2)srFactory.CreateGeographicCoordinateSystem(OriginalCoordSys);
            SourceGeographicBaseID = gcsSource.FactoryCode;
            srSourceCoordSys = (ISpatialReference3)gcsSource;
        }

        //Define the target coordinate system
        if (TargetCoordSysType.ToUpper() == "PROJECTED")
        {
            pcsTarget = (IProjectedCoordinateSystem3)srFactory.CreateProjectedCoordinateSystem(TargetCoordSys);
            TargetGeographicBaseID = pcsTarget.GeographicCoordinateSystem.FactoryCode;
            srTargetCoordSys = (ISpatialReference3)pcsTarget;

        }
        else
        {
            gcsTarget = (IGeographicCoordinateSystem2)srFactory.CreateGeographicCoordinateSystem(TargetCoordSys);
            TargetGeographicBaseID = gcsTarget.FactoryCode;
            srTargetCoordSys = (ISpatialReference3)gcsTarget;
        }

2

最も簡単な方法は、Pythonスクリプト(arcpy)を記述して、それをarcobjectsのツールボックスに公開する方法です。次に、arcobjectsを使用してこのツールを呼び出します。

arcpyにはListTransformations(http://resources.arcgis.com/en/help/main/10.1/index.html#/ListTransformations/018v0000001p000000/)があります。

ツールボックスで公開されるツールボックスツール:

 import arcpy
 try:

     layer = arcpy.GetParameter(0)
     layerDescribe = arcpy.Describe(layer)

     from_sr = layerDescribe.featureClass.spatialReference
     to_sr = arcpy.GetParameter(1)
     extent = layerDescribe.extent

     transformations = arcpy.ListTransformations(from_sr, to_sr, extent)
     arcpy.SetParameter(2, transformations)

 except StandardError, ErrDesc:
     arcpy.AddMessage("Error: " + str(ErrDesc))
 except:
     arcpy.AddMessage("Error: get list transformations")

アークオブジェクト:

            IVariantArray parameters = new VarArrayClass();

            parameters.Add(this.pathLayer); //path and file lyr example c:\temp\test.lyr
            parameters.Add(this.spatialReferenceOut);

            IGPValue output = null;
            Geoprocessor geoprocessor = new Geoprocessor();
            geoprocessor.AddToolbox(@"c:\Temp\myToolbox.tbx");
            ExecuteTask(this.geoprocessor, parameters, "ListTransformations", 0 ,out output);   //ListTransformations is the name of your toolbox tool

            IGPMultiValue GPMultiValue = output as IGPMultiValue;

            for (int i = 0; i < GPMultiValue.Count;i++ )
            {
                cboDatumTransformation.Items.Add((GPMultiValue.get_Value(i) as IGPString).Value);
            }

したがって、入力の範囲に使用できるデータム変換のみがあります

ニュース:現在、ArcGIS Server 10.3 API Restでは、GeometryService-> Project FindTransformationsで使用できます。これは、入力空間参照から出力空間参照にジオメトリを投影するときに使用する必要のある、適用可能な地理変換のリストを返します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.