Imports System.Collections.ObjectModel
Imports EgtUILib

Public Class FrameCutPageUC

   ' Riferimenti a pagine
   Private m_MainWindow As MainWindow = DirectCast(Application.Current.MainWindow, MainWindow)
   Private WithEvents m_CurrProjPage As CurrentProjectPageUC
   Friend m_ProjectMgr As ProjectMgrUC
   Private m_CurrMachine As CurrentMachine
   Friend m_FrameMachiningUC As FrameMachiningUC

   ' Flag di pagina attiva
   Private m_bActive As Boolean = False
   ' Dati del grezzo
   Private m_nRawId As Integer = GDB_ID.NULL
   Private m_RawBox As New BBox3d
   Private m_dKerf As Double = 0
   ' Array per combo direzioni
   Private m_AlongAx As New List(Of String)
   ' Direzione corrente
   Private m_CurrAx As Integer = 0
   ' Importazione guida in corso
   Private m_bGuide As Boolean = False

   Private Sub FrameCutPage_Initialized(sender As Object, e As EventArgs) Handles Me.Initialized
      ' Creazione delle Page UserControl
      m_ProjectMgr = New ProjectMgrUC
      m_FrameMachiningUC = New FrameMachiningUC

      ' Posizionamento nella griglia delle Page UserControl
      m_ProjectMgr.SetValue(Grid.RowProperty, 2)
      m_ProjectMgr.SetValue(Grid.ColumnProperty, 1)
      m_FrameMachiningUC.SetValue(Grid.RowProperty, 1)

      ' Assegno UC a questa pagina
      FrameCutPageGrid.Children.Add(m_ProjectMgr)

      ' Associo ComboBox e Liste
      AlongAxCmBx.ItemsSource = m_AlongAx

      ' Imposto dati arco
      Dim dExtRad As Double = GetPrivateProfileDouble(S_FRAME, K_ARCRAD, 400, m_MainWindow.GetIniFile())
      ArcRadTxBx.Text = LenToString(dExtRad, 3)
      Dim dAngCenDeg As Double = Math.Abs(GetPrivateProfileDouble(S_FRAME, K_ARCANG, 90, m_MainWindow.GetIniFile()))
      ArcAngTxBx.Text = DoubleToString(dAngCenDeg, 3)

      ' Imposto offset in Z dal sopra del grezzo e in XY da angolo in basso a sx
      Dim dOffsZ As Double = GetPrivateProfileDouble(S_FRAME, K_OFFSZ, 5, m_MainWindow.GetIniFile())
      OffsZTxBx.Text = LenToString(dOffsZ, 3)
      Dim dOffsXY As Double = GetPrivateProfileDouble(S_FRAME, K_OFFSXY, 5, m_MainWindow.GetIniFile())
      OffsXyTxBx.Text = LenToString(dOffsXY, 3)
      Dim dOffsYY As Double = GetPrivateProfileDouble(S_FRAME, K_OFFSYY, 5, m_MainWindow.GetIniFile())
      OffsYyTxBx.Text = LenToString(dOffsYY, 3)

      ' Imposto i messaggi letti dal file dei messaggi
      m_AlongAx.Add(EgtMsg(MSG_FRAMECUTPAGEUC + 1))            'Lungo X
      m_AlongAx.Add(EgtMsg(MSG_FRAMECUTPAGEUC + 2))            'Lungo Y
      If GetPrivateProfileInt(S_FRAME, K_ARC_ENABLE, 0, m_MainWindow.GetIniFile()) <> 0 And
         m_MainWindow.GetKeyOption( MainWindow.KEY_OPT.CURVED_FRAME) Then
         m_AlongAx.Add(EgtMsg(MSG_FRAMECUTPAGEUC + 13))        'Arco
         m_AlongAx.Add(EgtMsg(MSG_FRAMECUTPAGEUC + 14))        'Guida
      End If
      SelSectionBtn.ToolTip = EgtMsg(MSG_FRAMECUTPAGEUC + 15)   'Sezione
      SelGuideBtn.Content = EgtMsg(MSG_FRAMECUTPAGEUC + 16)     'Guida
      ArcRadTxBl.Text = EgtMsg(MSG_FRAMECUTPAGEUC + 17)         'Rad
      ArcAngTxBl.Text = EgtMsg(MSG_FRAMECUTPAGEUC + 18)         'Ang
      MirrorPartBtn.ToolTip = EgtMsg(MSG_FRAMECUTPAGEUC + 7)    'Mirror cornice
      RemovePartBtn.ToolTip = EgtMsg(MSG_FRAMECUTPAGEUC + 3)    'Rimuovi cornice
      OffsZTxBl.Text = EgtMsg(MSG_FRAMECUTPAGEUC + 8)           'Distanza sopra
      OffsXyTxBl.Text = EgtMsg(MSG_FRAMECUTPAGEUC + 9)          'Distanza inizio
      OffsYyTxBl.Text = EgtMsg(MSG_FRAMECUTPAGEUC + 22)         'Distanza Y
   End Sub

   Private Sub FrameCutPage_Loaded(sender As Object, e As RoutedEventArgs) Handles Me.Loaded
      m_CurrProjPage = m_MainWindow.m_CurrentProjectPageUC
      m_CurrMachine = m_MainWindow.m_CurrentMachine
      m_bActive = True
      m_bGuide = False
      ' Nascondo bottoni CSV, VeinMatching e Registration
      m_ProjectMgr.CSVBtn.Visibility = Windows.Visibility.Hidden
      m_ProjectMgr.VeinMatchingBtn.Visibility = Windows.Visibility.Hidden
      m_ProjectMgr.RegisterBtn.Visibility = Windows.Visibility.Hidden
      ' Recupero dimensioni e kerf del grezzo
      m_nRawId = EgtGetFirstRawPart()
      GetRawBox(m_RawBox)
      EgtGetInfo(m_nRawId, KEY_KERF, m_dKerf)
      ' Imposto direzione cornici
      UpdatePage()
      ' Se macchina fotografica abilitata
      If m_MainWindow.GetKeyOption(MainWindow.KEY_OPT.MAN_PHOTO) Then
         PhotoBtn.IsEnabled = True
      Else
         PhotoBtn.IsEnabled = False
      End If
      ' Se provengo da grezzo, sistemo eventuali cornici
      If m_MainWindow.m_PrevActivePage = MainWindow.Pages.RawPart Then
         ' Aggiorno geometria
         UpdateFrames()
         ' Ricalcolo lavorazioni
         AddFrameMachinings(m_FrameMachiningUC.m_dStartTrim, m_FrameMachiningUC.m_dEndTrim)
      End If
      ' Abilito visualizzazione delle lavorazioni
      EgtSetCurrPhase(1)
      ShowAllCurrPhaseMachinings()
      EgtZoom(ZM.ALL)
   End Sub

   Private Sub UpdatePage()
      ' Se già presenti cornici
      Dim nPartId As Integer = EgtGetFirstPartInRawPart(m_nRawId)
      If nPartId <> GDB_ID.NULL Then
         ' Visualizzo direzione senza poterla modificare
         Dim nDir As Integer
         If EgtGetInfo(nPartId, INFO_FRAME_DIR, nDir) Then m_CurrAx = nDir
         AlongAxCmBx.SelectedIndex = m_CurrAx
         AlongAxCmBx.IsEnabled = False
         ' Se cornice arco o curva, disabilito scelta nuova sezione 
         SelSectionBtn.IsEnabled = ( m_CurrAx = 0 Or m_CurrAx = 1)
         ' Se cornice curva, verifico se disabilitare scelta guida
         If m_CurrAx = 3 Then
            SelGuideBtn.IsEnabled = ( EgtGetFirstNameInGroup( nPartId, NAME_GUIDE) = GDB_ID.NULL)
         End If
         ' Se cornice su arco ne leggo i dati
         If m_CurrAx = 2 Then
            Dim dExtRad As Double
            if EgtGetInfo(nPartId, INFO_FRAME_ARCRAD, dExtRad) Then ArcRadTxBx.Text = LenToString( dExtRad, 3)
            Dim dAngCenDeg As Double
            if EgtGetInfo(nPartId, INFO_FRAME_ARCANG, dAngCenDeg) Then ArcAngTxBx.Text = DoubleToString( dAngCenDeg, 3)
         End If
      ' Altrimenti
      Else
         ' Abilito cambio direzione e scelta sezione
         AlongAxCmBx.SelectedIndex = m_CurrAx
         AlongAxCmBx.IsEnabled = True
         SelSectionBtn.IsEnabled = True
         SelGuideBtn.IsEnabled = True
      End If
   End Sub

   Private Sub AlongAxCmBx_SelectionChanged() Handles AlongAxCmBx.SelectionChanged
      Select Case AlongAxCmBx.SelectedIndex
         Case 0, 1            'Lungo X, Lungo Y
            SelSectionBtn.Visibility = Windows.Visibility.Visible
            SelGuideBtn.Visibility = Windows.Visibility.Collapsed
            ArcGrid.Visibility = Windows.Visibility.Collapsed
            OffsYyTxBl.Visibility = Windows.Visibility.Collapsed
            OffsYyTxBx.Visibility = Windows.Visibility.Collapsed
            OffsXyTxBl.Text = EgtMsg(MSG_FRAMECUTPAGEUC + 9)          'Distanza inizio
         Case 2               'Arco
            SelSectionBtn.Visibility = Windows.Visibility.Visible
            SelGuideBtn.Visibility = Windows.Visibility.Collapsed
            ArcGrid.Visibility = Windows.Visibility.Visible
            OffsYyTxBl.Visibility = Windows.Visibility.Visible
            OffsYyTxBx.Visibility = Windows.Visibility.Visible
            OffsXyTxBl.Text = EgtMsg(MSG_FRAMECUTPAGEUC + 21)          'Distanza X
         Case 3               'Guida
            SelSectionBtn.Visibility = Windows.Visibility.Visible
            SelGuideBtn.Visibility = Windows.Visibility.Visible
            SelGuideBtn.IsEnabled = False
            ArcGrid.Visibility = Windows.Visibility.Collapsed
            OffsYyTxBl.Visibility = Windows.Visibility.Visible
            OffsYyTxBx.Visibility = Windows.Visibility.Visible
            OffsXyTxBl.Text = EgtMsg(MSG_FRAMECUTPAGEUC + 21)          'Distanza X
      End Select
   End Sub

   Private Sub FrameCutPage_Unloaded(sender As Object, e As RoutedEventArgs) Handles Me.Unloaded
      ' Nascondo tutte le lavorazioni
      HideAllMachinings()
      ' se aperta pagina lavorazioni la chiudo
      If MachiningBtn.IsChecked Then
         LeftGrid.Children.Remove(m_FrameMachiningUC)
         MachiningBtn.IsChecked = False
      End If

      ' La dichiaro non attiva
      m_bActive = False

   End Sub

   Private Sub OnMyMouseDownScene(sender As Object, e As System.Windows.Forms.MouseEventArgs) Handles m_CurrProjPage.OnMouseDownScene
      ' Verifico di essere il gestore attivo
      If Not m_bActive Then Return
      ' Si può selezionare solo con il tasto sinistro e se stato NULL
      If e.Button <> Windows.Forms.MouseButtons.Left Or
         Not m_CurrProjPage.CurrentProjectScene.IsStatusNull() Then
         Return
      End If
      ' Verifico se selezionato indicativo di pezzo
      EgtSetObjFilterForSelWin(False, False, True, False, False)
      Dim nSel As Integer
      EgtSelect(e.Location, Scene.DIM_SEL, Scene.DIM_SEL, nSel)
      Dim nId As Integer = EgtGetFirstObjInSelWin()
      While nId <> GDB_ID.NULL
         ' Recupero l'identificativo del layer e del pezzo cui appartiene
         Dim nLayId As Integer = EgtGetParent(nId)
         Dim nPartId As Integer = EgtGetParent(nLayId)
         ' Ignoro superfici del layer Facet
         Dim nLayName As String = String.Empty
         EgtGetName(nLayId, nLayName)
         If nLayName = NAME_FACET Then
            nId = EgtGetNextObjInSelWin()
            Continue While
         End If
         ' Se pezzo in tavola
         Dim bPartInTable As Boolean = (EgtGetParent(nPartId) = m_nRawId)
         If bPartInTable Then
            ' Effetto selezione/deselezione
            Dim nOldStat As Integer = GDB_ST.ON_
            EgtGetStatus(nPartId, nOldStat)
            Dim nStat As Integer = If(nOldStat = GDB_ST.SEL, GDB_ST.ON_, GDB_ST.SEL)
            EgtSetStatus(nPartId, nStat)
            ' Se selezione, recupero superficie e faccia identificati
            If nStat = GDB_ST.SEL Then
               Dim PtTemp As Point3d
               Dim nTria As Integer
               If EgtGetPointFromSelect(nId, e.Location, PtTemp, nTria) Then
                  Dim nFacet As Integer = EgtSurfTmFacetFromTria(nId, nTria)
                  ' Cancello eventuali vecchie info e facce da lavorare
                  Dim nPirId As Integer = EgtGetFirstPartInRawPart(m_nRawId)
                  While nPirId <> GDB_ID.NULL
                     EgtRemoveInfo(nPirId, INFO_FRAME_SURF)
                     EgtRemoveInfo(nPirId, INFO_FRAME_FACET)
                     EgtEmptyGroup(EgtGetFirstNameInGroup(nPirId, NAME_FACET))
                     nPirId = EgtGetNextPartInRawPart(nPirId)
                  End While
                  ' Imposto le nuove info
                  EgtSetInfo(nPartId, INFO_FRAME_SURF, nId)
                  EgtSetInfo(nPartId, INFO_FRAME_FACET, nFacet)
                  ' Creo la copia di facet selezionata
                  Dim nFacetLayId As Integer = EgtGetFirstNameInGroup(nPartId, NAME_FACET)
                  If nFacetLayId = GDB_ID.NULL Then
                     nFacetLayId = EgtCreateGroup(nPartId)
                     EgtSetName(nFacetLayId, NAME_FACET)
                  End If
                  Dim nNewFacetId As Integer = EgtCopySurfTmFacet(nId, nFacet, nFacetLayId)
                  EgtSetColor(nNewFacetId, New Color3d(0, 255, 255))
               End If
            End If
            EgtDraw()
            Exit While
         End If
         nId = EgtGetNextObjInSelWin()
      End While
   End Sub

   Private Sub ArcXXTxBx_EgtClosed(sender As Object, e As EventArgs) Handles ArcRadTxBx.EgtClosed, ArcAngTxBx.EgtClosed
      ' Forzo aggiornamento grezzo nella pagina di Nesting
      m_MainWindow.m_CadCutPageUC.m_NestPage.CalcRawPart()
      ' Parcheggio pezzi presenti nel grezzo
      Dim nPartId As Integer = EgtGetFirstPartInRawPart(m_CurrProjPage.m_nRawId)
      While nPartId <> GDB_ID.NULL
         m_MainWindow.m_CadCutPageUC.m_NestPage.StoreOnePart(nPartId)
         nPartId = EgtGetFirstPartInRawPart(m_CurrProjPage.m_nRawId)
      End While
      ' Aggiorno geometria
      UpdateFrames()
      ' Ricalcolo lavorazioni
      AddFrameMachinings(m_FrameMachiningUC.m_dStartTrim, m_FrameMachiningUC.m_dEndTrim)
      ' Aggiorno visualizzazione
      EgtDraw()
      ' Salvo offset in Z dal sopra del grezzo e in XY da angolo in basso a sx
      Dim dExtRad As Double = 0
      If StringToLen(ArcRadTxBx.Text, dExtRad) Then
         WritePrivateProfileString(S_FRAME, K_ARCRAD, DoubleToString(dExtRad, 3), m_MainWindow.GetIniFile())
      End If
      Dim dAngCenDeg As Double = 0
      If StringToDouble(ArcAngTxBx.Text, dAngCenDeg) Then
         WritePrivateProfileString(S_FRAME, K_ARCANG, DoubleToString(dAngCenDeg, 3), m_MainWindow.GetIniFile())
      End If
   End Sub

   Private Sub OffsXXTxBx_EgtClosed(sender As Object, e As EventArgs) Handles OffsZTxBx.EgtClosed, OffsXyTxBx.EgtClosed, OffsYyTxBx.EgtClosed
      ' Forzo aggiornamento grezzo nella pagina di Nesting
      m_MainWindow.m_CadCutPageUC.m_NestPage.CalcRawPart()
      ' Parcheggio pezzi presenti nel grezzo
      Dim nPartId As Integer = EgtGetFirstPartInRawPart(m_CurrProjPage.m_nRawId)
      While nPartId <> GDB_ID.NULL
         m_MainWindow.m_CadCutPageUC.m_NestPage.StoreOnePart(nPartId)
         nPartId = EgtGetFirstPartInRawPart(m_CurrProjPage.m_nRawId)
      End While
      ' Aggiorno geometria
      UpdateFrames()
      ' Ricalcolo lavorazioni
      AddFrameMachinings(m_FrameMachiningUC.m_dStartTrim, m_FrameMachiningUC.m_dEndTrim)
      ' Aggiorno visualizzazione
      EgtDraw()
      ' Salvo offset in Z dal sopra del grezzo e in XY da angolo in basso a sx
      Dim dOffsZ As Double = 0
      If StringToLen(OffsZTxBx.Text, dOffsZ) Then
         WritePrivateProfileString(S_FRAME, K_OFFSZ, DoubleToString(dOffsZ, 3), m_MainWindow.GetIniFile())
      End If
      Dim dOffsXy As Double = 0
      If StringToLen(OffsXyTxBx.Text, dOffsXy) Then
         WritePrivateProfileString(S_FRAME, K_OFFSXY, DoubleToString(dOffsXy, 3), m_MainWindow.GetIniFile())
      End If
      Dim dOffsYy As Double = 0
      If StringToLen(OffsYyTxBx.Text, dOffsYY) Then
         WritePrivateProfileString(S_FRAME, K_OFFSYY, DoubleToString(dOffsYy, 3), m_MainWindow.GetIniFile())
      End If
   End Sub

   Private Sub MirrorPartBtn_Click(sender As Object, e As RoutedEventArgs) Handles MirrorPartBtn.Click
      ' Se non ci sono pezzi selezionati, esco subito
      If EgtGetSelectedObjCount() = 0 Then Return
      ' Ciclo di mirror dei pezzi selezionati
      Dim nId As Integer = EgtGetFirstSelectedObj()
      While nId <> GDB_ID.NULL
         ' Elimino eventuale facet selezionata
         EgtRemoveInfo(nId, INFO_FRAME_SURF)
         EgtRemoveInfo(nId, INFO_FRAME_FACET)
         EgtEmptyGroup(EgtGetFirstNameInGroup(nId, NAME_FACET))
         ' Recupero layer e curva della sezione
         Dim nSectLayId As Integer = EgtGetFirstNameInGroup(nId, NAME_SECT)
         Dim nCrvId As Integer = EgtGetFirstInGroup(nSectLayId)
         ' Recupero box della sezione
         Dim b3Box As New BBox3d
         EgtGetBBoxGlob(nCrvId, GDB_BB.STANDARD, b3Box)
         ' Eseguo rotazione di 180 deg attorno a Z
         EgtRotate(nCrvId, b3Box.Center(), Vector3d.Z_AX(), 180, GDB_RT.GLOB)
         ' Per arco
         If m_CurrAx = 2 Then
            ' Inverto senso
            EgtInvertCurve(nCrvId)
            ' Porto l'inizio della curva a X0 locale
            ChangeCurveStartToX0(nCrvId)
         End If
         ' Aggiorno la cornice
         UpdateFrame(nId)
         ' Passo al successivo selezionato
         nId = EgtGetNextSelectedObj()
      End While
      ' Ricalcolo lavorazioni
      AddFrameMachinings(m_FrameMachiningUC.m_dStartTrim, m_FrameMachiningUC.m_dEndTrim)
      ' Aggiorno vista
      EgtDraw()
   End Sub

   Private Sub RemovePartBtn_Click(sender As Object, e As RoutedEventArgs) Handles RemovePartBtn.Click
      ' Se non ci sono pezzi selezionati
      If EgtGetSelectedObjCount() = 0 Then
         ' Cerco pezzo in grezzo
         Dim nPartId As Integer = EgtGetFirstPartInRawPart(m_nRawId)
         ' Se modalità curva e presa solo sezione, cancello unico pezzo in grezzo
         If m_CurrAx = 3 And EgtGetFirstNameInGroup( nPartId, NAME_GUIDE) = GDB_ID.NULL
            If EgtRemovePartFromRawPart(nPartId) Then
               ' Rimuovo le lavorazioni
               EraseMachinings(nPartId)
               ' Cancello
               EgtErase(nPartId)
            End If
         ' Altrimenti esco subito 
         Else
            Return
         End If
      End If
      ' Ciclo di cancellazione dei pezzi selezionati
      Dim nId As Integer = EgtGetFirstSelectedObj()
      While nId <> GDB_ID.NULL
         ' Recupero indice del successivo
         Dim nNextId = EgtGetNextSelectedObj()
         ' Cancello il pezzo
         If EgtRemovePartFromRawPart(nId) Then
            ' Rimuovo le lavorazioni
            EraseMachinings(nId)
            ' Cancello
            EgtErase(nId)
         End If
         ' Passo al successivo selezionato
         nId = nNextId
      End While
      ' Aggiusto posizione dei rimanenti pezzi nel grezzo
      nId = EgtGetFirstPartInRawPart(m_nRawId)
      While nId <> GDB_ID.NULL
         EgtRemovePartFromRawPart(nId)
         nId = EgtGetFirstPartInRawPart(m_nRawId)
      End While
      nId = EgtGetFirstPart()
      While nId <> GDB_ID.NULL
         InsertPartInRawPart(nId)
         nId = EgtGetFirstPart()
      End While
      ' Ricalcolo lavorazioni
      AddFrameMachinings(m_FrameMachiningUC.m_dStartTrim, m_FrameMachiningUC.m_dEndTrim)
      ' Aggiorno vista
      EgtDraw()
      ' Aggiorno combo per direzioni
      UpdatePage()
   End Sub

   Private Sub SelectSectionBtn_Click(sender As Object, e As RoutedEventArgs) Handles SelSectionBtn.Click
      m_MainWindow.MainWindowGrid.Children.Remove(m_MainWindow.m_CurrentProjectPageUC)
      m_MainWindow.MainWindowGrid.Children.Add(m_MainWindow.m_ImportPageUC)
      m_MainWindow.m_ActivePage = MainWindow.Pages.Import
      m_MainWindow.m_PrevActivePage = MainWindow.Pages.FrameCut
   End Sub

   Private Sub SelectGuideBtn_Click(sender As Object, e As RoutedEventArgs) Handles SelGuideBtn.Click
      m_MainWindow.MainWindowGrid.Children.Remove(m_MainWindow.m_CurrentProjectPageUC)
      m_MainWindow.MainWindowGrid.Children.Add(m_MainWindow.m_ImportPageUC)
      m_MainWindow.m_ActivePage = MainWindow.Pages.Import
      m_MainWindow.m_PrevActivePage = MainWindow.Pages.FrameCut
      m_bGuide = True
   End Sub

   Private Sub PhotoBtn_Click(sender As Object, e As RoutedEventArgs) Handles PhotoBtn.Click
      EgtSetCurrentContext(m_MainWindow.m_CurrentProjectPageUC.CurrentProjectScene.GetCtx())
      ' Se macchina fotografica collegata, faccio una foto
      If m_MainWindow.m_Camera.GetCameraLink() Then
         If Not m_MainWindow.m_Camera.CameraClick() Then
            m_CurrProjPage.SetErrorMessage(EgtMsg(90313))    'Fotografia non riuscita
         End If
         ' Altrimenti lancio browser di immagini
      Else
         m_MainWindow.MainWindowGrid.Children.Remove(m_MainWindow.m_CurrentProjectPageUC)
         m_MainWindow.MainWindowGrid.Children.Add(m_MainWindow.m_PhotoPage)
         m_MainWindow.m_ActivePage = MainWindow.Pages.Photo
         m_MainWindow.m_PrevActivePage = MainWindow.Pages.FrameCut
      End If
   End Sub

   Private Sub RawPartBtn_Click(sender As Object, e As RoutedEventArgs) Handles RawPartBtn.Click
      m_MainWindow.m_CurrentProjectPageUC.CurrProjGrid.Visibility = Windows.Visibility.Hidden
      m_MainWindow.m_CurrentProjectPageUC.CurrentProjectPageGrid.Children.Remove(Me)
      m_MainWindow.m_CurrentProjectPageUC.CurrentProjectPageGrid.Children.Add(m_MainWindow.m_RawPartPage)
      m_MainWindow.m_ActivePage = MainWindow.Pages.RawPart
      m_MainWindow.m_PrevActivePage = MainWindow.Pages.FrameCut
   End Sub

   Private Sub MachiningBtn_Click(sender As Object, e As RoutedEventArgs) Handles MachiningBtn.Click
      If MachiningBtn.IsChecked Then
         LeftGrid.Children.Add(m_FrameMachiningUC)
      Else
         LeftGrid.Children.Remove(m_FrameMachiningUC)
      End If
   End Sub

   Friend Function CreateFrame(nPartId As Integer) As Boolean
      If Not MyCreateFrame( nPartId) Then
         EgtErase( nPartId)
         If m_CurrAx <> 2 Then
            ' Errore : creazione cornice non riuscita
            m_CurrProjPage.SetErrorMessage( EgtMsg(MSG_FRAMECUTPAGEUC + 20))
         Else
            ' Errore : raggio più piccolo della larghezza della sezione
            m_CurrProjPage.SetErrorMessage( EgtMsg(MSG_FRAMECUTPAGEUC + 19))
         End If
         Return False
      End If
      m_FrameMachiningUC.ResetOthSide()
      Return True
   End Function

   Private Function MyCreateFrame(nPartId As Integer) As Boolean
      ' Pulisco messaggi
      m_CurrProjPage.ClearMessage()
      ' Aggiorno direzione corrente
      m_CurrAx = AlongAxCmBx.SelectedIndex
      ' Sistemo la sezione o la guida della cornice
      If Not m_bGuide Then
         If Not AdjustSection(nPartId) Then
            EgtOutLog( "Error in CreateFrame : problems with Section") 
            Return False
         End If
      Else
         If Not AdjustGuide(nPartId) Then
            EgtOutLog( "Error in CreateFrame : problems with Guide") 
            Return False
         End If
      End If
      Dim nSurfId As Integer = GDB_ID.NULL
      ' Se cornice rettilinea
      If m_CurrAx = 0 Or m_CurrAx = 1 Then
         ' Recupero layer e curva della sezione
         Dim nSectLayId As Integer = EgtGetFirstNameInGroup(nPartId, NAME_SECT)
         Dim nSectId As Integer = EgtGetFirstInGroup(nSectLayId)
         If nSectId = GDB_ID.NULL Then Return False
         ' Creazione cornice
         nSurfId = CreateLineFrame( nSectId, nSectLayId, nPartId)
         ' Se non creata superficie, reset di tutto e segnalazione errore
         If nSurfId = GDB_ID.NULL Then
            EgtErase( nPartId)
            EgtOutLog( "Error in CreateFrame : Surface not constructible")
            Return False
         End If
      ' se cornice su arco
      ElseIf m_CurrAx = 2 Then
         ' Recupero layer e curva della sezione
         Dim nSectLayId As Integer = EgtGetFirstNameInGroup(nPartId, NAME_SECT)
         Dim nSectId As Integer = EgtGetFirstInGroup(nSectLayId)
         If nSectId = GDB_ID.NULL Then Return False
         ' Porto l'inizio della curva a X0 locale
         ChangeCurveStartToX0( nSectId)
         ' Creazione cornice
         nSurfId = CreateArcFrame( nSectId, nSectLayId, nPartId)
         ' Se non creata superficie, reset di tutto e segnalazione errore
         If nSurfId = GDB_ID.NULL Then
            EgtErase( nPartId)
            EgtOutLog( "Error in CreateFrame : radius too small for the section")
            Return False
         End If
      ' altrimenti cornice su guida
      Else
         If not m_bGuide Then
            ' Recupero layer e curva della sezione
            Dim nSectLayId As Integer = EgtGetFirstNameInGroup(nPartId, NAME_SECT)
            Dim nSectId As Integer = EgtGetFirstInGroup(nSectLayId)
            If nSectId = GDB_ID.NULL Then Return False
            ' Porto l'inizio della curva a X0 locale
            ChangeCurveStartToX0( nSectId)
         Else
            ' Porto la guida nel pezzo con la sezione
            Dim nTruePartId As Integer = EgtGetFirstPartInRawPart( m_nRawId)
            If nTruePartId = GDB_ID.NULL Then
               EgtOutLog( "Error in CreateFrame : Section not found")
               Return False
            End If
            ' Parcheggio il pezzo trovato
            m_MainWindow.m_CadCutPageUC.m_NestPage.CalcRawPart()
            m_MainWindow.m_CadCutPageUC.m_NestPage.StoreOnePart( nTruePartId)
            ' Recupero layer e curva della sezione
            Dim nSectLayId As Integer = EgtGetFirstNameInGroup(nTruePartId, NAME_SECT)
            Dim nSectId As Integer = EgtGetFirstInGroup(nSectLayId)
            If nSectId = GDB_ID.NULL Then Return False
            ' Recupero layer e curva della guida
            Dim nGuideLayId As Integer = EgtGetFirstNameInGroup(nPartId, NAME_GUIDE)
            Dim nGuideId As Integer = EgtGetFirstInGroup(nGuideLayId)
            If nGuideId = GDB_ID.NULL Then Return False
            ' Sposto la guida in questo pezzo
            EgtRelocate( nGuideLayId, nTruePartId)
            ' Cancello il pezzo
            EgtErase( nPartId)
            ' Creazione cornice
            nPartId = nTruePartId 
            nSurfId = CreateCurveFrame( nSectId, nSectLayId, nGuideId, nGuideLayId, nPartId)
            m_bGuide = False
            ' Se non creata superficie, reset di tutto e segnalazione errore
            If nSurfId = GDB_ID.NULL Then
               EgtErase( nPartId)
               EgtOutLog( "Error in CreateFrame : Surface not constructible")
               Return False
            End If
         End If
      End If
      ' Assegno nome e tipo cornice a pezzo
      EgtSetName(nPartId, NAME_FRAME)
      EgtSetInfo(nPartId, INFO_FRAME_DIR, m_CurrAx)
      ' Se cornice su arco, salvo i dati di questo
      If m_CurrAx = 2 Then
         Dim dExtRad As Double = 0 : StringToLen(ArcRadTxBx.Text, dExtRad)
         EgtSetInfo(nPartId, INFO_FRAME_ARCRAD, dExtRad)
         Dim dAngCenDeg As Double = 0 : StringToDouble(ArcAngTxBx.Text, dAngCenDeg)
         If dAngCenDeg > 360 Then dAngCenDeg = 360
         EgtSetInfo(nPartId, INFO_FRAME_ARCANG, dAngCenDeg)
      End If
      ' Inserisco il pezzo nel grezzo
      Return InsertPartInRawPart(nPartId)
   End Function

   Private Function UpdateFrames() As Boolean
      ' Pulisco messaggi
      m_CurrProjPage.ClearMessage()
      ' Ciclo sui pezzi
      Dim nId As Integer = EgtGetFirstPart()
      While nId <> GDB_ID.NULL
         If Not UpdateFrame(nId) OrElse Not InsertPartInRawPart(nId) Then
            EgtErase(nId)
         End If
         nId = EgtGetFirstPart()
      End While
      Return True
   End Function

   Private Function UpdateFrame(nPartId As Integer) As Boolean
      ' Aggiorno direzione corrente
      m_CurrAx = AlongAxCmBx.SelectedIndex
      ' Recupero layer e curva della sezione
      Dim nSectLayId As Integer = EgtGetFirstNameInGroup(nPartId, NAME_SECT)
      Dim nSectId As Integer = EgtGetFirstInGroup(nSectLayId)
      If nSectId = GDB_ID.NULL Then Return False
      Dim nSurfId As Integer = GDB_ID.NULL
      ' Se cornice rettilinea
      If m_CurrAx = 0 Or m_CurrAx = 1 Then
         nSurfId = CreateLineFrame( nSectId, nSectLayId, nPartId)
      ' se cornice su arco
      ElseIf m_CurrAx = 2 Then
         nSurfId = CreateArcFrame( nSectId, nSectLayId, nPartId)
      ' altrimenti cornice su curva
      Else
         ' Recupero layer e curva della guida
         Dim nGuideLayId As Integer = EgtGetFirstNameInGroup(nPartId, NAME_GUIDE)
         Dim nGuideId As Integer = EgtGetFirstInGroup(nGuideLayId)
         If nGuideId = GDB_ID.NULL Then Return False
         nSurfId = CreateCurveFrame( nSectId, nSectLayId, nGuideId, nGuideLayId, nPartId)
      End If
      ' Assegno nome e direzione a pezzo
      EgtSetName(nPartId, NAME_FRAME)
      EgtSetInfo(nPartId, INFO_FRAME_DIR, m_CurrAx)
      ' Se cornice su arco, salvo i dati di questo
      If m_CurrAx = 2 Then
         Dim dExtRad As Double = 0 : StringToLen(ArcRadTxBx.Text, dExtRad)
         EgtSetInfo(nPartId, INFO_FRAME_ARCRAD, dExtRad)
         Dim dAngCenDeg As Double = 0 : StringToDouble(ArcAngTxBx.Text, dAngCenDeg)
         If dAngCenDeg > 360 Then dAngCenDeg = 360
         EgtSetInfo(nPartId, INFO_FRAME_ARCANG, dAngCenDeg)
      End If
      ' Aggiorno info per superficie/facet
      EgtSetInfo(nPartId, INFO_FRAME_SURF, nSurfId)
      Return True
   End Function

   Private Function AdjustSection(nPartId As Integer) As Boolean
      ' Recupero identificativo del primo layer
      Dim nLayerId As Integer = EgtGetFirstLayer(nPartId)
      ' Concateno le curve del primo layer
      EgtSelectLayerObjs(nLayerId)
      Dim nCrvIds(0) As Integer
      nCrvIds(0) = GDB_ID.SEL
      Dim nCrvId As Integer = EgtCreateCurveCompoByChain(nLayerId, 1, nCrvIds, New Point3d(), True)
      If nCrvId = GDB_ID.NULL Then Return False
      ' Elimino eventuali curve oltre la prima
      Dim nId As Integer = EgtGetNext(nCrvId)
      While nId <> GDB_ID.NULL
         Dim nNextId = EgtGetNext(nId)
         EgtErase(nId)
         nId = nNextId
      End While
      ' Verifico se curva piana e ne recupero il piano medio
      Dim vtN As Vector3d
      Dim dDist As Double
      If Not EgtCurveIsFlat(nCrvId, vtN, dDist) Then
         EgtProjectCurveOnPlane(nCrvId, Point3d.ORIG() + dDist * vtN, vtN)
      End If
      ' Creo layer sezione con riferimento OCS del piano
      Dim frPlane As New Frame3d
      frPlane.Setup(Point3d.ORIG(), vtN.Glob(nLayerId))
      Dim nSectLayId As Integer = EgtCreateGroup(nPartId, frPlane, GDB_RT.GLOB)
      EgtSetName(nSectLayId, NAME_SECT)
      EgtSetColor(nSectLayId, COL_FRAME())
      EgtRelocateGlob(nCrvId, nSectLayId)
      ' Elimino vecchio layer
      EgtErase(nLayerId)
      ' Verifico chiusura sezione
      If Not EgtCurveIsClosed(nCrvId) Then
         ' Recupero ingombro locale
         Dim b3Box As New BBox3d
         EgtGetBBox(nCrvId, GDB_BB.STANDARD, b3Box)
         ' Recupero estremi
         Dim ptStart, ptEnd As Point3d
         EgtStartPoint(nCrvId, ptStart)
         EgtEndPoint(nCrvId, ptEnd)
         ' Deve andare da dx a sn
         If ptStart.x < ptEnd.x Then
            EgtInvertCurve(nCrvId)
            Dim ptTmp As Point3d = New Point3d(ptEnd)
            ptEnd = ptStart
            ptStart = ptTmp
         End If
         ' Se cornice rettilinea
         If m_CurrAx = 0  Or m_CurrAx = 1 Then
            ' Se linea orizzontale, aggiungo tratti verticali
            If b3Box.DimY() < EPS_SMALL Then
               ptStart -= 10 * EPS_SMALL * Vector3d.Y_AX()
               EgtInvertCurve(nCrvId)
               EgtAddCurveCompoLine(nCrvId, ptStart)
               EgtInvertCurve(nCrvId)
               b3Box.Add(ptStart)
               ptEnd -= 10 * EPS_SMALL * Vector3d.Y_AX()
               EgtAddCurveCompoLine(nCrvId, ptEnd)
               b3Box.Add(ptEnd)
            End If
            ' Se necessario, aggiungo due tratti orizzontali agli estremi
            Dim vtStart, vtEnd As Vector3d
            EgtStartVector(nCrvId, vtStart)
            EgtEndVector(nCrvId, vtEnd)
            If ptStart.x < b3Box.Max().x - EPS_SMALL Or (vtStart.x > -EPS_SMALL And vtStart.y < 0) Then
               ptStart = New Point3d(b3Box.Max().x + 10 * EPS_SMALL, ptStart.y, ptStart.z)
               EgtInvertCurve(nCrvId)
               EgtAddCurveCompoLine(nCrvId, ptStart)
               EgtInvertCurve(nCrvId)
               b3Box.Add(ptStart)
            End If
            If ptEnd.x > b3Box.Min().x + EPS_SMALL Or (vtEnd.x > -EPS_SMALL And vtEnd.y > 0) Then
               ptEnd = New Point3d(b3Box.Min().x - 10 * EPS_SMALL, ptEnd.y, ptEnd.z)
               EgtAddCurveCompoLine(nCrvId, ptEnd)
               b3Box.Add(ptEnd)
            End If
            ' Eseguo chiusura (con aggiunta di eventuali tratti verticali)
            If ptStart.y > b3Box.Min().y + EPS_SMALL Or Math.Abs(vtStart.y) < EPS_SMALL Then
               ptStart = New Point3d(ptStart.x, b3Box.Min().y - 10 * EPS_SMALL, ptStart.z)
               EgtInvertCurve(nCrvId)
               EgtAddCurveCompoLine(nCrvId, ptStart)
               EgtInvertCurve(nCrvId)
               b3Box.Add(ptStart)
            End If
            If ptEnd.y > b3Box.Min().y + EPS_SMALL Or Math.Abs(vtEnd.y) < EPS_SMALL Then
               ptEnd = New Point3d(ptEnd.x, b3Box.Min().y - 10 * EPS_SMALL, ptEnd.z)
               EgtAddCurveCompoLine(nCrvId, ptEnd)
               b3Box.Add(ptEnd)
            End If
         ' Altrimenti cornice curva
         Else
            ' Aggiungo linea verticale dall'estremo più alto alla quota del più basso
            If ptStart.y > ptEnd.y Then
               ptStart = New Point3d(ptStart.x, ptEnd.y, ptStart.z)
               EgtInvertCurve(nCrvId)
               EgtAddCurveCompoLine(nCrvId, ptStart)
               EgtInvertCurve(nCrvId)
            Else
               ptEnd = New Point3d(ptEnd.x, ptStart.y, ptEnd.z)
               EgtAddCurveCompoLine(nCrvId, ptEnd)
            End If
         End If
         EgtMergeCurvesInCurveCompo(nCrvId, EPS_SMALL)
      End If
      ' Eseguo chiusura
      EgtCloseCurveCompo(nCrvId)
      Return True
   End Function

   Private Function AdjustGuide(nPartId As Integer) As Boolean
      ' Recupero identificativo del primo layer
      Dim nLayerId As Integer = EgtGetFirstLayer(nPartId)
      ' Concateno le curve del primo layer
      EgtSelectLayerObjs(nLayerId)
      Dim nCrvIds(0) As Integer
      nCrvIds(0) = GDB_ID.SEL
      Dim nCrvId As Integer = EgtCreateCurveCompoByChain(nLayerId, 1, nCrvIds, New Point3d(), True)
      If nCrvId = GDB_ID.NULL Then Return False
      ' Elimino eventuali curve oltre la prima
      Dim nId As Integer = EgtGetNext(nCrvId)
      While nId <> GDB_ID.NULL
         Dim nNextId = EgtGetNext(nId)
         EgtErase(nId)
         nId = nNextId
      End While
      ' Verifico se curva piana e ne recupero il piano medio
      Dim vtN As Vector3d
      Dim dDist As Double
      If Not EgtCurveIsFlat(nCrvId, vtN, dDist) Then
         EgtProjectCurveOnPlane(nCrvId, Point3d.ORIG() + dDist * vtN, vtN)
      End If
      ' Creo layer guida con riferimento TOP
      Dim frPlane As New Frame3d
      frPlane.Setup(Point3d.ORIG(), Frame3d.TYPE.TOP)
      Dim nSectLayId As Integer = EgtCreateGroup(nPartId, frPlane, GDB_RT.GLOB)
      EgtSetName(nSectLayId, NAME_GUIDE)
      EgtSetColor(nSectLayId, COL_FRAME())
      EgtRelocate(nCrvId, nSectLayId)
      ' Elimino vecchio layer
      EgtErase(nLayerId)
      ' Impongo rotazione guida CCW
      Dim bClosed As Boolean = EgtCurveIsClosed( nCrvId)
      If Not bClosed Then EgtCloseCurveCompo( nCrvId)
      Dim dArea As Double = 0
      EgtCurveAreaXY( nCrvId, dArea)
      If Not bClosed Then EgtRemoveCurveCompoCurve( nCrvId)
      If dArea < -1 Then EgtInvertCurve( nCrvId)
      ' Se curva chiusa, impongo inizio a metà del lato a X max
      If bClosed Then
         Dim b3Guide As New BBox3d
         EgtGetBBox( nCrvId, GDB_BB.STANDARD, b3Guide)
         Dim ptStart As New Point3d( b3Guide.Max().x, b3Guide.Center().y, b3Guide.Center().z)
         EgtChangeClosedCurveStartPoint(nCrvId, ptStart)
      End If
      Return True
   End Function

   Private Function ChangeCurveStartToX0(nCrvId As Integer) As Boolean
      Dim ptStart As Point3d : EgtStartPoint(nCrvId, ptStart)
      Dim dUs, dUe As Double
      EgtCurveDomain(nCrvId, dUs, dUe)
      Dim dU As Double = dUs
      While dU < dUe + EPS_ZERO
         Dim ptCurr As Point3d
         EgtAtParamPoint(nCrvId, dU, ptCurr)
         If Math.Abs(ptCurr.x) < Math.Abs(ptStart.x) Then
            ptStart = ptCurr
         End If
         dU += 1
      End While
      EgtChangeClosedCurveStartPoint(nCrvId, ptStart)
      If Math.Abs(ptStart.x) > EPS_SMALL Then
         EgtMove(nCrvId, New Vector3d(-ptStart.x, 0, 0))
      End If
      Return True
   End Function

   Private Function CreateLineFrame( nSectId As Integer, nSectLayId As Integer, nPartId As Integer) As Integer
      ' Porto la sezione nel piano opportuno e calcolo il vettore di estrusione
      Dim vtExtr As Vector3d
      If m_CurrAx = 0 Then
         ' Se lungo X nel piano YZ
         EgtChangeGroupFrame(nSectLayId, New Frame3d(Point3d.ORIG(), Frame3d.TYPE.LEFT))
         vtExtr = New Vector3d(m_RawBox.DimX() - 2 * m_dKerf, 0, 0)
      Else
         ' Se lungo Y nel piano XZ
         EgtChangeGroupFrame(nSectLayId, New Frame3d(Point3d.ORIG(), Frame3d.TYPE.FRONT))
         vtExtr = New Vector3d(0, m_RawBox.DimY() - 2 * m_dKerf, 0)
      End If
      ' Recupero layer per la linea guida
      Dim nGuideLayId As Integer = EgtGetFirstNameInGroup(nPartId, NAME_GUIDE)
      If nGuideLayId = GDB_ID.NULL Then
         nGuideLayId = EgtCreateGroup(nPartId, New Frame3d())
         EgtSetName(nGuideLayId, NAME_GUIDE)
      Else
         EgtEmptyGroup(nGuideLayId)
      End If
      EgtSetColor(nGuideLayId, COL_FRAME())
      ' Creo la linea guida
      Dim ptStart As Point3d
      EgtStartPoint(nSectId, nGuideLayId, ptStart)
      EgtCreateLine(nGuideLayId, ptStart, ptStart + vtExtr)
      ' Recupero layer per la superficie
      Dim nSurfLayId As Integer = EgtGetFirstNameInGroup(nPartId, NAME_SURF)
      If nSurfLayId = GDB_ID.NULL Then
         nSurfLayId = EgtCreateGroup(nPartId, New Frame3d())
         EgtSetName(nSurfLayId, NAME_SURF)
      Else
         EgtEmptyGroup(nSurfLayId)
      End If
      EgtSetColor(nSurfLayId, COL_FRAME())
      ' Creo la superficie di estrusione
      Dim nSectIds(0) As Integer
      nSectIds(0) = nSectId
      Dim nSurfId As Integer = EgtCreateSurfTmByRegionExtrusion(nSurfLayId, 1, nSectIds, vtExtr, EPS_STM, GDB_RT.GLOB)
      Return nSurfId
   End Function

   Private Function CreateArcFrame( nSectId As Integer, nSectLayId As Integer, nPartId As Integer) As Integer
      ' Recupero ingombro locale della sezione
      Dim b3Sect As New BBox3d
      EgtGetBBox(nSectId, GDB_BB.STANDARD, b3Sect)
      ' Differenza in Y sezione tra start e minimo della sezione
      Dim ptTmp As Point3d : EgtStartPoint(nSectId, nSectLayId, ptTmp)
      Dim dDiffY = ptTmp.y - b3Sect.Min().y
      ' Porto la sezione nel piano YZ
      EgtChangeGroupFrame(nSectLayId, New Frame3d(Point3d.ORIG(), Frame3d.TYPE.LEFT))
      ' Recupero o creo layer per la linea guida
      Dim nGuideLayId As Integer = EgtGetFirstNameInGroup(nPartId, NAME_GUIDE)
      If nGuideLayId = GDB_ID.NULL Then
         nGuideLayId = EgtCreateGroup(nPartId, New Frame3d())
         EgtSetName(nGuideLayId, NAME_GUIDE)
      Else
         EgtEmptyGroup(nGuideLayId)
      End If
      EgtSetColor(nGuideLayId, COL_FRAME())
      ' Creo la curva guida (per ora arco)
      Dim ptStart As Point3d : EgtStartPoint(nSectId, nGuideLayId, ptStart)
      ptStart.z -= dDiffY
      Dim dExtRad As Double = 0 : StringToLen(ArcRadTxBx.Text, dExtRad)
      Dim dRad As Double = dExtRad - b3Sect.DimX()
      If dRad < 10 * EPS_SMALL Then
         Return GDB_ID.NULL
      End If
      Dim dAngCenDeg As Double = 0 : StringToDouble(ArcAngTxBx.Text, dAngCenDeg)
      If dAngCenDeg > 360 Then dAngCenDeg = 360
      Dim dAngIniDeg As Double = If(dAngCenDeg < 180, -90 - dAngCenDeg / 2, -dAngCenDeg)
      Dim ptCen As Point3d = ptStart - Vector3d.FromPolar(dRad, dAngIniDeg)
      Dim nGuideId As Integer = EgtCreateArc(nGuideLayId, ptCen, dExtRad, dAngIniDeg, dAngCenDeg, 0)
      ' Recupero o creo layer per la superficie
      Dim nSurfLayId As Integer = EgtGetFirstNameInGroup(nPartId, NAME_SURF)
      If nSurfLayId = GDB_ID.NULL Then
         nSurfLayId = EgtCreateGroup(nPartId, New Frame3d())
         EgtSetName(nSurfLayId, NAME_SURF)
      Else
         EgtEmptyGroup(nSurfLayId)
      End If
      EgtSetColor(nSurfLayId, COL_FRAME())
      ' Creo la superficie swept
      Dim dSectRotDeg As Double = 90 + dAngIniDeg
      EgtRotate(nSectLayId, ptStart, Vector3d.Z_AX(), dSectRotDeg, GDB_RT.LOC)
      Dim nSurfId As Integer = EgtCreateSurfTmSwept( nSurfLayId, nSectId, nGuideId, True, EPS_STM)
      Return nSurfId
   End Function

   Private Function CreateCurveFrame( nSectId As Integer, nSectLayId As Integer, nGuideId As Integer, nGuideLayId As Integer, nPartId As Integer) As Integer
      ' Recupero flag lavorazione da lato opposto
      Dim bOthSide As Boolean = False
      EgtGetInfo( nPartId, INFO_FRAME_OTHSIDE, bOthSide)
      ' Recupero dati inizio guida
      Dim ptStart As Point3d
      EgtStartPoint(nGuideId, nPartId, ptStart)
      Dim vtStart As Vector3d
      EgtStartVector(nGuideId, nPartId, vtStart)
      ' Creo riferimento per sezione
      dim frSect As New Frame3d
      frSect.Setup( ptStart, -vtStart)
      ' Porto la sezione in questo riferimento
      EgtChangeGroupFrame(nSectLayId, frSect)
      ' Recupero ingombro locale della sezione
      Dim b3Sect As New BBox3d
      EgtGetBBox(nSectId, GDB_BB.STANDARD, b3Sect)
      ' Recupero ingombro locale della guida
      Dim b3Guide As New BBox3d
      EgtGetBBox( nGuideId, GDB_BB.STANDARD, b3Guide)
      b3Guide.ToLoc( frSect)
      ' Muovo sezione dalla parte interna della curva
      If ( Not bOthSide And Math.Abs( b3Guide.Min().x) > Math.Abs( b3Guide.Max().x))  OrElse
         ( bOthSide And Math.Abs( b3Guide.Min().x) <= Math.Abs( b3Guide.Max().x)) Then
         Dim vtMove As New Vector3d( - b3Sect.Max().x, -b3Sect.Min().y, 0)
         EgtMove( nSectId, vtMove)
      Else
         Dim vtMove As New Vector3d( - b3Sect.Min().x, -b3Sect.Min().y, 0)
         EgtMove( nSectId, vtMove)
      End If
      ' Recupero o creo layer per la superficie
      Dim nSurfLayId As Integer = EgtGetFirstNameInGroup(nPartId, NAME_SURF)
      If nSurfLayId = GDB_ID.NULL Then
         nSurfLayId = EgtCreateGroup(nPartId, New Frame3d())
         EgtSetName(nSurfLayId, NAME_SURF)
      Else
         EgtEmptyGroup(nSurfLayId)
      End If
      EgtSetColor(nSurfLayId, COL_FRAME())
      ' Creo la superficie swept
      Dim nSurfId As Integer = EgtCreateSurfTmSwept( nSurfLayId, nSectId, nGuideId, True, EPS_STM)
      Return nSurfId
   End Function

   Private Function InsertPartInRawPart(nPartId As Integer) As Boolean
      ' Determino ingombro del pezzo
      Dim PartBox As New BBox3d
      EgtGetBBoxGlob(nPartId, GDB_BB.EXACT + GDB_BB.IGNORE_TEXT + GDB_BB.IGNORE_DIM, PartBox)
      ' Determino ingombro di eventuali pezzi già presenti
      Dim OtherBox As New BBox3d
      Dim nId2 As Integer = EgtGetFirstPartInRawPart(m_nRawId)
      While nId2 <> GDB_ID.NULL
         Dim TmpBox As New BBox3d
         If EgtGetBBoxGlob(nId2, GDB_BB.EXACT + GDB_BB.IGNORE_TEXT + GDB_BB.IGNORE_DIM, TmpBox) Then
            OtherBox.Add(TmpBox)
         End If
         nId2 = EgtGetNextPartInRawPart(nId2)
      End While
      ' Determino distanza da spessore lama
      Dim dMinDist As Double = 0
      Dim dSawThick As Double = 0
      If EgtTdbSetCurrTool(m_MainWindow.m_CurrentMachine.sCurrSaw) AndAlso
         EgtTdbGetCurrToolParam(MCH_TP.THICK, dSawThick) Then
         dMinDist = dSawThick + 5 * EPS_SMALL
      Else
         EgtOutLog("Not found current saw for frames mindist")
         dMinDist = 0
      End If
      ' Inserisco il pezzo nel grezzo
      Dim ptIns As Point3d
      If OtherBox.IsEmpty() Then
         Dim dOffsXy As Double = 0
         StringToLen(OffsXyTxBx.Text, dOffsXy)
         Dim dOffsYy As Double = 0
         StringToLen(OffsYyTxBx.Text, dOffsYy)
         If m_CurrAx = 0 Then
            ptIns.x = m_dKerf
            ptIns.y = m_dKerf + dOffsXy
         ElseIf m_CurrAx = 1 Then
            ptIns.x = m_dKerf + dOffsXy
            ptIns.y = m_dKerf
         Else   ' 2 Or 3
            ptIns.x = m_dKerf + dOffsXy
            ptIns.y = m_dKerf + dOffsYy
         End If
      Else
         If m_CurrAx = 0 Then
            ptIns.x = m_dKerf
            ptIns.y = OtherBox.Max().y - m_RawBox.Min().y + dMinDist
         Else
            ptIns.x = OtherBox.Max().x - m_RawBox.Min().x + dMinDist
            ptIns.y = m_dKerf
         End If
      End If
      Dim dOffsZ As Double = 0
      StringToLen(OffsZTxBx.Text, dOffsZ)
      ptIns.z = (m_RawBox.Max().z - m_RawBox.Min().z) - (PartBox.Max().z - PartBox.Min().z) - dOffsZ
      ptIns.z = Math.Max(ptIns.z, 0)
      Return EgtAddPartToRawPart(nPartId, ptIns, EgtGetFirstRawPart())
   End Function

End Class
