Imports EgtUILib
Imports OmagCUT.MainWindow

Public Class SquaringUC

   ' Riferimenti a pagine
   Private m_MainWindow As MainWindow = DirectCast(Application.Current.MainWindow, MainWindow)
   Private WithEvents m_CurrProjPage As CurrentProjectPageUC
   ' Flag di pagina attiva
   Private m_bActive As Boolean = False
   ' Flag di simulazione in corso
   Private m_bSimul As Boolean = False

   ' Origine tavola e dati grezzo
   Private m_bRawOk As Boolean = False
   Private m_ptTabOri As Point3d
   Private m_ptRawMin As Point3d
   Private m_ptRawMax As Point3d
   ' Parametri P1 acquisito
   Private m_ptTipP1 As Point3d
   Private m_vtToolP1 As Vector3d
   ' Parametri P2 acquisito
   Private m_ptTipP2 As Point3d
   Private m_vtToolP2 As Vector3d
   ' Parametri della lavorazione
   Private m_bCutOk As Boolean = False
   Private m_dDepth As Double = 0
   Private m_dOffsetSquaring As Double = 150
   Private m_dExtraLength As Double = 0
   Private m_dAngO As Double = 180
   Private m_dAngV As Double = 0
   Private m_nNumX As Integer = 0
   Private m_dDimX As Double = 0
   Private m_nNumY As Integer = 0
   Private m_dDimY As Double = 0
   Private m_bHeadSide As Boolean = False

   ' Punto selezionato nel disegno
   Private m_ptPrev As Point3d
   ' Layer per crocette temporanee
   Private m_nTempLay As Integer = GDB_ID.NULL

   ' Costanti
   Private Const MAX_TAB_DEPTH As Double = 10.0
   Private Const MIN_CUT_LEN As Double = 10.0
   Private Const MAX_SIDE_ANG As Double = 60.0

   'Costante che indica il lato in cui posizionare i tagli
   Private Enum CutSide As Integer
      Left
      Right
   End Enum

   Private Sub GridCut_Initialized(sender As Object, e As EventArgs) Handles Me.Initialized
      OffsetTxBl.Text = EgtMsg(90228)        ' Offset
      ExtraLenTxBl.Text = EgtMsg(90260)      ' Extra length
      SimulBtn.ToolTip = EgtMsg(90301)       ' Simula
      OkBtn.ToolTip = EgtMsg(90230)          ' Esegui

      ' Carico i dati dell'ultimo taglio
      m_dOffsetSquaring = GetPrivateProfileDouble(S_DIRECTCUTS, K_DC_OFFSET_SQUARING, m_dOffsetSquaring, m_MainWindow.GetIniFile())
      m_dExtraLength = GetPrivateProfileDouble(S_DIRECTCUTS, K_DC_EXTRA_LEN_SQUARING, m_dExtraLength, m_MainWindow.GetIniFile())
      m_dDepth = 0
      m_dAngO = 90
      m_dAngV = GetPrivateProfileDouble(S_DIRECTCUTS, K_DC_GRID_ANGV, m_dAngV, m_MainWindow.GetIniFile())
      m_nNumX = 1
      m_dDimX = GetPrivateProfileDouble(S_DIRECTCUTS, K_DC_GRID_DIMX, m_dDimX, m_MainWindow.GetIniFile())
      m_nNumY = 1
      m_dDimY = GetPrivateProfileDouble(S_DIRECTCUTS, K_DC_GRID_DIMY, m_dDimY, m_MainWindow.GetIniFile())
      m_bHeadSide = False
   End Sub

   Private Sub Squaring_Loaded(sender As Object, e As RoutedEventArgs) Handles Me.Loaded
      ' Attivo la pagina
      m_CurrProjPage = m_MainWindow.m_CurrentProjectPageUC
      m_bActive = True
      ' Se rientro da simulazione
      If m_bSimul Then
         m_bSimul = False
         ' Disabilito registrazione progetto modificato
         EgtDisableModified()
         m_MainWindow.m_DirectCutPageUC.m_bShowMachine = False
         EgtSetMachineLook(MCH_LOOK.TAB)
         EgtDraw()
         Return
      End If
      ' Disabilito registrazione progetto modificato
      EgtDisableModified()
      ' Creo layer temporaneo per crocette
      m_nTempLay = EgtCreateGroup(GDB_ID.ROOT)
      EgtSetLevel(m_nTempLay, GDB_LV.TEMP)
      ' Origine tavola
      m_bRawOk = True
      If Not EgtGetTableRef(1, m_ptTabOri) Then
         m_bRawOk = False
         EgtOutLog("Error on TableRef1")
      End If

      ' Dati del grezzo
      If Not GetRawBox(m_ptRawMin, m_ptRawMax) Then
         m_bRawOk = False
         EgtOutLog("Error on RawBox")
      End If
      ' calcolo lalavorazione di squadratura
      RefreshSquaring()
   End Sub

   Private Sub RefreshSquaring()
      If Not m_bRawOk Then Return

      Dim m_ThickSaw As Double
      EgtTdbGetCurrToolParam(MCH_TP.THICK, m_ThickSaw)

      m_dDepth = CamAuto.GetRawHeight()
      m_dDimX = Math.Abs(m_ptRawMax.x - m_ptRawMin.x) - 2 * (m_dOffsetSquaring)
      m_dDimY = Math.Abs(m_ptRawMax.y - m_ptRawMin.y) - 2 * (m_dOffsetSquaring)

      Dim ptStart As New Point3d(m_ptRawMin.x + m_dOffsetSquaring - m_ThickSaw, m_ptRawMin.y + m_dOffsetSquaring, m_ptRawMin.z)
      Dim ptEnd As New Point3d(ptStart.x + m_dDimX, ptStart.y, m_ptRawMin.z)

      SetCoordVisibility(True)
      ShowCoord()

      OffsetTxBx.Text = LenToString(m_dOffsetSquaring, 1)
      ExtraLenTxBx.Text = LenToString(m_dExtraLength, 1)
      m_bCutOk = False
      UpdateSimulOkBtn()

      SquaringPoint(ptStart, ptEnd)
      m_ptPrev = ptStart
   End Sub

   Friend Sub Squaring_Unloaded(sender As Object, e As RoutedEventArgs) Handles Me.Unloaded
      ' Salvo i dati correnti
      ' Salvo i dati correnti
      WritePrivateProfileString(S_DIRECTCUTS, K_DC_OFFSET_SQUARING, DoubleToString(m_dOffsetSquaring, 2), m_MainWindow.GetIniFile())
      WritePrivateProfileString(S_DIRECTCUTS, K_DC_EXTRA_LEN_SQUARING, DoubleToString(m_dExtraLength, 2), m_MainWindow.GetIniFile())
      ' Se non vado in simulazione
      If Not m_bSimul Then
         ' Dichiaro sottopagina da non riattivare
         m_MainWindow.m_DirectCutPageUC.m_ControlsDirectCutUC.m_ActiveDirectCutPage = ControlsDirectCutUC.DirectCutPages.DirectCut
         ' Rimuovo layer temporaneo per crocette
         EgtErase(m_nTempLay)
         ' Rimuovo eventuale pezzo per taglio diretto
         EraseDirectCutPart()
         ' Riattivo eventuali lavorazioni presenti
         ActivateAllMachinings()
         ' Abilito registrazione progetto modificato
         EgtEnableModified()
         ' Nascondo la macchina
         m_MainWindow.m_DirectCutPageUC.m_bShowMachine = False
         EgtSetMachineLook(MCH_LOOK.TAB)
         EgtDraw()
      End If
      ' Dichiaro pagina non attiva
      m_bActive = False
   End Sub

   Private Sub UpdateSimulOkBtn()
      If m_bCutOk Then
         SimulBtn.IsEnabled = True
         SimulBtn.Foreground = Brushes.Black
         OkBtn.IsEnabled = True
         OkBtn.Foreground = Brushes.Black
      Else
         SimulBtn.IsEnabled = False
         SimulBtn.Foreground = Brushes.DarkGray
         OkBtn.IsEnabled = False
         OkBtn.Foreground = Brushes.DarkGray
      End If
   End Sub

   Private Sub SquaringPoint(ptMin As Point3d, ptMax As Point3d)
      ' Rimuovo eventuali crocette create acquisendo i punti nel disegno
      EgtEmptyGroup(m_nTempLay)
      ' Verifico configurazione tavola e grezzo
      If Not m_bRawOk Then Return

      ' Recupero dati utensile e testa corrente
      Dim sTool As String = ""
      Dim sHead As String = ""
      Dim nExit As Integer = 0
      EgtGetCalcTool(sTool, sHead, nExit)
      '------------- BOTTOM LEFT -------------------
      ' Assegno punto selezionato nel disegno a m_ptTipP1
      m_ptTipP1 = ptMin
      ' Porto il tip nell'origine tavola
      m_ptTipP1.ToLoc(New Frame3d(m_ptTabOri))
      ' Reimposto eventuale precedente utensile
      EgtSetCalcTool(sTool, sHead, nExit)
      '-------------  TOP RIGHT   -------------------
      ' Assegno punto selezionato nel disegno a m_ptTipP2
      m_ptTipP2 = ptMax
      ' Porto il tip nell'origine tavola
      m_ptTipP2.ToLoc(New Frame3d(m_ptTabOri))
      ' Reimposto eventuale precedente utensile
      EgtSetCalcTool(sTool, sHead, nExit)

      ' Se il secondo punto non coincide con il primo, disegno il taglio
      Dim vtDiff As Vector3d = m_ptTipP2 - m_ptTipP1
      vtDiff.z = 0
      Dim dLen As Double
      Dim dAngVertDeg As Double
      Dim dAngOrizzDeg As Double
      vtDiff.ToSpherical(dLen, dAngVertDeg, dAngOrizzDeg)
      If dLen > EPS_SMALL Then
         m_dAngO = dAngOrizzDeg
         CreateGridCut()
         ' visuliazzo tavola 
         m_MainWindow.m_DirectCutPageUC.m_bShowMachine = False
         EgtSetMachineLook(MCH_LOOK.TAB)
         EgtDraw()
      End If
   End Sub

   Private Sub OffsetTxBx_EgtClosed(sender As Object, e As EventArgs) Handles OffsetTxBx.EgtClosed
      ' Verifico che l'offset impostato non sia superiore a quello massimo
      Dim dMaxOffset As Double = Math.Min(m_dDimX, m_dDimY) / 2 - 15
      Dim dOffset As Double = 0
      StringToLen(OffsetTxBx.Text, dOffset)
      If dOffset < 0 Then
         dOffset = 0
      ElseIf dOffset > dMaxOffset Then
         dOffset = dMaxOffset
      End If
      m_dOffsetSquaring = dOffset
      OffsetTxBx.Text = LenToString(m_dOffsetSquaring, 2)
      ' Disegno il taglio
      RefreshSquaring()
      EgtDraw()
   End Sub

   Private Sub ExtraLength_EgtClosed(sender As Object, e As EventArgs) Handles ExtraLenTxBx.EgtClosed
      ' Verifico che il valore indicato sia almeno maggiore dell'offset indicato
      Dim dOffset As Double = 0
      StringToLen(OffsetTxBx.Text, dOffset)
      Dim MadExtraLeng As Double = Math.Abs(dOffset)
      Dim dExtraLen As Double
      StringToLen(ExtraLenTxBx.Text, dExtraLen)
      If dExtraLen < 0 AndAlso dExtraLen < -MadExtraLeng Then
         dExtraLen = 0
      End If
      m_dExtraLength = dExtraLen
      ExtraLenTxBx.Text = LenToString(m_dExtraLength, 2)
      ' Disegno il taglio
      RefreshSquaring()
      EgtDraw()
   End Sub

   Private Sub SimulBtn_Click(sender As Object, e As RoutedEventArgs) Handles SimulBtn.Click
      ' Verifico ci sia un taglio valido
      If Not m_bCutOk Then Return
      ' Salvo il progetto con le lavorazioni
      EgtSetCurrentContext(m_CurrProjPage.CurrentProjectScene.GetCtx())
      Dim sMchPath As String = m_MainWindow.GetTempDir() & "\" & "DirectProj.nge"
      m_MainWindow.m_CurrentProjectPageUC.SaveFile(sMchPath, False)
      ' Predispongo passaggio a simulazione
      m_bSimul = True
      m_CurrProjPage.m_SceneButtons.MeasureBtn.IsChecked = False
      m_CurrProjPage.CurrProjGrid.Visibility = Windows.Visibility.Hidden
      m_MainWindow.m_DirectCutPageUC.m_ControlsDirectCutUC.LeftButtonGrid.Children.Remove(Me)
      m_CurrProjPage.CurrentProjectPageGrid.Children.Remove(m_MainWindow.m_DirectCutPageUC)
      m_MainWindow.m_PrevActivePage = MainWindow.Pages.DirectCut
      m_CurrProjPage.CurrentProjectPageGrid.Children.Add(m_MainWindow.m_SimulationPage)
      m_MainWindow.m_ActivePage = MainWindow.Pages.Simulation
   End Sub

   Private Sub OkBtn_Click(sender As Object, e As RoutedEventArgs) Handles OkBtn.Click
