Imports EgtUILib
Imports EgtWPFLib5
Imports EgtBEAMWALL.Core

Public Class FreeContourManagerVM
   Inherits VMBase

#Region "FIELDS & PROPERTIES"

   Public Enum FreeContourTypes As Integer
      ONE = 0
      ONEWITHANGLES = 1
      TWO = 2
   End Enum
   Public Enum Paths As Integer
      FIRST = 0
      SECOND = 1
   End Enum

   Private m_bPrevShowSolid As Boolean

   ' variabile che indica se il percorso deve essere chiuso
   Private m_bClosedPathNeeded As Boolean = False

   ' variabile che indica se il progetto era modificato prima di modificare il percorso
   Private m_bAlreadyModified As Boolean = False

   ' variabile che gestisce l'apertura della composita
   Private m_bIsOpeningCurveCompo As Boolean
   Public ReadOnly Property bIsOpeningCurveCompo As Boolean
      Get
         Return m_bIsOpeningCurveCompo
      End Get
   End Property

   Private m_bIsActive As Boolean = False
   Public ReadOnly Property bIsActive As Boolean
      Get
         Return m_bIsActive
      End Get
   End Property

   Private m_nSelTextId As Integer = GDB_ID.NULL
   ' parametro che indica se e' in corso l'editing di un angolo
   Private m_bIsModifyingTextAngle As Boolean = False
   Public ReadOnly Property bIsModifyingTextAngle As Boolean
      Get
         Return m_bIsModifyingTextAngle
      End Get
   End Property
   ' parametro che indica se e' in corso il disegno di un percorso
   Private m_bIsCreatingPath As Boolean = False
   Public ReadOnly Property bIsCreatingPath As Boolean
      Get
         Return m_bIsCreatingPath
      End Get
   End Property

   Private m_TypeList As New List(Of String)({EgtMsg(62001), EgtMsg(62002), EgtMsg(62003)})
   Public Property TypeList As List(Of String)
      Get
         Return m_TypeList
      End Get
      Set(value As List(Of String))
         m_TypeList = value
      End Set
   End Property

   Private m_SelType As Integer
   Public Property SelType As Integer
      Get
         Return m_SelType
      End Get
      Set(value As Integer)
         ' se precedentemente impostato 2 percorsi
         Select Case m_SelType
            Case FreeContourTypes.ONEWITHANGLES
               ' elimino layer testi angoli e layer copia
               EgtErase(nSideAngTextLayer)
               EgtErase(m_nNewPathCopyForSideAngleId)
               nSideAngTextLayer = GDB_ID.NULL
               m_TextAngle_Visibility = Visibility.Collapsed
               NotifyPropertyChanged(NameOf(TextAngle_Visibility))
            Case FreeContourTypes.TWO
               ' chiedo conferma
               If MessageBox.Show(EgtMsg(61862), "", MessageBoxButton.YesNo, MessageBoxImage.Warning) <> MessageBoxResult.Yes Then
                  m_SelType = FreeContourTypes.TWO
                  NotifyPropertyChanged(NameOf(SelType))
                  Return
               Else
                  ' elimino secondo percorso
                  EgtErase(m_nNewSecondPathId)
                  m_PathList_Visibility = Visibility.Collapsed
                  NotifyPropertyChanged(NameOf(PathList_Visibility))
               End If
         End Select
         m_SelType = value
         ' se nuova impostazione e' uno con angoli
         Select Case m_SelType
            Case FreeContourTypes.ONEWITHANGLES
               ' creo testi angoli sul percorso
               CreateSideAngText("")
               m_TextAngle_Visibility = Visibility.Visible
            Case FreeContourTypes.TWO
               m_PathList_Visibility = Visibility.Visible
               NotifyPropertyChanged(NameOf(PathList_Visibility))
               SelPath = Paths.FIRST
               NotifyPropertyChanged(NameOf(SelPath))
         End Select
         NotifyPropertyChanged(NameOf(TextAngle_Visibility))
         EgtDraw()
      End Set
   End Property

   Private m_PathList As New List(Of String)({EgtMsg(62004), EgtMsg(62005)})
   Public Property PathList As List(Of String)
      Get
         Return m_PathList
      End Get
      Set(value As List(Of String))
         m_PathList = value
      End Set
   End Property

   Private m_SelPath As Paths
   Public Property SelPath As Integer
      Get
         Return m_SelPath
      End Get
      Set(value As Integer)
         m_SelPath = value
         Select Case m_SelPath
            Case Paths.FIRST
               EgtDeselectAll()
               EgtResetMark(m_nNewSecondPathId)
               If m_nNewPathId = GDB_ID.NULL OrElse EgtGetType(m_nNewPathId) = GDB_TY.NONE Then
                  m_Line2P_IsEnabled = True
                  NotifyPropertyChanged(NameOf(Line2P_IsEnabled))
               Else
                  EgtSetMark(m_nNewPathId)
                  If m_Line2P_IsEnabled Then
                     m_Line2P_IsEnabled = False
                     NotifyPropertyChanged(NameOf(Line2P_IsEnabled))
                  End If
               End If
            Case Paths.SECOND
               EgtDeselectAll()
               EgtResetMark(m_nNewPathId)
               If m_nNewSecondPathId = GDB_ID.NULL OrElse EgtGetType(m_nNewSecondPathId) = GDB_TY.NONE Then
                  m_Line2P_IsEnabled = True
                  NotifyPropertyChanged(NameOf(Line2P_IsEnabled))
               Else
                  EgtSetMark(m_nNewSecondPathId)
                  If m_Line2P_IsEnabled Then
                     m_Line2P_IsEnabled = False
                     NotifyPropertyChanged(NameOf(Line2P_IsEnabled))
                  End If
               End If
         End Select
         EgtDraw()
      End Set
   End Property

   Private m_Line2P_IsEnabled As Boolean = False
   Public Property Line2P_IsEnabled As Boolean
      Get
         Return m_Line2P_IsEnabled
      End Get
      Set(value As Boolean)
         m_Line2P_IsEnabled = value
      End Set
   End Property

   Private m_TextAngle_Visibility As Visibility = Visibility.Collapsed
   Public Property TextAngle_Visibility As Visibility
      Get
         Return m_TextAngle_Visibility
      End Get
      Set(value As Visibility)
         m_TextAngle_Visibility = value
      End Set
   End Property

   Private m_PathList_Visibility As Visibility = Visibility.Collapsed
   Public Property PathList_Visibility As Visibility
      Get
         Return m_PathList_Visibility
      End Get
      Set(value As Visibility)
         m_PathList_Visibility = value
      End Set
   End Property

#Region "Messages"

   Public ReadOnly Property Line2P_ToolTip As String
      Get
         Return EgtMsg(62006)
      End Get
   End Property
   Public ReadOnly Property Delete_ToolTip As String
      Get
         Return EgtMsg(5223)
      End Get
   End Property
   Public ReadOnly Property ArcFlip_ToolTip As String
      Get
         Return EgtMsg(5159)
      End Get
   End Property
   Public ReadOnly Property ModifyCurve_ToolTip As String
      Get
         Return EgtMsg(5160)
      End Get
   End Property
   Public ReadOnly Property AddPointCurve_ToolTip As String
      Get
         Return EgtMsg(5161)
      End Get
   End Property
   Public ReadOnly Property RemovePointCurve_ToolTip As String
      Get
         Return EgtMsg(5162)
      End Get
   End Property
   Public ReadOnly Property ChangeStart_ToolTip As String
      Get
         Return EgtMsg(5229)
      End Get
   End Property
   Public ReadOnly Property InvertCurve_ToolTip As String
      Get
         Return EgtMsg(5228)
      End Get
   End Property
   Public ReadOnly Property Move_ToolTip As String
      Get
         Return EgtMsg(5236)
      End Get
   End Property
   Public ReadOnly Property Rotate_ToolTip As String
      Get
         Return EgtMsg(5237)
      End Get
   End Property
   Public ReadOnly Property TextAngle_ToolTip As String
      Get
         Return EgtMsg(5249)
      End Get
   End Property

