Imports System.Globalization
Imports EgtUILib
Imports EgtWPFLib

Public Class RawPartPageUC

   ' Riferimento alla MainWindow
   Dim m_MainWindow As MainWindow = DirectCast(Application.Current.MainWindow, MainWindow)
   Dim WithEvents m_CurrProjPage As CurrentProjectPageUC
   Dim m_CurrentMachine As CurrentMachine = m_MainWindow.m_CurrentMachine
   ' Dichiarazione delle Page UserControl
   Friend m_MachineButtons As MachineButtonsUC
   ' Definizione pagina di scelta della lavorazione corrente
   Dim m_ChooseMachiningPage As ChooseMachining
   ' Flag di pagina attiva
   Private m_bActive As Boolean = False
   ' Tipo definizione rettangolo / per punti / laser / aree danneggiate
   Private m_ActiveRawMode As RAWMODE = RAWMODE.RECTANGLE
   ' Tipo definizione precedente alla scelta di "Zona rovinata"=> aree danneggiate
   Private m_PrecActiveRawMode As RAWMODE = m_ActiveRawMode
   ' Modalità operazione su punti grezzo
   Private m_nPtMode As PTMODE = PTMODE.MOVE
   ' Modalità operazione su punti aree danneggiate
   Private m_nPtDmgMode As DMGMODE = DMGMODE.NONE
   ' Dati per Drag
   Private m_bDrag As Boolean = False
   Private m_ptPrev As Point3d
   Private m_nDragEnt As Integer = -1
   Private m_dDragPar As Double = 0
   ' Colori standard
   Private m_RawCol As New Color3d(64, 192, 255, 40)
   Private m_KerfCol As New Color3d(255, 0, 0, 100)
   ' Dati tavola
   Private m_ptTableMin As Point3d
   Private m_dTableLength As Double = 0
   Private m_dTableWidth As Double = 0
   ' Dimensioni grezzo rettangolare
   Private m_RawLength As Double = 0
   Private m_RawWidth As Double = 0
   Private m_RawHeight As Double = 0
   Private m_RawOffsX As Double = 0
   Private m_RawOffsY As Double = 0
   Private m_RawKerf As Double = 0
   Private m_PrecKerf As Double = 0
   ' Layer per crocette temporanee
   Private m_nTempLay As Integer = GDB_ID.NULL
   ' Definizione lista modalità di definizione grezzo per ComboBox
   Private m_RawModeList(2) As String
   Private m_RawModeDamagedList(1) As String
   Private m_RawModeListEx(3) As String
   ' Variabile che indica la zona danneggiata selezionata
   Private m_nSelDmg As Integer
   ' Array per modalità per punti
   Private ByPointsModeArray As New List(Of StringIdCmBx)
   ' Id della curva composita Kerf definita con il laser
   Private m_nLaserKerfId As Integer = GDB_ID.NULL
   ' Primo punto acquisito
   Private m_bptLast As Boolean = False
   Private m_ptLast As Point3d = Point3d.ORIG
   ' Lista di linee che creeranno la curva composita Kerf
   Private m_CurveXKerfList As New List(Of Integer)
   ' Lista di linee che creerenno la curva composita DamagedArea
   Private m_CurveXDamagedAreaList As New List(Of Integer)
   ' Flag che indica se è in corso la definizione tramite laser o se il grezzo è già chiuso
   Private m_bIsRawDefiningByLaser As Boolean = False
   ' Flag di tastatura in corso
   Private m_bProbingOn As Boolean = False
   ' Flag inserimento punti laser da disegno
   Private m_bFromDraw As Boolean = True
   ' Flag abilitazione SlabId
   Private m_bSlabId As Boolean = False
   ' Costante minima dimensione del grezzo
   Private Const MIN_RAW_DIM As Double = 10
   ' Costante distanza di sicurezza del grezzo dal bordo
   Private Const SAFE_RAW_DIST As Double = 5
   ' Costante raggio cerchietto
   Private Const RAD_CIRCLE As Double = 30

   ' mostra la pagina delle lavorazioni
   Private m_SmartMachiningPage As Boolean = False

   ' Costanti modo operazione punti
   Private Enum PTMODE
      MOVE = 0
      ADD = 1
      REMOVE = 2
   End Enum
   ' Costanti modo operazione zone danneggiate
   Private Enum DMGMODE
      NONE = 0
      ADD = 1
      REMOVE = 2
   End Enum
   ' Costanti modalità di creazione grezzo
   Private Enum RAWMODE As Integer
      RECTANGLE = 0
      BY_POINTS = 1
      FROM_LASER = 2
      FROM_PHOTO = 3
      DAMAGED = 4
      DAMAGED_BY_LASER = 5
   End Enum

   Private Sub RawPartPage_Initialized(sender As Object, e As EventArgs)

      'Creazione della Page UserControl e relative impostazioni
      m_MachineButtons = New MachineButtonsUC(True)
      m_MachineButtons.SetValue(Grid.ColumnProperty, 1)
      Me.LowerButtonGrid.Children.Add(m_MachineButtons)

      ' Associazione della lista materiali alla combobox
      MaterialsCmbx.ItemsSource = m_CurrentMachine.Materials

      ' Associazione tag textbox e label per visualizzare nome nella calcolatrice
      LengthTxBx.Tag = LengthTxBl
      WidthTxBx.Tag = WidthTxBl
      HeightTxBx.Tag = HeightTxBl
      OffsetXTxBx.Tag = OffsetXTxBl
      OffsetYTxBx.Tag = OffsetYTxBl
      KerfTxBx.Tag = KerfTxBl

      ' Creo lista modalità di definizione del grezzo
      m_RawModeList(0) = EgtMsg(MSG_RAWPARTPAGEUC + 1)           'Rettangolo
      m_RawModeList(1) = EgtMsg(MSG_RAWPARTPAGEUC + 2)           'Per Punti
      m_RawModeList(2) = EgtMsg(MSG_RAWPARTPAGEUC + 30)          'Da Laser
      m_RawModeListEx(0) = EgtMsg(MSG_RAWPARTPAGEUC + 1)         'Rettangolo
      m_RawModeListEx(1) = EgtMsg(MSG_RAWPARTPAGEUC + 2)         'Per Punti
      m_RawModeListEx(2) = EgtMsg(MSG_RAWPARTPAGEUC + 30)        'Da Laser
      m_RawModeListEx(3) = EgtMsg(MSG_RAWPARTPAGEUC + 35)        'Da Fotografia
      RawModeCmBx.ItemsSource = m_RawModeList
      ' lista per selezione RawModeDamaged
      m_RawModeDamagedList(0) = EgtMsg(MSG_RAWPARTPAGEUC + 2)    'Per Punti
      m_RawModeDamagedList(1) = EgtMsg(MSG_RAWPARTPAGEUC + 30)   'Da Laser
      RawModeDamagedCmBx.ItemsSource = m_RawModeDamagedList

      ' Nascondo bottone tastatura lastra se disattivato da file .ini
      RawProbingBtn.Visibility = If(m_CurrentMachine.bHasRawProbe, Windows.Visibility.Visible, Windows.Visibility.Collapsed)
      ' Nascondo bottone lettura codice a barre se non attivato da file .ini
      BarCodeBtn.Visibility = If(m_CurrentMachine.bHasRawBarCodeReader, Windows.Visibility.Visible, Windows.Visibility.Collapsed)
      ' Nascondo bottone dati lastra se non attivato da file .ini
      m_bSlabId = (Not m_CurrentMachine.bHasRawBarCodeReader And
                   GetPrivateProfileInt(S_RAWPART, K_SLABID, 0, m_MainWindow.GetIniFile()) <> 0)
      SlabIdBtn.Visibility = If(m_bSlabId, Windows.Visibility.Visible, Windows.Visibility.Collapsed)

      m_SmartMachiningPage = GetPrivateProfileInt(S_GENERAL, K_SMARTMACHININGPAGE, 0, m_MainWindow.GetIniFile()) <> 0

      ' Imposto i messaggi letti dal file dei messaggi
      OutlineBtn.Content = EgtMsg(MSG_RAWPARTPAGEUC + 33)       'Rectangle - Rettangolo
      DamagedBtn.Content = EgtMsg(MSG_RAWPARTPAGEUC + 10)       'By points - Per punti
      LengthTxBl.Text = EgtMsg(MSG_RAWPARTPAGEUC + 3)           'Length - Lunghezza
      WidthTxBl.Text = EgtMsg(MSG_RAWPARTPAGEUC + 4)            'Width - Larghezza
      HeightTxBl.Text = EgtMsg(MSG_RAWPARTPAGEUC + 5)           'Height - Spessore
      OffsetXTxBl.Text = EgtMsg(MSG_RAWPARTPAGEUC + 6)          'Offset X
      OffsetYTxBl.Text = EgtMsg(MSG_RAWPARTPAGEUC + 7)          'Offset Y
      KerfTxBl.Text = EgtMsg(MSG_RAWPARTPAGEUC + 8)             'Kerf
      MaterialGpBx.Header = EgtMsg(MSG_RAWPARTPAGEUC + 9)       'Material - Materiale
      DamagedAreaGpBx.Header = EgtMsg(MSG_RAWPARTPAGEUC + 10)   'Damaged area - Zona rovinata
      NewBtn.Content = EgtMsg(MSG_RAWPARTPAGEUC + 11)           'New - Nuovo
      DeleteBtn.Content = EgtMsg(MSG_RAWPARTPAGEUC + 12)        'Delete - Cancella
      PointsGpBx.Header = EgtMsg(MSG_RAWPARTPAGEUC + 13)        'Points - Punti
      AddBtn.Content = EgtMsg(MSG_RAWPARTPAGEUC + 14)           'Add - Aggiungi
      RemoveBtn.Content = EgtMsg(MSG_RAWPARTPAGEUC + 15)        'Remove - Rimuovi
      CloseBtn.Content = EgtMsg(MSG_RAWPARTPAGEUC + 31)         'Close - Chiudi
      ConfirmPhotoBtn.Content = EgtMsg(MSG_RAWPARTPAGEUC + 24)  'Conferma
   End Sub

   Private Sub RawPartPage_Loaded(sender As Object, e As RoutedEventArgs)
      ' aggiorno la lista dei materiali
      Dim Index As Integer = 1
      If m_CurrentMachine.bWaterJet And m_CurrentMachine.bFromDBWaterJet Then
         m_CurrentMachine.LoadWJMaterial()
      End If

      m_CurrProjPage = m_MainWindow.m_CurrentProjectPageUC
      m_bActive = True
      ' Assegno modalità acquisizione punti laser (da disegno se non collegato alla macchina)
      m_bFromDraw = (m_MainWindow.m_CNCommunication.m_nNCType = 0)
      ' Correggo differenza tra machinebuttons che ha 10 colonne e spazio disponibile solo per 9 facendolo sbordare(non si vede perchè la parte che avanza è vuota)
      m_MachineButtons.Width = LowerButtonGrid.ActualWidth / 12 * 10
      ' Se disponibile, imposto possibilità di contorno da foto
      If m_CurrProjPage.GetContour() = GDB_ID.NULL Then
         RawModeCmBx.ItemsSource = m_RawModeList
      Else
         RawModeCmBx.ItemsSource = m_RawModeListEx
      End If
      ' Colori standard
      GetPrivateProfileColor(S_RAWPART, K_RAWCOLOR, m_RawCol, m_MainWindow.GetIniFile())
      GetPrivateProfileColor(S_RAWPART, K_KERFCOLOR, m_KerfCol, m_MainWindow.GetIniFile())
      ' Dimensioni tavola
      Dim ptMin, ptMax As Point3d
      If EgtGetTableArea(1, ptMin, ptMax) Then
         m_ptTableMin = ptMin
         m_dTableLength = ptMax.x - ptMin.x
         m_dTableWidth = ptMax.y - ptMin.y
      End If
      ' Origine tavola
      Dim ptRef1 As Point3d
      If EgtGetTableRef(1, ptRef1) Then
         If Not Point3d.SameApprox(m_ptTableMin, ptRef1) Then
            EgtOutLog("Error : TableMin e TableRef1 are different")
         End If
      End If
      ' Nascondo eventuali pezzi in parcheggio
      HideParkedParts()
      ' Deseleziono pezzi
      EgtDeselectAll()
      VeinMatching.OnDeselectAll()
      ' Visualizzo eventuale foto
      m_MainWindow.m_CurrentProjectPageUC.ShowPhoto(True)
      Dim bHeightModified As Boolean = False
      ' Se esiste già il grezzo...
      Dim ptRawMin, ptRawMax As Point3d
      Dim dInvertKerf As Double = 1
      If GetRawBox(ptRawMin, ptRawMax) Then
         ' kerf
         EgtGetInfo(EgtGetFirstRawPart(), KEY_KERF, m_RawKerf)
         ' verifico se il kerf è negativo
         EgtGetInfo(EgtGetFirstRawPart(), KEY_INVERT_KERF, dInvertKerf)
         ' aggiorno dati grezzo
         If dInvertKerf < 0 Then
            m_RawLength = ptRawMax.x - ptRawMin.x
            m_RawWidth = ptRawMax.y - ptRawMin.y
            m_RawHeight = ptRawMax.z - ptRawMin.z
            m_RawOffsX = ptRawMin.x - m_ptTableMin.x
            m_RawOffsY = ptRawMin.y - m_ptTableMin.y
         Else
            m_RawLength = ptRawMax.x - ptRawMin.x - 2 * m_RawKerf * dInvertKerf
            m_RawWidth = ptRawMax.y - ptRawMin.y - 2 * m_RawKerf * dInvertKerf
            m_RawHeight = ptRawMax.z - ptRawMin.z
            m_RawOffsX = ptRawMin.x - m_ptTableMin.x + m_RawKerf * dInvertKerf
            m_RawOffsY = ptRawMin.y - m_ptTableMin.y + m_RawKerf * dInvertKerf
         End If
         ' aggiorno l'apparenza del grezzo
         AdjustRawPartOnStart()
         ' Altrimenti lo definisco
      Else
         ' Leggo da Ini gli ultimi valori
         m_RawLength = GetPrivateProfileDouble(S_RAWPART, K_RAWLENGTH, 2500, m_MainWindow.GetIniFile())
         m_RawWidth = GetPrivateProfileDouble(S_RAWPART, K_RAWWIDTH, 1500, m_MainWindow.GetIniFile())
         m_RawHeight = GetPrivateProfileDouble(S_RAWPART, K_RAWHEIGHT, 30, m_MainWindow.GetIniFile())
         m_RawOffsX = GetPrivateProfileDouble(S_RAWPART, K_RAWOFFSX, 100, m_MainWindow.GetIniFile())
         m_RawOffsY = GetPrivateProfileDouble(S_RAWPART, K_RAWOFFSY, 100, m_MainWindow.GetIniFile())
         m_RawKerf = GetPrivateProfileDouble(S_RAWPART, K_RAWKERF, 50, m_MainWindow.GetIniFile())
         m_PrecKerf = m_RawKerf
         ' Richiedo ricalcolo quota eventuale foto
         UpdateRawPart(True)
         ' Eventuale gestione dati lastra
         If m_bSlabId Then
            Dim sBlock As String = ""
            GetPrivateProfileString(S_RAWPART, K_BLOCKNAME, "", sBlock, m_MainWindow.GetIniFile())
            Dim nSlabNbr As Integer = GetPrivateProfileInt(S_RAWPART, K_SLABNBR, 0, m_MainWindow.GetIniFile())
            nSlabNbr += 1
            Dim sSlabNbr As String = nSlabNbr.ToString()
            WritePrivateProfileString(S_RAWPART, K_SLABNBR, sSlabNbr, m_MainWindow.GetIniFile())
            Utility.SetBlockAndSlabNbr(sBlock, sSlabNbr)
         End If
      End If
      ' Assegno dati grezzo rettangolare ai textbox
      LengthTxBx.Text = LenToString(m_RawLength, 2)
      WidthTxBx.Text = LenToString(m_RawWidth, 2)
      HeightTxBx.Text = LenToString(m_RawHeight, 3)
      OffsetXTxBx.Text = LenToString(m_RawOffsX, 2)
      OffsetYTxBx.Text = LenToString(m_RawOffsY, 2)
      KerfTxBx.Text = LenToString(dInvertKerf * m_RawKerf, 2)
      ' Creo layer temporaneo per crocette
      m_nTempLay = EgtCreateGroup(GDB_ID.ROOT)
      EgtSetLevel(m_nTempLay, GDB_LV.TEMP)
      ' Determino modalità di definizione
      OutlineBtn.IsChecked = True
      If EgtExistsInfo(m_CurrProjPage.m_nRawId, KEY_RAWBYPOINTS) Then
         RawModeCmBx.SelectedIndex = RAWMODE.BY_POINTS
         PointsGpBx.Visibility = Windows.Visibility.Visible
         CloseBtn.Visibility = Windows.Visibility.Hidden
         ' Visualizzo crocette
         UpdateCircles()
         EgtZoom(ZM.ALL)
      Else
         m_ActiveRawMode = RAWMODE.RECTANGLE
         RawModeCmBx.SelectedIndex = RAWMODE.RECTANGLE
         PointsGpBx.Visibility = Windows.Visibility.Hidden
         If dInvertKerf < 1 Then
            AdjustRawPartPositionNegativeKerf()
            ' assegno il giosto colore al kerf
            Dim nKerfId As Integer = EgtGetFirstNameInGroup(m_CurrProjPage.m_nRawId, NAME_KERF)
            EgtSetColor(nKerfId, m_KerfCol)
         Else
            AdjustRawPartPosition()
         End If
         EgtZoom(ZM.ALL)
      End If
      'Imposto il materiale corrente nella combobox
      'MaterialsCmbx.SelectedItem = m_CurrentMachine.CurrMat
      Dim Item As Material
      For Each Item In MaterialsCmbx.Items
         If Not IsNothing(m_CurrentMachine.CurrMat) AndAlso Item.sName = m_CurrentMachine.CurrMat.sName Then
            MaterialsCmbx.SelectedItem = Item
         End If
      Next
   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 cosa selezionato
      Dim nSolidId = EgtGetFirstNameInGroup(m_CurrProjPage.m_nRawId, NAME_RAW_SOLID)
      Dim nKerfId = EgtGetFirstNameInGroup(m_CurrProjPage.m_nRawId, NAME_KERF)
      '----------------------------------------- INIZIO ------------------ se decido di inserire i punti laser manualmente --------------------------------------------------
      ' se decido di inserire i punti laser manualmente
      If m_bFromDraw And m_ActiveRawMode = RAWMODE.FROM_LASER Or m_ActiveRawMode = RAWMODE.DAMAGED_BY_LASER Then
         ' Rimuovo eventuali crocette create acquisendo i punti nel disegno
         EgtEmptyGroup(m_nTempLay)
         ' Acquisisco punto da disegno
         EgtUnProjectPoint(e.Location, m_ptPrev)
         ' Aggiusto Z punto acquisito (è in globale)
         Dim dPtPrevZ As Double = m_ptPrev.z
         Dim ptRawMin, ptRawMax As Point3d
         GetRawBox(ptRawMin, ptRawMax)
         m_ptPrev.z = ptRawMax.z
         ' Se direzione di vista calcolabile e da sopra posso aggiustare anche XY
         Dim dAngVertDeg, dAngHorizDeg As Double
         If EgtGetGenericView(dAngVertDeg, dAngHorizDeg) Then
            Dim vtDir As Vector3d = Vector3d.FromSpherical(1, dAngVertDeg, dAngHorizDeg)
            If vtDir.z > EPS_SMALL Then
               m_ptPrev.z = dPtPrevZ
               m_ptPrev += vtDir * (ptRawMax.z - m_ptPrev.z) / vtDir.z
            End If
         End If
         ' Disegno crocetta che indica il punto acquisito
         CreateCross(m_nTempLay, m_ptPrev)
         EgtDraw()
         Return
      End If
      '-----------------------------------------  FINE  ------------------ se decido di inserire i punti laser manualmente --------------------------------------------------
      EgtSetObjFilterForSelWin(True, True, True, True, True)
      Dim nSel As Integer
      EgtSelect(e.Location, 2 * Scene.DIM_SEL, 2 * Scene.DIM_SEL, nSel)
      ' Ricavo nome dell'entità selezionata e identificativo
      Dim nSelId As Integer = EgtGetFirstObjInSelWin()
      Dim sName As String = String.Empty
      While nSelId <> GDB_ID.NULL
         sName = String.Empty
         EgtGetName(nSelId, sName)
         If sName = NAME_RAW_SOLID Then
            m_bDrag = EgtUnProjectPoint(e.Location, m_ptPrev)
            m_nDragEnt = -1
            m_dDragPar = -1
         ElseIf sName = NAME_KERF And
                (m_ActiveRawMode = RAWMODE.RECTANGLE Or m_ActiveRawMode = RAWMODE.BY_POINTS) Then
            m_bDrag = EgtUnProjectPoint(e.Location, m_ptPrev)
            Dim dDist, dU As Double
            If Not EgtPointCurveDist(m_ptPrev.Loc(nKerfId), nKerfId, nKerfId, dDist, dU) Then
               m_bDrag = False
            End If
            m_nDragEnt = CInt(Math.Ceiling(dU))
            m_dDragPar = dU
            ' Privilegio il kerf, pertanto esco
            Exit While
         ElseIf sName = NAME_DAMAGED And (m_ActiveRawMode = RAWMODE.DAMAGED Or m_ActiveRawMode = RAWMODE.DAMAGED_BY_LASER) Then
            m_bDrag = EgtUnProjectPoint(e.Location, m_ptPrev)
            Dim dDist, dU As Double
            If Not EgtPointCurveDist(m_ptPrev.Loc(nSelId), nSelId, nSelId, dDist, dU) Then
               m_bDrag = False
            End If
            m_nDragEnt = CInt(Math.Ceiling(dU))
            m_dDragPar = dU
            m_nSelDmg = nSelId
            ' Aggiorno cerchi
            UpdateCircles()
            EgtDraw()
            ' Privilegio l'area danneggiata, pertanto esco
            Exit While
         End If
         nSelId = EgtGetNextObjInSelWin()
      End While
      ' se drag e modalità punti
      If m_bDrag And m_ActiveRawMode = RAWMODE.BY_POINTS Then
         ' se aggiungi punto
         If m_nPtMode = PTMODE.ADD Then
            If EgtAddCurveCompoJoint(nKerfId, m_dDragPar) Then m_dDragPar = Math.Ceiling(m_dDragPar)
            ' il grezzo non è cambiato, perchè il nuovo punto è sulla vecchia linea
            AddBtn.IsChecked = False
            m_nPtMode = PTMODE.MOVE
            ' Aggiorno cerchi
            UpdateCircles()
            EgtDraw()
            ' altrimenti
         Else
            '  verifico di essere abbastanza vicino ad un estremo
            Dim ptJoint As Point3d
            If Not EgtAtParamPoint(nKerfId, Math.Round(m_dDragPar), GDB_ID.ROOT, ptJoint) OrElse
               Point3d.SqDistXY(ptJoint, m_ptPrev) > RAD_CIRCLE * RAD_CIRCLE Then
               m_bDrag = False
            End If
            ' se rimuovi
            If m_bDrag And m_nPtMode = PTMODE.REMOVE Then
               ' ci devono essere almeno 4 punti
               If EgtGetCurveCompoJointCount(nKerfId) >= 4 Then
                  EgtRemoveCurveCompoJoint(nKerfId, CInt(m_dDragPar))
                  ' Aggiorno il solido del grezzo, l'ingombro e la posizione
                  UpdateRawPartKerf()
                  ' Aggiorno cerchi
                  UpdateCircles()
                  EgtDraw()
               End If
               RemoveBtn.IsChecked = False
               m_nPtMode = PTMODE.MOVE
               m_bDrag = False
            End If
         End If
         ' se drag e modalità zona danneggiata
      ElseIf m_bDrag And (m_ActiveRawMode = RAWMODE.DAMAGED Or m_ActiveRawMode = RAWMODE.DAMAGED_BY_LASER) Then
         ' se aggiungi zona rovinata
         If m_nPtDmgMode = DMGMODE.ADD Then
            AddNewDamagedArea()
            ' Aggiorno cerchi
            UpdateCircles()
            EgtDraw()
            ' se rimuovi zona rovinata
         ElseIf m_nPtDmgMode = DMGMODE.REMOVE Then
            ' Verifico di essere sulla zona danneggiata
            Dim ptNear As Point3d
            If EgtAtParamPoint(m_nSelDmg, m_dDragPar, GDB_ID.ROOT, ptNear) And
               Point3d.SqDistXY(ptNear, m_ptPrev) <= RAD_CIRCLE * RAD_CIRCLE Then
               RemoveDamagedArea()
            End If
            ' Aggiorno cerchi
            UpdateCircles()
            EgtDraw()
            ' altrimenti eventuali operazioni di punto
         Else
            ' se aggiungi punto
            If m_nPtMode = PTMODE.ADD Then
               If EgtAddCurveCompoJoint(m_nSelDmg, m_dDragPar) Then m_dDragPar = Math.Ceiling(m_dDragPar)
               ' il grezzo non è cambiato, perchè il nuovo punto è sulla vecchia linea
               AddBtn.IsChecked = False
               m_nPtMode = PTMODE.MOVE
               ' Aggiorno cerchi
               UpdateCircles()
               EgtDraw()
               ' altrimenti
            Else
               '  verifico di essere abbastanza vicino ad un estremo
               Dim ptJoint As Point3d
               If Not EgtAtParamPoint(m_nSelDmg, Math.Round(m_dDragPar), GDB_ID.ROOT, ptJoint) OrElse
                  Point3d.SqDistXY(ptJoint, m_ptPrev) > RAD_CIRCLE * RAD_CIRCLE Then
                  m_bDrag = False
               End If
               ' se rimuovi
               If m_bDrag And m_nPtMode = PTMODE.REMOVE Then
                  ' ci devono essere almeno 4 punti
                  If EgtGetCurveCompoJointCount(m_nSelDmg) >= 4 Then
                     EgtRemoveCurveCompoJoint(m_nSelDmg, CInt(m_dDragPar))
                     ' aggiorno il solido del grezzo, l'ingombro e la posizione
                     UpdateRawPartKerf()
                     ' Aggiorno cerchi
                     UpdateCircles()
                     EgtDraw()
                  End If
                  RemoveBtn.IsChecked = False
                  m_nPtMode = PTMODE.MOVE
                  m_bDrag = False
               End If
            End If
         End If
      End If
   End Sub

   Private Sub OnMyMouseMoveScene(sender As Object, e As System.Windows.Forms.MouseEventArgs) Handles m_CurrProjPage.OnMouseMoveScene
      ' Verifico di essere il gestore attivo
      If Not m_bActive Then Return
      ' Verifico di essere in modalità drag
      If Not m_bDrag Then Return
      ' Ricavo il punto corrente in coordinate mondo
      Dim ptCurr As Point3d
      EgtUnProjectPoint(e.Location, ptCurr)
      ' Eseguo modifica
      Select Case m_ActiveRawMode
         Case RAWMODE.RECTANGLE
            ModifyRectangle(ptCurr)
         Case RAWMODE.BY_POINTS
            ModifyGeneric(ptCurr)
         Case RAWMODE.DAMAGED
            ModifyDamaged(ptCurr)
      End Select
      ' Aggiorno il punto precedente
      m_ptPrev = ptCurr
   End Sub

   Private Sub ModifyRectangle(ptCurr As Point3d)
      Dim dKerf As Double = 0
      StringToLen(KerfTxBx.Text, dKerf)
      ' Se movimento del grezzo
      If m_nDragEnt = -1 Then
         ' Ricavo il vettore di movimento (tengo solo XY)
         Dim vtMove As Vector3d = ptCurr - m_ptPrev
         vtMove.z = 0
         ' Muovo il grezzo
         If EgtMoveRawPart(m_CurrProjPage.m_nRawId, vtMove) Then
            EgtDraw()
            ' Aggiorno gli offset
            m_RawOffsX += vtMove.x
            m_RawOffsY += vtMove.y
            If dKerf < 0 Then
               OffsetXTxBx.Text = LenToString(m_RawOffsX - m_RawKerf, 2)
               OffsetYTxBx.Text = LenToString(m_RawOffsY - m_RawKerf, 2)
            Else
               OffsetXTxBx.Text = LenToString(m_RawOffsX, 2)
               OffsetYTxBx.Text = LenToString(m_RawOffsY, 2)
            End If

         End If
         ' se sposto lato sotto
      ElseIf m_nDragEnt = 1 Then
         Dim dDelta = ptCurr.y - m_ptPrev.y
         If m_RawWidth - dDelta > MIN_RAW_DIM And m_RawOffsY + dDelta > m_RawKerf Then
            m_RawWidth -= dDelta
            m_RawOffsY += dDelta
            EgtModifyRawPartSize(m_CurrProjPage.m_nRawId, m_RawLength + 2 * m_RawKerf,
                                 m_RawWidth + 2 * m_RawKerf, m_RawHeight)
            AdjustRawPartKerf()
            Dim vtMove As New Vector3d(0, dDelta, 0)
            EgtMoveRawPart(m_CurrProjPage.m_nRawId, vtMove)
            EgtDraw()
            If dKerf < 0 Then
               WidthTxBx.Text = LenToString(m_RawWidth + 2 * m_RawKerf, 2)
               OffsetYTxBx.Text = LenToString(m_RawOffsY - m_RawKerf, 2)
            Else
               WidthTxBx.Text = LenToString(m_RawWidth, 2)
               OffsetYTxBx.Text = LenToString(m_RawOffsY, 2)
            End If

         End If
         ' se sposto lato a destra
      ElseIf m_nDragEnt = 2 Then
         Dim dDelta = ptCurr.x - m_ptPrev.x
         If m_RawLength + dDelta > MIN_RAW_DIM And
            m_RawOffsX + m_RawLength + dDelta + m_RawKerf < m_dTableLength Then
            m_RawLength += dDelta
            EgtModifyRawPartSize(m_CurrProjPage.m_nRawId, m_RawLength + 2 * m_RawKerf,
                                 m_RawWidth + 2 * m_RawKerf, m_RawHeight)
            AdjustRawPartKerf()
            EgtDraw()
            If dKerf < 0 Then
               LengthTxBx.Text = LenToString(m_RawLength + 2 * m_RawKerf, 2)
            Else
               LengthTxBx.Text = LenToString(m_RawLength, 2)
            End If

         End If
         ' se sposto lato sopra
      ElseIf m_nDragEnt = 3 Then
         Dim dDelta = ptCurr.y - m_ptPrev.y
         If m_RawWidth + dDelta > MIN_RAW_DIM And
            m_RawOffsY + m_RawWidth + dDelta + m_RawKerf < m_dTableWidth Then
            m_RawWidth += dDelta
            EgtModifyRawPartSize(m_CurrProjPage.m_nRawId, m_RawLength + 2 * m_RawKerf,
                                 m_RawWidth + 2 * m_RawKerf, m_RawHeight)
            AdjustRawPartKerf()
            EgtDraw()
            If dKerf < 0 Then
               WidthTxBx.Text = LenToString(m_RawWidth + 2 * m_RawKerf, 2)
            Else
               WidthTxBx.Text = LenToString(m_RawWidth, 2)
            End If

         End If
         ' se sposto lato a sinistra
      ElseIf m_nDragEnt = 4 Then
         Dim dDelta = ptCurr.x - m_ptPrev.x
         If m_RawLength - dDelta > MIN_RAW_DIM And m_RawOffsX + dDelta > m_RawKerf Then
            m_RawLength -= dDelta
            m_RawOffsX += dDelta
            EgtModifyRawPartSize(m_CurrProjPage.m_nRawId, m_RawLength + 2 * m_RawKerf,
                                 m_RawWidth + 2 * m_RawKerf, m_RawHeight)
            AdjustRawPartKerf()
            Dim vtMove As New Vector3d(dDelta, 0, 0)
            EgtMoveRawPart(m_CurrProjPage.m_nRawId, vtMove)
            EgtDraw()
            If dKerf < 0 Then
               LengthTxBx.Text = LenToString(m_RawLength + 2 * m_RawKerf, 2)
               OffsetXTxBx.Text = LenToString(m_RawOffsX - m_RawKerf, 2)

            Else
               LengthTxBx.Text = LenToString(m_RawLength, 2)
               OffsetXTxBx.Text = LenToString(m_RawOffsX, 2)

            End If
         End If
      End If
   End Sub

   Private Sub ModifyGeneric(ptCurr As Point3d)
      ' Se non selezionata entità del kerf, esco
      If m_nDragEnt = -1 Then Return
      ' Limito il punto a stare nella tavola con franco pari al kerf
      If ptCurr.x < m_ptTableMin.x + m_RawKerf Then ptCurr.x = m_ptTableMin.x + m_RawKerf + SAFE_RAW_DIST
      If ptCurr.y < m_ptTableMin.y + m_RawKerf Then ptCurr.y = m_ptTableMin.y + m_RawKerf + SAFE_RAW_DIST
      If ptCurr.x > m_ptTableMin.x + m_dTableLength - m_RawKerf Then ptCurr.x = m_ptTableMin.x + m_dTableLength - m_RawKerf - SAFE_RAW_DIST
      If ptCurr.y > m_ptTableMin.y + m_dTableWidth - m_RawKerf Then ptCurr.y = m_ptTableMin.y + m_dTableWidth - m_RawKerf - SAFE_RAW_DIST
      ' Identificativo curva di kerf
      Dim nKerfId = EgtGetFirstNameInGroup(m_CurrProjPage.m_nRawId, NAME_KERF)
      ' Identifico il punto
      Dim nU As Integer = CInt(m_dDragPar)
      ' Aggiusto Z punto movimentato (è in globale)
      ptCurr.z = m_ptTableMin.z + m_CurrentMachine.dAdditionalTable + m_RawHeight
      ' Sposto il punto
      If Not EgtModifyCurveCompoJoint(nKerfId, nU, ptCurr, GDB_RT.GLOB) Then Return
      ' Aggiorno il grezzo, l'ingombro e la posizione
      UpdateRawPartKerf()
      ' Salvo il valore del kerf (sempre in mm)
      EgtSetInfo(m_CurrProjPage.m_nRawId, KEY_KERF, m_RawKerf)
      ' Aggiorno cerchi
      UpdateCircles()
      ' Aggiorno visualizzazione
      EgtDraw()
   End Sub

   Private Sub ModifyDamaged(ptCurr As Point3d)
      ' Se non selezionata entità, esco
      If m_nDragEnt = -1 Then Return
      ' Recupero Id kerf
      Dim nKerfId As Integer = EgtGetFirstNameInGroup(m_CurrProjPage.m_nRawId, NAME_KERF)
      ' Limito il punto a stare nel kerf
      Dim ptLocCurr As Point3d = ptCurr.Loc(nKerfId)
      Dim dMinDist As Double
      Dim ptLocMin As Point3d
      Dim nSide As Integer
      If EgtPointCurveDistSide(ptLocCurr, nKerfId, Vector3d.Z_AX, nKerfId, dMinDist, ptLocMin, nSide) And nSide = +1 Then
         ptCurr = ptLocMin.Glob(nKerfId)
      End If
      ' Identifico il punto
      Dim nU As Integer = CInt(m_dDragPar)
      ' Aggiusto Z punto movimentato (è in globale)
      ptCurr.z = m_ptTableMin.z + m_CurrentMachine.dAdditionalTable + m_RawHeight
      ' Sposto il punto
      If Not EgtModifyCurveCompoJoint(m_nSelDmg, nU, ptCurr, GDB_RT.GLOB) Then Return
      ' Aggiorno cerchi
      UpdateCircles()
      ' Aggiorno visualizzazione
      EgtDraw()
   End Sub

   Private Sub OnMyMouseUpScene(sender As Object, e As System.Windows.Forms.MouseEventArgs) Handles m_CurrProjPage.OnMouseUpScene
      ' Verifico di essere il gestore attivo
      If Not m_bActive Then Return
      ' Disabilito modalità drag
      m_bDrag = False
   End Sub

   Private Sub MaterialsCmbx_SelectionChanged(sender As Object, e As SelectionChangedEventArgs) Handles MaterialsCmbx.SelectionChanged
      If Not IsNothing(MaterialsCmbx.SelectedItem) Then
         m_CurrentMachine.CurrMat = DirectCast(MaterialsCmbx.SelectedItem, Material)
         m_CurrProjPage.MaterialTxBx.Text = m_CurrentMachine.CurrMat.sName
      Else
         m_CurrentMachine.CurrMat = Nothing
         m_CurrProjPage.MaterialTxBx.Text = "Non definito"
      End If
   End Sub

   Private Sub OkBtn_Click(sender As Object, e As RoutedEventArgs) Handles OkBtn.Click
      ' Non è possibile uscire con tastatura in corso
      If m_bProbingOn Then Return
      ' Se confermata uscita
      If ExitRawPart(True) Then
         m_MainWindow.m_CurrentProjectPageUC.CurrentProjectPageGrid.Children.Remove(Me)
         m_CurrProjPage.CurrProjGrid.Visibility = Windows.Visibility.Visible
         If m_MainWindow.m_PrevActivePage = MainWindow.Pages.CadCut Then
            m_MainWindow.m_CurrentProjectPageUC.CurrentProjectPageGrid.Children.Add(m_MainWindow.m_CadCutPageUC)
            m_MainWindow.m_ActivePage = MainWindow.Pages.CadCut
         ElseIf m_MainWindow.m_PrevActivePage = MainWindow.Pages.DirectCut Then
            m_MainWindow.m_CurrentProjectPageUC.CurrentProjectPageGrid.Children.Add(m_MainWindow.m_DirectCutPageUC)
            m_MainWindow.m_ActivePage = MainWindow.Pages.DirectCut
         ElseIf m_MainWindow.m_PrevActivePage = MainWindow.Pages.FrameCut Then
            m_MainWindow.m_CurrentProjectPageUC.CurrentProjectPageGrid.Children.Add(m_MainWindow.m_FrameCutPageUC)
            m_MainWindow.m_ActivePage = MainWindow.Pages.FrameCut
         End If
         m_MainWindow.m_PrevActivePage = MainWindow.Pages.RawPart
      End If
   End Sub

   Friend Function ExitRawPart(bAskMachining As Boolean) As Boolean
      m_CurrProjPage.m_SceneButtons.MeasureBtn.IsChecked = False
      ' Sistemo grezzo da punti con laser macchina
      If m_ActiveRawMode = RAWMODE.FROM_LASER Then
         If m_bIsRawDefiningByLaser Then
            CloseRawByLaser()
         End If
      End If
      If m_ActiveRawMode = RAWMODE.DAMAGED_BY_LASER Then
         If m_bIsRawDefiningByLaser Then
            CloseDamagedAreaByLaser()
         End If
      End If
      ' Apro pagina di selezione della lavorazione prima di chiudere il grezzo
      m_ChooseMachiningPage = New ChooseMachining(m_MainWindow)
      '--------------------------- SELEZIONE LAVORAZIONI ---------------------------------
      ' mostro la finestra di selezione delle lavorazioni
      If m_ChooseMachiningPage.MachIsModified OrElse Not m_SmartMachiningPage Then
         m_ChooseMachiningPage.ShowDialog()
         '--------------------------- SELEZIONE LAVORAZIONI ---------------------------------
         If m_ChooseMachiningPage.DialogResult Then
            Return AdjustRawPartInCurrProject()
         Else
            Return False
         End If
      Else
         Return AdjustRawPartInCurrProject()
      End If
      ' forzo l'uscita dalla pagina
      Return True
   End Function

   Private Function AdjustRawPartInCurrProject() As Boolean
      ' Sistemo il grezzo
      AdjustRawPartOnExit()
      ' Imposto spessore del grezzo
      m_CurrProjPage.m_dRawHeight = GetRawHeight()
      m_CurrProjPage.UpdateHeightTxBx()
      ' Aggiorno lavorazione in interfaccia
      m_CurrProjPage.UpdateMachiningTxBx()
      ' Salvo nel file Ini le dimensioni del grezzo (sempre in mm)
      WritePrivateProfileString(S_RAWPART, K_RAWLENGTH, DoubleToString(m_RawLength, 2), m_MainWindow.GetIniFile())
      WritePrivateProfileString(S_RAWPART, K_RAWWIDTH, DoubleToString(m_RawWidth, 2), m_MainWindow.GetIniFile())
      WritePrivateProfileString(S_RAWPART, K_RAWHEIGHT, DoubleToString(m_RawHeight, 2), m_MainWindow.GetIniFile())
      WritePrivateProfileString(S_RAWPART, K_RAWOFFSX, DoubleToString(m_RawOffsX, 2), m_MainWindow.GetIniFile())
      WritePrivateProfileString(S_RAWPART, K_RAWOFFSY, DoubleToString(m_RawOffsY, 2), m_MainWindow.GetIniFile())
      WritePrivateProfileString(S_RAWPART, K_RAWKERF, DoubleToString(m_RawKerf, 2), m_MainWindow.GetIniFile())
      ' Se ci sono pezzi nel grezzo
      If EgtGetFirstPartInRawPart(m_CurrProjPage.m_nRawId) <> GDB_ID.NULL Then
         ' Cancello tutte le lavorazioni
         EraseMachinings(GDB_ID.NULL)
         ' Se progetto con pezzi piani
         Dim nPrjType As Integer = m_CurrProjPage.GetCurrentProjectType()
         If nPrjType = CurrentProjectPageUC.PRJ_TYPE.FLATS Then
            ' Reinserisco tutte le lavorazioni piane
            Dim nWarn As Integer = 0
            AddMachinings(GDB_ID.NULL, nWarn)
            If nWarn = 1 Then m_CurrProjPage.SetWarningMessage(EgtMsg(MSG_SPLITPAGEUC + 11)) ' Lama troppo grande per utilizzo ventosa
            ' Aggiorno regioni per nesting
            m_MainWindow.m_CadCutPageUC.m_NestPage.UpdateNestRegions()
            m_MainWindow.m_CadCutPageUC.m_NestPage.EnableReferenceRegion(False)
            ' Visualizzo i pezzi parcheggiati (per inserire correttamente in parcheggio i pezzi del grezzo)
            ShowParkedParts()
            ' Verifico ogni singolo pezzo
            Dim bReducedCut As Boolean = (GetPrivateProfileInt(S_MACH_NEST, K_MACH_REDUCEDCUT, 0, m_MainWindow.GetMachIniFile()) <> 0)
            Dim nPartId As Integer = EgtGetFirstPartInRawPart(m_CurrProjPage.m_nRawId)
            While nPartId <> GDB_ID.NULL
               Dim nNextPartId = EgtGetNextPartInRawPart(nPartId)
               If Not EgtVerifyPart(nPartId, bReducedCut) Then
                  m_MainWindow.m_CadCutPageUC.m_NestPage.StoreOnePart(nPartId)
                  VeinMatching.OnRemovePartFromRaw(nPartId)
               End If
               nPartId = nNextPartId
            End While
            ' Nascondo i pezzi parcheggiati
            HideParkedParts()
            ' Aggiusto eventuali solidi per lavorazioni da sotto
            nPartId = EgtGetFirstPartInRawPart(m_CurrProjPage.m_nRawId)
            While nPartId <> GDB_ID.NULL
               UpdateSolidForDrip(nPartId)
               nPartId = EgtGetNextPartInRawPart(nPartId)
            End While
            ' Se altrimenti progetto con cornici
         ElseIf nPrjType = CurrentProjectPageUC.PRJ_TYPE.FRAMES Then
            ' Reinserisco tutte le lavorazioni delle cornici
            AddFrameMachinings(m_MainWindow.m_FrameCutPageUC.m_FrameMachiningUC.m_dStartTrim, m_MainWindow.m_FrameCutPageUC.m_FrameMachiningUC.m_dEndTrim)
         End If
      End If
      Return True
   End Function

   Private Sub RawModeCmBx_SelectionChanged(sender As Object, e As SelectionChangedEventArgs) Handles RawModeCmBx.SelectionChanged
      Select Case RawModeCmBx.SelectedIndex
         Case 0          ' Rettangolo
            ' Se ero in modalità da laser
            VerifyLaserDefining()
            ' Verificos e sto realmente cambiando modalità
            Dim bChanging As Boolean = (m_ActiveRawMode <> RAWMODE.RECTANGLE)
            ' Imposto nuova modalità
            m_ActiveRawMode = RAWMODE.RECTANGLE
            ' Riattivo i controlli in base a quale modalità di inserimento contorni è attiva
            RawModeView()
            RemoveCircles()
            If bChanging Then UpdateRawPart()
         Case 1          ' Punti
            ' Se ero in modalità da laser
            VerifyLaserDefining()
            ' Imposto nuova modalità
            m_ActiveRawMode = RAWMODE.BY_POINTS
            ' Riattivo i controlli in base a quale modalità di inserimento contorni è attiva
            RawModeView()
            UpdateCircles()
            EgtDraw()
         Case 2          ' Da laser
            ' Imposto nuova modalità
            m_ActiveRawMode = RAWMODE.FROM_LASER
            RemoveCircles()
            LoadFromMachine()
            ' Azzero lista e punto di partenza
            m_CurveXKerfList.Clear()
            m_bptLast = False
            ' Segno flag che indica definizione grezzo con laser in corso
            m_bIsRawDefiningByLaser = True
            ' Riattivo i controlli in base a quale modalità di inserimento contorni è attiva
            RawModeView()
            ' Disattivo il bottone
            CloseBtn.IsEnabled = False
            OkBtn.IsEnabled = False
         Case 3          ' Da fotografia
            ' Se ero in modalità da laser
            VerifyLaserDefining()
            ' Imposto nuova modalità
            m_ActiveRawMode = RAWMODE.FROM_PHOTO
            ' Riattivo i controlli in base a quale modalità di inserimento contorni è attiva
            RawModeView()
            RemoveCircles()
            ' Creo il grezzo dal contorno riconosciuto nella fotografia
            CreateRawFromPhotoContour()
            EgtDraw()
      End Select
   End Sub

   Private Sub RawModeDamagedCmBx_SelectionChanged(sender As Object, e As SelectionChangedEventArgs) Handles RawModeDamagedCmBx.SelectionChanged
      Select Case RawModeDamagedCmBx.SelectedIndex
         Case 0          ' By Points
            m_ActiveRawMode = RAWMODE.DAMAGED
         Case 1          ' Da laser
            m_ActiveRawMode = RAWMODE.DAMAGED_BY_LASER
      End Select
      RawModeView()
      EgtDraw()
   End Sub

   Private Sub RawModeView()
      Select Case m_ActiveRawMode
         Case RAWMODE.RECTANGLE
            RawModeCmBx.IsEnabled = True
            RawModeDamagedCmBx.Visibility = Visibility.Collapsed
            LengthTxBx.IsEnabled = True
            WidthTxBx.IsEnabled = True
            OffsetXTxBx.IsEnabled = True
            OffsetYTxBx.IsEnabled = True
            PointsGpBx.Visibility = Windows.Visibility.Hidden
            ' Disattivo bottoni zone rovinate
            DamagedAreaGpBx.Visibility = Windows.Visibility.Hidden
            ConfirmPhotoBtn.Visibility = Windows.Visibility.Hidden
         Case RAWMODE.BY_POINTS
            RawModeCmBx.IsEnabled = True
            RawModeDamagedCmBx.Visibility = Visibility.Collapsed
            LengthTxBx.IsEnabled = False
            WidthTxBx.IsEnabled = False
            OffsetXTxBx.IsEnabled = False
            OffsetYTxBx.IsEnabled = False
            ' Visualizzo bottoni per disegno
            PointsGpBx.Visibility = Windows.Visibility.Visible
            PointsGpBx.SetValue(Grid.RowSpanProperty, 1)
            AddBtn.SetValue(Grid.RowSpanProperty, 2)
            RemoveBtn.SetValue(Grid.RowSpanProperty, 2)
            CloseBtn.Visibility = Windows.Visibility.Hidden
            ' Disattivo bottoni zone rovinate e foto
            DamagedAreaGpBx.Visibility = Windows.Visibility.Hidden
            ConfirmPhotoBtn.Visibility = Windows.Visibility.Hidden
         Case RAWMODE.FROM_LASER
            RawModeCmBx.IsEnabled = True
            RawModeDamagedCmBx.Visibility = Visibility.Collapsed
            LengthTxBx.IsEnabled = False
            WidthTxBx.IsEnabled = False
            OffsetXTxBx.IsEnabled = False
            OffsetYTxBx.IsEnabled = False
            ' Visualizzo bottoni per laser            
            PointsGpBx.Visibility = Windows.Visibility.Visible
            PointsGpBx.SetValue(Grid.RowSpanProperty, 2)
            AddBtn.SetValue(Grid.RowSpanProperty, 1)
            RemoveBtn.SetValue(Grid.RowSpanProperty, 1)
            CloseBtn.Visibility = Windows.Visibility.Visible
            ' Disattivo bottoni zone rovinate e foto
            DamagedAreaGpBx.Visibility = Windows.Visibility.Hidden
            ConfirmPhotoBtn.Visibility = Windows.Visibility.Hidden
         Case RAWMODE.DAMAGED
            RawModeCmBx.IsEnabled = False
            RawModeDamagedCmBx.Visibility = Visibility.Visible
            LengthTxBx.IsEnabled = False
            WidthTxBx.IsEnabled = False
            OffsetXTxBx.IsEnabled = False
            OffsetYTxBx.IsEnabled = False
            ' Visualizzo bottoni per laser            
            PointsGpBx.Visibility = Windows.Visibility.Visible
            PointsGpBx.SetValue(Grid.RowSpanProperty, 1)
            RemoveBtn.SetValue(Grid.ColumnSpanProperty, 3)
            AddBtn.SetValue(Grid.RowSpanProperty, 2)
            RemoveBtn.SetValue(Grid.RowSpanProperty, 2)
            CloseBtn.Visibility = Windows.Visibility.Hidden
            ' Attivo bottoni zone rovinate
            DamagedAreaGpBx.Visibility = Windows.Visibility.Visible
            ' Disattivo bottoni foto
            ConfirmPhotoBtn.Visibility = Windows.Visibility.Hidden
         Case RAWMODE.FROM_PHOTO
            RawModeCmBx.IsEnabled = True
            RawModeDamagedCmBx.Visibility = Visibility.Collapsed
            LengthTxBx.IsEnabled = False
            WidthTxBx.IsEnabled = False
            OffsetXTxBx.IsEnabled = False
            OffsetYTxBx.IsEnabled = False
            ' Nascondo bottoni per punti e zone rovinate            
            PointsGpBx.Visibility = Windows.Visibility.Hidden
            DamagedAreaGpBx.Visibility = Windows.Visibility.Hidden
            ' Visualizzo bottoni foto
            ConfirmPhotoBtn.Visibility = Windows.Visibility.Visible
         Case RAWMODE.DAMAGED_BY_LASER
            RawModeCmBx.IsEnabled = True
            RawModeDamagedCmBx.Visibility = Visibility.Visible
            LengthTxBx.IsEnabled = False
            WidthTxBx.IsEnabled = False
            OffsetXTxBx.IsEnabled = False
            OffsetYTxBx.IsEnabled = False
            ' Visualizzo bottoni per laser            
            PointsGpBx.Visibility = Windows.Visibility.Visible
            PointsGpBx.SetValue(Grid.RowSpanProperty, 2)
            AddBtn.SetValue(Grid.RowSpanProperty, 1)
            RemoveBtn.SetValue(Grid.RowSpanProperty, 1)
            CloseBtn.Visibility = Windows.Visibility.Visible
            ' Disattivo bottoni zone rovinate e foto
            DamagedAreaGpBx.Visibility = Windows.Visibility.Hidden
            ConfirmPhotoBtn.Visibility = Windows.Visibility.Hidden
      End Select
   End Sub

   Private Sub OutlineBtn_Click(sender As Object, e As RoutedEventArgs) Handles OutlineBtn.Click
      If m_ActiveRawMode = RAWMODE.DAMAGED Or m_ActiveRawMode = RAWMODE.DAMAGED_BY_LASER Then
         ' m_ActiveRawMode = RAWMODE.BY_POINTS
         m_ActiveRawMode = m_PrecActiveRawMode
         RawModeCmBx.SelectedIndex = m_ActiveRawMode
         RawModeView()
         UpdateCircles()
         EgtDraw()
      End If
   End Sub

   Private Sub DamagedBtn_Click(sender As Object, e As RoutedEventArgs) Handles DamagedBtn.Click
      m_PrecActiveRawMode = m_ActiveRawMode
      If m_PrecActiveRawMode = RAWMODE.FROM_LASER Then
         m_ActiveRawMode = RAWMODE.DAMAGED_BY_LASER
         RawModeDamagedCmBx.SelectedIndex = 1
      Else
         m_ActiveRawMode = RAWMODE.DAMAGED
         RawModeDamagedCmBx.SelectedIndex = 0
      End If
      RawModeView()
      RemoveCircles()
      EgtDraw()
   End Sub

   Private Sub AddBtn_Click(sender As Object, e As RoutedEventArgs) Handles AddBtn.Click
      Select Case m_ActiveRawMode
         Case RAWMODE.RECTANGLE
            AddBtn.IsChecked = False
         Case RAWMODE.BY_POINTS
            RemoveBtn.IsChecked = False
            m_nPtMode = If(AddBtn.IsChecked, PTMODE.ADD, PTMODE.MOVE)
         Case RAWMODE.FROM_LASER
            Dim ptAcquired As Point3d
            ' Se inserimento manuale dei punti laser
            If m_bFromDraw Then
               If Not IsNothing(m_ptPrev) Then
                  ptAcquired = m_ptPrev
                  ptAcquired.ToLoc(New Frame3d(m_ptTableMin))
               Else
                  m_CurrProjPage.SetErrorMessage(EgtMsg(90532))   ' Errore nell'acquisizione del punto
                  Return
               End If
               ' altrimenti da macchina
            Else
               If Not AcquireLaserPoint(ptAcquired) Then
                  m_CurrProjPage.SetErrorMessage(EgtMsg(90532))   ' Errore nell'acquisizione del punto
                  Return
               End If
            End If
            ' Limito il punto a stare nella tavola con franco pari al kerf
            If ptAcquired.x < m_RawKerf Then ptAcquired.x = m_RawKerf + SAFE_RAW_DIST
            If ptAcquired.y < m_RawKerf Then ptAcquired.y = m_RawKerf + SAFE_RAW_DIST
            If ptAcquired.x > m_dTableLength - m_RawKerf Then ptAcquired.x = m_dTableLength - m_RawKerf - SAFE_RAW_DIST
            If ptAcquired.y > m_dTableWidth - m_RawKerf Then ptAcquired.y = m_dTableWidth - m_RawKerf - SAFE_RAW_DIST
            ' Aggiusto Z punto movimentato (è in locale al tavolo)
            ptAcquired.z = m_CurrentMachine.dAdditionalTable + m_RawHeight
            'Porto il punto nel riferimento del grezzo
            Dim frRaw As New Frame3d
            EgtGetGroupGlobFrame(m_CurrProjPage.m_nRawId, frRaw)
            ptAcquired.LocToLoc(New Frame3d(m_ptTableMin), frRaw)
            m_ptPrev.LocToLoc(New Frame3d(m_ptTableMin), frRaw)
            If m_bptLast Then
               If Point3d.SameApprox(ptAcquired, m_ptLast) Then
                  AddBtn.IsChecked = False
                  Exit Sub
               End If
               Dim NewLine As Integer = EgtCreateLine(m_CurrProjPage.m_nRawId, m_ptLast, ptAcquired)
               EgtSetColor(NewLine, m_KerfCol)
               m_CurveXKerfList.Add(NewLine)
            Else
               m_bptLast = True
            End If
            m_ptLast = ptAcquired
            If m_CurveXKerfList.Count > 1 Then
               OkBtn.IsEnabled = True
               CloseBtn.IsEnabled = True
            End If
            AddBtn.IsChecked = False
            EgtDraw()
         Case RAWMODE.DAMAGED
            ' Verifico ci sia almeno una zona rovinata
            If EgtGetFirstNameInGroup(m_CurrProjPage.m_nRawId, NAME_DAMAGED) = GDB_ID.NULL Then
               AddBtn.IsChecked = False
            End If
            RemoveBtn.IsChecked = False
            NewBtn.IsChecked = False
            DeleteBtn.IsChecked = False
            m_nPtMode = If(AddBtn.IsChecked, PTMODE.ADD, PTMODE.MOVE)
            m_nPtDmgMode = DMGMODE.NONE
         Case RAWMODE.DAMAGED_BY_LASER
            Dim ptAcquired As Point3d
            ' Se inserimento manuale dei punti laser
            If m_bFromDraw Then
               If Not IsNothing(m_ptPrev) Then
                  ptAcquired = m_ptPrev
                  ptAcquired.ToLoc(New Frame3d(m_ptTableMin))
               Else
                  m_CurrProjPage.SetErrorMessage(EgtMsg(90532))   ' Errore nell'acquisizione del punto
                  Return
               End If
               ' altrimenti da macchina
            Else
               If Not AcquireLaserPoint(ptAcquired) Then
                  m_CurrProjPage.SetErrorMessage(EgtMsg(90532))   ' Errore nell'acquisizione del punto
                  Return
               End If
            End If
            ' Limito il punto a stare nella tavola con franco pari al kerf
            If ptAcquired.x < m_RawKerf Then ptAcquired.x = m_RawKerf + SAFE_RAW_DIST
            If ptAcquired.y < m_RawKerf Then ptAcquired.y = m_RawKerf + SAFE_RAW_DIST
            If ptAcquired.x > m_dTableLength - m_RawKerf Then ptAcquired.x = m_dTableLength - m_RawKerf - SAFE_RAW_DIST
            If ptAcquired.y > m_dTableWidth - m_RawKerf Then ptAcquired.y = m_dTableWidth - m_RawKerf - SAFE_RAW_DIST
            ' Aggiusto Z punto movimentato (è in locale al tavolo)
            ptAcquired.z = m_CurrentMachine.dAdditionalTable + m_RawHeight
            'Porto il punto nel riferimento del grezzo
            Dim frRaw As New Frame3d
            EgtGetGroupGlobFrame(m_CurrProjPage.m_nRawId, frRaw)
            ptAcquired.LocToLoc(New Frame3d(m_ptTableMin), frRaw)
            m_ptPrev.LocToLoc(New Frame3d(m_ptTableMin), frRaw)
            If m_bptLast Then
               If Point3d.SameApprox(ptAcquired, m_ptLast) Then
                  AddBtn.IsChecked = False
                  Exit Sub
               End If
               Dim NewLine As Integer = EgtCreateLine(m_CurrProjPage.m_nRawId, m_ptLast, ptAcquired)
               EgtSetColor(NewLine, m_KerfCol)
               m_CurveXDamagedAreaList.Add(NewLine)
            Else
               m_bptLast = True
            End If
            m_ptLast = ptAcquired
            If m_CurveXDamagedAreaList.Count > 1 Then
               OkBtn.IsEnabled = True
               CloseBtn.IsEnabled = True
            End If
            AddBtn.IsChecked = False
            EgtDraw()
      End Select
   End Sub

   Private Function AcquireLaserPoint(ByRef ptAcquired As Point3d) As Boolean
      Dim ptTipP1 As Point3d
      ' Recupero la posizione macchina
      Dim dL1, dL2, dL3, dR1, dR2 As Double
      If Not m_MainWindow.m_CNCommunication.GetAxesPositions(dL1, dL2, dL3, dR1, dR2) Then
         Return False
      End If
      ' Recupero dati utensile e testa corrente
      Dim sTool As String = ""
      Dim sHead As String = ""
      Dim nExit As Integer = 0
      EgtGetCalcTool(sTool, sHead, nExit)
      ' Imposto come testa corrente il laser (senza utensile ovviamente)
      If Not EgtSetCalcTool("", "H3", 1) Then
         Return False
      End If
      ' Trasformo in posizione punta utensile in basso
      If Not EgtGetCalcTipFromPositions(dL1, dL2, dL3, dR1, dR2, True, ptTipP1) Then
         Return False
      End If
      ' Reimposto eventuale precedente utensile
      EgtSetCalcTool(sTool, sHead, nExit)
      ' Porto il tip nell'origine tavola
      ptAcquired = ptTipP1
      ptAcquired.ToLoc(New Frame3d(m_ptTableMin))
      Return True
   End Function

   Private Sub RemoveBtn_Click(sender As Object, e As RoutedEventArgs) Handles RemoveBtn.Click
      Select Case m_ActiveRawMode
         Case RAWMODE.RECTANGLE
            RemoveBtn.IsChecked = False
         Case RAWMODE.BY_POINTS
            AddBtn.IsChecked = False
            m_nPtMode = If(RemoveBtn.IsChecked(), PTMODE.REMOVE, PTMODE.MOVE)
         Case RAWMODE.FROM_LASER
            If m_CurveXKerfList.Count > 0 Then
               If m_CurveXKerfList.Count = 1 Then
                  ' Aggiorno ptLast con primo punto
                  EgtStartPoint(m_CurveXKerfList(m_CurveXKerfList.Count - 1), m_ptLast)
                  ' Cancello ultima linea
                  EgtErase(m_CurveXKerfList(m_CurveXKerfList.Count - 1))
                  m_CurveXKerfList.RemoveAt(m_CurveXKerfList.Count - 1)
               Else
                  ' Cancello ultima linea
                  EgtErase(m_CurveXKerfList(m_CurveXKerfList.Count - 1))
                  m_CurveXKerfList.RemoveAt(m_CurveXKerfList.Count - 1)
                  ' Aggiorno ptLast
                  EgtEndPoint(m_CurveXKerfList(m_CurveXKerfList.Count - 1), m_ptLast)
               End If
            Else
               m_bptLast = False
            End If
            RemoveBtn.IsChecked = False
            EgtDraw()
         Case RAWMODE.DAMAGED
            ' Verifico ci sia almeno una zona rovinata
            If EgtGetFirstNameInGroup(m_CurrProjPage.m_nRawId, NAME_DAMAGED) = GDB_ID.NULL Then
               RemoveBtn.IsChecked = False
            End If
            AddBtn.IsChecked = False
            NewBtn.IsChecked = False
            DeleteBtn.IsChecked = False
            m_nPtMode = If(RemoveBtn.IsChecked(), PTMODE.REMOVE, PTMODE.MOVE)
            m_nPtDmgMode = DMGMODE.NONE
      End Select
   End Sub

   Private Sub ConfirmPhotoBtn_Click(sender As Object, e As RoutedEventArgs) Handles ConfirmPhotoBtn.Click
      ' Passo in modalità per punti
      RawModeCmBx.SelectedIndex = RAWMODE.BY_POINTS
      ' Riattivo i controlli in base a quale modalità di inserimento contorni è attiva
      RawModeView()
      UpdateCircles()
      EgtDraw()
   End Sub

   Private Sub UpdateRawPart(Optional bHeightModified As Boolean = False)
      ' Se cambiato spessore e c'è foto, aggiorno quota fotografia
      If bHeightModified And m_CurrProjPage.GetPhoto() <> GDB_ID.NULL Then
         ' Aggiorno spessore in progetto corrente
         m_CurrProjPage.m_dRawHeight = m_RawHeight
         m_CurrProjPage.UpdateHeightTxBx()
         ' Ricarico fotografia
         m_CurrProjPage.UpdatePhoto()
         ' Aggiorno eventuale contorno da foto
         m_CurrProjPage.UpdateContour()
      End If
      ' Recupero il colore (con la foto lo rendo molto più trasparente)
      Dim Col = m_RawCol
      ' in presenza di foto rendo molto più trasparente
      If m_CurrProjPage.GetPhoto() <> GDB_ID.NULL Then Col.A = 20
      ' Se non esiste già il grezzo (primo con fase 1) e richiesto, lo inserisco
      Dim nRawId As Integer = GetCurrentRaw()
      If nRawId = GDB_ID.NULL And m_RawHeight > EPS_SMALL Then
         m_CurrProjPage.m_nRawId = EgtAddRawPart(Point3d.ORIG(), m_RawLength + 2 * m_RawKerf,
                                                 m_RawWidth + 2 * m_RawKerf, m_RawHeight, Col)
         ' se esiste e da cancellare
      ElseIf m_RawHeight < EPS_SMALL Then
         EgtRemoveRawPart(nRawId)
         m_CurrProjPage.m_nRawId = GDB_ID.NULL
         ' Altrimenti lo modifico
      Else
         m_CurrProjPage.m_nRawId = nRawId
         EgtModifyRawPart(nRawId, Point3d.ORIG(), m_RawLength + 2 * m_RawKerf,
                          m_RawWidth + 2 * m_RawKerf, m_RawHeight, Col)
      End If
      ' Se non cancellato
      If m_RawHeight > EPS_SMALL Then
         AdjustRawPartKerf()
         AdjustRawPartPosition()
      End If
      ' Aggiorno visualizzazione
      EgtZoom(ZM.ALL)
   End Sub

   Private Function AdjustRawPartPosition() As Boolean
      ' Sistemo la posizione
      Dim ptRef As New Point3d(m_RawOffsX - m_RawKerf, m_RawOffsY - m_RawKerf, m_CurrentMachine.dAdditionalTable)
      If EgtMoveToCornerRawPart(m_CurrProjPage.m_nRawId, ptRef, MCH_CR.BL) Then
         OkBtn.IsEnabled = True
         m_CurrProjPage.ClearMessage()
      Else
         OkBtn.IsEnabled = False
         m_CurrProjPage.SetErrorMessage(EgtMsg(MSG_RAWPARTPAGEUC + 47))      ' Errore nella posizione o dimensione del grezzo
      End If
      Return True
   End Function

   Private Function AdjustRawPartKerf() As Boolean
      ' Se non c'è il grezzo, esco
      If m_CurrProjPage.m_nRawId = GDB_ID.NULL Then Return False
      ' Cancello eventuale vecchio contorno di kerf
      Dim nKerfId As Integer = EgtGetFirstNameInGroup(m_CurrProjPage.m_nRawId, NAME_KERF)
      EgtErase(nKerfId)
      ' box grezzo
      Dim ptMin, ptMax As Point3d
      GetRawBox(ptMin, ptMax)
      Dim Lenght As Double = ptMax.x - ptMin.x
      Dim Width As Double = ptMax.y - ptMin.y
      ptMin.x += m_RawKerf
      ptMin.y += m_RawKerf
      ptMin.z = ptMax.z
      ptMax.x -= m_RawKerf
      ptMax.y -= m_RawKerf
      ' Creo il nuovo contorno del kerf
      nKerfId = EgtCreateRectangle2P(m_CurrProjPage.m_nRawId, ptMin, ptMax, GDB_RT.GLOB)
      EgtSetName(nKerfId, NAME_KERF)
      EgtSetColor(nKerfId, m_KerfCol)
      ' Salvo il valore del kerf (sempre in mm)
      EgtSetInfo(m_CurrProjPage.m_nRawId, KEY_KERF, m_RawKerf)
      Return True
   End Function

