ArcObjects Library Reference  

TranslateTree

About the Implementing a schematic layout algorithm and its layout property page Sample

[C#]

TranslateTree.cs

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using ESRI.ArcGIS.esriSystem;
using ESRI.ArcGIS.ADF.CATIDs;
using ESRI.ArcGIS.Schematic;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.Geometry;

namespace ApplicativeAlgorithmsCS
{
    [ClassInterface(ClassInterfaceType.None)]
    [Guid(TranslateTree.GUID)]
    [ProgId(TranslateTree.PROGID)]
    public class TranslateTree : ISchematicAlgorithm, ISchematicJSONParameters, ITranslateTree
    {
        // private member data
        public const string GUID = "A675D260-6AF0-438d-80AB-630B3F956D05";
        private const string PROGID = "ApplicativeAlgorithms.TranslateTree";

        // property names (for the algorithm property set)
        private const string TranslationFactorXName = "Translation Factor X";
        private const string TranslationFactorYName = "Translation Factor Y";

        // the JSON parameter names 
        private const string JSONTranslationFactorX = "TranslationFactorX";
        private const string JSONTranslationFactorY = "TranslationFactorY";

        // Algorithms parameters JSON representation Names used by the REST interface 
        private const string JSONName = "name";
        private const string JSONType = "type";
        private const string JSONValue = "value";
        // Algorithms parameters JSON representation Types used by the REST interface
        private const string JSONLong = "Long";
        private const string JSONDouble = "Double";
        private const string JSONBoolean = "Boolean";
        private const string JSONString = "String";



        private string m_algoLabel = "Translate Tree C#";

        private bool m_available;
        private bool m_overridable;
        private bool m_useRootNode;
        private bool m_useEndNode;

        private double m_paramX;
        private double m_paramY;

        private ISchematicDiagramClassName m_schematicDiagramClassName;

        public TranslateTree()
        {
            m_paramX = 50.0;
            m_paramY = 50.0;
            m_available = true;// In this example, the algorithm is available by default
            m_overridable = true; // user is allowed to edit the parameters
            m_useRootNode = false; // don't need the user to define root nodes
            m_useEndNode = false; // don't need the user to define an end node

            m_schematicDiagramClassName = null;

        }

        ~TranslateTree()
        {
            m_schematicDiagramClassName = null;
        }


        #region Component Category Registration

        [ComRegisterFunction()]
        public static void Reg(string regKey)
        {
            SchematicAlgorithms.Register(regKey);
        }

        [ComUnregisterFunction()]
        public static void Unreg(string regKey)
        {
            SchematicAlgorithms.Unregister(regKey);
        }
        #endregion


        #region Implements ITranslateTree
        public double TranslationFactorX
        {
            get
            {
                return m_paramX;
            }
            set
            {
                m_paramX = value;
            }
        }

        public double TranslationFactorY
        {
            get
            {
                return m_paramY;
            }
            set
            {
                m_paramY = value;
            }
        }
        #endregion
        ///////////////////////////////////////////////////////////////////////////////////////
        //
        // ISchematicAlgorithm interface : Defines its properties and methods (mandatory)
        //
        #region Implements ISchematicAlgorithm


        public bool get_Enabled(ISchematicLayer schematicLayer)
        {
            if (schematicLayer == null)
                return false;

            // an algorithm needs the diagram to be in editing mode in order to run
            if (!schematicLayer.IsEditingSchematicDiagram())
                return false;

            IEnumSchematicFeature enumFeatures = schematicLayer.GetSchematicSelectedFeatures(true);
            if (enumFeatures == null)
                return false;

            // Count the selected nodes
            int iCount = 0;
            ISchematicFeature feature;
            enumFeatures.Reset();
            feature = enumFeatures.Next();
            while (feature != null && iCount < 2)
            {
                ISchematicInMemoryFeatureClass inMemoryFeatureClass;

                // just want SchematicFeatureNode
                inMemoryFeatureClass = (ISchematicInMemoryFeatureClass)feature.Class;

                if (inMemoryFeatureClass.SchematicElementClass.SchematicElementType == esriSchematicElementType.esriSchematicNodeType)
                    iCount++;
                feature = enumFeatures.Next();
            }

            if (iCount == 1)
                return true; // just want one selected node
            else
                return false;
        }

        public bool Available
        {
            get
            {
                return m_available;
            }
            set
            {
                m_available = value;
            }
        }

        public bool Overridable
        {
            get
            {
                return m_overridable;
            }
            set
            {
                m_overridable = value;
            }
        }

        public ISchematicDiagramClassName SchematicDiagramClassName
        {
            get
            {
                return m_schematicDiagramClassName;
            }
            set
            {
                m_schematicDiagramClassName = value;
            }
        }

        public string Label
        {
            get
            {
                return m_algoLabel;
            }
            set
            {
                m_algoLabel = value;
            }
        }

        public bool UseRootNode
        {
            get
            {
                return m_useRootNode;
            }
        }

        public bool UseEndNode
        {
            get
            {
                return m_useEndNode;
            }
        }

        public IPropertySet PropertySet
        {
            get
            {
                // build the property set
                IPropertySet propSet = new PropertySet();
                if (propSet == null)
                    return null;

                propSet.SetProperty(TranslationFactorXName, m_paramX);
                propSet.SetProperty(TranslationFactorYName, m_paramY);

                return propSet;
            }
            set
            {
                IPropertySet pPropertySet = value;

                if (pPropertySet != null)
                {
                    try
                    {
                        m_paramX = (double)pPropertySet.GetProperty(TranslationFactorXName);
                        m_paramY = (double)pPropertySet.GetProperty(TranslationFactorYName);
                    }
                    catch { }
                }
            }
        }

        public string AlgorithmCLSID
        {
            get
            {
                //return "{" + GUID + "}"; Working as well with GUID
                return PROGID;
            }
        }

        // The execute part of the algorithm
        public void Execute(ISchematicLayer schematicLayer, ITrackCancel CancelTracker)
        {
            if (schematicLayer == null)
                return;

            // Before Execute part
            ISchematicInMemoryDiagram inMemoryDiagram;
            inMemoryDiagram = schematicLayer.SchematicInMemoryDiagram;

            // Core algorithm
            InternalExecute(schematicLayer, inMemoryDiagram, CancelTracker);

            // Release the COM objects
            if (inMemoryDiagram != null)
                while (System.Runtime.InteropServices.Marshal.ReleaseComObject(inMemoryDiagram) > 0) { }

            while (System.Runtime.InteropServices.Marshal.ReleaseComObject(schematicLayer) > 0) { }
        }



        // The execute part of the algorithm
        private void InternalExecute(ISchematicLayer schematicLayer, ISchematicInMemoryDiagram inMemoryDiagram, ITrackCancel CancelTracker)
        {
            if (schematicLayer == null || inMemoryDiagram == null)
                return;

            // get the diagram spatial reference for geometry transformation
            IGeoDataset geoDataset = (IGeoDataset)inMemoryDiagram;
            if (geoDataset == null)
                return;

            ISpatialReference spatialReference = geoDataset.SpatialReference;

            ISchematicDiagramClass diagramClass;
            diagramClass = inMemoryDiagram.SchematicDiagramClass;
            if (diagramClass == null)
                return;

            ISchematicDataset schemDataset;
            schemDataset = diagramClass.SchematicDataset;
            if (schemDataset == null)
                return;

            ISchematicAlgorithmEventsTrigger algorithmEventsTrigger;
            algorithmEventsTrigger = (ISchematicAlgorithmEventsTrigger)schemDataset;
            if (algorithmEventsTrigger == null)
                return;

            ESRI.ArcGIS.Carto.ILayer layer = (ESRI.ArcGIS.Carto.ILayer)schematicLayer;
            ISchematicAlgorithm algorithm = (ISchematicAlgorithm)this;

            bool canExecute = true;
            algorithmEventsTrigger.FireBeforeExecuteAlgorithm(layer, algorithm, ref canExecute);
            if (!canExecute)
                return; // cannot execute

            // Get the selected Features
            IEnumSchematicFeature enumFeatures = schematicLayer.GetSchematicSelectedFeatures(true);
            if (enumFeatures == null)
                return;

            // Count the selected nodes
            ISchematicInMemoryFeatureClass inMemoryFeatureClass;
            ISchematicFeature selectedFeature = null;
            int iCount = 0;
            ISchematicFeature schemFeature;
            enumFeatures.Reset();
            schemFeature = enumFeatures.Next();
            while (schemFeature != null && iCount < 2)
            {
                // just want SchematicFeatureNode
                inMemoryFeatureClass = (ISchematicInMemoryFeatureClass)schemFeature.Class;

                if (inMemoryFeatureClass.SchematicElementClass.SchematicElementType == esriSchematicElementType.esriSchematicNodeType)
                {
                    selectedFeature = schemFeature;
                    iCount++;
                }
                schemFeature = enumFeatures.Next();
            }

            if (iCount != 1 || selectedFeature == null)
                return; // must be only one

            // Create a new SchematicAnalystFindConnected algorithm
            ISchematicAnalystFindConnected analystFindConnected = null;

            analystFindConnected = (ISchematicAnalystFindConnected)new SchematicAnalystFindConnected();
            if (analystFindConnected == null)
                return;

            // Modifying parameters value for this SchematicAnalystFindConnected algorithm so that when it is launched the trace result appears a selection set{
            analystFindConnected.SelectLink = true;
            analystFindConnected.SelectNode = true;
            analystFindConnected.UseFlow = false;
            //pAnalystFindConnected.FlowDirection = 1;
            // Execute the algorithm
            analystFindConnected.Execute(schematicLayer, CancelTracker);

            // Retrieving the trace result (if any)
            IEnumSchematicFeature resultFeatures;
            resultFeatures = analystFindConnected.TraceResult;

            // free the schematic analyst COM object
            while (System.Runtime.InteropServices.Marshal.ReleaseComObject(analystFindConnected) > 0) { }

            if (resultFeatures == null || resultFeatures.Count < 1)
                return;

            // Apply the translation to the result
            //ISchematicInMemoryDiagram inMemoryDiagram;
            //inMemoryDiagram = schematicLayer.SchematicInMemoryDiagram;

            // Translating each traced elements according to the TranslationFactorX and TranslationFactorY parameters current values
            ISchematicInMemoryFeature inMemoryFeature;
            resultFeatures.Reset();
            while ((inMemoryFeature = (ISchematicInMemoryFeature)resultFeatures.Next()) != null)
            {
                IGeometry geometry;
                ITransform2D transform;
                esriSchematicElementType elemType;

                inMemoryFeatureClass = (ISchematicInMemoryFeatureClass)inMemoryFeature.Class;
                elemType = inMemoryFeatureClass.SchematicElementClass.SchematicElementType;
                if (elemType == esriSchematicElementType.esriSchematicLinkType || elemType == esriSchematicElementType.esriSchematicNodeType)
                {
                    // get a copy of the feature geometry
                    // then process the cloned geometry rather than the feature geometry directly
                    // Thus the modifications are stored in the heap of the current operation
                    // meaning it can be undone then redo (undo/redo)
                    geometry = inMemoryFeature.ShapeCopy;
                    // Convert the geometry into the SpatialReference of diagram class
                    geometry.Project(spatialReference);
                    // Move the geometry
                    transform = (ITransform2D)geometry;
                    if (transform != null)
                    {
                        transform.Move(m_paramX, m_paramY);

                        // Convert the moved geometry into the spatial reference of storage
                        // and feed it back to the feature
                        IObjectClass table = inMemoryFeature.Class;
                        if (table == null)
                            continue;

                        IGeoDataset featureGeoDataset = (IGeoDataset)table;
                        if (featureGeoDataset == null)
                            continue;

                        ISpatialReference featureSpatialRef = featureGeoDataset.SpatialReference;
                        if (featureSpatialRef == null)
                            continue;

                        IGeometry movedGeometry = (IGeometry)transform;
                        movedGeometry.Project(featureSpatialRef);


                        inMemoryFeature.Shape = movedGeometry;
                    }
                }
            }

            // After Execute part
            algorithmEventsTrigger.FireAfterExecuteAlgorithm(layer, algorithm);

            // update the diagram extent
            schematicLayer.UpdateExtent();
        }

         
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////
        //
        // ISchematicJSONParameters interface : Defines its properties and methods (mandatory to run on server)
        //
        #region Implements ISchematicJSONParameters 

        public IJSONArray JSONParametersArray
        {
            get
            {

                JSONArray aJSONArray = new JSONArray();

                // build JSON object for the first parameter
                IJSONObject oJSONObject1 = new JSONObject();

                oJSONObject1.AddString(JSONName, JSONTranslationFactorX);
                oJSONObject1.AddString(JSONType, JSONDouble);
                oJSONObject1.AddDouble(JSONValue, m_paramX);

                aJSONArray.AddJSONObject(oJSONObject1);

                // build JSON object for the second parameter
                IJSONObject oJSONObject2 = new JSONObject();

                oJSONObject2.AddString(JSONName, JSONTranslationFactorY);
                oJSONObject2.AddString(JSONType, JSONDouble);
                oJSONObject2.AddDouble(JSONValue, m_paramY);

                aJSONArray.AddJSONObject(oJSONObject2);

                // encode JSON array as a string
                return aJSONArray; // null propertyset 

            }
        }


        public IJSONObject JSONParametersObject
        {
            set
            {
                IJSONObject oJSONObject = value;

                double paramX;
                double paramY;
                if (oJSONObject != null)
                {
                    // decode input parameters
                    if (oJSONObject.TryGetValueAsDouble(JSONTranslationFactorX, out paramX))
                        m_paramX = paramX; // otherwise use current value

                    if (oJSONObject.TryGetValueAsDouble(JSONTranslationFactorY, out paramY))
                        m_paramY = paramY; // otherwise use current value
                }
                
            }
        }
        #endregion
    }
}

[Visual Basic .NET]

TranslateTree.vb

Imports System
Imports System.Collections.Generic
Imports System.Text
Imports System.Runtime.InteropServices
Imports ESRI.ArcGIS.esriSystem
Imports ESRI.ArcGIS.ADF.CATIDs
Imports ESRI.ArcGIS.Schematic
Imports ESRI.ArcGIS.Geodatabase
Imports ESRI.ArcGIS.Geometry

<ClassInterface(ClassInterfaceType.None)> _
<Guid(TranslateTree.GUID)> _
<ProgId(TranslateTree.PROGID)> _
Public Class TranslateTree

    Implements ISchematicAlgorithm
    Implements ISchematicJSONParameters
    Implements ITranslateTree


    ' private member data
    Public Const GUID As String = "F80339F6-9E87-4a75-AF8E-1B44C76D7D96"
    Public Const PROGID As String = "ApplicativeAlgorithms.TranslateTreeVB"

    ' property names (for the algorithm property set)
    Private Const TranslationFactorXName As String = "Translation Factor X"
    Private Const TranslationFactorYName As String = "Translation Factor Y"


    ' The JSON parameter names 
    Private Const JSONTranslationFactorX As String = "TranslationFactorX"
    Private Const JSONTranslationFactorY As String = "TranslationFactorY"

    'Algorithms parameters JSON representation Names used by the REST interface 
    Private Const JSONName As String = "name"
    Private Const JSONType As String = "type"
    Private Const JSONValue As String = "value"
    'Algorithms parameters JSON representation Types used by the REST interface
    Private Const JSONLong As String = "Long"
    Private Const JSONDouble As String = "Double"
    Private Const JSONBoolean As String = "Boolean"
    Private Const JSONString As String = "String"

    Private m_algoLabel As String = "Translate Tree VBNet"

    Private m_available As Boolean
    Private m_overridable As Boolean
    Private m_useRootNode As Boolean
    Private m_useEndNode As Boolean

    Private m_paramX As Double
    Private m_paramY As Double

    Private m_schematicDiagramClassName As ISchematicDiagramClassName

    Public Sub New()

        m_paramX = 50.0
        m_paramY = 50.0
        m_available = True    ' In this example, the algorithm is available by default
        m_overridable = True   ' user is allowed to edit the parameters
        m_useRootNode = False ' don't need the user to define root nodes
        m_useEndNode = False   ' don't need the user to define an end node

        m_schematicDiagramClassName = Nothing
    End Sub

    Protected Overrides Sub Finalize()
        m_schematicDiagramClassName = Nothing
    End Sub


#Region "COM Registration Function(s)"
    <ComRegisterFunction()> _
    <ComVisibleAttribute(True)> _
    Public Shared Sub Reg(ByVal sKey As String)
        SchematicAlgorithms.Register(sKey)
    End Sub

    <ComUnregisterFunction()> _
    <ComVisibleAttribute(True)> _
    Public Shared Sub Unreg(ByVal sKey As String)
        SchematicAlgorithms.Unregister(sKey)
    End Sub
#End Region

#Region "Implements ITranslateTree"
    Public Property TranslationFactorX() As Double Implements ITranslateTree.TranslationFactorX
        Get
            Return m_paramX
        End Get
        Set(ByVal value As Double)
            m_paramX = value
        End Set
    End Property

    Public Property TranslationFactorY() As Double Implements ITranslateTree.TranslationFactorY
        Get
            Return m_paramY
        End Get
        Set(ByVal value As Double)
            m_paramY = value
        End Set
    End Property
#End Region

#Region "Implements ISchematicAlgorithm"

    Public ReadOnly Property Enabled(Optional ByVal schematicLayer As ESRI.ArcGIS.Schematic.ISchematicLayer = Nothing) As Boolean Implements ESRI.ArcGIS.Schematic.ISchematicAlgorithm.Enabled
        Get

            Dim enumFeatures As IEnumSchematicFeature
            Dim schemFeature As ISchematicFeature

            Dim iCount As Integer = 0

            If (schematicLayer Is Nothing) Then Return False

            ' an algorithm needs the diagram to be in editing mode in order to run
            If (Not schematicLayer.IsEditingSchematicDiagram()) Then Return False

            enumFeatures = schematicLayer.GetSchematicSelectedFeatures(True)
            If (enumFeatures Is Nothing) Then Return False

            ' Count the selected nodes
            enumFeatures.Reset()
            schemFeature = enumFeatures.Next()
            While (schemFeature IsNot Nothing And iCount < 2)

                Dim inMemoryFeatureClass As ISchematicInMemoryFeatureClass = Nothing
                inMemoryFeatureClass = TryCast(schemFeature.Class, ISchematicInMemoryFeatureClass)

                If (inMemoryFeatureClass Is Nothing) Then
                    schemFeature = enumFeatures.Next()
                    Continue While
                End If

                If (inMemoryFeatureClass.SchematicElementClass.SchematicElementType = esriSchematicElementType.esriSchematicNodeType) Then
                    iCount += 1
                End If
                schemFeature = enumFeatures.Next()
            End While

            If (iCount = 1) Then
                Return True     'just want one selected node
            Else
                Return False
            End If
        End Get
    End Property


    Public Property Available() As Boolean Implements ISchematicAlgorithm.Available
        Get
            Return m_available
        End Get
        Set(ByVal value As Boolean)
            m_available = value
        End Set
    End Property

    ' enclose the name of the property by brackets since the word is reserved (in VBNet)
    Public Property [Overridable]() As Boolean Implements ISchematicAlgorithm.Overridable
        Get
            Return m_overridable
        End Get
        Set(ByVal value As Boolean)
            m_overridable = value
        End Set
    End Property

    Public Property SchematicDiagramClassName() As ISchematicDiagramClassName Implements ISchematicAlgorithm.SchematicDiagramClassName
        Get
            Return m_schematicDiagramClassName
        End Get
        Set(ByVal value As ISchematicDiagramClassName)
            m_schematicDiagramClassName = value
        End Set
    End Property

    Public Property Label() As String Implements ISchematicAlgorithm.Label
        Get
            Return m_algoLabel
        End Get
        Set(ByVal value As String)
            m_algoLabel = value
        End Set
    End Property

    Public ReadOnly Property UseRootNode() As Boolean Implements ISchematicAlgorithm.UseRootNode
        Get
            Return m_useRootNode
        End Get
    End Property

    Public ReadOnly Property UseEndNode() As Boolean Implements ISchematicAlgorithm.UseEndNode
        Get
            Return m_useEndNode
        End Get
    End Property

    Public Property PropertySet() As IPropertySet Implements ISchematicAlgorithm.PropertySet
        Get
            ' build the property set
            Dim builtPropertySet As New ESRI.ArcGIS.esriSystem.PropertySet

            If (builtPropertySet Is Nothing) Then
                Return Nothing
            End If

            builtPropertySet.SetProperty(TranslationFactorXName, m_paramX)
            builtPropertySet.SetProperty(TranslationFactorYName, m_paramY)

            Return builtPropertySet
        End Get

        Set(ByVal value As IPropertySet)
            Dim propSet As IPropertySet = value
            Dim oneParameter As Object

            If (propSet IsNot Nothing) Then
                Try
                    oneParameter = propSet.GetProperty(TranslationFactorXName)
                    m_paramX = CDbl(oneParameter)

                    oneParameter = propSet.GetProperty(TranslationFactorYName)
                    m_paramY = CDbl(oneParameter)
                Catch ex As Exception
                End Try
            End If

        End Set
    End Property


    Public ReadOnly Property AlgorithmCLSID() As String Implements ISchematicAlgorithm.AlgorithmCLSID
        Get
            Return "{" & GUID & "}"
        End Get
    End Property

    Public Sub Execute(Optional ByVal schematicLayer As ESRI.ArcGIS.Schematic.ISchematicLayer = Nothing, Optional ByVal cancelTracker As ESRI.ArcGIS.esriSystem.ITrackCancel = Nothing) Implements ESRI.ArcGIS.Schematic.ISchematicAlgorithm.Execute

        If (schematicLayer Is Nothing) Then Return

        Dim inMemoryDiagram As ISchematicInMemoryDiagram
        inMemoryDiagram = schematicLayer.SchematicInMemoryDiagram

        ' Core algorithm
        InternalExecute(schematicLayer, inMemoryDiagram, cancelTracker)

        ' Release the COM objects
        If (inMemoryDiagram IsNot Nothing) Then
            While (System.Runtime.InteropServices.Marshal.ReleaseComObject(inMemoryDiagram) > 0)
            End While
        End If

        While (System.Runtime.InteropServices.Marshal.ReleaseComObject(schematicLayer) > 0)
        End While

    End Sub

 

    Private Sub InternalExecute(ByVal schematicLayer As ESRI.ArcGIS.Schematic.ISchematicLayer,
                                ByVal inMemoryDiagram As ESRI.ArcGIS.Schematic.ISchematicInMemoryDiagram,
                                Optional ByVal cancelTracker As ESRI.ArcGIS.esriSystem.ITrackCancel = Nothing)

        If (schematicLayer Is Nothing Or inMemoryDiagram Is Nothing) Then Return

        '''''''''''''''''''''''''''''''''''''''''''

        ' get the diagram spatial reference for geometry transformation
        Dim geoDataset As IGeoDataset = CType(inMemoryDiagram, IGeoDataset)
        If (geoDataset Is Nothing) Then Return
        Dim spatialReference As ISpatialReference = geoDataset.SpatialReference

        Dim diagramClass As ISchematicDiagramClass
        diagramClass = inMemoryDiagram.SchematicDiagramClass
        If (diagramClass Is Nothing) Then Return

        Dim schemDataset As ISchematicDataset
        schemDataset = diagramClass.SchematicDataset
        If (schemDataset Is Nothing) Then Return

        Dim algorithmEventsTrigger As ISchematicAlgorithmEventsTrigger
        algorithmEventsTrigger = CType(schemDataset, ISchematicAlgorithmEventsTrigger)
        If (algorithmEventsTrigger Is Nothing) Then Return

        Dim layer As ESRI.ArcGIS.Carto.ILayer = CType(schematicLayer, ESRI.ArcGIS.Carto.ILayer)
        Dim algorithm As ISchematicAlgorithm = CType(Me, ISchematicAlgorithm)
        Dim canExecute As Boolean

        algorithmEventsTrigger.FireBeforeExecuteAlgorithm(layer, algorithm, canExecute)
        If Not canExecute Then Return ' cannot execute

        ' Get the selected Features
        Dim enumFeatures As IEnumSchematicFeature = schematicLayer.GetSchematicSelectedFeatures(True)
        If (enumFeatures Is Nothing) Then Return

        ' Count the selected nodes
        Dim inMemoryFeatureClass As ISchematicInMemoryFeatureClass
        Dim selectedFeature As ISchematicFeature = Nothing
        Dim iCount As Integer = 0
        Dim schemFeature As ISchematicFeature
        enumFeatures.Reset()
        schemFeature = enumFeatures.Next()
        While (schemFeature IsNot Nothing AndAlso iCount < 2)
            ' just want SchematicFeatureNode
            inMemoryFeatureClass = CType(schemFeature.Class, ISchematicInMemoryFeatureClass)

            If (inMemoryFeatureClass.SchematicElementClass.SchematicElementType = esriSchematicElementType.esriSchematicNodeType) Then
                selectedFeature = schemFeature
                iCount += 1
            End If
            schemFeature = enumFeatures.Next()
        End While

        If (iCount <> 1 OrElse selectedFeature Is Nothing) Then Return ' must be only one

        ' Create a new SchematicAnalystFindConnected algorithm
        Dim analystFindConnected As ISchematicAnalystFindConnected = Nothing

        analystFindConnected = CType(New SchematicAnalystFindConnected(), ISchematicAnalystFindConnected)
        If (analystFindConnected Is Nothing) Then Return

        ' Modifying parameters value for this SchematicAnalystFindConnected algorithm so that when it is launched the trace result appears   a selection set{
        analystFindConnected.SelectLink = True
        analystFindConnected.SelectNode = True
        analystFindConnected.UseFlow = False
        'pAnalystFindConnected.FlowDirection = 1
        ' Execute the algorithm
        analystFindConnected.Execute(schematicLayer, cancelTracker)

        ' Retrieving the trace result (if any)
        Dim resultFeatures As IEnumSchematicFeature
        resultFeatures = analystFindConnected.TraceResult

        ' free the schematic analyst COM object
        While (System.Runtime.InteropServices.Marshal.ReleaseComObject(analystFindConnected) > 0)
        End While

        If (resultFeatures Is Nothing OrElse resultFeatures.Count < 1) Then Return

        ' Apply the translation to the result
        ' Translating each traced elements according to the TranslationFactorX and TranslationFactorY parameters current values
        Dim inMemoryFeature As ISchematicInMemoryFeature
        resultFeatures.Reset()
        inMemoryFeature = CType(resultFeatures.Next(), ISchematicInMemoryFeature)
        While (inMemoryFeature IsNot Nothing)
            Dim geometry As IGeometry
            Dim transform As ITransform2D
            Dim elemType As esriSchematicElementType

            inMemoryFeatureClass = CType(inMemoryFeature.Class, ISchematicInMemoryFeatureClass)
            elemType = inMemoryFeatureClass.SchematicElementClass.SchematicElementType
            If (elemType = esriSchematicElementType.esriSchematicLinkType OrElse elemType = esriSchematicElementType.esriSchematicNodeType) Then
                ' get a copy of the feature geometry
                ' then process the cloned geometry rather than the feature geometry directly
                ' Thus the modifications are stored in the heap of the current operation
                ' meaning it can be undone then redo (undo/redo)
                geometry = inMemoryFeature.ShapeCopy
                ' Convert the geometry into the SpatialReference of diagram class
                geometry.Project(spatialReference)
                ' Move the geometry
                transform = CType(geometry, ITransform2D)
                If (transform IsNot Nothing) Then
                    transform.Move(m_paramX, m_paramY)

                    ' Convert the moved geometry into the spatial reference of storage
                    ' and feed it back to the feature
                    Dim table As IObjectClass = inMemoryFeature.Class
                    If (table Is Nothing) Then Continue While

                    Dim featureGeoDataset As IGeoDataset = CType(table, IGeoDataset)
                    If (featureGeoDataset Is Nothing) Then Continue While

                    Dim featureSpatialRef As ISpatialReference = featureGeoDataset.SpatialReference
                    If (featureSpatialRef Is Nothing) Then Continue While

                    Dim movedGeometry As IGeometry = CType(transform, IGeometry)
                    movedGeometry.Project(featureSpatialRef)

                    inMemoryFeature.Shape = movedGeometry
                End If
            End If
            inMemoryFeature = CType(resultFeatures.Next(), ISchematicInMemoryFeature)
        End While

        ' After Execute part
        algorithmEventsTrigger.FireAfterExecuteAlgorithm(layer, algorithm)

        ' update the diagram extent
        schematicLayer.UpdateExtent()

    End Sub


#End Region


#Region "Implements ISchematicJSONParameters"

    ' ISchematicJSONParameters interface : Defines its properties and methods (mandatory to run on server)
    Public ReadOnly Property JSONParametersArray1() As IJSONArray Implements ISchematicJSONParameters.JSONParametersArray
        Get

            Dim aJSONArray As New JSONArray
            Dim oJSONObject1 As IJSONObject = New JSONObject
            Dim oJSONObject2 As IJSONObject = New JSONObject

            ' build JSON object for the first parameter
            oJSONObject1.AddString(JSONName, JSONTranslationFactorX)
            oJSONObject1.AddString(JSONType, JSONDouble)
            oJSONObject1.AddDouble(JSONValue, m_paramX)

            aJSONArray.AddJSONObject(oJSONObject1)

            'build JSON object for the second parameter
            oJSONObject2.AddString(JSONName, JSONTranslationFactorY)
            oJSONObject2.AddString(JSONType, JSONDouble)
            oJSONObject2.AddDouble(JSONValue, m_paramY)

            aJSONArray.AddJSONObject(oJSONObject2)

            Return aJSONArray
        End Get
    End Property

    Public WriteOnly Property JSONParametersObject1() As IJSONObject Implements ISchematicJSONParameters.JSONParametersObject
        Set(ByVal value As IJSONObject)

            Dim oJSONObject As IJSONObject = value
            Dim paramX As Double
            Dim paramY As Double

            If (oJSONObject IsNot Nothing) Then            'decode input JSONparameters
                If (oJSONObject.TryGetValueAsDouble(JSONTranslationFactorX, paramX)) Then
                    m_paramX = paramX
                End If 'otherwise use current value

                If (oJSONObject.TryGetValueAsDouble(JSONTranslationFactorX, paramY)) Then
                    m_paramY = paramY
                End If 'otherwise use current value
            End If
        End Set
    End Property

#End Region

End Class

'End Namespace