#End Region    ' Messages

   Friend SelPart As BTLPartVM
   Friend SelFeature As BTLFeatureVM
   Friend nSelPartId As Integer
   Friend nSelFeatureId As Integer
   Friend nProcessingLayerId As Integer
   Friend nAuxId As Integer = 0
   Friend nSecondAuxId As Integer = 0
   Friend nOrigPathId As Integer = GDB_ID.NULL
   Friend m_nNewPathId As Integer = GDB_ID.NULL
   Friend m_nNewPathCopyForSideAngleId As Integer = GDB_ID.NULL
   Friend nOrigSecondPathId As Integer = GDB_ID.NULL
   Friend m_nNewSecondPathId As Integer = GDB_ID.NULL
   Friend nSideAngTextLayer As Integer = GDB_ID.NULL
   Friend SideAngValues As New List(Of SideAngle)

   ' Definizione comandi
   Private m_cmdLine2P As ICommand
   Private m_cmdDelete As ICommand
   Private m_cmdModifyCurve As ICommand
   Private m_cmdAddPointCurve As ICommand
   Private m_cmdRemovePointCurve As ICommand
   Private m_cmdArcflip As ICommand
   Private m_cmdMove As ICommand
   Private m_cmdRotate As ICommand
   Private m_cmdMirror As ICommand
   Private m_cmdScale As ICommand
   Private m_cmdChangeStart As ICommand
   Private m_cmdInvertCurve As ICommand
   Private m_cmdTextAngle As ICommand

#End Region    ' FIELDS & PROPERTIES

#Region "CONSTRUCTORS"

   Sub New()
      ' imposto riferimento in Map
      Map.SetRefFreeContourManagerVM(Me)
   End Sub

#End Region    ' CONSTRUCTORS