#If TRIAL Then
      m_CurrProjPage.SetWarningMessage("Trial Version")
#Else
      ' Verifico non sia versione Ufficio
      If m_MainWindow.GetKeyOption(MainWindow.KEY_OPT.OFFICE_TYPE) Then
         m_CurrProjPage.SetWarningMessage("Office Version")
         Return
      End If
      ' Verifico ci sia un taglio valido
      If Not m_bCutOk Then Return
      ' Salvo il progetto con le lavorazioni
      Dim sMchPath As String = m_MainWindow.GetTempDir() & "\" & "DirectProj.nge"
      m_MainWindow.m_CurrentProjectPageUC.SaveFile(sMchPath, False)
      ' Genero file CNC (lancio anche se errore in precedenza)
      Dim sCncPath As String = m_MainWindow.GetCncDir() & "\DirectCut" & m_MainWindow.m_CurrentMachine.sIsoFileExt
      Dim bOk As Boolean = EgtGenerate(sCncPath, "OmagCut ver." & m_MainWindow.GetVersion())
      ' Se errore in generazione, segnalo l'errore ed esco
      If Not bOk Then
         m_CurrProjPage.SetErrorMessage(EgtMsg(90314))       'Errore nella generazione del programma CN
         Return
      End If
      Dim sNameProg As Integer = 900
      sNameProg = GetPrivateProfileInt(S_PARTPROGRAM, "NameProg", sNameProg, m_MainWindow.GetMachIniFile)
      ' Download programma (eventuali errori sono segnalati dalla funzione)
      If m_MainWindow.m_CNCommunication.SendProgram(sCncPath, sNameProg) Then
         ' copio il progetto corrente come progetto in lavorazione
         Dim sWrkPath As String = m_MainWindow.GetTempDir() & "\" & "WorkProj.nge"
         My.Computer.FileSystem.CopyFile(sMchPath, sWrkPath, True)
         ' lancio eventuale lua post-trasmissione
         m_MainWindow.ExecSentProgScript(True)
      End If
