FAQ
ArcObjects でスナップを有効化してポリゴンを描画する方法 (SnappingFeedback)

ナレッジ番号:2993 | 登録日:2023/05/29 | 更新日:2024/07/02

概要

簡易的にポリゴンを描画する方法として RubberPolygon クラスの TrackNew メソッドを使用する方法がありますが、スナップを有効にして図形を描画することができません。スナップを有効にしてポリゴンを作成するには下記 2 つの操作が必要になります。

このサンプルでは、スナップ機能を有効にし(※詳細については「Snapping クラスを使用したスナップ」からご参照ください。)フィードバック ポリゴンに追加する頂点に、スナップされたポイントを設定しています。

作成手順

  1. ツールのコンストラクターで、ISnappingFeedback 型で宣言したグローバル変数に SnappingFeedback オブジェクトをセットします。
  2. ISnappingFeedback::Initialize メソッドを実行してスナッピング フィードバックを初期化します。メソッドの引数に第一引数に IApplication オブジェクト、第二引数に ISnappingEnvironment オブジェクト、第三引数に True を設定して実行します。
  3. ツールのリフレッシュイベントで、ISnappingFeedback::Refresh メソッドを実行してスナップ フィードバックをリフレッシュします。
  4. INewPolygonFeedback 型の変数をグローバル変数として宣言します。
  5. ツールのマウスダウン イベントで INewPolygonFeedback オブジェクトが存在しない場合に宣言したグローバル変数に NewPolygonFeedback オブジェクトをセットします。
  6. INewPolygonFeedback::Display プロパティに ScreenDisplay オブジェクトを設定し、INewPolygonFeedback::Start メソッドを実行しポリゴンの描画を開始します。メソッドの引数には、マップのクリック地点の Point オブジェクトをセットして実行します。
  7. INewPolygonFeedback オブジェクトがすでに存在している場合は、INewPolygonFeedback::AddPoint メソッドを実行して頂点を追加します。この時スナップ地点に頂点を移動させたい場合は、スナップされた Point オブジェクトをセットします。
  8. ツールのマウスムーブ イベントで INewPolygonFeedback オブジェクトがすでに存在している場合に INewPolygonFeedback::MoveTo メソッドを実行して頂点を移動します。この時スナップ地点に頂点を移動させたい場合は、スナップされた Point オブジェクトをセットします。
  9. ツールのリフレッシュイベントで INewPolygonFeedback::Refresh メソッドを実行し、フィードバックをリフレッシュします。
  10. ダブルクリック イベントなどで、INewPolygonFeedback::Stop メソッドを実行し、フィードバックを確定しますと戻り値として Polygon オブジェクトを取得できます。

サンプル コード

using ESRI.ArcGIS.Geometry;
using ESRI.ArcGIS.Framework;
using ESRI.ArcGIS.esriSystem;
using ESRI.ArcGIS.Display;
using ESRI.ArcGIS.Controls;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.ArcMapUI;
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;

namespace SnapDrawPolygonCS
{
    public class SnapDrawPolygonCS : ESRI.ArcGIS.Desktop.AddIns.Tool
    {
        // 参考
        // Working with the ArcGIS snapping environment
        // http://resources.arcgis.com/en/help/arcobjects-net/conceptualhelp/index.html#/d/0001000001s1000000.htm
        // NewPolygonFeedback Example
        // http://resources.esri.com/help/9.3/arcgisengine/arcobjects/esriDisplay/NewPolygonFeedback_Example.htm

        // モジュールレベル変数
        private ISnappingEnvironment pSnappingEnvironment;
        private IPointSnapper pPointSnapper;
        private ISnappingFeedback pSnappingFeedback; 
        private IActiveView pActiveView;
        private INewPolygonFeedback pNewPolygonFeedback;
        private ISnappingResult pSnappingResult;
        private IPoint pSnapPoint;

        public SnapDrawPolygonCS()
        {
            // スナップ環境の初期化
            UID pUID = new UIDClass();
            pUID.Value = "{E07B4C52-C894-4558-B8D4-D4050018D1DA}";
            pSnappingEnvironment = (ISnappingEnvironment)ArcMap.Application.FindExtensionByCLSID(pUID);

            // スナップタイプの設定
            pSnappingEnvironment.SnappingType = (esriSnappingType)2 + 8;

            // スナップの許容値
            pSnappingEnvironment.Tolerance = 20;

            pSnappingEnvironment.Enabled = true;
            pPointSnapper = pSnappingEnvironment.PointSnapper;

            // スナップ フィードバックの初期化
            pSnappingFeedback = new SnappingFeedbackClass();
            pSnappingFeedback.Initialize(ArcMap.Application, pSnappingEnvironment, true);
        }