#Region "Negative Kerf"

   Private Function AdjustRawPartNegativeKerf(Optional NegativeOffset As Boolean = True) As Boolean
      ' Se non c'è il grezzo, esco
      If m_CurrProjPage.m_nRawId = GDB_ID.NULL Then Return False
      ' Cancello eventuale vecchio contorno di kerf
      Dim nKerfId As Integer = EgtGetFirstNameInGroup(m_CurrProjPage.m_nRawId, NAME_KERF)
      Dim nInvert As Double = 1
      If Not NegativeOffset Then
         nInvert = -1
      End If
      EgtOffsetCurve(nKerfId, (-m_RawKerf - m_PrecKerf) * nInvert, OFF_TYPE.EXTEND)
      EgtSetColor(nKerfId, m_KerfCol)
      ' Salvo il valore del kerf (sempre in mm)
      EgtSetInfo(m_CurrProjPage.m_nRawId, KEY_KERF, m_RawKerf)
      Return True
   End Function

   Private Function AdjustRawPartPositionNegativeKerf() As Boolean
      ' Sistemo la posizione
      Dim ptRef As New Point3d(m_RawOffsX, m_RawOffsY, m_CurrentMachine.dAdditionalTable)
      If EgtMoveToCornerRawPart(m_CurrProjPage.m_nRawId, ptRef, MCH_CR.BL) Then
         OkBtn.IsEnabled = True
         m_CurrProjPage.ClearMessage()
      Else
         OkBtn.IsEnabled = False
         m_CurrProjPage.SetErrorMessage(EgtMsg(MSG_RAWPARTPAGEUC + 47))      ' Errore nella posizione o dimensione del grezzo
      End If
      ' Aggiorno visualizzazione
      EgtZoom(ZM.ALL)
      Return True
   End Function