#Region "METHODS"

   Friend Sub Open()
      m_bIsActive = True
      m_bAlreadyModified = EgtGetModified()
      ' blocco funzionalita' interfaccia
      Map.refProjectVM.ManageIsEnabled(False)
      Map.refPartListVM.SetBTLPartListIsEnabled(False)
      Map.refFeatureListVM.SetBTLFeatureListIsEnabled(False)
      Map.refPParameterListVM.SetPParameterListIsEnabled(False)
      Map.refQParameterListVM.SetQParameterListIsEnabled(False)
      Map.refShowBeamPanelVM.SetShowSolid_IsEnabled(False)
      Map.refShowBeamPanelVM.SetShowAll_IsEnabled(False)
      'resetto tutte le variabili
      SelPart = Nothing
      SelFeature = Nothing
      nSelPartId = GDB_ID.NULL
      nSelFeatureId = GDB_ID.NULL
      nProcessingLayerId = GDB_ID.NULL
      nAuxId = 0
      nSecondAuxId = 0
      nOrigPathId = GDB_ID.NULL
      m_nNewPathId = GDB_ID.NULL
      m_nNewPathCopyForSideAngleId = GDB_ID.NULL
      nOrigSecondPathId = GDB_ID.NULL
      m_nNewSecondPathId = GDB_ID.NULL
      nSideAngTextLayer = GDB_ID.NULL
      SideAngValues.Clear()
      ' nascondo PartManager
      Map.refProjectVM.NotifyPropertyChanged(NameOf(Map.refProjectVM.PartManager_Visibility))
      ' verifico se solido attivo
      m_bPrevShowSolid = Map.refShowBeamPanelVM.ShowSolid_IsChecked
      If m_bPrevShowSolid Then Map.refProjectVM.BTLStructureVM.ShowSolid(GDB_ID.NULL, False, False)
      ' attivo visualizzazione direzione curve
      EgtSetShowCurveDirection(True)
      ' elimino eventuale vecchio layer testi
      EgtErase(nSideAngTextLayer)
      nSideAngTextLayer = GDB_ID.NULL
      ' imposto Part/Feature/Layer Processing ...
      SelPart = Map.refProjectVM.BTLStructureVM.SelBTLPart
      SelFeature = Map.refProjectVM.BTLStructureVM.SelBTLPart.SelBTLFeatureVM
      nSelPartId = Map.refProjectVM.BTLStructureVM.SelBTLPart.nPartId
      nSelFeatureId = Map.refProjectVM.BTLStructureVM.SelBTLPart.SelBTLFeatureVM.nFeatureId
      nProcessingLayerId = EgtGetFirstNameInGroup(nSelPartId, PROCESSINGS)
      Dim sAuxId As String = ""
      If EgtGetInfo(nSelFeatureId, "AUXID", sAuxId) Then
         ' verifico se ha uno o due percorsi
         Dim sAuxIdSplit() As String = sAuxId.Split(","c)
         If Integer.TryParse(sAuxIdSplit(0), nAuxId) Then
            nOrigPathId = nSelFeatureId + nAuxId
            ' faccio copia del percorso feature
            m_nNewPathId = EgtCopyGlob(nOrigPathId, nSelFeatureId, GDB_POS.AFTER)
            EgtModifyCurveThickness(m_nNewPathId, 0)
            ' verifico se c'e' info angoli
            Dim sSideAng As String = ""
            If EgtGetInfo(nOrigPathId, "SideAngs", sSideAng) Then
               ' creo testi angoli sul percorso
               CreateSideAngText(sSideAng)
               ' imposto modalita' con angoli
               m_SelType = FreeContourTypes.ONEWITHANGLES
            Else
               ' imposto modalita' un percorso
               m_SelType = FreeContourTypes.ONE
            End If
         End If
         If sAuxIdSplit.Count > 1 AndAlso Not String.IsNullOrWhiteSpace(sAuxIdSplit(1)) Then
            If Integer.TryParse(sAuxIdSplit(1), nSecondAuxId) Then
               nOrigSecondPathId = nSelFeatureId + nSecondAuxId
               ' faccio copia del percorso feature
               m_nNewSecondPathId = EgtCopyGlob(nOrigSecondPathId, nSelFeatureId, GDB_POS.AFTER)
               EgtModifyCurveThickness(m_nNewSecondPathId, 0)
               ' imposto modalita' due percorsi
               m_SelType = FreeContourTypes.TWO
            End If
         End If
      ' se nuova senza percorsi
      Else
         ' imposto modalita' un percorso
         m_SelType = FreeContourTypes.ONE
      End If
      NotifyPropertyChanged(NameOf(SelType))
      ' verifico se deve essere contorno chiuso
      m_bClosedPathNeeded = SelFeature.nPRC <> 250
      ' imposto filtro selezione solo su curve
      Map.refSceneHostVM.MainScene.SetObjFilterForSel(False, True, False, False, False)
      ' imposto layer corrente per disegno
      EgtSetCurrPartLayer(nSelPartId, nProcessingLayerId)
      ' nascondo tutte le feature
      Dim nTempFeatureId As Integer = EgtGetFirstInGroup(nProcessingLayerId)
      While nTempFeatureId <> GDB_ID.NULL
         EgtSetMode(nTempFeatureId, GDB_MD.HIDDEN)
         nTempFeatureId = EgtGetNext(nTempFeatureId)
      End While
      ' nascondo tutti gli outline
      Dim nOutlineLayerId As Integer = EgtGetFirstNameInGroup(nSelPartId, OUTLINE)
      Dim nTempOutlineId As Integer = EgtGetFirstInGroup(nOutlineLayerId)
      While nTempOutlineId <> GDB_ID.NULL
         EgtSetMode(nTempOutlineId, GDB_MD.HIDDEN)
         nTempOutlineId = EgtGetNext(nTempOutlineId)
      End While
      ' deseleziono tutto
      EgtDeselectAll()
      ' rendo visibile solo percorso feature
      EgtSetMode(m_nNewPathId, GDB_MD.STD)
      If m_SelType = FreeContourTypes.TWO Then
         EgtSetMode(m_nNewSecondPathId, GDB_MD.STD)
      End If
      ' verifico se modalita' uno o due percorsi
      Select Case m_SelType
         Case FreeContourTypes.ONE
            ' se c'e' gia' un percorso disattivo la possibilita' di aggiungerne
            m_Line2P_IsEnabled = (m_nNewPathId = GDB_ID.NULL)
            m_TextAngle_Visibility = Visibility.Collapsed
            m_PathList_Visibility = Visibility.Collapsed
         Case FreeContourTypes.ONEWITHANGLES
            ' se c'e' gia' un percorso disattivo la possibilita' di aggiungerne
            m_Line2P_IsEnabled = (m_nNewPathId = GDB_ID.NULL)
            m_TextAngle_Visibility = Visibility.Visible
            m_PathList_Visibility = Visibility.Collapsed
         Case FreeContourTypes.TWO
            ' se ci sono gia' due percorsi 
            ' disattivo la possibilita' di aggiungerne
            m_Line2P_IsEnabled = (m_nNewPathId = GDB_ID.NULL OrElse m_nNewSecondPathId = GDB_ID.NULL)
            m_TextAngle_Visibility = Visibility.Collapsed
            m_PathList_Visibility = Visibility.Visible
            ' seleziono primo percorso
            SelPath = Paths.FIRST
            NotifyPropertyChanged(NameOf(SelPath))
      End Select
      NotifyPropertyChanged(NameOf(Line2P_IsEnabled))
      NotifyPropertyChanged(NameOf(TextAngle_Visibility))
      NotifyPropertyChanged(NameOf(PathList_Visibility))
      ' posiziono la griglia sul riferimento del contorno libero
      Dim frFace As New Frame3d
      EgtBeamGetSideData(SelFeature.nSelSIDE, frFace)
      Dim frFrame As New Frame3d(SelFeature.BTLFeatureM.frFRAME)
      frFrame.ToGlob( frFace)
      EgtSetGridFrame(frFrame)
      EgtSetGridShow(True, True)
      Map.refSceneHostVM.MainScene.CPlaneView()
      ' rimetto la selezione scena a null
      Map.refSceneHostVM.MainScene.SetStatusNull()
      ' attivo bottoni save e cancel
      SelFeature.RefreshFCMBtnVisibility()
      ' nascondo Part Manager
      Map.refProjectVM.NotifyPropertyChanged(NameOf(Map.refProjectVM.PartManager_Visibility))
      ' attivo pannello
      Map.refProjectVM.SetFreeContourManager_Visibility(True)
      EgtDraw()
   End Sub

   Friend Sub Close(bSave As Boolean)
      If not m_bIsActive Then Return
      m_bIsActive = False
      ' gestisco modifiche ai percorsi
      If bSave Then
         Select Case m_SelType
            Case FreeContourManagerVM.FreeContourTypes.ONE
               EgtRemoveInfo(m_nNewPathId, "SideAngs")
               ' ricalcolo auxid
               EgtSetInfo(nSelFeatureId, "AUXID", (m_nNewPathId - nSelFeatureId).ToString("+#;-#;0"))
            Case FreeContourManagerVM.FreeContourTypes.ONEWITHANGLES
               SideAngValues = SideAngValues.OrderBy(Function(x) x.nIndex).ToList()
               Dim sSideAngInfo As String = ""
               For Index = 0 To SideAngValues.Count - 1
                  If Index > 0 Then sSideAngInfo &= ","
                  Dim sAng As String = DoubleToString(SideAngValues(Index).dValue, 2)
                  sSideAngInfo &= sAng
               Next
               EgtSetInfo(m_nNewPathId, "SideAngs", sSideAngInfo)
               EgtSetInfo(nSelFeatureId, "AUXID", (m_nNewPathId - nSelFeatureId).ToString("+#;-#;0"))
            Case FreeContourManagerVM.FreeContourTypes.TWO
               ' ricalcolo auxid
               EgtSetInfo(nSelFeatureId, "AUXID", (m_nNewPathId - nSelFeatureId).ToString("+#;-#;0") & "," & (m_nNewSecondPathId - nSelFeatureId).ToString("+#;-#;0"))
         End Select
         ' aggiorno la feature con nuovo valore
         Dim vPar() As Double = Nothing
         Dim sPar As String = String.Empty
         Dim vParQ() As String = Nothing
         Dim BTLFeatureM As BTLFeatureM = SelFeature.BTLFeatureM
         BTLFeatureM.CalcParamArray(vPar, sPar, vParQ)
         Dim bOK As Boolean = BTLFeatureM.UpdateParams(BTLFeatureM.nSelGRP, BTLFeatureM.nPRC, BTLFeatureM.nSelSIDE, BTLFeatureM.sDES, BTLFeatureM.nPRID,
                                                       BTLFeatureM.frFRAME, vPar, sPar, vParQ)
         If bOK Then
            SelFeature.SelGeomFeature()
            ' rendo non calcolata questa feature
            SelFeature.ResetCalcFeature()
            SelPart.CalcGlobalUpdate(True)
            ' cancello vecchi percorsi
            EgtErase(nOrigPathId)
            If nOrigSecondPathId <> GDB_ID.NULL Then
               EgtErase(nOrigSecondPathId)
            End If
         End If
      Else
         ' elimino nuovo percorso
         EgtErase(m_nNewPathId)
         If m_nNewSecondPathId <> GDB_ID.NULL Then
            EgtErase(m_nNewSecondPathId)
         End If
      End If
      ' se con angoli elimino percorso copia
      If SelType = FreeContourTypes.ONEWITHANGLES Then
         EgtErase(m_nNewPathCopyForSideAngleId)
      End If
      ' se non e' a due percorsi ma e' rimasto il secondo originale, lo cancello
      If SelType <> FreeContourTypes.TWO AndAlso nOrigSecondPathId <> GDB_ID.NULL Then
         EgtErase(nOrigSecondPathId)
      End If
      ' mostro tutte le altre feature
      Dim nTempFeatureId As Integer = EgtGetFirstInGroup(nProcessingLayerId)
      While nTempFeatureId <> GDB_ID.NULL
         'If nTempFeatureId <> nSelFeatureId Then
         EgtSetMode(nTempFeatureId, GDB_MD.STD)
         'End If
         nTempFeatureId = EgtGetNext(nTempFeatureId)
      End While
      ' mostro outline
      Dim nOutlineLayerId As Integer = EgtGetFirstNameInGroup(nSelPartId, OUTLINE)
      Dim nTempOutlineId As Integer = EgtGetFirstInGroup(nOutlineLayerId)
      While nTempOutlineId <> GDB_ID.NULL
         EgtSetMode(nTempOutlineId, GDB_MD.STD)
         nTempOutlineId = EgtGetNext(nTempOutlineId)
      End While
      ' elimino eventuale layer dei testi angoli
      EgtErase(nSideAngTextLayer)
      nSideAngTextLayer = GDB_ID.NULL
      ' riporto griglia globale e la nascondo
      EgtSetGridFrame( New Frame3d())
      EgtSetGridShow(False, False)
      ' se il progetto non era modificato ed esco senza salvare, resetto lo stato di modificato
      If Not m_bAlreadyModified And Not bSave Then
         EgtResetModified()
      End If
      ' disattivo pannello
      Map.refProjectVM.SetFreeContourManager_Visibility(False)
      ' attivo bottone edit
      SelFeature.RefreshFCMBtnVisibility()
      ' resetto tutte le variabili correnti
      SelPart = Nothing
      SelFeature = Nothing
      nSelPartId = GDB_ID.NULL
      nSelFeatureId = GDB_ID.NULL
      nProcessingLayerId = GDB_ID.NULL
      ' riattivo Part Manager
      Map.refProjectVM.NotifyPropertyChanged(NameOf(Map.refProjectVM.PartManager_Visibility))
      ' disattivo modifiche su scena
      Map.refSceneHostVM.MainScene.SetStatusNull()
      If m_bPrevShowSolid Then Map.refProjectVM.BTLStructureVM.ShowSolid(GDB_ID.NULL, True, False)
      ' disattivo visualizzazione direzione curve
      EgtSetShowCurveDirection(False)
      ' reimposto filtro selezione
      Map.refSceneHostVM.MainScene.SetObjFilterForSel(True, True, True, True, True)
      ' sblocco funzionalita' interfaccia
      Map.refProjectVM.ManageIsEnabled(True)
      Map.refPartListVM.SetBTLPartListIsEnabled(True)
      Map.refFeatureListVM.SetBTLFeatureListIsEnabled(True)
      Map.refPParameterListVM.SetPParameterListIsEnabled(True)
      Map.refQParameterListVM.SetQParameterListIsEnabled(True)
      Map.refShowBeamPanelVM.SetShowSolid_IsEnabled(True)
      Map.refShowBeamPanelVM.SetShowAll_IsEnabled(True)
      ' reimposto vista normale per pezzo
      Core.ViewPanelVM.BWSetView(If(Core.ViewPanelVM.Type = BWType.BEAM, VT.ISO_SW, VT.TOP), False)
      EgtZoom(ZM.ALL)
      ' rimetto PartManager
      Map.refProjectVM.NotifyPropertyChanged(NameOf(Map.refProjectVM.PartManager_Visibility))
   End Sub

   ' funzione lanciata su fine creazione percorso
   Friend Sub CreatingPathEnd()
      m_bIsCreatingPath = False
      'Dim nNewPathId As Integer = EgtGetLastInGroup(nProcessingLayerId)
      Dim nNewPathLayerId As Integer = EgtGetFirstNameInGroup(nSelPartId, "NewPathLayer")
      Dim nNewPathId As Integer = EgtGetFirstInGroup(nNewPathLayerId)
      If nNewPathId <> GDB_ID.NULL Then
         ' lo sposto nel layer delle feature
         EgtRelocateGlob(nNewPathId, nSelFeatureId, GDB_POS.AFTER)
         ' se deve essere chiuso
         If m_bClosedPathNeeded AndAlso Not EgtCurveIsClosed(nNewPathId) Then
            EgtCloseCurveCompo(nNewPathId)
         End If
         Select Case SelType
            Case FreeContourTypes.TWO
               Select Case m_SelPath
                  Case Paths.FIRST
                     m_nNewPathId = nNewPathId
                  Case Paths.SECOND
                     m_nNewSecondPathId = nNewPathId
               End Select
            Case FreeContourTypes.ONEWITHANGLES
               m_nNewPathId = nNewPathId
               CreateSideAngText("")
            Case Else
               m_nNewPathId = nNewPathId
         End Select
         m_Line2P_IsEnabled = False
         NotifyPropertyChanged(NameOf(Line2P_IsEnabled))
      End If
      EgtErase(nNewPathLayerId)
      EgtSetCurrPartLayer(nSelPartId, nProcessingLayerId)
   End Sub

   Friend Sub UpdateUi()
      ' se attiva operazione in piu' passaggi, esco
      If Map.refSceneHostVM.MainController.GetContinue() Then Return
      ' se finita creazione curva (è stata chiusa)
      If Map.refFreeContourManagerVM.bIsCreatingPath Then
         Dim nNewPathLayerId As Integer = EgtGetFirstNameInGroup(nSelPartId, "NewPathLayer")
         Dim nNewPathId As Integer = EgtGetFirstInGroup(nNewPathLayerId)
         If EgtGetType(nNewPathId) = GDB_TY.CRV_COMPO Then Map.refFreeContourManagerVM.CreatingPathEnd()
      End If
      ' se non ci sono piu' i percorsi, permetto di aggiungerli
      If EgtGetType(m_nNewPathId) = GDB_TY.NONE Then
         m_nNewPathId = GDB_ID.NULL
         m_Line2P_IsEnabled = True
         NotifyPropertyChanged(NameOf(Line2P_IsEnabled))
         If m_SelType = FreeContourTypes.ONEWITHANGLES Then
            EgtErase(m_nNewPathCopyForSideAngleId)
            m_nNewPathCopyForSideAngleId = GDB_ID.NULL
            EgtErase(nSideAngTextLayer)
            nSideAngTextLayer = GDB_ID.NULL
         End If
      End If
      If m_SelType = FreeContourTypes.TWO AndAlso m_SelPath = Paths.SECOND AndAlso EgtGetType(m_nNewSecondPathId) = GDB_TY.NONE Then
         m_nNewSecondPathId = GDB_ID.NULL
         m_Line2P_IsEnabled = True
         NotifyPropertyChanged(NameOf(Line2P_IsEnabled))
      End If
      ' se modalita' angoli
      If m_SelType = FreeContourTypes.ONEWITHANGLES And m_nNewPathId <> GDB_ID.NULL Then
         UpdateSideAngText()
      End If
      ' rimetto la selezione scena a null
      EgtDeselectAll()
      Map.refSceneHostVM.MainScene.SetStatusNull()
      EgtDraw()
   End Sub

   Private Sub CreateSideAngText(SideAng As String)
      SideAngValues.Clear()
      ' faccio copia per modifiche future
      m_nNewPathCopyForSideAngleId = EgtCopyGlob(m_nNewPathId, nSelFeatureId, GDB_POS.AFTER)
      ' creo testi angoli sul percorso
      If nSideAngTextLayer = GDB_ID.NULL Then
         nSideAngTextLayer = EgtCreateGroup(nSelPartId)
         EgtSetName(nSideAngTextLayer, PATH_SIDEANGLAYER)
      End If
      Dim sSideAngSplit() As String = SideAng.Split(","c)
      Dim nSideFirst As Integer
      Dim nSideLast As Integer
      EgtCurveDomain(m_nNewPathId, nSideFirst, nSideLast)
      Dim nSideCnt As Integer = nSideLast - nSideFirst
      For Index = 0 To nSideCnt - 1
         ' riporto angoli nel disegno
         Dim ptText As Point3d
         EgtAtParamPoint(m_nNewPathId, Index + 0.5, ptText)
         Dim dSideAng As Double = 0
         If sSideAngSplit.Count - 1 >= Index Then
            StringToDoubleAdv(sSideAngSplit(Index), dSideAng, True)
         End If
         Dim sSideAng As String = DoubleToString( dSideAng, 2) & "°"
         Dim TextId As Integer = EgtCreateText(nSideAngTextLayer, ptText, sSideAng, 20)
         EgtSetInfo(TextId, "SideAng", dSideAng)
         SideAngValues.Add(New SideAngle(TextId, Index, dSideAng))
      Next
   End Sub

   Private Sub UpdateSideAngText()
      Dim bNewIsClosed As Boolean = EgtCurveIsClosed(m_nNewPathId)
      Dim bOldIsClosed As Boolean = EgtCurveIsClosed(m_nNewPathCopyForSideAngleId)
      Dim NewSideAngValues As New List(Of SideAngle)
      Dim nSideFirst As Integer
      Dim nSideLast As Integer
      EgtCurveDomain(m_nNewPathId, nSideFirst, nSideLast)
      Dim nSideCnt As Integer = nSideLast - nSideFirst
      'If SideAngValues.Count() <> nSideCnt Then
      Dim NewAngleList As New List(Of Point3d)
      Dim OldAngleList As New List(Of Point3d)
      ' leggo punti nuovi
      For Index = 0 To nSideCnt '+ If(bIsClosed, -1, 0)
         Dim ptNew As Point3d
         EgtAtParamPoint(m_nNewPathId, Index, ptNew)
         NewAngleList.Add(ptNew)
      Next
      ' leggo punti vecchi
      For Index = 0 To SideAngValues.Count() '+ If(bIsClosed, -1, 0)
         Dim ptOld As Point3d
         EgtAtParamPoint(m_nNewPathCopyForSideAngleId, Index, ptOld)
         OldAngleList.Add(ptOld)
      Next
      ' confronto
      Dim nNewIndex As Integer = 0
      Dim nOldIndex As Integer = 0
      Dim nPointsQty As Integer = Math.Max(SideAngValues.Count(), nSideCnt) '+ If(bIsClosed, -1, 0)
      ' figura rigida
      Dim bRotTrans As Boolean = True
      If NewAngleList.Count = OldAngleList.Count Then
         For RTIndex = 1 To NewAngleList.Count - 1
            ' verifico distanza del punto dal precedente
            Dim NewDist As Double = Point3d.Dist(NewAngleList(RTIndex), NewAngleList(RTIndex - 1))
            Dim OldDist As Double = Point3d.Dist(OldAngleList(RTIndex), OldAngleList(RTIndex - 1))
            If Math.Abs(NewDist - OldDist) > EPS_SMALL Then
               bRotTrans = False
               Exit For
            End If
            ' verifico distanza del punto da quello iniziale
            Dim NewDist0 As Double = Point3d.Dist(NewAngleList(RTIndex), NewAngleList(0))
            Dim OldDist0 As Double = Point3d.Dist(OldAngleList(RTIndex), OldAngleList(0))
            If Math.Abs(NewDist0 - OldDist0) > EPS_SMALL Then
               bRotTrans = False
               Exit For
            End If
         Next
      End If
      ' ciclo sui punti
      For Index = 0 To nPointsQty
         Dim CurrIndex As Integer = Index
         '' percorso chiuso
         ' cambiato punto inizio
         Dim bChangedStart As Boolean = False
         Dim nMovedIndex As Integer = -1
         If Not bRotTrans AndAlso bNewIsClosed OrElse bOldIsClosed Then
            If Index < NewAngleList.Count Then
               ' calcolo nuovo indice del punto
               nMovedIndex = OldAngleList.FindIndex(Function(x) AreSamePointApprox(x, NewAngleList(CurrIndex)))
               ' verifico se coincidono anche punti successivi o precedenti
               If nMovedIndex <> -1 AndAlso nMovedIndex <> Index AndAlso ((Index + 1 < NewAngleList.Count AndAlso nMovedIndex + 1 < OldAngleList.Count AndAlso AreSamePointApprox(NewAngleList(Index + 1), OldAngleList(nMovedIndex + 1))) OrElse
                                                                          (Index - 1 >= 0 AndAlso nMovedIndex - 1 >= 0 AndAlso AreSamePointApprox(NewAngleList(Index - 1), OldAngleList(nMovedIndex - 1))) OrElse
                                                                          (Index - 1 >= 0 AndAlso nMovedIndex = 0 AndAlso AreSamePointApprox(NewAngleList(Index - 1), OldAngleList(OldAngleList.Count - 2)))) Then
                  bChangedStart = True
                  ' aggiorno lista sideang che deve essere riordinata
                  If Index < nPointsQty Then
                     Dim nOffset As Integer = If(nMovedIndex < Index, nPointsQty + nMovedIndex, nMovedIndex) - Index
                     Dim NewIndex As Integer = (Index + nOffset) Mod nPointsQty
                     NewSideAngValues.Add(New SideAngle(SideAngValues(NewIndex).nId, NewSideAngValues.Count, SideAngValues(NewIndex).dValue))
                  End If

               End If
            End If
         End If
         If bRotTrans Then
            ' aggiorno posizione testo successivo
            Dim ptOld As Point3d
            Dim ptNew As Point3d
            Dim vtDistance As Vector3d
            If Index < nPointsQty Then
               EgtAtParamPoint(m_nNewPathCopyForSideAngleId, Index + 0.5, ptOld)
               EgtAtParamPoint(m_nNewPathId, Index + 0.5, ptNew)
               vtDistance = ptNew - ptOld
               EgtMove(SideAngValues(Index).nId, vtDistance)
               NewSideAngValues.Add(New SideAngle(SideAngValues(Index).nId, NewSideAngValues.Count, SideAngValues(Index).dValue))
            End If
         ElseIf bChangedStart Then
            ' non faccio nulla perche' gestito sopra
         ' se apro percorso
         ElseIf Not bNewIsClosed AndAlso bOldIsClosed AndAlso Index = NewAngleList.Count Then
            ' cancello il testo del lato rimosso
            nMovedIndex = OldAngleList.FindIndex(Function(x) AreSamePointApprox(x, NewAngleList(CurrIndex - 1)))
            Dim nOffset As Integer = If(nMovedIndex < Index, nPointsQty + nMovedIndex, nMovedIndex) - Index
            Dim NewIndex As Integer = (nPointsQty + nOffset) Mod nPointsQty
            EgtErase(SideAngValues(nOffset).nId)
            NewSideAngValues.RemoveAt(NewSideAngValues.Count - 1)
         ' se chiudo percorso
         ElseIf bNewIsClosed AndAlso Not bOldIsClosed AndAlso Index = OldAngleList.Count Then
            ' creo il testo del lato aggiunto
            Dim ptText As Point3d
            EgtAtParamPoint(m_nNewPathId, Index - 0.5, ptText)
            Dim TextId As Integer = EgtCreateText(nSideAngTextLayer, ptText, "0°", 20)
            ' aggiungo punto e incremento indice di confronto per riallineare successivo
            NewSideAngValues.Add(New SideAngle(TextId, NewSideAngValues.Count - 1, 0))
            '' percorso aperto
         ' punti coincidono: verifico che i punti coincidano e non siano il centro del percorso simmetrico
         ElseIf Not bNewIsClosed AndAlso nNewIndex <= NewAngleList.Count - 1 AndAlso nOldIndex <= OldAngleList.Count - 1 AndAlso AreSamePointApprox(NewAngleList(nNewIndex), OldAngleList(nOldIndex)) AndAlso
                Not (Index = nPointsQty / 2 AndAlso AreSamePointApprox(NewAngleList(Index - 1), OldAngleList(nPointsQty - Index + 1))) Then
            If Index < nPointsQty AndAlso nOldIndex <= SideAngValues.Count - 1 Then
               NewSideAngValues.Add(New SideAngle(SideAngValues(nOldIndex).nId, NewSideAngValues.Count, SideAngValues(nOldIndex).dValue))
            End If
         ' punti simmetrici: verifico se sono simmetrici o se coincidono ma i precedenti sono simmetrici
         ElseIf Not bNewIsClosed AndAlso Not bOldIsClosed AndAlso NewAngleList.Count = OldAngleList.Count AndAlso (AreSamePointApprox(NewAngleList(Index), OldAngleList(nPointsQty - Index)) OrElse
                (AreSamePointApprox(NewAngleList(nNewIndex), OldAngleList(nOldIndex)) AndAlso AreSamePointApprox(NewAngleList(Index - 1), OldAngleList(nPointsQty - Index + 1)))) Then
            If Index < nPointsQty Then
               Dim sText As String = DoubleToString( SideAngValues(nPointsQty - 1 - Index).dValue, 2)
               EgtModifyText(SideAngValues(Index).nId, sText)
               NewSideAngValues.Add(New SideAngle(SideAngValues(nPointsQty - 1 - Index).nId, NewSideAngValues.Count, SideAngValues(nPointsQty - 1 - Index).dValue))
            End If
         ' punto spostato: verifico che non coincidano ma che i precedenti o i successivi coincidano
         ElseIf Not bNewIsClosed AndAlso
                ((Index = nPointsQty AndAlso Index <= OldAngleList.Count - 1 AndAlso Not AreSamePointApprox(NewAngleList(Index), OldAngleList(Index)) AndAlso AreSamePointApprox(NewAngleList(Index - 1), OldAngleList(Index - 1))) OrElse
                 (nOldIndex + 1 <= OldAngleList.Count - 1 AndAlso nNewIndex + 1 <= NewAngleList.Count - 1 AndAlso AreSamePointApprox(NewAngleList(nNewIndex + 1), OldAngleList(nOldIndex + 1)))) Then
            ' aggiorno posizione testo precedente
            Dim ptOld As Point3d
            Dim ptNew As Point3d
            Dim vtDistance As Vector3d
            If Index > 0 Then
               EgtAtParamPoint(m_nNewPathCopyForSideAngleId, Index - 0.5, ptOld)
               EgtAtParamPoint(m_nNewPathId, Index - 0.5, ptNew)
               vtDistance = ptNew - ptOld
               EgtMove(SideAngValues(Index - 1).nId, vtDistance)
            End If
            If Index < nPointsQty Then
               ' aggiorno posizione testo successivo
               EgtAtParamPoint(m_nNewPathCopyForSideAngleId, Index + 0.5, ptOld)
               EgtAtParamPoint(m_nNewPathId, Index + 0.5, ptNew)
               vtDistance = ptNew - ptOld
               EgtMove(SideAngValues(Index).nId, vtDistance)
               NewSideAngValues.Add(New SideAngle(SideAngValues(Index).nId, NewSideAngValues.Count, SideAngValues(Index).dValue))
            End If
            '' percorso chiuso
         ' punti coincidono:  verifico che i punti coincidano e non siano inizio, fine o centro del percorso simmetrico
         ElseIf bNewIsClosed AndAlso nNewIndex <= NewAngleList.Count - 1 AndAlso nOldIndex <= OldAngleList.Count - 1 AndAlso AreSamePointApprox(NewAngleList(nNewIndex), OldAngleList(nOldIndex)) AndAlso
                Not ((Index = 0 AndAlso AreSamePointApprox(NewAngleList(Index + 1), OldAngleList(nPointsQty - 1))) OrElse
                     ((Index = nPointsQty / 2 OrElse Index = nPointsQty) AndAlso AreSamePointApprox(NewAngleList(Index - 1), OldAngleList(nPointsQty - Index + 1)))) Then
            If Index < nPointsQty AndAlso nOldIndex < SideAngValues.Count Then
               NewSideAngValues.Add(New SideAngle(SideAngValues(nOldIndex).nId, NewSideAngValues.Count, SideAngValues(nOldIndex).dValue))
            End If
         ' punti simmetrici: verifico se sono simmetrici o se coincidono ma i precedenti sono simmetrici
         ElseIf bNewIsClosed AndAlso bOldIsClosed AndAlso (AreSamePointApprox(NewAngleList(Index), OldAngleList(nPointsQty - Index)) OrElse
                (AreSamePointApprox(NewAngleList(nNewIndex), OldAngleList(nOldIndex)) AndAlso AreSamePointApprox(NewAngleList(Index - 1), OldAngleList(nPointsQty - Index + 1)))) Then
            If Index < nPointsQty Then
               NewSideAngValues.Add(New SideAngle(SideAngValues(nPointsQty - 1 - Index).nId, NewSideAngValues.Count, SideAngValues(nPointsQty - 1 - Index).dValue))
            End If
         ' punto spostato: verifico che non coincidano ma che i precedenti o i successivi coincidano
         ElseIf (nOldIndex + 1 <= OldAngleList.Count - 1 AndAlso nNewIndex + 1 <= NewAngleList.Count - 1 AndAlso AreSamePointApprox(NewAngleList(nNewIndex + 1), OldAngleList(nOldIndex + 1))) OrElse
                (bNewIsClosed AndAlso nOldIndex + 1 = OldAngleList.Count AndAlso nNewIndex + 1 = NewAngleList.Count AndAlso AreSamePointApprox(NewAngleList(1), OldAngleList(1))) Then
            ' aggiorno posizione testo precedente
            Dim ptOld As Point3d
            Dim ptNew As Point3d
            Dim vtDistance As Vector3d
            If Index > 0 Then
               EgtAtParamPoint(m_nNewPathCopyForSideAngleId, Index - 0.5, ptOld)
               EgtAtParamPoint(m_nNewPathId, Index - 0.5, ptNew)
               vtDistance = ptNew - ptOld
               EgtMove(SideAngValues(Index - 1).nId, vtDistance)
            End If
            If Index < nPointsQty Then
               ' aggiorno posizione testo successivo
               EgtAtParamPoint(m_nNewPathCopyForSideAngleId, Index + 0.5, ptOld)
               EgtAtParamPoint(m_nNewPathId, Index + 0.5, ptNew)
               vtDistance = ptNew - ptOld
               EgtMove(SideAngValues(nOldIndex).nId, vtDistance)
               NewSideAngValues.Add(New SideAngle(SideAngValues(nOldIndex).nId, NewSideAngValues.Count, SideAngValues(nOldIndex).dValue))
            End If
         ' punto aggiunto: Verifico che il punto successivo coincida con il vecchio corrente o che sia stato aggiunto in fondo
         ElseIf (nNewIndex + 1 <= NewAngleList.Count - 1 AndAlso AreSamePointApprox(NewAngleList(nNewIndex + 1), OldAngleList(nOldIndex))) OrElse
                (nOldIndex = OldAngleList.Count AndAlso OldAngleList.Count < NewAngleList.Count) Then
            ' se non e' percorso aperto e primo punto
            If bNewIsClosed OrElse (Index > 0 AndAlso Index <= SideAngValues.Count) Then
               ' aggiorno posizione testo vecchio
               Dim ptOld As Point3d
               EgtAtParamPoint(m_nNewPathCopyForSideAngleId, Index - 0.5, ptOld)
               Dim ptNew As Point3d
               EgtAtParamPoint(m_nNewPathId, Index - 0.5, ptNew)
               Dim vtDistance As Vector3d = ptNew - ptOld
               EgtMove(SideAngValues(Index - 1).nId, vtDistance)
            End If
            ' aggiungo testo nuovo
            Dim TextIndex As Integer = If(bNewIsClosed OrElse Index <= SideAngValues.Count, Index, Index - 1)
            'If bIsClosed OrElse Index <= SideAngValues.Count - 1 Then
            Dim ptText As Point3d
            EgtAtParamPoint(m_nNewPathId, TextIndex + 0.5, ptText)
            Dim TextId As Integer = EgtCreateText(nSideAngTextLayer, ptText, "0°", 20)
            ' aggiungo punto e incremento indice di confronto per riallineare successivo
            NewSideAngValues.Insert(TextIndex, New SideAngle(TextId, TextIndex, 0))
            nOldIndex -= 1
         ' punto tolto: verifico che il punto coincida con il vecchio successivo o che sia stato tolto in fondo
         ElseIf (nOldIndex + 1 <= OldAngleList.Count - 1 AndAlso AreSamePointApprox(NewAngleList(nNewIndex), OldAngleList(nOldIndex + 1))) OrElse
             (nNewIndex = NewAngleList.Count AndAlso OldAngleList.Count > NewAngleList.Count) Then
            ' non aggiungo nulla, ma cancello testo
            EgtErase(SideAngValues(Index).nId)
            nNewIndex -= 1
            ' riposiziono testo del punto precedente
            Dim ptOld As Point3d
            EgtAtParamPoint(m_nNewPathCopyForSideAngleId, If(Index = 0, OldAngleList.Count, Index) - 0.5, ptOld)
            Dim ptNew As Point3d
            EgtAtParamPoint(m_nNewPathId, If(Index = 0, NewAngleList.Count, Index) - 0.5, ptNew)
            Dim vtDistance As Vector3d = ptNew - ptOld
            EgtMove(SideAngValues(If(Index = 0, OldAngleList.Count, Index) - 1).nId, vtDistance)
         ' spostato o ruotato intero percorso
         Else
            ' aggiorno posizione testo successivo
            Dim ptOld As Point3d
            Dim ptNew As Point3d
            Dim vtDistance As Vector3d
            If Index < nPointsQty Then
               EgtAtParamPoint(m_nNewPathCopyForSideAngleId, Index + 0.5, ptOld)
               EgtAtParamPoint(m_nNewPathId, Index + 0.5, ptNew)
               vtDistance = ptNew - ptOld
               EgtMove(SideAngValues(Index).nId, vtDistance)
               NewSideAngValues.Add(New SideAngle(SideAngValues(Index).nId, NewSideAngValues.Count, SideAngValues(Index).dValue))
            End If
         End If
         nNewIndex += 1
         nOldIndex += 1
      Next
      ' cancello vecchia copia e faccio copia nuovo percorso per modifiche future
      EgtErase(m_nNewPathCopyForSideAngleId)
      m_nNewPathCopyForSideAngleId = EgtCopyGlob(m_nNewPathId, nSelFeatureId, GDB_POS.AFTER)
      SideAngValues = NewSideAngValues
      EgtDraw()
      'End If
   End Sub

   Friend Sub CloseIsModifyingTextAngle(bResult As Boolean)
      If bResult Then
         ' scrivo info con nuova inclinazione
         Dim dAng As Double
         StringToDoubleAdv(Map.refFreeContourInputVM.Text, dAng, True)
         EgtSetInfo(m_nSelTextId, "SideAng", dAng)
         Dim sAng As String = DoubleToString( dAng, 2) & "°"
         EgtModifyText(m_nSelTextId, sAng)
         Dim SideAngValue As SideAngle = SideAngValues.First(Function(x) x.nId = m_nSelTextId)
         SideAngValue.dValue = dAng
      End If
      m_nSelTextId = GDB_ID.NULL
      Map.refSceneHostVM.MainScene.SetObjFilterForSel(False, True, False, False, False)
      Map.refFreeContourInputVM.ResetInputBox()
      ' rimetto la selezione scena a null
      EgtDeselectAll()
      EgtDraw()
      Map.refSceneHostVM.MainScene.SetStatusNull()
      m_bIsModifyingTextAngle = False
   End Sub

   Friend Sub CloseIsOpeningCurveCompo()
      Map.refSceneHostVM.MainScene.SetObjFilterForSel(False, True, False, False, False)
      Map.refFreeContourInputVM.ResetInputBox()
      ' rimetto la selezione scena a null
      EgtDeselectAll()
      EgtDraw()
      Map.refSceneHostVM.MainScene.SetStatusNull()
      m_bIsOpeningCurveCompo = False
   End Sub

   Friend Function OnMouseSelectingObj(nId As Integer) As Boolean
      ' se sto editando testo angoli
      If Map.refFreeContourManagerVM.bIsModifyingTextAngle Then
         ' verifico che il testo selezionato sia uno degli angoli
         Dim nLayerId As Integer = EgtGetParent(nId)
         Dim sLayerName As String = ""
         EgtGetName(nLayerId, sLayerName)
         Return sLayerName = PATH_SIDEANGLAYER
      ElseIf Map.refFreeContourManagerVM.bIsOpeningCurveCompo Then
         Return nId = m_nNewPathId
      Else
         Return False
      End If
   End Function

   Friend Sub OnMouseSelectedObj(nId As Integer, bLast As Boolean)
      ' se sto editando testo angoli
      If Map.refFreeContourManagerVM.bIsModifyingTextAngle Then
         m_nSelTextId = nId
         ' mostro campo da editare
         Map.refFreeContourInputVM.PrepareInputBox(EgtMsg(62007), EgtMsg(62008), "", False, False)
         Dim dSideAng As Double = 0
         EgtGetInfo(nId, "SideAng", dSideAng)
         Dim sSideAng As String = DoubleToString( dSideAng, 2)
         Map.refFreeContourInputVM.SetInputBoxText(sSideAng)
      ' se sto aprendo percorso chiuso
      ElseIf Map.refFreeContourManagerVM.bIsOpeningCurveCompo Then
         Map.refSceneHostVM.MainController.ExecuteCommand(Controller.CMD.OPENCOMPO)
         m_bIsOpeningCurveCompo = False
      End If
   End Sub

   Private Sub InitCommand(bSelPath As Boolean)
      ' attivo modifiche su scena
      Map.refSceneHostVM.MainScene.ResetStatus()
      ' seleziono percorso corrente
      EgtDeselectAll()
      If bSelPath Then EgtSelectObj(If(SelType = FreeContourTypes.TWO AndAlso m_SelPath = Paths.SECOND, m_nNewSecondPathId, m_nNewPathId))
   End Sub