        protected override void OnMouseDown(ESRI.ArcGIS.Desktop.AddIns.Tool.MouseEventArgs arg)
        {
            base.OnMouseDown(arg);

            // クリック地点から Point オブジェクトを取得
            pActiveView = ArcMap.Document.ActiveView;
            IPoint pPoint = pActiveView.ScreenDisplay.DisplayTransformation.ToMapPoint(arg.X, arg.Y);

            // INewPolygonFeedback オブジェクトが存在していない場合
            if(pNewPolygonFeedback == null)
            {
                // 宣言したグローバル変数に NewPolygonFeedback オブジェクトをセット
                pNewPolygonFeedback = new NewPolygonFeedbackClass();

                // ポリゴン フィードバックのシンボルを設定
                ISimpleLineSymbol pSimpleLineSymbol = (ISimpleLineSymbol)pNewPolygonFeedback.Symbol;
                IRgbColor pRgbColor = new RgbColorClass();
                pRgbColor.Red = 100;
                pRgbColor.Green = 100;
                pRgbColor.Blue = 255;
                
                pSimpleLineSymbol.Color = pRgbColor;
                pSimpleLineSymbol.Style = esriSimpleLineStyle.esriSLSDot;

                // ポリゴン フィードバックのディスプレイと開始点を設定
                pNewPolygonFeedback.Display = pActiveView.ScreenDisplay;
                pNewPolygonFeedback.Start(pPoint);
            }

            // INewPolygonFeedback オブジェクトが存在している場合
            else
            {                
                if (pSnappingResult != null)
                {
                    // スナップ結果が存在している場合、スナップ結果の位置にポリゴン フィードバックの頂点を追加
                    pNewPolygonFeedback.AddPoint(pSnapPoint);
                }                
                else
                {
                    // スナップ結果が存在していない場合、クリック地点にポリゴン フィードバックの頂点を追加
                    pNewPolygonFeedback.AddPoint(pPoint);
                }                
            }
        }

        protected override void OnMouseMove(ESRI.ArcGIS.Desktop.AddIns.Tool.MouseEventArgs arg)
        {
            base.OnMouseMove(arg);

            // INewPolygonFeedback オブジェクトが存在している場合
            if(pNewPolygonFeedback != null)
            {
                // マウス位置から Point オブジェクトを取得
                IPoint pPoint = pActiveView.ScreenDisplay.DisplayTransformation.ToMapPoint(arg.X, arg.Y);

                // スナップ結果を取得し、スナップ フィードバックを更新
                pSnappingResult = pPointSnapper.Snap(pPoint);
                pSnappingFeedback.Update(pSnappingResult, 0);

                if (pSnappingResult != null)
                {
                    // スナップ結果が存在している場合、スナップ結果の位置にポリゴン フィードバックの頂点を移動
                    pSnapPoint = pSnappingResult.Location;
                    pNewPolygonFeedback.MoveTo(pSnapPoint);
                }
                else
                {
                    // スナップ結果が存在していない場合は、マウス位置にポリゴン フィードバックの頂点を移動
                    pNewPolygonFeedback.MoveTo(pPoint);
                }   
            }
        }

        protected override void OnDoubleClick()
        {
            base.OnDoubleClick();
        
            // ポリゴン フィードバックで描いた図形を取得して、マップ上にエレメントを追加
            IPolygon pPolygon = (IPolygon)pNewPolygonFeedback.Stop();
            if(pPolygon != null)
            {
                AddCreateElement(pPolygon, pActiveView);
                pActiveView.PartialRefresh((esriViewDrawPhase)8, null, null);
            }

            pNewPolygonFeedback = null;  
        }

        protected override void OnRefresh(int hDC)
        {
            base.OnRefresh(hDC);

            // スナップ フィードバックの更新
            if(pSnappingFeedback != null)
            {
                pSnappingFeedback.Refresh(hDC);
            }

            // ポリゴン フィードバックの更新
            if(pNewPolygonFeedback != null)
            {
                pNewPolygonFeedback.Refresh(hDC);
            }
        }

