gis
gis
管理员
管理员
  • 注册日期2003-07-16
  • 发帖数15951
  • QQ
  • 铜币25345枚
  • 威望15368点
  • 贡献值0点
  • 银元0个
  • GIS帝国居民
  • 帝国沙发管家
  • GIS帝国明星
  • GIS帝国铁杆
阅读:1275回复:2

如何实现在ArcMap上进行测量[代码+说明]

楼主#
更多 发布于:2005-08-30 15:05
  距离的测量:要实现的是测量两个点之间的距离。用ToolControl实现,选中工具后,在测量的开始点按鼠标左键,鼠标拖动过程中实时画一条从开始点到鼠标当前位置的橡皮线,计算并显示开始点到目标点的距离,释放左键后擦除所画的线和文本。 <br>
<P>l   要点</P>
<P>要实时显示结果,计算过程应该在MouseMove事件中处理。</P>
<P>要绘制橡皮线,必须设置当前绘图模式为esriROPXOrPen。即混合后的颜色取为当前背景色和画笔颜色的“异或”结果。这样在设定了画笔颜色后,在同一位置第二次画同一图形,就会将图形“擦除”,并恢复原来的背景色。</P>
<P>所有的对设备(包括显示器、打印机、内存位图)的绘图操的前后都应分别调用IDisplay的两个方法StartDrawing和EndDrawing。StartDrawing可以准备特定的设备环境,管理本例中要用到的各种Symbols,FinishDrawing完成收尾工作,以保证下一次对StartDrawing的调用不会出错。</P>
<P>l   程序说明</P>
<P>函数UITMeasureDistance_Deactivate是Deactivate属性的处理代码,当工具失去焦点时,清除已创建的对象。过程UITMeasureDistance_MouseDown是MouseDown事件的处理代码,当鼠标键按下时,记录起始点。过程UITMeasureDistance_MouseMove是MouseMove事件的处理代码,鼠标移动过程中测量距离,计算文本显示的角度,以及完成屏幕上橡皮线的绘制。过程UITMeasureDistance_MouseUp是MouseUp事件的处理代码,当释放鼠标键时,擦除刚绘制的图形。函数GetSmashedLine将获得一条IPolyline对象,这条Polyline在要显示文本的地方留下了空白,以防止出现所画线穿过文字的现象。</P>
<P>另外,本例未考虑坐标系的转换,在球面地理坐标系是测量结果为经度差或纬度差。</P>
<P>l   代码</P>
<P>Option Explicit<br>Private m_bInUse        As Boolean<br>Private m_pLineSymbol   As ILineSymbol<br>Private m_pLinePolyline As IPolyline<br>Private m_pTextSymbol   As ITextSymbol<br>Private m_pStartPoint   As IPoint<br>Private m_pTextPoint    As IPoint </P>
<P>Private Function UITMeasureDistance_Deactivate() As Boolean<br>    ' Stop doing operation<br>    Set m_pTextSymbol = Nothing<br>    Set m_pTextPoint = Nothing<br>    Set m_pLinePolyline = Nothing<br>    Set m_pLineSymbol = Nothing<br>    m_bInUse = False<br>    UITMeasureDistance_Deactivate = True<br>End Function </P>
<P>Private Sub UITMeasureDistance_MouseDown(ByVal Button As Long, ByVal Shift As Long, _ByVal X As Long, ByVal Y As Long)   <br>    Dim pMxDocument     As IMxDocument<br>    Dim pActiveView     As IActiveView<br>    m_bInUse = True<br>    Set pMxDocument = ThisDocument<br>    Set pActiveView = pMxDocument.FocusMap<br>    ' Get point to measure distance from<br>    Set m_pStartPoint = pActiveView.ScreenDisplay.DisplayTransformation.ToMapPoint(X, Y)<br>End Sub </P>
<P>Private Sub UITMeasureDistance_MouseMove(ByVal Button As Long, ByVal Shift As Long, _ByVal X As Long, ByVal Y As Long)<br>    Dim pMxDocument         As IMxDocument<br>    Dim pActiveView         As IActiveView<br>    Dim bFirstTime          As Boolean<br>    Dim pPoint              As IPoint<br>    Dim pRGBColor           As IRgbColor<br>    Dim pSymbol             As ISymbol<br>    Dim pFont               As IFontDisp<br>    Dim pLine               As ILine<br>    Dim dAngle              As Double<br>    Dim dDeltaX             As Double<br>    Dim dDeltaY             As Double<br>    Dim dDistance           As Double<br>    Dim pPolyLine           As IPolyline<br>    Dim pSegmentCollection  As ISegmentCollection<br>    On Error GoTo ErrorHandler<br>    If (Not m_bInUse) Then<br>        Exit Sub<br>    End If<br>    Set pMxDocument = ThisDocument<br>    Set pActiveView = pMxDocument.FocusMap           </P>
<P>    If (m_pLineSymbol Is Nothing) Then<br>        bFirstTime = True<br>    End If<br>    ' Get current point<br>    Set pPoint = pActiveView.ScreenDisplay.DisplayTransformation.ToMapPoint(X, Y)<br>    pActiveView.ScreenDisplay.StartDrawing pActiveView.ScreenDisplay.hDC, -1</P>
<P>    If bFirstTime Then<br>        ' Set Line Symbol<br>        Set m_pLineSymbol = New SimpleLineSymbol<br>        m_pLineSymbol.Width = 2<br>        Set pRGBColor = New RgbColor<br>        With pRGBColor<br>            .Red = 222<br>            .Green = 222<br>            .Blue = 222<br>        End With<br>        m_pLineSymbol.Color = pRGBColor<br>        Set pSymbol = m_pLineSymbol<br>        pSymbol.ROP2 = esriROPXOrPen<br>        ' Set Text Symbol<br>        Set m_pTextSymbol = New TextSymbol<br>        m_pTextSymbol.HorizontalAlignment = esriTHACenter<br>        m_pTextSymbol.VerticalAlignment = esriTVACenter<br>        m_pTextSymbol.Size = 16<br>        Set pSymbol = m_pTextSymbol<br>        Set pFont = m_pTextSymbol.Font<br>        pFont.Name = "Arial"<br>        pSymbol.ROP2 = esriROPXOrPen<br>        ' Create point to draw text in<br>        Set m_pTextPoint = New Point<br>    Else<br>        ' Use existing symbols and draw existing text and polyline<br>        pActiveView.ScreenDisplay.SetSymbol m_pTextSymbol<br>        pActiveView.ScreenDisplay.DrawText m_pTextPoint, m_pTextSymbol.Text<br>        pActiveView.ScreenDisplay.SetSymbol m_pLineSymbol<br>        If (m_pLinePolyline.Length > 0) Then<br>            pActiveView.ScreenDisplay.DrawPolyline m_pLinePolyline<br>        End If<br>    End If<br>    ' Get line between from and to points, and dAngle for text<br>    Set pLine = New esriCore.Line<br>    pLine.PutCoords m_pStartPoint, pPoint<br>    dAngle = pLine.angle<br>    dAngle = dAngle * (180# / 3.14159)<br>    If ((dAngle > 90#) And (dAngle < 180#)) Then<br>        dAngle = dAngle + 180#<br>    ElseIf ((dAngle < 0#) And (dAngle < -90#)) Then<br>        dAngle = dAngle - 180#<br>    ElseIf ((dAngle < -90#) And (dAngle > -180)) Then<br>        dAngle = dAngle - 180#<br>    ElseIf (dAngle > 180) Then<br>        dAngle = dAngle - 180#<br>    End If<br>    ' For drawing text, get text(dDistance), dAngle, and point<br>    dDeltaX = pPoint.X - m_pStartPoint.X<br>    dDeltaY = pPoint.Y - m_pStartPoint.Y<br>    m_pTextPoint.X = m_pStartPoint.X + dDeltaX / 2#<br>    m_pTextPoint.Y = m_pStartPoint.Y + dDeltaY / 2#<br>    m_pTextSymbol.angle = dAngle<br>    dDistance = Round(pLine.Length, 3)<br>    m_pTextSymbol.Text = "[" ; dDistance ; "]"<br>    ' Draw text<br>    pActiveView.ScreenDisplay.SetSymbol m_pTextSymbol<br>    pActiveView.ScreenDisplay.DrawText m_pTextPoint, m_pTextSymbol.Text<br>    ' Get polyline with blank space for text<br>    Set pPolyLine = New Polyline<br>    Set pSegmentCollection = pPolyLine<br>    pSegmentCollection.AddSegment pLine<br>    Set m_pLinePolyline = GetSmashedLine(pActiveView.ScreenDisplay, m_pTextSymbol, _m_pTextPoint, pPolyLine)<br>    ' Draw polyline<br>    pActiveView.ScreenDisplay.SetSymbol m_pLineSymbol<br>    If (m_pLinePolyline.Length > 0) Then<br>        pActiveView.ScreenDisplay.DrawPolyline m_pLinePolyline<br>    End If<br>    pActiveView.ScreenDisplay.FinishDrawing<br>    Exit Sub<br>ErrorHandler:<br>    MsgBox Err.Description<br>End Sub</P>
<P>Private Sub UITMeasureDistance_MouseUp(ByVal Button As Long, ByVal Shift As Long, _ByVal X As Long, ByVal Y As Long)<br>    Dim pMxDocument     As IMxDocument<br>    Dim pActiveView     As IActiveView<br>    On Error GoTo ErrorHandler<br>    If (Not m_bInUse) Then<br>        Exit Sub<br>    End If<br>    m_bInUse = False<br>    If (m_pLineSymbol Is Nothing) Then<br>        Exit Sub<br>    End If<br>    Set pMxDocument = ThisDocument<br>    Set pActiveView = pMxDocument.FocusMap<br>    'Draw measure line and text<br>    pActiveView.ScreenDisplay.StartDrawing pActiveView.ScreenDisplay.hDC, -1<br>    pActiveView.ScreenDisplay.SetSymbol m_pTextSymbol<br>    pActiveView.ScreenDisplay.DrawText m_pTextPoint, m_pTextSymbol.Text<br>    pActiveView.ScreenDisplay.SetSymbol m_pLineSymbol<br>     If (m_pLinePolyline.Length > 0) Then<br>        pActiveView.ScreenDisplay.DrawPolyline m_pLinePolyline<br>    End If<br>    pActiveView.ScreenDisplay.FinishDrawing<br>    Set m_pTextSymbol = Nothing<br>    Set m_pTextPoint = Nothing<br>    Set m_pLinePolyline = Nothing<br>    Set m_pLineSymbol = Nothing<br>    Exit Sub<br>ErrorHandler:<br>    MsgBox Err.Description<br>End Sub </P>
<P>Private Function GetSmashedLine(pDisplay As IScreenDisplay, pTextSymbol As ISymbol, _pPoint As IPoint, pPolyLine As IPolyline) As IPolyline<br>    ' Returns a Polyline with a blank space for the text to go in<br>    Dim pSmashed                As IPolyline<br>    Dim pBoundary               As IPolygon<br>    Dim pTopologicalOperator    As ITopologicalOperator<br>    Dim pIntersect              As IPolyline<br>    On Error GoTo ErrorHandler<br>    Set pBoundary = New Polygon<br>    pTextSymbol.QueryBoundary pDisplay.hDC, pDisplay.DisplayTransformation, pPoint, pBoundary<br>    Set pTopologicalOperator = pBoundary<br>    Set pIntersect = pTopologicalOperator.Intersect(pPolyLine, esriGeometry1Dimension)<br>    Set pTopologicalOperator = pPolyLine<br>    Set GetSmashedLine = pTopologicalOperator.Difference(pIntersect)<br>    Exit Function<br>ErrorHandler:<br>    MsgBox Err.Description<br>End Function</P>
<P>本例要实现的是如何在ArcMap上测量一个Polygon的面积。</P>
<P>l   要点</P>
<P>首先用IRubberBand.TrackNew方法在ArcMap上画出一个Polygon,然后由这个Polygon获得一个IArea的实例,最后使用IArea.Area方法计算出这个Polygon的面积。</P>
<P>主要用到IRubberBand接口,IPolygon接口和IArea接口。</P>
<P>l   程序说明</P>
<P>函数DrawPolygon实现在ArcMap上画一个Polygon。</P>
<P>函数MeasurePolygon实现测量pPolygon的面积。</P>
<P>l   代码</P>
<P>Private Function DrawPolygon() As IPolygon<br>    Dim pMxDocument             As IMxDocument<br>    Dim pActiveView             As IActiveView<br>    Dim pSimpleFillS            As ISimpleFillSymbol<br>    Dim pRgbColor               As IRgbColor<br>    Dim pRubberBand             As IRubberBand<br>    Dim pPolygon                As IPolygon<br>    On Error GoTo ErrorHandler:<br>    Set pMxDocument = ThisDocument<br>    Set pActiveView = pMxDocument.ActiveView<br>    Set pSimpleFillS = New SimpleFillSymbol<br>    Set pRgbColor = New RgbColor<br>    pRgbColor.Red = 255<br>    pSimpleFillS.Color = pRgbColor<br>    Set pRubberBand = New esriCore.RubberPolygon<br>    Set pPolygon = pRubberBand.TrackNew(pActiveView.ScreenDisplay, pSimpleFillS)<br>    With pActiveView.ScreenDisplay<br>        .StartDrawing pActiveView.ScreenDisplay.hDC, esriNoScreenCache<br>        .SetSymbol pSimpleFillS<br>        .DrawPolygon pPolygon<br>        .FinishDrawing<br>    End With<br>    Set DrawPolygon = pPolygon<br>    Exit Function<br>ErrorHandler:<br>    MsgBox Err.Desciption<br>End Function </P>
<P>Private Function MeasurePolygon(pPolygon As IPolygon) As Double<br>    Dim pArea                   As IArea<br>On Error GoTo ErrorHandler:<br>    Set pArea = pPolygon<br>    MeasurePolygon = Abs(pArea.Area())<br>    Exit Function<br>ErrorHandler:<br>    MsgBox Err.Desciption<br>End Function </P>
<P>Private Sub UIToolControl1_MouseDown(ByVal button As Long, ByVal shift As Long, _ByVal x As Long, ByVal y As Long)   <br>    Dim pPolygon                As IPolygon<br>    Dim dArea                   As Double<br>On Error GoTo ErrorHandler:<br>    Set pPolygon = DrawPolygon()<br>    dArea = MeasurePolygon(pPolygon)<br>    MsgBox "面积为:" ; dArea<br>    Exit Sub<br>ErrorHandler:<br>    MsgBox Err.Desciption<br>End Sub</P>
[此贴子已经被作者于2005-8-30 15:13:52编辑过]
喜欢0 评分0
GIS麦田守望者,期待与您交流。
wzhipeng0117
路人甲
路人甲
  • 注册日期2005-05-05
  • 发帖数53
  • QQ
  • 铜币317枚
  • 威望0点
  • 贡献值0点
  • 银元0个
1楼#
发布于:2005-08-31 18:18
<P>有没有globe里面的量算,介绍一下方法?</P>
举报 回复(0) 喜欢(0)     评分
cftao2008
路人甲
路人甲
  • 注册日期2005-03-09
  • 发帖数141
  • QQ
  • 铜币568枚
  • 威望0点
  • 贡献值0点
  • 银元0个
2楼#
发布于:2005-08-31 13:12
多谢!整理的这么精细,有收藏价值哦!呵呵!<img src="images/post/smile/dvbbs/em08.gif" /><img src="images/post/smile/dvbbs/em08.gif" />
举报 回复(0) 喜欢(0)     评分
游客

返回顶部