#End Region    ' METHODS

#Region "COMMANDS"

#Region "Line2P"

   ''' <summary>
   ''' Returns a command that do Line2P.
   ''' </summary>
   Public ReadOnly Property Line2P_Command As ICommand
      Get
         If m_cmdLine2P Is Nothing Then
            m_cmdLine2P = New Command(AddressOf Line2P)
         End If
         Return m_cmdLine2P
      End Get
   End Property

   ''' <summary>
   ''' Execute the Line2P.  This method is invoked by the Line2PCommand.
   ''' </summary>
   Public Sub Line2P(ByVal param As Object)
      ' cancello eventuale gruppo precedente
      Dim nNewPathLayerId As Integer = EgtGetFirstNameInGroup(nSelPartId, "NewPathLayer")
      If nNewPathLayerId <> GDB_ID.NULL Then
         EgtEmptyGroup(nNewPathLayerId)
      Else
         nNewPathLayerId = EgtCreateGroup(nSelPartId)
      End If
      EgtSetName(nNewPathLayerId, "NewPathLayer")
      EgtSetCurrPartLayer(nSelPartId, nNewPathLayerId)
      InitCommand(False)
      Map.refSceneHostVM.MainController.SetContinue()
      If Map.refSceneHostVM.MainController.ExecuteCommand(Controller.CMD.LINE2P) Then
         m_bIsCreatingPath = True
      Else
         EgtErase(nNewPathLayerId)
      End If
   End Sub