        private void AddCreateElement(IGeometry pGeomPoly, IActiveView pAv)
        {
            // ポリゴン エレメントの作成
            IElement pElement = new PolygonElementClass();
            pElement.Geometry = pGeomPoly;
            IFillShapeElement pFillShapeElement = (IFillShapeElement)pElement;

            // カラーの設定
            IRgbColor pRgbColor = new RgbColorClass();
            pRgbColor.Red = 255;
            pRgbColor.Green = 255;
            pRgbColor.Blue = 180;

            // シンボルの設定
            ISimpleFillSymbol pSimpleFillSymbol = new SimpleFillSymbolClass();
            pSimpleFillSymbol.Color = pRgbColor;
            pSimpleFillSymbol.Style = esriSimpleFillStyle.esriSFSSolid;
            pFillShapeElement.Symbol = pSimpleFillSymbol;

            // グラフィック コンテナーに作成したエレメントを追加
            IGraphicsContainer pGraphicsContainer = (IGraphicsContainer)pAv;
            pGraphicsContainer.AddElement((IElement)pFillShapeElement, 0);
        }
        
        protected override void OnUpdate()
        {
            Enabled = ArcMap.Application != null;
        }
    }
}
Imports ESRI.ArcGIS.Geometry
Imports ESRI.ArcGIS.Framework
Imports ESRI.ArcGIS.esriSystem
Imports ESRI.ArcGIS.Display
Imports ESRI.ArcGIS.Controls
Imports ESRI.ArcGIS.Carto
Imports ESRI.ArcGIS.ArcMapUI

