Sử dụng ArcObjects để chọn GeoTransatures?


8

Tôi hiện đang xây dựng một công cụ bổ trợ cho Máy tính để bàn với ArcObjects:

  1. Yêu cầu người dùng chọn một lớp đối tượng
  2. Tái định nghĩa lớp tính năng cho Web Mercator
  3. Thực hiện một số địa lý

Hệ tọa độ ban đầu của lớp đối tượng có thể là một trong nhiều hệ thống địa lý hoặc dự kiến ​​khác nhau. Do đó, tôi cũng cần người dùng chọn GeoTransatures nếu cần. Rõ ràng, tôi có thể trình bày cho người dùng danh sách chuyển đổi khổng lồ được cung cấp trong bảng liệt kê của esriSRGeoTransaturesType, esriSRGeoTransifying2Type, esriSRGeoTransifying3Type. Nhưng đó sẽ là một danh sách lớn. Những gì tôi muốn làm là thu hẹp danh sách đó dựa trên Hệ thống tọa độ đầu vào và đầu ra - nhưng tôi chưa thể tìm ra cách thực hiện thu hẹp đó.

Bất cứ ai cũng có kinh nghiệm làm điều này? Tôi biết phải có một số cách để làm, bởi vì UI Tool Project thực hiện chính xác thao tác thu hẹp này. Nhưng tôi không thể tìm ra phương pháp, mặc dù tìm kiếm trên internet đầy đủ.

Câu trả lời:


12

Xem mã c # bên dưới. (Cập nhật: tái cấu trú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()
        {

        }

    }
}

Cảm ơn rất nhiều ... khá nhiều làm việc hoàn hảo. Tôi tự hỏi về phần này mặc dù: if ((fromGcsSR.FactoryCode == fromFactcode && toGcsSR.FactoryCode == toFactcode) || (fromGcsSR.FactoryCode == fromFactcode && toGcsSR.FactoryCode == toFactcode)) Cả hai mặt của toán tử OR giống hệt nhau.
rgwozdz

@rgwozdz Hmm, tôi đã sửa dòng mã đó. Tôi bối rối tại sao nó hoạt động hoàn hảo khi cho rằng dòng đó là một lỗi.
Kirk Kuykendall

2

Đối với phương thức GetDir, tham số thứ hai và thứ ba phải là mã nhà máy của hệ thống tọa độ địa lý cơ sở của hệ thống tọa độ nguồn và đích. Đối với các hệ tọa độ dự kiến, giao diện ISpatialReference sẽ cung cấp mã nhà máy của hệ tọa độ chứ không phải hệ tọa độ địa lý cơ sở. Ví dụ: NAD27 Vùng 12 tương đương với mã nhà máy 26712 và hệ tọa độ địa lý cơ sở là 4267 (NAD27 địa lý). Các tham số 'out' của GeoTrans.GetSpatialReferences (outSR, outSR); sẽ chỉ là mã nhà máy cho các hệ tọa độ địa lý.

Bạn có thể có được hệ tọa độ địa lý cơ sở của một hệ tọa độ được chiếu bằng cách tạo một đối tượng hệ tọa độ được chiếu và sau đó lấy geogr cơ sở của nó. tọa độ sys mã nhà máy.

Mã dưới đây sẽ giúp. Các số nguyên cho các hệ tọa độ gốc và đích sẽ phải được cung cấp để tạo đúng đối tượng. Và mã đang mong đợi loại (dự kiến ​​so với địa lý) của các hệ tọa độ nguồn / đích đã được cung cấp.

//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

Phương pháp đơn giản nhất là viết một kịch bản python (arcpy) và hiển thị nó như thế nào hộp công cụ trong arcobjects. Sau đó, bạn sử dụng arcobjects và gọi công cụ này.

Trong arcpy, bạn có ListTransformations ( http://resource.arcgis.com/en/help/main/10.1/index.html#/ListTransformations/018v0000001p000000/ )

công cụ hộp công cụ tiếp xúc với một hộp công cụ:

 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")

Trong arcobjects:

            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);
            }

Vì vậy, bạn chỉ có các phép biến đổi chuẩn cho phạm vi đầu vào

Tin tức: hiện có trong ArcGIS Server 10.3 API Phần còn lại bạn có sẵn trong GeometryService -> Project FindTransformations trả về danh sách các phép biến đổi địa lý có thể sử dụng khi chiếu hình học từ tham chiếu không gian đầu vào vào tham chiếu không gian đầu ra

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.