Files
DataBeam/LuaLibs/ProcessLapJointNew.lua
T
DarioS b51487f5af DataBeam :
- modifiche per ottimizzazione con più teste
- modifiche per compilazione.
2022-05-09 20:42:45 +02:00

5166 lines
221 KiB
Lua

-- ProcessLapJoint.lua by Egaltech s.r.l. 2022/01/28
-- Gestione calcolo mezzo-legno per Travi
-- 2019/10/08 Agg. gestione OpenPocket.
-- 2021/01/24 Con sega a catena ora sempre impostato asse A.
-- 2021/02/03 Corretto riconoscimento feature di coda.
-- 2021/02/04 Razionalizzata gestione forzatura lama. Corretta gestione diametro minimo utensile per svuotatura.
-- 2021/03/04 Due facce con testa da sotto.
-- 2021/03/20 Piccole correzioni.
-- 2021/03/22 Modificata gestione caso due facce lunghe come la trave con trave corta.
-- 2021/04/13 Modificata gestione fessura U con sega a catena (corta ora ok, lunga ancora da correggere).
-- 2021/04/14 Correzioni ribasso a U con fresa da sotto.
-- 2021/04/15 Aggiunta gestione massima lunghezza fresa da sotto su svuotature.
-- 2021/04/21 Anche feature lunga con due facce con opzione lama ora si taglia con lama.
-- 2021/04/23 Corretto caso con antischeggia non inseriti perchè inutili.
-- 2021/04/27 Antischeggia solo se feature trasversali.
-- 2021/05/12 Semplificata gestione diametro minimo utensile per svuotatura.
-- 2021/06/04 Su U passante con faccia perpendicolare aggiunta si forza Pocket.
-- 2021/06/11 Su U passante e profonda se non bastano due svuotature su faccia ortogonale si fa anche la faccia di fondo per quanto possibile.
-- 2021/06/21 Nel caso precedente si fa la terza svuotatura anche se è possibile fare una sola delle prime due (altra da sotto).
-- 2021/06/21 Gestione ripresa spigoli o contorno con fresa più piccola ( diametro < 3/4 utensile svuotatura) attivata da parametro Q.
-- 2021/07/02 Migliorie e correzioni su svuotature e pulitura spigoli.
-- 2021/07/15 Aggiunti antischeggia con fresa.
-- 2021/09/08 Aggiunta gestione parametro Q04 per i tagli di lama lungo facce lunghe (con o senza facce di chiusura)
-- 2021/09/21 Aggiunta lavorazione/opzione "lamello" con le feature 16, 30, 32, 39,
-- che si attiva abilitando il check al tipo milling: SideMillAsBlade (SideMillAsBlade_2)
-- 2021/09/23 Gestione migliorata lavorazioni BH (blockhaus) su macchina fast BH,
-- migliorata applicazione lavorazioni BH su feature lunghe lavorte a passi
-- 2021/10/06 Ad antischeggia con lama in presenza di testa da sotto aggiunta preferenza a testa da sopra.
-- 2021/10/19 Corretta gestione inversione per Tunnel. OpenPocket anche se spezzato ma 1 o 2 facce. Introdotta lunghezza minima per lamello.
-- 2021/10/21 Migliorato controllo affondamento utensile in U lavorato da 3 parti (anche da sotto).
-- 2021/10/27 Migliorato calcolo asse tunnel o similare.
-- 2021/11/02 In svuotatura con lati aperti diametro fresa non superiore al doppio del lato piccolo.
-- 2021/11/15 Quando si usa sega a catena uso Q10 come massima elevazione.
-- 2021/11/22 Corretta segnalazione warning su foro di L20 e L25.
-- 2021/12/17 Lettura parametri Q una volta sola all'inizio.
-- 2022/01/13 Estrapolazione da MakeMoreFaces() di MakeTwoFaces() e MakeThreeFaces(), e varie ottimizzazioni.
-- 2022/01/19 Cambiata % lunghezza pezzo per spezzatura. Tolta correzione spessore fresa a disco con superficie da lavorare verso Z-.
-- 2022/01/26 Migliorato controllo uso testa da sotto nel caso due facce con lama.
-- 2022/01/28 Aggiunte funzioni DoClean, DoPocketing, DoHeadChainSaw, DoSideChainSaw e DoHeadCut.
-- Tabella per definizione modulo
local ProcessLapJoint = {}
-- Include
require( 'EgtBase')
local BL = require( 'BeamLib')
local Fbs = require( 'FacesBySaw')
local Cut = require( 'ProcessCut')
local DoubleCut = require( 'ProcessDoubleCut')
local LongCut = require( 'ProcessLongCut')
local Long2Cut = require( 'ProcessLongDoubleCut')
EgtOutLog( ' ProcessLapJoint started', 1)
-- Dati
local BD = require( 'BeamData')
local ML = require( 'MachiningLib')
-- variabili assegnazione parametri Q
local Q_FORCE_BLADE = nil -- i
local Q_DEPTH_CHAMFER = 0.0 -- d
local Q_MAX_ELEVATION = 0.0 -- d
local Q_ONLY_CHAMFER = 0 -- i
local Q_USE_MILL = 0 -- i
local Q_USE_ROUGH_TOOL = 0 -- i
local Q_USE_ROUGH_TOOL_B90 = 0 -- i
local Q_USE_ROUGH_TOOL_B0 = 0 -- i
local Q_BORE_ON_CORNER = 0 -- i
local Q_CONTOUR_SMALL_TOOL = 0 -- i
local Q_ONLY_CONTOUR = 0 -- i
local Q_SIDE_ROUGH_TOOL = 0 -- i
local Q_ANTISPLINT_TYPE = 0 -- i
local Q_BLADE_ON_ALONG_FACE = 0 -- i
-- variabile smussi
local _bMadeChamfer
local _nChamfer, _dDepthCham, _sErrCham, _bForceUseBlade
-- Settaggi interni
local _bTrySidePocketAtFirst = true
local _nPhase, _nRawId, _nPartId, _dOvmHead
local _b3Raw, _b3Solid
local _nAddGrpId
---------------------------------------------------------------------
-- Riconoscimento della feature
function ProcessLapJoint.Identify( Proc)
return ( (( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 16) or
(( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 17) or
(( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 20) or
(( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 25) or
(( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 30) or
(( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 32) or
(( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 33) or
(( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 34) or
( Proc.Grp == 4 and Proc.Prc == 37) or
( Proc.Grp == 4 and Proc.Prc == 39) or
( Proc.Grp == 4 and Proc.Prc == 120))
end
---------------------------------------------------------------------
local function AssignQValues( Proc)
-- reset assegnazione parametri Q
Q_FORCE_BLADE = nil
Q_BLADE_ON_ALONG_FACE = 0
Q_DEPTH_CHAMFER = 0.0
Q_ONLY_CHAMFER = 0
Q_USE_MILL = 0
Q_USE_ROUGH_TOOL = 0
Q_USE_ROUGH_TOOL_B90 = 0
Q_USE_ROUGH_TOOL_B0 = 0
Q_BORE_ON_CORNER = 0
Q_CONTOUR_SMALL_TOOL = 0
Q_ONLY_CONTOUR = 0
Q_SIDE_ROUGH_TOOL = 0
Q_ANTISPLINT_TYPE = 0
Q_MAX_ELEVATION = EgtGetInfo( Proc.Id, 'Q10', 'd') or 0.0
if ( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 16 then
Q_FORCE_BLADE = EgtGetInfo( Proc.Id, 'Q01', 'i') -- can be nil
Q_DEPTH_CHAMFER = EgtGetInfo( Proc.Id, 'Q04', 'd') or 0.0
Q_ONLY_CHAMFER = EgtGetInfo( Proc.Id, 'Q05', 'i') or 0
elseif ( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 17 then
Q_DEPTH_CHAMFER = EgtGetInfo( Proc.Id, 'Q01', 'd') or 0.0
Q_ONLY_CHAMFER = EgtGetInfo( Proc.Id, 'Q02', 'i') or 0
elseif ( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 20 then
Q_DEPTH_CHAMFER = EgtGetInfo( Proc.Id, 'Q01', 'd') or 0.0
Q_USE_MILL = EgtGetInfo( Proc.Id, 'Q02', 'i') or 0
Q_USE_ROUGH_TOOL = EgtGetInfo( Proc.Id, 'Q03', 'i') or 0
Q_USE_ROUGH_TOOL_B90 = EgtGetInfo( Proc.Id, 'Q04', 'i') or 0
Q_USE_ROUGH_TOOL_B0 = EgtGetInfo( Proc.Id, 'Q05', 'i') or 0
Q_BORE_ON_CORNER = EgtGetInfo( Proc.Id, 'Q06', 'i') or 0
elseif ( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 25 then
Q_BORE_ON_CORNER = EgtGetInfo( Proc.Id, 'Q01', 'i') or 0
elseif ( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 30 then
Q_CONTOUR_SMALL_TOOL = EgtGetInfo( Proc.Id, 'Q01', 'i') or 0
Q_ONLY_CONTOUR = EgtGetInfo( Proc.Id, 'Q02', 'i') or 0
Q_SIDE_ROUGH_TOOL = EgtGetInfo( Proc.Id, 'Q03', 'i') or 0
Q_BLADE_ON_ALONG_FACE = EgtGetInfo( Proc.Id, 'Q04', 'i') or 0
Q_ANTISPLINT_TYPE = EgtGetInfo( Proc.Id, 'Q06', 'i') or 0
Q_DEPTH_CHAMFER = EgtGetInfo( Proc.Id, 'Q07', 'd') or 0.0
elseif ( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 32 then
Q_SIDE_ROUGH_TOOL = EgtGetInfo( Proc.Id, 'Q01', 'i') or 0
Q_CONTOUR_SMALL_TOOL = EgtGetInfo( Proc.Id, 'Q02', 'i') or 0
Q_ANTISPLINT_TYPE = EgtGetInfo( Proc.Id, 'Q06', 'i') or 0
elseif ( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 34 then
Q_CONTOUR_SMALL_TOOL = EgtGetInfo( Proc.Id, 'Q01', 'i') or 0
Q_ANTISPLINT_TYPE = EgtGetInfo( Proc.Id, 'Q06', 'i') or 0
end
end
---------------------------------------------------------------------
local function EvaluateChamfer()
local sErr
-- verifico che lo smusso sia richiesto
local nChamfer = 0
if Q_DEPTH_CHAMFER > 0 then
nChamfer = 1
end
-- verifico se posso fare solo lo smusso
if Q_ONLY_CHAMFER == 1 then
if Q_DEPTH_CHAMFER > 0 then
nChamfer = nChamfer + 1
-- altrimenti se non ho l'affondamento esco
else
sErr = 'Error : no chamfer depth'
EgtOutLog( sErr)
return -1, dDepth, sErr
end
end
-- verifico se devo usare lama invece della sega-catena
-- 2020-03-20 forzata abilitazione uso lama se parametro Q non è presente
-- xxxx-xx-xx tolta la preferenza alla lama in favore della sega-catena per un caso particolare
-- 2021-02-15 re-introdotta la preferenza alla lama se non c'è il parametro Q. Rimane da
-- implementare un ulteriore parametro per poter scegliere di prediligere la sega-catena o no al fine di continuare
-- a cambiare il codice per gestire il caso particolare
local bForceUseBlade = false
if Q_FORCE_BLADE == nil or Q_FORCE_BLADE == 1 then
bForceUseBlade = true
end
return nChamfer, dDepth, sErr, bForceUseBlade
end
---------------------------------------------------------------------
local function InitGlob( Proc, nPhase, nRawId, nPartId, dOvmHead)
if not Proc then
return false, 'Error : Proc is missing'
end
-- setto a nil la variabile smussi
_bMadeChamfer = nil
_nPhase = nPhase
_nRawId = nRawId
_nPartId = nPartId
_dOvmHead = dOvmHead
if _nRawId then
-- recupero l'ingombro del grezzo di appartenenza
_b3Raw = EgtGetRawPartBBox( _nRawId)
end
if not _nPartId then
_nPartId = EgtGetParent( EgtGetParent( Proc.Id) or GDB_ID.NULL)
end
if _nPartId then
-- recupero gruppo per geometria addizionale
_nAddGrpId = BL.GetAddGroup( _nPartId)
-- recupero l'ingombro della trave
_b3Solid = EgtGetBBoxGlob( EgtGetFirstNameInGroup( _nPartId, 'Box') or GDB_ID.NULL, GDB_BB.STANDARD)
else
local sErr = 'Error : part ID not found'
EgtOutLog( sErr)
return false, sErr
end
if not _b3Solid then
local sErr = 'Error : part box not found'
EgtOutLog( sErr)
return false, sErr
end
if not _nAddGrpId then
local sErr = 'Error : missing AddGroup'
EgtOutLog( sErr)
return false, sErr
end
-- leggo i valori dei parametri Q
AssignQValues( Proc)
-- verifico se sono presenti i parametri per la profondità smusso e
-- per eseguire in esclusiva solo lo smusso
_nChamfer, _dDepthCham, _sErrCham, _bForceUseBlade = EvaluateChamfer()
return true, ''
end
---------------------------------------------------------------------
local function UpdateFacet1Data( nProcId, tFData, nFacInd, dFacElev)
if not tFData then
tFData = {}
end
tFData.nFacInd = nFacInd
if dFacElev then
tFData.dFacElev = dFacElev
end
if tFData.nFacInd and tFData.nFacInd > -1 then
tFData.ptC, tFData.vtN = EgtSurfTmFacetCenter( nProcId, tFData.nFacInd, GDB_ID.ROOT)
tFData.rfFac, tFData.dH, tFData.dV = EgtSurfTmFacetMinAreaRectangle( nProcId, tFData.nFacInd, GDB_ID.ROOT)
end
return tFData
end
---------------------------------------------------------------------
local function UpdateFacet2Data( nProcId, tFData, nFacInd2, dFacElev2)
if not tFData then
tFData = {}
end
tFData.nFacInd2 = nFacInd2
if dFacElev2 then
tFData.dFacElev2 = dFacElev2
end
if tFData.nFacInd2 and tFData.nFacInd2 ~= true and tFData.nFacInd2 > -1 then
tFData.ptC2, tFData.vtN2 = EgtSurfTmFacetCenter( nProcId, tFData.nFacInd2, GDB_ID.ROOT)
tFData.rfFac2, tFData.dH2, tFData.dV2 = EgtSurfTmFacetMinAreaRectangle( nProcId, tFData.nFacInd2, GDB_ID.ROOT)
end
return tFData
end
---------------------------------------------------------------------
local function GetFacetsData( nProcId)
local tFData = {}
local nFacInd, dFacElev, nFacInd2, dFacElev2 = BL.GetFaceWithMostAdj( nProcId, _nPartId)
if nFacInd then
tFData = UpdateFacet1Data( nProcId, tFData, nFacInd, dFacElev)
tFData = UpdateFacet2Data( nProcId, tFData, nFacInd2, dFacElev2)
if tFData.nFacInd == -1 and tFData.nFacInd2 and tFData.nFacInd2 == true then
tFData.isOrthoFaces = true
end
end
return tFData
end
---------------------------------------------------------------------
local function SwapFacetsData( tFData)
if tFData then
tFData.nFacInd, tFData.nFacInd2 = tFData.nFacInd2, tFData.nFacInd
tFData.dFacElev, tFData.dFacElev2 = tFData.dFacElev2, tFData.dFacElev
tFData.ptC, tFData.ptC2 = tFData.ptC2, tFData.ptC
tFData.vtN, tFData.vtN2 = tFData.vtN2, tFData.vtN
tFData.rfFac, tFData.rfFac2 = tFData.rfFac2, tFData.rfFac
tFData.dH, tFData.dH2 = tFData.dH2, tFData.dH
tFData.dV, tFData.dV2 = tFData.dV2, tFData.dV
end
return tFData
end
---------------------------------------------------------------------
local function GetToolInfoForMachining( sMachiningName)
if EgtMdbSetCurrMachining( sMachiningName) then
local toolInfo = {}
toolInfo.sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID)
if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( toolInfo.sTuuid) or '') then
toolInfo.dLength = EgtTdbGetCurrToolParam( MCH_TP.LEN)
toolInfo.dDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM)
toolInfo.dThDiam = EgtTdbGetCurrToolThDiam()
toolInfo.dMaxMat = EgtTdbGetCurrToolParam( MCH_TP.MAXMAT)
toolInfo.dMaxDepth = EgtTdbGetCurrToolMaxDepth()
toolInfo.dSideDepth = EgtTdbGetCurrToolValInNotes( MCH_TP.USERNOTES, 'SIDEDEPTH', 'd')
toolInfo.dCornerRad = EgtTdbGetCurrToolParam( MCH_TP.CORNRAD)
toolInfo.dThick = EgtTdbGetCurrToolParam( MCH_TP.THICK)
return toolInfo
end
end
return nil
end
---------------------------------------------------------------------
local function FormatWarning( sWarn, sWarn2)
if sWarn2 then
if not sWarn then sWarn = '' end
sWarn = EgtIf( #sWarn > 0, sWarn .. '\n' .. sWarn2, sWarn2)
end
return sWarn
end
---------------------------------------------------------------------
-- Restituisce solo gli indici delle facce adiacenti esistenti (no -1)
local function GetValidFacetAdjacencies( nSurfId, nFacet)
local vValidAdj
local vFacAdj = EgtSurfTmFacetAdjacencies( nSurfId, nFacet)[1]
if vFacAdj then
vValidAdj = {}
for j = 1, #vFacAdj do
if vFacAdj[j] >= 0 then
table.insert( vValidAdj, vFacAdj[j])
end
end
end
return vValidAdj
end
---------------------------------------------------------------------
local function TestElleShape3( Proc, bNotProc)
local nNumFacet
local nProcId
-- se non passato il Proc vero e proprio
if bNotProc then
nProcId = Proc
nNumFacet = EgtSurfTmFacetCount( nProcId)
else
nProcId = Proc.Id
nNumFacet = Proc.Fct
end
-- valida solo nel caso di tre facce
if nNumFacet ~= 3 then return false end
-- determino se L con una faccia terminale o U con tre facce
local bIsL = true
for i = 1, 3 do
-- conto le facce adiacenti (solo quelle valide)
local vFacAdj = GetValidFacetAdjacencies( nProcId, i - 1)
if #vFacAdj == 1 then
bIsL = false
break
end
end
return bIsL
end
---------------------------------------------------------------------
local function TestElleShape4( Proc)
-- valida solo nel caso di quattro facce
if Proc.Fct ~= 4 then return false end
-- determino se L con due facce terminali o O
local nFac3Adj = 0
local dMinArea3 = GEO.INFINITO * GEO.INFINITO
local dMaxArea2 = 0
for i = 1, 4 do
-- conto le facce adiacenti (solo quelle valide)
local vFacAdj = GetValidFacetAdjacencies( Proc.Id, i - 1)
local _, dH, dV = EgtSurfTmFacetMinAreaRectangle( Proc.Id, i - 1, GDB_ID.ROOT)
local dArea = dH * dV
if #vFacAdj == 2 then
dMaxArea2 = max( dMaxArea2, dArea)
elseif #vFacAdj == 3 then
dMinArea3 = min( dMinArea3, dArea)
nFac3Adj = nFac3Adj + 1
end
end
if nFac3Adj ~= 2 then return false end
-- verifico se L profonda oppure lunga
if dMinArea3 < 2 * dMaxArea2 then
return 1
else
return 2
end
end
---------------------------------------------------------------------
--- Test per facce a forma di U o a forma di L
local function TestUL( Proc)
local bIsU = ( Proc.Fct == 3 and not TestElleShape3( Proc))
-- verifico se due facce o L con una o due facce di terminazione
local bIsL = ( Proc.Fct == 2 or TestElleShape3( Proc) or TestElleShape4( Proc) == 2)
return bIsU, bIsL
end
---------------------------------------------------------------------
local function GetIdIniEndPoints( ptP1, ptP2, tFac)
local nIdIniPoint
local nIdEndPoint
if ptP1 and ptP2 then
if dist( ptP1, tFac[4]) < GEO.EPS_SMALL or dist( ptP2, tFac[4]) < GEO.EPS_SMALL then
nIdEndPoint = 4
nIdIniPoint = 5
elseif dist( ptP1, tFac[5]) < GEO.EPS_SMALL or dist( ptP2, tFac[5]) < GEO.EPS_SMALL then
nIdEndPoint = 5
nIdIniPoint = 4
end
end
return nIdIniPoint, nIdEndPoint
end
---------------------------------------------------------------------
local function GetChainSawBlockedAxis( nInd)
if BD.GetChainSawBlockedAxis then
return BD.GetChainSawBlockedAxis( nInd)
else
if nInd == 1 then
return EgtIf( BD.C_SIMM, 'A=90', 'A=0')
else
return EgtIf( BD.C_SIMM, 'A=0', 'A=90')
end
end
end
---------------------------------------------------------------------
local function GetChainSawInitAngs( vtN, vtO)
if BD.GetChainSawInitAngs then
return BD.GetChainSawInitAngs( vtN, vtO)
else
if BD.C_SIMM then
if vtN:getY() > 0 then
return 'C=180'
else
return 'C=-180'
end
else
return ''
end
end
end
---------------------------------------------------------------------
local function VerifyChainSaw( dMinDim, dMaxDim)
local bUseChainSaw = false
local sMchFind = 'Sawing'
local sSawing = ML.FindSawing( sMchFind)
local dMaxMat = 0
local dSawCornerRad = 0
local dSawThick = 0
local dMaxDepth = 200
-- se non trova una lavorazione di sawing esco
if not sSawing then
return bUseChainSaw
else
-- recupero i dati dell'utensile
local dToolLength = 0
local dSawWidth = 75
local TI = GetToolInfoForMachining( sSawing)
if TI then
dToolLength = TI.dLength or dToolLength
dMaxMat = TI.dMaxMat or dMaxMat
dSawWidth = TI.dDiam or dSawWidth
dSawThick = TI.dThick or dSawThick
dSawCornerRad = TI.dCornerRad or dSawCornerRad
dMaxDepth = TI.dMaxDepth or dMaxDepth
if dSawThick < ( dMinDim + 10 * GEO.EPS_SMALL) and dSawWidth < ( dMaxDim + 10 * GEO.EPS_SMALL) then
bUseChainSaw = true
end
end
end
return bUseChainSaw, sSawing, dMaxMat, dSawCornerRad, dSawThick, dMaxDepth
end
---------------------------------------------------------------------
local function VerifyPocket( dDiam, dDepth, dMaxTotLen, sMchFindMaster, bPocketUp, bPocketDown)
-- tipo di svuotatura
local sMchFind = EgtIf( sMchFindMaster and #sMchFindMaster > 0, sMchFindMaster, 'Pocket')
-- ricerca della svuotatura
local sPocketing
if dDepth then
sPocketing, _, _, bPocketDown = ML.FindPocketing( sMchFind, dDiam, dDepth, dMaxTotLen) or
ML.FindPocketing( sMchFind, dDiam, 0.8 * dDepth, dMaxTotLen) or
ML.FindPocketing( sMchFind, dDiam, 0.6 * dDepth, dMaxTotLen) or
ML.FindPocketing( sMchFind, dDiam, 0.4 * dDepth, dMaxTotLen) or
ML.FindPocketing( sMchFind, dDiam, 0, dMaxTotLen)
else
sPocketing, _, _, bPocketDown = ML.FindPocketing( sMchFind, dDiam, 0, dMaxTotLen)
end
if not sPocketing then
return false
end
-- recupero i dati dell'utensile
local bUsePocketing = false
local dMaxDepth = 0
local dToolDiam = 0
local TI = GetToolInfoForMachining( sPocketing)
if TI then
dToolDiam = TI.dDiam or dToolDiam
dMaxDepth = TI.dMaxDepth or dMaxDepth
bUsePocketing = true
end
return bUsePocketing, sPocketing, dMaxDepth, dToolDiam, bPocketDown
end
---------------------------------------------------------------------
local function VerifyBHSideMill( Proc, bSinglePart, bPrevBhSideMill)
local bUseBHSideMill = false
local bHead = true
local bHeadDir = true
local sMilling
local dThickTool = 0
local dToolDiam = 0
-- 22/09/2021 Su richiesta di Alessandro Sola, si toglie la richiesta di presenza del parametro Q per poter applicare
-- la lavorazione su più features (che non hanno questo parametro Q), quindi questa lavorazione viene verificata se è abilitato il parametro utensile
-- che ovviamente tramite la lavorazione è abbinata alla lista lavorazioni con BHSideMill.
-- Al fine di mantenere il funzionamento precedente (purtroppo non sono stati descritti i motivi del confrontare il parametro Q)
-- si elude il controllo del Q solo se la variabile del Beamdata BD.BH_MACHINE segnala che non è una macchina tipo BH (ha la fresa blockhaus al posto della lama)
-- se non feature BlockHausHalfLap o non abilitato parametro Q per lavorarlo di fianco esco
if Proc.Prc ~= 37 and Q_SIDE_ROUGH_TOOL == 0 and not BD.BH_MACHINE then
return false
end
-- verifico se U o L
local bIsU, bIsL = TestUL( Proc)
-- verifico se la funzione è lanciata da IsTailFeature o Classify
if bSinglePart == nil then
-- se lunghezza non richiede spezzatura setto la variabile bSinglePart per non fare con fresa BH
-- perchè deve avere almeno 2 facce
if not ( ( Proc.Box:getDimX() > BD.LONGCUT_MAXLEN) or
( Proc.Box:getDimX() > 0.8 * _b3Solid:getDimX() and Proc.Box:getDimX() > BD.LONGCUT_ENDLEN)) then
bSinglePart = true
end
end
-- ad oggi 22/09/2021 la lavorazione BH non va bene se le facce di chiusura non sono perpendicolari a X, quindi
-- se non sono perpendicolari non si applica la lavorazione BH
if bIsU or bIsL then
local bExit = false
for i = 1, Proc.Fct do
local _, vtN = EgtSurfTmFacetCenter( Proc.Id, i - 1, GDB_ID.ROOT)
if abs( vtN:getX()) > 0.001 and abs( vtN:getX()) < 0.999962 then
bExit = true
break
end
end
if bExit then
return false
end
end
-- se forma a U o L verifico che
-- se U e lunghezza non richiede spezzatura
if ( bIsU or bIsL or ( Proc.Fct == 1 and not bSinglePart)) and Proc.Box:getDimX() <= BD.LONGCUT_MAXLEN then
-- se faccia singola di un passo multiplo e risultato precedente non applicato, riporto il risultato del passo precedente
if ( bIsU or bIsL or ( Proc.Fct == 1 and not bSinglePart)) and bPrevBhSideMill ~= nil and not bPrevBhSideMill then
return false
end
-- recupero la lavorazione
sMilling = ML.FindMilling( 'BHSideMill')
if sMilling then
-- recupero i dati dell'utensile
local dToolLength = 0
local dMaxDepth = 0
local TI = GetToolInfoForMachining( sMilling)
if TI then
dToolLength = TI.dLength or dToolLength
dToolDiam = TI.dDiam or dToolDiam
dMaxDepth = TI.dMaxDepth or dMaxDepth
dThickTool = TI.dThick or dThickTool
end
-- verifico se la feature è abbastanza vicino a testa/coda da permettere la lavorazione con questo utensile
if _b3Solid then
local dMinXF = Proc.Box:getMin():getX()
local dMaxXF = Proc.Box:getMax():getX()
local dMinT = _b3Solid:getMin():getX()
local dMaxT = _b3Solid:getMax():getX()
-- determino se è più vicino alla testa o al bordo (con offset per evitare problemi a metà)
bHeadDir = ( dMaxT - dMinXF) < ( dMaxXF - dMinT) + 50
bHead = bHeadDir
-- determino se è compatibile con il massimo affondamento dell'utensile
-- nota F.M il 22/09/2021: non sarebbe meglio utilizzare lo spessore lama invece della massima lavorazione?
-- questo perchè Alessandro ha settato il parametro Max Material a 80 con spessore lama 42
-- se invece il Max material viene usato per definire fino a che affondamento (lungo l'asse utensile)
-- può arrivare prima di collidere con la testa allora si può utilizzare il dMaxDepth
bUseBHSideMill = EgtIf( bHead, ( dMaxT - dMinXF), ( dMaxXF - dMinT)) < dMaxDepth
-- se diametro maggiore della testa
if BD.HEAD_DIM_FOR_BH and dToolDiam > BD.HEAD_DIM_FOR_BH then
bHead = true
bUseBHSideMill = true
end
end
end
end
return bUseBHSideMill, bHead, bHeadDir, sMilling, dThickTool, dToolDiam
end
---------------------------------------------------------------------
local function GetTunnelDimension( Proc)
-- sono necessarie almeno due facce
if Proc.Fct < 2 then return 0, 0, 0 end
-- recupero centro e normale delle facce
local ptC = {}
local vtN = {}
for i = 1, Proc.Fct do
ptC[i], vtN[i] = EgtSurfTmFacetCenter( Proc.Id, i - 1, GDB_ID.ROOT)
end
-- calcolo l'orientamento del tunnel
local vtOrtho
local bAdj = EgtSurfTmFacetsContact( Proc.Id, 0, 1)
if bAdj then
vtOrtho = vtN[1] ^ vtN[2]
else
if Proc.Fct >= 3 then
vtOrtho = vtN[1] ^ vtN[3]
else
return 0, 0, 0
end
end
-- ottengo il boundingBox e prendo le dimensioni lungo la direzione (Z locale) che rappresenta la profondità della fessura
local frFc = Frame3d( ptC[1], vtOrtho)
local b3BoxLoc = EgtGetBBoxRef( Proc.Id, GDB_BB.STANDARD, frFc)
local dDepth = b3BoxLoc:getDimZ()
-- centro del bounding box locale
local ptCen = b3BoxLoc:getCenter()
ptCen:toGlob( frFc)
-- creo superficie intermedia
local nSurfInt = EgtSurfTmPlaneInBBox( _nAddGrpId, ptCen, vtOrtho, _b3Solid, GDB_ID.ROOT)
if not nSurfInt then return 0, 0, 0 end
-- ritaglio la superficie con le facce della fessura
for i = 1, Proc.Fct do
EgtCutSurfTmPlane( nSurfInt, ptC[i], -vtN[i], false, GDB_ID.ROOT)
end
local frSurfInt, dDimMax, dDimMin = EgtSurfTmFacetMinAreaRectangle( nSurfInt, 0, GDB_ID.ROOT)
-- cerco la faccia con larghezza pari a dimensione massima della fessura
local nLongFaceId = 0
for i = 1, Proc.Fct do
if abs( vtN[i] * frSurfInt:getVersX()) < 0.5 then
nLongFaceId = i - 1
break
end
end
return dDimMin, dDimMax, dDepth, vtOrtho, nLongFaceId, nSurfInt
end
---------------------------------------------------------------------
local function GetFaceAdj( Proc, tFData)
-- Recupero le facce adiacenti alla principale (solo quelle esistenti)
local vAdj = GetValidFacetAdjacencies( Proc.Id, tFData.nFacInd)
if not vAdj or #vAdj == 0 then
local sErr = 'Error : main face without adjacencies'
return -1, sErr
end
EgtOutLog( 'Adjac=' .. table.concat( vAdj, ','), 4)
-- Riordino le dimensioni per avere dH > dV
if tFData.dH < tFData.dV then
tFData.dH, tFData.dV = tFData.dV, tFData.dH
end
-- Cerco una faccia adiacente alla principale sul lato lungo
local nFacAdj
for i = 1, #vAdj do
local _, ptP1, ptP2, _ = EgtSurfTmFacetsContact( Proc.Id, tFData.nFacInd, vAdj[i], GDB_ID.ROOT)
local dLen = dist( ptP1, ptP2)
if dLen > 0.5 * tFData.dH then
nFacAdj = vAdj[i]
EgtOutLog( string.format( 'Adjac=%d Len=%.3f H=%.3f V=%.3f', vAdj[i], dLen, tFData.dH, tFData.dV), 4)
break
end
end
if not nFacAdj then
local sErr = 'Error : main face without long adjacent face'
return -1, sErr
end
return nFacAdj
end
---------------------------------------------------------------------
local function CalcCollisionSafety( vtDir)
local dCollSic = 10 * BD.COLL_SIC
if abs( vtDir:getX()) > 0.999 or abs( vtDir:getY()) > 0.999 or abs( vtDir:getZ()) > 0.999 then
dCollSic = 0
elseif abs( vtDir:getX()) > 0.996 or abs( vtDir:getY()) > 0.996 or abs( vtDir:getZ()) > 0.996 then
dCollSic = 1 * BD.COLL_SIC
elseif abs( vtDir:getX()) > 0.89 or abs( vtDir:getY()) > 0.89 or abs( vtDir:getZ()) > 0.89 then
dCollSic = 2.5 * BD.COLL_SIC
elseif abs( vtDir:getX()) > 0.866 or abs( vtDir:getY()) > 0.866 or abs( vtDir:getZ()) > 0.866 then
dCollSic = 4 * BD.COLL_SIC
elseif abs( vtDir:getX()) > 0.707 or abs( vtDir:getY()) > 0.707 or abs( vtDir:getZ()) > 0.707 then
dCollSic = 5.5 * BD.COLL_SIC
end
return dCollSic
end
---------------------------------------------------------------------
-- Verifica se feature di testa
function ProcessLapJoint.IsHeadFeature( Proc, b3Raw, dCurrOvmH)
if not InitGlob( Proc) then
return false
end
-- se una sola faccia
if Proc.Fct == 1 then
local _, vtN0 = EgtSurfTmFacetCenter( Proc.Id, 0, GDB_ID.ROOT)
if vtN0:getX() > 0.1 then
return true
end
end
-- verifico se è in testa
if Proc.Box:getMax():getX() < b3Raw:getMax():getX() - dCurrOvmH - BD.MAX_DIST_HTFEA then
return false
end
-- la sua lunghezza non deve superare il massimo e 60% della lunghezza della trave
if Proc.Box:getDimX() > min( BD.MAX_LEN_HTFEA, 0.6 * b3Raw:getDimX()) then
return false
end
-- se una o due facce e interessa veramente la testa, allora di testa
if Proc.Fct <= 2 then
if Proc.Box:getMax():getX() > _b3Solid:getMax():getX() - 1. then
return true
elseif Proc.Box:getMax():getX() < _b3Solid:getMax():getX() - 5. then
return false
end
end
local tFData = GetFacetsData( Proc.Id)
-- deve avere la normale principale diretta verso la testa
if tFData.vtN and tFData.vtN:getX() < 0.499 then
return false
elseif Proc.Fct >= 5 then
return true
end
-- deve occupare la maggior parte dell'area
if Proc.Box:getDimY() > 0.75 * b3Raw:getDimY() or Proc.Box:getDimZ() > 0.75 * b3Raw:getDimZ() then
return true
end
-- non è di testa
return false
end
---------------------------------------------------------------------
-- Verifica se feature di coda
function ProcessLapJoint.IsTailFeature( Proc, b3Raw)
if not InitGlob( Proc) then
return false
end
-- se una sola faccia
if Proc.Fct == 1 then
local _, vtN0 = EgtSurfTmFacetCenter( Proc.Id, 0, GDB_ID.ROOT)
if vtN0:getX() < -0.1 then
return true
end
end
-- se può essere fatto con utensile tipo lama
local bUseBHSideMill, bHead, bHeadDir = VerifyBHSideMill( Proc)
if bUseBHSideMill then
Proc.HeadDir = bHeadDir
return not bHead
end
-- verifico se è in coda
local dEndDist = Proc.Box:getMin():getX() - _b3Solid:getMin():getX()
if dEndDist > BD.MAX_DIST_HTFEA then
return false
end
-- la sua lunghezza non deve superare il massimo e 60% della lunghezza della trave
if Proc.Box:getDimX() > min( BD.MAX_LEN_HTFEA, 0.6 * b3Raw:getDimX()) then
return false
end
-- se una o due facce e interessa veramente la coda, allora di coda
if Proc.Fct <= 2 then
if Proc.Box:getMin():getX() < _b3Solid:getMin():getX() + 1. then
return true
elseif Proc.Box:getMin():getX() > _b3Solid:getMin():getX() + 5. then
return false
end
end
local tFData = GetFacetsData( Proc.Id)
-- deve avere la normale principale diretta verso la coda (oppure tunnel)
if tFData.vtN and tFData.vtN:getZ() < BD.NZ_MINA and tFData.nFacInd2 then
tFData = SwapFacetsData( tFData)
end
if not tFData.vtN or tFData.vtN:getX() > -0.001 or dEndDist + tFData.vtN:getX() * tFData.dFacElev > 0 then
return false
else
return true
end
end
---------------------------------------------------------------------
-- Classificazione della feature
function ProcessLapJoint.Classify( Proc, b3Raw)
if not InitGlob( Proc) then
return false
end
-- se 1 faccia
if Proc.Fct == 1 then
-- dati della faccia
--local ptC, vtN = EgtSurfTmFacetCenter( Proc.Id, 0, GDB_ID.ROOT)
-- verifico se è lavorabile solo dal basso
--local bDown = ( vtN:getZ() < BD.NZ_MINA)
--return true, bDown
return true, false
-- se 2 facce
elseif Proc.Fct == 2 then
-- dati delle facce
local vtN = {}
_, vtN[1] = EgtSurfTmFacetCenter( Proc.Id, 0, GDB_ID.ROOT)
_, vtN[2] = EgtSurfTmFacetCenter( Proc.Id, 1, GDB_ID.ROOT)
-- verifico se è lavorabile solo dal basso
local bSmall = ( ( Proc.Head or Proc.Tail) and Proc.Box:getDimX() <= BD.GetMaxLenRidgeLapFromBottom( b3Raw:getDimZ())) or
( not ( Proc.Head or Proc.Tail) and Proc.Box:getDimY() <= BD.GetMaxLenRidgeLapFromBottom( b3Raw:getDimZ()))
local bDown = ( vtN[1]:getZ() < BD.NZ_MINB and vtN[2]:getZ() < BD.NZ_MINB) or
( vtN[1]:getZ() < BD.NZ_MINA and ( vtN[2]:getZ() < -0.1 or not bSmall)) or
( vtN[2]:getZ() < BD.NZ_MINA and ( vtN[1]:getZ() < -0.1 or not bSmall))
bDown = ( bDown and not BD.DOWN_HEAD)
return true, bDown
-- se più di 2 facce
else
local bClosedOrthoFaces
local nDeletedFace
local tFData = GetFacetsData( Proc.Id)
if not tFData.nFacInd or tFData.nFacInd < 0 then
if tFData.nFacInd == -1 then
bClosedOrthoFaces = tFData.isOrthoFaces
else
return false
end
end
-- se è una feature scanalatura (con 5 facce) e non è stata riconosciuta come fessura, eseguo altre verifiche
if Proc.Prc == 16 and Proc.Fct == 5 and not bClosedOrthoFaces then
-- dalla copia della superfice, ciclo eliminando una faccia per volta per verificare se trova fessura
for i = 1, Proc.Fct do
local nNewProc = EgtCopyGlob( Proc.Id, _nAddGrpId) or GDB_ID.NULL
-- elimino una faccia
nDeletedFace = i - 1
if EgtSurfTmRemoveFacet( nNewProc, nDeletedFace) then
-- recupero la faccia con il maggior numero di adiacenze e l'elevazione relativa
tFData = GetFacetsData( nNewProc)
if not tFData.nFacInd or tFData.nFacInd < 0 then
if tFData.nFacInd == -1 then
bClosedOrthoFaces = tFData.isOrthoFaces
EgtErase( nNewProc)
break
else
EgtErase( nNewProc)
return false
end
end
-- altrimenti esco
else
EgtErase( nNewProc)
break
end
end
-- se riconosciuta fessura ricalcolo l'elevazione dalla faccia di fondo
if bClosedOrthoFaces then
tFData = UpdateFacet1Data( Proc.Id, tFData, nDeletedFace)
-- rendo nulla la faccia opzionale perchè si tratta di una fessura
tFData = UpdateFacet2Data( Proc.Id, tFData, nil)
bClosedOrthoFaces = false -- non lo setto come tunnel
end
end
-- se facce formano un tunnel e sono ortogonali
if bClosedOrthoFaces then
-- ottengo le dimensioni del tunnel
local dDimMin, dDimMax, dDepth, vtOrtho, nLongFaceId, nSurfInt = GetTunnelDimension( Proc)
EgtErase( nSurfInt)
-- verifico se può essere fatto con svuotatura
if VerifyPocket( dDimMin) then
return true, false
elseif VerifyChainSaw( dDimMin, dDimMax) then
return true, false
else
return false
end
else
-- se può essere fatto con utensile tipo lama
local bUseBHSideMill, _, _, dMaxMat = VerifyBHSideMill( Proc)
-- if bUseBHSideMill and ( dMaxMat <= tFData.dV + 15 * GEO.EPS_SMALL) then
if bUseBHSideMill and ( dMaxMat <= tFData.dH + 15 * GEO.EPS_SMALL) then
return true, false
-- altrimenti controllo se deve essere ruotato con le altre lavorazioni
else
-- dati della faccia
local _, vtN = EgtSurfTmFacetCenter( Proc.Id, tFData.nFacInd, GDB_ID.ROOT)
-- cerco se c'è faccia adiacente sul lato più lungo
local nFaceAdj = GetFaceAdj( Proc, tFData) or -1
local _, bIsL = TestUL( Proc)
-- verifico se è lavorabile solo dal basso
local bDown = ( vtN:getZ() < BD.NZ_MINA and not BD.DOWN_HEAD)
-- se verso il basso, verifico se utilizzabile seconda faccia
if bDown then
if tFData.nFacInd2 and tFData.dFacElev2 < 2 * tFData.dFacElev then
local _, vtN2 = EgtSurfTmFacetCenter( Proc.Id, tFData.nFacInd2, GDB_ID.ROOT)
bDown = ( vtN2:getZ() < BD.NZ_MINB)
elseif not tFData.nFacInd2 and bIsL and nFaceAdj >= 0 then
local _, vtN2 = EgtSurfTmFacetCenter( Proc.Id, nFaceAdj, GDB_ID.ROOT)
bDown = ( vtN2:getZ() < BD.NZ_MINB)
end
-- verifico se la faccia principale è sottosquadra, ha forma L ed esiste la faccia adiacente
elseif vtN:getZ() < -0.2589 and bIsL and nFaceAdj >= 0 then
-- se il numero di facce > 2 o il box della feature supera una certa distanza dalle teste allora controllo la z della faccia ausiliaria
if Proc.Fct > 2 or ( Proc.Box:getMax():getX() < _b3Solid:getMin():getX() - 150) or ( Proc.Box:getMin():getX() > _b3Solid:getMax():getX() + 150) then
local _, vtN2 = EgtSurfTmFacetCenter( Proc.Id, nFaceAdj, GDB_ID.ROOT)
bDown = ( vtN2:getZ() < BD.NZ_MINB)
end
end
return true, bDown
end
end
end
end
---------------------------------------------------------------------
-- Lavorazione con fresa
---------------------------------------------------------------------
local function MakeOneFaceByMill( Proc)
-- verifico il numero di facce della tacca
assert( ( Proc.Fct == 1), 'Error : MakeOneFaceByMill in LapJoint with ' .. tostring( Proc.Fct) .. ' faces')
-- dati della faccia
local _, vtN = EgtSurfTmFacetCenter( Proc.Id, 0, GDB_ID.ROOT)
-- verifico se orientata verso l'alto
local bUp = ( vtN:getZ() >= BD.NZ_MINA)
-- scelta faccia da lavorare
local nFacInd = 0
-- recupero la lavorazione
local sMilling = ML.FindMilling( 'BirdsMouth')
if not sMilling then
local sErr = 'Error : BirdsMouth not found in library'
EgtOutLog( sErr)
return false, sErr
end
-- inserisco la lavorazione di fresatura
local sName = 'Mill_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id))
local nMchFId = EgtAddMachining( sName, sMilling)
if not nMchFId then
local sErr = 'Error adding machining ' .. sName .. '-' .. sMilling
EgtOutLog( sErr)
return false, sErr
end
-- aggiungo geometria
EgtSetMachiningGeometry( {{ Proc.Id, nFacInd}})
-- imposto uso faccia e lato correzione
if vtN:getX() > 0 then
EgtSetMachiningParam( MCH_MP.FACEUSE, EgtIf( bUp, MCH_MILL_FU.ORTHO_LEFT, MCH_MILL_FU.PARAL_LEFT))
else
EgtSetMachiningParam( MCH_MP.FACEUSE, EgtIf( bUp, MCH_MILL_FU.ORTHO_RIGHT, MCH_MILL_FU.PARAL_RIGHT))
end
-- imposto lato di correzione
EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.LEFT)
if not bUp then EgtSetMachiningParam( MCH_MP.INVERT, true) end
-- imposto posizione braccio porta testa
if vtN:getY() < GEO.EPS_SMALL then
EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.ADIR_YM)
else
EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.ADIR_YP)
end
-- dichiaro non si generano sfridi per VMill
EgtSetMachiningParam( MCH_MP.USERNOTES, 'VMRS=0;')
-- eseguo
if not ML.ApplyMachining( true, false) then
local _, sErr = EgtGetLastMachMgrError()
EgtSetOperationMode( nMchFId, false)
return false, sErr
end
-- eventuale segnalazione ingombro di testa o coda
local dMinHIng = min( 0.5 * BD.VICE_MINH, 0.5 * _b3Raw:getDimZ())
if Proc.Box:getDimZ() > dMinHIng and Proc.Box:getMin():getZ() < _b3Raw:getMin():getZ() + dMinHIng then
if Proc.Head then
local dOffs = _b3Solid:getMax():getX() - Proc.Box:getMin():getX()
BL.UpdateHCING( _nRawId, dOffs)
elseif Proc.Tail then
local dOffs = Proc.Box:getMax():getX() - _b3Solid:getMin():getX()
BL.UpdateTCING( _nRawId, dOffs)
end
end
return true
end
---------------------------------------------------------------------
local function DoMill( Proc, sName, sMilling, offset, nFacInd, nFac2Ind, vtN)
-- inserisco la lavorazione di fresatura
local nMchFId = EgtAddMachining( sName, sMilling)
if not nMchFId then
local sErr = 'Error adding machining ' .. sName .. '-' .. sMilling
EgtOutLog( sErr)
return false, sErr
end
-- aggiungo geometria
EgtSetMachiningGeometry( {{ Proc.Id, nFacInd}})
-- imposto uso faccia e lato correzione
local nFaceUse = BL.GetNearestOrthoOpposite( vtN[nFac2Ind+1])
EgtSetMachiningParam( MCH_MP.FACEUSE, nFaceUse)
-- imposto lato di correzione
EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.LEFT)
-- tolgo l'inversione
EgtSetMachiningParam( MCH_MP.INVERT, false)
-- aggiungo offset laterale
if offset then EgtSetMachiningParam( MCH_MP.OFFSR, offset) end
-- imposto posizione braccio porta testa
if vtN[nFacInd+1]:getY() < GEO.EPS_SMALL then
EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.ADIR_YM)
else
EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.ADIR_YP)
end
-- dichiaro non si generano sfridi per VMill
EgtSetMachiningParam( MCH_MP.USERNOTES, 'VMRS=0;')
-- eseguo
if not ML.ApplyMachining( true, false) then
local _, sErr = EgtGetLastMachMgrError()
EgtSetOperationMode( nMchFId, false)
return false, sErr
end
return true
end
---------------------------------------------------------------------
local function MakeTwoFacesByMill( Proc, bDownHead)
-- verifico il numero di facce della tacca
assert( ( Proc.Fct == 2), 'Error : MakeTwoFacesByMill in LapJoint with ' .. tostring( Proc.Fct) .. ' faces')
-- recupero la lavorazione
local sMilling
sMilling = ML.FindMilling( EgtIf( Q_USE_MILL and Q_USE_MILL == 1, 'LongSmallCut', 'BirdsMouth'), nil , nil, nil, nil, not bDownHead, bDownHead)
if not sMilling then
local sErr = 'Error : LongSmallCut & BirdsMouth not found in library'
EgtOutLog( sErr)
return false, sErr
end
-- recupero i dati dell'utensile
local dTDiam = 0
local TI = GetToolInfoForMachining( sMilling)
if TI then
dTDiam = TI.dDiam or dTDiam
end
-- dati delle facce
local ptC = {}
local vtN = {}
ptC[1], vtN[1] = EgtSurfTmFacetCenter( Proc.Id, 0, GDB_ID.ROOT)
ptC[2], vtN[2] = EgtSurfTmFacetCenter( Proc.Id, 1, GDB_ID.ROOT)
-- dati medi
local ptM = ( ptC[1] + ptC[2]) / 2
-- verifico non siano orientate verso il basso
local bFaceOk = {}
bFaceOk[1] = ( vtN[1]:getZ() >= BD.NZ_MINB)
bFaceOk[2] = ( vtN[2]:getZ() >= BD.NZ_MINB)
if not bDownHead and not bFaceOk[1] and not bFaceOk[2] then
local sErr = 'Error : LapJoint from bottom impossible'
EgtOutLog( sErr)
return false, sErr
end
-- scelta faccia da lavorare
local nFacInd
-- se entrambe possibili
if bFaceOk[1] and bFaceOk[2] then
-- se in testa, scelgo quella orientata verso la testa
if Proc.Head then
if vtN[1]:getX() > vtN[2]:getX() then
nFacInd = 0
else
nFacInd = 1
end
-- se altrimenti in coda, scelgo quella orientata verso la coda
elseif Proc.Tail then
if vtN[1]:getX() < vtN[2]:getX() then
nFacInd = 0
else
nFacInd = 1
end
-- altrimenti, scelgo quella con la normale più perpendicolare all'asse trave (se uguali, quella verso X+)
else
if abs( abs( vtN[1]:getX()) - abs( vtN[2]:getX())) < GEO.EPS_SMALL then
if ptM:getX() > _b3Raw:getCenter():getX() then
nFacInd = EgtIf( vtN[1]:getX() > vtN[2]:getX(), 0, 1)
else
nFacInd = EgtIf( vtN[1]:getX() < vtN[2]:getX(), 0, 1)
end
else
nFacInd = EgtIf( abs( vtN[1]:getX()) < abs( vtN[2]:getX()), 0, 1)
end
end
elseif bFaceOk[1] then
nFacInd = 0
else
nFacInd = 1
end
local nOthInd = 1 - nFacInd
local bOk, sErr, sName
-- se forzato uso fresa controllo se posso fare in una o più passate
if Q_USE_MILL and Q_USE_MILL == 1 then
sName = 'Mill_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) .. '_1'
bOk, sErr = DoMill( Proc, sName, sMilling, dTDiam / 2, nFacInd, nOthInd, vtN)
if not bOk then return bOk, sErr end
end
sName = 'Mill_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id))
bOk, sErr = DoMill( Proc, sName, sMilling, 0, nFacInd, nOthInd, vtN)
if not bOk then return bOk, sErr end
-- eventuale segnalazione ingombro di testa o coda
local dMinHIng = min( 0.5 * BD.VICE_MINH, 0.5 * _b3Raw:getDimZ())
if Proc.Box:getDimZ() > dMinHIng and Proc.Box:getMin():getZ() < _b3Raw:getMin():getZ() + dMinHIng then
if Proc.Head then
local dOffs = _b3Solid:getMax():getX() - Proc.Box:getMin():getX()
BL.UpdateHCING( _nRawId, dOffs)
elseif Proc.Tail then
local dOffs = Proc.Box:getMax():getX() - _b3Solid:getMin():getX()
BL.UpdateTCING( _nRawId, dOffs)
elseif Proc.Box:getCenter():getX() > _b3Solid:getCenter():getX() then
local dOffs = _b3Solid:getMax():getX() - Proc.Box:getMin():getX()
local dDist = _b3Solid:getMax():getX() - Proc.Box:getMax():getX()
-- sempre concavo aumento la distanza (rimane una punta...)
dDist = dDist + 10
BL.UpdateHCING( _nRawId, dOffs, dDist)
end
end
return true
end
---------------------------------------------------------------------
local function MakePreCuts( Proc)
-- se interessa l'intera sezione della trave, necessaria sgrossatura
if _nChamfer < 2 and Proc.Box:getDimY() > 0.9 * _b3Raw:getDimY() and Proc.Box:getDimZ() > 0.9 * _b3Raw:getDimZ() then
-- aggiungo sgrossatura e la lavoro
local AddId = EgtSurfTmConvexHullInBBox( _nAddGrpId, Proc.Id, _b3Raw, GDB_RT.GLOB)
if AddId then
EgtSetName( AddId, 'AddCut_' .. tostring( Proc.Id))
-- applico lavorazione
local CutProc = { Id = AddId, Grp = Proc.Grp, Prc = Proc.Prc, Box = Proc.Box, Fct = Proc.Fct, Flg = Proc.Flg,
Head = Proc.Head, Tail = Proc.Tail, CutId = Proc.CutId, TaskId = Proc.TaskId}
local nCutFacet = EgtSurfTmFacetCount( AddId)
if nCutFacet == 1 then
return Cut.Make( CutProc, _nPhase, _nRawId, _nPartId, _dOvmHead)
elseif nCutFacet == 2 then
return DoubleCut.Make( CutProc, _nPhase, _nRawId, _nPartId, _dOvmHead)
end
end
end
return true
end
---------------------------------------------------------------------
local function MakeByMill( Proc, tFData, dCollSic, bSpecialApp, sMillMaster)
-- Cerco una faccia adiacente alla principale sul lato lungo
local nFacAdj, sErr = GetFaceAdj( Proc, tFData)
if nFacAdj < 0 then
EgtOutLog( sErr)
return false, sErr
end
-- Determino se estremi aperti o chiusi e faccia adiacente da aggiungere alla lavorazione
local bOpenStart = false
local bOpenEnd = false
local vAdj2 = EgtSurfTmFacetAdjacencies( Proc.Id, nFacAdj)[1]
EgtOutLog( 'Adj2=' .. table.concat( vAdj2, ' ,'), 3)
local _, dH2, dV2 = EgtSurfTmFacetMinAreaRectangle( Proc.Id, nFacAdj, GDB_ID.ROOT)
-- Riordino le dimensioni per avere dH > dV
if dH2 < dV2 then
dH2, dV2 = dV2, dH2
end
local nFacAdj2
for j = 1, #vAdj2 do
if vAdj2[j] == tFData.nFacInd then
-- Se non esiste faccia adiacente a lato precedente -> inizio aperto
local i = EgtIf( j > 1, j - 1, #vAdj2)
while vAdj2[i] == tFData.nFacInd do
i = EgtIf( i > 1, i - 1, #vAdj2)
end
bOpenStart = ( vAdj2[i] < 0)
-- Se non esiste faccia adiacente a lato successivo -> fine aperto
local k = EgtIf( j < #vAdj2, j + 1, 1)
while vAdj2[k] == tFData.nFacInd do
k = EgtIf( k < #vAdj2, k + 1, 1)
end
bOpenEnd = ( vAdj2[k] < 0)
end
-- decommentare questa parte per concatenare due facce
--if bSpecialApp and vAdj2[j] >= 0 then
-- local _, ptP1, ptP2, _ = EgtSurfTmFacetsContact( Proc.Id, nFacAdj, vAdj2[j], GDB_ID.ROOT)
-- local dLen = dist( ptP1, ptP2)
-- if abs( dLen - dV2) < 10 * GEO.EPS_SMALL then
-- nFacAdj2 = vAdj2[j]
-- end
--end
end
-- Recupero la lavorazione di fresa
local sMilling
if bSpecialApp then
sMilling = sMillMaster
else
sMilling = ML.FindMilling( 'LongSmallCut')
if not sMilling then
sErr = 'Error : LongSmallCut not found in library'
EgtOutLog( sErr)
return false, sErr
end
end
-- recupero i dati dell'utensile
local dTDiam = 50
local dMaxMat = 0
local TI = GetToolInfoForMachining( sMilling)
if TI then
dTDiam = TI.dDiam or dTDiam
dMaxMat = TI.dMaxMat or dMaxMat
end
-- Se massimo materiale utensile è molto inferiore dell'elevazione non faccio la lavorazione e do un warning
if dMaxMat > 0 and dMaxMat + 15 < tFData.dFacElev + dCollSic then
local sWarn = 'Warning : skipped milling; elevation bigger than max tool depth'
return true, sWarn, dMaxMat
end
-- Calcolo uso faccia
local nFaceUse = BL.GetNearestParalOpposite( tFData.rfFac:getVersZ())
-- inserisco la lavorazione di fresatura
local sName = 'Mill_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id))
local nMchFId = EgtAddMachining( sName, sMilling)
if not nMchFId then
sErr = 'Error adding machining ' .. sName .. '-' .. sMilling
EgtOutLog( sErr)
return false, sErr
end
-- aggiungo geometria
if nFacAdj2 then
EgtSetMachiningGeometry( {{ Proc.Id, nFacAdj}, { Proc.Id, nFacAdj2}})
else
EgtSetMachiningGeometry( {{ Proc.Id, nFacAdj}})
end
-- imposto uso faccia
EgtSetMachiningParam( MCH_MP.FACEUSE, nFaceUse)
-- imposto posizione braccio porta testa
local nSCC = MCH_SCC.ADIR_YM
if tFData.rfFac:getVersZ():getY() > 100 * GEO.EPS_ZERO then
nSCC = MCH_SCC.ADIR_YP
end
EgtSetMachiningParam( MCH_MP.SCC, nSCC)
-- lato di lavoro e direzione
EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.LEFT)
EgtSetMachiningParam( MCH_MP.INVERT, true)
-- tipo di attacco e uscita
EgtSetMachiningParam( MCH_MP.LEADINTYPE, MCH_MILL_LI.LINEAR)
EgtSetMachiningParam( MCH_MP.LEADOUTTYPE, MCH_MILL_LO.LINEAR)
-- imposto accorciamento iniziale/finale per estremi aperti/chiusi
if bSpecialApp then
-- applico gli allungamenti o accorciamenti considerando che la lavorazione è invertita
if nFacAdj2 then
EgtSetMachiningParam( MCH_MP.STARTADDLEN, dTDiam / 2)
EgtSetMachiningParam( MCH_MP.ENDADDLEN, dTDiam / 2)
else
EgtSetMachiningParam( MCH_MP.STARTADDLEN, EgtIf( bOpenEnd, dTDiam / 2, - dTDiam / 2))
EgtSetMachiningParam( MCH_MP.ENDADDLEN, EgtIf( bOpenStart, dTDiam / 2, - dTDiam / 2))
-- confronto la faccia applicata nella lavorazione (faccia adiacente) con la seconda faccia passata nella funzione
-- se corrispondono allora aggiungo una estensione nei lati chiusi pari all'elevazione della stessa faccia corrispondente
if nFacAdj == tFData.nFacInd2 then
if not bOpenStart then
EgtSetMachiningParam( MCH_MP.LOPERP, tFData.dFacElev2)
EgtSetMachiningParam( MCH_MP.LOTANG, 0)
end
if not bOpenEnd then
EgtSetMachiningParam( MCH_MP.LIPERP, tFData.dFacElev2)
EgtSetMachiningParam( MCH_MP.LITANG, 0)
end
end
end
-- applico elevazione
local sNotes = 'MaxElev=' .. EgtNumToString( tFData.dFacElev, 1) .. ';'
EgtSetMachiningParam( MCH_MP.USERNOTES, sNotes)
else
EgtSetMachiningParam( MCH_MP.STARTADDLEN, EgtIf( bOpenEnd, 0, - dTDiam / 2))
EgtSetMachiningParam( MCH_MP.ENDADDLEN, EgtIf( bOpenStart, 0, - dTDiam / 2))
end
-- eseguo
if not ML.ApplyMachining( true, false) then
_, sErr = EgtGetLastMachMgrError()
EgtSetOperationMode( nMchFId, false)
return false, sErr
end
return true, '', dTDiam
end
---------------------------------------------------------------------
local function ChooseCorner( Proc, nFacInd)
-- Recupero le adiacenze della faccia principale
local vAdj = EgtSurfTmFacetAdjacencies( Proc.Id, nFacInd)[1]
-- Cerco i corner tra le facce adiacenti alla principale
local tFacAdj = {}
for i = 1, #vAdj do
if vAdj[i] >= 0 then
for j = i + 1, #vAdj do
if vAdj[j] >= 0 then
local _, ptP1, ptP2, dAng = EgtSurfTmFacetsContact( Proc.Id, vAdj[i], vAdj[j], GDB_ID.ROOT)
if ptP1 and ptP2 and dAng < 0 then
local dLen = dist( ptP1, ptP2)
table.insert( tFacAdj, { vAdj[i], vAdj[j], dLen, ptP1, ptP2, dAng})
end
end
end
end
end
-- Tra le linee dei corner determino la più lunga
local dMaxLen = 0
local nIdLine
for i = 1, #tFacAdj do
if tFacAdj[i][3] > dMaxLen then
nIdLine = i
dMaxLen = tFacAdj[i][3]
end
end
return dMaxLen, nIdLine, tFacAdj
end
---------------------------------------------------------------------
local function ChooseContour( Proc, nFacInd, bVerifyCorner)
-- Recupero le adiacenze della faccia principale
local vAdj = EgtSurfTmFacetAdjacencies( Proc.Id, nFacInd)[1]
-- Se richiesto, verifico che ci siano facce adiacenti consecutive (sicuramente con angolo)
if bVerifyCorner then
local bCorner = false
for i = 1, #vAdj do
local j = EgtIf( i > 1, i - 1, #vAdj)
if vAdj[i] >= 0 and vAdj[j] >= 0 then
bCorner = true
break
end
end
if not bCorner then return {} end
end
-- Cerco le facce adiacenti con angolo convesso
local tFacAdjMain = {}
for i = 1, #vAdj do
if vAdj[i] >= 0 then
local _, ptP1, ptP2, dAng = EgtSurfTmFacetsContact( Proc.Id, nFacInd, vAdj[i], GDB_ID.ROOT)
if ptP1 and ptP2 and dAng < 0 then
local dLen = dist( ptP1, ptP2)
table.insert( tFacAdjMain, { vAdj[i], dLen, ptP1, ptP2, dAng})
end
end
end
return tFacAdjMain
end
---------------------------------------------------------------------
local function CheckToInvert( AuxId, bPositive)
-- recupero versore estrusione
local vtExtr = EgtCurveExtrusion( AuxId, GDB_ID.ROOT)
-- faccio una copia del percorso
local sParnt = EgtGetParent( AuxId)
local nNewEntId = EgtCopyGlob( AuxId, sParnt)
-- chiudo il percorso
if EgtCloseCurveCompo( nNewEntId) then
local vtMPlane, dDist, dArea = EgtCurveArea( nNewEntId)
-- cancello percorso copia
EgtErase( nNewEntId)
if dArea and abs(dArea) > 1 then
local frEnt = EgtGetGlobFrame( AuxId)
if vtMPlane then
vtMPlane:toGlob(frEnt)
if dArea and dArea * ( vtMPlane * vtExtr) < 0 then
if bPositive then
return true
end
elseif dArea and dArea * ( vtMPlane * vtExtr) > 0 then
if not bPositive then
return true
end
end
end
end
else
-- cancello percorso copia
EgtErase(nNewEntId)
end
return false
end
---------------------------------------------------------------------
local function TestPoints( nPathInt, idx, dDiff, pP1, pP2, sAxis)
local pPini = EgtIf( sAxis == 'X', pP1:getX(), EgtIf( sAxis == 'Y', pP1:getY(), pP1:getZ()))
local pPend = EgtIf( sAxis == 'X', pP2:getX(), EgtIf( sAxis == 'Y', pP2:getY(), pP2:getZ()))
local b3SolidMin = EgtIf( sAxis == 'X', _b3Solid:getMin():getX(), EgtIf( sAxis == 'Y', _b3Solid:getMin():getY(), _b3Solid:getMin():getZ()))
local b3SolidMax = EgtIf( sAxis == 'X', _b3Solid:getMax():getX(), EgtIf( sAxis == 'Y', _b3Solid:getMax():getY(), _b3Solid:getMax():getZ()))
if ( abs( pPini - b3SolidMax) < dDiff and abs( pPend - b3SolidMax) < dDiff) or
( abs( pPini - b3SolidMin) < dDiff and abs( pPend - b3SolidMin) < dDiff) then
-- setto l'entità open
local sActInfo = EgtGetInfo( nPathInt, 'OPEN', 's') or ''
if #sActInfo > 0 then
EgtSetInfo( nPathInt, 'OPEN', sActInfo .. ',' .. idx)
else
EgtSetInfo( nPathInt, 'OPEN', idx)
end
return true
else
return false
end
end
---------------------------------------------------------------------
local function SetOpenSide( nPathInt, vtOrtho, nStartPoint)
-- fondo tra loro le curve compatibili
EgtMergeCurvesInCurveCompo( nPathInt)
local nStartIdEnt, nNumEnt = EgtCurveDomain( nPathInt)
local pLastPIni, pLastPEnd
-- faccio una copia della curva e la esplodo
if nStartIdEnt then
-- prendo i punti
for i = 1, nNumEnt do
local pPini = EgtUP( nPathInt, (i - 1), GDB_RT.GLOB)
local pPend = EgtUP( nPathInt, EgtIf( i == nNumEnt, 0, i), GDB_RT.GLOB)
-- Se normale lungo la Z considero il box in X e Y
if abs( vtOrtho:getZ()) > 0.999 then
-- se corrisponde a X prendo i punti per eventuale modifica del punto di inizio percorso
if TestPoints( nPathInt, i - 1, 10 * GEO.EPS_SMALL, pPini, pPend, 'X') then
pLastPIni = pPini
pLastPEnd = pPend
-- altrimenti se corrisponde a Y prendo i punti per eventuale modifica del punto di inizio percorso
elseif TestPoints( nPathInt, i - 1, 10 * GEO.EPS_SMALL, pPini, pPend, 'Y') then
pLastPIni = pPini
pLastPEnd = pPend
end
-- altrimenti se normale lungo la Y considero il box in X e Z
elseif abs( vtOrtho:getZ()) < 0.001 and abs( vtOrtho:getY()) > 0.999 then
-- se corrisponde a X prendo i punti per eventuale modifica del punto di inizio percorso
if TestPoints( nPathInt, i - 1, 10 * GEO.EPS_SMALL, pPini, pPend, 'X') then
pLastPIni = pPini
pLastPEnd = pPend
-- altrimenti se corrisponde a Z prendo i punti per eventuale modifica del punto di inizio percorso
elseif TestPoints( nPathInt, i - 1, 10 * GEO.EPS_SMALL, pPini, pPend, 'Z') then
pLastPIni = pPini
pLastPEnd = pPend
end
-- caso che non dovrebbe mai capitare ma gestito per completezza
-- altrimenti se normale lungo la X considero il box in Y e Z
elseif abs( vtOrtho:getZ()) < 0.001 and abs( vtOrtho:getX()) > 0.999 then
-- se corrisponde a Y prendo i punti per eventuale modifica del punto di inizio percorso
if TestPoints( nPathInt, i - 1, 10 * GEO.EPS_SMALL, pPini, pPend, 'Y') then
pLastPIni = pPini
pLastPEnd = pPend
-- altrimenti se corrisponde a Z prendo i punti per eventuale modifica del punto di inizio percorso
elseif TestPoints( nPathInt, i - 1, 10 * GEO.EPS_SMALL, pPini, pPend, 'Z') then
pLastPIni = pPini
pLastPEnd = pPend
end
-- se asse Z orizzontale verifico se si avvicina piú a Y
elseif abs( vtOrtho:getZ()) < 0.001 then
if abs( vtOrtho:getY()) > 0.75 then
-- se corrisponde a Z prendo i punti per eventuale modifica del punto di inizio percorso
if TestPoints( nPathInt, i - 1, 10 * GEO.EPS_SMALL, pPini, pPend, 'Z') then
pLastPIni = pPini
pLastPEnd = pPend
end
end
-- se asse Y a 0 (fresa ne davanti ne dietro) verifico se si avvicina piú a Z+
elseif abs( vtOrtho:getY()) < 0.001 then
if abs( vtOrtho:getZ()) > 0.75 then
-- se corrisponde a Y prendo i punti per eventuale modifica del punto di inizio percorso
if TestPoints( nPathInt, i - 1, 10 * GEO.EPS_SMALL, pPini, pPend, 'Y') then
pLastPIni = pPini
pLastPEnd = pPend
end
end
end
end
-- se devo cambiare il punto di partenza
if nStartPoint then
if pLastPIni and pLastPEnd then
-- calcolo il punto medio con gli ultimi punti utilizzati
local ptPs = ( pLastPIni + pLastPEnd) / 2
EgtChangeClosedCurveStartPoint( nPathInt, ptPs, GDB_RT.GLOB)
-- se devo eliminare la parte open
if nStartPoint == 2 then
EgtRemoveCurveCompoCurve( nPathInt, true)
EgtRemoveCurveCompoCurve( nPathInt, false)
return true
end
end
end
end
return false
end
---------------------------------------------------------------------
local function DoClean( sName, sMilling, nIdPath, vtN, dMaxElev, dMachDepth, dExtraDepth, dNoLeadsAddLen, dLeadInPerp,
bLeftWorkside, bInvertTool, bInvertDir, bCheckToInvertPath, bSCCEvaluateOppositeVector, bEvaluateAddLeads)
local nMchId = EgtAddMachining( sName, sMilling)
local sMyWarn
if not nMchId then
sMyWarn = 'Warning : impossible add machining ' .. sName .. '-' .. sMilling
return false, sMyWarn
end
-- aggiungo geometria
EgtSetMachiningGeometry( {{ nIdPath, -1}})
-- imposto lato di lavoro sinistro
if bLeftWorkside then
EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.LEFT)
end
-- imposto direzione utensile opposta
if bInvertTool then
EgtSetMachiningParam( MCH_MP.TOOLINVERT, true)
end
-- imposto posizione braccio porta testa
local nSCC = MCH_SCC.NONE
if not BD.C_SIMM then
if EgtIf( bSCCEvaluateOppositeVector, AreSameOrOppositeVectorApprox( vtN, Z_AX()), AreSameVectorApprox( vtN, Z_AX())) then
nSCC = MCH_SCC.ADIR_YM
elseif abs( vtN:getX()) < 0.1 then
nSCC = EgtIf( BL.IsPartFinalPhase( _nPhase), MCH_SCC.ADIR_XM, MCH_SCC.ADIR_XP)
elseif vtN:getY() < GEO.EPS_SMALL then
nSCC = EgtIf( bInvertDir, MCH_SCC.ADIR_YP, MCH_SCC.ADIR_YM)
else
nSCC = EgtIf( bInvertDir, MCH_SCC.ADIR_YM, MCH_SCC.ADIR_YP)
end
end
EgtSetMachiningParam( MCH_MP.SCC, nSCC)
-- gestione attacco e uscita
if bEvaluateAddLeads and EgtCurveIsClosed( nIdPath) then
-- attacco e uscita a quarto di cerchio senza allungamenti a inizio e fine
EgtSetMachiningParam( MCH_MP.LEADINTYPE, MCH_MILL_LI.TANGENT)
EgtSetMachiningParam( MCH_MP.LEADOUTTYPE, MCH_MILL_LO.AS_LI)
EgtSetMachiningParam( MCH_MP.LITANG, 0)
EgtSetMachiningParam( MCH_MP.LIPERP, dLeadInPerp)
EgtSetMachiningParam( MCH_MP.LIELEV, 0)
EgtSetMachiningParam( MCH_MP.STARTADDLEN, 0)
EgtSetMachiningParam( MCH_MP.ENDADDLEN, 0)
else
-- nessun attacco e uscita, allungo inizio e fine di 3/4 del diametro utensile
EgtSetMachiningParam( MCH_MP.LEADINTYPE, MCH_MILL_LI.NONE)
EgtSetMachiningParam( MCH_MP.LEADOUTTYPE, MCH_MILL_LO.AS_LI)
EgtSetMachiningParam( MCH_MP.STARTADDLEN, dNoLeadsAddLen)
EgtSetMachiningParam( MCH_MP.ENDADDLEN, dNoLeadsAddLen)
end
-- setto massimo affondamento possibile
EgtSetMachiningParam( MCH_MP.DEPTH, dMachDepth + dExtraDepth)
-- setto se devo invertire il percorso
if bCheckToInvertPath then
local bInvert = CheckToInvert( nIdPath, true)
EgtSetMachiningParam( MCH_MP.INVERT, EgtIf( bInvertDir, not bInvert, bInvert))
end
-- Note utente con dichiarazione nessuna generazione sfridi per Vmill e massima elevazione
local sUserNotes = 'VMRS=0;MaxElev=' .. EgtNumToString( ( dMaxElev + dMachDepth), 1) .. ';'
EgtSetMachiningParam( MCH_MP.USERNOTES, sUserNotes)
-- eseguo
if ML.ApplyMachining( true, false) then
_, sMyWarn = EgtGetMachMgrWarning( 0)
if EgtIsMachiningEmpty() then
EgtSetOperationMode( nMchId, false)
end
-- altrimenti lavorazione non applicata
else
_, sMyWarn = EgtGetLastMachMgrError()
EgtSetOperationMode( nMchId, false)
return false, sMyWarn
end
return true, sMyWarn
end
---------------------------------------------------------------------
local function MakeRoundCleanCorner( Proc, nFacInd, dDiam, bMillDown, bDoubleSide)
-- recupero la lavorazione senza considerare l'elevazione
local sMilling = ML.FindMilling( 'SmallToolContour', nil, nil, nil, nil, not ( bMillDown and not bDoubleSide), bMillDown and not bDoubleSide)
if not sMilling then
local sMyWarn = 'Warning : SmallToolContour not found in library'
EgtOutLog( sMyWarn)
return true, sMyWarn
end
-- recupero i dati dell'utensile
local dTDiam = 50
local dTMaxDepth = 0
local TI = GetToolInfoForMachining( sMilling)
if TI then
dTDiam = TI.dDiam or dTDiam
dTMaxDepth = TI.dMaxDepth or dTMaxDepth
end
-- se il diametro trovato non è minore dei 3/4 del diametro utilizzato in precedenza, esco
if dTDiam > ( 0.75 * dDiam) then
local sMyWarn = 'Warning : tool diameter not enough small'
EgtOutLog( sMyWarn)
return true, sMyWarn
end
-- ottengo gli angoli dove applicare il percorso con fresa più piccola
local _, _, tFacAdj = ChooseCorner( Proc, nFacInd)
-- se non trovato nessun angolo interno valido esco
if #tFacAdj == 0 then
return true
end
-- recupero la normale della faccia di fondo
local vtN1 = EgtSurfTmFacetNormVersor( Proc.Id, nFacInd, GDB_ID.ROOT)
-- se fresatura da sotto salto la lavorazione
if vtN1:getZ() < BD.DRILL_VZ_MIN and not bMillDown then
local sErr = 'Error : milling from bottom '
EgtOutLog( sErr)
return false, sErr
end
-- ciclo su tutti gli angoli trovati
local sMyWarn = ''
for i = 1, #tFacAdj do
local pAuxId = {}
-- le 2 facce di contatto devono essere perpendicolari e non sottosquadra rispetto alla faccia di fondo
local _, ptP1, ptP2, dAng = EgtSurfTmFacetsContact( Proc.Id, nFacInd, tFacAdj[i][1], GDB_ID.ROOT)
local _, ptP1x, ptP2x, dAngx = EgtSurfTmFacetsContact( Proc.Id, nFacInd, tFacAdj[i][2], GDB_ID.ROOT)
if dAng >= 0 or dAng < -90 - 10 * GEO.EPS_SMALL or dAngx >= 0 or dAngx < -90 - 10 * GEO.EPS_SMALL then
goto continue
end
-- prendo la lunghezza di adiacenza delle due linee
local dLen1 = dist( ptP1, ptP2)
local dLen2 = dist( ptP1x, ptP2x)
-- cerco il punto tra le 3 facce: nIdEndPoint
local _, nIdEndPoint = GetIdIniEndPoints( ptP1, ptP2, tFacAdj[i])
-- devo avere un punto comune
if not nIdEndPoint then
goto continue
end
-- calcolo lunghezza minima in base all'angolo tra le due pareti
local dMinDist = ( ( dDiam / 2) / tan( ( 180 + tFacAdj[i][6]) / 2)) + 2
-- verifico che entrambe le linee siano maggiori delle lunghezza minima
if dLen1 <= dMinDist or dLen2 <= dMinDist then
sMyWarn = 'Warning : impossible make clean corner path'
goto continue
end
-- se il punto finale corrisponde con il punto utilizzato in precedenza, uso l'altro
local ptApPoint = EgtIf( dist( tFacAdj[i][nIdEndPoint], ptP1) < 10 * GEO.EPS_SMALL, ptP2, ptP1)
-- prima linea
local nAuxId = EgtLine( _nAddGrpId, ptApPoint, tFacAdj[i][nIdEndPoint], GDB_RT.GLOB)
-- calcolo arretramento
local dTrimDist = dLen1 - dMinDist
-- se arretramento valido
if dTrimDist > 100 * GEO.EPS_SMALL then
EgtTrimExtendCurveByLen( nAuxId , -dTrimDist, ptApPoint, GDB_RT.GLOB)
end
table.insert( pAuxId, nAuxId)
-- se il punto finale corrisponde con il punto comune, uso l'altro
ptApPoint = EgtIf( dist( tFacAdj[i][nIdEndPoint], ptP1x) < 10 * GEO.EPS_SMALL, ptP2x, ptP1x)
-- seconda linea
nAuxId = EgtLine( _nAddGrpId, tFacAdj[i][nIdEndPoint], ptApPoint, GDB_RT.GLOB)
-- calcolo arretramento
dTrimDist = dLen2 - dMinDist
-- se arretramento valido
if dTrimDist > 100 * GEO.EPS_SMALL then
EgtTrimExtendCurveByLen( nAuxId , -dTrimDist, ptApPoint, GDB_RT.GLOB)
end
table.insert( pAuxId, nAuxId)
-- trasformo in percorso
local AuxId
if #pAuxId > 0 then
AuxId = EgtCurveCompo( _nAddGrpId, pAuxId, true)
end
-- deve esserci il percorso
if not AuxId then
sMyWarn = 'Warning : impossible make clean corner path'
goto continue
end
-- modifico versore direzione
EgtModifyCurveExtrusion( AuxId, vtN1, GDB_RT.GLOB)
-- inserisco la lavorazione
local sName = 'Clean_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id))
local dDepth = 0
if tFacAdj[i][3] > dTMaxDepth then
dDepth = dTMaxDepth - tFacAdj[i][3]
end
_, sMyWarn = DoClean( sName, sMilling, AuxId, vtN1, tFacAdj[i][3], dDepth, 0, 0, 0, true, false, false, true, true, false)
::continue::
end
if #sMyWarn > 0 then
EgtOutLog( sMyWarn)
end
return true, sMyWarn
end
---------------------------------------------------------------------
local function MakeRoundCleanContour( Proc, nFacInd, dDiam, bMillDown,
bDoubleSide, vtOrtho, nPathInt, nSurfInt,
dDepth, bOneShot)
-- recupero la lavorazione senza considerare l'elevazione perché viene calcolata l'elevazione utile
local sMilling = ML.FindMilling( 'SmallToolContour', nil, nil, nil, nil, not ( bMillDown and not bDoubleSide), bMillDown and not bDoubleSide)
if not sMilling then
local sMyWarn = 'Warning : SmallToolContour not found in library'
EgtOutLog( sMyWarn)
return true, sMyWarn
end
-- recupero i dati dell'utensile
local dTDiam = 50
local dTMaxDepth = 0
local TI = GetToolInfoForMachining( sMilling)
if TI then
dTDiam = TI.dDiam or dTDiam
dTMaxDepth = TI.dMaxDepth or dTMaxDepth
end
local sMillingDn = ML.FindMilling( 'SmallToolContour', nil, nil, nil, nil, not ( bMillDown and bDoubleSide), bMillDown and bDoubleSide)
if not sMillingDn then
local sMyWarn = 'Warning : Opposite SmallToolContour not found in library'
EgtOutLog( sMyWarn)
return true, sMyWarn
end
-- recupero i dati dell'utensile testa da sotto
local dTDiamDn = 50
local dTMaxDepthDn = 0
local TI = GetToolInfoForMachining( sMillingDn)
if TI then
dTDiamDn = TI.dDiam or dTDiamDn
dTMaxDepthDn = TI.dMaxDepth or dTMaxDepthDn
end
-- se il diametro trovato non è minore dei 3/4 del diametro utilizzato in precedenza, esco
if dTDiam > ( 0.75 * dDiam) then
local sMyWarn = 'Warning : tool diameter not enough small'
EgtOutLog( sMyWarn)
return true, sMyWarn
end
local vtN1
local nFirstId, nNumId
local dMaxElev
local dCollSic = 0
local dExtraDepth = 0
-- se non ho la faccia aggiunta
if not nPathInt then
-- cerco gli angoli dove applicare il percorso con fresa piú piccola e i lati in comune
local tFacAdjMain = ChooseContour( Proc, nFacInd, true)
-- se non trovato nessun angolo interno da pulire esco
if #tFacAdjMain == 0 then
return true
end
-- normale alla faccia di fondo
vtN1 = EgtSurfTmFacetNormVersor( Proc.Id, nFacInd, GDB_ID.ROOT)
-- se fresatura da sotto salto la lavorazione
if vtN1:getZ() < BD.DRILL_VZ_MIN and not bMillDown then
local sErr = 'Error : milling from bottom'
EgtOutLog( sErr)
return false, sErr
end
-- distanza di sicurezza per evitare collisioni
dCollSic = CalcCollisionSafety( vtN1)
-- elevazione massima della faccia
dMaxElev = BL.GetFaceElevation( Proc.Id, nFacInd, _nPartId)
-- ciclo tutta la tabella
local tPaths = {}
local ptIniPath
local ptMidDist
local dMaxLen = 0
for i = 1, #tFacAdjMain do
-- le 2 facce di contatto devono essere perpendicolari o non sottosquadra rispetto alla faccia di fondo
local ptP1, ptP2, dAng
ptP1 = tFacAdjMain[i][3]
ptP2 = tFacAdjMain[i][4]
dAng = tFacAdjMain[i][5]
if ( dAng < 0 and dAng >= -90 - 10 * GEO.EPS_SMALL) then
-- creo la linea da P1 a P2
local nAuxId = EgtLine( _nAddGrpId, ptP1, ptP2, GDB_RT.GLOB)
table.insert( tPaths, nAuxId)
-- prendo la lunghezza massima e il punto medio
if tFacAdjMain[i][2] > dMaxLen then
ptIniPath = ptP1
dMaxLen = tFacAdjMain[i][2]
ptMidDist = ( ptP1 + ptP2) / 2
end
end
end
-- costruisco il/i percorso/i
nFirstId, nNumId = EgtCurveCompoByReorder( _nAddGrpId, tPaths, ptIniPath, true, GDB_RT.GLOB)
if nFirstId then
-- se un solo percorso e chiuso cambio il punto di inizio nell'entitá piú lunga
if nNumId == 1 and EgtCurveIsClosed( nFirstId) then
EgtChangeClosedCurveStartPoint( nFirstId, ptMidDist, GDB_RT.GLOB)
end
-- modifico versore direzione
for i = 1, nNumId do
EgtModifyCurveExtrusion( nFirstId + i - 1, vtN1, GDB_RT.GLOB)
end
end
-- alrimenti ho la faccia aggiunta
else
-- assegno il percorso
nFirstId = EgtCopyGlob( nPathInt, _nAddGrpId)
nNumId = 1
-- distanza di sicurezza per evitare collisioni
dCollSic = CalcCollisionSafety( vtOrtho)
-- calcolo elevazione dalla faccia trasversale aggiunta
local dSurfIntElev = BL.GetOtherFaceElevation( Proc.Id, nSurfInt, 0)
if bDoubleSide then
dMaxElev = dSurfIntElev
else
dMaxElev = dDepth
-- se la precedente svuotatura è stata fatta completamente in una sola volta
-- valuto di nuovo se devo fare due passate o una sola
if bOneShot then
-- se non è possibile svuotare completamente da una sola parte
if dTMaxDepth <= ( dMaxElev + BD.CUT_EXTRA + dCollSic) then
bDoubleSide = true
dMaxElev = BL.GetOtherFaceElevation( Proc.Id, nSurfInt, 0)
else
dExtraDepth = dMaxElev - BL.GetOtherFaceElevation( Proc.Id, nSurfInt, 0)
end
-- altrimenti non è stata fatta completamente calcolo la distanza tra faccia aggiunta e profondità superficie
else
dExtraDepth = dMaxElev - BL.GetOtherFaceElevation( Proc.Id, nSurfInt, 0)
end
end
-- normale alla faccia aggiunta
vtN1 = Vector3d( vtOrtho)
-- imposto i lati aperti
SetOpenSide( nFirstId, vtOrtho, 2)
end
-- se non trovato il percorso, esco
if not nFirstId then
local sMyWarn = 'Warning : impossible make clean corner path'
EgtOutLog( sMyWarn)
return true, sMyWarn
end
-- assegno lavorazioni ad ogni percorso
local sMyWarn = ''
local bOk
for i = 1, nNumId do
local nIdPath = nFirstId + i - 1
local sName = 'Clean_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id))
local bInvertMach
if nPathInt then
-- verifico se devo invertire direzione utensile (in caso di direzione verso la verticale)
if vtN1:getZ() < BD.NZ_MINA and abs(vtN1:getZ()) >= 0.707 then
bInvertMach = true
-- altrimenti se da fare in una sola volta e direzionato verso Y+ lo inverto per lavorarlo davanti
elseif not bDoubleSide and vtN1:getY() > GEO.EPS_SMALL then
bInvertMach = true
end
end
local dMachDepth = 0
if ( dMaxElev + dCollSic) > dTMaxDepth then
dMachDepth = dTMaxDepth - ( dMaxElev + dCollSic)
end
bOk, sMyWarn = DoClean( sName, sMilling, nIdPath, vtN1, dMaxElev, dMachDepth, dExtraDepth, 0.75 * dTDiam, 0.5 * dTDiam, true, bInvertMach, bInvertMach, true, true, true)
-- se devo applicare la contornatura anche sul lato opposto
if bOk and bDoubleSide then
if bMillDown then
sMilling = sMillingDn
dTDiam = dTDiamDn
dTMaxDepth = dTMaxDepthDn
end
sName = 'CleanOppo_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id))
bOk, sMyWarn = DoClean( sName, sMilling, nIdPath, vtN1, dMaxElev, dMachDepth, 0, 0.75 * dTDiam, 0, true, true, true, true, false, false)
end
end
if #sMyWarn > 0 then
EgtOutLog( sMyWarn)
end
return true, sMyWarn
end
---------------------------------------------------------------------
local function MakeRoundCleanCornerOrContour( Proc, nFacInd, dDiam, bMillDown, bDoubleSide,
vtOrtho, nPathInt, nSurfInt, dDepth, bOneShot)
local nFunction = Q_CONTOUR_SMALL_TOOL
-- se modalitá pulitura spigoli e lavorazione di lato forzo a fare il contorno
if nFunction == 2 and nPathInt then
nFunction = 1
end
-- se richiesta pulitura del contorno
if nFunction == 1 then
return MakeRoundCleanContour( Proc, nFacInd, dDiam, bMillDown, bDoubleSide,
vtOrtho, nPathInt, nSurfInt, dDepth, bOneShot)
-- se richiesta pulitura dei soli corner
elseif nFunction == 2 then
return MakeRoundCleanCorner( Proc, nFacInd, dDiam, bMillDown, bDoubleSide)
-- altri casi non previsti
else
return true
end
end
---------------------------------------------------------------------
local function MakeSharpCleanCorner( Proc, nFacInd, dDiam)
local sMyWarn = ''
local pAuxId = {}
local nAuxId
local AuxId
local ptApPoint
local dLenTrimExt
local sMilling
local dMaxDepth = 0
-- cerco l'angolo di riferimento dove applicare il percorso di pulitura, altrimenti esco
local _, nIdLine, tFacAdj = ChooseCorner( Proc, nFacInd)
if #tFacAdj == 0 then
return true
end
-- prendo i versori
local vtN1 = EgtSurfTmFacetNormVersor( Proc.Id, nFacInd, GDB_ID.ROOT)
local vtN2 = EgtSurfTmFacetNormVersor( Proc.Id, tFacAdj[nIdLine][1], GDB_ID.ROOT)
local vtN3 = EgtSurfTmFacetNormVersor( Proc.Id, tFacAdj[nIdLine][2], GDB_ID.ROOT)
-- trovo il punto sulla superfice di riferimento
local _, ptLocP1, ptLocP2 = EgtSurfTmFacetsContact( Proc.Id, nFacInd, tFacAdj[nIdLine][1], GDB_ID.ROOT)
local nIdIniPoint, nIdEndPoint = GetIdIniEndPoints( ptLocP1, ptLocP2, tFacAdj[nIdLine])
-- versore direzione
local vtExtr = tFacAdj[nIdLine][nIdIniPoint] - tFacAdj[nIdLine][nIdEndPoint]
vtExtr:normalize()
-- inserisco le prime tre linee
if nIdIniPoint and nIdEndPoint then
-- se fresatura da sotto salto la lavorazione
if vtExtr:getZ() < BD.DRILL_VZ_MIN then
local sErr = 'Error : clean corner milling from bottom impossible'
EgtOutLog( sErr)
return false, sErr
end
-- sommo i tre versori per avre una direzione media
vtExtr = vtN1 + vtN2 + vtN3
vtExtr:normalize()
-- recupero la lavorazione non calcolando l'elevazione
sMilling = ML.FindMilling( 'CleanCorner', ( 0.5 * dDiam))
if not sMilling then
local sErr = 'Error : CleanCorner not found in library'
EgtOutLog( sErr)
return false, sErr
end
-- recupero i dati dell'utensile (temporaneo, per compensare errore nella lavorazione)
local TI = GetToolInfoForMachining( sMilling)
if TI then
dMaxDepth = TI.dMaxMat or dMaxDepth
end
-- l'altezza di taglio del tagliente corrisponde al raggio del raccordo che si riesce a coprire
-- quindi confronto l'elevazione con il raggio utensile utilizzato per la svuotatura
if dMaxDepth < ( dDiam * 0.5) - 100 * GEO.EPS_SMALL then
sMyWarn = 'Warning : skip clean corner (the cut heigth is too small to machine the corner radius)'
EgtOutLog( sMyWarn)
return false, sMyWarn
end
nAuxId = EgtLine( _nAddGrpId, tFacAdj[nIdLine][nIdIniPoint], tFacAdj[nIdLine][nIdEndPoint], GDB_RT.GLOB)
table.insert( pAuxId, nAuxId)
-- se il punto finale corrisponde con il punto utilizzato in precedenza, uso l'altro
if dist( tFacAdj[nIdLine][nIdEndPoint], ptLocP1) < 10 * GEO.EPS_SMALL then
ptApPoint = ptLocP2
else
ptApPoint = ptLocP1
end
nAuxId = EgtLine( _nAddGrpId, tFacAdj[nIdLine][nIdEndPoint], ptApPoint, GDB_RT.GLOB)
dLenTrimExt = dist( tFacAdj[nIdLine][nIdEndPoint], ptApPoint) - ( ( dDiam / 2) + 2)
-- se la distanza dei due punti della linea è maggiore dal raggio fresa + delta, trimmo al raggio fresa + delta
if dLenTrimExt > 10 * GEO.EPS_SMALL then
EgtTrimExtendCurveByLen( nAuxId, -dLenTrimExt, ptApPoint, GDB_RT.GLOB)
-- prendo il nuovo punto finale
ptApPoint = EgtEP( nAuxId, GDB_RT.GLOB)
end
table.insert( pAuxId, nAuxId)
-- creo linea di ritorno
nAuxId = EgtLine( _nAddGrpId, ptApPoint, tFacAdj[nIdLine][nIdEndPoint], GDB_RT.GLOB)
table.insert( pAuxId, nAuxId)
end
-- inserisco le ultime tre linee + uscita discostata rispetto all'ingresso
-- trovo il secondo punto sulla superfice di riferimento
_, ptLocP1, ptLocP2 = EgtSurfTmFacetsContact( Proc.Id, nFacInd, tFacAdj[nIdLine][2], GDB_ID.ROOT)
if ptLocP1 and ptLocP2 then
-- se il punto finale corrisponde con il punto utilizzato in precedenza, uso l'altro
if dist( tFacAdj[nIdLine][nIdEndPoint], ptLocP1) < 10 * GEO.EPS_SMALL then
ptApPoint = ptLocP2
else
ptApPoint = ptLocP1
end
nAuxId = EgtLine( _nAddGrpId, tFacAdj[nIdLine][nIdEndPoint], ptApPoint, GDB_RT.GLOB)
dLenTrimExt = dist( tFacAdj[nIdLine][nIdEndPoint], ptApPoint) - ( ( dDiam / 2) + 2)
-- se la distanza dei due punti della linea è maggiore dal raggio fresa + delta, trimmo al raggio fresa + delta
if dLenTrimExt > 10 * GEO.EPS_SMALL then
EgtTrimExtendCurveByLen( nAuxId, -dLenTrimExt, ptApPoint, GDB_RT.GLOB)
-- prendo il nuovo punto finale
ptApPoint = EgtEP( nAuxId, GDB_RT.GLOB)
end
table.insert( pAuxId, nAuxId)
-- creo linea di ritorno
nAuxId = EgtLine( _nAddGrpId, ptApPoint, tFacAdj[nIdLine][nIdEndPoint], GDB_RT.GLOB)
table.insert( pAuxId, nAuxId)
-- piccolo scostamento di 2mm dall'angolo
nAuxId = EgtLine( _nAddGrpId, tFacAdj[nIdLine][nIdEndPoint], tFacAdj[nIdLine][nIdEndPoint] + ( 2 * vtExtr), GDB_RT.GLOB)
table.insert( pAuxId, nAuxId)
-- ultima linea di risalita
nAuxId = EgtLine( _nAddGrpId, tFacAdj[nIdLine][nIdEndPoint] + ( 2 * vtExtr), tFacAdj[nIdLine][nIdIniPoint] + ( 2 * vtExtr), GDB_RT.GLOB)
table.insert( pAuxId, nAuxId)
end
-- trasformo in percorso
if #pAuxId > 0 then
AuxId = EgtCurveCompo( _nAddGrpId, pAuxId, true)
end
-- se non c'é il percorso do errore
if not AuxId then
local sErr = 'Error : impossible make clean corner path'
EgtOutLog( sErr)
return false, sErr
end
-- modifico versore direzione
EgtModifyCurveExtrusion( AuxId, vtExtr, GDB_RT.GLOB)
-- inserisco la lavorazione
local sName = 'Clean_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id))
local bOk
bOk, sMyWarn = DoClean( sName, sMilling, AuxId, vtN1, dMaxDepth, 0, 0, 10, 0, false, false, true, false, false, false)
if not bOk then
return false, sMyWarn
end
return true, sMyWarn
end
---------------------------------------------------------------------
local function MakeDrillOnCorner( Proc, nFacInd, dDiam, bSpecialMach)
local sMyWarn = ''
-- ottengo l'angolo dove applicare il foro
local dMaxLen, nIdLine, tFacAdj = ChooseCorner( Proc, nFacInd)
-- se non trovato nessun angolo interno valido esco
if #tFacAdj == 0 then
return true, sMyWarn
end
-- trovo il punto sulla superfice di riferimento
local _, ptLocP1, ptLocP2, _ = EgtSurfTmFacetsContact( Proc.Id, nFacInd, tFacAdj[nIdLine][1], GDB_ID.ROOT)
local nIdIniPoint, nIdEndPoint = GetIdIniEndPoints(ptLocP1, ptLocP2, tFacAdj[nIdLine])
-- inserisco foro
if nIdIniPoint and nIdEndPoint then
local vtExtr
if bSpecialMach then
local _, vtN0 = EgtSurfTmFacetCenter( Proc.Id, nFacInd, GDB_ID.ROOT)
local _, vtN1 = EgtSurfTmFacetCenter( Proc.Id, tFacAdj[nIdLine][1], GDB_ID.ROOT)
local _, vtN2 = EgtSurfTmFacetCenter( Proc.Id, tFacAdj[nIdLine][2], GDB_ID.ROOT)
vtExtr = vtN0 + vtN1 + vtN2
else
-- versore direzione
vtExtr = tFacAdj[nIdLine][nIdIniPoint] - tFacAdj[nIdLine][nIdEndPoint]
end
vtExtr:normalize()
-- se foratura da sotto salto la lavorazione
if vtExtr:getZ() < BD.DRILL_VZ_MIN then
local sErr = 'Error : drilling from bottom impossible'
EgtOutLog( sErr)
return false, sErr
end
-- recupero la lavorazione
local sDrilling, nType = ML.FindDrilling( dDiam)
if not sDrilling then
local sErr = 'Error : drilling not found in library'
EgtOutLog( sErr)
return false, sErr
end
-- recupero i dati dell'utensile
local dMaxDepth = 20
local dDiamTool = 20
local dDiamTh = 35
local bIsDrilling
local TI = GetToolInfoForMachining( sDrilling)
if TI then
bIsDrilling = ( EgtMdbGetCurrMachiningParam( MCH_MP.TYPE) == MCH_MY.DRILLING)
if bIsDrilling then
dMaxDepth = TI.dMaxMat or dMaxDepth
else
dMaxDepth = TI.dMaxDepth or dMaxDepth
end
dDiamTool = TI.dDiam or dDiamTool
dDiamTh = TI.dThDiam or dDiamTh
end
-- se foro inclinato, limito il massimo affondamento
local CosB = abs( vtExtr:getX())
if CosB < BD.DRILL_VX_MAX then
local TgA = CosB / sqrt( 1 - CosB * CosB)
dMaxDepth = dMaxDepth - dDiamTh / 2 * TgA
else
dMaxDepth = 0
end
-- setto griglia
if bSpecialMach then
EgtSetGridFrame( Frame3d( tFacAdj[nIdLine][nIdEndPoint], vtExtr))
else
EgtSetGridFrame( Frame3d( tFacAdj[nIdLine][nIdIniPoint], vtExtr))
end
-- creo geometria
local AuxId = EgtCircle( _nAddGrpId, {0, 0, 0}, EgtIf( bIsDrilling, dDiamTool / 2, ( dDiamTool / 2) + 0.1), GDB_RT.GRID)
-- riporto la griglia a globale
EgtSetGridFrame()
-- calcolo spessore
local dDepthBore = dMaxLen
if bSpecialMach then
-- calcolo l'elevazione
local dLenIn, dLedOut = BL.GetPointDirDepth( _nPartId, tFacAdj[nIdLine][nIdEndPoint], vtExtr)
if dLenIn > 0 then
dDepthBore = dLenIn
elseif dLedOut then
dDepthBore = dLedOut
end
EgtModifyCurveThickness( AuxId, dDepthBore)
else
EgtModifyCurveThickness( AuxId, -dMaxLen)
end
-- inserisco la lavorazione
local sName = 'Drill_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id))
local nMchId = EgtAddMachining( sName, sDrilling)
if not nMchId then
local sErr = 'Error adding machining ' .. sName .. '-' .. sDrilling
EgtOutLog( sErr)
return false, sErr
end
-- aggiungo geometria
EgtSetMachiningGeometry( {{ AuxId, -1}})
-- imposto posizione braccio porta testa
local nSCC = MCH_SCC.ADIR_YM
if vtExtr:getY() > 100 * GEO.EPS_ZERO then
nSCC = MCH_SCC.ADIR_YP
end
EgtSetMachiningParam( MCH_MP.SCC, nSCC)
-- aggiusto l'affondamento
local dDepth
if bSpecialMach then
dDepth = dDepthBore
else
dDepth = dMaxLen
if dDepth > dMaxDepth + 10 * GEO.EPS_SMALL then
sMyWarn = 'Warning in drill : depth (' .. EgtNumToString( dDepth, 1) .. ') bigger than max tool depth (' .. EgtNumToString( dMaxDepth, 1) .. ')'
dDepth = dMaxDepth
EgtOutLog( sMyWarn)
end
end
EgtSetMachiningParam( MCH_MP.DEPTH, dDepth)
-- Note utente con dichiarazione nessuna generazione sfridi per Vmill e massima elevazione (coincide con affondamento)
local sUserNotes = 'VMRS=0;MaxElev=' .. EgtNumToString( dDepth, 1) .. ';'
EgtSetMachiningParam( MCH_MP.USERNOTES, sUserNotes)
if not ML.ApplyMachining( true, false) then
local _, sErr = EgtGetLastMachMgrError()
EgtSetOperationMode( nMchId, false)
return false, sErr
else
local _, sWarn = EgtGetMachMgrWarning( 0)
if EgtIsMachiningEmpty() then
EgtSetOperationMode( nMchId, false)
return false, sWarn
else
return true, ( sMyWarn or sWarn)
end
end
end
return true, sMyWarn
end
---------------------------------------------------------------------
local function ErasePathIfNecessary( nPathId, sDeleteByDir, dDiff)
local ptP1 = EgtSP( nPathId, GDB_RT.GLOB)
local ptP2 = EgtEP( nPathId, GDB_RT.GLOB)
if abs( EgtIf( sDeleteByDir == 'X', ( ptP1:getX() - ptP2:getX()), EgtIf( sDeleteByDir == 'Y', ( ptP1:getY() - ptP2:getY()), ( ptP1:getZ() - ptP2:getZ())))) > dDiff then
EgtErase( nPathId)
end
end
---------------------------------------------------------------------
local function TestPaths( sDeleteByDir, nStartId, nNumIds, dDiff)
local tPaths = {}
local dMaxVal, dMinVal
for i = 1, nNumIds do
local bInsTab
local nIdx = nStartId + i - 1
local ptP1 = EgtSP( nIdx, GDB_RT.GLOB)
if ptP1 then
for j = 1, #tPaths do
local dLocalVal = tPaths[j][2]
if abs( EgtIf( sDeleteByDir == 'X', ptP1:getX() - dLocalVal, EgtIf( sDeleteByDir == 'Y', ptP1:getY() - dLocalVal, ptP1:getZ() - dLocalVal))) < dDiff then
local tLocIds = tPaths[j][1]
table.insert( tLocIds, ( nIdx))
tPaths[j][1] = tLocIds
bInsTab = true
end
end
-- se non ho trovato da inserirlo aggiungo nuovo elemento in tabella
if not bInsTab then
table.insert( tPaths, {{ nIdx}, ptP1:getX()})
dMaxVal = EgtIf( sDeleteByDir == 'X', _b3Solid:getMax():getX(), EgtIf( sDeleteByDir == 'Y', _b3Solid:getMax():getY(), _b3Solid:getMax():getZ()))
dMinVal = EgtIf( sDeleteByDir == 'X', _b3Solid:getMin():getX(), EgtIf( sDeleteByDir == 'Y', _b3Solid:getMin():getY(), _b3Solid:getMin():getZ()))
end
end
end
return tPaths, dMaxVal, dMinVal
end
---------------------------------------------------------------------
local function ModifyPathExtrusion(tPath, sDeleteByDir, dMaxVal, dDiff)
local ptP1 = EgtSP( tPath, GDB_RT.GLOB)
if abs( EgtIf( sDeleteByDir == 'X', ptP1:getX(), EgtIf( sDeleteByDir == 'Y', ptP1:getY(), ptP1:getZ())) - dMaxVal) < dDiff then
EgtModifyCurveExtrusion( tPath, EgtIf( sDeleteByDir == 'X', X_AX(), EgtIf( sDeleteByDir == 'Y', Y_AX(), Z_AX())), GDB_RT.GLOB)
else
EgtModifyCurveExtrusion( tPath, EgtIf( sDeleteByDir == 'X', -X_AX(), EgtIf( sDeleteByDir == 'Y', -Y_AX(), -Z_AX())), GDB_RT.GLOB)
end
end
---------------------------------------------------------------------
local function ExtractExternalPaths( nPathInt, nNumIdAux, vtOrtho)
if nNumIdAux == 1 then
-- fondo tra loro le curve compatibili
EgtMergeCurvesInCurveCompo( nPathInt)
-- esplodo il percorso in modo da avere entià separate per poterle controllare
local nStartId, nNumIds = EgtExplodeCurveCompo( nPathInt)
if nStartId then
local sDeleteByDir
-- Se normale lungo la Z elimino le entità che hanno differenza in Z
if abs(vtOrtho:getZ()) > 0.7 then
sDeleteByDir = 'Z'
-- altrimenti se normale lungo la Y elimino le entità che hanno variazione in Y
-- elseif abs(vtOrtho:getZ()) < 0.001 and abs(vtOrtho:getY()) > 0.7 then
elseif abs(vtOrtho:getY()) > 0.7 then
sDeleteByDir = 'Y'
-- caso che non dovrebbe mai capitare ma gestito per completezza
-- altrimenti se normale lungo la X elimino le entità che hanno variazione in X
-- elseif abs(vtOrtho:getZ()) < 0.001 and abs(vtOrtho:getX()) > 0.7 then
elseif abs(vtOrtho:getX()) > 0.7 then
sDeleteByDir = 'X'
end
if sDeleteByDir then
for i = 1, nNumIds do
ErasePathIfNecessary( nStartId + i - 1, sDeleteByDir, 10 * GEO.EPS_SMALL)
end
-- ricreo i vari percorsi
local tPaths, dMaxVal, dMinVal = TestPaths( sDeleteByDir, nStartId, nNumIds, 10 * GEO.EPS_SMALL)
if tPaths then
local tChamPath = {}
-- elimino quelle che non corrispondono agli estremi
for i = 1, #tPaths do
-- se non corrisponde ai limiti elimino l'elemento
if abs( tPaths[i][2] - dMaxVal) > 10 * GEO.EPS_SMALL and abs( tPaths[i][2] - dMinVal) > 10 * GEO.EPS_SMALL then
tPaths[i] = nil
else
local tNoMatch = {}
local tPathLoc = tPaths[i][1]
local pIniLoc = EgtSP( tPathLoc[1], GDB_RT.GLOB)
local pEndLoc = EgtEP( tPathLoc[1], GDB_RT.GLOB)
-- ciclo sui percorsi per trovare i punti non coincidenti (se percorso non chiuso)
for j = 2, #tPathLoc do
-- prendo i punti del percorso successivo
local pAddIni = EgtSP( tPathLoc[j], GDB_RT.GLOB)
local pAddEnd = EgtEP( tPathLoc[j], GDB_RT.GLOB)
-- se consecutivi
if AreSamePointApprox( pEndLoc, pAddIni) then
pEndLoc = pAddEnd
elseif AreSamePointApprox( pIniLoc, pAddEnd) then
pIniLoc = pAddIni
else
table.insert( tNoMatch, tPathLoc[j])
end
end
-- controllo eventuali percorsi scartati
for j = 1, #tNoMatch do
-- prendo i punti del percorso successivo
local pAddIni = EgtSP( tNoMatch[j], GDB_RT.GLOB)
local pAddEnd = EgtEP( tNoMatch[j], GDB_RT.GLOB)
-- se consecutivi
if AreSamePointApprox( pEndLoc, pAddIni) then
pEndLoc = pAddEnd
elseif AreSamePointApprox( pIniLoc, pAddEnd) then
pIniLoc = pAddIni
end
end
-- creo concatenamento partendo dal punto iniziale
local nIdLoc = EgtCurveCompoByReorder( _nAddGrpId, tPathLoc, pIniLoc, true)
if nIdLoc then
table.insert( tChamPath, nIdLoc)
end
end
end
for i = 1, #tChamPath do
-- modifico estrusione percorso
ModifyPathExtrusion( tChamPath[i], sDeleteByDir, dMaxVal, 10 * GEO.EPS_SMALL)
end
if #tChamPath == 1 then
return tChamPath[1], 1, nil
elseif #tChamPath == 2 then
return tChamPath[1], 2, tChamPath[2]
else
for i = 1, nNumIds do
EgtErase( nStartId + i - 1)
end
for i = 1, #tChamPath do
EgtErase( tChamPath[i])
end
end
else
for i = 1, nNumIds do
EgtErase( nStartId + i - 1)
end
end
-- altrimenti cancello tutte le emtità e restituisco nil
else
for i = 1, nNumIds do
EgtErase( nStartId + i - 1)
end
end
end
end
return nil, 0, nil
end
---------------------------------------------------------------------
local function MakeChamfer( Proc, vtOrtho, nSurfInt)
-- Se variabile globale indica che lo smusso è già stato fatto, esco
if _bMadeChamfer then
return 0
end
_bMadeChamfer = true
local bIs3Faces = Proc.Fct == 3
-- recupero la lavorazione
local sMilling = ML.FindMilling( 'Mark')
if not sMilling then
local sErr = 'Error : Mark not found in library'
EgtOutLog( sErr)
return -1, sErr
end
-- ottengo le curve di contorno libero
local nAuxId1, nAuxId2, nNumIdAux
if bIs3Faces then
-- nAuxId1, _ = EgtExtractSurfTmLoops( nSurfInt, nAddGrpId)
-- EgtModifyCurveExtrusion( nAuxId1, vtOrtho, GDB_RT.GLOB)
-- SetOpenSide( nAuxId1, vtOrtho, b3Solid, nAddGrpId, 1)
-- nNumIdAux = 2
-- estraggo i percorsi
nAuxId1, nNumIdAux = EgtExtractSurfTmLoops( Proc.Id, _nAddGrpId)
-- se percorso creato estraggo solo i percorsi delle facce interessate, non di testa
if nAuxId1 then
nAuxId1, nNumIdAux, nAuxId2 = ExtractExternalPaths( nAuxId1, nNumIdAux, vtOrtho)
end
else
nAuxId1, nNumIdAux = EgtExtractSurfTmLoops( Proc.Id, _nAddGrpId)
if not nNumIdAux then nNumIdAux = 0 end
end
local dExtra = 2
for i = 1, nNumIdAux do
local AuxId
local vtExtr
if bIs3Faces then
if i == 1 then
AuxId = nAuxId1
else
-- faccio la copia del percorso
-- AuxId = EgtCopyGlob( nAuxId1, nAddGrpId)
AuxId = nAuxId2
end
if AuxId then
vtExtr = EgtCurveExtrusion( AuxId, GDB_RT.GLOB)
end
else
AuxId = nAuxId1 + i - 1
vtExtr, _, _ = EgtCurveArea( AuxId)
end
if vtExtr then
if not bIs3Faces then
local fFrCurve = EgtGetGlobFrame( AuxId)
vtExtr:toGlob( fFrCurve)
end
-- if bIs3Faces and i == nNumIdAux then
-- vtExtr = -vtExtr
-- end
-- Se normale entro certi limiti
-- if vtExtr:getZ() > -0.707 and ( abs(vtOrtho:getX()) > 0.99 or abs(vtOrtho:getY()) > 0.99 or abs(vtOrtho:getZ()) > 0.99) then
if vtExtr:getZ() > -0.707 and ( abs(vtExtr:getX()) > 0.99 or abs(vtExtr:getY()) > 0.99 or abs(vtExtr:getZ()) > 0.99) then
-- inserisco la lavorazione
local sNameCh = 'Cham_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) .. '_' .. tostring( i)
local nMchId = EgtAddMachining( sNameCh, sMilling)
if not nMchId then
local sErr = 'Error adding machining ' .. sNameCh .. '-' .. sMilling
EgtOutLog( sErr)
return -1, sErr
end
-- modifico estrusione percorso
EgtModifyCurveExtrusion( AuxId, vtExtr, GDB_RT.GLOB)
-- aggiungo geometria
EgtSetMachiningGeometry( {{ AuxId, -1}})
-- imposto posizione braccio porta testa
if vtExtr:getY() < GEO.EPS_SMALL then
EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.ADIR_YM)
else
EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.ADIR_YP)
end
EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.LEFT)
-- assegno affondamento e offset radiale
-- EgtSetMachiningParam( MCH_MP.DEPTH, _dDepthCham + dExtra - EgtIf( bIs3Faces, (dDepth / 2), 0))
EgtSetMachiningParam( MCH_MP.DEPTH, _dDepthCham + dExtra)
EgtSetMachiningParam( MCH_MP.OFFSR, dExtra)
-- se opero su 3 facce e sono al secondo e ultimo percorso inverto la lavorazione
-- if bIs3Faces and i == nNumIdAux then
-- EgtSetMachiningParam( MCH_MP.INVERT, true)
-- end
-- eseguo
if not ML.ApplyMachining( true, false) then
local _, sErr = EgtGetLastMachMgrError()
EgtSetOperationMode( nMchId, false)
return -1, sErr
end
-- se non perpendicolare emetto un warning
-- else
-- sWarn = 'Warning : chamfer skipped because not perpendicular to face or from bottom'
-- EgtOutLog( sWarn)
end
--emetto un warning
-- else
-- sWarn = 'Warning : chamfer skipped because not perpendicular to face'
-- EgtOutLog( sWarn)
end
end
return 0
end
---------------------------------------------------------------------
local function MakeByMillAsSaw( Proc, tFData, nBottomFace, sMillingOnSide, dSawDiam, dSawThick)
local sWarn
-- ottengo la distanza tra la fine del pezzo e il pezzo successivo
local dDistToNextPiece = EgtGetInfo( _nRawId, 'BDST', 'd') or 5.
-- Recupero le facce adiacenti alla principale (solo quelle esistenti)
local vAdj = GetValidFacetAdjacencies( Proc.Id, tFData.nFacInd)
if not vAdj or #vAdj == 0 then
local sErr = 'Error : main face without adjacencies'
EgtOutLog( sErr)
return false, sErr
end
EgtOutLog( 'Adjac=' .. table.concat( vAdj, ','), 3)
-- Cerco una faccia adiacente alla principale sul lato più lungo
local nFacAdj
local dMaxLen = 0
for i = 1, #vAdj do
local _, ptP1, ptP2, _ = EgtSurfTmFacetsContact( Proc.Id, tFData.nFacInd, vAdj[i], GDB_ID.ROOT)
local dLen = dist( ptP1, ptP2)
if dLen > dMaxLen then
nFacAdj = vAdj[i]
dMaxLen = dLen
EgtOutLog( string.format( 'Adjac=%d Len=%.3f H=%.3f V=%.3f', vAdj[i], dLen, tFData.dH, tFData.dV), 3)
end
end
if not nFacAdj then
local sErr = 'Error : long adjacent face not found'
EgtOutLog( sErr)
return false, sErr
end
-- Riordino le dimensioni per avere dH come lato lungo e dV come perpendicolare
local _, vtN = EgtSurfTmFacetCenter( Proc.Id, nFacAdj, GDB_ID.ROOT)
if abs( vtN * tFData.rfFac:getVersX()) > abs( vtN * tFData.rfFac:getVersY()) then
tFData.dH, tFData.dV = tFData.dV, tFData.dH
end
-- Determino se estremi aperti o chiusi
local bOpenStart = false
local bOpenEnd = false
-- se non ho la faccia di fondo (che comporta essere una fessura) verifico se ho lati aperti
if not nBottomFace then
local vAdj2 = EgtSurfTmFacetAdjacencies( Proc.Id, nFacAdj)[1]
EgtOutLog( 'Adj2=' .. table.concat( vAdj2, ' ,'), 3)
for j = 1, #vAdj2 do
if vAdj2[j] == tFData.nFacInd then
-- Se non esiste faccia adiacente a lato precedente -> inizio aperto
local i = EgtIf( j > 1, j - 1, #vAdj2)
while vAdj2[i] == tFData.nFacInd do
i = EgtIf( i > 1, i - 1, #vAdj2)
end
bOpenStart = ( vAdj2[i] < 0)
-- Se non esiste faccia adiacente a lato successivo -> fine aperto
local k = EgtIf( j < #vAdj2, j + 1, 1)
while vAdj2[k] == tFData.nFacInd do
k = EgtIf( k < #vAdj2, k + 1, 1)
end
bOpenEnd = ( vAdj2[k] < 0)
end
end
end
-- Se possibile, lavoro con la lama
if _bForceUseBlade then
-- Recupero la lavorazione di lama
local sCutting = sMillingOnSide
-- Calcolo uso faccia
local nFaceUse = BL.GetNearestOrthoOpposite( tFData.rfFac:getVersZ())
local dStartDist = -1
local dEndDist = -1
-- calcolo eventuali arretramenti lama
if not bOpenStart then
local dRadius = dSawDiam / 2
local dCat1 = dRadius - tFData.dFacElev
dStartDist = sqrt( ( dRadius * dRadius) - ( dCat1 * dCat1))
end
if not bOpenEnd then
if not bOpenStart then
dEndDist = dStartDist
else
local dRadius = dSawDiam / 2
local dCat1 = dRadius - tFData.dFacElev
dEndDist = sqrt( ( dRadius * dRadius) - ( dCat1 * dCat1))
end
end
-- Eseguo i tagli
local nStep = ceil( ( tFData.dV - 10 * GEO.EPS_SMALL) / dSawThick)
local dStep = 0
if nStep > 1 then
dStep = ( tFData.dV - dSawThick) / ( nStep - 1)
end
for i = 1, nStep do
local dOffs = ( i - 1) * dStep
--if vtN:getZ() < BD.NZ_MINA then dOffs = dOffs + dSawThick end
local bOk, sErr, nMchId = Fbs.MakeOne( Proc.Id, nFacAdj, sCutting, dSawDiam, nFaceUse, -0.01, 0, BD.CUT_SIC, dOffs, dStartDist, dEndDist, nil, _b3Raw)
if not bOk then return bOk, sErr end
-- setto l'elevazione
local sNotes = 'MaxElev=' .. EgtNumToString( 0, 1) .. ';'
-- applico elevazione
EgtSetMachiningParam( MCH_MP.USERNOTES, sNotes)
-- tolgo eventuale step
EgtSetMachiningParam( MCH_MP.STEP, 0)
if not ML.ApplyMachining( true, false) then
local _, sErr = EgtGetLastMachMgrError()
EgtSetOperationMode( nMchId, false)
return false, sErr
end
end
-- in base all'elevazione calcolo l'impronta della lama
local dUsedBladeLen = sqrt( ( ( dSawDiam / 2) * ( dSawDiam / 2)) - ( ( ( dSawDiam / 2) - tFData.dFacElev) * ( ( dSawDiam / 2) - tFData.dFacElev)))
-- controllo direzione taglio e se il minimo della feature sborda in coda
if abs( vtN:getX()) < GEO.EPS_SMALL and abs( _b3Solid:getMin():getX() - Proc.Box:getMin():getX()) < 100 * GEO.EPS_SMALL and dDistToNextPiece < dUsedBladeLen then
-- do avviso che la lama può sbordare nel pezzo successivo
sWarn = 'Warning on mill side as blade : Cut machining can damage next piece'
EgtOutLog( sWarn .. ' (process ' .. tostring( Proc.Id) .. ')')
end
end
return true, sWarn
end
---------------------------------------------------------------------
local function DoHeadChainSaw( Proc, sName, sSawing, tFData, nFaceUse, nFacAdj, vtN, vtNE, vtNS, dSawWidth,
dOffs, dDistToNextPiece, dMaxDepth, bOpenStart, bOpenEnd)
local nMchFId = EgtAddMachining( sName, sSawing)
if not nMchFId then
local sErr = 'Error adding machining ' .. sName .. '-' .. sSawing
EgtOutLog( sErr)
return false, sErr
end
-- aggiungo geometria
EgtSetMachiningGeometry( {{ Proc.Id, nFacAdj}})
-- imposto uso faccia
EgtSetMachiningParam( MCH_MP.FACEUSE, nFaceUse)
-- controllo direzione taglio e se il minimo della feature sborda in coda
if not Proc.Tail and abs( vtN:getX()) < GEO.EPS_SMALL and abs( _b3Solid:getMin():getX() - Proc.Box:getMin():getX()) < 100 * GEO.EPS_SMALL then
-- se ho lato partenza aperto e lato uscita chiuso e direzione lato chiuso è negativa, allora controllo uscita lama
if bOpenStart and not bOpenEnd and vtNE:getX() < -0.99 and dDistToNextPiece < ( dSawWidth / 2) then
-- imposto accorciamento iniziale per estremi aperti/chiusi
EgtSetMachiningParam( MCH_MP.STARTADDLEN, dDistToNextPiece - 1 - ( dSawWidth / 2))
else
-- imposto accorciamento iniziale per estremi aperti/chiusi
EgtSetMachiningParam( MCH_MP.STARTADDLEN, EgtIf( bOpenStart, 0, - dSawWidth / 2))
end
-- se ho lato uscita aperto e lato partenza chiuso e direzione lato partenza è negativa, allora controllo uscita lama
if bOpenEnd and not bOpenStart and vtNS:getX() < -0.99 and dDistToNextPiece < ( dSawWidth / 2) then
-- imposto accorciamento finale per estremi aperti/chiusi
EgtSetMachiningParam( MCH_MP.ENDADDLEN, dDistToNextPiece - 1 - ( dSawWidth / 2))
else
-- imposto accorciamento finale per estremi aperti/chiusi
EgtSetMachiningParam( MCH_MP.ENDADDLEN, EgtIf( bOpenEnd, 0, - dSawWidth / 2))
end
else
-- imposto accorciamento iniziale/finale per estremi aperti/chiusi
EgtSetMachiningParam( MCH_MP.STARTADDLEN, EgtIf( bOpenStart, 0, - dSawWidth / 2))
EgtSetMachiningParam( MCH_MP.ENDADDLEN, EgtIf( bOpenEnd, 0, - dSawWidth / 2))
end
-- imposto angolo 3° asse rot e eventuale angolo suggerito per inizio
EgtSetMachiningParam( MCH_MP.BLOCKEDAXIS, GetChainSawBlockedAxis( 1))
EgtSetMachiningParam( MCH_MP.INITANGS, GetChainSawInitAngs( vtN, tFData.rfFac:getVersZ()))
-- imposto offset radiale
EgtSetMachiningParam( MCH_MP.OFFSR, dOffs)
-- se necessario, limito l'affondamento
if tFData.dFacElev > dMaxDepth + 10 * GEO.EPS_SMALL then
local sWarn = 'Warning in LapJoint : elevation (' .. EgtNumToString( tFData.dFacElev, 1) .. ') bigger than max tool depth (' .. EgtNumToString( dMaxDepth, 1) .. ')'
local dDepth = dMaxDepth - tFData.dFacElev
EgtOutLog( sWarn)
EgtSetMachiningParam( MCH_MP.DEPTH_STR, 'TH ' .. EgtNumToString( dDepth, 1))
end
-- imposto elevazione
local sNotes = 'MaxElev=' .. EgtNumToString( tFData.dFacElev, 2) .. ';'
EgtSetMachiningParam( MCH_MP.USERNOTES, sNotes)
-- eseguo
if not ML.ApplyMachining( true, false) then
if EgtGetOutstrokeInfo() then
local _, sErr = EgtGetLastMachMgrError()
EgtSetOperationMode( nMchFId, false)
return false, sErr
end
-- impostazione alternativa angolo 3° asse rot
EgtSetMachiningParam( MCH_MP.BLOCKEDAXIS, GetChainSawBlockedAxis( 2))
EgtSetMachiningParam( MCH_MP.INITANGS, GetChainSawInitAngs( vtN, tFData.rfFac:getVersZ()))
if not ML.ApplyMachining( true, false) then
local _, sErr = EgtGetLastMachMgrError()
EgtSetOperationMode( nMchFId, false)
return false, sErr
end
end
if EgtIsMachiningEmpty() then
local _, sWarn = EgtGetMachMgrWarning( 0)
EgtSetOperationMode( nMchFId, false)
return false, sWarn
end
return true
end
---------------------------------------------------------------------
local function DoSideChainSaw( Proc, sName, sSawing, tFData, vtN, vtOrtho, nLongFaceId,
dOffs, dMaxMat, dSawCornerRad, bOpenStart, bOpenEnd)
local nMchFId = EgtAddMachining( sName, sSawing)
if not nMchFId then
local sErr = 'Error adding machining ' .. sName .. '-' .. sSawing
EgtOutLog( sErr)
return false, sErr
end
-- aggiungo geometria
EgtSetMachiningGeometry( {{ Proc.Id, nLongFaceId}})
-- imposto uso del lato faccia
local nFaceUse
-- se non è un tunnel a 4 facce
if Proc.Fct < 4 then
nFaceUse = BL.GetNearestParalOpposite( tFData.rfFac:getVersZ(), vtN)
-- altrimenti vero tunnel (solo sopra-sotto o davanti-dietro)
else
if abs( vtOrtho:getZ()) >= 0.707 then
nFaceUse = MCH_MILL_FU.PARAL_DOWN
else
nFaceUse = MCH_MILL_FU.PARAL_BACK
end
end
EgtSetMachiningParam( MCH_MP.FACEUSE, nFaceUse)
-- imposto angolo 3° asse rot
EgtSetMachiningParam( MCH_MP.BLOCKEDAXIS, GetChainSawBlockedAxis( 1))
EgtSetMachiningParam( MCH_MP.INITANGS, GetChainSawInitAngs( vtN, vtOrtho))
-- imposto offset radiale
EgtSetMachiningParam( MCH_MP.OFFSR, dOffs)
-- se non è un tunnel a 4 facce
if Proc.Fct < 4 then
-- imposto sempre massimo affondamento
local dBoxDepth
if nFaceUse == MCH_MILL_FU.PARAL_LEFT or nFaceUse == MCH_MILL_FU.PARAL_RIGHT then
dBoxDepth = Proc.Box:getDimX()
elseif nFaceUse == MCH_MILL_FU.PARAL_FRONT or nFaceUse == MCH_MILL_FU.PARAL_BACK then
dBoxDepth = Proc.Box:getDimY()
else
dBoxDepth = Proc.Box:getDimZ()
end
EgtSetMachiningParam( MCH_MP.DEPTH, dBoxDepth)
if dBoxDepth > dMaxMat then
local sWarn = 'Warning : elevation bigger than max tool depth'
EgtOutLog( sWarn)
end
-- sistemo inizio e fine
if bOpenStart then EgtSetMachiningParam( MCH_MP.STARTADDLEN, 0) end
if bOpenEnd then EgtSetMachiningParam( MCH_MP.ENDADDLEN, 0) end
-- altrimenti vero tunnel (solo sopra-sotto o davanti-dietro)
else
-- se possibile aumento l'affondamento pari al raggio corner + 1
if dMaxMat > ( dDepth + dSawCornerRad + 1) then
EgtSetMachiningParam( MCH_MP.DEPTH, ( dDepth + dSawCornerRad + 1))
-- se massimo affondamento supera altezza fessura, uso massimo affondamento
elseif dMaxMat > ( dDepth + 1) then
EgtSetMachiningParam( MCH_MP.DEPTH, ( dMaxMat - 1))
-- se massimo affondamento utensile inferiore fessura, setto affondamento ed emetto warning
elseif dMaxMat < dDepth then
EgtSetMachiningParam( MCH_MP.DEPTH, dMaxMat)
local sWarn = 'Warning : elevation bigger than max tool depth'
EgtOutLog( sWarn)
end
end
if Q_MAX_ELEVATION and Q_MAX_ELEVATION > 10 then
local sNotes = 'MaxElev=' .. EgtNumToString( Q_MAX_ELEVATION, 1) .. ';'
EgtSetMachiningParam( MCH_MP.USERNOTES, sNotes)
end
-- eseguo
if not ML.ApplyMachining( true, false) then
if EgtGetOutstrokeInfo() then
local _, sErr = EgtGetLastMachMgrError()
EgtSetOperationMode( nMchFId, false)
return false, sErr
end
-- impostazione alternativa angolo 3° asse rot
EgtSetMachiningParam( MCH_MP.BLOCKEDAXIS, GetChainSawBlockedAxis( 2))
EgtSetMachiningParam( MCH_MP.INITANGS, GetChainSawInitAngs( vtN, vtOrtho))
if not ML.ApplyMachining( true, false) then
local _, sErr = EgtGetLastMachMgrError()
EgtSetOperationMode( nMchFId, false)
return false, sErr
end
end
if EgtIsMachiningEmpty() then
local _, sWarn = EgtGetMachMgrWarning( 0)
EgtSetOperationMode( nMchFId, false)
return false, sWarn
end
return true
end
---------------------------------------------------------------------
local function MakeByChainOrSaw( Proc, tFData, dDimMin, dDimMax, vtOrtho, nLongFaceId,
bOrthoFacesMaster, nBottomFace, nSurfInt)
local bIs3Faces = Proc.Fct == 3
local bOrthoFaces
local sWarn
-- ottengo la distanza tra la fine del pezzo e il pezzo successivo
local dDistToNextPiece = EgtGetInfo( _nRawId, 'BDST', 'd') or 5.4
if bIs3Faces then
-- recupero la faccia con il maggior numero di adiacenze e l'elevazione relativa
local nFacInd1, dFacElev1, nFacInd2, dFacElev2 = BL.GetFaceWithMostAdj( Proc.Id, _nPartId, bIs3Faces)
if not nFacInd1 or nFacInd1 < 0 then
if nFacInd1 == -1 then
bOrthoFaces = nFacInd2
else
local sErr = 'Error : MakeByChainOrSaw could not find reference face'
EgtOutLog( sErr)
return false, sErr
end
end
else
bOrthoFaces = bOrthoFacesMaster
end
if bOrthoFaces then
-- ottengo le dimensioni del tunnel
dDimMin, dDimMax, dDepth, vtOrtho, nLongFaceId, nSurfInt = GetTunnelDimension( Proc)
-- verifico la direzione
-- se devo inserire il chamfer
if _nChamfer > 0 then
local nOk, sErr = MakeChamfer( Proc, vtOrtho, nSurfInt)
if nOk < 0 then return false, sErr end
end
end
-- Recupero le facce adiacenti alla principale (solo quelle esistenti)
local vAdj = GetValidFacetAdjacencies( Proc.Id, tFData.nFacInd)
if not vAdj or #vAdj == 0 then
local sErr = 'Error : main face without adjacencies'
EgtOutLog( sErr)
return false, sErr
end
EgtOutLog( 'Adjac=' .. table.concat( vAdj, ','), 3)
-- Cerco una faccia adiacente alla principale sul lato più lungo
local nFacAdj
local dMaxLen = 0
for i = 1, #vAdj do
local _, ptP1, ptP2, _ = EgtSurfTmFacetsContact( Proc.Id, tFData.nFacInd, vAdj[i], GDB_ID.ROOT)
local dLen = dist( ptP1, ptP2)
if dLen > dMaxLen then
nFacAdj = vAdj[i]
dMaxLen = dLen
EgtOutLog( string.format( 'Adjac=%d Len=%.3f H=%.3f V=%.3f', vAdj[i], dLen, tFData.dH, tFData.dV), 3)
end
end
if not nFacAdj then
local sErr = 'Error : long adjacent face not found'
EgtOutLog( sErr)
return false, sErr
end
-- Riordino le dimensioni per avere dH come lato lungo e dV come perpendicolare
local _, vtN = EgtSurfTmFacetCenter( Proc.Id, nFacAdj, GDB_ID.ROOT)
if abs( vtN * tFData.rfFac:getVersX()) > abs( vtN * tFData.rfFac:getVersY()) then
tFData.dH, tFData.dV = tFData.dV, tFData.dH
end
-- Determino se estremi aperti o chiusi
local bOpenStart = false
local bOpenEnd = false
local vtNS, vtNE
-- se non ho la faccia di fondo (che comporta essere una fessura) verifico se ho lati aperti
if not nBottomFace then
local vAdj2 = EgtSurfTmFacetAdjacencies( Proc.Id, nFacAdj)[1]
EgtOutLog( 'Adj2=' .. table.concat( vAdj2, ' ,'), 3)
for j = 1, #vAdj2 do
if vAdj2[j] == tFData.nFacInd then
-- Se non esiste faccia adiacente a lato precedente -> inizio aperto
local i = EgtIf( j > 1, j - 1, #vAdj2)
while vAdj2[i] == tFData.nFacInd do
i = EgtIf( i > 1, i - 1, #vAdj2)
end
bOpenStart = ( vAdj2[i] < 0)
-- se è chiusa acquisisco vettore faccia tappo
if not bOpenStart and vAdj2[i] >= 0 then
_, vtNS = EgtSurfTmFacetCenter( Proc.Id, vAdj2[i], GDB_ID.ROOT)
end
-- Se non esiste faccia adiacente a lato successivo -> fine aperto
local k = EgtIf( j < #vAdj2, j + 1, 1)
while vAdj2[k] == tFData.nFacInd do
k = EgtIf( k < #vAdj2, k + 1, 1)
end
bOpenEnd = ( vAdj2[k] < 0)
-- se è chiusa acquisisco vettore faccia tappo
if not bOpenEnd and vAdj2[k] >= 0 then
_, vtNE = EgtSurfTmFacetCenter( Proc.Id, vAdj2[k], GDB_ID.ROOT)
end
end
end
end
-- Recupero il massimo affondamento possibile con la lama
local dSawMaxDepth = 0
local sCutting = ML.FindCutting( 'HeadSide')
if sCutting then
local TI = GetToolInfoForMachining( sCutting)
if TI then
dSawMaxDepth = TI.dMaxDepth or dSawMaxDepth
end
end
-- se lavorazione sulle teste e altezza trave supera il limite (che causa collisione con la forcella) e direzione taglio lungo la Z
-- e limite profondità BeamData è maggiore del taglio massimo lama, assegno il massimo affondamento pari al limite profondità del BeamData
if bOpenStart and bOpenEnd and _bForceUseBlade and ( Proc.Head or Proc.Tail) and abs( tFData.rfFac:getVersY():getY()) > 0.866 and
_b3Solid:getDimZ() > BD.MIN_DIM_HBEAM and dSawMaxDepth > BD.MAX_DIM_HTCUT_HBEAM then
dSawMaxDepth = BD.MAX_DIM_HTCUT_HBEAM
end
-- Se entrambi gli estremi sono aperti e possibile, lavoro con la lama
if bOpenStart and bOpenEnd and _bForceUseBlade and tFData.dFacElev < dSawMaxDepth + 10 * GEO.EPS_SMALL then
-- Recupero la lavorazione di lama
local sCutting = ML.FindCutting( 'HeadSide')
if not sCutting then
local sErr = 'Error : HeadSide (cutting) not found in library'
EgtOutLog( sErr)
return false, sErr, 'MNF'
end
-- recupero i dati dell'utensile
local dSawDiam = 400
local dSawThick = 4
local TI = GetToolInfoForMachining( sCutting)
if TI then
dSawDiam = TI.dDiam or dSawDiam
dSawThick = TI.dThick
end
if dSawThick > tFData.dV + 10 * GEO.EPS_SMALL then
local sErr = 'Error : sawblade too thick'
EgtOutLog( sErr)
return false, sErr
end
-- Calcolo uso faccia
local nFaceUse = BL.GetNearestOrthoOpposite( tFData.rfFac:getVersZ())
-- Eseguo i tagli
local nStep = ceil( ( tFData.dV - 10 * GEO.EPS_SMALL) / dSawThick)
local dStep = 0
if nStep > 1 then
dStep = ( tFData.dV - dSawThick) / ( nStep - 1)
end
for i = 1, nStep do
local dOffs = ( i - 1) * dStep
local bOk, sErr = Fbs.MakeOne( Proc.Id, nFacAdj, sCutting, dSawDiam, nFaceUse, -0.01, 0, BD.CUT_SIC, dOffs, 0, 0, nil, _b3Raw)
if not bOk then return bOk, sErr end
end
-- in base all'elevazione calcolo l'impronta della lama
local dUsedBladeLen = sqrt( ( ( dSawDiam / 2) * ( dSawDiam / 2)) - ( ( ( dSawDiam / 2) - tFData.dFacElev) * ( ( dSawDiam / 2) - tFData.dFacElev)))
-- controllo direzione taglio e se il minimo della feature sborda in coda
if not Proc.Tail and abs( vtN:getX()) < GEO.EPS_SMALL and abs( _b3Solid:getMin():getX() - Proc.Box:getMin():getX()) < 100 * GEO.EPS_SMALL and dDistToNextPiece < dUsedBladeLen then
-- do avviso che la lama può sbordare nel pezzo successivo
sWarn = 'Warning on saw cut : Cut machining can damage next piece'
EgtOutLog( sWarn .. ' (process ' .. tostring( Proc.Id) .. ')')
end
-- altrimenti con sega a catena
else
-- Recupero la lavorazione
local sSawing = ML.FindSawing( 'Sawing')
if not sSawing then
local sErr = 'Error : Sawing not found in library'
EgtOutLog( sErr)
return false, sErr, 'MNF'
end
-- Recupero i dati dell'utensile
local dSawWidth = 75
local dSawThick = 8
local dMaxDepth = 200
local TI = GetToolInfoForMachining( sSawing)
if TI then
dSawWidth = TI.dDiam or dSawWidth
dSawThick = TI.dThick or dSawThick
dMaxDepth = TI.dMaxDepth or dMaxDepth
end
if dSawThick > tFData.dV + 10 * GEO.EPS_SMALL then
local sErr = 'Error : chainsaw too thick'
EgtOutLog( sErr)
return false, sErr
end
local bGoFromHead = true
-- se la lunghezza utensile non riesce ad arrivare sul fondo assegno la possibilità di lavorare di testa o di fianco
if tFData.dFacElev > dMaxDepth + 10 * GEO.EPS_SMALL then
-- lavora di testa se è un tunnel, lavora di fianco se non è un tunnel
bGoFromHead = not bOrthoFaces
end
-- se continuo a lavorare di testa
if bGoFromHead then
-- Calcolo uso faccia
local nFaceUse = BL.GetNearestParalOpposite( tFData.rfFac:getVersZ())
-- Calcolo normale faccia adiacente
local vtN = EgtSurfTmFacetNormVersor( Proc.Id, nFacAdj, GDB_ID.ROOT)
-- Verifico se necessarie più passate
local nStep = ceil( ( tFData.dV - 10 * GEO.EPS_SMALL) / dSawThick)
local dStep = 0
if nStep > 1 then
dStep = ( tFData.dV - dSawThick) / ( nStep - 1)
end
for i = 1, nStep do
-- Applico la lavorazione con sega a catena a questa faccia
local sName = 'Csaw_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) .. '_' .. tostring( i)
local dOffs = ( i - 1) * dStep
local bOk, sErr = DoHeadChainSaw( Proc, sName, sSawing, tFData, nFaceUse, nFacAdj, vtN, vtNE, vtNS, dSawWidth, dOffs, dDistToNextPiece, dMaxDepth, bOpenStart, bOpenEnd)
if not bOk then
return false, sErr
end
end
-- altrimenti segacatena di fianco
else
-- verifico se posso farlo con la sega-catena
local bMakeChainSaw, sSawing2, dMaxMat2, dSawCornerRad2, dSawThick2 = VerifyChainSaw( dDimMin, dDimMax)
if bMakeChainSaw then
-- Verifico se necessarie più passate
local nStep = ceil( ( dDimMin - 10 * GEO.EPS_SMALL) / dSawThick2)
local dStep = 0
if nStep > 1 then
dStep = ( dDimMin - dSawThick2) / ( nStep - 1)
end
for i = 1, nStep do
-- inserisco la lavorazione di sawing
local sName = 'Csaw_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) .. '_' .. tostring( i)
local dOffs = ( i - 1) * dStep
local bOk, sErr = DoSideChainSaw( Proc, sName, sSawing2, tFData, vtN, vtOrtho, nLongFaceId, dOffs, dMaxMat2, dSawCornerRad2, bOpenStart, bOpenEnd)
if not bOk then
return false, sErr
end
end
end
end
end
return true, sWarn
end
---------------------------------------------------------------------
local function MakeAntiSplintBySaw( Proc, nFacet, vtN, nFacInd, bReduceDepth, bMillDown)
-- Recupero la lavorazione di lama
local sCutting = ML.FindCutting( 'HeadSide', not bMillDown, bMillDown)
if not sCutting then
local sErr = 'Error : HeadSide (cutting) not found in library'
EgtOutLog( sErr)
return false, sErr
end
-- valuto l'angolo tra le due facce
local bAdj, ptP1, ptP2, dAng = EgtSurfTmFacetsContact( Proc.Id, nFacInd, nFacet, GDB_ID.ROOT)
local ptPm = (ptP1 + ptP2) / 2
-- ottengo il boundingBox e prendo le dimensioni lungo la normale (Z locale) che rappresenta l'elevazione della faccia
-- laterale sul punto medio della linea in comune
local frFc = Frame3d( ptPm, vtN)
local b3BoxLoc = EgtGetBBoxRef( Proc.Id, GDB_BB.STANDARD, frFc)
local dDepth = b3BoxLoc:getDimZ() or 0
-- recupero i dati dell'utensile
local dSawDiam = 400
local dSawThick = 0
local dMaxDepth = 0
local TI = GetToolInfoForMachining( sCutting)
if TI then
dSawDiam = TI.dDiam or dSawDiam
dSawThick = TI.dThick or dSawThick
dMaxDepth = TI.dMaxDepth or dMaxDepth
end
local dExtraOffs = 0
-- se profondità superiore al massimo lama modifico elevazione
if dDepth > dMaxDepth then
dExtraOffs = dMaxDepth - dDepth
end
-- se devo ridurre l'affondamento
if bReduceDepth then
local dLimitDepth = 100
-- se ho ridotto l'affondamento ne riduco ulteriormente l'affondamento (50mm)
if abs( dExtraOffs) > 0 then
if dMaxDepth > dLimitDepth then
dExtraOffs = dLimitDepth - dDepth
end
else
if dDepth > dLimitDepth then
dExtraOffs = dLimitDepth - dDepth
else
dExtraOffs = -( dDepth / 2)
end
end
end
-- eseguo il taglio
local bMadeASbyBld, sWarn, nIdMach = Fbs.MakeOne( Proc.Id, nFacet, sCutting, dSawDiam, vtN, nil, ( -0.5 + dExtraOffs), BD.CUT_SIC, 0, 0, 0, nil, _b3Raw)
if bMadeASbyBld then
sWarn = nil
if abs( dExtraOffs) > 0 then
sWarn = 'Warning : antisplint elevation is bigger than max tool depth'
end
end
return bMadeASbyBld, sWarn, nIdMach, dSawThick, dMaxDepth, dAng
end
---------------------------------------------------------------------
local function DoPocketing( sName, sPocketing, sMchFind, vtN, nPathInt, nFaceIdx, nUseRoughTool, dMachDepth, dMaxElev, bInvertTool, bInvertPath, bFaceOrtho, bSCCEvaluateOppositeVector, bSCCYSpecialStrategy)
-- inserisco la lavorazione di svuotatura
local nMchFId = EgtAddMachining( sName, sPocketing)
if not nMchFId then
local sErr = 'Error adding machining ' .. sName .. '-' .. sPocketing
EgtOutLog( sErr)
return false, sErr
end
-- aggiungo geometria
EgtSetMachiningGeometry( {{ nPathInt, nFaceIdx}})
if bInvertTool then
EgtSetMachiningParam( MCH_MP.TOOLINVERT, true)
end
if bFaceOrtho then
-- imposto uso faccia
EgtSetMachiningParam( MCH_MP.FACEUSE, MCH_MILL_FU.ORTHO_CONT)
end
-- imposto posizione braccio porta testa
local nSCC = MCH_SCC.NONE
if not BD.C_SIMM then
if EgtIf( bSCCEvaluateOppositeVector, AreSameOrOppositeVectorApprox( vtN, Z_AX()), AreSameVectorApprox( vtN, Z_AX())) then
nSCC = MCH_SCC.ADIR_YM
elseif abs( vtN:getX()) < 0.1 then
nSCC = EgtIf( BL.IsPartFinalPhase( _nPhase), MCH_SCC.ADIR_XM, MCH_SCC.ADIR_XP)
elseif bSCCYSpecialStrategy then
if vtN:getY() > 0.1 then
nSCC = MCH_SCC.ADIR_YP
else
nSCC = MCH_SCC.ADIR_YM
end
else
if vtN:getY() < GEO.EPS_SMALL then
nSCC = EgtIf( bInvertTool, MCH_SCC.ADIR_YP, MCH_SCC.ADIR_YM)
else
nSCC = EgtIf( bInvertTool, MCH_SCC.ADIR_YM, MCH_SCC.ADIR_YP)
end
end
end
EgtSetMachiningParam( MCH_MP.SCC, nSCC)
-- se tasca aperta, imposto opportuno attacco
if (sMchFind == 'OpenPocket' and nUseRoughTool == 0) or sMchFind == 'OpenPocket_H2' then
EgtSetMachiningParam( MCH_MP.SUBTYPE, MCH_POCK_SUB.SPIRALIN)
end
if bInvertPath then
-- inverto il percorso di lavorazione se necessario lavorare sinistro
EgtSetMachiningParam( MCH_MP.INVERT, bInvertPath)
end
if dMachDepth ~= 0 then
-- imposto affondamento
EgtSetMachiningParam( MCH_MP.DEPTH, dMachDepth)
end
-- imposto elevazione e dichiaro non si generano sfridi per VMill
local sNotes = 'VMRS=0;'
if dMaxElev > 0 then
sNotes = sNotes .. 'MaxElev=' .. EgtNumToString( dMaxElev, 1) .. ';'
end
EgtSetMachiningParam( MCH_MP.USERNOTES, sNotes)
-- eseguo
if not ML.ApplyMachining( true, false) then
-- provo ad allargare leggermente la tasca
EgtSetMachiningParam( MCH_MP.OFFSR, -0.1)
if not ML.ApplyMachining( true, false) then
local bOk, sErr = EgtGetLastMachMgrError()
EgtSetOperationMode( nMchFId, false)
return false, sErr
end
end
return true, '', nMchFId
end
---------------------------------------------------------------------
local function MakePocket( Proc, ptPs, tvtN, nFaceRef, sMchFind, nUseRoughTool,
sMasterPocket, dPrevFaceElev, tDimAndRef, dAng)
-- calcolo l'elevazione dal punto medio
local dElev
local dLenIn, dLedOut = BL.GetPointDirDepth( _nPartId, ptPs, tvtN[2])
if dLenIn > 0 then
dElev = dLenIn
elseif dLedOut then
dElev = dLedOut
end
local dCollSic = 2 * BD.COLL_SIC
-- calcolo il diametro utensile
local dDiamTool
local dFaceDiamTool
if tDimAndRef then
-- prendo il valore dalle dimensioni minime delle facce
dFaceDiamTool = min( tDimAndRef[2][1], tDimAndRef[2][2])
end
-- se ho lavorazione precedente ricalcolo grossolanamente l'elevazione
if dPrevFaceElev and dPrevFaceElev > 0 and dAng then
dElev = dElev + ( sqrt( ( dElev * dElev) - ( dPrevFaceElev * dPrevFaceElev)) * sin( dAng))
elseif dPrevFaceElev and dPrevFaceElev > dElev then
dElev = dPrevFaceElev
end
local sPocketing
if sMasterPocket then
sPocketing = sMasterPocket
else
sPocketing = ML.FindPocketing( sMchFind, dFaceDiamTool, dElev + dCollSic)
end
if not sPocketing then
local sErr = 'Error : ' .. sMchFind .. ' not found in library'
EgtOutLog( sErr)
return false, sErr
end
dDiamTool = 20
local dMaxDepth = 0
local sTuuidPk
if EgtMdbSetCurrMachining( sPocketing) then
sTuuidPk = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID)
if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuidPk) or '') then
dMaxDepth = ( EgtTdbGetCurrToolMaxDepth() or dMaxDepth)
dDiamTool = EgtTdbGetCurrToolParam( MCH_TP.DIAM)
end
end
-- se nome svuotatura non è stato ricalcolato, confronto il diametro utensile utilizzato con il minimo faccia e se non sono compatibili esco
if sMasterPocket and dFaceDiamTool and dDiamTool >= dFaceDiamTool then
return false, '', sTuuidPk, dDiamTool, dElev
end
-- inserisco la lavorazione di svuotatura
local sName = 'Pock_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) .. 'F' .. tostring( nFaceRef)
local dMachDepth = 0
if dElev > dMaxDepth + 10 * GEO.EPS_SMALL then
dMachDepth = dMaxDepth - dElev
dElev = dMaxDepth
sWarn = 'Warning : elevation bigger than max tool depth'
EgtOutLog( sWarn)
end
local bOk, sWarn, nMchFId = DoPocketing( sName, sPocketing, sMchFind, tvtN[2], Proc.Id, nFaceRef, nUseRoughTool, dMachDepth, dElev, false, false, true, false, true)
if not bOk then
return bOk, sWarn
end
return true, sWarn, sTuuidPk, dDiamTool
end
---------------------------------------------------------------------
local function DoHeadCut( Proc, sName, sMilling, nMchFId, dElev, nSideFace, tvtN)
local nMchId = EgtAddMachining( sName, sMilling)
if not nMchId then
local sErr = 'Error adding machining ' .. sName .. '-' .. sMilling
EgtOutLog( sErr)
return false, sErr
end
-- aggiungo geometria
EgtSetMachiningGeometry( {{ Proc.Id, nSideFace}})
-- imposto uso faccia
local nFaceUse = BL.GetNearestOrthoOpposite( tvtN[1])
-- aggiusto i parametri
EgtSetMachiningParam( MCH_MP.FACEUSE, nFaceUse)
EgtSetMachiningParam( MCH_MP.DEPTH_STR, 'TH')
EgtSetMachiningParam( MCH_MP.OFFSR, 0)
EgtSetMachiningParam( MCH_MP.INVERT, false)
EgtSetMachiningParam( MCH_MP.WORKSIDE, 1)
-- imposto posizione braccio porta testa
if tvtN[2]:getY() < GEO.EPS_SMALL then
EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.ADIR_YM)
else
EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.ADIR_YP)
end
-- imposto elevazione e dichiaro non si generano sfridi per VMill
local sNotes = 'MaxElev=' .. EgtNumToString( dElev, 1) .. ';VMRS=0;'
EgtSetMachiningParam( MCH_MP.USERNOTES, sNotes)
if not ML.ApplyMachining( true, false) then
local _, sErr = EgtGetLastMachMgrError()
EgtSetOperationMode( nMchFId, false)
return false, sErr
end
return true
end
---------------------------------------------------------------------
local function MachineByMill( Proc, tvtN, nBaseFace, nSideFace, ptPs, tDimAndRef,
nDiffWidth, nUseRoughTool, dAng, sPocketing, sTuuidPk, dPrevFaceElev)
-- se angolo tra le facce maggiore di 90, inserisco la contornatura o svuotatura del lato più corto
if ( 180 + dAng) > 90.1 then
local sMchFind = 'Pocket'
local dAngLimit = 40
-- se feature é larga come trave imposto openpocket
if nDiffWidth == 0 then
sMchFind = 'OpenPocket'
-- altrimenti non è passante disabilito il truciolatore
else
nUseRoughTool = 0
end
-- calcolo l'angolo dalla verticale dall'angolo tra le due facce, perchè la feature potrebbe essere ruotata sulla Z locale della
-- faccia principale e quindi la componente X del versore della faccia potrebbe dare un valore non coerente
local dDiffFromSqAng = dAng + 90
-- se l'angolo dalla verticale si discosta di più dell'angolo limite impostato, utilizzo la svuotatura
if cos( dDiffFromSqAng) < cos( dAngLimit) then
-- applico la svuotatura
local bOk, sWarn, sTuuidPk, dDiamTool, dElev = MakePocket( Proc, ptPs, tvtN, nSideFace, sMchFind, nUseRoughTool, sPocketing, dPrevFaceElev, tDimAndRef, dAng)
if not bOk then
if sTuuidPk then
-- recupero la lavorazione
local sMilling = ML.FindMilling( 'Long2Cut', dElev, sTuuidPk)
if not sMilling then
local sErr = 'Error : Long2Cut not found in library'
EgtOutLog( sErr)
return false, sErr
end
-- inserisco la lavorazione
local sName = 'Prof_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id))
bOk, sWarn = DoHeadCut( Proc, sName, sMilling, nMchFId, dElev, nSideFace, tvtN)
if not bOk then
return false, sWarn
end
end
else
return bOk, sWarn
end
-- altrimenti contornatura di fianco
else
local bOpenStart = false
local bOpenEnd = false
if nDiffWidth == 0 then
bOpenStart = true
bOpenEnd = true
else
local vAdj2 = EgtSurfTmFacetAdjacencies( Proc.Id, (nBaseFace))[1]
for j = 1, #vAdj2 do
if vAdj2[j] == nSideFace then
-- Se non esiste faccia adiacente a lato precedente -> inizio aperto
local i = EgtIf( j > 1, j - 1, #vAdj2)
while vAdj2[i] == nSideFace do
i = EgtIf( i > 1, i - 1, #vAdj2)
end
bOpenStart = ( vAdj2[i] < 0)
-- Se non esiste faccia adiacente a lato successivo -> fine aperto
local k = EgtIf( j < #vAdj2, j + 1, 1)
while vAdj2[k] == nSideFace do
k = EgtIf( k < #vAdj2, k + 1, 1)
end
bOpenEnd = ( vAdj2[k] < 0)
end
end
end
local sMilling
if nUseRoughTool > 0 then
sMilling = ML.FindMilling( 'Long2Cut', nil, sTuuidPk)
else
sMilling = ML.FindMilling( 'LongSmallCut', nil, sTuuidPk)
end
if not sMilling then
local sErr = 'Error : Long2Cut & LongSmallCut not found in library'
EgtOutLog( sErr)
return false, sErr
end
-- recupero i dati dell'utensile
local dTDiam = 50
local TI = GetToolInfoForMachining( sMilling)
if TI then
dTDiam = TI.dDiam or dTDiam
end
-- Calcolo uso faccia
local nFaceUse = BL.GetNearestParalOpposite( tDimAndRef[1][3]:getVersZ())
-- inserisco la lavorazione di fresatura
local sName = 'Mill_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id))
local nMchFId = EgtAddMachining( sName, sMilling)
if not nMchFId then
local sErr = 'Error adding machining ' .. sName .. '-' .. sMilling
EgtOutLog( sErr)
return false, sErr
end
-- aggiungo geometria
EgtSetMachiningGeometry( {{ Proc.Id, (nSideFace)}})
-- imposto uso faccia
EgtSetMachiningParam( MCH_MP.FACEUSE, nFaceUse)
-- setto inversione del percorso
EgtSetMachiningParam( MCH_MP.INVERT, true)
-- setto a 0 eventuali offset
EgtSetMachiningParam( MCH_MP.OFFSR, 0)
-- calcolo elevazione per allungamenti attacchi con fianchi chiusi
local dElev
local dLenIn, dLedOut = BL.GetPointDirDepth( _nPartId, ptPs, tvtN[2])
if dLenIn > 0 then
dElev = dLenIn
elseif dLedOut then
dElev = dLedOut
end
-- applico gli allungamenti o accorciamenti
if bOpenStart then
EgtSetMachiningParam( MCH_MP.STARTADDLEN, dTDiam / 2)
else
EgtSetMachiningParam( MCH_MP.STARTADDLEN, -dTDiam / 2)
if dElev > 0 then
EgtSetMachiningParam( MCH_MP.LIPERP, dElev)
end
end
if bOpenEnd then
EgtSetMachiningParam( MCH_MP.ENDADDLEN, dTDiam / 2)
else
EgtSetMachiningParam( MCH_MP.ENDADDLEN, -dTDiam / 2)
if dElev > 0 then
EgtSetMachiningParam( MCH_MP.LOPERP, dElev)
end
end
-- eseguo
if not ML.ApplyMachining( true, false) then
local _, sErr = EgtGetLastMachMgrError()
EgtSetOperationMode( nMchFId, false)
return false, sErr
end
end
end
return true
end
---------------------------------------------------------------------
local function GetUShapeWidth( Proc, nFacInd)
-- Recupero le facce adiacenti alla principale (solo quelle esistenti)
local vAdj = GetValidFacetAdjacencies( Proc.Id, nFacInd)
-- se non ho facce adiacenti esco subito
if not vAdj or #vAdj == 0 then return nil end
-- Normale della faccia
local ptC, vtN = EgtSurfTmFacetCenter( Proc.Id, nFacInd, GDB_ID.ROOT)
-- Cerco le facce adiacenti alla principale con angolo concavo >= 90
local dWidth = 0
for i = 1, #vAdj do
-- verifico l'angolo tra le facce ( esco se angolo compreso < 90)
local bAdj, _, _, dAng = EgtSurfTmFacetsContact( Proc.Id, nFacInd, vAdj[i], GDB_ID.ROOT)
if bAdj and dAng < -90 - 20 * GEO.EPS_ANG_SMALL then return nil end
-- larghezza della faccia ortogonalmente alla adiacente
local vtN2 = EgtSurfTmFacetNormVersor( Proc.Id, vAdj[i], GDB_ID.ROOT)
local vtX = vtN2 ^ vtN
local frRef = Frame3d( ptC, ptC + 100 * vtX, ptC + 100 * vtN2)
local b3Ref = EgtSurfTmGetFacetBBoxRef( Proc.Id, nFacInd, GDB_BB.STANDARD, frRef)
if b3Ref then
dWidth = max( dWidth, b3Ref:getDimY())
end
end
return dWidth
end
---------------------------------------------------------------------
local function MakeByPockets( Proc, bOrthoFacesMaster, bMillDown)
local nFirstMachId
local bOrthoFaces
local sWarn
local sMchFind = 'Pocket'
local dDimMin, dDimMax, dDepth, vtOrtho, nLongFaceId, nSurfInt
local bBadMach = false
local bIs3Faces = Proc.Fct == 3
if bIs3Faces then
-- recupero la faccia con il maggior numero di adiacenze e l'elevazione relativa
local nFacInd, _, nFacInd2, _ = BL.GetFaceWithMostAdj( Proc.Id, _nPartId, bIs3Faces)
if not nFacInd or nFacInd < 0 then
if nFacInd == -1 then
bOrthoFaces = nFacInd2
else
local sErr = 'Error : MakeByPockets could not find reference face'
EgtOutLog( sErr)
return -1, sErr
end
end
else
bOrthoFaces = bOrthoFacesMaster
end
-- se è un tunnel verifico se è possibile usare la svuotatura
if bOrthoFaces then
-- ottengo le dimensioni del tunnel
dDimMin, dDimMax, dDepth, vtOrtho, nLongFaceId, nSurfInt = GetTunnelDimension( Proc)
local nPathInt
-- se devo inserire il chamfer
if _nChamfer > 0 then
local nOk, sErr = MakeChamfer( Proc, vtOrtho, nSurfInt)
if nOk < 0 then return -1, sErr end
end
-- se smusso non è esclusivo
if _nChamfer < 2 then
-- ricalcolo se è lavorabile da sotto
bMillDown = ( BD.DOWN_HEAD == true)
-- verifico se può essere fatto con svuotatura
local bMakePocket, sPocketing, dMaxDepth, dDiamTool = VerifyPocket( dDimMin, dDepth / 2, nil, sMchFind)
local bMakePocketDn, sPocketingDn, dMaxDepthDn
if bMillDown then
bMakePocketDn, sPocketingDn, dMaxDepthDn = VerifyPocket( dDimMin, dDepth / 2, nil, sMchFind .. '_H2', false, true)
-- se è negativo inverto il versore e la faccia
if vtOrtho:getZ() < 0 then
vtOrtho = -vtOrtho
EgtInvertSurf( nSurfInt)
end
end
if bMakePocket then
-- gestione svuotatura da un solo lato o anche dal lato opposto (se non verticale)
-- estraggo il contorno dalla superfice per evitare i problemi con la svuotatura
-- e assegno l'estrusione
nPathInt = EgtExtractSurfTmLoops( nSurfInt, _nAddGrpId)
EgtModifyCurveExtrusion( nPathInt, vtOrtho, GDB_RT.GLOB)
-- se ho 3 facce, ciclo sulle entità del percorso per segnare quelle che sono aperte
if bIs3Faces then
SetOpenSide( nPathInt, vtOrtho)
end
-- variabili per parametri lavorazione
local dMachDepth
local dElev = 0
local bDoubleSide
local bOneShot
local bComplete = true
-- imposto altezza aggiuntiva di elevazione
local dCollSic = CalcCollisionSafety( vtOrtho)
-- se possibile svuotare completamente da una sola parte
if dMaxDepth > ( dDepth + BD.CUT_EXTRA + dCollSic) then
dMachDepth = ( dDepth / 2) + BD.CUT_EXTRA
dElev = dDepth + BD.CUT_EXTRA
bOneShot = true
else
-- se direzione verso la verticale setto max affondamento possibile ed
-- emetto messaggio di warning perché non lavorabile interamente
if abs( vtOrtho:getZ()) >= 0.707 and not BD.DOWN_HEAD then
dMachDepth = dMaxDepth - ( dDepth / 2) - dCollSic
dElev = dMaxDepth
sWarn = 'Warning : elevation bigger than max tool depth'
EgtOutLog( sWarn)
bComplete = false
-- altrimenti setto il flag per fare la svuotatura da due parti
else
-- se l'altezza utensile riesce a lavorare completamente da due parti
if dMaxDepth > ( dDepth / 2) + dCollSic + BD.CUT_EXTRA_MIN then
dMachDepth = BD.CUT_EXTRA_MIN
dElev = ( dDepth / 2) + BD.CUT_EXTRA_MIN
-- altrimenti non si riesce in due passate, limito la profondità e setto l'elevazione
else
dMachDepth = dMaxDepth - ( dDepth / 2) - dCollSic
dElev = dMaxDepth
-- se molto inclinato rispetto alla normale della faccia di riferimento, lavorazione non idonea per probabili collisioni
local vtRef = Y_AX()
if abs( vtOrtho:getX()) > abs( vtOrtho:getY()) and abs( vtOrtho:getX()) > abs( vtOrtho:getZ()) then
vtRef = X_AX()
elseif abs( vtOrtho:getZ()) > abs( vtOrtho:getX()) and abs( vtOrtho:getZ()) > abs( vtOrtho:getY()) then
vtRef = Z_AX()
end
if abs( vtOrtho * vtRef) < 0.5 then
bBadMach = true
end
end
bDoubleSide = true
end
end
-- se lavorazione non idonea esco
if bIs3Faces and bBadMach then
local sErr = 'Impossible apply perpendicular pocketing: ' .. sPocketing
return -2, sErr
end
-- inserisco la lavorazione di svuotatura
local sName = 'Pock_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id))
local bToolInvert = false
-- verifico se devo invertire direzione utensile (in caso di direzione verso la verticale)
if vtOrtho:getZ() < BD.NZ_MINA and abs( vtOrtho:getZ()) >= 0.707 and not BD.DOWN_HEAD then
bToolInvert = true
-- altrimenti se da fare in una sola volta e direzionato verso Y+ lo inverto per lavorarlo davanti
elseif not bDoubleSide and vtOrtho:getY() > GEO.EPS_SMALL and not ( -(vtOrtho:getZ()) < BD.NZ_MINA) then
bToolInvert = true
end
-- eseguo svuotatura
local bOk, sErr, nMchFId = DoPocketing( sName, sPocketing, sMchFind, vtOrtho, nPathInt, -1, 0, dMachDepth, dElev, bToolInvert, true, false, true)
if not bOk then
return -1, sErr
end
-- prendo l'id della prima lavorazione inserita
if not nFirstMachId then
nFirstMachId = nMchFId
end
-- se posso applicare la svuotatura sul lato opposto
if bDoubleSide then
-- se ho la lavorazione da sotto ricalcolo in base a questa lavorazione
if bMakePocketDn then
-- sPocketing = sPocketingDn
-- dMaxDepth = dMaxDepthDn
-- dDiamTool = dDiamToolDn
-- se l'altezza utensile riesce a lavorare completamente da due parti
if dMaxDepthDn > ( dDepth / 2) + dCollSic + BD.CUT_EXTRA_MIN then
dMachDepth = BD.CUT_EXTRA_MIN
dElev = ( dDepth / 2) + BD.CUT_EXTRA_MIN
-- altrimenti non si riesce in due passate, limito la profondità e setto l'elevazione
else
dMachDepth = dMaxDepthDn - ( dDepth / 2) - dCollSic
dElev = dMaxDepthDn
bComplete = false
sWarn = 'Warning : elevation bigger than max tool depth'
EgtOutLog( sWarn)
end
else
-- se anche lavorando dal lato opposto non riesco a svuotare completamente la fessura
-- setto i parametri affondamento ed emetto warning
if dMaxDepth < ( dDepth / 2) + BD.CUT_EXTRA + dCollSic then
dMachDepth = dMaxDepth - ( dDepth / 2) - dCollSic
dElev = dMaxDepth
bComplete = false
sWarn = 'Warning : elevation bigger than max tool depth'
EgtOutLog( sWarn)
end
end
-- inserisco la lavorazione di svuotatura
local sName = 'PockOppo_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id))
-- eseguo svuotatura in direzione invertita
local bOk, sErr, nMchFId = DoPocketing( sName, sPocketing, sMchFind, vtOrtho, nPathInt, -1, 0, dMachDepth, dElev, true, true, false, false)
if not bOk then
return -1, sErr
end
-- prendo l'id della prima lavorazione inserita
if not nFirstMachId then
nFirstMachId = nMchFId
end
end
-- se non completo e U, cerco di lavorare anche la faccia di fondo (con il massimo affondamento possibile)
if not bComplete and bIs3Faces then
-- recupero la faccia da lavorare
local nFacInd, dFacElev = BL.GetFaceWithMostAdj( Proc.Id, _nPartId)
local vtN
local bPock3rd = false
if nFacInd then
vtN = EgtSurfTmFacetNormVersor( Proc.Id, nFacInd, GDB_ID.ROOT)
bPock3rd = ( vtN and ( vtN:getZ() >= BD.NZ_MINA or bMakePocketDn))
end
if bPock3rd then
-- recupero la distanza di sicurezza aggiuntiva
local dFacCollSic = CalcCollisionSafety( vtN)
-- scelgo se lavorare da sotto
local bFacPocketDn = ( bMakePocketDn and vtN:getZ() < -0.174)
-- calcolo affondamento
local dDepth = 0
local dActMaxDepth = EgtIf( bFacPocketDn, dMaxDepthDn, dMaxDepth)
if dActMaxDepth < dFacElev + dFacCollSic then
dDepth = dActMaxDepth - dFacElev + dFacCollSic
end
-- inserisco la lavorazione di svuotatura
local sName = EgtIf( bDoubleSide, 'Pock3rd_', 'Pock2nd_') .. ( EgtGetName( Proc.Id) or tostring( Proc.Id))
-- eseguo svuotatura
local bOk, sErr, nMchFId = DoPocketing( sName, sPocketing, sMchFind, vtN, Proc.Id, nFacInd, 0, dDepth, 0, false, true, false, true)
if not bOk then
return -1, sErr
end
-- prendo l'id della prima lavorazione inserita
if not nFirstMachId then
nFirstMachId = nMchFId
end
end
end
return 1, sWarn, dDimMin, dDimMax, dDepth, vtOrtho, nLongFaceId, dDiamTool, bDoubleSide, nPathInt, nSurfInt, bOneShot, bMillDown, nFirstMachId
end
end
end
return 0, sWarn, dDimMin, dDimMax, dDepth, vtOrtho, nLongFaceId, dDiamTool, bDoubleSide, nPathInt, nSurfInt, bOneShot, bMillDown, nFirstMachId, bOrthoFaces
end
---------------------------------------------------------------------
local function ManageAntiSplintBySaw( Proc, bIsU, vtN, nFacInd, sWarn, bMillDown, bReduceDepth)
local bMadeASbyBld = false
local nNumFac = EgtIf( bIsU, 2, 1)
local nPrefSide = 1 -- di preferenza il motore è meglio tenerlo sinistra
-- se a U cerco di ottimizzare il lato di lavoro della lama
if bIsU then
if abs( vtN:getY()) > 0.996 then
nPrefSide = 0
elseif abs( vtN:getZ()) > 0.63 or abs( vtN:getY()) > 0.63 then
-- se X è negativa allora devo tenere il motore a destra
if vtN:getX() < -(10 * GEO.EPS_SMALL) then
nPrefSide = 2
end
end
end
-- va eseguito sulle facce diverse dalla principale
local nPrevSCC = nil
for nFacet = 0, nNumFac do
if nFacet ~= nFacInd then
-- lavoro
local dSawThick = 0
local dAng, sWarn2, nIdMach
bMadeASbyBld, sWarn2, nIdMach, dSawThick, dMaxDepth, dAng = MakeAntiSplintBySaw( Proc, nFacet, vtN, nFacInd, bReduceDepth, bMillDown)
if not bMadeASbyBld then return bMadeASbyBld, false, sWarn2 end
sWarn = FormatWarning( sWarn, sWarn2)
-- se antischeggia veramente inserito perchè necessario
if nIdMach then
-- verifico se da invertire
local bInvertMach = false
if bIsU then
if abs( vtN:getZ()) > 0.63 or abs( vtN:getY()) > 0.63 then
-- if abs( vtN:getZ()) > 0.7 or abs( vtN:getY()) > 0.7 then
-- prendo il vettore normale alla faccia
local ptC, vtNFc = EgtSurfTmFacetCenter( Proc.Id, nFacet, GDB_ID.ROOT)
-- se superficie principale parallela al piano XZ
if nPrefSide == 0 then
-- se facce inclinate \\ allora mandrino a destra (per essere verso l'alto)
if vtNFc:getX() * vtNFc:getZ() > 0 then
nPrefSide = 2
-- altrimenti facce inclinate // quindi mandrino a sinistra (per essere ancora verso l'alto)
else
nPrefSide = 1
end
end
-- se faccia verso X+ e mandrino verso sinistra
if vtNFc:getX() > 0 and nPrefSide == 1 then
-- se angolo interno e circa -90
if abs( dAng + 90) < 5 then
bInvertMach = true
end
-- se faccia verso X- e mandrino verso destra
elseif vtNFc:getX() < 0 and nPrefSide == 2 then
-- se angolo interno e circa -90
if abs( dAng + 90) < 5 then
bInvertMach = true
end
end
end
end
-- eseguo inversione
if bInvertMach then
local bToolInvert = EgtGetMachiningParam( MCH_MP.TOOLINVERT)
local nWS = EgtGetMachiningParam( MCH_MP.WORKSIDE)
local nInvWS = EgtIf( nWS == MCH_MILL_WS.RIGHT, MCH_MILL_WS.LEFT, MCH_MILL_WS.RIGHT)
local nFaceUse = EgtGetMachiningParam( MCH_MP.FACEUSE)
local bOrtUp = ( nFaceUse >= MCH_MILL_FU.ORTUP_DOWN and nFaceUse <= MCH_MILL_FU.ORTUP_RIGHT)
if not bOrtUp then
-- assegno i parametri invertiti
EgtSetMachiningParam( MCH_MP.WORKSIDE, nInvWS)
EgtSetMachiningParam( MCH_MP.TOOLINVERT, not bToolInvert)
-- setto l'offset pari allo spessore lama
EgtSetMachiningParam( MCH_MP.OFFSL, -dSawThick)
end
end
-- posizione del braccio : se primo taglio la recupero, altrimenti la imposto
if not nPrevSCC then
nPrevSCC = EgtGetMachiningParam( MCH_MP.SCC)
else
EgtSetMachiningParam( MCH_MP.SCC, nPrevSCC)
end
-- rieseguo
if not ML.ApplyMachining( true, false) then
local _, sErr = EgtGetLastMachMgrError()
EgtSetOperationMode( nIdMach, false)
return false, false, sErr
end
end
end
end
return bMadeASbyBld, true, sWarn
end
---------------------------------------------------------------------
local function MakePathsOnExtremePoints( nIdPath, pPaths, dTDiam)
local dLength = 2
if not nIdPath then return pPaths end
-- prendo i punti iniziali e finali del percorso e i versori direzione
local ptIni = EgtSP( nIdPath, GDB_RT.GLOB)
local ptEnd = EgtEP( nIdPath, GDB_RT.GLOB)
-- se distanza tra i punti è <= del diametro utensile esco
if dist( ptIni, ptEnd) <= dTDiam then return pPaths end
-- prendo i versori iniziali e finali
local vtIni = EgtSV( nIdPath, GDB_RT.GLOB)
local vtEnd = EgtEV( nIdPath, GDB_RT.GLOB)
local ptIniP = ptIni
local ptEndP = ptIniP + (vtIni * dLength)
local nAuxId = EgtLine( _nAddGrpId, ptIniP, ptEndP, GDB_RT.GLOB)
table.insert( pPaths, { nAuxId, 1, ptIniP})
ptIniP = ptEnd
ptEndP = ptEnd - ( vtEnd * dLength)
nAuxId = EgtLine( _nAddGrpId, ptIniP, ptEndP, GDB_RT.GLOB)
table.insert( pPaths, { nAuxId, 2, ptIniP})
return pPaths
end
---------------------------------------------------------------------
local function MakeAntiSplintByMill( Proc, pPaths, nPathInt, vtN1,
bDoubleSide, bOppoSide, sMilling, sMyWarn,
dMaxElevMaster, dExtraDepth, dCollSic, dMaxDepth, nFirstMachId)
local sMyWarn2
-- assegno lavorazioni ad ogni percorso
for i = 1, #pPaths do
local nIdPath = pPaths[i][1]
local nSide = pPaths[i][2]
-- modifico versore direzione
EgtModifyCurveExtrusion( nIdPath, vtN1, GDB_RT.GLOB)
local sName
if bOppoSide then
sName = 'AntiSplintOppo_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id))
else
sName = 'AntiSplint_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id))
end
local nMchId = EgtAddMachining( sName, sMilling)
if nMchId then
-- aggiungo geometria
EgtSetMachiningGeometry( {{ nIdPath, -1}})
if ( bOppoSide and nSide == 1) or ( not bOppoSide and nSide == 2) then
-- imposto lato di lavoro destro
EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.RIGHT)
else
-- imposto lato di lavoro sinistro
EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.LEFT)
end
local nSCC
if bOppoSide then
-- imposto direzione utensile opposta
EgtSetMachiningParam( MCH_MP.TOOLINVERT, true)
-- imposto posizione braccio porta testa
nSCC = MCH_SCC.ADIR_YM
if not BD.C_SIMM then
if AreSameVectorApprox( vtN1, Z_AX()) then
nSCC = MCH_SCC.ADIR_YM
elseif abs( vtN1:getX()) < 0.1 then
nSCC = EgtIf( BL.IsPartFinalPhase( _nPhase), MCH_SCC.ADIR_XM, MCH_SCC.ADIR_XP)
elseif vtN1:getY() < GEO.EPS_SMALL then
nSCC = MCH_SCC.ADIR_YP
else
nSCC = MCH_SCC.ADIR_YM
end
end
else
local bInvertMach = false
if not nPathInt then
-- imposto posizione braccio porta testa
nSCC = MCH_SCC.ADIR_YM
if vtN1:getY() > 100 * GEO.EPS_ZERO then
nSCC = MCH_SCC.ADIR_YP
end
else
-- verifico se devo invertire direzione utensile (in caso di direzione verso la verticale)
if vtN1:getZ() < BD.NZ_MINA and abs(vtN1:getZ()) >= 0.707 then
EgtSetMachiningParam( MCH_MP.TOOLINVERT, true)
bInvertMach = true
-- altrimenti se da fare in una sola volta e direzionato verso Y+ lo inverto per lavorarlo davanti
elseif not bDoubleSide and vtN1:getY() > GEO.EPS_SMALL then
EgtSetMachiningParam( MCH_MP.TOOLINVERT, true)
bInvertMach = true
end
-- imposto posizione braccio porta testa
nSCC = MCH_SCC.NONE
if not BD.C_SIMM then
if AreSameOrOppositeVectorApprox( vtN1, Z_AX()) then
nSCC = MCH_SCC.ADIR_YM
elseif abs( vtN1:getX()) < 0.1 then
nSCC = EgtIf( BL.IsPartFinalPhase( _nPhase), MCH_SCC.ADIR_XM, MCH_SCC.ADIR_XP)
elseif vtN1:getY() < GEO.EPS_SMALL then
nSCC = EgtIf( bInvertMach, MCH_SCC.ADIR_YP, MCH_SCC.ADIR_YM)
else
nSCC = EgtIf( bInvertMach, MCH_SCC.ADIR_YM, MCH_SCC.ADIR_YP)
end
end
end
end
EgtSetMachiningParam( MCH_MP.SCC, nSCC)
-- parametri attacco
EgtSetMachiningParam( MCH_MP.LEADINTYPE, 1)
-- allungo inizio
EgtSetMachiningParam( MCH_MP.STARTADDLEN, 2)
EgtSetMachiningParam( MCH_MP.LITANG, 10)
EgtSetMachiningParam( MCH_MP.LIPERP, -5)
-- parametri uscita
EgtSetMachiningParam( MCH_MP.LEADOUTTYPE, 0)
EgtSetMachiningParam( MCH_MP.ENDADDLEN, 0)
local dMachDepth = 0
local dExtraElev = 0
if bDoubleSide then
dExtraElev = BL.GetFaceElevationFromPointDir( Proc.Id, _nPartId, pPaths[i][3], EgtIf( bOppoSide, -vtN1, vtN1)) - dMaxElevMaster
end
local dMaxElev = dMaxElevMaster + dExtraElev
if ( dMaxElev + BD.CUT_EXTRA + dCollSic) > dMaxDepth then
dMachDepth = dMaxDepth - ( dMaxElev + dCollSic)
end
-- setto se devo invertire il percorso
local bInvert = CheckToInvert( nIdPath, true)
if bOppoSide then
EgtSetMachiningParam( MCH_MP.DEPTH, dMachDepth)
EgtSetMachiningParam( MCH_MP.INVERT, bInvert)
else
EgtSetMachiningParam( MCH_MP.DEPTH, (dMachDepth + dExtraDepth))
EgtSetMachiningParam( MCH_MP.INVERT, EgtIf( bInvertMach, not bInvert, bInvert))
end
-- Note utente con dichiarazione nessuna generazione sfridi per Vmill e massima elevazione
local sUserNotes = 'VMRS=0;MaxElev=' .. EgtNumToString( ( dMaxElev + dMachDepth), 1) .. ';'
EgtSetMachiningParam( MCH_MP.USERNOTES, sUserNotes)
-- eseguo
if ML.ApplyMachining( true, false) then
_, sMyWarn2 = EgtGetMachMgrWarning( 0)
if EgtIsMachiningEmpty() then
EgtSetOperationMode( nMchId, false)
else
-- se ho la lavorazione di svuotatura riloco la lavorazione antischeggia prima di questa
if nFirstMachId then
EgtRelocateGlob( nMchId, nFirstMachId, GDB_IN.BEFORE)
end
end
-- altrimenti lavorazione non applicata
else
_, sMyWarn2 = EgtGetLastMachMgrError()
EgtSetOperationMode( nMchId, false)
end
-- altrimenti non è stata inserita lavorazione
else
sMyWarn2 = 'warning adding machining ' .. sName .. '-' .. sMilling
end
end
if sMyWarn2 and #sMyWarn2 > 0 then
sMyWarn = sMyWarn .. '\n' .. sMyWarn2
end
return sMyWarn
end
---------------------------------------------------------------------
local function ManageAntiSplintByMill( Proc, nFacInd, bMillDown, bDoubleSide,
vtOrtho, nPathInt, nSurfInt, dDepth,
bOneShot, nFirstMachId)
local sMyWarn = ''
local pPaths = {}
local nAuxId
local sMilling
-- recupero la lavorazione tenendo conto dell'elevazione
local dCheckDepth
if bDoubleSide then
dCheckDepth = 0.5 * dDepth
else
if not nPathInt then
dCheckDepth = BL.GetFaceElevation( Proc.Id, nFacInd)
else
dCheckDepth = dDepth
end
end
sMilling = ML.FindMilling( 'AntiSplintMillCut', dCheckDepth, nil, nil, nil, not ( bMillDown and not bDoubleSide), bMillDown and not bDoubleSide) or
ML.FindMilling( 'AntiSplintMillCut', 2/3 * dCheckDepth, nil, nil, nil, not ( bMillDown and not bDoubleSide), bMillDown and not bDoubleSide) or
ML.FindMilling( 'AntiSplintMillCut', nil, nil, nil, nil, not ( bMillDown and not bDoubleSide), bMillDown and not bDoubleSide)
if sMilling then
local vtN1
local nFirstId, nNumId
local dMaxElevMaster
local dExtraDepth = 0
local dCollSic
-- recupero i dati dell'utensile
local dTDiam = 50
local dMaxDepth = 0
local TI = GetToolInfoForMachining( sMilling)
if TI then
dTDiam = TI.dDiam or dTDiam
dMaxDepth = TI.dMaxDepth or dMaxDepth
end
-- se non ho la faccia aggiunta
if not nPathInt then
-- ottengo i percorsi da cui estrapolare il percorso di antischeggia
local tFacAdjMain = ChooseContour( Proc, nFacInd, false)
local tPaths = {}
-- se non trovato nessun angolo interno valido esco
if #tFacAdjMain == 0 then
return true, sMyWarn
end
-- prendo il primo versore
_, vtN1 = EgtSurfTmFacetCenter( Proc.Id, nFacInd, GDB_ID.ROOT)
dCollSic = CalcCollisionSafety( vtN1) or 0
-- se direzione tende verso una delle alle 3 direzioni azzero l'altezza extra
if abs( vtN1:getX()) > 0.7 or abs( vtN1:getY()) > 0.7 or abs( vtN1:getZ()) > 0.7 then dCollSic = 0 end
-- se fresatura da sotto salto la lavorazione
if vtN1:getZ() < BD.DRILL_VZ_MIN and not bMillDown then
local sErr = 'Error : milling from bottom'
EgtOutLog( sErr)
return false, sErr
end
local ptIniPath
local nMaxLen = 0
dMaxElevMaster = BL.GetFaceElevation( Proc.Id, nFacInd)
-- ciclo tutta la tabella
for i = 1, #tFacAdjMain do
-- le 2 facce di contatto devono essere perpendicolari o non sottosquadra rispetto alla faccia di fondo
local ptP1, ptP2, dAng
ptP1 = tFacAdjMain[i][3]
ptP2 = tFacAdjMain[i][4]
dAng = tFacAdjMain[i][5]
if ( dAng < 0 and 180 + dAng >= 90 - 10 * GEO.EPS_SMALL) then
-- creo la linea da P1 a P2
nAuxId = EgtLine( _nAddGrpId, ptP1, ptP2, GDB_RT.GLOB)
table.insert( tPaths, nAuxId)
-- prendo la lunghezza massima e il punto iniziale
if tFacAdjMain[i][2] > nMaxLen then
ptIniPath = ptP1
nMaxLen = tFacAdjMain[i][2]
end
end
end
-- costruisco il/i percorso/i
nFirstId, nNumId = EgtCurveCompoByReorder( _nAddGrpId, tPaths, ptIniPath, true, GDB_RT.GLOB)
local bOkPath = true
for i = 1, nNumId do
local nIdPath = nFirstId + i - 1
if EgtCurveIsClosed( nIdPath) then
bOkPath = false
end
end
-- se ho un percorso chiuso cancello tutto
if not bOkPath then
for i = 1, nNumId do
local nIdPath = nFirstId + i - 1
EgtErase(nIdPath)
end
else
-- creo percorsi antisplint dagli estremi dei percorsi di contorno trovati
for i = 1, nNumId do
local nIdPath = nFirstId + i - 1
pPaths = MakePathsOnExtremePoints( nIdPath, pPaths, dTDiam)
end
end
-- alrimenti ho la faccia aggiunta
else
dCollSic = CalcCollisionSafety( vtOrtho)
nFirstId = EgtCopyGlob( nPathInt, _nAddGrpId)
nNumId = 1
-- calcolo elevazione dalla faccia trasversale aggiunta
if bDoubleSide then
dMaxElevMaster = 0.5 * dDepth
else
dMaxElevMaster = dDepth
-- se la precedente svuotatura è stata fatta completamente in una sola volta
-- valuto di nuovo se devo fare due passate o una sola
if bOneShot then
-- se non è possibile svuotare completamente da una sola parte
if dMaxDepth <= ( dMaxElevMaster + BD.CUT_EXTRA + dCollSic) then
bDoubleSide = true
dMaxElevMaster = BL.GetOtherFaceElevation( Proc.Id, nSurfInt, 0)
else
dExtraDepth = dMaxElevMaster - BL.GetOtherFaceElevation( Proc.Id, nSurfInt, 0)
end
-- altrimenti non è stata fatta completamente calcolo la distanza tra faccia aggiunta e profondità superficie
else
dExtraDepth = dMaxElevMaster - BL.GetOtherFaceElevation( Proc.Id, nSurfInt, 0)
end
end
vtN1 = Vector3d(vtOrtho)
local bOkPath = SetOpenSide( nFirstId, vtOrtho, 2)
-- se non ho un percorso chiuso estraggo i percorsi
if bOkPath then
-- creo percorsi antisplint dagli estremi dei percorsi di contorno trovati
pPaths = MakePathsOnExtremePoints( nFirstId, pPaths, dTDiam)
end
EgtErase(nFirstId)
end
if #pPaths > 0 then
sMyWarn = MakeAntiSplintByMill( Proc, pPaths, nPathInt, vtN1,
bDoubleSide, false, sMilling, sMyWarn,
dMaxElevMaster, dExtraDepth, dCollSic, dMaxDepth, nFirstMachId)
if bDoubleSide then
if bMillDown then
local sMillingDn = ML.FindMilling( 'AntiSplintMillCut_H2', dCheckDepth) or
ML.FindMilling( 'AntiSplintMillCut_H2', 2/3 * dCheckDepth) or
ML.FindMilling( 'AntiSplintMillCut_H2')
sMilling = sMillingDn
-- controllo dati lavorazione
local TI = GetToolInfoForMachining( sMilling)
if TI then
dTDiam = TI.dDiam or dTDiam
dMaxDepth = TI.dMaxDepth or dMaxDepth
end
end
-- se lavorazione valida
if sMilling then
sMyWarn = MakeAntiSplintByMill( Proc, pPaths, nPathInt, vtN1,
bDoubleSide, true, sMilling, sMyWarn,
dMaxElevMaster, dExtraDepth, dCollSic, dMaxDepth, nFirstMachId)
else
sMyWarn = 'warning in process ' .. tostring( Proc.Id) .. ' clean corner milling/tool not found in library'
end
end
-- altrimenti non c'è il percorso
else
sMyWarn = 'warning in process ' .. tostring( Proc.Id) .. ' impossible make clean corner path'
end
-- altrimenti non è stata trovata lavorazione
else
sMyWarn = 'warning in process ' .. tostring( Proc.Id) .. ' clean corner milling/tool not found in library'
end
if #sMyWarn > 0 then
EgtOutLog( sMyWarn)
end
return true, sMyWarn
end
---------------------------------------------------------------------
local function DoSideMill( Proc, sName, sMilling, tFData, dMaxMat, dToolDiam, bHeadDir, bHalf, dV)
local nMchFId = EgtAddMachining( sName, sMilling)
if not nMchFId then
local sErr = 'Error adding machining ' .. sName .. '-' .. sMilling
EgtOutLog( sErr)
return false, sErr
end
sName = EgtGetName( nMchFId)
-- aggiungo geometria
EgtSetMachiningGeometry( {{ Proc.Id, tFData.nFacInd}})
-- imposto uso del lato faccia
EgtSetMachiningParam( MCH_MP.FACEUSE, EgtIf( bHeadDir, MCH_MILL_FU.PARAL_LEFT, MCH_MILL_FU.PARAL_RIGHT))
-- calcolo step effettivo ed elevazione
local dVcalc = dV - dMaxMat
local dStep = EgtMdbGetCurrMachiningParam( MCH_MP.STEP) or dMaxMat
local nStep = ceil( dVcalc / dStep)
if tFData.vtN:getZ() < - 0.5 and ( nStep % 2) == 0 then
nStep = nStep + 1
end
dStep = dVcalc / nStep + 0.1
EgtSetMachiningParam( MCH_MP.STEP, dStep)
-- imposto elevazione e dichiaro non si generano sfridi per VMill
local sNotes = 'MaxElev=' .. EgtNumToString( dVcalc + dStep, 2) .. ';'
sNotes = sNotes .. 'VMRS=0;'
EgtSetMachiningParam( MCH_MP.USERNOTES, sNotes)
-- attacchi e uscite
if tFData.vtN:getZ() > -0.5 then
EgtSetMachiningParam( MCH_MP.LITANG, 0)
EgtSetMachiningParam( MCH_MP.LIPERP, tFData.dFacElev + BD.CUT_SIC)
else
EgtSetMachiningParam( MCH_MP.LITANG, dToolDiam / 2 + BD.CUT_SIC)
EgtSetMachiningParam( MCH_MP.LIPERP, 0)
EgtSetMachiningParam( MCH_MP.LEADOUTTYPE, MCH_MILL_LO.LINEAR)
EgtSetMachiningParam( MCH_MP.LOTANG, 0)
EgtSetMachiningParam( MCH_MP.LOPERP, tFData.dFacElev + BD.COLL_SIC)
if bHalf then
EgtSetMachiningParam( MCH_MP.ENDADDLEN, - dH / 2)
end
end
-- tipo passate multiple
local nStepType = EgtIf( ( Proc.HeadDir and tFData.vtN:getY() < -0.5) or ( not Proc.HeadDir and tFData.vtN:getY() > 0.5), MCH_MILL_ST.ONEWAY, MCH_MILL_ST.ZIGZAG)
EgtSetMachiningParam( MCH_MP.STEPTYPE, nStepType)
-- imposto posizione braccio porta testa
local nSCC = EgtIf( ( tFData.vtN:getY() > 0.5 or ( bHeadDir and tFData.vtN:getZ() > 0.5 ) or ( not bHeadDir and tFData.vtN:getZ() < -0.5)), MCH_SCC.ADIR_YP, MCH_SCC.ADIR_YM)
EgtSetMachiningParam( MCH_MP.SCC, nSCC)
-- eseguo
if not ML.ApplyMachining( true, false) then
local _, sErr = EgtGetLastMachMgrError()
EgtSetOperationMode( nMchFId, false)
return false, sErr
end
-- se divisa in due metà
if bHalf then
local nMchFNId = EgtCopyMachining( sName .. '_2', sName)
if not nMchFNId then
local sErr = 'Error copying machining ' .. sName
EgtOutLog( sErr)
return false, sErr
end
-- inverto direzione e lato di lavoro e direzione ausiliaria
local bInvert = EgtGetMachiningParam( MCH_MP.INVERT)
EgtSetMachiningParam( MCH_MP.INVERT, not bInvert)
local nWorkSide = EgtGetMachiningParam( MCH_MP.WORKSIDE)
EgtSetMachiningParam( MCH_MP.WORKSIDE, EgtIf( nWorkSide == MCH_MILL_WS.LEFT, MCH_MILL_WS.RIGHT, MCH_MILL_WS.LEFT))
EgtSetMachiningParam( MCH_MP.SCC, EgtIf( nSCC == MCH_SCC.ADIR_YP, MCH_SCC.ADIR_YM, MCH_SCC.ADIR_YP))
-- eseguo
if not ML.ApplyMachining( true, false) then
local _, sErr = EgtGetLastMachMgrError()
EgtSetOperationMode( nMchFNId, false)
return false, sErr
end
end
return true, ''
end
---------------------------------------------------------------------
local function MakeSideMill( Proc, sMilling, tFData, dMaxMat, dToolDiam, bHeadDir)
local dH, dV
-- recupero la larghezza della faccia perpendicolarmente alle altre 2
local vtN2 = EgtSurfTmFacetNormVersor( Proc.Id, EgtIf( tFData.nFacInd == 0, 1, 0), GDB_ID.ROOT)
local vtX = vtN2 ^ tFData.vtN
local frRef = Frame3d( tFData.ptC, tFData.ptC + 100 * vtX, tFData.ptC + 100 * vtN2)
local b3Ref = EgtSurfTmGetFacetBBoxRef( Proc.Id, tFData.nFacInd, GDB_BB.STANDARD, frRef)
if b3Ref then
dV = b3Ref:getDimY()
dH = b3Ref:getDimX()
end
-- se lavorazione da sotto e lunga, va divisa in due metà
local bHalf = ( tFData.vtN:getZ() < -0.5 and dH > ( BD.MAX_LEN_BH_FROM_BOTTOM or 200))
-- inserisco la lavorazione di fresatura
local sName = 'BHMill_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id))
local nMchFId = EgtAddMachining( sName, sMilling)
local bOk, sErr = DoSideMill( Proc, sName, sMilling, tFData, dMaxMat, dToolDiam, bHeadDir, bHalf, dV)
return bOk, sErr
end
---------------------------------------------------------------------
local function MakeSpecialThreeFaces( Proc, tFData)
-- se orientata verso il basso, verifico l'alternativa
if tFData.vtN:getZ() < BD.NZ_MINA and tFData.vtN2:getZ() < BD.NZ_MINA then
local sErr = 'Error : special LapJoint from bottom impossible'
EgtOutLog( sErr)
return false, sErr
end
-- eventuali tagli preliminari
do
local bOk, sErr = MakePreCuts( Proc)
if not bOk then return false, sErr end
end
-- Recupero la lavorazione di fresa
local sMilling = ML.FindMilling( 'LongSmallCut')
if not sMilling then
local sErr = 'Error : LongSmallCut not found in library'
EgtOutLog( sErr)
return false, sErr
end
-- Recupero la lavorazione di svuotatura
local sMchFind = 'Pocket'
-- se forzato uso truciolatore
if Q_USE_ROUGH_TOOL == 1 then
sMchFind = 'OpenPocket'
end
local dDiam = min( tFData.dH, tFData.dV)
local dDiam2 = min( tFData.dH2, tFData.dV2)
local dCollSic = 2 * BD.COLL_SIC
local dCollSic2 = 2 * BD.COLL_SIC
if abs( tFData.vtN:getX()) > 0.7 or abs( tFData.vtN:getY()) > 0.7 or abs( tFData.vtN:getZ()) > 0.7 then dCollSic = 0 end
if abs( tFData.vtN2:getX()) > 0.7 or abs( tFData.vtN2:getY()) > 0.7 or abs( tFData.vtN2:getZ()) > 0.7 then dCollSic2 = 0 end
local sPocketing = ML.FindPocketing( sMchFind, dDiam2, tFData.dFacElev2 + dCollSic2)
local nPockFace = tFData.nFacInd2
-- se non trova una svuotatura adatta provo ad assegnarla all'altra faccia
if not sPocketing then
dDiam, dDiam2 = dDiam2, dDiam
dCollSic, dCollSic2 = dCollSic2, dCollSic
tFData = SwapFacetsData( tFData)
-- prendo a riferimento la seconda faccia per la svuotatura
sPocketing = ML.FindPocketing( sMchFind, dDiam2, tFData.dFacElev2 + dCollSic2)
if not sPocketing then
local sErr = 'Error : ' .. sMchFind .. ' not found in library'
EgtOutLog( sErr)
return false, sErr
end
end
-- provo con contornatura
local dDiamTool = 20
-- verifico se forma ad L
local bIsU, bIsL = TestUL( Proc)
if bIsL then
local bOk, sWarn
bOk, sWarn, _ = MakeByMill( Proc, tFData, dCollSic, true, sMilling)
if not bOk then return bOk, sWarn end
else
local sErr = 'Error : Impossible mill special LapJoint'
EgtOutLog( sErr)
return false, sErr
end
-- inserisco la lavorazione di svuotatura
local sName = 'Pock_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id))
local nMchFId = EgtAddMachining( sName, sPocketing)
if not nMchFId then
local sErr = 'Error adding machining ' .. sName .. '-' .. sPocketing
EgtOutLog( sErr)
return false, sErr
end
-- aggiungo geometria
EgtSetMachiningGeometry( {{ Proc.Id, nPockFace}})
-- imposto uso faccia
EgtSetMachiningParam( MCH_MP.FACEUSE, MCH_MILL_FU.ORTHO_CONT)
-- imposto posizione braccio porta testa
if tFData.vtN:getY() < GEO.EPS_SMALL then
EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.ADIR_YM)
else
EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.ADIR_YP)
end
-- se tasca aperta, imposto opportuno attacco
if sMchFind == 'OpenPocket' then
EgtSetMachiningParam( MCH_MP.SUBTYPE, MCH_POCK_SUB.SPIRALIN)
end
-- imposto elevazione
local sNotes = 'MaxElev=' .. EgtNumToString( tFData.dFacElev2, 1) .. ';'
EgtSetMachiningParam( MCH_MP.USERNOTES, sNotes)
-- eseguo
if not ML.ApplyMachining( true, false) then
-- provo ad allargare leggermente la tasca
EgtSetMachiningParam( MCH_MP.OFFSR, -0.1)
if not ML.ApplyMachining( true, false) then
local _, sErr = EgtGetLastMachMgrError()
EgtSetOperationMode( nMchFId, false)
return false, sErr
end
end
-- se abilitato dal parametro Q inserisco foro sullo spigolo
if Q_BORE_ON_CORNER == 1 then
local bOk, sWarn = MakeDrillOnCorner( Proc, 0, dDiamTool, true)
if not bOk then return false, sWarn end
-- altrimenti se abilitato dal parametro Q inserisco percorso di pulitura
elseif Q_BORE_ON_CORNER == 2 then
local bOk, sWarn = MakeSharpCleanCorner( Proc, 0, dDiamTool)
if not bOk then return false, sWarn end
end
return true, ''
end
---------------------------------------------------------------------
local function MakeByChainsaw( Proc, dDimMin, dDimMax, dDepth, vtOrtho, nLongFaceId)
-- verifico se posso farlo con la sega-catena
local bMakeChainSaw, sSawing, dMaxMat, dSawCornerRad, dSawThick = VerifyChainSaw( dDimMin, dDimMax)
if bMakeChainSaw then
-- Verifico se necessarie più passate
local nStep = ceil( ( dDimMin - 10 * GEO.EPS_SMALL) / dSawThick)
local dStep = 0
if nStep > 1 then
dStep = ( dDimMin - dSawThick) / ( nStep - 1)
end
for i = 1, nStep do
-- inserisco la lavorazione di sawing
local sName = 'Csaw_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) .. '_' .. tostring( i)
local nMchFId = EgtAddMachining( sName, sSawing)
if not nMchFId then
local sErr = 'Error adding machining ' .. sName .. '-' .. sSawing
EgtOutLog( sErr)
return false, sErr
end
-- aggiungo geometria
EgtSetMachiningGeometry( {{ Proc.Id, nLongFaceId}})
-- imposto uso del lato faccia
-- al momento, dato che la fessura è passante da parte a parte, gestisco solo la lavorazione
-- dall'alto e di fronte (da dietro è disabilitata perchè ho exracorsa con la FAST).
-- Questa feature non è applicata su facce di testa e quindi non controllo l'entrata in X
if abs(vtOrtho:getZ()) >= 0.707 then
EgtSetMachiningParam( MCH_MP.FACEUSE, MCH_MILL_FU.PARAL_DOWN)
else
EgtSetMachiningParam( MCH_MP.FACEUSE, MCH_MILL_FU.PARAL_BACK)
end
local vtN = EgtSurfTmFacetNormVersor( Proc.Id, nLongFaceId, GDB_ID.ROOT)
-- imposto angolo 3° asse rot
EgtSetMachiningParam( MCH_MP.BLOCKEDAXIS, GetChainSawBlockedAxis( 1))
EgtSetMachiningParam( MCH_MP.INITANGS, GetChainSawInitAngs( vtN, vtOrtho))
-- imposto offset radiale
local dOffs = ( i - 1) * dStep
EgtSetMachiningParam( MCH_MP.OFFSR, dOffs)
-- se possibile aumento l'affondamento pari al raggio corner + 1
if dMaxMat > (dDepth + dSawCornerRad + 1) then
EgtSetMachiningParam( MCH_MP.DEPTH, (dDepth + dSawCornerRad + 1))
-- se massimo affondamento utensile inferiore fessura, setto affondamento ed emetto warning
elseif dMaxMat < dDepth then
EgtSetMachiningParam( MCH_MP.DEPTH, dMaxMat)
local sWarn = 'Warning : elevation bigger than max tool depth'
EgtOutLog( sWarn)
end
-- eseguo
if not ML.ApplyMachining( true, false) then
if EgtGetOutstrokeInfo() then
local _, sErr = EgtGetLastMachMgrError()
EgtSetOperationMode( nMchFId, false)
return false, sErr
end
EgtSetMachiningParam( MCH_MP.BLOCKEDAXIS, GetChainSawBlockedAxis( 2))
EgtSetMachiningParam( MCH_MP.INITANGS, GetChainSawInitAngs( vtN, vtOrtho))
if not ML.ApplyMachining( true, false) then
local _, sErr = EgtGetLastMachMgrError()
EgtSetOperationMode( nMchFId, false)
return false, sErr
end
end
if EgtIsMachiningEmpty() then
local _, sWarn = EgtGetMachMgrWarning( 0)
EgtSetOperationMode( nMchFId, false)
return false, sWarn
end
end
end
return true
end
---------------------------------------------------------------------
local function MakeSidePocketings( Proc, tFData, dCollSic, bSpecialMillOnSide,
nBottomFace, sMillingOnSide, dToolDiamOnSide, dThickMillOnSide,
bSinglePart, bIsU, bIsL, dDiam, bMillDown, bMillUp, sMchFind, sMchFindBackUp)
local bTryWithBlades = true
local nOk, bOk, sWarn, sStat, sErr, dDimMin, dDimMax, dDepth, vtOrtho, bOrthoFaces, nSurfInt, sPocketing, nLongFaceId
if bSpecialMillOnSide then
-- eseguo
bOk, sWarn = MakeByMillAsSaw( Proc, tFData, nBottomFace, sMillingOnSide, dToolDiamOnSide, dThickMillOnSide)
if bOk then
return 1, true, sWarn
end
end
-- se feature 16 o 17 e se forzata lama provo prima con questa e poi con la fresa
if ( Proc.Prc == 16 or Proc.Prc == 17) and _bForceUseBlade then
-- Se la svuotatura precedente non è stata fatta e smusso non è esclusivo, provo con le lame
if bTryWithBlades and _nChamfer < 2 then
-- anche su macchine con testa da sotto, la sega a catena è solo da sopra
if tFData.vtN:getZ() < BD.NZ_MINA and BD.DOWN_HEAD and tFData.nFacInd2 then
tFData = SwapFacetsData( tFData)
end
-- eseguo
bOk, sWarn, sStat = MakeByChainOrSaw( Proc, tFData, dDimMin, dDimMax, vtOrtho, nil, bOrthoFaces, nBottomFace, nSurfInt)
if not bOk then
-- in base al flag interno e al numero di facce e se ha forma ad U: provo prima la svuotatura sul fianco e
-- se non è possibile allora provo in seguito con lama o segacatena
-- o passare subito dalla lavorazione con lama/sega catena
if Proc.Fct == 3 and bIsU then
-- lavoro con svuotature (singola o doppia contrapposta)
nOk, sErr, dDimMin, dDimMax, dDepth, vtOrtho, _, _, _, _, _, _, _, _, bOrthoFaces = MakeByPockets( Proc, nil, bMillDown)
-- se lavorazione non idonea (asse della feature troppo inclinato e impossibile lavorare completamente da due parti)
if nOk == -2 then
if not sMchFind then
sMchFind = sMchFindBackUp
end
sPocketing = ML.FindPocketing( sMchFind, dDiam)
if not sPocketing then
local sErr = 'Error : ' .. sMchFind .. ' not found in library'
EgtOutLog( sErr)
return 1, false, sErr
end
elseif nOk < 0 then
return 1, false, sErr
elseif nOk == 0 then
if sStat == 'MNF' then
sPocketing = ML.FindPocketing( sMchFind, dDiam)
if not sPocketing then
local sErr = 'Error : ' .. sMchFind .. ' not found in library'
EgtOutLog( sErr)
return 1, false, sErr
end
else
return 1, bOk, sWarn
end
else
bOk = true
return 1, bOk, sErr
end
else
sPocketing = ML.FindPocketing( sMchFind, dDiam)
if not sPocketing then
local sErr = 'Error : ' .. sMchFind .. ' not found in library'
EgtOutLog( sErr)
return 1, false, sErr
end
end
else
return 1, bOk, sWarn
end
else
-- se devo inserire il chamfer
if ( ( Proc.Fct == 3 and bIsU) or ( Proc.Fct == 2 and bIsL)) and _nChamfer > 0 then
-- ottengo le dimensioni dello pseudotunnel
local dDimMin, dDimMax, dDepth, vtOrtho, nLongFaceId, nSurfInt = GetTunnelDimension( Proc)
local nOk, sErr = MakeChamfer( Proc, vtOrtho, nSurfInt)
if nOk < 0 then return 1, false, sErr end
end
bOk = true
return 1, bOk, sWarn
end
else
-- se richiesti antischeggia con lama su U trasversale e smusso non esclusivo
-- rimane da gestire: se da eseguire con fresa o se richiesto lama ma impossibile utilizzarla, si utilizza fresa
-- 2021.04.27 esegue antischeggia di lama se forma U o L con feature passante in Y o Z
-- 2021.07.16 Per poter eseguire antischeggia di lama su feature che non sono passanti da faccia a faccia
-- ma che sono su un angolo (coinvolgono 2 facce contigue) è stato modificato il confronto in:
-- esegue antischeggia di lama se forma U o L con feature passante in Y o Z, oppure se feature a furma U e con 3 facce oppore a forma a L e con 2 facce
local bPassThrou = ( Proc.Box:getDimY() > _b3Raw:getDimY() - 1 or Proc.Box:getDimZ() > _b3Raw:getDimZ() - 1)
local bPassEdge = ( ( ( bIsU and Proc.Fct == 3) or ( bIsL and Proc.Fct == 2)) and bSinglePart and Proc.Box:getDimX() < 0.9 * _b3Raw:getDimX())
if _nChamfer < 2 and Q_ANTISPLINT_TYPE == 1 and ( ( bIsU or bIsL) and ( bPassThrou or bPassEdge)) then
local bOk
local bSawDown = ( bMillDown and not bMillUp)
_, bOk, sWarn = ManageAntiSplintBySaw( Proc, bIsU, tFData.vtN, tFData.nFacInd, sWarn, bSawDown, true)
if not bOk then return 1, false, sWarn end
end
-- in base al flag interno e al numero di facce e se ha forma ad U: provo prima la svuotatura sul fianco e
-- se non è possibile allora provo in seguito con lama o segacatena
-- o passare subito dalla lavorazione con lama/sega catena
if _bTrySidePocketAtFirst and Proc.Fct == 3 and bIsU then
-- lavoro con svuotature (singola o doppia contrapposta)
local dDiamTool = 100
local nPathInt, nSurfInt, bOneShot, nFirstMachId, bDoubleSide
nOk, sErr, dDimMin, dDimMax, dDepth, vtOrtho, nLongFaceId, dDiamTool,
bDoubleSide, nPathInt, nSurfInt, bOneShot, bMillDown, nFirstMachId, bOrthoFaces = MakeByPockets( Proc, nil, bMillDown)
if nOk == -2 then
if not sMchFind then
sMchFind = sMchFindBackUp
end
sPocketing = ML.FindPocketing( sMchFind, dDiam)
if not sPocketing then
local sErr2 = 'Error : ' .. sMchFind .. ' not found in library'
EgtOutLog( sErr2)
return 1, false, sErr2
end
bTryWithBlades = false
sWarn = sErr
elseif nOk < 0 then
return 1, false, sErr
elseif nOk > 0 then
bTryWithBlades = false
sWarn = sErr
-- se ho antischeggia con fresa le inserisco
if _nChamfer < 2 and Q_ANTISPLINT_TYPE == 2 then
local bOk, sWarn2 = ManageAntiSplintByMill( Proc, tFData.nFacInd, bMillDown, bDoubleSide, vtOrtho,
nPathInt, nSurfInt, dDepth, bOneShot, nFirstMachId)
sWarn = FormatWarning( sWarn, sWarn2)
end
-- se abilitato dal parametro Q inserisco pulitura spigoli o contorno con fresa più piccola
if Q_CONTOUR_SMALL_TOOL > 0 then
local bOk, sWarn2 = MakeRoundCleanCornerOrContour( Proc, tFData.nFacInd, dDiamTool, bMillDown,
bDoubleSide, vtOrtho, nPathInt, nSurfInt, dDepth, bOneShotm)
if not bOk then return 1, false, sWarn2 end
sWarn = FormatWarning( sWarn, sWarn2)
end
end
bOk = true
end
-- 03/09/2020 da conferma di Fabio Squaratti: Per ora solo sulla feature 016:
-- se ha fallito la fresatura (qua sopra) allora di default (anche se il flag Q della lama è disattivato) prima provo la lama
if Proc.Prc == 16 then
_bForceUseBlade = true
end
-- Se la svuotatura precedente non è stata fatta e smusso non è esclusivo, provo con le lame
if bTryWithBlades and _nChamfer < 2 then
-- anche su macchine con testa da sotto, la sega a catena è solo da sopra
if tFData.vtN:getZ() < BD.NZ_MINA and BD.DOWN_HEAD and tFData.nFacInd2 then
tFData = SwapFacetsData( tFData)
end
-- eseguo
bOk, sWarn, sStat = MakeByChainOrSaw( Proc, tFData, dDimMin, dDimMax, vtOrtho, nLongFaceId, bOrthoFaces, nBottomFace, nSurfInt)
if not bOk and sStat == 'MNF' then
_, sPocketing = VerifyPocket( dDiam, tFData.dFacElev + dCollSic, nil, sMchFind, bMillUp, bMillDown)
if sPocketing then
sWarn = ''
else
local sErr2 = 'Error : ' .. sMchFind .. ' not found in library'
EgtOutLog( sErr2)
return 1, false, sErr2
end
else
-- se abilitato dal parametro Q inserisco pulitura spigoli o contorno con fresa più piccola
if Q_CONTOUR_SMALL_TOOL > 0 then
local bOk, sWarn2 = MakeRoundCleanCornerOrContour( Proc, tFData.nFacInd, 100, bMillDown)
if not bOk then return 1, false, sWarn2 end
sWarn = FormatWarning( sWarn, sWarn2)
end
return 1, bOk, sWarn
end
-- altrimenti verifico se ho già svuotato dal fianco, se si esco
else
-- se non ho annullato la/le svuotatura/e dal fianco
if nOk ~= -2 then
return 1, bOk, sWarn
end
end
end
return 0, true, ''
end
---------------------------------------------------------------------
local function MakePocketingOrMilling( Proc, tFData, bSinglePart)
-- verifico se forma ad U o L
local bIsU, bIsL = TestUL( Proc)
local bUseOtherFace
-- se orientata verso il basso e non c'è testa da sotto, verifico l'alternativa
if tFData.vtN:getZ() < BD.NZ_MINA and not BD.DOWN_HEAD and tFData.nFacInd2 then
tFData = SwapFacetsData( tFData)
bUseOtherFace = true
end
-- verifico non sia orientata verso il basso o ci sia una testa dal basso
local bFaceDown = ( tFData.vtN:getZ() < BD.NZ_MINA)
if bFaceDown and not BD.DOWN_HEAD then
local sErr = 'Error : LapJoint from bottom impossible'
EgtOutLog( sErr)
return false, sErr
end
-- se forma a L e la componente in X è maggiore di 60° e non in testa allora verifico se posso utilizzare la faccia secondaria
if bIsL and abs( tFData.vtN:getX()) > 0.866 and
( Proc.Box:getMax():getX() < _b3Solid:getMax():getX() - 10 or tFData.vtN:getX() < 0) and
( not Proc.Tail or tFData.vtN:getX() > 0) then
-- se non ho scambiato la faccia
if not bUseOtherFace then
if tFData.nFacInd2 then
tFData = SwapFacetsData( tFData)
-- altrimenti cerco la faccia secondaria per adiacenza alla principale
else
-- Cerco una faccia adiacente alla principale sul lato lungo
local nFacAdj, sErr = GetFaceAdj( Proc, tFData)
if nFacAdj < 0 then
EgtOutLog( sErr)
return false, sErr
end
tFData = UpdateFacet1Data( Proc.Id, tFData, nFacAdj)
end
-- altrimenti se ho già cambiato faccia do errore per impossibilità di lavorazione
else
local sErr = 'Error : impossible to machine by side angle too big that cause collision'
EgtOutLog( sErr)
return false, sErr
end
end
-- eventuali tagli preliminari
do
local bOk, sErr = MakePreCuts( Proc)
if not bOk then return false, sErr end
end
-- imposto altezza aggiuntiva di elevazione
local dCollSic = CalcCollisionSafety( tFData.vtN)
-- abilitazione lavorazione da sotto
local bMillUp = ( BD.DOWN_HEAD and tFData.vtN:getZ() > -0.259)
local bMillDown = ( BD.DOWN_HEAD and tFData.vtN:getZ() < 0.342)
-- settaggio voluto da Alessandro/Fabio (per fare angoli con fresa piccola)
local sMchFind = 'Pocket'
local dDiam = min( tFData.dH, tFData.dV)
local bTailOnSide = ( Proc.Box:getMin():getX() - _b3Solid:getMin():getX() < 0.1 and not Proc.Tail)
if ( Proc.Fct == 1) or ( ( Proc.Fct == 2 or Proc.Fct == 3) and bIsL) or ( ( ( Proc.Fct == 3 and bIsU) or ( Proc.Fct == 4 and not bTailOnSide)) and bSinglePart) then
sMchFind = 'OpenPocket'
if bIsU then
dDiam = GetUShapeWidth( Proc, tFData.nFacInd) or dDiam
elseif Proc.Fct == 4 then
-- per rifinire gli angoli premio utensile diam 25 o da BD
dDiam = min( dDiam, BD.MAXDIAM_POCK_CORNER or 30)
elseif Proc.Fct == 3 and bIsL then
-- per rifinire gli angoli premio utensile diam 25 o da BD
dDiam = min( 2 * dDiam, BD.MAXDIAM_POCK_CORNER or 30)
else
dDiam = 2 * dDiam
end
end
sMchFindBackUp = sMchFind
local nUseRoughTool = EgtIf( bSinglePart, 0, 1)
-- 04/08/2020 Se settato parametro uso truciolatore (parametro Q), non si devono prendere altre frese, si da errore (Fabio)
-- Questa opzione si scontra facilmente con altre interpretazioni dello stasso parametro Q (per tornare indietro bNewCheck = false)
local bNewCheck = true
-- se processo 20 e non sto usando il truciolatore
if bNewCheck and Proc.Prc == 20 and nUseRoughTool == 0 then
-- verifico se forzato uso truciolatore
if Q_USE_ROUGH_TOOL and Q_USE_ROUGH_TOOL ~= 0 then
sMchFind = 'OpenPocket'
nUseRoughTool = 1
end
end
-- 03/12/2020 aggiunto controllo su feature 30 senza uso truciolatore
if bNewCheck and Proc.Prc == 30 and nUseRoughTool == 0 then
-- verifico se forzato uso truciolatore
if Q_SIDE_ROUGH_TOOL and Q_SIDE_ROUGH_TOOL ~= 0 then
sMchFind = 'OpenPocket'
nUseRoughTool = 1
end
end
-- se processo 20 e non sto usando il truciolatore
if Proc.Prc == 20 and nUseRoughTool == 0 then
if Q_USE_ROUGH_TOOL and Q_USE_ROUGH_TOOL ~= 0 then
sMchFind = 'OpenPocket'
nUseRoughTool = 1
end
end
-- se da sotto, imposto massima lunghezza secondo la direzione
local dMaxTotLen
if bMillDown and BD.GetBottomToolMaxTotLen then
dMaxTotLen = BD.GetBottomToolMaxTotLen( tFData.vtN)
end
-- ricerca lavorazione
local sPocketing, sMyPocketing, dMyTMaxDepth
_, sMyPocketing, dMyTMaxDepth, _, bMillDown = VerifyPocket( dDiam, tFData.dFacElev + dCollSic, dMaxTotLen, sMchFind .. EgtIf( bMillDown, '_H2', ''), bMillUp, bMillDown)
--local sMyPocketing, dMyTDiam, dMyTMaxDepth = ML.FindPocketing( sMchFind .. EgtIf( bMillDown, '_H2', ''), dDiam, dFacElev + dCollSic, dMaxTotLen)
--if not sMyPocketing then
-- sMyPocketing, dMyTDiam, dMyTMaxDepth = ML.FindPocketing( sMchFind .. EgtIf( bMillDown, '_H2', ''), dDiam, nil, dMaxTotLen)
--end
--if not sMyPocketing and bMillUp then
-- sMyPocketing, dMyTDiam, dMyTMaxDepth = ML.FindPocketing( sMchFind, dDiam, dFacElev + dCollSic)
-- if not sMyPocketing then
-- sMyPocketing, dMyTDiam, dMyTMaxDepth = ML.FindPocketing( sMchFind, dDiam)
-- end
-- bMillDown = false
--end
if sMyPocketing and
( dMyTMaxDepth > tFData.dFacElev + dCollSic - 10 * GEO.EPS_SMALL or ( dMyTMaxDepth > 0.8 * tFData.dFacElev + dCollSic and not bIsU) or ( bIsL and nUseRoughTool == 0)) then
sPocketing = sMyPocketing
end
if bMillDown then
sMchFind = sMchFind .. '_H2'
end
-- 2021.09.16 Richiesta di Fabio Squaratti per lavorazione "Lamello":
-- se ho attiva questo tipo di lavorazione (delle fresature) e una di queste feature: L016, L030, L032, L039
-- verifico se sono compatibili con questa lavorazione forma a U e larga più dell'altezza tagliente e profondità compatibile con
local bSpecialMillOnSide
local dThickMillOnSide = 0
local sMillingOnSide
local dToolDiamOnSide = 0
local dMaxDepthOnSide = 0
if ( Proc.Prc == 16 or Proc.Prc == 30 or Proc.Prc == 32 or Proc.Prc == 39) then
-- verifico se ho una gola con 3 facce ed eventualmente delle facce terminali:
-- faccio una copia della superfice ed elimino le facce che hanno dimensione X < 1 e le facce risultanti devono essere una U
local nTestId = EgtCopyGlob( Proc.Id, _nAddGrpId) or GDB_ID.NULL
if nTestId then
local bNewIsU
local bExit
local nFaces = EgtSurfTmFacetCount( nTestId)
while not bExit and nFaces >= 3 do
local bDeleteFace
local nInt = 0
while not bDeleteFace and nInt < nFaces do
nInt = nInt + 1
local b3Facet = EgtSurfTmGetFacetBBoxGlob( nTestId, nInt - 1, GDB_BB.STANDARD)
local vtNi = EgtSurfTmFacetNormVersor( nTestId, nInt - 1, GDB_ID.ROOT)
-- se dimensione faccia sulla X
if b3Facet:getDimX() < 1 or abs( vtNi:getX()) > 0.1 then
EgtSurfTmRemoveFacet( nTestId, nInt - 1)
bDeleteFace = true
end
end
nFaces = EgtSurfTmFacetCount( nTestId)
-- se non ho cancellato una faccia faccio il test per forma ad U
if not bDeleteFace then
-- ottengo il numero di facce rimanenti
bNewIsU = ( nFaces == 3 and not TestElleShape3( nTestId, true))
bExit = true
end
end
-- verifico che la componente x della faccia 0 deve essere nulla
local vtN1 = EgtSurfTmFacetNormVersor( nTestId, 0, GDB_ID.ROOT)
if bNewIsU and abs( vtN1:getX()) > 0.01 then
bNewIsU = false
end
-- cancello la copia del percorso
EgtErase( nTestId)
if bNewIsU and ( not BD.MIN_LEN_LAMELLO or
( Proc.TotBox and Proc.TotBox:getDimX() > BD.MIN_LEN_LAMELLO) or
( not Proc.TotBox and Proc.Box:getDimX() > BD.MIN_LEN_LAMELLO)) then
-- recupero la lavorazione
local bDownhead = BD.DOWN_HEAD and tFData.vtN:getZ() < BD.NZ_MINA
sMillingOnSide = ML.FindMilling( 'SideMillAsBlade_H2', nil, nil, nil, nil, not bDownhead, bDownhead)
if sMillingOnSide then
-- recupero i dati dell'utensile
local dToolLength = 0
local TI = GetToolInfoForMachining( sMillingOnSide)
if TI then
dToolLength = TI.dLength or dToolLength
dToolDiamOnSide = TI.dDiam or dToolDiamOnSide
dThickMillOnSide = TI.dMaxMat or dThickMillOnSide
dMaxDepthOnSide = TI.dSideDepth or dMaxDepthOnSide
end
-- 2021.09.17 Su conferma di Fabio Squaratti, se la gola è più stretta dell'utensile o la profondità della gole è maggiore
-- del valore parametro SIDEDEPTH (preso dalle note utente dell'utensile) allora si prosegue come se non fosse abilitata
-- questo tipo di lavorazione SideMillAsBlade
if dDiam > dThickMillOnSide - 10 * GEO.EPS_SMALL and tFData.dFacElev < dMaxDepthOnSide + 10 * GEO.EPS_SMALL then
bSpecialMillOnSide = true
-- disabilito eventuale svuotatura
sPocketing = nil
end
end
end
end
end
-- se feature 16 e forzata lama e forma ad U, annulla la svuotatura
if Proc.Prc == 16 and _bForceUseBlade and Proc.Fct == 3 and bIsU then
sPocketing = nil
end
-- se lavorazione fresa come lama disabilito eventuale antischegggia
if bSpecialMillOnSide then Q_ANTISPLINT_TYPE = 0 end
-- se non trova una svuotatura adatta
if not sPocketing then
-- se forma a L provo con contornatura
if bIsL and not bSpecialMillOnSide then
-- se smusso non è esclusivo
if _nChamfer < 2 then
return MakeByMill( Proc, tFData, dCollSic)
end
-- altrimenti, in base alla forma, provo con svuotature di fianco o con la sega a catena o lama
else
local stat, bOk, sWarn = MakeSidePocketings( Proc, tFData, dCollSic, bSpecialMillOnSide, nBottomFace,
sMillingOnSide, dToolDiamOnSide, dThickMillOnSide, bSinglePart,
bIsU, bIsL, dDiam, bMillDown, bMillUp, sMchFind, sMchFindBackUp)
if stat == 1 then
return bOk, sWarn
end
end
else
-- se devo inserire il chamfer
if ( ( Proc.Fct == 3 and bIsU) or ( Proc.Fct == 2 and bIsL)) and _nChamfer > 0 then
-- ottengo le dimensioni dello pseudotunnel
local dDimMin, dDimMax, dDepth, vtOrtho, nLongFaceId, nSurfInt = GetTunnelDimension( Proc)
local nOk, sErr = MakeChamfer( Proc, vtOrtho, nSurfInt)
if nOk < 0 then return false, sErr end
end
end
-- se richiesti antischeggia con lama su U trasversale e smusso non esclusivo
-- rimane da gestire: se da eseguire con fresa o se richiesto lama ma impossibile utilizzarla, si utilizza fresa
-- 2021.04.27 esegue antischeggia di lama se forma U o L con feature passante in Y o Z
-- 2021.07.16 Per poter eseguire antischeggia di lama su feature che non sono passanti da faccia a faccia
-- ma che sono su un angolo (coinvolgono 2 facce contigue) è stato modificato il confronto in:
-- esegue antischeggia di lama se forma U o L con feature passante in Y o Z, oppure se feature a forma U e con 3 facce oppore a forma a L e con 2 facce
local bMadeASbyBld = false
local bPassThrou = ( Proc.Box:getDimY() > _b3Raw:getDimY() - 1 or Proc.Box:getDimZ() > _b3Raw:getDimZ() - 1)
local bPassEdge = ( ( ( bIsU and Proc.Fct == 3) or ( bIsL and Proc.Fct == 2)) and bSinglePart and Proc.Box:getDimX() < 0.9 * _b3Raw:getDimX())
if _nChamfer < 2 and Q_ANTISPLINT_TYPE == 1 and ( ( bIsU or bIsL) and ( bPassThrou or bPassEdge)) then
local bOk
local bSawDown = ( bMillDown and not bMillUp)
bMadeASbyBld, bOk, sWarn = ManageAntiSplintBySaw( Proc, bIsU, tFData.vtN, tFData.nFacInd, sWarn, bSawDown)
if not bOk then return false, sWarn end
end
if _nChamfer < 2 and Q_ANTISPLINT_TYPE == 2 then
local bOk, sWarn2
bOk, sWarn2 = ManageAntiSplintByMill( Proc, tFData.nFacInd, bMillDown)
if not bOk then return false, sWarn2 end
end
-- se smusso non esclusivo
if _nChamfer < 2 then
-- eseguo la svuotatura della faccia principale, mi restituisce id utensile, il diametro utensile per il foro opzionale
local tvtNx = {}
tvtNx[2] = tFData.vtN
local bOk, sWarn2, sTuuidPk, dDiamTool
bOk, sWarn2, sTuuidPk, dDiamTool = MakePocket( Proc, tFData.ptC, tvtNx, tFData.nFacInd, sMchFind, nUseRoughTool, sPocketing, tFData.dFacElev + dCollSic)
if not bOk then return false, sWarn2 end
sWarn = FormatWarning( sWarn, sWarn2)
-- se ho più di 3 facce e non di forma ad U oppure ho 3 facce e di forma ad U
-- e non sono stati inseriti antischeggia di lama
-- controllo se c'è una faccia non ortogonale alla principale e la lavoro con una contornatura o svuotatura
if ( ( Proc.Fct > 3 and not bIsU) or ( Proc.Fct == 3 and bIsU)) and not bMadeASbyBld then
-- Recupero le facce adiacenti alla principale (solo quelle esistenti)
local vAdj = GetValidFacetAdjacencies( Proc.Id, tFData.nFacInd)
if not vAdj or #vAdj == 0 then
local sErr = 'Error : main face without adjacencies'
EgtOutLog( sErr)
return false, sErr
end
-- Cerco una faccia adiacente alla principale con angolo > 90
local tDimAndRef = {}
tvtNx = {}
tvtNx[1] = tFData.vtN
tDimAndRef[1] = { tFData.dH, tFData.dV, tFData.rfFac}
for i = 1, #vAdj do
local bAdj, ptP1, ptP2, dAng = EgtSurfTmFacetsContact( Proc.Id, tFData.nFacInd, vAdj[i], GDB_ID.ROOT)
if bAdj and dAng < 0 and 180 + dAng > 90.1 then
local rfFac2, dH2, dV2 = EgtSurfTmFacetMinAreaRectangle( Proc.Id, vAdj[i], GDB_ID.ROOT)
_, tvtNx[2] = EgtSurfTmFacetCenter( Proc.Id, vAdj[i], GDB_ID.ROOT)
tDimAndRef[2] = { dH2, dV2, rfFac2}
local ptPs = ( ptP1 + ptP2) / 2
local bOk, sWarn2 = MachineByMill( Proc, tvtNx, tFData.nFacInd, vAdj[i], ptPs, tDimAndRef,
EgtIf( Proc.Fct == 3 and bIsU, 0, 2), nUseRoughTool, dAng, sPocketing, sTuuidPk, tFData.dFacElev)
if not bOk then return bOk, sWarn2 end
sWarn = FormatWarning( sWarn, sWarn2)
end
end
end
-- se abilitato dal parametro Q inserisco foro sullo spigolo
if Q_BORE_ON_CORNER == 1 then
local bOk, sWarn2 = MakeDrillOnCorner( Proc, tFData.nFacInd, dDiamTool)
if not bOk then return false, sWarn2 end
sWarn = FormatWarning( sWarn, sWarn2)
-- altrimenti se abilitato dal parametro Q inserisco percorso di pulitura
elseif Q_BORE_ON_CORNER == 2 then
local bOk, sWarn2 = MakeSharpCleanCorner( Proc, tFData.nFacInd, dDiamTool)
if not bOk then return false, sWarn2 end
sWarn = FormatWarning( sWarn, sWarn2)
-- altrimenti se abilitato dal parametro Q inserisco pulitura spigoli o contorno con fresa più piccola
elseif Q_CONTOUR_SMALL_TOOL > 0 then
local bOk, sWarn2 = MakeRoundCleanCornerOrContour( Proc, tFData.nFacInd, dDiamTool, bMillDown)
if not bOk then return false, sWarn2 end
sWarn = FormatWarning( sWarn, sWarn2)
end
end
return true, ''
end
---------------------------------------------------------------------
local function MakeTwoFaces( Proc, bSinglePart, bPrevBhSideMill)
-- se non posso lavorare la feature perché condizionata dall'esecuzione del solo chamfer
-- genero errore e non faccio nulla
if _nChamfer < 0 then
return false, _sErrCham
end
-- recupero la faccia con il maggior numero di adiacenze e l'elevazione relativa
local tFData = GetFacetsData( Proc.Id)
if not tFData.nFacInd or tFData.nFacInd < 0 then
local sErr = 'Error : MakeTwoFaces could not find reference face'
EgtOutLog( sErr)
return false, sErr
end
-- se fattibile con fresa BH di fianco e spessore utensile inferiore alla larghezza faccia
local bMakeBySideMill, _, bHeadDir, sMilling, dMaxMat, dToolDiam = VerifyBHSideMill( Proc, bSinglePart, bPrevBhSideMill)
if bPrevBhSideMill == nil then
bPrevBhSideMill = bMakeBySideMill
end
if bMakeBySideMill and ( dMaxMat <= tFData.dH + 15 * GEO.EPS_SMALL) then
-- se smusso non è esclusivo
if _nChamfer < 2 then
local bOk, sErr = MakeSideMill( Proc, sMilling, tFData, dMaxMat, dToolDiam, bHeadDir)
return bOk, sErr
end
-- altrimenti lavoro con svuotatura
else
local bOk, sErr = MakePocketingOrMilling( Proc, tFData, bSinglePart)
return bOk, sErr
end
return true, '', bPrevBhSideMill
end
---------------------------------------------------------------------
local function MakeThreeFaces( Proc, bSinglePart, bPrevBhSideMill)
-- se non posso lavorare la feature perché condizionata dall'esecuzione del solo chamfer
-- genero errore e non faccio nulla
if _nChamfer < 0 then
return false, _sErrCham
end
-- recupero la faccia con il maggior numero di adiacenze e l'elevazione relativa
local tFData = GetFacetsData( Proc.Id)
if not tFData.nFacInd or tFData.nFacInd < 0 then
local sErr = 'Error : MakeThreeFaces could not find reference face'
EgtOutLog( sErr)
return false, sErr
end
-- se fattibile con fresa BH di fianco e spessore utensile inferiore alla larghezza faccia
local bMakeBySideMill, _, bHeadDir, sMilling, dMaxMat, dToolDiam = VerifyBHSideMill( Proc, bSinglePart, bPrevBhSideMill)
if bPrevBhSideMill == nil then
bPrevBhSideMill = bMakeBySideMill
end
--if bMakeBySideMill and ( dMaxMat <= tFData.dV + 15 * GEO.EPS_SMALL) then
if bMakeBySideMill and ( dMaxMat <= tFData.dH + 15 * GEO.EPS_SMALL) then
-- se smusso non è esclusivo
if _nChamfer < 2 then
local bOk, sErr = MakeSideMill( Proc, sMilling, tFData, dMaxMat, dToolDiam, bHeadDir)
return bOk, sErr
end
-- altrimenti lavoro con svuotatura
else
local bSpecial3faces = false
local bBoxF = EgtGetBBoxRef( Proc.Id, GDB_BB.STANDARD, tFData.rfFac)
if tFData.dH * tFData.dV < 0.9 * ( bBoxF:getDimX() * bBoxF:getDimY()) then
bSpecial3faces = true
end
-- se riconosciuta gestione special (limitata per ora alla feature 20)
if bSpecial3faces and Proc.Prc == 20 and tFData.nFacInd2 then
-- se smusso non è esclusivo
if _nChamfer < 2 then
local bOk, sErr = MakeSpecialThreeFaces( Proc, tFData)
return bOk, sErr
end
-- altrimenti lavorazione di svuotatura o contornatura
else
local bOk, sErr = MakePocketingOrMilling( Proc, tFData, bSinglePart)
return bOk, sErr
end
end
return true, '', bPrevBhSideMill
end
---------------------------------------------------------------------
local function MakeMoreFaces( Proc, bSinglePart, bPrevBhSideMill)
local bClosedOrthoFaces
-- recupero la faccia con il maggior numero di adiacenze e l'elevazione relativa
local tFData = GetFacetsData( Proc.Id)
if not tFData.nFacInd or tFData.nFacInd < 0 then
if tFData.nFacInd == -1 then
bClosedOrthoFaces = tFData.isOrthoFaces
else
local sErr = 'Error : MakeMoreFaces could not find reference face'
EgtOutLog( sErr)
return false, sErr
end
end
-- se è una feature scanalatura (con 5 facce) e non è stata riconosciuta come fessura, eseguo altre verifiche
if Proc.Prc == 16 and Proc.Fct == 5 and not bClosedOrthoFaces then
local nBottomFace
-- dalla copia della superfice, ciclo eliminando una faccia per volta per verificare se trova fessura
for i = 1, Proc.Fct do
local nNewProcId = EgtCopyGlob( Proc.Id, _nAddGrpId) or GDB_ID.NULL
-- elimino una faccia
nBottomFace = i - 1
if EgtSurfTmRemoveFacet( nNewProcId, nBottomFace) then
-- recupero la faccia con il maggior numero di adiacenze e l'elevazione relativa
tFData = GetFacetsData( nNewProcId)
if not tFData.nFacInd or tFData.nFacInd < 0 then
if tFData.nFacInd == -1 then
bClosedOrthoFaces = tFData.isOrthoFaces
EgtErase( nNewProcId)
break
else
EgtErase( nNewProcId)
local sErr = 'Error : MakeMoreFaces could not find reference face'
EgtOutLog( sErr)
return false, sErr
end
end
-- altrimenti esco
else
EgtErase( nNewProcId)
break
end
end
-- se riconosciuta fessura ricalcolo l'elevazione dalla faccia di fondo
if bClosedOrthoFaces then
local dFacElev = BL.GetFaceElevation( Proc.Id, nBottomFace)
tFData = UpdateFacet1Data( Proc.Id, tFData, nBottomFace, dFacElev)
-- rendo nulla la faccia opzionale perchè si tratta di una fessura
tFData = UpdateFacet2Data( Proc.Id, tFData, nil)
-- non setto come tunnel
bClosedOrthoFaces = false
end
end
-- se non posso lavorare la feature perché condizionata dall'esecuzione del solo chamfer
-- genero errore e non faccio nulla
if _nChamfer < 0 then
return false, _sErrCham
end
-- se è un tunnel provo a vedere se è possibile lavorarlo con la svuotatura o con la sega catena
if bClosedOrthoFaces then
local bTryWithBlades = true
-- lavoro fessura con svuotature (singola o doppia contrapposta)
local nOk, sErr, dDimMin, dDimMax, dDepth, vtOrtho, nLongFaceId = MakeByPockets( Proc, bClosedOrthoFaces)
if nOk < 0 then
return false, sErr
elseif nOk > 0 then
bTryWithBlades = false
end
-- Se la svuotatura precedente non è stata fatta e chamfer non è mutuamente esclusivo provo con la sega-catena
if bTryWithBlades and _nChamfer < 2 then
-- verifico se posso farlo con la sega-catena
local bOk, sErr = MakeByChainsaw( Proc, dDimMin, dDimMax, dDepth, vtOrtho, nLongFaceId)
if not bOk then
return false, sErr
end
end
-- altrimenti non è una fessura
else
local bOk, sErr = MakePocketingOrMilling( Proc, tFData, bSinglePart)
return bOk, sErr, bPrevBhSideMill
end
return true, '', bPrevBhSideMill
end
---------------------------------------------------------------------
local function MakeLongFaces( Proc, Func)
-- divido in parti lungo X
local vAddId = {}
local nPart = max( ceil( Proc.Box:getDimX() / BD.LONGCUT_MAXLEN), 2)
local dPartLen = Proc.Box:getDimX() / nPart
local Xmin = Proc.Box:getMin():getX()
for i = 1, nPart do
-- eseguo divisione
local AddId = EgtCopyGlob( Proc.Id, _nAddGrpId) or GDB_ID.NULL
EgtSetName( AddId, 'AddPart_' .. tostring( Proc.Id) .. '_' .. tostring( i))
if i > 1 then
local ptOn = Point3d( Xmin + ( i - 1) * dPartLen, 0, 0)
EgtCutSurfTmPlane( AddId, ptOn, -X_AX(), true, GDB_RT.GLOB)
end
if i < nPart then
local ptOn = Point3d( Xmin + i * dPartLen, 0, 0)
EgtCutSurfTmPlane( AddId, ptOn, X_AX(), true, GDB_RT.GLOB)
end
-- eseguo inserimento in modo da ordinare da X+ a X-
table.insert( vAddId, 1, AddId)
end
-- applico le lavorazioni sulle diverse parti
local sWarn
local bPrevBhSideMill
for i = 1, #vAddId do
local b3Box = EgtGetBBoxGlob( vAddId[i], GDB_BB.STANDARD)
local nFct = EgtSurfTmFacetCount( vAddId[i])
local AddProc = { Id = vAddId[i], Grp = Proc.Grp, Prc = Proc.Prc, Box = b3Box, TotBox = Proc.Box, Fct = nFct, Flg = Proc.Flg}
local bOk, sMyWarn
-- richiamo la funzione necessaria (passata come parametro)
bOk, sMyWarn, bPrevBhSideMill = Func( AddProc, false, bPrevBhSideMill)
if not sWarn then sWarn = sMyWarn end
if not bOk then return bOk, sWarn end
end
return true, sWarn
end
---------------------------------------------------------------------
local function TestTwoFacesDownHead( Proc)
-- verifico ci siano due facce
if Proc.Fct ~= 2 then return false end
-- verifico se da lavorare con testa da sotto
local bDownHead = false
if BD.DOWN_HEAD then
local ptC = {}
local vtN = {}
ptC[1], vtN[1] = EgtSurfTmFacetCenter( Proc.Id, 0, GDB_ID.ROOT)
ptC[2], vtN[2] = EgtSurfTmFacetCenter( Proc.Id, 1, GDB_ID.ROOT)
local vtNm = ( vtN[1] + vtN[2]) ; vtNm:normalize()
bDownHead = ( vtNm:getZ() < -0.5)
end
return bDownHead
end
---------------------------------------------------------------------
-- Applicazione della lavorazione
---------------------------------------------------------------------
function ProcessLapJoint.Make( Proc, nPhase, nRawId, nPartId, dOvmHead)
-- inizializzo variabili globali al modulo
local bOk, sErr = InitGlob( Proc, nPhase, nRawId, nPartId, dOvmHead)
if not bOk then
return bOk, sErr
end
-- limiti di fresatura semplice
local MAX_MILL_LIN = 80
-- se non forzate frese, uso la lama
local bUseBlade = Q_USE_ROUGH_TOOL ~= 1 and Q_USE_MILL ~= 1
local nForceUseBladeOnNotContinueFace
-- se ho attiva la lama e ho la feature 30, verifico i parametri Q propri della feature
if bUseBlade then
if Proc.Prc == 30 then
nForceUseBladeOnNotContinueFace = Q_BLADE_ON_ALONG_FACE
-- se antischeggia di fresa o abilitato sgrossatore di fianco
if Q_ANTISPLINT_TYPE == 2 or Q_SIDE_ROUGH_TOOL == 1 then
bUseBlade = false
end
-- se ho attiva la lama e ho la feature 32, verifico i parametri Q propri della feature
elseif Proc.Prc == 32 then
-- se antischeggia di fresa o abilitato sgrossatore di fianco
if Q_ANTISPLINT_TYPE == 2 or Q_SIDE_ROUGH_TOOL == 1 then
bUseBlade = false
end
-- se ho attiva la lama e ho la feature 34, verifico i parametri Q propri della feature
elseif Proc.Prc == 34 then
-- se antischeggia di fresa o abilitato sgrossatore di fianco
if Q_ANTISPLINT_TYPE == 2 then
bUseBlade = false
end
end
end
-- se lunghezza richiede spezzatura
if ( Proc.Box:getDimX() > BD.LONGCUT_MAXLEN) or
( Proc.Box:getDimX() > 0.7 * _b3Solid:getDimX() and Proc.Box:getDimX() > BD.LONGCUT_ENDLEN) then
-- una faccia
if Proc.Fct == 1 then
if bUseBlade and nForceUseBladeOnNotContinueFace and nForceUseBladeOnNotContinueFace > 0 then
return LongCut.Make( Proc, _nPhase, _nRawId, _nPartId, bUseBlade, nForceUseBladeOnNotContinueFace)
else
return LongCut.Make( Proc, _nPhase, _nRawId, _nPartId)
end
-- due facce
elseif Proc.Fct == 2 then
-- verifico se da lavorare con testa da sotto
local bDownHead = TestTwoFacesDownHead( Proc)
-- determino se due facce lunghe oppure una lunga e l'altra terminale
local b3Fac1 = EgtSurfTmGetFacetBBoxGlob( Proc.Id, 0, GDB_BB.STANDARD)
local b3Fac2 = EgtSurfTmGetFacetBBoxGlob( Proc.Id, 1, GDB_BB.STANDARD)
if abs( b3Fac1:getDimX() - b3Fac2:getDimX()) < 50 then
-- leggo i parametri Q per utilizzare la fresa di fianco e/o lama
return Long2Cut.Make( Proc, _nPhase, _nRawId, _nPartId, Q_ANTISPLINT_TYPE == 1, Q_SIDE_ROUGH_TOOL)
elseif b3Fac1:getDimX() < 1 or b3Fac2:getDimX() < 1 then
-- la faccia 0 deve essere quella lunga
if b3Fac1:getDimX() < 1 then EgtSurfTmSwapFacets( Proc.Id, 0, 1) end
if bUseBlade then
if nForceUseBladeOnNotContinueFace and nForceUseBladeOnNotContinueFace > 0 then
return LongCut.Make( Proc, _nPhase, _nRawId, _nPartId, bUseBlade, nForceUseBladeOnNotContinueFace)
else
return Fbs.MakeTwo( Proc, _nPhase, _nRawId, _nPartId, _dOvmHead, 'HeadSide' .. EgtIf( bDownHead, '_H2', ''), true, bDownHead)
end
else
return LongCut.Make( Proc, _nPhase, _nRawId, _nPartId)
end
else
if bUseBlade then
return Fbs.MakeTwo( Proc, _nPhase, _nRawId, _nPartId, _dOvmHead, 'HeadSide' .. EgtIf( bDownHead, '_H2', ''), true, bDownHead)
else
return MakeLongFaces( Proc, MakeTwoFaces)
end
end
-- tre facce
elseif Proc.Fct == 3 then
-- determino se due facce lunghe oppure una lunga e l'altra terminale
local b3Fac1 = EgtSurfTmGetFacetBBoxGlob( Proc.Id, 0, GDB_BB.STANDARD)
local b3Fac2 = EgtSurfTmGetFacetBBoxGlob( Proc.Id, 1, GDB_BB.STANDARD)
local b3Fac3 = EgtSurfTmGetFacetBBoxGlob( Proc.Id, 2, GDB_BB.STANDARD)
local bApplyBladeOnLongNotContinueFace
if b3Fac1:getDimX() < 1 and b3Fac3:getDimX() < 1 then
-- la faccia 0 deve essere quella lunga
EgtSurfTmSwapFacets( Proc.Id, 0, 1)
bApplyBladeOnLongNotContinueFace = true
elseif b3Fac1:getDimX() < 1 and b3Fac2:getDimX() < 1 then
-- la faccia 0 deve essere quella lunga
EgtSurfTmSwapFacets( Proc.Id, 0, 2)
bApplyBladeOnLongNotContinueFace = true
elseif b3Fac2:getDimX() < 1 and b3Fac3:getDimX() < 1 then
bApplyBladeOnLongNotContinueFace = true
end
if bApplyBladeOnLongNotContinueFace and bUseBlade and nForceUseBladeOnNotContinueFace and nForceUseBladeOnNotContinueFace > 0 then
return LongCut.Make( Proc, _nPhase, _nRawId, _nPartId, bUseBlade, nForceUseBladeOnNotContinueFace)
else
return MakeLongFaces( Proc, MakeThreeFaces)
end
-- 4 o 5 facce
else
return MakeLongFaces( Proc, MakeMoreFaces)
end
-- altrimenti lavorazione unica
else
-- una faccia
if Proc.Fct == 1 then
-- se piccola, con fresa
if not bUseBlade and ( Proc.Box:getDimX() < MAX_MILL_LIN and ( Proc.Box:getDimZ() < MAX_MILL_LIN or Proc.Box:getDimY() < MAX_MILL_LIN)) then
return MakeOneFaceByMill( Proc)
-- altrimenti, con lama
else
return Cut.Make( Proc, _nPhase, _nRawId, _nPartId, _dOvmHead)
end
-- due facce
elseif Proc.Fct == 2 then
-- se praticamente è lunga come la trave
if Proc.Box:getDimX() > 0.8 * _b3Solid:getDimX() then
return Long2Cut.Make( Proc, _nPhase, _nRawId, _nPartId, bUseBlade, Q_SIDE_ROUGH_TOOL)
-- altrimenti
else
-- verifico se da lavorare con testa da sotto
local bDownHead = TestTwoFacesDownHead( Proc)
if BD.DOWN_HEAD then
local ptC = {}
local vtN = {}
ptC[1], vtN[1] = EgtSurfTmFacetCenter( Proc.Id, 0, GDB_ID.ROOT)
ptC[2], vtN[2] = EgtSurfTmFacetCenter( Proc.Id, 1, GDB_ID.ROOT)
local vtNm = ( vtN[1] + vtN[2])
vtNm:normalize()
bDownHead = ( vtNm:getZ() < -0.5)
end
-- determino l'angolo tra le facce
local bAdj, _, _, dAng = EgtSurfTmFacetsContact( Proc.Id, 0, 1, GDB_ID.ROOT)
-- se ortogonali e non forzata lama oppure con testa da sotto, con fresa
if ( not bUseBlade or bDownHead) and bAdj and abs( dAng + 90) < 1 then
-- se piccole
if Proc.Box:getDimX() < MAX_MILL_LIN and ( Proc.Box:getDimZ() < MAX_MILL_LIN or Proc.Box:getDimY() < MAX_MILL_LIN) then
return MakeTwoFacesByMill( Proc, bDownHead)
else
return MakeTwoFaces( Proc, true)
end
-- altrimenti, con lama
else
-- verifico se due facce o L con una o due facce di terminazione
local _, bIsL = TestUL( Proc)
if bIsL and _nChamfer > 0 then
local dDimMin, dDimMax, dDepth, vtOrtho, nLongFaceId, nSurfInt = GetTunnelDimension( Proc)
local nOk, sErr = MakeChamfer( Proc, vtOrtho, _b3Solid, nSurfInt)
if nOk < 0 then return false, sErr end
end
return Fbs.MakeTwo( Proc, _nPhase, _nRawId, _nPartId, _dOvmHead, 'HeadSide' .. EgtIf( bDownHead, '_H2', ''), true, bDownHead)
end
end
-- tre facce
elseif Proc.Fct == 3 then
return MakeThreeFaces( Proc, true)
-- 4 o 5 facce
else
return MakeMoreFaces( Proc, true)
end
end
end
---------------------------------------------------------------------
return ProcessLapJoint