Public Class SnapPolygon
    Inherits ESRI.ArcGIS.Desktop.AddIns.Tool

    '参考
    'Working with the ArcGIS snapping environment
    'http://resources.arcgis.com/en/help/arcobjects-net/conceptualhelp/index.html#/d/0001000001s1000000.htm
    'NewPolygonFeedback Example
    'http://resources.esri.com/help/9.3/arcgisengine/arcobjects/esriDisplay/NewPolygonFeedback_Example.htm

    'モジュールレベル変数
    Private pSnappingEnvironment As ISnappingEnvironment
    Private pPointSnapper As IPointSnapper
    Private pSnappingFeedback As ISnappingFeedback
    Private pActiveView As IActiveView
    Private pNewPolygonFeedback As INewPolygonFeedback
    Private pSnappingResult As ISnappingResult
    Private pSnapPoint As IPoint

    Public Sub New()
        ' スナップ環境の初期化
        Dim pUID As UID = New UIDClass()
        pUID.Value = "{E07B4C52-C894-4558-B8D4-D4050018D1DA}"
        pSnappingEnvironment = CType(My.ArcMap.Application.FindExtensionByCLSID(pUID), ISnappingEnvironment)

        ' スナップタイプの設定
        pSnappingEnvironment.SnappingType = DirectCast(2 + 8, esriSnappingType)

        ' スナップの許容値
        pSnappingEnvironment.Tolerance = 20

        pSnappingEnvironment.Enabled = True
        pPointSnapper = pSnappingEnvironment.PointSnapper

        ' スナップ フィードバックの初期化
        pSnappingFeedback = New SnappingFeedbackClass()
        pSnappingFeedback.Initialize(My.ArcMap.Application, pSnappingEnvironment, True)
    End Sub

    Protected Overrides Sub OnMouseDown(arg As ESRI.ArcGIS.Desktop.AddIns.Tool.MouseEventArgs)
        MyBase.OnMouseDown(arg)

        ' クリック地点から Point オブジェクトを取得
        pActiveView = My.ArcMap.Document.ActiveView
        Dim pPoint As IPoint = pActiveView.ScreenDisplay.DisplayTransformation.ToMapPoint(arg.X, arg.Y)

        ' INewPolygonFeedback オブジェクトが存在していない場合
        If pNewPolygonFeedback Is Nothing Then

            ' 宣言したグローバル変数に NewPolygonFeedback オブジェクトをセット
            pNewPolygonFeedback = New NewPolygonFeedbackClass()

            ' ポリゴン フィードバックのシンボルを設定
            Dim pSimpleLineSymbol As ISimpleLineSymbol = CType(pNewPolygonFeedback.Symbol, ISimpleLineSymbol)
            Dim pRgbColor As IRgbColor = New RgbColorClass()
            pRgbColor.Red = 100
            pRgbColor.Green = 100
            pRgbColor.Blue = 255

            pSimpleLineSymbol.Color = pRgbColor
            pSimpleLineSymbol.Style = esriSimpleLineStyle.esriSLSDot

            ' ポリゴン フィードバックのディスプレイと開始点を設定
            pNewPolygonFeedback.Display = pActiveView.ScreenDisplay
            pNewPolygonFeedback.Start(pPoint)
        Else
            If Not pSnappingResult Is Nothing Then
                ' スナップ結果が存在している場合、スナップ結果の位置にポリゴン フィードバックの頂点を追加
                pNewPolygonFeedback.AddPoint(pSnapPoint)
            Else
                ' スナップ結果が存在していない場合、クリック地点にポリゴン フィードバックの頂点を追加
                pNewPolygonFeedback.AddPoint(pPoint)
            End If
        End If
    End Sub

    Protected Overrides Sub OnMouseMove(arg As ESRI.ArcGIS.Desktop.AddIns.Tool.MouseEventArgs)
        MyBase.OnMouseMove(arg)

        ' INewPolygonFeedback オブジェクトが存在している場合
        If Not pNewPolygonFeedback Is Nothing Then

            ' マウス位置から Point オブジェクトを取得
            Dim pPoint As IPoint = pActiveView.ScreenDisplay.DisplayTransformation.ToMapPoint(arg.X, arg.Y)

            ' スナップ結果を取得し、スナップ フィードバックを更新
            pSnappingResult = pPointSnapper.Snap(pPoint)
            pSnappingFeedback.Update(pSnappingResult, 0)

            If Not pSnappingResult Is Nothing Then

                ' スナップ結果が存在している場合、スナップ結果の位置にポリゴン フィードバックの頂点を移動
                pSnapPoint = pSnappingResult.Location
                pNewPolygonFeedback.MoveTo(pSnapPoint)
            Else
                ' スナップ結果が存在していない場合は、マウス位置にポリゴン フィードバックの頂点を移動
                pNewPolygonFeedback.MoveTo(pPoint)
            End If
        End If
    End Sub

    Protected Overrides Sub OnDoubleClick()
        MyBase.OnDoubleClick()

        ' ポリゴン フィードバックで描いた図形を取得して、マップ上にエレメントを追加
        Dim pPolygon As IPolygon = pNewPolygonFeedback.Stop()
        If Not pPolygon Is Nothing Then
            AddCreateElement(pPolygon , pActiveView)
            pActiveView.PartialRefresh(CType(8, esriViewDrawPhase), Nothing, Nothing)
        End If

        pNewPolygonFeedback = Nothing
    End Sub

    Protected Overrides Sub OnRefresh(hDC As Integer)
        MyBase.OnRefresh(hDC)

        ' スナップ フィードバックの更新
        If Not pSnappingFeedback Is Nothing Then
            pSnappingFeedback.Refresh(hDC)
        End If

        ' ポリゴン フィードバックの更新
        If Not pNewPolygonFeedback Is Nothing Then
            pNewPolygonFeedback.Refresh(hDC)
        End If
    End Sub

    Protected Overrides Sub OnUpdate()
        Enabled = My.ArcMap.Application IsNot Nothing
    End Sub

    Private Sub AddCreateElement(pGeomPoly As IGeometry, pAv As IActiveView)
        ' ポリゴン エレメントの作成
        Dim pElement As IElement = New PolygonElementClass()
        pElement.Geometry = pGeomPoly
        Dim pFillShapeElement As IFillShapeElement = CType(pElement, IFillShapeElement)

        ' カラーの設定
        Dim pRgbColor As IRgbColor = New RgbColorClass()
        pRgbColor.Red = 255
        pRgbColor.Green = 255
        pRgbColor.Blue = 180

        ' シンボルの設定
        Dim pSimpleFillSymbol As ISimpleFillSymbol = New SimpleFillSymbolClass()
        pSimpleFillSymbol.Color = pRgbColor
        pSimpleFillSymbol.Style = esriSimpleFillStyle.esriSFSSolid
        pFillShapeElement.Symbol = pSimpleFillSymbol

        ' グラフィック コンテナーに作成したエレメントを追加
        Dim pGraphicsContainer As IGraphicsContainer = CType(pAv, IGraphicsContainer)
        pGraphicsContainer.AddElement(CType(pFillShapeElement, IElement), 0)
    End Sub
End Class

免責事項

こちらのサンプルはあくまでもコーディングの見本であり、実行時に発生したエラーの対処方法につきましては、サポート対象外とさせていただきます。
また、操作方法やソースコードに関するご質問は別途有償の開発者サポート契約にてご対応させていただきます。なお、コードを実行して生じたいかなる損害についても弊社では責任を負いかねます。

参考情報

メタデータ

種類

製品