#End If
   End Sub

   Private Sub ExitBtn_Click(sender As Object, e As RoutedEventArgs) Handles ExitBtn.Click
      m_MainWindow.m_DirectCutPageUC.m_ControlsDirectCutUC.LeftButtonGrid.Children.Remove(Me)
   End Sub

   Private Function CreateGridCut() As Boolean
      ' Verifico sia definito il punto iniziale e il grezzo
      If Not m_bRawOk Then
         m_bCutOk = False
         Return False
      End If
      ' Spessore grezzo
      Dim dRawHeight As Double = m_ptRawMax.z - m_ptRawMin.z
      ' Rimuovo eventuale vecchio pezzo per taglio diretto
      EraseDirectCutPart()
      ' Disattivo eventuali lavorazioni presenti
      DeactivateAllMachinings()
      ' Creo nuovo pezzo per il taglio diretto
      Dim nPartId = EgtCreateGroup(GDB_ID.ROOT)
      EgtSetName(nPartId, NAME_DIRECTCUT)
      Dim nLayerId = EgtCreateGroup(nPartId)
      EgtSetName(nLayerId, NAME_OUTLOOP)
      ' Creo il taglio parallelo alla lama
      Dim ptStart As Point3d = m_ptTipP1
      ptStart.z = 0
      ' Funzione che crea i tagli successivi al primo
      MultiplyCut(nLayerId)
      ' Calcolo punto di inserimento nel grezzo
      Dim ptMin, ptMax As Point3d
      EgtGetBBoxGlob(nPartId, GDB_BB.STANDARD, ptMin, ptMax)
      Dim ptIns As Point3d = ptMin + (m_ptTabOri - m_ptRawMin)
      ptIns.z = dRawHeight
      ' Inserisco il pezzo nel grezzo
      EgtAddPartToRawPart(nPartId, ptIns, m_MainWindow.m_CurrentProjectPageUC.m_nRawId)
      ' Inserisco la lavorazione
      m_bCutOk = AddMachinings(nPartId) AndAlso UpdateAllMachiningsToolpaths()
      EgtSetCurrPhase(1)
      ' Eventuale eliminazione Home finale
      If Not m_MainWindow.m_CurrentMachine.bDirectCutsFinalHome Then
         RemoveFinalHome()
      End If
      UpdateSimulOkBtn()
      Return m_bCutOk
   End Function

   Private Function MultiplyCut(nLayerId As Integer) As Boolean
      ' Recupero lo spessore del taglio della lama o del waterjet correntemente attiva
      Dim nType As Integer = 0
      EgtTdbGetCurrToolParam(MCH_TP.TYPE, nType)
      Dim dThick As Double = 0
      EgtTdbGetCurrToolParam(If(nType = MCH_TY.SAW_STD, MCH_TP.THICK, MCH_TP.DIAM), dThick)
      EgtOutLog("Curr tool type in use for squaring: " & If(nType = MCH_TY.SAW_STD, "SAW_STD", "NOT 'SAW_STD'"))
      ' Ricalcolo lo spessore in base all'inclinazione
      dThick = dThick / Math.Cos(m_dAngV * Math.PI / 180)
      ' Imposto angolo di rotazione a seconda del lato dei tagli paralleli
      Dim dRotAngOX As Double = 90
      ' Recupero dati da interfaccia
      Dim dDimPzX As Double = m_dDimX
      Dim nNumPzX As Integer = m_nNumX
      Dim dDimPzY As Double = m_dDimY
      Dim nNumPzY As Integer = m_nNumY
      ' Definisco vettore di spostamento
      Dim vtDelta As Vector3d
      ' Calcolo primo taglio parallelo
      Dim ptStart As Point3d = m_ptTipP1
      ptStart.z = 0
      If dDimPzY <> 0 And nNumPzY > 0 And dDimPzX <> 0 And nNumPzX > 0 Then
         Dim dLenX As Double = dThick + (dDimPzX + dThick) * nNumPzX
         Dim nCutParaId = EgtCreateLinePDL(nLayerId, ptStart, m_dAngO, dLenX + 0.1)
         ' Inidico che è un taglio Diretto di tipo Squaring
         EgtSetInfo(nCutParaId, INFO_DIRECTCUT, FlagDirectCuts.Squaring)
         ' Imposto affondamento e angolo di fianco sul taglio (solo se non lama STD)
         If Not nType = MCH_TY.SAW_STD Then
            EgtSetInfo(nCutParaId, INFO_DEPTH, m_dDepth)
            EgtSetInfo(nCutParaId, INFO_SIDE_ANGLE, m_dAngV)
            EgtOutLog("Curr tool in use is not of type SAW_STD: Depth is limited to raw thickness")
         End If
         ' Allungo la geometria
         EgtExtendCurveStartByLen(nCutParaId, m_dOffsetSquaring + m_dExtraLength)
         EgtExtendCurveEndByLen(nCutParaId, m_dOffsetSquaring + +m_dExtraLength)
         ' Calcolo vettore di spostamento
         vtDelta = Vector3d.FromPolar((dDimPzY + dThick), m_dAngO)
         ' Ruoto il vettore di traslazione 
         vtDelta.Rotate(Vector3d.Z_AX, dRotAngOX)
         For Index As Integer = 1 To nNumPzY
            Dim vtPerpMove As Vector3d = Index * vtDelta
            ' Creo copie
            Dim nCut2Id = EgtCopyGlob(nCutParaId, nLayerId)
            EgtMove(nCut2Id, vtPerpMove, GDB_RT.GLOB)
         Next
         ' Calcolo primo taglio perpendicolare
         Dim dLenY As Double = dThick + (dDimPzY + dThick) * nNumPzY
         ' Arretro il punto di partenza di uno spessore lama
         Dim vtDeltaPos As Vector3d = Vector3d.FromPolar(dThick + 0.1, m_dAngO - 90)
         Dim nCutPerpId = EgtCreateLinePDL(nLayerId, ptStart + vtDeltaPos, m_dAngO + 90, dLenY + 0.2)
         ' Imposto affondamento e angolo di fianco sul taglio
         EgtSetInfo(nCutPerpId, INFO_DEPTH, m_dDepth)
         EgtSetInfo(nCutPerpId, INFO_SIDE_ANGLE, m_dAngV)
         ' Allungo la geometria
         EgtExtendCurveStartByLen(nCutPerpId, m_dOffsetSquaring + m_dExtraLength)
         EgtExtendCurveEndByLen(nCutPerpId, m_dOffsetSquaring + +m_dExtraLength)
         ' Calcolo secondo vettore di spostamento
         vtDelta = Vector3d.FromPolar((dDimPzX + dThick), m_dAngO)
         For Index As Integer = 1 To nNumPzX
            Dim vtPerpMove As Vector3d = vtDelta * Index
            ' Creo copie
            Dim nCut3Id = EgtCopyGlob(nCutPerpId, nLayerId)
            EgtMove(nCut3Id, vtPerpMove, GDB_RT.GLOB)
         Next
      End If
      Return True
   End Function

   Private Sub SetCoordVisibility(bShow As Boolean)
      XcoordTxBl.Visibility = If(bShow, Windows.Visibility.Visible, Windows.Visibility.Hidden)
      XcoordTxBx.Visibility = If(bShow, Windows.Visibility.Visible, Windows.Visibility.Hidden)
      YcoordTxBl.Visibility = If(bShow, Windows.Visibility.Visible, Windows.Visibility.Hidden)
      YcoordTxBx.Visibility = If(bShow, Windows.Visibility.Visible, Windows.Visibility.Hidden)
   End Sub

   Private Sub ShowCoord()
      Dim ptText As Point3d = m_ptPrev
      ptText.ToLoc(New Frame3d(m_ptTabOri))
      XcoordTxBx.Text = LenToString(ptText.x, 2)
      YcoordTxBx.Text = LenToString(ptText.y, 2)
   End Sub

   Private Function SetMachineInCurrPos() As Boolean
      ' 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
      ' Recupero il nome degli assi macchina
      Dim sL1 As String = String.Empty
      Dim sL2 As String = String.Empty
      Dim sL3 As String = String.Empty
      Dim sR1 As String = String.Empty
      Dim sR2 As String = String.Empty
      If Not m_MainWindow.m_CNCommunication.GetAxesNames(sL1, sL2, sL3, sR1, sR2) Then Return False
      ' Visualizzo macchina in posizione
      EgtSetAxisPos(sL1, dL1)
      EgtSetAxisPos(sL2, dL2)
      EgtSetAxisPos(sL3, dL3)
      EgtSetAxisPos(sR1, dR1)
      EgtSetAxisPos(sR2, dR2)
      Return True
   End Function

End Class