#End Region ' Line2P

#Region "Delete"

   ''' <summary>
   ''' Returns a command that do Line2P.
   ''' </summary>
   Public ReadOnly Property Delete_Command As ICommand
      Get
         If m_cmdDelete Is Nothing Then
            m_cmdDelete = New Command(AddressOf Delete)
         End If
         Return m_cmdDelete
      End Get
   End Property

   ''' <summary>
   ''' Execute the Line2P.  This method is invoked by the Line2PCommand.
   ''' </summary>
   Public Sub Delete(ByVal param As Object)
      InitCommand(True)
      Map.refSceneHostVM.MainController.SetLastInteger(GDB_ID.SEL)
      Map.refSceneHostVM.MainController.ExecuteCommand(Controller.CMD.DELETE)
   End Sub

#End Region ' Line2P

#Region "ModifyCurve"

   ''' <summary>
   ''' Returns a command that do Linear Dimension.
   ''' </summary>
   Public ReadOnly Property ModifyCurve_Command As ICommand
      Get
         If m_cmdModifyCurve Is Nothing Then
            m_cmdModifyCurve = New Command(AddressOf ModifyCurve)
         End If
         Return m_cmdModifyCurve
      End Get
   End Property

   ''' <summary>
   ''' Execute the LinearDimension.  This method is invoked by the LinDimCommand.
   ''' </summary>
   Public Sub ModifyCurve(ByVal param As Object)
      InitCommand(True)
      Map.refSceneHostVM.MainController.ExecuteCommand(Controller.CMD.MODIFYCURVE)
   End Sub