#End Region    ' Negative Kerf

   Private Sub UpdateRawPartHeight()
      ' Se da creare
      If m_CurrProjPage.m_nRawId = GDB_ID.NULL Then
         UpdateRawPart(True)
         Return
         ' se da cancellare
      ElseIf m_RawHeight < EPS_SMALL Then
         ' Se ci sono pezzi
         If EgtGetFirstPartInRawPart(m_CurrProjPage.m_nRawId) <> GDB_ID.NULL Then
            ' Visualizzo i pezzi parcheggiati (per inserire correttamente in parcheggio i pezzi del grezzo)
            ShowParkedParts()
            ' Parcheggio pezzi presenti nel grezzo e li tolgo da VeinMatcing
            Dim nPartId As Integer = EgtGetFirstPartInRawPart(m_CurrProjPage.m_nRawId)
            While nPartId <> GDB_ID.NULL
               Dim nNextPartId As Integer = EgtGetNextPartInRawPart(nPartId)
               m_MainWindow.m_CadCutPageUC.m_NestPage.StoreOnePart(nPartId)
               VeinMatching.OnRemovePartFromRaw(nPartId)
               nPartId = nNextPartId
            End While
            ' Cancello tutte le lavorazioni
            EraseMachinings(GDB_ID.NULL)
            ' Nascondo i pezzi parcheggiati
            HideParkedParts()
         End If
         ' Elimino il grezzo
         EgtRemoveRawPart(m_CurrProjPage.m_nRawId)
         m_CurrProjPage.m_nRawId = GDB_ID.NULL
         ' Imposto modalità rettangolo
         RawModeCmBx.SelectedIndex = RAWMODE.RECTANGLE
         PointsGpBx.Visibility = Windows.Visibility.Hidden
         ' altrimenti da aggiornare
      Else
         ' Salvo vecchia altezza
         Dim dOldHeight As Double = GetRawHeight()
         ' Aggiorno solido
         EgtModifyRawPartHeight(m_CurrProjPage.m_nRawId, m_RawHeight)
         ' Vettore spostamento
         Dim vtMove As New Vector3d(0, 0, m_RawHeight - dOldHeight)
         ' Aggiorno quota kerf
         Dim nKerfId As Integer = EgtGetFirstNameInGroup(m_CurrProjPage.m_nRawId, NAME_KERF)
         If nKerfId <> GDB_ID.NULL Then
            EgtMove(nKerfId, vtMove)
         End If
         ' Se ci sono pezzi ne aggiorno la quota
         Dim nPartId As Integer = EgtGetFirstPartInRawPart(m_CurrProjPage.m_nRawId)
         While nPartId <> GDB_ID.NULL
            EgtMovePartInRawPart(nPartId, vtMove)
            nPartId = EgtGetNextPartInRawPart(nPartId)
         End While
      End If
      ' Aggiorno spessore in progetto corrente
      m_CurrProjPage.m_dRawHeight = m_RawHeight
      ' Se c'è foto, aggiorno quota fotografia
      If m_CurrProjPage.GetPhoto() <> GDB_ID.NULL Then
         ' Ricarico fotografia
         m_CurrProjPage.UpdatePhoto()
         ' Aggiorno eventuale contorno da foto
         m_CurrProjPage.UpdateContour()
      End If
   End Sub

   Private Sub UpdateRawPartKerf()
      ' Se non c'è il grezzo, esco
      If m_CurrProjPage.m_nRawId = GDB_ID.NULL Then Return
      ' Recupero percorso di contorno kerf
      Dim nKerfId As Integer = EgtGetFirstNameInGroup(m_CurrProjPage.m_nRawId, NAME_KERF)
      ' Recupero colore grezzo ( in presenza di foto rendo molto più trasparente)
      Dim Col = m_RawCol
      If m_CurrProjPage.GetPhoto() <> GDB_ID.NULL Then Col.A = 20
      ' Aggiorno il grezzo
      EgtModifyRawPart(m_CurrProjPage.m_nRawId, nKerfId, m_RawKerf, m_ptTableMin.z, m_RawHeight, Col)
      ' Salvo il nuovo valore (sempre in mm)
      EgtSetInfo(m_CurrProjPage.m_nRawId, KEY_KERF, m_RawKerf)
      ' Aggiorno dimensioni e posizione grezzo
      UpdateRawXYData()
   End Sub

   Private Sub UpdateRawXYData()
      ' Identificativo solido del grezzo
      Dim dKerf As Double = 0
      StringToLen(KerfTxBx.Text, dKerf)
      Dim nRawSolidId = EgtGetFirstNameInGroup(m_CurrProjPage.m_nRawId, NAME_RAW_SOLID)
      ' Aggiorno dimensioni grezzo nel piano XY
      Dim ptMin, ptMax As Point3d
      If EgtGetBBoxGlob(nRawSolidId, GDB_BB.STANDARD, ptMin, ptMax) Then
         ' aggiorno dati grezzo
         m_RawLength = ptMax.x - ptMin.x - 2 * m_RawKerf
         m_RawWidth = ptMax.y - ptMin.y - 2 * m_RawKerf
         m_RawOffsX = ptMin.x + m_RawKerf - m_ptTableMin.x
         m_RawOffsY = ptMin.y + m_RawKerf - m_ptTableMin.y
         ' Assegno dati grezzo rettangolare ai textbox
         If dKerf < 0 Then
            LengthTxBx.Text = LenToString(m_RawLength + 2 * m_RawKerf, 2)
            WidthTxBx.Text = LenToString(m_RawWidth + 2 * m_RawKerf, 2)
            OffsetXTxBx.Text = LenToString(m_RawOffsX - m_RawKerf, 2)
            OffsetYTxBx.Text = LenToString(m_RawOffsY - m_RawKerf, 2)
         Else
            LengthTxBx.Text = LenToString(m_RawLength, 2)
            WidthTxBx.Text = LenToString(m_RawWidth, 2)
            OffsetXTxBx.Text = LenToString(m_RawOffsX, 2)
            OffsetYTxBx.Text = LenToString(m_RawOffsY, 2)
         End If

      End If
      ' Aggiorno la posizione del grezzo
      Dim ptRef As New Point3d(m_RawOffsX - m_RawKerf, m_RawOffsY - m_RawKerf, m_CurrentMachine.dAdditionalTable)
      If EgtMoveToCornerRawPart(m_CurrProjPage.m_nRawId, ptRef, MCH_CR.BL) Then
         OkBtn.IsEnabled = True
         m_CurrProjPage.ClearMessage()
      Else
         OkBtn.IsEnabled = False
         m_CurrProjPage.SetErrorMessage("Errore nella posizione o dimensione del grezzo")
      End If
   End Sub

   Private Function CreateRawFromPhotoContour() As Boolean
      ' Calcolo offset interno di kerf dal contorno riconosciuto nella fotografia
      Dim nCount As Integer = 0
      Dim nKerfId As Integer = EgtOffsetCurveAdv(m_CurrProjPage.GetContour(), -m_RawKerf, OFF_TYPE.EXTEND, nCount)
      If nKerfId = GDB_ID.NULL Then
         EgtOutLog("Error on RawPart from Photo Contour")
         Return False
      End If
      ' Cancello eventuali curve risultato dell'offset oltre la prima
      For i As Integer = 1 To nCount - 1
         EgtErase(nKerfId + i)
      Next
      ' Cancello il vecchio kerf
      EgtErase(EgtGetFirstNameInGroup(m_CurrProjPage.m_nRawId, NAME_KERF))
      ' Sposto la curva di offset nel gruppo del grezzo e la rinomino come kerf
      EgtRelocateGlob(nKerfId, m_CurrProjPage.m_nRawId)
      EgtSetName(nKerfId, NAME_KERF)
      EgtSetColor(nKerfId, m_KerfCol)
      ' Aggiorno il grezzo, l'ingombro e la posizione
      UpdateRawPartKerf()
      Return True
   End Function

   Private Sub AdjustRawPartOnStart()
      ' Se non c'è la foto va già bene così
      If m_CurrProjPage.GetPhoto() = GDB_ID.NULL Then Return

      ' Disabilito impostazione modificato
      Dim bOldEnMod = EgtGetEnableModified()
      If bOldEnMod Then EgtDisableModified()
      ' Disabilito la texture sul grezzo
      Dim nSolidId = EgtGetFirstNameInGroup(m_CurrProjPage.m_nRawId, NAME_RAW_SOLID)
      EgtRemoveTextureData(nSolidId)
      ' Sistemo il colore
      Dim Col = m_RawCol
      Col.A = 20
      EgtSetColor(nSolidId, Col, True)
      ' Ripristino precedente impostazione modificato
      If bOldEnMod Then EgtEnableModified()
   End Sub

   Private Sub AdjustRawPartOnExit()
      ' Se non c'è il grezzo, esco
      If m_CurrProjPage.m_nRawId = GDB_ID.NULL Then Return

      ' Disabilito impostazione modificato
      Dim bOldEnMod = EgtGetEnableModified()
      If bOldEnMod Then EgtDisableModified()
      ' Salvo la modalità di definizione
      If m_ActiveRawMode = RAWMODE.RECTANGLE Then
         EgtRemoveInfo(m_CurrProjPage.m_nRawId, KEY_RAWBYPOINTS)
      Else
         EgtSetInfo(m_CurrProjPage.m_nRawId, KEY_RAWBYPOINTS, 1)
      End If
      ' Verifico senso antiorario della curva di kerf
      Dim nKerfId = EgtGetFirstNameInGroup(m_CurrProjPage.m_nRawId, NAME_KERF)
      Dim dArea As Double
      If EgtCurveAreaXY(nKerfId, dArea) AndAlso dArea < 0 Then
         EgtInvertCurve(nKerfId)
      End If
      ' Elimino regioni per nesting
      RemoveNestRegions()
      ' Se c'è la foto devo sistemare
      If m_CurrProjPage.GetPhoto() <> GDB_ID.NULL Then
         ' Carico la texture della foto sul grezzo
         Dim nSolidId = EgtGetFirstNameInGroup(m_CurrProjPage.m_nRawId, NAME_RAW_SOLID)
         Dim sTxrName As String = String.Empty
         EgtGetTextureName(m_CurrProjPage.GetPhoto(), sTxrName)
         EgtSetTextureName(nSolidId, sTxrName)
         ' Sistemo il riferimento della texture
         Dim refTxr As New Frame3d
         m_CurrProjPage.GetPhotoTextureRef(refTxr)
         EgtSetTextureFrame(nSolidId, refTxr, GDB_RT.GLOB)
         ' Sistemo il colore
         Dim colWhite As New Color3d(255, 255, 255, 100)
         EgtSetColor(nSolidId, colWhite)
         ' Anche per il contorno
         Dim nOutlineId = EgtGetFirstNameInGroup(m_CurrProjPage.m_nRawId, NAME_RAW_OUTLINE)
         EgtSetColor(nOutlineId, colWhite)
         EgtSetStatus(nOutlineId, GDB_ST.OFF)
         ' Nascondo la foto
         m_CurrProjPage.ShowPhoto(False)
      End If
      ' Se prevista centratura, la eseguo
      If m_CurrentMachine.CenterRawOnX() Then
         ' Centro in X del grezzo
         Dim ptRawCen As Point3d
         CamAuto.GetRawCenter(ptRawCen)
         Dim dRawCenX As Double = ptRawCen.x
         ' Centro in X della tavola
         Dim dTabCenX = m_ptTableMin.x + m_dTableLength / 2
         ' Se molto diversi, eseguo centratura
         If Math.Abs(dTabCenX - dRawCenX) > 10 Then
            Dim vtMove As New Vector3d(dTabCenX - dRawCenX, 0, 0)
            If EgtMoveRawPart(m_CurrProjPage.m_nRawId, vtMove) Then
               ' Aggiorno gli offset
               m_RawOffsX += vtMove.x
               OffsetXTxBx.Text = LenToString(m_RawOffsX, 2)
               ' Se c'è la foto, devo aggiornarne la posizione
               Dim nPhotoId = m_CurrProjPage.GetPhoto()
               If nPhotoId <> GDB_ID.NULL Then
                  EgtMove(nPhotoId, vtMove, GDB_RT.GLOB)
                  Dim refTxr As New Frame3d
                  EgtGetTextureFrame(nPhotoId, GDB_ID.ROOT, refTxr)
                  refTxr.Move(vtMove)
                  EgtSetTextureFrame(nPhotoId, refTxr, GDB_RT.GLOB)
               End If
            End If
         End If
      End If
      ' Ripristino precedente impostazione modificato
      If bOldEnMod Then EgtEnableModified()
   End Sub

   Private Function RemoveNestRegions() As Boolean
      ' Cancello eventuale vecchia regione fuori kerf per nesting
      EgtErase(EgtGetFirstNameInGroup(m_CurrProjPage.m_nRawId, NAME_OUTKERF_REG))
      ' Cancello eventuale vecchia regione di riferimento per nesting
      EgtErase(EgtGetFirstNameInGroup(m_CurrProjPage.m_nRawId, NAME_REF_REG))
      ' Cancello eventuali vecchie regioni aree rovinate per nesting
      Dim nId As Integer = EgtGetFirstNameInGroup(m_CurrProjPage.m_nRawId, NAME_DAMAGED_REG)
      While nId <> GDB_ID.NULL
         EgtErase(nId)
         nId = EgtGetFirstNameInGroup(m_CurrProjPage.m_nRawId, NAME_DAMAGED_REG)
      End While
      Return True
   End Function

   Private Sub LengthTxBx_EgtClosed(sender As Object, e As EventArgs) Handles LengthTxBx.EgtClosed
      Dim dKerf As Double = 0
      StringToLen(KerfTxBx.Text, dKerf)
      Dim dLength As Double
      If Not StringToLen(LengthTxBx.Text, dLength) Or dLength < EPS_SMALL Then
         Return
      End If
      Dim dInvertKerf As Double = 1
      EgtGetInfo(EgtGetFirstRawPart(), KEY_INVERT_KERF, dInvertKerf)
      Dim dMaxLen = m_dTableLength - m_RawOffsX - m_RawKerf * dInvertKerf
      If dLength <= dMaxLen Then
         m_CurrProjPage.ClearMessage()
         If dKerf < 0 Then
            m_RawLength = dLength - 2 * m_RawKerf
         Else
            m_RawLength = dLength
         End If
         UpdateRawPart()
      Else
         LengthTxBx.Text = LenToString(m_RawLength, 2)
         m_CurrProjPage.SetErrorMessage(EgtMsg(MSG_RAWPARTPAGEUC + 16) & " " & LenToString(dMaxLen, 2))      'Massima lunghezza =
      End If
   End Sub

   Private Sub WidthTxBx_EgtClosed(sender As Object, e As EventArgs) Handles WidthTxBx.EgtClosed
      Dim dKerf As Double = 0
      StringToLen(KerfTxBx.Text, dKerf)
      Dim dWidth As Double
      If Not StringToLen(WidthTxBx.Text, dWidth) Or dWidth < EPS_SMALL Then
         Return
      End If
      Dim dInvertKerf As Double = 1
      EgtGetInfo(EgtGetFirstRawPart(), KEY_INVERT_KERF, dInvertKerf)
      Dim dMaxWidth = m_dTableWidth - m_RawOffsY - m_RawKerf
      If dWidth <= dMaxWidth Then
         m_CurrProjPage.ClearMessage()
         If dKerf < 0 Then
            m_RawWidth = dWidth - 2 * m_RawKerf
         Else
            m_RawWidth = dWidth
         End If
         UpdateRawPart()
      Else
         WidthTxBx.Text = LenToString(m_RawWidth, 2)
         m_CurrProjPage.SetErrorMessage(EgtMsg(MSG_RAWPARTPAGEUC + 17) & " " & LenToString(dMaxWidth, 2))   'Massima larghezza =
      End If
   End Sub

   Private Sub HeightTxBx_EgtClosed(sender As Object, e As EventArgs) Handles HeightTxBx.EgtClosed
      Dim dHeight As Double
      If Not StringToLen(HeightTxBx.Text, dHeight) Then
         Return
      End If
      If dHeight > -EPS_ZERO Then
         m_CurrProjPage.ClearMessage()
         If Math.Abs(dHeight - m_RawHeight) > EPS_SMALL Then
            m_RawHeight = dHeight
            If m_ActiveRawMode <> RAWMODE.FROM_PHOTO Or m_RawHeight < EPS_SMALL Then
               UpdateRawPartHeight()
            Else
               ' Aggiorno spessore in progetto corrente
               m_CurrProjPage.m_dRawHeight = m_RawHeight
               ' Aggiorno quota fotografia e contorno
               m_CurrProjPage.UpdatePhoto()
               m_CurrProjPage.UpdateContour()
               ' Ricreo grezzo
               CreateRawFromPhotoContour()
            End If
            ' Ridisegno
            EgtDraw()
         End If
      Else
         HeightTxBx.Text = LenToString(m_RawHeight, 3)
         m_CurrProjPage.SetErrorMessage(EgtMsg(MSG_RAWPARTPAGEUC + 18)) 'Non sono ammessi spessori negativi
      End If
   End Sub

   Private Sub OffsetXTxBx_EgtClosed(sender As Object, e As EventArgs) Handles OffsetXTxBx.EgtClosed
      Dim dKerf As Double = 0
      StringToLen(KerfTxBx.Text, dKerf)
      Dim dOffsetX As Double
      If Not StringToLen(OffsetXTxBx.Text, dOffsetX) Then
         Return
      End If
      Dim dMinOffsetX = m_RawKerf
      If dKerf < 0 And dOffsetX >= 0 Then
         'm_RawOffsX = dOffsetX + m_RawKerf
         'UpdateRawPart()
         m_RawOffsX = dOffsetX
         AdjustRawPartPositionNegativeKerf()
      ElseIf dKerf >= 0 And dOffsetX >= dMinOffsetX Then
         m_RawOffsX = dOffsetX
         UpdateRawPart()
      Else
         OffsetXTxBx.Text = LenToString(m_RawOffsX, 2)
         m_CurrProjPage.SetErrorMessage(EgtMsg(MSG_RAWPARTPAGEUC + 19) & " " & LenToString(dMinOffsetX, 2))   'Minimo offset X = 
      End If
   End Sub

   Private Sub OffsetYTxBx_EgtClosed(sender As Object, e As EventArgs) Handles OffsetYTxBx.EgtClosed
      Dim dKerf As Double = 0
      StringToLen(KerfTxBx.Text, dKerf)
      Dim dOffsetY As Double
      If Not StringToLen(OffsetYTxBx.Text, dOffsetY) Then
         Return
      End If
      Dim dMinOffsetY = m_RawKerf
      If dKerf < 0 And dOffsetY >= 0 Then
         'm_RawOffsY = dOffsetY + m_RawKerf
         'UpdateRawPart()
         m_RawOffsY = dOffsetY
         AdjustRawPartPositionNegativeKerf()
      ElseIf dKerf >= 0 And dOffsetY >= dMinOffsetY Then
         m_RawOffsY = dOffsetY
         UpdateRawPart()
      Else
         OffsetYTxBx.Text = LenToString(m_RawOffsY, 2)
         m_CurrProjPage.SetErrorMessage(EgtMsg(MSG_RAWPARTPAGEUC + 20) & " " & LenToString(dMinOffsetY, 2))   'Minimo offset Y = 
      End If
   End Sub

   Private Sub KerfTxBx_EgtClosed(sender As Object, e As EventArgs) Handles KerfTxBx.EgtClosed
      Dim dKerf As Double
      If Not StringToLen(KerfTxBx.Text, dKerf) Then
         Return
      End If
      'Dim dMinKerf = 0
      Dim dMaxKerf = Math.Min(Math.Min(m_RawOffsX, m_RawOffsY),
                     Math.Min(m_dTableLength - m_RawLength - m_RawOffsX, m_dTableWidth - m_RawWidth - m_RawOffsY))
      Dim dMinKerf = -Math.Min(m_RawLength, m_RawWidth) / 2
      ' recuper il segno del valore del Kerf precedente
      Dim dInvertKerf As Double = 1
      EgtGetInfo(EgtGetFirstRawPart(), KEY_INVERT_KERF, dInvertKerf)
      m_PrecKerf = Math.Abs(m_RawKerf)
      m_PrecKerf = m_PrecKerf * dInvertKerf
      ' Sostituisco: dKerf >= dMinKerf And dKerf <= dMaxKerf
      If dKerf >= 0 And dKerf <= dMaxKerf Then
         m_RawKerf = dKerf
         If m_PrecKerf < 0 Then
            ' definsco la dimensione del grezzo pari a quella del kerf
            m_RawKerf = 0
            AdjustRawPartNegativeKerf()
            UpdateCircles()
            UpdateRawPartKerf()
            m_RawKerf = dKerf
            m_PrecKerf = 0
         End If
         If m_ActiveRawMode <> RAWMODE.FROM_PHOTO Then
            StringToLen(LengthTxBx.Text, m_RawLength)
            StringToLen(WidthTxBx.Text, m_RawWidth)
            StringToLen(OffsetXTxBx.Text, m_RawOffsX)
            StringToLen(OffsetYTxBx.Text, m_RawOffsY)
            ' UpdateRawPart()
            UpdateRawPartKerf()
            ' Recupero id contorno kerf
            Dim nKerfId As Integer = EgtGetFirstNameInGroup(m_CurrProjPage.m_nRawId, NAME_KERF)
            ' Modifico il colore
            EgtSetColor(nKerfId, New Color3d(255, 0, 0))
            ' Specifico che si tratta di un Kerf positivo (per interfaccia grafica)
            EgtSetInfo(m_CurrProjPage.m_nRawId, KEY_INVERT_KERF, 1)
         Else
            CreateRawFromPhotoContour()
         End If
         ' Ridisegno
         EgtDraw()
      ElseIf dKerf >= dMinKerf And dKerf < 0 Then
         ' aggiorno il valore del Kerf corrente
         m_RawKerf = dKerf
         If m_ActiveRawMode <> RAWMODE.FROM_PHOTO Then
            ' recupero dati grezzo
            StringToLen(LengthTxBx.Text, m_RawLength)
            StringToLen(WidthTxBx.Text, m_RawWidth)
            StringToLen(OffsetXTxBx.Text, m_RawOffsX)
            StringToLen(OffsetYTxBx.Text, m_RawOffsY)

            If m_PrecKerf >= 0 Then
               m_RawLength = m_RawLength + 2 * m_RawKerf
               m_RawWidth = m_RawWidth + 2 * m_RawKerf
               m_RawOffsX = m_RawOffsX - m_RawKerf
               m_RawOffsY = m_RawOffsY - m_RawKerf
            End If
            m_RawKerf = -m_RawKerf
            ' esegue l'aggiornamento della dimensione del grezzo solo quando passo dal kerf positivo a quello negativo

            If m_PrecKerf >= 0 Then
               ' definsco la dimensione del grezzo pari a quella del kerf
               m_RawKerf = 0
               AdjustRawPartNegativeKerf(False)
               UpdateCircles()
               UpdateRawPartKerf()
               m_RawKerf = -dKerf
               m_PrecKerf = 0
            End If
            AdjustRawPartNegativeKerf()
            UpdateCircles()
            'If m_PrecKerf > 0 And m_RawKerf < 0 Then
            '   m_RawLength = m_RawLength + 2 * m_RawKerf
            '   m_RawWidth = m_RawWidth + 2 * m_RawKerf
            '   m_RawOffsX = m_RawOffsX - m_RawKerf - m_PrecKerf
            '   m_RawOffsY = m_RawOffsY - m_RawKerf - m_PrecKerf
            '   m_RawKerf = -m_RawKerf
            '   UpdateRawPartKerf()
            'If m_PrecKerf >=0 And m_RawKerf < 0 Then
            '   m_RawOffsX = m_RawOffsX - m_PrecKerf
            '   m_RawOffsY = m_RawOffsY - m_PrecKerf
            '   UpdateNegativeRawPart()
            'Else
            '   UpdateNegativeRawPart()
            'End If

            'UpdateRawPart()
            'UpdateNegativeRawPart()

            'm_RawKerf = -m_RawKerf
            'UpdateRawPartKerf()

            ' Recupero id contorno kerf
            Dim nKerfId As Integer = EgtGetFirstNameInGroup(m_CurrProjPage.m_nRawId, NAME_KERF)
            ' Modifico il colore
            EgtSetColor(nKerfId, New Color3d(255, 128, 0))
            ' Specifico che si tratta di un Kerf negativo (per interfaccia grafica)
            EgtSetInfo(m_CurrProjPage.m_nRawId, KEY_INVERT_KERF, -1)
         Else
            CreateRawFromPhotoContour()
         End If
         ' Ridisegno
         EgtDraw()
      ElseIf dKerf < dMinKerf Then
         KerfTxBx.Text = LenToString(m_RawKerf, 2)
         m_CurrProjPage.SetErrorMessage(EgtMsg(MSG_RAWPARTPAGEUC + 21) & " " & LenToString(dMinKerf, 2))   'Minimo kerf =
      Else
         KerfTxBx.Text = LenToString(m_RawKerf, 2)
         m_CurrProjPage.SetErrorMessage(EgtMsg(MSG_RAWPARTPAGEUC + 22) & " " & LenToString(dMaxKerf, 2))   'Massimo kerf = 
      End If
   End Sub

   Private Sub RawProbingBtn_Click(sender As Object, e As RoutedEventArgs) Handles RawProbingBtn.Click
      ' Verifico non sia già in corso una tastatura
      If m_bProbingOn Then Return
      m_bProbingOn = True
      ' Verifico diametro lama corrente rispetto a massimo per tastatura grezzo
      If Not m_CurrentMachine.IsRawProbingPossible() Then
         m_CurrProjPage.SetWarningMessage(EgtMsg(90534))    ' Lama troppo grande per tastatura
         m_bProbingOn = False
         Return
      End If
      ' Verifico esistenza grezzo
      If m_CurrProjPage.m_nRawId = GDB_ID.NULL OrElse EgtGetFirstNameInGroup(m_CurrProjPage.m_nRawId, NAME_RAW_SOLID) = GDB_ID.NULL Then
         m_CurrProjPage.SetWarningMessage(EgtMsg(90499))    ' Grezzo non definito
         m_bProbingOn = False
         Return
      End If
      ' Recupero origine tavola rispetto allo 0 macchina
      Dim TableRef As Point3d
      EgtGetTableRef(1, TableRef)
      ' Recupero file LUA
      EgtLuaExecFile(m_CurrentMachine.sMachDir() & "\DirectCmd\RawProbing.lua")
      ' Imposto parametri
      EgtLuaSetGlobNumVar("CMD.MIDRAWX", m_RawOffsX + m_RawLength / 2)
      EgtLuaSetGlobNumVar("CMD.MIDRAWY", m_RawOffsY + m_RawWidth / 2)
      EgtLuaSetGlobNumVar("CMD.THICK", m_RawHeight + m_CurrentMachine.dAdditionalTable)
      EgtLuaSetGlobNumVar("CMD.TABLEX", TableRef.x)
      EgtLuaSetGlobNumVar("CMD.TABLEY", TableRef.y)
      EgtLuaSetGlobNumVar("CMD.TABLEZ", TableRef.z)
      EgtLuaSetGlobBoolVar("CMD.INCHES", m_MainWindow.m_CNCommunication.GetMachineInInches())
      EgtLuaCallFunction("CMD.CmdString")
      ' Leggo variabili
      Dim CmdString As String = String.Empty
      EgtLuaGetGlobStringVar("CMD.CMDSTRING", CmdString)
      ' Reset lua
      EgtLuaResetGlobVar("CMD")
      ' Modifico stringa per inserire i newline
      CmdString = CmdString.Replace("<br/>", Environment.NewLine)
      ' Creo file...
      Dim FilePath As String = m_MainWindow.GetCncDir() & "\RawProbing" & m_CurrentMachine.sIsoFileExt
      ' ...e ci scrivo
      Dim Writer As New IO.StreamWriter(FilePath, False)
      Writer.Write(CmdString)
      Writer.Close()
      ' Verifico se sono connesso alla macchina prima di continuare
      If Not m_MainWindow.m_bNCLink Then
         m_CurrProjPage.SetWarningMessage(EgtMsg(90316))        'Non connesso alla macchina
         m_bProbingOn = False
         Return
      End If
      ' Mando file al CN
      If Not m_MainWindow.m_CNCommunication.SendProgram(FilePath, 900) Then
         m_bProbingOn = False
         Return
      End If
      m_MainWindow.m_CurrentProjectPageUC.ClearMessage()
      EgtOutLog("RawProbing : sent NC program")
      ' Aspetto e lo avvio
      System.Threading.Thread.Sleep(300)
      m_MainWindow.m_CNCommunication.m_CN.DGeneralFunctions_CycleStart()
      ' Creo MsgBox di attesa
      Dim MsgBoxStateInfo As New EgtMsgBox(m_MainWindow, EgtMsg(MSG_RAWPARTPAGEUC + 25), EgtMsg(MSG_RAWPARTPAGEUC + 26), True, EgtMsgBox.Buttons.CANCEL, EgtMsgBox.Icons.NULL)
      Dim ProbingStateNameVar As String = String.Empty
      GetPrivateProfileString(S_MACH_PROBING, K_PROBINGSTATEVAR, "", ProbingStateNameVar, m_MainWindow.GetMachIniFile())
      m_MainWindow.m_CNCommunication.m_CN.n_DReadELS_handle = 0
      ' Definisco flag tastatura
      Dim bProbingOk As Boolean = False
      For I As Integer = 0 To 120
         ' Devo rileggere la variabile ad ogni ciclo
         m_MainWindow.m_CNCommunication.m_CN.ReadEls_Add_Parameter(ProbingStateNameVar, 3)
         System.Threading.Thread.Sleep(100)
         If m_MainWindow.m_CNCommunication.m_CN.n_DReadELS_handle = 3 Then
            Dim L108Val As Integer = CInt(m_MainWindow.m_CNCommunication.m_CN.d_DReadELS_value)
            Select Case L108Val
               Case 0
                  ' Non faccio alcunchè perchè sta tastando
               Case 1
                  ' Tastatura completata
                  bProbingOk = True
                  Exit For
               Case 2
                  ' Errore
                  bProbingOk = False
                  Exit For
            End Select
         End If
         System.Threading.Thread.Sleep(900)
         ' Incremento progressbar
         MsgBoxStateInfo.LoadingPrBr_Value += 100 / 120
         ' Costringo ad aggiornare UI
         UpdateUI()
         ' Verifico se interrotto dall'utente
         If MsgBoxStateInfo.m_nPressedBtn = 0 Then
            bProbingOk = False
            Exit For
         End If
      Next
      ' Se tastatura riuscita
      If bProbingOk Then
         ' Leggo spessore misurato
         Dim bRead As Boolean = False
         Dim RawThicknessNameVar As String = String.Empty
         GetPrivateProfileString(S_MACH_PROBING, K_RAWTHICKNESS, "", RawThicknessNameVar, m_MainWindow.GetMachIniFile())
         m_MainWindow.m_CNCommunication.m_CN.n_DReadELS_handle = 0
         For I As Integer = 0 To 20
            ' Devo rileggere la variabile ad ogni ciclo
            m_MainWindow.m_CNCommunication.m_CN.ReadEls_Add_Parameter(RawThicknessNameVar, 3)
            If m_MainWindow.m_CNCommunication.m_CN.n_DReadELS_handle = 3 Then
               bRead = True
               Dim RawThickness As Double = m_MainWindow.m_CNCommunication.m_CN.d_DReadELS_value
               MsgBoxStateInfo.LoadingPrBr_Value = 100
               MsgBoxStateInfo.Text = EgtMsg(MSG_RAWPARTPAGEUC + 27)      ' Tastatura completata con successo
               m_MainWindow.m_CurrentProjectPageUC.SetInfoMessage(EgtMsg(MSG_RAWPARTPAGEUC + 27))
               EgtOutLog("RawThickness=" & RawThickness.ToString())
               ' Costringo ad aggiornare UI
               UpdateUI()
               ' Trasformo misura rilevata in mm
               If m_MainWindow.m_CNCommunication.GetMachineInInches() Then
                  RawThickness *= ONEINCH / 1000
               Else
                  RawThickness *= ONEMM / 1000
               End If
               ' Sottraggo eventuale spessore sovratavola
               RawThickness -= m_CurrentMachine.dAdditionalTable
               ' Imposto spessore misurato come altezza grezzo
               If RawThickness > -EPS_ZERO Then
                  m_CurrProjPage.ClearMessage()
                  If Math.Abs(RawThickness - m_RawHeight) > EPS_SMALL Then
                     HeightTxBx.Text = LenToString(RawThickness, 3)
                     m_RawHeight = RawThickness
                     UpdateRawPartHeight()
                     ' Ridisegno
                     EgtDraw()
                  End If
               Else
                  HeightTxBx.Text = LenToString(m_RawHeight, 3)
                  m_CurrProjPage.SetErrorMessage(EgtMsg(MSG_RAWPARTPAGEUC + 18))    'Non sono ammessi spessori negativi
               End If
               ' Chiudo msgbox
               System.Threading.Thread.Sleep(3000)
               MsgBoxStateInfo.Close()
               Exit For
            End If
            System.Threading.Thread.Sleep(100)
         Next
         If Not bRead Then bProbingOk = False
      End If
      ' Se tastatura non riuscita
      If Not bProbingOk Then
         MsgBoxStateInfo.Text = EgtMsg(MSG_RAWPARTPAGEUC + 28)          'Errore nella tastatura del grezzo
         m_MainWindow.m_CurrentProjectPageUC.SetErrorMessage(EgtMsg(MSG_RAWPARTPAGEUC + 28))
         EgtOutLog("RawProbing error")
         ' Costringo ad aggiornare GUI
         UpdateUI()
         System.Threading.Thread.Sleep(3000)
         MsgBoxStateInfo.Close()
      End If
      m_bProbingOn = False
   End Sub

   Private Sub BarCodeBtn_Click(sender As Object, e As RoutedEventArgs) Handles BarCodeBtn.Click
      Dim BarCodeWindow As New BarCodeWD(m_MainWindow)
      If BarCodeWindow.ShowDialog() Then
         Dim nRawId As Integer = GetCurrentRaw()
         If nRawId <> GDB_ID.NULL Then
            ' Cancello eventuale vecchio BarCode
            EgtErase(EgtGetFirstNameInGroup(nRawId, NAME_BARCODE))
            ' Se definito, inserisco nuovo BarCode
            Dim sBarCode As String = BarCodeWindow.GetBarCode()
            If Not String.IsNullOrWhiteSpace(sBarCode) Then
               Dim ptRawCen As Point3d
               GetRawCenter(ptRawCen)
               Dim ptRawMin, ptRawMax As Point3d
               GetRawBox(ptRawMin, ptRawMax)
               Dim ptText As New Point3d(ptRawCen.x, ptRawCen.y, ptRawMax.z)
               Dim nText As Integer = EgtCreateTextAdv(nRawId, ptText, 0, sBarCode, "", 500, False, 50.0, 1, 0, INS_POS.MC, GDB_RT.GLOB)
               EgtSetName(nText, NAME_BARCODE)
               EgtSetColor(nText, New Color3d(255, 0, 0))
            End If
            ' Aggiorno visualizzazione
            EgtDraw()
         End If
      End If
   End Sub

   Private Sub SlabIdBtn_Click(sender As Object, e As RoutedEventArgs) Handles SlabIdBtn.Click
      Dim nRawId As Integer = GetCurrentRaw()
      ' Finestra input dati
      Dim SlabIdWindow As New SlabIdWD(m_MainWindow)
      ' Recupero eventuali vecchi dati della lastra
      If nRawId <> GDB_ID.NULL Then
         Dim sBlock As String = "" : EgtGetInfo(nRawId, INFO_RAW_BLOCK, sBlock)
         Dim sSlabNbr As String = "" : EgtGetInfo(nRawId, INFO_RAW_SLABNBR, sSlabNbr)
         SlabIdWindow.SetBlockName(sBlock)
         SlabIdWindow.SetSlabNbr(sSlabNbr)
      End If
      ' Visualizzo finestra richiesta dati
      If SlabIdWindow.ShowDialog() Then
         ' Recupero i dati
         Dim sBlock As String = SlabIdWindow.GetBlockName()
         Dim sSlabNbr As String = SlabIdWindow.GetSlabNbr()
         ' Li assegno
         Utility.SetBlockAndSlabNbr(sBlock, sSlabNbr)
         ' Li salvo
         WritePrivateProfileString(S_RAWPART, K_BLOCKNAME, sBlock, m_MainWindow.GetIniFile())
         WritePrivateProfileString(S_RAWPART, K_SLABNBR, sSlabNbr, m_MainWindow.GetIniFile())
         ' Aggiorno visualizzazione
         EgtDraw()
      End If
   End Sub

   Private Sub RawPartPage_Unloaded(sender As Object, e As RoutedEventArgs)
      ' Rimuovo layer temporaneo per crocette
      EgtErase(m_nTempLay)
      ' Dichiaro pagina non attiva
      m_bActive = False
   End Sub

   Private Sub VerifyLaserDefining()
      If m_bIsRawDefiningByLaser Then
         If m_CurveXKerfList.Count > 1 Then
            CloseRawByLaser()
         Else
            ' Elimino tutti i segmenti disegnati
            For Each nEntityId As Integer In m_CurveXKerfList
               If EgtGetType(nEntityId) = GDB_TY.CRV_LINE Then
                  EgtErase(nEntityId)
               End If
            Next
            ' Azzero lista e punto di partenza
            m_CurveXKerfList.Clear()
            ' Creo rettangolo
            UpdateRawPart()
         End If
         m_bIsRawDefiningByLaser = False
      End If
   End Sub

   Private Sub LoadFromMachine()
      ' Elimino grezzo già presente
      EgtErase(EgtGetFirstNameInGroup(m_CurrProjPage.m_nRawId, NAME_RAW_SOLID))
      EgtErase(EgtGetFirstNameInGroup(m_CurrProjPage.m_nRawId, NAME_KERF))
      EgtErase(EgtGetFirstNameInGroup(m_CurrProjPage.m_nRawId, NAME_RAW_OUTLINE))
      Dim nId As Integer = EgtGetFirstNameInGroup(m_CurrProjPage.m_nRawId, NAME_DAMAGED)
      While nId <> GDB_ID.NULL
         EgtErase(nId)
         nId = EgtGetFirstNameInGroup(m_CurrProjPage.m_nRawId, NAME_DAMAGED)
      End While
      EgtDraw()
   End Sub

   Private Sub CloseBtn_Click(sender As Object, e As RoutedEventArgs) Handles CloseBtn.Click
      Select Case m_ActiveRawMode
         Case RAWMODE.DAMAGED_BY_LASER
            CloseDamagedAreaByLaser()
         Case Else
            CloseRawByLaser()
      End Select
      ' Rimuovo eventuali crocette create acquisendo i punti nel disegno
      EgtEmptyGroup(m_nTempLay)
   End Sub

   Private Sub CloseRawByLaser()
      ' Verifico ci siano punti
      If m_CurveXKerfList.Count() = 0 Then Return
      ' Recupero punto iniziale prima linea del grezzo
      Dim ptStart As Point3d
      EgtStartPoint(m_CurveXKerfList(0), ptStart)
      m_CurveXKerfList.Add(EgtCreateLine(m_CurrProjPage.m_nRawId, m_ptLast, ptStart))
      ' Trasformo lista di curve in un array
      Dim CurveXKerfArray As Integer() = m_CurveXKerfList.ToArray
      ' Creo contorno kerf
      Dim nKerfId As Integer = EgtCreateCurveCompoByChain(m_CurrProjPage.m_nRawId, m_CurveXKerfList.Count, CurveXKerfArray, ptStart, True)
      EgtSetName(nKerfId, NAME_KERF)
      EgtSetColor(nKerfId, m_KerfCol)
      ' Pulisco lista entità del grezzo
      m_CurveXKerfList.Clear()
      ' Aggiorno il grezzo comprese dimensioni e posizione
      UpdateRawPartKerf()
      ' Salvo il valore del kerf (sempre in mm)
      Dim dKerf As Double = 0
      StringToLen(KerfTxBx.Text, dKerf)
      If dKerf < 0 Then
         EgtSetInfo(m_CurrProjPage.m_nRawId, KEY_INVERT_KERF, -1)
      Else
         EgtSetInfo(m_CurrProjPage.m_nRawId, KEY_INVERT_KERF, 1)
      End If
      EgtSetInfo(m_CurrProjPage.m_nRawId, KEY_KERF, m_RawKerf)
      ' Segno flag che indica fine della definizione
      m_bIsRawDefiningByLaser = False
      ' Elimino primo punto per prossimo grezzo
      m_bptLast = False
      ' Aggiorno visualizzazione
      EgtDraw()
      ' Disattivo il bottone chiudi grezzo
      CloseBtn.IsEnabled = False
   End Sub

