【问题标题】:How to get Geographic Coordinates of a Mouse Click using C# ArcObjects如何使用 C# ArcObjects 获取鼠标单击的地理坐标
【发布时间】:2015-05-12 07:37:43
【问题描述】:

我在 ArcGIS 中有一个 ArcObjects C# 工具(大部分代码可在 Stack Exchange 上找到),当用户单击地图中的某个位置时,它可以识别地图坐标。这是我使用的代码:

    public override void OnMouseDown(int Button, int Shift, int X, int Y)
    {
        if (Button == 1)
        {
            ESRI.ArcGIS.Display.IScreenDisplay screenDisplay = (m_application.Document as IMxDocument).ActiveView.ScreenDisplay;
            ESRI.ArcGIS.Geometry.IPoint point = screenDisplay.DisplayTransformation.ToMapPoint(X, Y);

            MessageBox.Show("X position is " + point.X.ToString() + " Y position is " + point.Y.ToString());
        }
    }

我们的地图使用英尺单位,因此该工具会显示英尺坐标。我怎样才能让这个工具返回度-分-秒? ESRI 的标准识别工具可以做到这一点,这也是我希望获得类似结果的工具。

【问题讨论】:

    标签: c# coordinates arcgis arcobjects


    【解决方案1】:

    您必须首先将屏幕点转换为地图当前坐标系,然后您需要将该点投影到 WGS84 中,然后转换为度分秒。我在下面创建了一个类。不客气,伙计。

    实施

    Public Overrides Sub OnMouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Integer, ByVal Y As Integer)
        Dim getMethod As New DecimalDegreesToDegreesMinutesSeconds
        getMethod.PointFromScreenPoint(X, Y)
    End Sub
    
        Public Class DecimalDegreesToDegreesMinutesSeconds
    ' Used by both
    Private pSpRFc As ESRI.ArcGIS.Geometry.SpatialReferenceEnvironment
    
    ' WGS1984
    Private pSpRef1 As ESRI.ArcGIS.Geometry.ISpatialReference
    Private pGCS As ESRI.ArcGIS.Geometry.IGeographicCoordinateSystem
    
    '' NAD83 FEET STATEPLANES NC 
    'Private pSpRef2 As ESRI.ArcGIS.Geometry.ISpatialReference
    'Private pPCS As ESRI.ArcGIS.Geometry.IProjectedCoordinateSystem
    
    Private ReadOnly Property WGS84() As ESRI.ArcGIS.Geometry.ISpatialReference
        Get
            ' WGS1984
            pSpRFc = New ESRI.ArcGIS.Geometry.SpatialReferenceEnvironment
            pGCS = pSpRFc.CreateGeographicCoordinateSystem(4326)
            pSpRef1 = pGCS
            pSpRef1.SetFalseOriginAndUnits(-180, -90, 1000000)
            Return pSpRef1
        End Get
    End Property
    
    ' pass the original screen point into this function
    Public Sub PointFromScreenPoint(pX As Double, pY As Double)
        Dim scrDisp As ESRI.ArcGIS.Display.IScreenDisplay = Nothing
        Dim pnt As ESRI.ArcGIS.Geometry.IPoint = Nothing
        Dim pGeoSpRef As ESRI.ArcGIS.Geometry.IGeometry = Nothing
    
        Try
            '
            scrDisp = New ESRI.ArcGIS.Display.ScreenDisplay
            scrDisp = SGProperties.pActiveView.ScreenDisplay ' the activeview
            scrDisp.StartDrawing(scrDisp.hDC, CShort(ESRI.ArcGIS.Display.esriScreenCache.esriNoScreenCache))
            '
            pnt = scrDisp.DisplayTransformation.ToMapPoint(pX, pY)
            '
            pGeoSpRef = pnt
            pGeoSpRef.SpatialReference = SGProperties.pMap.SpatialReference ' the current maps
            pGeoSpRef.Project(WGS84())
    
            Windows.Forms.MessageBox.Show("X position is " + ConvertDegrees(pnt.X, DegreesType.Longitude).ToString() + " Y position is " + ConvertDegrees(pnt.Y, DegreesType.Latitude).ToString())
        Catch ex As Exception
    
        Finally
            If scrDisp IsNot Nothing Then System.Runtime.InteropServices.Marshal.ReleaseComObject(scrDisp)
            scrDisp = Nothing
            If pnt IsNot Nothing Then System.Runtime.InteropServices.Marshal.ReleaseComObject(pnt)
            pnt = Nothing
            If pGeoSpRef IsNot Nothing Then System.Runtime.InteropServices.Marshal.ReleaseComObject(pGeoSpRef)
            pGeoSpRef = Nothing
        End Try
    End Sub
    
    Enum DegreesType
        Latitude
        Longitude
    End Enum
    
    Private Function ConvertDegrees(pInDegrees As Double, pInType As DegreesType)
        Dim degrees As Integer
        Dim submin As Double
        Dim minutes As Double
        Dim subsecsonds As Double
        Dim direction As String
        Dim output As String
    
        Try
    
            degrees = Math.Truncate(pInDegrees)
            submin = Math.Abs((pInDegrees - Math.Truncate(pInDegrees)) * 60)
            minutes = Math.Truncate(submin)
            subsecsonds = Math.Abs((submin - Math.Truncate(submin)) * 60)
            direction = ""
    
            If pInType.ToString().Trim().ToUpper() = "Latitude".ToUpper() Then
                If degrees < 0 Then
                    direction = "S"
                ElseIf (degrees > 0) Then
                    direction = "N"
                Else
                    direction = ""
                End If
            ElseIf pInType.ToString().Trim().ToUpper() = "Longitude".ToUpper() Then
                If degrees < 0 Then
                    direction = "W"
                ElseIf (degrees > 0) Then
                    direction = "E"
                Else
                    direction = ""
                End If
            End If
    
            output = degrees.ToString() + ":" + minutes.ToString() + ":" + subsecsonds.ToString().Substring(0, 5) + direction
    
            Return output
        Catch ex As Exception
            Return Nothing
        End Try
    End Function
    

    结束类

    【讨论】:

      【解决方案2】:

      在获取坐标之前,您可以轻松更改 IDisplayTransformation 对象的地图单位:

              ESRI.ArcGIS.Display.IDisplayTransformation displayTransformation = screenDisplay.DisplayTransformation;
              displayTransformation.Units = ESRI.ArcGIS.esriSystem.esriUnits.esriMeters; // or another unit
              ESRI.ArcGIS.Geometry.IPoint point = displayTransformation.ToMapPoint(X, Y);
      

      您可以获取有关不同 ESRI 单位的信息here

      【讨论】:

      • 感谢您的回复。我在声明 screenDisplay 之后添加了这段代码,并注释掉了我的初始点声明。点击地图后,实际的地图单位发生了变化,但消息框仍然显示英尺坐标。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-06-08
      • 2010-10-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-02
      相关资源
      最近更新 更多