#End Region ' ModifyCurve

#Region "AddPointCurve"

   ''' <summary>
   ''' Returns a command that do Linear Dimension.
   ''' </summary>
   Public ReadOnly Property AddPointCurve_Command As ICommand
      Get
         If m_cmdAddPointCurve Is Nothing Then
            m_cmdAddPointCurve = New Command(AddressOf AddPointCurve)
         End If
         Return m_cmdAddPointCurve
      End Get
   End Property

   ''' <summary>
   ''' Execute the LinearDimension.  This method is invoked by the LinDimCommand.
   ''' </summary>
   Public Sub AddPointCurve(ByVal param As Object)
      InitCommand(True)
      If (Keyboard.Modifiers And ModifierKeys.Control) = ModifierKeys.Control Then
         Map.refSceneHostVM.MainController.ExecuteCommand(Controller.CMD.CLOSECOMPO)
      ElseIf (Keyboard.Modifiers And ModifierKeys.Shift) = ModifierKeys.Shift Then
         Map.refSceneHostVM.MainController.ExecuteCommand(Controller.CMD.CURVETOARC)
      Else
         Map.refSceneHostVM.MainController.ExecuteCommand(Controller.CMD.ADDPOINTCURVE)
      End If
   End Sub

#End Region ' AddPointCurve