#Region "Damaged Area"

   Private Sub AddNewDamagedArea()
      ' Creo triangolo che abbia il punto selezionato come centro (lato 100mm)
      ' calcolo punto in basso a sinistra
      Dim ptBottomLeft As Point3d = New Point3d(m_ptPrev.x - 50,
                                                m_ptPrev.y - (100 / 6 * Math.Sqrt(3)),
                                                m_ptTableMin.z + m_CurrentMachine.dAdditionalTable + m_RawHeight)
      Dim vtRight As Vector3d = New Vector3d(100, 0, 0)
      ' creo lato base
      Dim nBaseId As Integer = EgtCreateLine(m_CurrProjPage.m_nRawId, ptBottomLeft, ptBottomLeft + vtRight, GDB_RT.GLOB)
      ' calcolo vertice superiore del triangolo
      Dim vtTop As New Vector3d(vtRight)
      vtTop.Rotate(Vector3d.Z_AX, 60)
      ' creo lati inclinati
      Dim nCat1 As Integer = EgtCreateLine(m_CurrProjPage.m_nRawId, ptBottomLeft + vtRight, ptBottomLeft + vtTop, GDB_RT.GLOB)
      Dim nCAt2 As Integer = EgtCreateLine(m_CurrProjPage.m_nRawId, ptBottomLeft + vtTop, ptBottomLeft, GDB_RT.GLOB)
      ' Creo contorno zona rovinata
      Dim nDmgId As Integer = EgtCreateCurveCompoByChain(m_CurrProjPage.m_nRawId, 3, {nBaseId, nCat1, nCAt2}, ptBottomLeft, True)
      ' Assegno il nome alla CCompo creata
      EgtSetName(nDmgId, NAME_DAMAGED)
      ' e il colore
      EgtSetColor(nDmgId, m_KerfCol)
      ' Imposto come area danneggiata corrente
      m_nSelDmg = nDmgId
      ' Disabilito modalità aggiungi zona rovinata
      m_nPtDmgMode = DMGMODE.NONE
      ' Tolgo il check al bottone nuovo
      NewBtn.IsChecked = False
   End Sub
   Private Sub CloseDamagedAreaByLaser()
      ' Verifico ci siano punti
      If m_CurveXDamagedAreaList.Count() = 0 Then Return
      ' Recupero punto iniziale prima linea del grezzo
      Dim ptStart As Point3d
      EgtStartPoint(m_CurveXDamagedAreaList(0), ptStart)
      ' creao la linea che va dal primo punto all'ultimo
      m_CurveXDamagedAreaList.Add(EgtCreateLine(m_CurrProjPage.m_nRawId, m_ptLast, ptStart))
      ' Trasformo lista di curve in un array
      Dim CurveXDamagedAreaArray As Integer() = m_CurveXDamagedAreaList.ToArray
      ' Creo contorno kerf
      Dim nDmgId As Integer = EgtCreateCurveCompoByChain(m_CurrProjPage.m_nRawId, m_CurveXDamagedAreaList.Count, CurveXDamagedAreaArray, ptStart, True)
      EgtSetName(nDmgId, NAME_DAMAGED)
      EgtSetColor(nDmgId, m_KerfCol)
      ' Pulisco lista entità del grezzo
      m_CurveXDamagedAreaList.Clear()
      ' Segno flag che indica fine della definizione
      m_bIsRawDefiningByLaser = False
      ' Elimino primo punto per prossimo grezzo
      m_bptLast = False
      ' Aggiorno visualizzazione
      EgtDraw()
      ' Disattivo il bottone chiudi grezzo
      CloseBtn.IsEnabled = False
   End Sub

   Private Sub RemoveDamagedArea()
      ' Elimino area rovinata selezionata
      EgtErase(m_nSelDmg)
      ' Dichiaro zona danneggiata non selezionata
      m_nSelDmg = GDB_ID.NULL
      ' Disabilito modalità rimuovi zona rovinata
      m_nPtDmgMode = DMGMODE.NONE
      ' Tolgo il check al bottone elimina
      DeleteBtn.IsChecked = False
   End Sub

   Private Sub NewBtn_Click(sender As Object, e As RoutedEventArgs) Handles NewBtn.Click
      ' Procedo solo se modalità aree danneggiate
      If Not DamagedBtn.IsChecked Then Return
      DeleteBtn.IsChecked = False
      m_nPtDmgMode = If(NewBtn.IsChecked(), DMGMODE.ADD, DMGMODE.NONE)
      AddBtn.IsChecked = False
      RemoveBtn.IsChecked = False
   End Sub

   Private Sub DeleteBtn_Click(sender As Object, e As RoutedEventArgs) Handles DeleteBtn.Click
      ' Procedo solo se modalità aree danneggiate
      If Not DamagedBtn.IsChecked Then Return
      ' Verifico ci sia almeno una zona rovinata
      If EgtGetFirstNameInGroup(m_CurrProjPage.m_nRawId, NAME_DAMAGED) = GDB_ID.NULL Then
         DeleteBtn.IsChecked = False
      End If
      NewBtn.IsChecked = False
      m_nPtDmgMode = If(DeleteBtn.IsChecked(), DMGMODE.REMOVE, DMGMODE.NONE)
      AddBtn.IsChecked = False
      RemoveBtn.IsChecked = False
   End Sub

