ArcObjects Library Reference  

CurveConversionDockWin

About the Curve conversion add-in Sample

[C#]

CurveConversionDockWin.cs

using System;
using System.Windows.Forms;
using ESRI.ArcGIS.Editor;
using ESRI.ArcGIS.EditorExt;
using ESRI.ArcGIS.esriSystem;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.Geometry;
using ESRI.ArcGIS.ArcMapUI;
using ESRI.ArcGIS.Framework;

namespace CurveConversion
{
    /// <summary>
    /// Designer class of the dockable window add-in. It contains user interfaces that
    /// make up the dockable window.
    /// </summary>
    public partial class CurveConversionDockWin : UserControl
    {
        private IDockableWindow _CurveDockWin;
        public static Double _Tolerance = 0.1;
        public static String _sFieldName = "";
        public static IFields _MFields;
        public static System.Object _UpdateValue = 0;
        private static bool _Cancel = false;
        public bool _UpdateFieldIsString = false;
        private bool _CheckTol = false;
        public IEditor _Editor;
        public IEnvelope _InvalidEnv;
        internal static CurveConversionDockWin _CurveUserControl;

        public CurveConversionDockWin(object hook)
        {
            InitializeComponent();
            this.Hook = hook;
            
            _CurveUserControl = this;
        }

        /// <summary>
        /// Host object of the dockable window
        /// </summary>
        private object Hook
        {
            get;
            set;
        }

        /// <summary>
        /// Implementation class of the dockable window add-in. It is responsible for 
        /// creating and disposing the user interface class of the dockable window.
        /// </summary>
        public class AddinImpl : ESRI.ArcGIS.Desktop.AddIns.DockableWindow
        {
            private CurveConversionDockWin m_windowUI;

            public AddinImpl()
            {
            }

            protected override IntPtr OnCreateChild()
            {
                m_windowUI = new CurveConversionDockWin(this.Hook);
                return m_windowUI.Handle;
            }

            protected override void Dispose(bool disposing)
            {
                if (m_windowUI != null)
                    m_windowUI.Dispose(disposing);

                base.Dispose(disposing);
            }
        }

        /// <summary>
        /// Populates the Fields combo box with the fields other than Shape_length and area.
        /// </summary>
        public static void UpdateFieldList()
        {
            _CurveUserControl.comboBoxField.Items.Clear();
            _CurveUserControl.comboBoxField.Items.Add("<none>");

            if (_MFields != null)
            {
                for (int i = 0; i < _MFields.FieldCount; i++)
                {
                    if (_MFields.get_Field(i).Type == esriFieldType.esriFieldTypeDouble |
                        _MFields.get_Field(i).Type == esriFieldType.esriFieldTypeInteger |
                        _MFields.get_Field(i).Type == esriFieldType.esriFieldTypeSingle |
                        _MFields.get_Field(i).Type == esriFieldType.esriFieldTypeString)
                    {
                        string FieldName = _MFields.get_Field(i).Name.ToUpper();
                        if (FieldName != "SHAPE_LENGTH" & FieldName != "SHAPE_AREA")
                        {
                            _CurveUserControl.comboBoxField.Items.Add(_MFields.get_Field(i).Name);
                        }
                    }
                }
            }

            //Reset the form. 
            _Cancel = true;
            _CurveUserControl.checkBoxTolerance.Checked = false;
            _CurveUserControl.textBoxTolerance.Text = _Tolerance.ToString();
            _CurveUserControl.textBoxTolerance.Enabled = false;
            _CurveUserControl.textBoxvalue.Text = ""; 
            _sFieldName = "";          
            _CurveUserControl.comboBoxField.SelectedIndex = 0;
        }

        private void buttonOK_Click(object sender, EventArgs e)
        {
            //You may also want to check that a shapefile is not being used. 



            //Get the editor for the dockable window. 
            UID eUID = new UIDClass();
            eUID.Value = "esriEditor.Editor";
            _Editor = ArcMap.Application.FindExtensionByCLSID(eUID) as IEditor;

            if (CheckValues() == false)
                return;
            _Tolerance = Convert.ToDouble(textBoxTolerance.Text);
            System.Windows.Forms.Cursor.Current = Cursors.WaitCursor;
            //Run the curve update. 
            CurveUpdate(_CheckTol);
            _Cancel = false;
            System.Windows.Forms.Cursor.Current = Cursors.Default;
            
            //cast the control to a dockable window to hide it from the user. 
            _CurveDockWin = CurveConversionCmd.GetCurveConversionWindow;
            if (_CurveDockWin == null)
                return;
            _CurveDockWin.Show(false);

        }

        private void buttonCancel_Click(object sender, EventArgs e)
        {
            //hide the dockable window from the user. 
            _CurveDockWin = CurveConversionCmd.GetCurveConversionWindow;
            if (_CurveDockWin == null)
                return;
            _CurveDockWin.Show(false);
        }

        private void checkBoxTolerance_CheckedChanged(object sender, EventArgs e)
        {
            if (checkBoxTolerance.Checked == false)
            {
                _CheckTol = false;
                textBoxTolerance.Enabled = false;
                
            }
            else
            {
                _CheckTol = true;
                textBoxTolerance.Enabled = true;
            }
        }

        private void comboBoxField_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (comboBoxField.SelectedIndex > 0)
            {
                int lIndex = _MFields.FindField(comboBoxField.Text);
                if (lIndex > -1)
                {
                    if (_MFields.get_Field(lIndex).Type == esriFieldType.esriFieldTypeString)
                    {
                        _UpdateFieldIsString = true;
                        _sFieldName = _MFields.get_Field(lIndex).Name;
                    }
                    else
                    {
                        _UpdateFieldIsString = false;
                        _sFieldName = _MFields.get_Field(lIndex).Name;
                    }
                }
                else
                {
                    //resets the field to none.
                    comboBoxField.SelectedIndex = 0;
                }
            }
            else
            {
                _UpdateFieldIsString = false;
            }
        }

        private bool CheckValues()
        {
            //Check for numeric tolerance value if option is checked
            int i;
            bool isnumeric = Int32.TryParse(textBoxTolerance.Text, out i);
            double a;
            isnumeric = double.TryParse(textBoxTolerance.Text, out a);
            if ((checkBoxTolerance.Checked == true) & (isnumeric == false))
            {
                MessageBox.Show("Tolerance value must be numeric!!");
                return false;
            }

            //Check for numeric value if field to update is not a string field
            if (comboBoxField.SelectedIndex > 0)
            {
                isnumeric = int.TryParse(textBoxvalue.Text, out i);
                if ((isnumeric = false) & (_UpdateFieldIsString = false))
                {
                    MessageBox.Show("Update value must be numeric when the field is numeric!!!");
                    return false;
                }
            }
            return true;
        }

        private void CurveUpdate(bool checkTol)
        {
            try
            {
                //***Not sure that the progress bar is needed***//
                //Set up the progress bar. 
                IStatusBar _Status = ArcMap.Application.StatusBar;
                IStepProgressor _StepProg = _Status.ProgressBar;
                _StepProg.Position = 1;
                _StepProg.MaxRange = _Editor.SelectionCount;
                _StepProg.Message = "Update progress:";
                _StepProg.StepValue = 1;
                _StepProg.Show();

                int lCount = 0;
                _InvalidEnv = null;
                //You will get an error if your feature is stored in a shapefile.
                //Check to make sure there is no existing edit operation, then start one.
                IWorkspaceEdit2 _WorkspaceEdit = (IWorkspaceEdit2)_Editor.EditWorkspace;
                if (!_WorkspaceEdit.IsInEditOperation)
                {
                    _Editor.StartOperation();
                }
                
                ICurve _Curve;
                ICurve _Curve2;
                ISegmentCollection _OrigSegs;
                ISegmentCollection _Polyline;
                IConstructCircularArc _NewLine;
                Boolean _bSegCheck;
                IPoint _MidPoint;
                ISegment _Seg;
                Double _Dist = 0, _Dist1 = 0, _Dist2 = 0;
                Boolean _Side = false, _Updated = false;
                IEnumTopologyEdge _EdgeEnum;
                ISegmentCollection _Path = new PathClass();
                ITopologyEdge _TopoEdge;
                IPolyline _SomeLine;
                IEnumFeature _EnumFeat = _Editor.EditSelection;
                IFeature feat = _EnumFeat.Next();
                
                //Check for a topology
                ITopologyGraph _TopoGraph = TopologyCheck(feat.Class);

                do
                {
                    if (feat.Shape.GeometryType == esriGeometryType.esriGeometryPolyline & (!IsStraight(feat)))
                    {
                        //Create the new segment based on a 3pt curve through the start point, mid point and end point of the feat geometry.
                        _Curve = feat.Shape as ICurve;
                        _OrigSegs = _Curve as ISegmentCollection;
                        _MidPoint = new PointClass();
                        _Curve.QueryPoint(esriSegmentExtension.esriNoExtension, 0.5, true, _MidPoint);
                        _NewLine = new CircularArcClass();
                        _NewLine.ConstructThreePoints(_Curve.FromPoint, _MidPoint, _Curve.ToPoint, false);
                        _Curve2 = _NewLine as ICurve;

                        //Check that the segments are within the tolerance. 
                        _bSegCheck = false;
                        if (checkTol)
                        {
                            for (int lLoop = 1; lLoop < _OrigSegs.SegmentCount; lLoop++)
                            {
                                _Seg = _OrigSegs.get_Segment(lLoop);
                                _Curve2.QueryPointAndDistance(esriSegmentExtension.esriNoExtension, _Seg.FromPoint, false, _MidPoint, ref _Dist, ref  _Dist1, ref _Side);
                                _Curve2.QueryPointAndDistance(esriSegmentExtension.esriNoExtension, _Seg.ToPoint, false, _MidPoint, ref _Dist, ref  _Dist2, ref _Side);

                                if (_Dist1 > _Tolerance | _Dist2 > _Tolerance)
                                {
                                    _bSegCheck = true;
                                    break;
                                }
                            }
                        }

                        if (!_bSegCheck)
                        {
                            //Check for a topology. 
                            if (_TopoGraph != null)
                            {
                                _EdgeEnum = GetParents(feat, _TopoGraph);
                                if (_EdgeEnum == null)
                                {
                                    //not sure what i need to add, but to get here something went wrong. 
                                }
                                else
                                {
                                    object Missing = Type.Missing;
                                    _Path.AddSegment(_NewLine as ISegment, ref Missing, ref Missing);


                                    switch (_EdgeEnum.Count)
                                    {
                                        case 1:
                                            _EdgeEnum.Reset();
                                            _TopoEdge = _EdgeEnum.Next();
                                            _Updated = UpdateEdge(_TopoGraph, _TopoEdge, _Path);
                                            if (_Updated)
                                            {
                                                UpdateField(feat, true);
                                                lCount++;
                                            }
                                            break;
                                        case 2:
                                            _EdgeEnum.Reset();
                                            _TopoEdge = _EdgeEnum.Next();

                                            do
                                            {
                                                _SomeLine = _TopoEdge.Geometry as IPolyline;
                                                double X1 = _Path.get_Segment(0).FromPoint.X;
                                                double Y1 = _Path.get_Segment(0).FromPoint.Y;
                                                double X2 = _Path.get_Segment(0).ToPoint.X;
                                                double Y2 = _Path.get_Segment(0).ToPoint.Y;

                                                if (X1 == _SomeLine.FromPoint.X & Y1 == _SomeLine.FromPoint.Y &
                                                    X2 == _SomeLine.ToPoint.X & Y2 == _SomeLine.FromPoint.Y)
                                                {
                                                    _Updated = UpdateEdge(_TopoGraph, _TopoEdge, _Path);
                                                    if (_Updated)
                                                    {
                                                        UpdateField(feat, true);
                                                        lCount++;
                                                    }
                                                    break;
                                                }
                                                _TopoEdge = _EdgeEnum.Next();
                                            }
                                            while (_TopoEdge != null);
                                            break;
                                        default:

                                            break;
                                    }
                                    _EdgeEnum = null;
                                }

                            }
                            else
                            {
                                //the current feature is not part of a topo, so just update it.
                                _Polyline = new PolylineClass();
                                object Missing = Type.Missing;
                                _Polyline.AddSegment(_NewLine as ISegment, ref Missing, ref Missing);
                                //This code sets the polyline ZAware so it will handle Z aware features. 
                                //However you need to check that the feature is Z aware first, so you can add this code here. 
                                //IZAware zAware = _Polyline as IZAware;
                                //zAware.ZAware = true;

                                feat.Shape = _Polyline as IGeometry;
                                UpdateField(feat, false);
                                feat.Store();
                                lCount++;
                                if (_InvalidEnv == null)
                                {
                                    _InvalidEnv = feat.Shape.Envelope;
                                }
                                else
                                {
                                    _InvalidEnv.Union(feat.Shape.Envelope);
                                }
                            }
                        }
                    }

                    feat = _EnumFeat.Next();
                    ArcMap.Application.StatusBar.ProgressBar.Step();
                } while (feat != null);

                if (lCount == 0)
                {
                    MessageBox.Show("No features were updated.");
                    _Editor.AbortOperation();
                }
                else
                {
                    MessageBox.Show(lCount + " feature(s) updated");
                    _Editor.StopOperation("Update Curves");
                }

                if (_InvalidEnv != null)
                {
                    IMxDocument _Doc = ArcMap.Application.Document as IMxDocument;
                    _Doc.ActiveView.PartialRefresh(ESRI.ArcGIS.Carto.esriViewDrawPhase.esriViewAll, null, _InvalidEnv);
                }
                ArcMap.Application.StatusBar.ProgressBar.Hide();
            }
            catch(Exception e)
            {
                MessageBox.Show("Error in updating the Curve, make sure you are not using a shapefile." + e.Message);
                ArcMap.Application.StatusBar.ProgressBar.Hide();
                return;
            } 
        }

        /// <summary>
        /// Checks the field type and converts the update value to the correct type and updates the feature.
        /// </summary>
        /// <param name="feat"></param>
        /// <param name="shouldStore"></param>
        private void UpdateField(IFeature feat, bool shouldStore)
        {
            try
            {
                int lFieldIndex = 0;
                
                if (_sFieldName != "<none>")
                {
                    lFieldIndex = feat.Fields.FindField(_sFieldName);
                    if (lFieldIndex > -1)
                    {
                        _UpdateValue = textBoxvalue.Text;
                        switch (feat.Fields.get_Field(lFieldIndex).Type)
                        {
                            case esriFieldType.esriFieldTypeString:
                                feat.set_Value(lFieldIndex, _UpdateValue.ToString());
                                break;
                            case esriFieldType.esriFieldTypeInteger | esriFieldType.esriFieldTypeSmallInteger:
                                feat.set_Value(lFieldIndex, Convert.ToInt32(_UpdateValue));
                                break;
                            case esriFieldType.esriFieldTypeDouble | esriFieldType.esriFieldTypeSingle:
                                feat.set_Value(lFieldIndex, Convert.ToDouble(_UpdateValue));
                                break;
                            default:
                                break;
                        }
                        if (shouldStore)
                            feat.Store();
                    }
                }
            }
            catch 
            {
                return;
            }
        }

        private bool UpdateEdge(ITopologyGraph topoGraph, ITopologyEdge _TopoEdge, ISegmentCollection _Path)
        {
            try
            {
                ISegmentCollection _NewSegs = _TopoEdge.Geometry as ISegmentCollection;
                IEnvelope _Invalid = new EnvelopeClass();
                int inCount = _NewSegs.SegmentCount;
                topoGraph.SetEdgeGeometry(_TopoEdge, _Path as IPath);
                topoGraph.Post(out _Invalid);
                if (_InvalidEnv == null)
                { _InvalidEnv = _Invalid; }
                else { _InvalidEnv.Union(_Invalid); }

                _NewSegs = _TopoEdge.Geometry as ISegmentCollection;
                if (_NewSegs.SegmentCount == 1 & inCount > 1)
                {
                    return true;
                }
                else
                    return false;
            }
            catch (Exception e)
            {
                MessageBox.Show("Error in updating the topo edge " + e.Message);
                return false;
            }
        }

        /// <summary>
        /// Gets an enum of the parent edges for the feature. 
        /// </summary>
        /// <param name="feat"></param>
        /// <param name="topoGraph"></param>
        /// <returns></returns>
        private IEnumTopologyEdge GetParents(IFeature feat, ITopologyGraph topoGraph)
        {
            IFeatureClass fFC = feat.Class as IFeatureClass;
            IEnumTopologyEdge _EnumTopoEdge = topoGraph.GetParentEdges(fFC, feat.OID);
            if (_EnumTopoEdge == null)
            {
                topoGraph.SetEmpty();
                topoGraph.Build(feat.Shape.Envelope, false);
                _EnumTopoEdge = topoGraph.GetParentEdges(fFC, feat.OID);
            }
            else
            {
                if (_EnumTopoEdge.Count > 1)
                {
                    topoGraph.DeletePseudoNodesFromSelection();
                }
            }
            return _EnumTopoEdge;
        }

        /// <summary>
        /// Check to see if the line is straight. So we do NOT convert straight lines to polycurves.
        /// </summary>
        /// <param name="feat"></param>
        private bool IsStraight(IFeature feat)
        {
            try
            {
                if (feat.Shape.GeometryType != esriGeometryType.esriGeometryPolyline)
                    return true;
                ISpatialReference _SR = feat.Shape.SpatialReference;
                IPolycurve _PolyCurve = feat.ShapeCopy as IPolycurve;
                ISegmentCollection _SegColl = _PolyCurve as ISegmentCollection;
                double _x;
                double _y;
                double _units;
                _SR.GetFalseOriginAndUnits(out _x, out _y, out _units);
                _PolyCurve.Generalize(2 / _units);

                if (_SegColl.SegmentCount == 1)
                { return true; }
                else
                { return false; }
            }
            catch (Exception e)
            {
                MessageBox.Show("Error in checking straight " + e.Message);
                return false;
            }
        }

        /// <summary>
        /// Checks to see if the feature class is part of a gdb or map topology. 
        /// If it is it will build the topo cache and return the topology graph.
        /// </summary>
        /// <param name="oBJClass"></param>
        /// <returns></returns>
        private ITopologyGraph TopologyCheck(IObjectClass oBJClass)
        {
            try
            {
                ITopologyClass topoClass = oBJClass as ITopologyClass;
                ITopologyGraph topoGraph;
                

                if (topoClass.IsInTopology) 
                {
                    //Check to see if the class of the selected feature is part of the a topology.
                    if (topoClass.Topology.Cache != null)
                    {
                       return topoGraph = topoClass.Topology.Cache as ITopologyGraph;
                    }
                    else
                    {
                        return topoGraph = null;
                    }
                }
                else
                {
                    //Check to see if the class of the selected feature is part of a map topology.
                    UID mUID = new UIDClass();
                    mUID.Value = "esriEditor.TopologyExtension";
                    ITopologyExtension topoExt = ArcMap.Application.FindExtensionByCLSID(mUID) as ITopologyExtension;
                    IMapTopology mapTopo = topoExt.MapTopology; 
                    IFeatureClass featClass = oBJClass as IFeatureClass;
                    int lID = mapTopo.FindClass(featClass);
                    if (lID > -1)
                    {
                       return topoGraph = mapTopo.Cache;
                    }
                    else
                    {
                       return topoGraph = null;
                    }
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("Error checking topology" + e);
                return null;
            }
        }

    }
}

[Visual Basic .NET]

CurveConversionDockWin.vb

Imports System.Windows.Forms
Imports ESRI.ArcGIS.esriSystem
Imports ESRI.ArcGIS.Geodatabase
Imports ESRI.ArcGIS.EditorExt
Imports ESRI.ArcGIS.Geometry
Imports ESRI.ArcGIS.ArcMapUI
Imports ESRI.ArcGIS.Editor
Imports ESRI.ArcGIS.Framework

''' <summary>
''' Designer class of the dockable window add-in. It contains user interfaces that
''' make up the dockable window.
''' </summary>
Public Class CurveConversionDockWin

    Private _CurveDockwin As ESRI.ArcGIS.Framework.IDockableWindow
    Public Shared _MFields As IFields
    Dim _UpdateValue As System.Object
    Shared _Cancel As Boolean = False
    Dim _UpdateFieldIsString As Boolean = False
    Private _CheckTol As Boolean = False
    Dim _Editor As IEditor
    Dim _InvalidEnv As IEnvelope
    Shared _Tolerance As [Double] = 0.1
    Shared _sFieldName As [String] = ""
    Shared _CurveUserControl As CurveConversionDockWin

    Public Sub New(ByVal hook As Object)

        ' This call is required by the Windows Form Designer.
        InitializeComponent()

        ' Add any initialization after the InitializeComponent() call.
        Me.Hook = hook
        _CurveUserControl = Me
    End Sub

    Private m_hook As Object
    ''' <summary>
    ''' Host object of the dockable window
    ''' </summary> 
    Public Property Hook() As Object
        Get
            Return m_hook
        End Get
        Set(ByVal value As Object)
            m_hook = value
        End Set
    End Property

    Private Sub buttonOK_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles buttonOK.Click
        'You may also want to check that a shapefile is not being used. 
        'Get a refence to the editor.
        Dim uidEditor As New UID
        uidEditor.Value = "esriEditor.Editor"
        _Editor = TryCast(My.ArcMap.Application.FindExtensionByCLSID(uidEditor), ESRI.ArcGIS.Editor.IEditor)

        If CheckValues() = False Then
            Return
        End If
        _Tolerance = Convert.ToDouble(textBoxTolerance.Text)
        System.Windows.Forms.Cursor.Current = Cursors.WaitCursor

        'Run the curve update
        CurveUpdate(_CheckTol)
        _Cancel = False
        System.Windows.Forms.Cursor.Current = Cursors.Default
        'Cast the control to a dockable window to hide it from the user
        _CurveDockwin = CurveConversionCmd.GetCurveConversionWindow()

        If _CurveDockwin Is Nothing Then
            Return
        End If
        _CurveDockwin.Show(False)
    End Sub

    Private Sub buttonCancel_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles buttonCancel.Click
        'hide the dockable window from the user. 
        _CurveDockwin = CurveConversionCmd.GetCurveConversionWindow
        If _CurveDockwin Is Nothing Then
            Return
        End If
        _CurveDockwin.Show(False)
    End Sub

    Private Function CheckValues() As Boolean
        CheckValues = False

        'Check for numeric tolerance value if option is checked
        If checkBoxTolerance.Checked = True And Not IsNumeric(textBoxTolerance.Text) Then
            MessageBox.Show("Tolerance value must be numeric!!")
            Exit Function
        End If

        'Check for numeric value if field to update is not a string field
        If comboBoxField.SelectedIndex > 0 Then
            If Not IsNumeric(textBoxvalue.Text) And Not _UpdateFieldIsString Then
                MessageBox.Show("Update value must be numeric when the field is numeric!!!")
                Exit Function
            End If
        End If

        CheckValues = True
    End Function

    ''' <summary>
    ''' Populates the Fields combo box with the fields other than Shape_length and area.
    ''' </summary>
    ''' <remarks></remarks>
    Shared Sub UpdateFieldList()
        Dim lLoop As Long
        _CurveUserControl.comboBoxField.Items.Clear()
        _CurveUserControl.comboBoxField.Items.Add("<none>")
        If Not _MFields Is Nothing Then
            For lLoop = 0 To _MFields.FieldCount - 1
                If _MFields.Field(lLoop).Type = esriFieldType.esriFieldTypeDouble Or _
                 _MFields.Field(lLoop).Type = esriFieldType.esriFieldTypeSingle Or _
                 _MFields.Field(lLoop).Type = esriFieldType.esriFieldTypeInteger Or _
                 _MFields.Field(lLoop).Type = esriFieldType.esriFieldTypeSmallInteger Or _
                 _MFields.Field(lLoop).Type = esriFieldType.esriFieldTypeString Then
                    If UCase(_MFields.Field(lLoop).Name) <> "SHAPE_LENGTH" And _
                     UCase(_MFields.Field(lLoop).Name) <> "SHAPE_AREA" Then
                        _CurveUserControl.comboBoxField.Items.Add(_MFields.Field(lLoop).Name)
                    End If
                End If
            Next lLoop
        End If

        _Cancel = True
        _CurveUserControl.checkBoxTolerance.Checked = False
        _CurveUserControl.textBoxTolerance.Text = CStr(_Tolerance)
        _CurveUserControl.textBoxTolerance.Enabled = False
        _CurveUserControl.textBoxvalue.Text = ""
        _sFieldName = ""
        _CurveUserControl.comboBoxField.SelectedIndex = 0

    End Sub

    ''' <summary>
    ''' Implementation class of the dockable window add-in. It is responsible for
    ''' creating and disposing the user interface class for the dockable window.
    ''' </summary>
    Public Class AddinImpl
        Inherits ESRI.ArcGIS.Desktop.AddIns.DockableWindow

        Private m_windowUI As CurveConversionDockWin

        Protected Overrides Function OnCreateChild() As System.IntPtr
            m_windowUI = New CurveConversionDockWin(Me.Hook)
            Return m_windowUI.Handle
        End Function

        Protected Overrides Sub Dispose(ByVal Param As Boolean)
            If m_windowUI IsNot Nothing Then
                m_windowUI.Dispose(Param)
            End If

            MyBase.Dispose(Param)
        End Sub

    End Class

    Private Sub CurveUpdate(ByVal _CheckTol As Boolean)
        Try
            'Set up the progress bar.
            Dim _Status As IStatusBar = My.ArcMap.Application.StatusBar
            Dim _StepProg As IStepProgressor = _Status.ProgressBar
            With _StepProg
                .Position = 1
                .MaxRange = _Editor.SelectionCount
                .Message = "Update progress:"
                .StepValue = 1
                .Show()
            End With
            Dim lCount As Integer = 0
            _InvalidEnv = Nothing
            'You will get an error if your feature is stored in a shapefile.
            'Check to make sure there is no existing edit operation, then start one.

            Dim _WorkspaceEdit As IWorkspaceEdit2 = DirectCast(_Editor.EditWorkspace, IWorkspaceEdit2)
            If Not _WorkspaceEdit.IsInEditOperation Then
                _Editor.StartOperation()
            End If

            Dim _Curve As ICurve
            Dim _Curve2 As ICurve
            Dim _OrigSegs As ISegmentCollection
            Dim _Polyline As ISegmentCollection
            Dim _MidPoint As IPoint
            Dim _NewLine As IConstructCircularArc
            Dim _bSegCheck As [Boolean]
            Dim _OutPoint As IPoint = New PointClass()
            Dim _Seg As ISegment
            Dim _Dist As [Double] = 0, _Dist1 As [Double] = 0, _Dist2 As [Double] = 0
            Dim _Side As [Boolean] = False, _Updated As [Boolean] = False
            Dim _EdgeEnum As IEnumTopologyEdge
            Dim _Path As ISegmentCollection = New PathClass()
            Dim _TopoEdge As ITopologyEdge
            Dim _SomeLine As IPolyline
            Dim _EnumFeat As IEnumFeature = _Editor.EditSelection
            Dim feat As IFeature = _EnumFeat.[Next]()
            'Check for a topology
            Dim _TopoGraph As ITopologyGraph = TopologyCheck(feat.[Class])

            Do
                If feat.Shape.GeometryType = ESRI.ArcGIS.Geometry.esriGeometryType.esriGeometryPolyline And (Not IsStraight(feat)) Then
                    'Create the new segment based on a 3pt curve through the start point, mid point and end point of the feat geometry.
                    _Curve = TryCast(feat.Shape, ICurve)
                    _OrigSegs = TryCast(_Curve, ISegmentCollection)
                    _MidPoint = New PointClass()
                    _Curve.QueryPoint(ESRI.ArcGIS.Geometry.esriSegmentExtension.esriNoExtension, 0.5, True, _MidPoint)
                    _NewLine = New CircularArcClass()
                    _NewLine.ConstructThreePoints(_Curve.FromPoint, _MidPoint, _Curve.ToPoint, False)
                    _Curve2 = TryCast(_NewLine, ICurve)

                    'Check that the segments are within the tolerance. 
                    _bSegCheck = False
                    If _CheckTol Then
                        For lLoop As Integer = 1 To _OrigSegs.SegmentCount - 1
                            _Seg = _OrigSegs.Segment(lLoop)
                            _Curve2.QueryPointAndDistance(ESRI.ArcGIS.Geometry.esriSegmentExtension.esriNoExtension, _Seg.FromPoint, False, _MidPoint, _Dist, _Dist1, _
                            _Side)
                            _Curve2.QueryPointAndDistance(ESRI.ArcGIS.Geometry.esriSegmentExtension.esriNoExtension, _Seg.ToPoint, False, _MidPoint, _Dist, _Dist2, _
                            _Side)

                            If _Dist1 > _Tolerance Or _Dist2 > _Tolerance Then
                                _bSegCheck = True
                                Exit For
                            End If
                        Next
                    End If

                    If Not _bSegCheck Then
                        If _TopoGraph IsNot Nothing Then
                            _EdgeEnum = GetParents(feat, _TopoGraph)
                            If _EdgeEnum Is Nothing Then
                                'not sure what i need to add, but to get here something went wrong. 
                            Else
                                Dim Missing As Object = Type.Missing
                                _Path.AddSegment(TryCast(_NewLine, ISegment), Missing, Missing)


                                Select Case _EdgeEnum.Count
                                    Case 1
                                        _EdgeEnum.Reset()
                                        _TopoEdge = _EdgeEnum.[Next]()
                                        _Updated = UpdateEdge(_TopoGraph, _TopoEdge, _Path)
                                        If _Updated Then
                                            UpdateField(feat, True)
                                            lCount += 1
                                        End If
                                        Exit Select
                                    Case 2
                                        _EdgeEnum.Reset()
                                        _TopoEdge = _EdgeEnum.[Next]()

                                        Do
                                            _SomeLine = TryCast(_TopoEdge.Geometry, IPolyline)
                                            Dim X1 As Double = _Path.Segment(0).FromPoint.X
                                            Dim Y1 As Double = _Path.Segment(0).FromPoint.Y
                                            Dim X2 As Double = _Path.Segment(0).ToPoint.X
                                            Dim Y2 As Double = _Path.Segment(0).ToPoint.Y

                                            If X1 = _SomeLine.FromPoint.X And Y1 = _SomeLine.FromPoint.Y And X2 = _SomeLine.ToPoint.X And Y2 = _SomeLine.FromPoint.Y Then
                                                _Updated = UpdateEdge(_TopoGraph, _TopoEdge, _Path)
                                                If _Updated Then
                                                    UpdateField(feat, True)
                                                    lCount += 1
                                                End If
                                                Exit Do
                                            End If
                                            _TopoEdge = _EdgeEnum.[Next]()
                                        Loop While _TopoEdge IsNot Nothing
                                        Exit Select
                                    Case Else

                                        Exit Select
                                End Select
                                _EdgeEnum = Nothing

                            End If
                        Else
                            'the current feature is not part of a topo, so just update it.
                            _Polyline = New PolylineClass()
                            Dim Missing As Object = Type.Missing
                            _Polyline.AddSegment(TryCast(_NewLine, ISegment), Missing, Missing)
                            'This code sets the polyline ZAware so it will handle Z aware features. 
                            'However you need to check that the feature is Z aware first, so you can add this code here. 
                            'Dim zAware as IZAware = _Polyline as IZAware
                            'zAware.ZAware = true
                            feat.Shape = TryCast(_Polyline, IGeometry)
                            UpdateField(feat, False)
                            feat.Store()
                            lCount += 1
                            If _InvalidEnv Is Nothing Then
                                _InvalidEnv = feat.Shape.Envelope
                            Else
                                _InvalidEnv.Union(feat.Shape.Envelope)

                            End If
                        End If
                    End If
                End If
                feat = _EnumFeat.[Next]()
                My.ArcMap.Application.StatusBar.ProgressBar.[Step]()
            Loop While feat IsNot Nothing

            If lCount = 0 Then
                MessageBox.Show("No features were updated.")
                _Editor.AbortOperation()
            Else
                MessageBox.Show(lCount & " feature(s) updated")
                _Editor.StopOperation("Update Curves")
            End If

            If _InvalidEnv IsNot Nothing Then
                Dim _Doc As IMxDocument = TryCast(My.ArcMap.Application.Document, IMxDocument)
                _Doc.ActiveView.PartialRefresh(ESRI.ArcGIS.Carto.esriViewDrawPhase.esriViewAll, Nothing, _InvalidEnv)
            End If
            My.ArcMap.Application.StatusBar.ProgressBar.Hide()

        Catch ex As Exception
            MessageBox.Show("Error in updating the Curve, make sure you are not using a shapefile." + ex.Message)
            My.ArcMap.Application.StatusBar.ProgressBar.Hide()
            Return
        End Try
    End Sub

    Private Sub UpdateField(ByVal feat As IFeature, ByVal shouldStore As Boolean)
        Try
            Dim lFieldIndex As Integer = 0
           
            If Not _sFieldName Is "<none>" Then
                lFieldIndex = feat.Fields.FindField(_sFieldName)
                If lFieldIndex > -1 Then
                    _UpdateValue = textBoxvalue.Text

                    feat.Value(lFieldIndex) = _UpdateValue
                    Select Case feat.Fields.Field(lFieldIndex).Type
                        Case esriFieldType.esriFieldTypeString
                            feat.Value(lFieldIndex) = _UpdateValue.ToString()

                        Case esriFieldType.esriFieldTypeInteger Or esriFieldType.esriFieldTypeString
                            feat.Value(lFieldIndex) = Convert.ToInt32(_UpdateValue)

                        Case esriFieldType.esriFieldTypeDouble Or esriFieldType.esriFieldTypeSingle
                            feat.Value(lFieldIndex) = Convert.ToDouble(_UpdateValue)

                        Case Else
                            Return
                    End Select
                    If shouldStore Then
                        feat.Store()
                    End If
                End If
            End If

        Catch ex As Exception
            Return
        End Try
    End Sub

    Private Function UpdateEdge(ByVal topoGraph As ITopologyGraph, ByVal _TopoEdge As ITopologyEdge, ByVal _Path As ISegmentCollection) As Boolean
        Try
            Dim _NewSegs As ISegmentCollection = TryCast(_TopoEdge.Geometry, ISegmentCollection)
            Dim _Invalid As IEnvelope = New EnvelopeClass()
            Dim inCount As Integer = _NewSegs.SegmentCount
            topoGraph.SetEdgeGeometry(_TopoEdge, TryCast(_Path, IPath))
            topoGraph.Post(_Invalid)
            If _InvalidEnv Is Nothing Then
                _InvalidEnv = _Invalid
            Else
                _InvalidEnv.Union(_Invalid)
            End If

            _NewSegs = TryCast(_TopoEdge.Geometry, ISegmentCollection)
            If _NewSegs.SegmentCount = 1 And inCount > 1 Then
                Return True
            Else
                Return False
            End If
        Catch e As Exception
            MessageBox.Show("Error in updating the topo edge " & e.Message)
            Return False
        End Try
    End Function

    Private Function GetParents(ByVal feat As IFeature, ByVal _TopoGraph As ITopologyGraph) As IEnumTopologyEdge
        Dim fFC As IFeatureClass = TryCast(feat.[Class], IFeatureClass)
        Dim _EnumTopoEdge As IEnumTopologyEdge = _TopoGraph.GetParentEdges(fFC, feat.OID)
        If _EnumTopoEdge Is Nothing Then
            _TopoGraph.SetEmpty()
            _TopoGraph.Build(feat.Shape.Envelope, False)
            _EnumTopoEdge = _TopoGraph.GetParentEdges(fFC, feat.OID)
        Else
            If _EnumTopoEdge.Count > 1 Then
                _TopoGraph.DeletePseudoNodesFromSelection()
            End If
        End If
        Return _EnumTopoEdge
    End Function

    ''' <summary>
    ''' Check to see if the line is straight. So we do NOT convert straight lines to polycurves.
    ''' </summary>
    ''' <param name="feat"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function IsStraight(ByVal feat As IFeature) As Boolean
        Try
            If feat.Shape.GeometryType <> ESRI.ArcGIS.Geometry.esriGeometryType.esriGeometryPolyline Then
                Return True
            End If
            Dim _SR As ISpatialReference = feat.Shape.SpatialReference
            Dim _PolyCurve As IPolycurve = TryCast(feat.ShapeCopy, IPolycurve)
            Dim _SegColl As ISegmentCollection = TryCast(_PolyCurve, ISegmentCollection)
            Dim _x As Double
            Dim _y As Double
            Dim _units As Double
            _SR.GetFalseOriginAndUnits(_x, _y, _units)
            _PolyCurve.Generalize(2 / _units)

            If _SegColl.SegmentCount = 1 Then
                Return True
            Else
                Return False
            End If
        Catch e As Exception
            MessageBox.Show("Error in checking straight " & e.Message)
            Return False
        End Try
    End Function

    ''' <summary>
    ''' Checks to see if the feature class is part of a gdb or map topology. 
    ''' If it is it will build the topo cache and return the topology graph.
    ''' </summary>
    ''' <param name="oBJClass"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function TopologyCheck(ByVal oBJClass As IObjectClass) As ITopologyGraph
        Try

            Dim topoClass As ITopologyClass = TryCast(oBJClass, ITopologyClass)
            Dim topoGraph As ITopologyGraph

            If topoClass.IsInTopology Then
                If topoClass.Topology.Cache IsNot Nothing Then
                    topoGraph = TryCast(topoClass.Topology.Cache, ITopologyGraph)
                Else
                    topoGraph = Nothing
                End If
            Else
                'Check to see if the class of the selected feature is part of a map topology.
                Dim mUID As UID = New UIDClass()
                mUID.Value = "esriEditor.TopologyExtension"
                Dim topoExt As ITopologyExtension = TryCast(My.ArcMap.Application.FindExtensionByCLSID(mUID), ITopologyExtension)
                Dim mapTopo As IMapTopology = topoExt.MapTopology
                Dim featClass As IFeatureClass = TryCast(oBJClass, IFeatureClass)
                Dim lID As Integer = mapTopo.FindClass(featClass)
                If lID > -1 Then
                    topoGraph = mapTopo.Cache
                Else
                    topoGraph = Nothing
                End If
            End If
            Return topoGraph
        Catch e As Exception
            MessageBox.Show("Error checking topology: " & e.Message)
            Return Nothing
        End Try
    End Function

    Private Sub checkBoxTolerance_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles checkBoxTolerance.CheckedChanged
        If checkBoxTolerance.Checked = False Then
            _CheckTol = False
            textBoxTolerance.Enabled = False
        Else
            _CheckTol = True
            textBoxTolerance.Enabled = True
        End If
    End Sub

    Private Sub comboBoxField_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles comboBoxField.SelectedIndexChanged
        Try
            If comboBoxField.SelectedIndex > 0 Then

                Dim lIndex As Integer = _MFields.FindField(comboBoxField.Text)
                If lIndex > -1 Then
                    If _MFields.Field(lIndex).Type = esriFieldType.esriFieldTypeString Then
                        _UpdateFieldIsString = True
                        _sFieldName = _MFields.Field(lIndex).Name
                    Else
                        _UpdateFieldIsString = False
                        _sFieldName = _MFields.Field(lIndex).Name
                    End If
                Else
                    'resets the field to none.
                    comboBoxField.SelectedIndex = 0
                End If
            Else
                _UpdateFieldIsString = False
            End If
        Catch ex As Exception
            Return
        End Try
    End Sub
End Class