#Region "RemovePointCurve"

   ''' <summary>
   ''' Returns a command that do Linear Dimension.
   ''' </summary>
   Public ReadOnly Property RemovePointCurve_Command As ICommand
      Get
         If m_cmdRemovePointCurve Is Nothing Then
            m_cmdRemovePointCurve = New Command(AddressOf RemovePointCurve)
         End If
         Return m_cmdRemovePointCurve
      End Get
   End Property

   ''' <summary>
   ''' Execute the LinearDimension.  This method is invoked by the LinDimCommand.
   ''' </summary>
   Public Sub RemovePointCurve(ByVal param As Object)
      If (Keyboard.Modifiers And ModifierKeys.Control) = ModifierKeys.Control Then
         If Not m_bClosedPathNeeded Then
            InitCommand(False)
            m_bIsOpeningCurveCompo = True
            Map.refFreeContourInputVM.ShowMessage(EgtMsg(62009), EgtMsg(62010))
         Else
            Map.refSceneHostVM.MainScene.SetStatusNull()
         End If
      ElseIf (Keyboard.Modifiers And ModifierKeys.Shift) = ModifierKeys.Shift Then
         InitCommand(True)
         Map.refSceneHostVM.MainController.ExecuteCommand(Controller.CMD.CURVETOLINE)
      Else
         InitCommand(True)
         Map.refSceneHostVM.MainController.ExecuteCommand(Controller.CMD.REMOVEPOINTCURVE)
      End If
   End Sub