#End Region

#Region "Circles"

   Private Sub UpdateCircles()
      ' Elimino vecchi punti finali
      EgtEmptyGroup(m_nTempLay)
      ' Identificativo curva
      Dim nId As Integer = GDB_ID.NULL
      If m_ActiveRawMode = RAWMODE.BY_POINTS Then
         nId = EgtGetFirstNameInGroup(m_CurrProjPage.m_nRawId, NAME_KERF)
      ElseIf m_ActiveRawMode = RAWMODE.DAMAGED Then
         nId = m_nSelDmg
      End If
      ' Verifico validità curva
      If nId = GDB_ID.NULL Then Return
      ' riferimento globale della stessa
      Dim frRef As New Frame3d
      EgtGetGlobFrame(nId, frRef)
      ' Recupero i punti finali delle diverse entità componenti
      Dim dU As Double = 1
      Dim ptP As Point3d
      While EgtAtParamPoint(nId, dU, ptP)
         ptP.ToGlob(frRef)
         CreateCircle(m_nTempLay, ptP)
         dU += 1
      End While
   End Sub

   Private Sub RemoveCircles()
      EgtEmptyGroup(m_nTempLay)
   End Sub

   Private Function CreateCircle(nLayerId As Integer, ptP As Point3d) As Boolean
      ' Aggiungo cerchio
      Dim nCircId As Integer = EgtCreateCircle(nLayerId, ptP, RAD_CIRCLE)
      EgtSetColor(nCircId, New Color3d(255, 0, 0))
      Return True
   End Function

#End Region

   Private Function CreateCross(nLayerId As Integer, ptP As Point3d) As Boolean
      ' Aggiungo crocette
      ptP += New Vector3d(0, 0, 0.15)
      Dim vtCrossX As New Vector3d(20, 0, 0)
      Dim vtCrossY As New Vector3d(0, 20, 0)
      Dim nCrossId1 = EgtCreateLine(nLayerId, ptP + (-vtCrossX), ptP + vtCrossX)
      EgtSetColor(nCrossId1, New Color3d(255, 0, 0))
      Dim nCrossId2 = EgtCreateLine(nLayerId, ptP + (-vtCrossY), ptP + vtCrossY)
      EgtSetColor(nCrossId2, New Color3d(255, 0, 0))
      Dim nPntId = EgtCreateGeoPoint(nLayerId, ptP)
      EgtSetColor(nPntId, New Color3d(255, 0, 0))
      Return True
   End Function

End Class