#End Region ' RemovePointCurve

   '#Region "ArcFlip"

   '   ''' <summary>
   '   ''' Returns a command that do Arc Flip.
   '   ''' </summary>
   '   Public ReadOnly Property ArcFlip_Command As ICommand
   '      Get
   '         If m_cmdArcflip Is Nothing Then
   '            m_cmdArcflip = New Command(AddressOf ArcFlip)
   '         End If
   '         Return m_cmdArcflip
   '      End Get
   '   End Property

   '   ''' <summary>
   '   ''' Execute the ArcFlip.  This method is invoked by the ArcFlipCommand.
   '   ''' </summary>
   '   Public Sub ArcFlip(ByVal param As Object)
   '      InitCommand()
   '      If (Keyboard.Modifiers And ModifierKeys.Shift) = ModifierKeys.Shift Then
   '         Map.refSceneHostVM.MainController.ExecuteCommand(Controller.CMD.ARCEXPLEMENTARY)
   '      Else
   '         Map.refSceneHostVM.MainController.ExecuteCommand(Controller.CMD.ARCFLIP)
   '      End If
   '   End Sub

   '#End Region ' ArcFlip

#Region "Move"

   ''' <summary>
   ''' Returns a command that do Move.
   ''' </summary>
   Public ReadOnly Property Move_Command As ICommand
      Get
         If m_cmdMove Is Nothing Then
            m_cmdMove = New Command(AddressOf Move)
         End If
         Return m_cmdMove
      End Get
   End Property

   ''' <summary>
   ''' Execute the Move.  This method is invoked by the MoveCommand.
   ''' </summary>
   Public Sub Move(ByVal param As Object)
      InitCommand(True)
      Map.refSceneHostVM.MainController.ExecuteCommand(Controller.CMD.MOVE)
   End Sub

#End Region ' Move

#Region "Rotate"

   ''' <summary>
   ''' Returns a command that do Rotate.
   ''' </summary>
   Public ReadOnly Property Rotate_Command As ICommand
      Get
         If m_cmdRotate Is Nothing Then
            m_cmdRotate = New Command(AddressOf Rotate)
         End If
         Return m_cmdRotate
      End Get
   End Property

   ''' <summary>
   ''' Execute the Rotate.  This method is invoked by the RotateCommand.
   ''' </summary>
   Public Sub Rotate(ByVal param As Object)
      InitCommand(True)
      Map.refSceneHostVM.MainController.ExecuteCommand(Controller.CMD.ROTATE)
   End Sub

#End Region ' Rotate

#Region "Mirror"

   ''' <summary>
   ''' Returns a command that do Mirror.
   ''' </summary>
   Public ReadOnly Property Mirror_Command As ICommand
      Get
         If m_cmdMirror Is Nothing Then
            m_cmdMirror = New Command(AddressOf Mirror)
         End If
         Return m_cmdMirror
      End Get
   End Property

   ''' <summary>
   ''' Execute the Mirror.  This method is invoked by the MirrorCommand.
   ''' </summary>
   Public Sub Mirror(ByVal param As Object)
      InitCommand(True)
      Map.refSceneHostVM.MainController.ExecuteCommand(Controller.CMD.MIRROR)
   End Sub

#End Region ' Mirror

#Region "Scale"

   ''' <summary>
   ''' Returns a command that do Scale.
   ''' </summary>
   Public ReadOnly Property Scale_Command As ICommand
      Get
         If m_cmdScale Is Nothing Then
            m_cmdScale = New Command(AddressOf Scale)
         End If
         Return m_cmdScale
      End Get
   End Property

   ''' <summary>
   ''' Execute the Scale.  This method is invoked by the ScaleCommand.
   ''' </summary>
   Public Sub Scale(ByVal param As Object)
      InitCommand(True)
      Map.refSceneHostVM.MainController.ExecuteCommand(Controller.CMD.SCALE)
   End Sub

#End Region ' Scale

#Region "ChangeStart"

   ''' <summary>
   ''' Returns a command that do Scale.
   ''' </summary>
   Public ReadOnly Property ChangeStart_Command As ICommand
      Get
         If m_cmdChangeStart Is Nothing Then
            m_cmdChangeStart = New Command(AddressOf ChangeStart)
         End If
         Return m_cmdChangeStart
      End Get
   End Property

   ''' <summary>
   ''' Execute the Scale.  This method is invoked by the ScaleCommand.
   ''' </summary>
   Public Sub ChangeStart(ByVal param As Object)
      InitCommand(True)
      Map.refSceneHostVM.MainScene.SetSnapPointType(SP.PT_END)
      Map.refSceneHostVM.MainController.ExecuteCommand(Controller.CMD.CHANGESTARTCURVE)
   End Sub

#End Region ' ChangeStart

#Region "InvertCurve"

   ''' <summary>
   ''' Returns a command that do Scale.
   ''' </summary>
   Public ReadOnly Property InvertCurve_Command As ICommand
      Get
         If m_cmdInvertCurve Is Nothing Then
            m_cmdInvertCurve = New Command(AddressOf InvertCurve)
         End If
         Return m_cmdInvertCurve
      End Get
   End Property

   ''' <summary>
   ''' Execute the Scale.  This method is invoked by the ScaleCommand.
   ''' </summary>
   Public Sub InvertCurve(ByVal param As Object)
      InitCommand(True)
      Map.refSceneHostVM.MainController.ExecuteCommand(Controller.CMD.INVERTCURVE)
   End Sub

#End Region ' InvertCurve

#Region "TextAngle"

   ''' <summary>
   ''' Returns a command that do Scale.
   ''' </summary>
   Public ReadOnly Property TextAngle_Command As ICommand
      Get
         If m_cmdTextAngle Is Nothing Then
            m_cmdTextAngle = New Command(AddressOf TextAngle)
         End If
         Return m_cmdTextAngle
      End Get
   End Property

   ''' <summary>
   ''' Execute the Scale.  This method is invoked by the ScaleCommand.
   ''' </summary>
   Public Sub TextAngle(ByVal param As Object)
      InitCommand(False)
      ' imposto selezione solo testi
      Map.refSceneHostVM.MainScene.SetObjFilterForSel(False, False, False, False, True)
      Map.refFreeContourInputVM.ShowMessage(EgtMsg(62007), EgtMsg(62011))
      m_bIsModifyingTextAngle = True
   End Sub

#End Region ' ScaleCommand

#End Region    ' COMMANDS

End Class

Public Class SideAngle

   ' Id geometrico dell'entita' text
   Private m_nId As Integer
   Public ReadOnly Property nId As Integer
      Get
         Return m_nId
      End Get
   End Property

   ' indice della posizione di questo lato all'interno del percorso
   Private m_nIndex As Integer
   Public Property nIndex As Integer
      Get
         Return m_nIndex
      End Get
      Set(value As Integer)
         m_nIndex = value
      End Set
   End Property

   Private m_dValue As Double
   Friend Property dValue As Double
      Get
         Return m_dValue
      End Get
      Set(value As Double)
         m_dValue = value
      End Set
   End Property

   Sub New(Id As Integer, Index As Integer, Value As Double)
      m_nId = Id
      m_nIndex = Index
      m_dValue = Value
   End Sub

End Class