Files
DataWall/LuaLibs/WProcessFreeContour.lua
T
Dario Sassi 41f85808e2 DataWall 2.5i1 :
- correzioni per pulizia corner in FreeContour.
2023-09-12 11:25:15 +02:00

2591 lines
117 KiB
Lua

-- ProcessFreeContour.lua by Egaltech s.r.l. 2023/09/12
-- Gestione calcolo profilo libero per Pareti
-- 2021/11/15 Penna e chiodature sono sempre riportate sulla faccia sopra anche se nel progetto sono sotto.
-- 2021/12/10 In taglio con lama aggiunta gestione SCC per testa Gearbox.
-- 2022/01/13 Aggiunta gestione massimo affondamento in Z anche per pulizia spigoli con fresa 60deg (WD.MAX_CLEAN_CRN60).
-- 2022/02/03 Corretto controllo massimo affondamento nella tavola.
-- 2022/02/21 Corretti allungamenti/accorciamenti tagli inclinati con fresa. Migliorata gestione tagli trasversali per macchine travi.
-- 2022/03/14 Corretto riconoscimento lato esterno per percorsi aperti.
-- 2022/03/16 Ulteriore modifica per riconoscimento lato esterno (aggiunto uso vExtr a GetFacesExternalSide).
-- 2022/04/03 Correzioni e modifiche per pulitura spigoli tipo 2 e 3.
-- 2022/04/19 Aggiunta passibilita' fresatura ad affondamento ridotto quando non possibile completa o sega a catena.
-- 2022/04/26 Migliorata gestione caso pocketing.
-- 2022/08/05 Aggiunta segnalazione aree vietate non gestite.
-- 2022/08/29 Corretta gestione tipo Pocket senza fondo (sono lavorabili da entrambe le parti con fresatura).
-- 2022/12/13 Aggiunta la funzione Is3EdgesApprox per riconoscere come 3 lati anche facce con lati aggiuntivi molto corti (<15 mm)
-- 2022/12/14 Aggiunto l'accorciamento della lama in caso di facce vicine orientate verso il basso
-- 2023/02/28 In lavorazioni con sega a catena per invertire lato mandrino ora Invert + Left invece di MCH_SCC.OPPOSITE.
-- 2023/03/08 In lavorazione con fresa, se imposto Tool_ID non si controlla più possa lavorare di testa.
-- 2023/04/14 Aggiunta pulitura spigoli Q05=1 anche su sole fresature.
-- 2023/04/17 Lavorazione CleanCorner sempre forzata con lato di lavoro in centro.
-- 2023/05/25 Funzioni EgtAddMachining sostituite da WM.AddMachining in modo da trascrivere le priorità da btl alle lavorazioni.
-- 2023/06/06 Aggiunta gestione lavorazione per lamatura speciale affondata con Tool_ID specifico.
-- 2023/07/26 In MakeByCut migliorata la scelta della fresa secondaria nel caso non sia disponibile una fresa di lunghezza sufficiente.
-- 2023/09/12 Modifiche a GetTunnelDimension (asse deve essere com Z globale) e MakeLocalSurf per gestire finestre con lati inclinati.
-- Tabella per definizione modulo
local WPF = {}
-- Include
require( 'EgtBase')
local WL = require( 'WallLib')
EgtOutLog( ' WProcessFreeContour started', 1)
-- Dati
local WD = require( 'WallData')
local WM = require( 'WMachiningLib')
if WD.CHECK_MIN_Z_SAW == nil then WD.CHECK_MIN_Z_SAW = true end
if not WD.MIN_Z_SAW then WD.MIN_Z_SAW = 0 end
if not WD.MAX_CLEAN_CRN60 then WD.MAX_CLEAN_CRN60 = 150 end
if not WD.MAX_CLEAN_CRN30 then WD.MAX_CLEAN_CRN30 = 68 end
local WHISK_OFFS = 0.1
local WHISK_SAFE = 5
local MIN_LEN_CUT = 250
-- variabili assegnazione parametri Q
local sTypeCornerCut = 'Q05' -- i
-- variabile settaggio doppia lavorazione su angoo > 90
local bMakeTwinCut = true
-- variabile per valore sfondamento spigolo
local dExtraCorner = 1
-- angolo sottosquadra ammesso per fresa cono 30°
local dAngleSmall = 70
---------------------------------------------------------------------
-- Riconoscimento della feature
function WPF.Identify( Proc)
return ( ( Proc.Grp == 0 or Proc.Grp == 3 or Proc.Grp == 4) and ( Proc.Prc == 250 or Proc.Prc == 251 or Proc.Prc == 252))
end
---------------------------------------------------------------------
-- Classificazione della feature
function WPF.Classify( Proc, b3Raw)
-- verifico se di tipo pocket
local bPocket = ( EgtGetInfo( Proc.Id, 'PCKT', 'i') == 1)
-- recupero la curva associata
local AuxId = EgtGetInfo( Proc.Id, 'AUXID', 'i')
if not AuxId then return false end
AuxId = AuxId + Proc.Id
local vtExtr = EgtCurveExtrusion( AuxId, GDB_RT.GLOB)
-- recupero il tipo di lavorazione
local nCntType = EgtGetInfo( Proc.Id, 'CNT_TYPE', 'i') or 0
local nTool_ID = EgtGetInfo( Proc.Id, 'CNT_DATA', 'i')
-- se tasca
if bPocket then
-- cerco la faccia di fondo della superfice (deve avere direzione circa quella di estrusione della curva)
local nFacet
for i = 1, Proc.Fct do
local vtN = EgtSurfTmFacetNormVersor( Proc.Id, i-1, GDB_ID.ROOT)
if abs( vtN * vtExtr) > 0.99 then
nFacet = i - 1
vtExtr = vtN
break
end
end
local bDown = ( nFacet and vtExtr:getZ() < - 0.5)
return not bDown
-- se altrimenti profilo orizzontale
elseif abs( vtExtr:getZ()) < 0.5 then
return false
-- se penna o chiodatura va sempre bene (vengono sempre riportati sopra)
elseif nCntType == 10 or nCntType == 20 then
return true
-- se altrimenti profilo verticale che non interessa tutta la sezione e non caso speciale con lamatura affondata
elseif ( Proc.Box:getMax():getZ() < b3Raw:getMax():getZ() - 2) and ( not nTool_ID or ( nTool_ID ~= ( WD.RECESSED_COUNTERBORE_TOOLID or 0)) or ( not EgtCurveIsACircle( AuxId))) then
return false
-- altrimenti è profilo verticale che interessa tutta la sezione o caso speciale con lamatura affondata
else
return true
end
end
----------------------------------------------------------------------
-- Classificazione del flip della feature per nesting
-- return nFlip0, nFlip1
function WPF.FlipClassify( Proc, b3Raw)
local nFlip0 = 0
local nFlip1 = 0
-- verifico se di tipo pocket
local bPocket = ( EgtGetInfo( Proc.Id, 'PCKT', 'i') == 1)
-- recupero la curva associata se esiste
local AuxId = EgtGetInfo( Proc.Id, 'AUXID', 'i')
if not AuxId then return false end
AuxId = AuxId + Proc.Id
local vtN = EgtCurveExtrusion( AuxId, GDB_RT.GLOB)
local dVtNZ = vtN:getZ()
-- se tasca
if bPocket then
-- verifico se è lavorabile da sopra
nFlip0 = EgtIf( dVtNZ < -0.5, 0, 100)
-- verifico se e' lavorabile da fliped: cambio segno al versore
nFlip1 = EgtIf( -dVtNZ < -0.5, 0, 100)
-- se altrimenti profilo orizzontale
elseif abs( dVtNZ) < WD.NZ_MINA then
return 0, 0
-- se altrimenti profilo verticale che non interessa tutta la sezione
elseif Proc.Box:getMax():getZ() < b3Raw:getMax():getZ() - 2 then
return 0 , 0
-- altrimenti è profilo verticale che interessa tutta la sezione
else
local dVtNZMedia = 0
for i = 1, Proc.Fct do
local vtN = EgtSurfTmFacetNormVersor( Proc.Id, i - 1, GDB_ID.ROOT)
dVtNZMedia = dVtNZMedia + vtN:getZ()
end
dVtNZMedia = dVtNZMedia / Proc.Fct
if abs( dVtNZMedia) <= GEO.EPS_SMALL then
nFlip0 = 100
nFlip1 = 100
elseif dVtNZMedia >= 0 + GEO.EPS_SMALL then
nFlip0 = 75
nFlip1 = 50
else
nFlip0 = 50
nFlip1 = 75
end
end
return nFlip0, nFlip1
end
---------------------------------------------------------------------
local function TestElleShape3( nIdGeom, nNumFacet)
-- 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
local vFacAdj = EgtSurfTmFacetAdjacencies( nIdGeom, i - 1)[1]
-- le conto
local nCount = 0
for j = 1, #vFacAdj do
if vFacAdj[j] >= 0 then
nCount = nCount + 1
end
end
if nCount == 1 then
bIsL = false
break
end
end
return bIsL
end
---------------------------------------------------------------------
local function TestElleShape4( nIdGeom, nNumFacet)
-- valida solo nel caso di quattro facce
if nNumFacet ~= 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
local vFacAdj = EgtSurfTmFacetAdjacencies( nIdGeom, i - 1)[1]
-- le conto
local nCount = 0
for j = 1, #vFacAdj do
if vFacAdj[j] >= 0 then
nCount = nCount + 1
end
end
local _, dH, dV = EgtSurfTmFacetMinAreaRectangle( nIdGeom, i - 1, GDB_ID.ROOT)
local dArea = dH * dV
if nCount == 2 then
dMaxArea2 = max( dMaxArea2, dArea)
elseif nCount == 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 < dMaxArea2 then
return 1
else
return 2
end
end
---------------------------------------------------------------------
local function VerifyCornerType( Proc)
-- Verifico il tipo di lavorazione su angolo :
-- 0 : niente
-- 1 : ripresa corner dopo pausa per rimozione sfridi (fresa 60deg)
-- 2 : ripresa corner senza pausa (fresa 30 deg)
-- 3 : scarico corner (tipo foro).
local nVal = EgtGetInfo( Proc.Id, sTypeCornerCut, 'i')
return ( nVal or 0)
end
---------------------------------------------------------------------
local function IsPointOnRawLongEdges( ptCen, b3Raw)
return ( abs( ptCen:getY() - b3Raw:getMin():getY()) < 0.1 or abs( ptCen:getY() - b3Raw:getMax():getY()) < 0.1)
end
---------------------------------------------------------------------
local function GetOtherRegions( nPartId)
local vOthers = {}
-- ciclo sui pezzi
local nOtherId = EgtGetFirstPartInRawPart( EgtGetFirstRawPart() or GDB_ID.NULL)
while nOtherId do
-- cerco le regioni marcate
local nCount = 0
local nRegId = EgtGetFirstInGroup( EgtGetFirstNameInGroup( nOtherId, 'Outline') or GDB_ID.NULL)
while nRegId do
local vtN = EgtSurfFrNormVersor( nRegId, GDB_ID.ROOT)
if EgtExistsInfo( nRegId, 'REGION') and vtN and AreSameVectorApprox( vtN, Z_AX()) then
local b3Reg = EgtGetBBoxGlob( nRegId, GDB_BB.STANDARD)
if b3Reg then
nCount = nCount + 1
table.insert( vOthers, { PartId = nOtherId, RegId = nRegId, Box = b3Reg})
end
end
nRegId = EgtGetNext( nRegId)
end
-- se non trovate regioni marcate, cerco regioni con la normale corretta
if nCount == 0 then
local nRegId = EgtGetFirstInGroup( EgtGetFirstNameInGroup( nOtherId, 'Outline') or GDB_ID.NULL)
while nRegId do
local vtN = EgtSurfFrNormVersor( nRegId, GDB_ID.ROOT)
if EgtGetType( nRegId) == GDB_TY.SRF_FRGN and vtN and AreSameVectorApprox( vtN, Z_AX()) then
local b3Reg = EgtGetBBoxGlob( nRegId, GDB_BB.STANDARD)
if b3Reg then
table.insert( vOthers, { PartId = nOtherId, RegId = nRegId, Box = b3Reg})
end
end
nRegId = EgtGetNext( nRegId)
end
end
-- passo al pezzo successivo
nOtherId = EgtGetNextPartInRawPart( nOtherId)
end
return vOthers
end
---------------------------------------------------------------------
local function ReorderFaces( nIdSurf, nNumFacet)
-- recupero le adiacenze di tutte le facce
local vAdj = {}
for i = 1, nNumFacet do
-- recupero le adiacenze della faccia
local vFacAdj = EgtSurfTmFacetAdjacencies( nIdSurf, i - 1)[1]
-- le conto
local nCount = 0
for j = 1, #vFacAdj do
if vFacAdj[j] >= 0 then
nCount = nCount + 1
end
end
vAdj[i] = nCount
end
-- sposto le facce isolate alla fine
for i = #vAdj, 1, -1 do
if vAdj[i] == 0 then
if vAdj[#vAdj] == 0 then
table.remove( vAdj, i)
end
EgtSurfTmSwapFacets( nIdSurf, i - 1, #vAdj)
end
end
-- se facce tutte isolate, esco
if #vAdj == 0 then return end
-- cerco la faccia non isolata con il minor numero di adiacenze
local nIdFace
local nAdjMin = 1000
for i = 1, #vAdj do
if vAdj[i] < nAdjMin then
nAdjMin = vAdj[i]
nIdFace = i
end
end
-- se la faccia non isolata con minori adiacenze non è in prima posizione, eseguo scambio
if nIdFace and nIdFace ~= 1 and nAdjMin == 1 then
EgtSurfTmSwapFacets( nIdSurf, nIdFace-1, 0)
end
-- ordino le facce in modo da avere una sequenza di facce concatenate
for i = 1, #vAdj - 1 do
-- recupero l'angolo con la faccia successiva
local bAdj, _, _, _ = EgtSurfTmFacetsContact( nIdSurf, i-1, i, GDB_ID.ROOT)
-- se non ho adiacenza
if not bAdj then
for j = i+1, #vAdj do
bAdj, _, _, _ = EgtSurfTmFacetsContact( nIdSurf, i-1, j-1, GDB_ID.ROOT)
-- se ho adiacenza scambio le facce
if bAdj then
EgtSurfTmSwapFacets( nIdSurf, i, (j-1))
break
end
end
end
end
end
---------------------------------------------------------------------
local function RemoveBottomFaceAndReorder( Proc, nAddGrpId, nFaceToDel)
-- copio la superfice nel gruppo ausiliario
local nNewProc = EgtCopyGlob( Proc.Id, nAddGrpId) or GDB_ID.NULL
EgtSurfTmRemoveFacet( nNewProc, nFaceToDel)
local nNumFacet = EgtSurfTmFacetCount( nNewProc)
ReorderFaces( nNewProc, nNumFacet)
return nNewProc, nNumFacet
end
---------------------------------------------------------------------
local function GetFacesExternalSide( Proc, vtExtr)
-- 3=sinistra, 4=destra
-- se meno di due facce considero esterno come dichiarato dal gruppo
local nNumFacet = EgtSurfTmFacetCount( Proc.Id)
if nNumFacet < 2 then return Proc.Grp end
-- se facce isolate, considero esterno come dichiarato dal gruppo
local bAdj, ptV1, ptV2, dAng = EgtSurfTmFacetsContact( Proc.Id, 0, 1, GDB_ID.ROOT)
if not bAdj then return Proc.Grp end
-- calcolo dell'esterno rispetto all'avanzamento
local ptC1, vtN1 = EgtSurfTmFacetCenter( Proc.Id, 0, GDB_ID.ROOT)
local ptV = ( ptV1 + ptV2) / 2
local vtDir1 = ptV - ptC1
if ( vtN1 ^ vtDir1) * vtExtr > 0 then
return 4
else
return 3
end
end
---------------------------------------------------------------------
local function GetFacesData( Proc, bOpposite, bCalclForBlade, dToolDiam, dToolMaxDepth, dToolThick, nAddGrpId, b3Raw, nMasterNewProc)
--se richiesto, copio la superficie nel gruppo ausiliario
local nNewProc
if nMasterNewProc then
nNewProc = nMasterNewProc
else
nNewProc = EgtCopyGlob( Proc.Id, nAddGrpId) or GDB_ID.NULL
end
-- recupero i dati di tutte le facce
local vFace = {}
local nNumFacet = EgtSurfTmFacetCount( nNewProc)
for i = 1, nNumFacet do
-- indice faccia corrente e precedente
local nFac = EgtIf( bOpposite, nNumFacet - i, i - 1)
local nPrecFac
if bOpposite then
if nNumFacet > 2 then
nPrecFac = EgtIf( i == 1, 0, nFac + 1)
else
nPrecFac = EgtIf( i == 1, -1, nFac + 1)
end
else
if nNumFacet > 2 then
nPrecFac = EgtIf( i == 1, nNumFacet - 1, i - 2)
else
nPrecFac = EgtIf( i == 1, - 1, i - 2)
end
end
-- recupero centro e normale della faccia
local vtN = EgtSurfTmFacetNormVersor( nNewProc, nFac, GDB_ID.ROOT)
-- recupero le dimensioni della faccia
local frHV, dLen, dWidth = WL.GetFaceHvRefDim( nNewProc, nFac)
-- recupero l'angolo con la faccia precedente
local bAdj, ptLocP1, ptLocP2, dAng = EgtSurfTmFacetsContact( nNewProc, nPrecFac, nFac, GDB_ID.ROOT)
local dPrevAng = EgtIf( bAdj, dAng, 0)
-- se angolo con faccia precedente negativo, calcolo anche angolo tra le facce nel piano
local dPlanePrevAng = 0
if dPrevAng < 0 then
local vtPrevN = EgtSurfTmFacetNormVersor( nNewProc, nPrecFac, GDB_ID.ROOT)
local dCosA = ( Z_AX() ^ vtPrevN) * ( Z_AX() ^ vtN)
dPlanePrevAng = -acos( dCosA)
end
-- calcolo l'angolo di inclinazione (dalla verticale)
local dSideAng = asin( vtN:getZ())
-- salvo i dati
vFace[i] = { Fac = nFac, Cen = frHV:getOrigin(), Norm = vtN, Len = dLen, Width = dWidth, PrevAng = dPrevAng, PlPrevAng = dPlanePrevAng, SideAng = dSideAng}
if bAdj then
if ptLocP1:getZ() < ptLocP2:getZ() then
vFace[i].PPrev = ptLocP1
else
vFace[i].PPrev = ptLocP2
end
end
end
-- analizzo le facce
local dMaxWidth = 0
for i = 1, #vFace do
-- aggiorno la massima larghezza
if vFace[i].Width > dMaxWidth then
dMaxWidth = vFace[i].Width
end
-- verifico l'affondamento
local dDepth = WD.CUT_EXTRA
if vFace[i].Width + WD.CUT_EXTRA > dToolMaxDepth then
dDepth = dToolMaxDepth - vFace[i].Width
end
-- lunghezza baffo
local dElev = vFace[i].Width + dDepth
local dWhisk = EgtIf( bCalclForBlade, ( dElev * sqrt( dToolDiam / dElev - 1) + WHISK_SAFE) , (dToolDiam/2) + WHISK_SAFE)
-- determino la lunghezza del taglio passante e il tipo di attacco e uscita
local dLen = vFace[i].Len
local dLenY = dLen * abs( vFace[i].Norm:getX()) / sqrt( 1 - vFace[i].Norm:getZ() * vFace[i].Norm:getZ())
local nType = 0
if vFace[i].PrevAng < -0.1 or
( WD.BEAM_MACHINE and not IsPointOnRawLongEdges( vFace[i].Cen, b3Raw) and ( dLen > 0.5 * WD.CUT_MAX_LENGTH or dLenY > 0.4 * b3Raw:getDimY())) then
dLen = dLen - EgtIf( bCalclForBlade, dWhisk, 0)
nType = nType + 1
end
if vFace[EgtIf( i < nNumFacet, i + 1, 1)].PrevAng < -0.1 or
( WD.BEAM_MACHINE and not IsPointOnRawLongEdges( vFace[i].Cen, b3Raw) and ( dLen > 0.5 * WD.CUT_MAX_LENGTH or dLenY > 0.4 * b3Raw:getDimY())) then
dLen = dLen - EgtIf( bCalclForBlade, dWhisk, 0)
nType = nType + 2
end
-- se lunghezza non significativa, non va inserito il taglio
if dLen < MIN_LEN_CUT then
nType = 4
end
-- numero dei lati
local nEdges = #(EgtSurfTmFacetAdjacencies( nNewProc, i - 1)[1])
-- assegno i nuovi dati
vFace[i].Depth = dDepth
vFace[i].Whisk = dWhisk
vFace[i].Type = nType
vFace[i].Edges = nEdges
end
-- recupero le regioni degli altri pezzi
local vOthers = GetOtherRegions( Proc.PartId)
-- verifico i baffi sporgenti dei tagli rispetto alle altre regioni
for i = 1, #vFace do
-- verifico il baffo iniziale
if vFace[i].Type ~= 4 and ( vFace[i].Type & 1) == 0 then
-- creo il rettangolo del baffo
local vtOrt = Vector3d( vFace[i].Norm:getX(), vFace[i].Norm:getY(), 0) ; vtOrt:normalize()
local vtDir = Vector3d( vtOrt) ; vtDir:rotate( Z_AX(), -90)
local vtUp = Vector3d( vtDir) ; vtUp:rotate( vFace[i].Norm, -90)
local ptIni = vFace[i].Cen + vFace[i].Width / 2 * vtUp + ( vFace[i].Len / 2 + WHISK_OFFS) * vtDir + WHISK_OFFS * vtOrt
local ptDir = ptIni + ( vFace[i].Whisk - 2 * WHISK_OFFS) * vtDir
local ptCross = ptDir + ( dToolThick - 2 * WHISK_OFFS) * vtOrt
local WhId = EgtSurfFrRectangle3P( nAddGrpId, ptIni, ptCross, ptDir, GDB_RT.GLOB)
local b3Wh = EgtGetBBoxGlob( WhId or GDB_ID.NULL, GDB_BB.STANDARD)
-- verifico se interferisce con gli altri pezzi
for j = 1, #vOthers do
if OverlapsXY( b3Wh, vOthers[j].Box) then
local nClass = EgtSurfFrChunkSimpleClassify( WhId, 0, vOthers[j].RegId, 0)
if nClass ~= GDB_RC.OUT then
local dLen = vFace[i].Len - vFace[i].Whisk + EgtIf( ( vFace[i].Type & 2) ~= 0, -vFace[i].Whisk, 0)
if dLen >= MIN_LEN_CUT then
vFace[i].Type = vFace[i].Type + 1
else
vFace[i].Type = 4
end
break
end
end
end
EgtErase( WhId)
end
-- verifico il baffo finale
if vFace[i].Type ~= 4 and ( vFace[i].Type & 2) == 0 then
-- creo il rettangolo del baffo
local vtOrt = Vector3d( vFace[i].Norm:getX(), vFace[i].Norm:getY(), 0) ; vtOrt:normalize()
local vtDir = Vector3d( vtOrt) ; vtDir:rotate( Z_AX(), 90)
local vtUp = Vector3d( vtDir) ; vtUp:rotate( vFace[i].Norm, 90)
local ptIni = vFace[i].Cen + vFace[i].Width / 2 * vtUp + ( vFace[i].Len / 2 + WHISK_OFFS) * vtDir + WHISK_OFFS * vtOrt
local ptDir = ptIni + ( vFace[i].Whisk - 2 * WHISK_OFFS) * vtDir
local ptCross = ptDir + ( dToolThick - 2 * WHISK_OFFS) * vtOrt
local WhId = EgtSurfFrRectangle3P( nAddGrpId, ptIni, ptCross, ptDir, GDB_RT.GLOB)
local b3Wh = EgtGetBBoxGlob( WhId or GDB_ID.NULL, GDB_BB.STANDARD)
-- verifico se interferisce con gli altri pezzi
for j = 1, #vOthers do
if OverlapsXY( b3Wh, vOthers[j].Box) then
local nClass = EgtSurfFrChunkSimpleClassify( WhId, 0, vOthers[j].RegId, 0)
if nClass ~= GDB_RC.OUT then
local dLen = vFace[i].Len - vFace[i].Whisk + EgtIf( ( vFace[i].Type & 1) ~= 0, -vFace[i].Whisk, 0)
if dLen >= MIN_LEN_CUT then
vFace[i].Type = vFace[i].Type + 2
else
vFace[i].Type = 4
end
break
end
end
end
EgtErase( WhId)
end
end
-- se ciclo chiuso
if abs( vFace[1].PrevAng) > 0.1 then
-- verifico se c'è un solo tipo 3 e nessun tipo 0, 1 o 2
local nInd3
local nTot3 = 0
local nTot012 = 0
for i = 1, #vFace do
local Face = vFace[i]
if Face.Type == 0 or Face.Type == 1 or Face.Type == 2 then
nTot012 = nTot012 + 1
elseif Face.Type == 3 then
nTot3 = nTot3 + 1
nInd3 = i
end
end
-- se trovato il caso, trasformo il 3 in 4 (per evitare problemi con fresature con la stessa faccia a inizio e fine)
if nTot3 == 1 and nTot012 == 0 then
vFace[nInd3].Type = 4
end
end
-- eventuali stampe
for i = 1, #vFace do
local Face = vFace[i]
local sOut = 'Face '..tostring( Face.Fac)..' C'..tostring( Face.Cen)..' N'..tostring( Face.Norm)..
' L='..EgtNumToString( Face.Len, 1)..' W='..EgtNumToString( Face.Width, 1)..' Ap='..EgtNumToString( Face.PrevAng, 1)..
' App='..EgtNumToString( Face.PlPrevAng, 1)..' D='..EgtNumToString( Face.Depth, 1)..' B='..EgtNumToString( Face.Whisk, 1)..
' As='..EgtNumToString( Face.SideAng, 1)..' T='..tostring( Face.Type)..' E='..tostring( Face.Edges)
EgtOutLog( sOut)
end
return vFace, dMaxWidth, nNewProc
end
---------------------------------------------------------------------
local function GetTunnelDimension( nId, nPartId, nAddGrpId)
-- sono necessarie almeno 2 facce
local nFacCnt = EgtSurfTmFacetCount( nId)
if nFacCnt < 2 then return end
-- recupero l'ingombro del pezzo
local b3Solid = EgtGetBBoxGlob( EgtGetFirstNameInGroup( nPartId, 'Box') or GDB_ID.NULL, GDB_BB.STANDARD)
-- recupero centro e normale delle facce
local ptC = {}
local vtN = {}
for i = 1, nFacCnt do
ptC[i], vtN[i] = EgtSurfTmFacetCenter( nId, i - 1, GDB_ID.ROOT)
end
-- determino l'asse medio (le facce sono già ordinate consecutivamente)
local vtAx = V_NULL()
for i = 1, nFacCnt do
local j = i % nFacCnt + 1
local vtOrtho = vtN[i] ^ vtN[j]
if vtOrtho:normalize() then
vtAx = vtAx + vtOrtho
end
end
if not vtAx:normalize() or abs( vtAx:getZ()) < 0.5 then return end
-- impongo come asse Z globale
vtAx = Z_AX()
-- recupero ingombro del tunnel nel riferimento globale
local b3Box = EgtGetBBoxGlob( nId, GDB_BB.STANDARD)
local dDepth = b3Box:getDimZ()
-- creo faccia in basso (di poco sollevata)
local nSurfInt = EgtSurfTmPlaneInBBox( nAddGrpId, b3Box:getMin() + 2 * GEO.EPS_SMALL * vtAx, vtAx, b3Solid, GDB_ID.ROOT)
if not nSurfInt then return end
-- ritaglio la superficie con le facce della fessura
for i = 1, nFacCnt do
local ptN, vtN = EgtSurfTmFacetCenter( nId, i - 1, GDB_ID.ROOT)
EgtCutSurfTmPlane( nSurfInt, ptN, -vtN, false, GDB_ID.ROOT)
end
-- sposto la geometria trovata sulla Z minima del pezzo
EgtMove( nSurfInt, -2 * GEO.EPS_SMALL * vtAx, GDB_RT.GLOB)
-- mi faccio dare il contorno della superfice e la ricreo in modo più corretto
local nIdCont, nIdNum = EgtExtractSurfTmLoops( nSurfInt, nAddGrpId)
if not nIdCont then return end
-- elimino le entità allineate dello stesso tipo
EgtMergeCurvesInCurveCompo( nIdCont, 2 * GEO.EPS_SMALL)
EgtErase( nSurfInt)
nSurfInt = EgtSurfTmByFlatContour( nAddGrpId, nIdCont, 2 * GEO.EPS_SMALL)
EgtErase(nIdCont)
-- ne recupero le dimensioni
local _, dDimMax, dDimMin = EgtSurfTmFacetMinAreaRectangle( nSurfInt, 0, GDB_ID.ROOT)
-- cerco faccia del contorno con lunghezza vicino alla massima
local nLongIdFace
for i = 1, nFacCnt do
local _, DimH, DimV = EgtSurfTmFacetMinAreaRectangle( nId, i - 1, GDB_ID.ROOT)
if DimH > dDimMax - 100 * GEO.EPS_SMALL then
nLongIdFace = i - 1
break
end
end
return dDimMin, dDimMax, dDepth, vtAx, nLongIdFace, nSurfInt
end
---------------------------------------------------------------------
local function ReorderFacesFromTab( nIdSurf, vFace)
local nFacCnt = EgtSurfTmFacetCount( nIdSurf)
for i = 1, #vFace do
for j = 1, nFacCnt do
-- ottengo punto iniziale e versore della faccia
local ptC, vtN = EgtSurfTmFacetCenter( nIdSurf, (j-1), GDB_ID.ROOT)
-- se versore e posizione coincidono e non corrispondono al numero faccia, faccio lo swap
if AreSameVectorExact( vFace[i].Norm, vtN) and AreSamePointEpsilon( vFace[i].Cen, ptC, 50*GEO.EPS_SMALL) then
if (j-1) ~= vFace[i].Fac then
EgtSurfTmSwapFacets( nIdSurf, vFace[i].Fac, (j-1))
end
break
end
end
end
return nIdSurf
end
---------------------------------------------------------------------
local function MakeCustomPath( vGeom, nConeCut, dMillDiam, nAddGrpId, dThick, bClosed)
local nPath = {}
local nPathData = {}
for i = 1, #vGeom do
local dAng
-- ottengo curva inferiore 1
local ptP1, ptP2, ptP3, vtV1, vtV2, dDim1, dDim2 = EgtSurfTmFacetOppositeSide( vGeom[i][1], vGeom[i][2], Z_AX() , GDB_ID.ROOT)
if i < #vGeom then
-- ricavo i punti e l'angolo interno
_, _, _, dAng = EgtSurfTmFacetsContact( vGeom[i][1], vGeom[i][2], vGeom[i+1][2], GDB_ID.ROOT)
elseif bClosed then
-- ricavo i punti e l'angolo interno
_, _, _, dAng = EgtSurfTmFacetsContact( vGeom[i][1], vGeom[i][2], vGeom[1][2], GDB_ID.ROOT)
else
dAng = 0
end
-- creo linea
local nId1 = EgtLine( nAddGrpId, ptP1, ptP3, GDB_RT.GLOB)
table.insert( nPath, nId1)
table.insert( nPathData, {nId1, dAng})
end
-- creo il percorso e poi lo offsetto del raggio utensile
local AuxId = EgtCurveCompo( nAddGrpId, nPath, true)
EgtOffsetCurve( AuxId, dMillDiam / 2, GDB_OT.EXTEND)
-- spezzo il percorso nelle entità componenti
local nId1st, nIdCount = EgtExplodeCurveCompo( AuxId)
-- se il numero entità è diverso da quelle iniziali esco con errore
if nIdCount ~= #vGeom then
local sErr = 'Error : cannot make offset path'
return 0, sErr
end
-- resetto la tabella
nPath = {}
AuxId = nil
-- in base al tipo di ripresa spigolo modifico il percorso
if nConeCut == 2 then
-- acquisisco la lunghezza utensile
sMilling, dMaxDepth = WM.FindMilling( 'CleanCorner30')
if not sMilling then
local sErr = 'Error : CleanCorner 30 not found in library'
return 0, sErr
end
-- recupero i dati dell'utensile
local dMillDiam = 20
local dMillLength = 0
if EgtMdbSetCurrMachining( sMilling) then
local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID)
if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then
dMillDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dMillDiam
dMillLength = EgtTdbGetCurrToolParam( MCH_TP.LEN) or dMillLength
end
end
-- calcolo la lunghezza della linea da inserire in base all'angolo e alla lunghezza utensile
local dLenAdd = abs(( dMillLength * sin( 33)) - ( dMillDiam / 2))
-- per ogni entità compongo la nuova lista per creare percorso
for i = 1, nIdCount do
-- aggiungo linea precedente
table.insert( nPath, ( nId1st + i - 1))
-- se non è la linea finale e l'angolo tra le due facce è ammesso
if ( i < nIdCount or bClosed) and dThick <= ( WD.MAX_CLEAN_CRN30 + 20 * GEO.EPS_SMALL) and
nPathData[i][2] < 0 and nPathData[i][2] > -( 180 - dAngleSmall + 10 * GEO.EPS_SMALL) then
-- aggiungo una retta sulla bisettrice
local _, vtN2 = EgtSurfTmFacetCenter( vGeom[i][1], vGeom[i][2], GDB_ID.ROOT)
local _, vtN3 = EgtSurfTmFacetCenter( vGeom[i][1], vGeom[EgtIf( i == nIdCount, 1, i+1)][2], GDB_ID.ROOT)
local ptP1 = EgtEP( ( nId1st + i - 1), GDB_ID.ROOT)
-- sommo i tre versori per avere una direzione media
local vtExtrExit = vtN2 + vtN3
vtExtrExit:normalize()
-- linea intermedia (componente lunghezza utensile in direzione bisettrice)
local pEnd = ptP1 + ( dLenAdd * vtExtrExit)
nAuxId = EgtLine( nAddGrpId, ptP1, pEnd, GDB_RT.GLOB)
table.insert( nPath, nAuxId)
-- linea di ritorno
nAuxId = EgtLine( nAddGrpId, pEnd, ptP1, GDB_RT.GLOB)
table.insert( nPath, nAuxId)
end
end
-- ricreo il percorso
AuxId = EgtCurveCompo( nAddGrpId, nPath, true)
-- altrimenti sfondo spigolo
elseif nConeCut == 3 then
-- per ogni entità compongo la nuova lista per creare percorso
for i = 1, nIdCount do
-- aggiungo linea precedente
table.insert( nPath, ( nId1st + i - 1))
-- se non è la linea finale e l'angolo tra le due facce è ammesso
if ( i < nIdCount or bClosed) and nPathData[i][2] < 0 then
-- aggiungo una retta sulla bisettrice
local _, vtN2 = EgtSurfTmFacetCenter( vGeom[i][1], vGeom[i][2], GDB_ID.ROOT)
local _, vtN3 = EgtSurfTmFacetCenter( vGeom[i][1], vGeom[EgtIf( i == nIdCount, 1, i+1)][2], GDB_ID.ROOT)
local ptP1 = EgtEP( ( nId1st + i - 1), GDB_ID.ROOT)
-- sommo i tre versori per avere una direzione media
local vtExtrExit = vtN2 + vtN3
vtExtrExit:normalize()
vtExtrExit = -vtExtrExit
-- calcolo di quanto entrare
local dLenAdd = abs( (dMillDiam/2) / cos( nPathData[i][2]/2)) + dExtraCorner - (dMillDiam/2)
-- linea intermedia (componente lunghezza utensile in direzione bisettrice)
local pEnd = ptP1 + ( dLenAdd * vtExtrExit)
nAuxId = EgtLine( nAddGrpId, ptP1, pEnd, GDB_RT.GLOB)
table.insert( nPath, nAuxId)
-- linea di ritorno
nAuxId = EgtLine( nAddGrpId, pEnd, ptP1, GDB_RT.GLOB)
table.insert( nPath, nAuxId)
end
end
-- ricreo il percorso
AuxId = EgtCurveCompo( nAddGrpId, nPath, true)
end
if not AuxId then
local sErr = 'Error : Impossibe make custom machining path'
return 0, sErr
end
return AuxId
end
---------------------------------------------------------------------
local function CalcInterference( nNewProc, vtExtr, ptCentr, dDiam1, dDiam2,
dTall1, dTall2, dDiam3, dTall3)
local ptCentrGrid1 = ptCentr + ( vtExtr * 0.01)
local frOriTool = Frame3d( ptCentrGrid1, vtExtr)
local bColl1 = EgtCDeConeSolid( frOriTool, dDiam1/2, dDiam2/2, dTall1, nNewProc, 0, GDB_RT.GLOB)
if bColl1 then return true end
local ptCentrGrid2 = ptCentr + ( vtExtr * ( dTall1 + 0.01))
frOriTool = Frame3d( ptCentrGrid2, vtExtr)
local bColl2 = EgtCDeCylSolid( frOriTool, dDiam2/2, (dTall2-dTall1), nNewProc, 0, GDB_RT.GLOB)
if bColl2 then return true end
local ptCentrGrid3 = ptCentr + ( vtExtr * ( dTall2 + 0.01))
frOriTool = Frame3d( ptCentrGrid3, vtExtr)
local bColl3 = EgtCDeCylSolid( frOriTool, dDiam3/2, (dTall3-dTall2), nNewProc, 0, GDB_RT.GLOB)
if bColl3 then return true end
-- restituisco risultato controllo collisioni
return false
end
---------------------------------------------------------------------
local function MakeLocalSurf( ptP1, ptP2, ptP3, nAddGrpId)
-- verifico che i tre punti siano definiti
if not ptP1 or not ptP2 or not ptP3 then
return nil
end
-- creo il contorno
local nLoopId = EgtCurveCompoFromPoints( nAddGrpId, { ptP1, ptP2, ptP3, ptP1}, GDB_RT.GLOB)
if not nLoopId then
return nil
end
-- creo la superfice triangolare (quindi piana)
local nFaceId = EgtSurfTmByFlatContour( nAddGrpId, nLoopId, 0.01)
EgtErase( nLoopId)
if not nFaceId then
return nil
end
-- se normale negativa inverto
local vtN1 = EgtSurfTmFacetNormVersor( nFaceId, 0, GDB_ID.ROOT)
if vtN1:getZ() < -0.01 then
EgtInvertSurf( nFaceId)
end
return nFaceId
end
---------------------------------------------------------------------
local function AddMillCornerMachining( nPartId, nNewProc, nFacInd, tFacAdj, nTypeConeCut, nAddGrpId,
dToolDiam, dThick, sMilling, dOffsAng, dDepthMach,
bThruThick, dThSurf, dDiam1, dDiam2, dTall1,
dTall2, dDiam3, dTall3, bMakeLocSurf, vFace)
-- variabili costruzione geometria
local pAuxId = {}
local nAuxId
local ptApPoint
local AuxId
local nNewProcLoc
-- se devo creare superfice locale
if bMakeLocSurf then
-- creo superfice locale o esco
local nSurfToAdd = MakeLocalSurf( tFacAdj[7], tFacAdj[8], tFacAdj[9], nAddGrpId)
if nSurfToAdd then
local nFacCntPre = EgtSurfTmFacetCount( nNewProc)
-- creo copia del percorso principale e gli aggiungo la nuova faccia
nNewProcLoc = EgtCopyGlob( nNewProc, nAddGrpId)
nNewProcLoc = EgtSurfTmBySewing( nAddGrpId, {nNewProcLoc,nSurfToAdd} , true)
-- riordino le facce
ReorderFacesFromTab( nNewProcLoc, vFace)
-- acquisisco il numero della faccia
nFacCnt = EgtSurfTmFacetCount( nNewProcLoc)
nFacInd = nFacCnt - 1
else
return true, ''
end
else
nNewProcLoc = nNewProc
end
-- prendo il primo versore
local _, vtN1 = EgtSurfTmFacetCenter( nNewProcLoc, nFacInd, GDB_ID.ROOT)
local _, vtN2 = EgtSurfTmFacetCenter( nNewProcLoc, tFacAdj[1], GDB_ID.ROOT)
local _, vtN3 = EgtSurfTmFacetCenter( nNewProcLoc, tFacAdj[2], GDB_ID.ROOT)
-- trovo il punto sulla superfice di riferimento
local _, ptLocP1, ptLocP2, _ = EgtSurfTmFacetsContact( nNewProcLoc, nFacInd, tFacAdj[1], GDB_ID.ROOT)
local _, ptLocP3, ptLocP4, _ = EgtSurfTmFacetsContact( nNewProcLoc, nFacInd, tFacAdj[2], GDB_ID.ROOT)
-- se ho creato faccia locale su copia superficie, cancella la copia
if bMakeLocSurf then
EgtErase( nNewProcLoc)
end
if not ptLocP1 or not ptLocP2 then
return false, 'Error : clean corner with non adjacent faces'
end
local nIdIniPoint
local nIdEndPoint
if ptLocP1 and ptLocP2 then
if ( dist( ptLocP1, tFacAdj[4]) < GEO.EPS_SMALL) or ( dist( ptLocP2, tFacAdj[4]) < GEO.EPS_SMALL) then
nIdEndPoint = 4
nIdIniPoint = 5
elseif ( dist( ptLocP1, tFacAdj[5]) < GEO.EPS_SMALL) or ( dist( ptLocP2, tFacAdj[5]) < GEO.EPS_SMALL) then
nIdEndPoint = 5
nIdIniPoint = 4
end
end
-- versore direzione
local vtExtr = tFacAdj[nIdIniPoint] - tFacAdj[nIdEndPoint]
vtExtr:normalize()
-- versore direzione di uscita
local vtExtrExit
-- inserisco le prime tre linee
if nIdIniPoint and nIdEndPoint then
-- se fresatura da sotto salto la lavorazione
if vtExtr:getZ() < WD.DRILL_VZ_MIN then
local sErr = 'Error : Impossible insert clean corner from bottom'
EgtOutLog( sErr)
return false, sErr
end
-- sommo i tre versori per avere una direzione media
vtExtrExit = vtN2 + vtN3
vtExtrExit:normalize()
-- se tipo 1 calcolo angolo tilt di 45°
if nTypeConeCut == 1 then
vtExtr = vtExtrExit + Z_AX()
-- altrimenti tipo 2, calcolo angolo tilt di 33° (dalla verticale)
else
vtExtr = vtExtrExit + Vector3d(0,0,1.539865)
end
vtExtr:normalize()
local vtCheck = Vector3d(vtExtr)
-- se ho un offset angolare ruoto il percorso
if abs(dOffsAng) > 100 * GEO.EPS_SMALL then
vtCheck:rotate( Z_AX(), dOffsAng)
end
-- controllo se c'è collisione con le facce della superfice
if nTypeConeCut == 1 and CalcInterference( nNewProc, vtCheck, tFacAdj[nIdEndPoint] + Point3d( 0, 0, -dDepthMach), dDiam1, dDiam2,
dTall1, dTall2, dDiam3, dTall3) then
local sErr = 'Collision detect from clean corner tool and surface'
EgtOutLog( sErr)
return true, ''
end
nAuxId = EgtLine( nAddGrpId, tFacAdj[nIdIniPoint], tFacAdj[nIdEndPoint] + Point3d( 0, 0, -dDepthMach), GDB_RT.GLOB)
table.insert( pAuxId, nAuxId)
-- se uso utensile cono 60°
if nTypeConeCut == 1 then
-- se offset angolare valido e/o negativo creo il baffo precedente
if dOffsAng < ( 100 * GEO.EPS_SMALL) then
-- se il punto finale corrisponde con il punto utilizzato in precedenza, uso l'altro
if dist( tFacAdj[nIdEndPoint], ptLocP1) < 10 * GEO.EPS_SMALL then
ptApPoint = ptLocP2
else
ptApPoint = ptLocP1
end
nAuxId = EgtLine( nAddGrpId, tFacAdj[nIdEndPoint] + Point3d( 0, 0, -dDepthMach), ptApPoint + Point3d( 0, 0, -dDepthMach), GDB_RT.GLOB)
local dLenTrimExt = dist( tFacAdj[nIdEndPoint], ptApPoint) - (( dToolDiam/2) + 0.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 + Point3d( 0, 0, -dDepthMach), GDB_RT.GLOB)
-- se ho l'offset angolare ruoto la linea per compensare la rotazione che verrà applicata
if abs(dOffsAng) > 100 * GEO.EPS_SMALL then
EgtRotate( nAuxId, tFacAdj[nIdEndPoint], Z_AX(), -dOffsAng, GDB_RT.GLOB)
end
-- prendo il nuovo punto finale
ptApPoint = EgtEP( nAuxId, GDB_RT.GLOB) + Point3d( 0, 0, dDepthMach)
else
-- se ho l'offset angolare ruoto la linea per compensare la rotazione che verrà applicata
if abs(dOffsAng) > 100 * GEO.EPS_SMALL then
EgtRotate( nAuxId, tFacAdj[nIdEndPoint], Z_AX(), -dOffsAng, GDB_RT.GLOB)
end
end
table.insert( pAuxId, nAuxId)
-- creo linea di ritorno
nAuxId = EgtLine( nAddGrpId, ptApPoint + Point3d( 0, 0, -dDepthMach), tFacAdj[nIdEndPoint] + Point3d( 0, 0, -dDepthMach), GDB_RT.GLOB)
table.insert( pAuxId, nAuxId)
end
end
end
-- inserisco le ultime tre linee
-- trovo il secondo punto sulla superfice di riferimento
ptLocP1, ptLocP2 = ptLocP3, ptLocP4
if ptLocP1 and ptLocP2 then
-- se il punto finale corrisponde con il punto utilizzato in precedenza, uso l'altro
if dist( tFacAdj[nIdEndPoint], ptLocP1) < 10 * GEO.EPS_SMALL then
ptApPoint = ptLocP2
else
ptApPoint = ptLocP1
end
-- se uso utensile cono 60°
if nTypeConeCut == 1 then
-- se offset angolare valido e/o negativo creo il baffo precedente
if dOffsAng > -( 100 * GEO.EPS_SMALL) then
nAuxId = EgtLine( nAddGrpId, tFacAdj[nIdEndPoint] + Point3d( 0, 0, -dDepthMach), ptApPoint + Point3d( 0, 0, -dDepthMach), GDB_RT.GLOB)
local dLenTrimExt = dist( tFacAdj[nIdEndPoint], ptApPoint) - (( dToolDiam/2) + 0.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 + Point3d( 0, 0, -dDepthMach), GDB_RT.GLOB)
-- se ho l'offset angolare ruoto la linea per compensare la rotazione che verrà applicata
if abs(dOffsAng) > 100 * GEO.EPS_SMALL then
EgtRotate( nAuxId, tFacAdj[nIdEndPoint], Z_AX(), -dOffsAng, GDB_RT.GLOB)
end
-- prendo il nuovo punto finale
ptApPoint = EgtEP( nAuxId, GDB_RT.GLOB) + Point3d( 0, 0, dDepthMach)
else
-- se ho l'offset angolare ruoto la linea per compensare la rotazione che verrà applicata
if abs(dOffsAng) > 100 * GEO.EPS_SMALL then
EgtRotate( nAuxId, tFacAdj[nIdEndPoint], Z_AX(), -dOffsAng, GDB_RT.GLOB)
end
end
table.insert( pAuxId, nAuxId)
-- creo linea di ritorno
nAuxId = EgtLine( nAddGrpId, ptApPoint + Point3d( 0, 0, -dDepthMach), tFacAdj[nIdEndPoint] + Point3d( 0, 0, -dDepthMach), GDB_RT.GLOB)
table.insert( pAuxId, nAuxId)
end
-- ultima linea di distacco (5mm in direzione utensile)
local pEnd = tFacAdj[nIdEndPoint] + Point3d( 0, 0, -dDepthMach) + ( 5 * vtExtr)
nAuxId = EgtLine( nAddGrpId, tFacAdj[nIdEndPoint] + Point3d( 0, 0, -dDepthMach), pEnd, GDB_RT.GLOB)
table.insert( pAuxId, nAuxId)
else
-- linea di distacco (2mm in direzione utensile)
local pEnd = tFacAdj[nIdEndPoint] + ( 2 * vtExtr)
nAuxId = EgtLine( nAddGrpId, tFacAdj[nIdEndPoint], pEnd, GDB_RT.GLOB)
table.insert( pAuxId, nAuxId)
-- ultima linea di risalita in Z
local pIni = pEnd
pEnd = pIni + ( dThick * Z_AX())
nAuxId = EgtLine( nAddGrpId, pIni, pEnd, GDB_RT.GLOB)
table.insert( pAuxId, nAuxId)
end
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)
-- se ho un offset angolare ruoto il percorso
if abs(dOffsAng) > 100 * GEO.EPS_SMALL then
EgtRotate( AuxId, tFacAdj[nIdEndPoint], Z_AX(), dOffsAng, GDB_RT.GLOB)
end
-- inserisco la lavorazione
local sName = 'Clean_' .. ( EgtGetName( nNewProc) or tostring( nNewProc))
local nMchId = WM.AddMachining( nNewProc, sName, sMilling)
if not nMchId then
local sErr = 'Error adding machining ' .. sName .. '-' .. sMilling
EgtOutLog( sErr)
return false, sErr
end
EgtSetInfo( nMchId, 'Part', nPartId)
-- se flag lavorazione spessore passante setto la nota per spostarla dopo i tagli di lama
if bThruThick and nTypeConeCut == 1 then
EgtSetInfo( nMchId, 'MOVE_AFTER', 1)
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)
EgtSetMachiningParam( MCH_MP.LEADINTYPE, 0)
EgtSetMachiningParam( MCH_MP.LEADOUTTYPE, 4)
-- allungo inizio e fine di 10mm
EgtSetMachiningParam( MCH_MP.STARTADDLEN, 10)
EgtSetMachiningParam( MCH_MP.ENDADDLEN, 10)
-- setto affondamento 0
EgtSetMachiningParam( MCH_MP.DEPTH, 0)
-- forzo lato correzione a centrato
EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.CENTER)
-- Note utente con dichiarazione nessuna generazione sfridi per Vmill
local sUserNotes = 'VMRS=0;'
-- aggiungo alle note massima elevazione
sUserNotes = sUserNotes .. 'MaxElev=' .. EgtNumToString( 0.0, 1) .. ';'
EgtSetMachiningParam( MCH_MP.USERNOTES, sUserNotes)
if not EgtApplyMachining( 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
end
end
return true, ''
end
---------------------------------------------------------------------
local function AddMillCorner( nTypeConeCut, vFace, Proc, nRawId, b3Raw,
dToolDiam, nAddGrpId, dThick, nMasterNewProc, dDepthMach,
bThruThick)
local sMilling, dMaxDepth
-- se ripresa angolo con fresa cono 60° con ripresa
if nTypeConeCut == 1 then
-- recupero la lavorazione di fresatura
sMilling, dMaxDepth = WM.FindMilling( 'CleanCorner60')
if not sMilling then
local sErr = 'Error : CleanCorner 60 not found in library'
EgtOutLog( sErr)
return false, sErr
end
-- se ripresa angolo con fresa cono piccola senza ripresa
else
sMilling, dMaxDepth = WM.FindMilling( 'CleanCorner30')
if not sMilling then
local sErr = 'Error : CleanCorner 30 not found in library'
EgtOutLog( sErr)
return false, sErr
end
end
-- recupero i dati dell'utensile
local dMillDiam = 20
local dMillTotDiam = 20
local dMillDiamTh = 20
local dToolLength = 20
local dThickTool = 20
local dSideAng = 0
if EgtMdbSetCurrMachining( sMilling) then
local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID)
if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then
dMillDiamTh = EgtTdbGetCurrToolThDiam() or dMillDiamTh
dMillTotDiam = EgtTdbGetCurrToolParam( MCH_TP.TOTDIAM) or dMillTotDiam
dSideAng = EgtTdbGetCurrToolParam( MCH_TP.SIDEANG) or dSideAng
dMillDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dMillDiam
dThickTool = EgtTdbGetCurrToolParam( MCH_TP.THICK) or dThickTool
dToolLength = EgtTdbGetCurrToolParam( MCH_TP.LEN) or dToolLength
dMaxDepth = EgtTdbGetCurrToolMaxDepth() or dMaxDepth -- qui è la distanza dal portautensile
-- calcolo il secondo diametro del cono
dMillTotDiam = dMillDiam + ( abs( dThickTool) * tan( dSideAng)) * 2
end
end
-- copio la feature nel layer di appoggio
local nNewProc
if nMasterNewProc then
nNewProc = nMasterNewProc
else
nNewProc = EgtCopyGlob( Proc.Id, nAddGrpId) or GDB_ID.NULL
end
local nFacCnt = EgtSurfTmFacetCount( nNewProc)
local nFacInd, dDepth, nSurfInt
local bMakeLocSurf
if nFacCnt <= 4 then
-- recupero profondità e faccia di fondo
_, _, dDepth, _, _, nSurfInt = GetTunnelDimension( nNewProc, Proc.PartId, nAddGrpId)
if nSurfInt then
-- aggiungo la faccia di fondo appena calcolata
nNewProc = EgtSurfTmBySewing( nAddGrpId, { nNewProc, nSurfInt}, true)
-- riordino le facce
ReorderFacesFromTab( nNewProc, vFace)
-- aggiorno numero di facce e assegno indice di quella di fondo (sempre ultima)
nFacCnt = EgtSurfTmFacetCount( nNewProc)
nFacInd = nFacCnt - 1
else
return true
end
else
bMakeLocSurf = true
end
-- verifico se ciclo chiuso
local bClosed = ( abs( vFace[1].PrevAng) > 0.1)
-- ciclo di inserimento delle fresate sulle facce del contorno in esame
local i = 1
-- se faccia finale con fine non lavorato, forzo partenza da prima faccia non tutta saltata (tipo 4)
if bClosed and ( vFace[#vFace].Type == 4 or ( vFace[#vFace].Type & 2) ~= 0) then
while i <= #vFace and vFace[i].Type == 4 do
i = i + 1
end
end
-- se facce tutte da saltare, parto dall'inizio
local bAllType4 = ( i > #vFace)
if bAllType4 or bClosed then i = 1 end
while i <= #vFace do
-- se tutta la faccia o la sua fine senza taglio, inserisco una fresatura
if ( vFace[i].Type & 2) ~= 0 or vFace[i].Type == 4 then
-- variabili costruzione geometria (nface1, nFace2, tFacAdj)
local nFace1 = vFace[i].Fac
-- ricavo i tre punti per eventuale superficie locale
local ptLoc1, ptLoc2, ptLoc3
-- punto precedente (punto precedente della faccia [i])
ptLoc3 = vFace[i].PPrev
-- aggiungo geometria
i = i + 1
local j = EgtIf( i <= #vFace, i, EgtIf( bClosed, 1, nil))
if not j then
return true
end
local nFace2 = vFace[j].Fac
-- punto in comune tra le due facce (punto precedente della faccia [j])
ptLoc1 = vFace[j].PPrev
-- punto successivo ( precedente della faccia successiva)
j = j + 1
local k = EgtIf( j <= #vFace, j, EgtIf( bClosed, 1, nil))
-- se è un percorso aperto prendo il punto medio della seconda faccia come punto locale 2
if not k then
ptLoc2 = Point3d( vFace[j-1].Cen:getX(), vFace[j-1].Cen:getY(), ptLoc1:getZ())
else
ptLoc2 = vFace[k].PPrev
end
-- ricavo i punti e l'angolo interno
local _, ptP1, ptP2, dAng = EgtSurfTmFacetsContact( nNewProc, nFace1, nFace2, GDB_ID.ROOT)
-- se punti validi e angolo è interno e non è quasi piatto e >= 90 creo istanza
local tFacAdj = {}
if ptP1 and ptP2 and dAng < 0 and dAng < -6 and dAng > EgtIf( nTypeConeCut == 1, -(90 + 10 * GEO.EPS_SMALL), -(180-dAngleSmall + 10 * GEO.EPS_SMALL)) then
local dLen = dist( ptP1, ptP2)
tFacAdj = { nFace1, nFace2, dLen, ptP1, ptP2, dAng, ptLoc1, ptLoc2, ptLoc3}
end
-- se ho un elemento creo percorso o percorsi in base al tipo di cono e all'apertura dall'angolo rispetto ai 90°
-- con una tolleranza di 2 gradi
if #tFacAdj > 0 then
if nTypeConeCut == 1 and bMakeTwinCut and (dAng + 90) > 2 then
local dAngOffs = (dAng + 90) / 2
-- primo taglio
local bOk, sErr = AddMillCornerMachining( Proc.PartId, nNewProc, nFacInd, tFacAdj, nTypeConeCut, nAddGrpId,
dToolDiam, dThick, sMilling, -dAngOffs, dDepthMach,
bThruThick, dDepth, dMillDiam, dMillTotDiam, abs(dThickTool),
dMaxDepth, dMillDiamTh, dToolLength, bMakeLocSurf, vFace)
if not bOk then return bOk, sErr end
-- secondo taglio
bOk, sErr = AddMillCornerMachining( Proc.PartId, nNewProc, nFacInd, tFacAdj, nTypeConeCut, nAddGrpId,
dToolDiam, dThick, sMilling, dAngOffs, dDepthMach,
bThruThick, dDepth, dMillDiam, dMillTotDiam, abs(dThickTool),
dMaxDepth, dMillDiamTh, dToolLength, bMakeLocSurf, vFace)
if not bOk then return bOk, sErr end
-- altrimenti ho un solo percorso
else
local bOk, sErr = AddMillCornerMachining( Proc.PartId, nNewProc, nFacInd, tFacAdj, nTypeConeCut, nAddGrpId,
dToolDiam, dThick, sMilling, 0, dDepthMach,
bThruThick, dDepth, dMillDiam, dMillTotDiam, abs(dThickTool),
dMaxDepth, dMillDiamTh, dToolLength, bMakeLocSurf, vFace)
if not bOk then return bOk, sErr end
end
end
else
i = i + 1
end
end
-- cancello la copia della superfice
if nNewProc then
EgtErase( nNewProc)
end
return true
end
---------------------------------------------------------------------
local function GetMaxDepth( vtNz, dMillDiam, dDiamTh, dMaxDepth, dFreeLen)
local CosA = abs( vtNz)
if CosA >= 0.05 then
local SinA = sqrt( 1 - CosA * CosA)
local dRad = dDiamTh / 2 + dMillDiam / 2 * EgtIf( vtNz > 0, -1, 1)
local dSlantFreeLen = dFreeLen - ( dRad * CosA / SinA)
return min( dMaxDepth, dSlantFreeLen)
else
return dMaxDepth
end
end
---------------------------------------------------------------------
-- Funzione per determinare se la faccia ha lati molto corti (trascurabili) ed è quindi approssimabile ad una 3 facce
local function Is3EdgesApprox( Proc, nFacet, nAddGrpId)
local bResult = false
local nContourId = EgtExtractSurfTmFacetLoops( Proc.Id, nFacet, nAddGrpId)
EgtMergeCurvesInCurveCompo( nContourId)
-- recupero il numero effettivo di lati
local _, nEntityCount = EgtCurveDomain( nContourId)
local nEdges = nEntityCount
if nContourId then
if nEntityCount and nEntityCount == 3 then
bResult = true
-- rimuovo i lati molto corti dal conteggio totale
elseif nEntityCount then
for i = 1, nEntityCount do
local dLength = EgtCurveCompoLength( nContourId, i - 1)
if dLength < 15 then nEdges = nEdges - 1 end
end
end
if nEdges == 3 then bResult = true end
end
if bResult == true then
EgtOutLog( 'FreeContour : Face with ' .. tointeger( nEntityCount) .. ' edges skipped (approx 3 edges)')
end
return bResult
end
---------------------------------------------------------------------
local function AddMillings( sMilling, vFace, Proc, nRawId, b3Raw, nConeCut, nAddGrpId)
-- flag per fresature non passanti
local bNotThrou
local dThick
local dOriDepth
-- recupero i dati dell'utensile
local dMillDiam = 20
local dMaxDepth = 0
local dFreeLen = 0
local dDiamTh = 0
if EgtMdbSetCurrMachining( sMilling) then
local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID)
if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then
dMillDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dMillDiam
dDiamTh = EgtTdbGetCurrToolThDiam()
dFreeLen = EgtTdbGetCurrToolMaxDepth()
dMaxDepth = EgtIf( WD.MILL_MAX_DEPTH_AS_MAT, EgtTdbGetCurrToolParam( MCH_TP.MAXMAT), dFreeLen) or dMaxDepth
end
end
-- verifico se la facce hanno alcuni lati molto corti e possono quindi essere approssimate a 3 lati
for currentFace = 1, #vFace do
if Is3EdgesApprox( Proc, vFace[currentFace].Fac, nAddGrpId) then
vFace[currentFace].Is3EdgesApprox = true
end
end
-- verifico se ciclo chiuso
local bClosed = ( abs( vFace[1].PrevAng) > 0.1)
-- ciclo di inserimento delle fresate sulle facce del contorno in esame
local i = 1
-- se faccia finale con fine non lavorato, forzo partenza da prima faccia non tutta saltata (tipo 4)
if bClosed and ( ( vFace[#vFace].Type == 4 and ( vFace[#vFace].Edges > 3 and not vFace[#vFace].Is3EdgesApprox)) or ( vFace[#vFace].Type & 2) ~= 0) then
while i <= #vFace and vFace[i].Type == 4 and ( vFace[i].Edges > 3 and not vFace[i].Is3EdgesApprox) and abs( vFace[i].SideAng) < 0.1 do
i = i + 1
end
end
-- se facce tutte da saltare, parto dall'inizio
local bAllType4 = ( i > #vFace)
if bAllType4 then i = 1 end
while i <= #vFace do
-- se inizio faccia senza taglio e non è successiva di senza taglio, inserisco una fresatura
local j = EgtIf( i > 1, i - 1, EgtIf( bClosed, #vFace, nil))
if ( vFace[i].Type & 1) ~= 0 and ( not j or vFace[j].Type == 0 or vFace[j].Type == 1 or abs( vFace[i].SideAng) > 0.1 or abs( vFace[j].SideAng) > 0.1) then
-- inserisco la lavorazione
local sName = 'Free_' .. ( EgtGetName( Proc.PartId) or tostring( Proc.PartId))
local nMchId = WM.AddMachining( Proc, sName, sMilling)
if not nMchId then
local sErr = 'Error adding machining ' .. sName .. '-' .. sMilling
EgtOutLog( sErr)
return 0, sErr
end
EgtSetInfo( nMchId, 'Part', Proc.PartId)
-- calcolo l'affondamento
local dDepth = vFace[i].Width + WD.CUT_EXTRA
dThick = vFace[i].Width
local vtNz = vFace[i].Norm:getZ()
if WD.CHECK_MIN_Z_SAW then
if vtNz >= 0 then
dDepth = min( dDepth, vFace[i].Width - WD.MIN_Z_SAW)
else
dDepth = min( dDepth, dDepth - WD.MIN_Z_SAW + dMillDiam * vtNz / sqrt( 1 - vtNz * vtNz))
end
end
local dCurrMaxDepth = GetMaxDepth( vtNz, dMillDiam, dDiamTh, dMaxDepth, dFreeLen)
-- se affondamento superiore ai limiti della fresa
if dDepth > dCurrMaxDepth then
dOriDepth = dDepth
-- lo limito e tolgo eventuali Tabs
dDepth = dCurrMaxDepth
EgtSetMachiningParam( MCH_MP.LEAVETAB, false)
bNotThrou = true
end
-- tolgo i Tabs se devo rimuovere lo sfrido
if nConeCut == 1 then EgtSetMachiningParam( MCH_MP.LEAVETAB, false) end
-- aggiungo geometria
EgtSetMachiningGeometry( {{ Proc.Id, vFace[i].Fac}})
local dSal = 0
if #vFace == 1 then dSal = -dMillDiam / 2 end
-- se angolo interno prima
if vFace[i].PrevAng < -30 then
local dSinA = -sin( vFace[i].PlPrevAng + 90)
local dTanA = -tan( vFace[i].PlPrevAng + 90)
dSal = -dMillDiam / 2 * ( 1 + ( 1 + dSinA) * dTanA) + min( 0, vFace[i].Width * vFace[i].Norm:getZ() * dTanA)
-- se faccia precedente inclinata verso il basso
if j and vFace[j].Norm:getZ() < -0.017 then
dSal = dSal + vFace[j].Width * vFace[j].Norm:getZ()
end
-- se angolo esterno prima
elseif vFace[i].PrevAng > 30 then
-- se faccia precedente inclinata verso il basso
if j and vFace[j].Norm:getZ() < -0.017 then
dSal = dSal - vFace[j].Width * vFace[j].Norm:getZ()
end
end
local dEal = vFace[i].Whisk - vFace[i].Len
-- se faccia precedente inclinata verso il basso prolungo il finale per adeguarmi all percorso della lama
if j and vFace[j].Norm:getZ() < -0.017 then
dEal = dEal - vFace[j].Width * vFace[j].Norm:getZ()
end
-- se angolo interno prima e faccia precedente inclinata verso l'alto oltre 16.1deg
if vFace[i].PrevAng < -30 and j and vFace[j].Norm:getZ() < 0.96078 and vFace[j].Norm:getZ() > 0 then
dEal = dEal + vFace[j].Width * vFace[j].Norm:getZ()
end
-- se angolo interno dopo e faccia successiva inclinata verso l'alto oltre 16.1deg
local k = EgtIf( i < #vFace, i + 1, EgtIf( bClosed, 1, nil))
if k and vFace[k].PrevAng < -30 and vFace[k].Norm:getZ() < 0.96078 and vFace[k].Norm:getZ() > 0 then
dEal = dEal + vFace[k].Width * vFace[k].Norm:getZ()
-- se l'inclinazione è inferiore a 46.1deg
if vFace[k].Norm:getZ() > 0.72055 then
dEal = dEal - vFace[k].Width
end
end
EgtSetMachiningParam( MCH_MP.STARTADDLEN, dSal)
EgtSetMachiningParam( MCH_MP.ENDADDLEN, dEal)
-- percorso da non invertire
EgtSetMachiningParam( MCH_MP.INVERT, false)
-- assegno utilizzo faccia
EgtSetMachiningParam( MCH_MP.FACEUSE, MCH_MILL_FU.PARAL_DOWN)
-- assegno affondamento
EgtSetMachiningParam( MCH_MP.DEPTH, dDepth)
-- assegno lato di lavoro
EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.RIGHT)
-- posizione braccio porta testa
local nSCC = MCH_SCC.ADIR_ZP
if abs( vFace[i].Norm:getZ()) < GEO.EPS_SMALL then
nSCC = EgtIf( abs( vFace[i].Norm:getX()) > abs( vFace[i].Norm:getY()), MCH_SCC.ADIR_XP, MCH_SCC.ADIR_YP)
end
EgtSetMachiningParam( MCH_MP.SCC, nSCC)
-- eseguo
if not EgtApplyMachining( true, false) then
local _, sErr = EgtGetLastMachMgrError()
EgtSetOperationMode( nMchId, false)
return 0, sErr
end
end
-- se tutta la faccia o la sua fine senza taglio, inserisco una fresatura
if ( vFace[i].Type & 2) ~= 0 or ( vFace[i].Type == 4 and ( vFace[i].Edges > 3 and not vFace[i].Is3EdgesApprox)) then
-- inserisco la lavorazione
local sName = 'Free_' .. ( EgtGetName( Proc.PartId) or tostring( Proc.PartId))
local nMchId = WM.AddMachining( Proc, sName, sMilling)
if not nMchId then
local sErr = 'Error adding machining ' .. sName .. '-' .. sMilling
EgtOutLog( sErr)
return 0, sErr
end
EgtSetInfo( nMchId, 'Part', Proc.PartId)
-- calcolo l'affondamento
local dDepth = vFace[i].Width + WD.CUT_EXTRA
dThick = vFace[i].Width
local vtNz = vFace[i].Norm:getZ()
if WD.CHECK_MIN_Z_SAW then
if vtNz >= 0 then
dDepth = min( dDepth, vFace[i].Width - WD.MIN_Z_SAW)
else
dDepth = min( dDepth, dDepth - WD.MIN_Z_SAW + dMillDiam * vtNz / sqrt( 1 - vtNz * vtNz))
end
end
local dCurrMaxDepth = GetMaxDepth( vtNz, dMillDiam, dDiamTh, dMaxDepth, dFreeLen)
-- se affondamento superiore ai limiti della fresa
if dDepth > dCurrMaxDepth then
dOriDepth = dDepth
-- lo limito e tolgo eventuali Tabs
dDepth = dCurrMaxDepth
EgtSetMachiningParam( MCH_MP.LEAVETAB, false)
bNotThrou = true
end
-- tolgo i Tabs se devo rimuovere lo sfrido
if nConeCut == 1 then EgtSetMachiningParam( MCH_MP.LEAVETAB, false) end
-- aggiungo geometria
local vGeom = {{ Proc.Id, vFace[i].Fac}}
local dSal = EgtIf( ( vFace[i].Type & 2) ~= 0, vFace[i].Whisk - vFace[i].Len, 0)
local dEal = 0
local OrigI = i
local OrigH = j
local LastJ
i = i + 1
local j = EgtIf( i <= #vFace, i, EgtIf( bAllType4 or not bClosed, nil, 1))
while j and ( ( vFace[j].Type & 1) ~= 0 or ( vFace[j].Type == 4 and ( vFace[j].Edges > 3 and not vFace[j].Is3EdgesApprox))) and abs( vFace[j].SideAng) < 0.1 and abs( vFace[OrigI].SideAng) < 0.1 do
table.insert( vGeom, { Proc.Id, vFace[j].Fac})
LastJ = j
dEal = EgtIf( ( vFace[j].Type & 1) ~= 0, vFace[j].Whisk - vFace[j].Len, 0)
if ( vFace[j].Type & 1) ~= 0 then
break
end
i = i + 1
j = EgtIf( j + 1 <= #vFace, j + 1, EgtIf( bAllType4 or not bClosed, nil, 1))
end
-- se faccia singola è da fare tutta senza oltrepassare estremi
if #vFace == 1 and vFace[OrigI].Type == 4 and ( vFace[OrigI].Edges > 3 and not vFace[OrigI].Is3EdgesApprox) then
dSal = -dMillDiam / 2
dEal = -dMillDiam / 2
-- altrimenti va verificato
else
-- se lavorazione completa su faccia iniziale
if vFace[OrigI].Type == 4 and ( vFace[OrigI].Edges > 3 and not vFace[OrigI].Is3EdgesApprox) then
-- se angolo interno prima
if vFace[OrigI].PrevAng < -30 then
local dSinA = -sin( vFace[OrigI].PlPrevAng + 90)
local dTanA = -tan( vFace[OrigI].PlPrevAng + 90)
dSal = -dMillDiam / 2 * ( 1 + ( 1 + dSinA) * dTanA) + min( 0, vFace[OrigI].Width * vFace[OrigI].Norm:getZ() * dTanA)
-- se faccia precedente inclinata verso il basso
if OrigH and vFace[OrigH].Norm:getZ() < -0.017 then
dSal = dSal + vFace[OrigH].Width * vFace[OrigH].Norm:getZ()
end
-- se angolo esterno prima
elseif vFace[OrigI].PrevAng > 30 then
-- se faccia precedente inclinata verso il basso
if OrigH and vFace[OrigH].Norm:getZ() < -0.017 then
dSal = dSal - vFace[OrigH].Width * vFace[OrigH].Norm:getZ()
end
end
end
-- se lavorazione completa o finale su faccia finale
local LastFace = ( LastJ or OrigI)
local OrigK = EgtIf( LastFace < #vFace, LastFace + 1, EgtIf( bClosed, 1, nil))
if ( vFace[LastFace].Type == 4 and ( vFace[LastFace].Edges > 3 and not vFace[LastFace].Is3EdgesApprox)) or ( LastFace == OrigI and ( vFace[LastFace].Type & 2) ~= 0) then
-- se angolo interno dopo
if OrigK and vFace[OrigK].PrevAng < -30 then
local dSinA = -sin( vFace[OrigK].PlPrevAng + 90)
local dTanA = -sin( vFace[OrigK].PlPrevAng + 90)
dEal = -dMillDiam / 2 * ( 1 + ( 1 + dSinA) * dTanA) + min( 0, vFace[OrigI].Width * vFace[OrigI].Norm:getZ() * dTanA)
-- se faccia successiva inclinata verso il basso
if vFace[OrigK].Norm:getZ() < -0.017 then
dEal = dEal + vFace[OrigK].Width * vFace[OrigK].Norm:getZ()
end
-- se angolo esterno dopo
elseif OrigK and vFace[OrigK].PrevAng > 30 then
-- se faccia successiva inclinata verso il basso
if vFace[OrigK].Norm:getZ() < -0.017 then
dEal = dEal - vFace[OrigK].Width * vFace[OrigK].Norm:getZ()
end
end
end
-- per sola lavorazione finale
if LastFace == OrigI and ( vFace[LastFace].Type & 2) ~= 0 then
-- se angolo interno dopo e faccia successiva inclinata verso l'alto oltre 16.1 deg
if OrigK and vFace[OrigK].PrevAng < -30 and vFace[OrigK].Norm:getZ() < 0.96078 and vFace[OrigK].Norm:getZ() > 0 then
dSal = dSal + vFace[OrigK].Width * vFace[OrigK].Norm:getZ()
end
-- se angolo interno prima e faccia precedente inclinata verso l'alto oltre 16.1 deg
if vFace[OrigI].PrevAng < -30 and OrigH and vFace[OrigH].Norm:getZ() < 0.96078 and vFace[OrigH].Norm:getZ() > 0 then
dSal = dSal + vFace[OrigH].Width * vFace[OrigH].Norm:getZ()
-- se l'inclinazione è inferiore a 46.1deg
if vFace[OrigH].Norm:getZ() > 0.72055 then
dSal = dSal - vFace[OrigH].Width
end
end
end
-- se percorso chiuso e completo con fresa
if bClosed and bAllType4 then
dSal = 0
dEal = 0
end
-- se faccia singola non oltrepasso l'estremo finale
if #vFace == 1 then
dEal = -dMillDiam / 2
end
end
-- se non devo scaricare l'angolo o la faccia è inclinata
if nConeCut <= 1 or abs( vFace[OrigI].SideAng) > 0.1 then
EgtSetMachiningGeometry( vGeom)
EgtSetMachiningParam( MCH_MP.STARTADDLEN, dSal)
EgtSetMachiningParam( MCH_MP.ENDADDLEN, dEal)
-- tolgo i Tabs se devo rimuovere lo sfrido
if nConeCut == 1 then EgtSetMachiningParam( MCH_MP.LEAVETAB, false) end
-- percorso da non invertire
EgtSetMachiningParam( MCH_MP.INVERT, false)
-- assegno utilizzo faccia
EgtSetMachiningParam( MCH_MP.FACEUSE, MCH_MILL_FU.PARAL_DOWN)
-- assegno affondamento
EgtSetMachiningParam( MCH_MP.DEPTH, dDepth)
-- assegno lato di lavoro
EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.RIGHT)
-- posizione braccio porta testa
EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.ADIR_XP)
-- posizione braccio porta testa
local nSCC = MCH_SCC.ADIR_ZP
if abs( vFace[OrigI].Norm:getZ()) < GEO.EPS_SMALL then
nSCC = EgtIf( abs( vFace[OrigI].Norm:getX()) > abs( vFace[OrigI].Norm:getY()), MCH_SCC.ADIR_XP, MCH_SCC.ADIR_YP)
end
EgtSetMachiningParam( MCH_MP.SCC, nSCC)
-- altrimenti se devo fare rientranza per inserimento utensile cono 30°
elseif nConeCut == 2 then
-- eseguo la costruzione del percorso
local nPathId, sErr = MakeCustomPath( vGeom, nConeCut, dMillDiam, nAddGrpId, dThick, bClosed and bAllType4)
if nPathId == 0 then return 0, sErr end
EgtSetMachiningGeometry({{ nPathId, -1}})
EgtSetMachiningParam( MCH_MP.STARTADDLEN, dSal)
EgtSetMachiningParam( MCH_MP.ENDADDLEN, dEal)
-- percorso da non invertire
EgtSetMachiningParam( MCH_MP.INVERT, false)
-- assegno utilizzo faccia
EgtSetMachiningParam( MCH_MP.FACEUSE, MCH_MILL_FU.PARAL_DOWN)
-- assegno affondamento
-- EgtSetMachiningParam( MCH_MP.DEPTH, dDepth)
if bNotThrou then
EgtSetMachiningParam( MCH_MP.DEPTH, ( dDepth - dOriDepth))
else
EgtSetMachiningParam( MCH_MP.DEPTH, 0)
end
-- assegno lato di lavoro
EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.CENTER)
-- posizione braccio porta testa
EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.ADIR_XP)
-- altrimenti se devo scaricare l'angolo
elseif nConeCut == 3 then
-- eseguo la costruzione del percorso
local nPathId, sErr = MakeCustomPath( vGeom, nConeCut, dMillDiam, nAddGrpId, nil, bClosed and bAllType4)
if nPathId == 0 then return 0, sErr end
EgtSetMachiningGeometry({{ nPathId, -1}})
EgtSetMachiningParam( MCH_MP.STARTADDLEN, dSal)
EgtSetMachiningParam( MCH_MP.ENDADDLEN, dEal)
-- percorso da non invertire
EgtSetMachiningParam( MCH_MP.INVERT, false)
-- assegno affondamento
if bNotThrou then
EgtSetMachiningParam( MCH_MP.DEPTH, ( dDepth - dOriDepth))
else
EgtSetMachiningParam( MCH_MP.DEPTH, 0)
end
-- assegno lato di lavoro
EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.CENTER)
-- posizione braccio porta testa
EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.ADIR_XP)
end
-- eseguo
if not EgtApplyMachining( true, false) then
local _, sErr = EgtGetLastMachMgrError()
EgtSetOperationMode( nMchId, false)
return 0, sErr
end
else
i = i + 1
end
end
-- aggiungo eventuali fresature a metà faccia
for i =1, #vFace do
if vFace[i].Split then
-- inserisco la lavorazione
local sName = 'Free_' .. ( EgtGetName( Proc.PartId) or tostring( Proc.PartId)) .. '_M'
local nMchId = WM.AddMachining( Proc, sName, sMilling)
if not nMchId then
local sErr = 'Error adding machining ' .. sName .. '-' .. sMilling
EgtOutLog( sErr)
return 0, sErr
end
EgtSetInfo( nMchId, 'Part', Proc.PartId)
-- calcolo l'affondamento
local dDepth = vFace[i].Width + WD.CUT_EXTRA
dThick = vFace[i].Width
local vtNz = vFace[i].Norm:getZ()
if WD.CHECK_MIN_Z_SAW then
if vtNz >= 0 then
dDepth = min( dDepth, vFace[i].Width - WD.MIN_Z_SAW)
else
dDepth = min( dDepth, dDepth - WD.MIN_Z_SAW + dMillDiam * vtNz / sqrt( 1 - vtNz * vtNz))
end
end
local dCurrMaxDepth = GetMaxDepth( vtNz, dMillDiam, dDiamTh, dMaxDepth, dFreeLen)
-- se affondamento superiore ai limiti della fresa
if dDepth > dCurrMaxDepth then
dOriDepth = dDepth
-- lo limito e tolgo eventuali Tabs
dDepth = dCurrMaxDepth
EgtSetMachiningParam( MCH_MP.LEAVETAB, false)
bNotThrou = true
end
-- aggiungo geometria
EgtSetMachiningGeometry( {{ Proc.Id, vFace[i].Fac}})
local dSal = vFace[i].Whisk - vFace[i].Len / 2
local dEal = vFace[i].Whisk - vFace[i].Len / 2
EgtSetMachiningParam( MCH_MP.STARTADDLEN, dSal)
EgtSetMachiningParam( MCH_MP.ENDADDLEN, dEal)
-- percorso da non invertire
EgtSetMachiningParam( MCH_MP.INVERT, false)
-- assegno utilizzo faccia
EgtSetMachiningParam( MCH_MP.FACEUSE, MCH_MILL_FU.PARAL_DOWN)
-- assegno affondamento
EgtSetMachiningParam( MCH_MP.DEPTH, dDepth)
-- assegno lato di lavoro
EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.RIGHT)
-- posizione braccio porta testa
local nSCC = MCH_SCC.ADIR_ZP
if abs( vFace[i].Norm:getZ()) < GEO.EPS_SMALL then
nSCC = EgtIf( abs( vFace[i].Norm:getX()) > abs( vFace[i].Norm:getY()), MCH_SCC.ADIR_XP, MCH_SCC.ADIR_YP)
end
EgtSetMachiningParam( MCH_MP.SCC, nSCC)
-- eseguo
if not EgtApplyMachining( true, false) then
local _, sErr = EgtGetLastMachMgrError()
EgtSetOperationMode( nMchId, false)
return 0, sErr
end
end
end
-- se fresature non sono passanti
if bNotThrou then
return 2, dMillDiam, dThick
end
return 1, dMillDiam, dThick
end
---------------------------------------------------------------------
local function AddSawings( sSawing, vFace, Proc, nRawId, b3Raw)
-- flag per tagli non passanti
local bNotThrou
local dThick
-- recupero i dati dell'utensile
local dSawDiam = 0
local dMaxDepth = 0
local dSawThick = 0
if EgtMdbSetCurrMachining( sSawing) then
local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID)
if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then
dSawDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dSawDiam
dSawThick = EgtTdbGetCurrToolParam( MCH_TP.THICK) or dSawThick
dMaxDepth = EgtTdbGetCurrToolMaxDepth() or dMaxDepth
end
end
-- Calcolo angolo 3° asse rot (da direz. utensile)
local sRot3Ang = 'A1=180'
if WD.GetChainSawBlockedAxis then
sRot3Ang = WD.GetChainSawBlockedAxis( 1)
end
-- ciclo di inserimento dei tagli con sega a catena
for i = 1, #vFace do
-- se inizio faccia non tagliato completamente, inserisco un ripasso con sega a catena
if ( vFace[i].Type & 1) ~= 0 then
-- inserisco la lavorazione
local sName = 'Free_' .. ( EgtGetName( Proc.PartId) or tostring( Proc.PartId))
local nMchId = WM.AddMachining( Proc, sName, sSawing)
if not nMchId then
local sErr = 'Error adding machining ' .. sName .. '-' .. sSawing
EgtOutLog( sErr)
return 0, sErr
end
EgtSetInfo( nMchId, 'Part', Proc.PartId)
-- calcolo l'affondamento
local dDepth = vFace[i].Width + min( WD.CUT_EXTRA, -WD.MIN_Z_SAW)
dThick = vFace[i].Width
-- se affondamento superiore ai limiti della sega a catena
if dDepth > dMaxDepth then
dDepth = dMaxDepth
bNotThrou = true
end
-- aggiungo geometria
EgtSetMachiningGeometry( {{ Proc.Id, vFace[i].Fac}})
local dSal = - dSawDiam / 2
local dEal = vFace[i].Whisk - vFace[i].Len - dSawDiam / 2
EgtSetMachiningParam( MCH_MP.STARTADDLEN, dSal)
EgtSetMachiningParam( MCH_MP.ENDADDLEN, dEal)
-- assegno utilizzo faccia
EgtSetMachiningParam( MCH_MP.FACEUSE, MCH_MILL_FU.PARAL_DOWN)
-- imposto angolo 3° asse rot
EgtSetMachiningParam( MCH_MP.BLOCKEDAXIS, sRot3Ang)
-- assegno affondamento
EgtSetMachiningParam( MCH_MP.DEPTH, dDepth)
-- assegno lato di lavoro e inversione direzione movimento
if vFace[i].Norm:getX() < 0.018 then
EgtSetMachiningParam( MCH_MP.INVERT, false)
EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.RIGHT)
else
EgtSetMachiningParam( MCH_MP.INVERT, true)
EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.LEFT)
end
-- posizione braccio porta testa
EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.NONE)
-- eseguo
if not EgtApplyMachining( true, false) then
local _, sErr = EgtGetLastMachMgrError()
EgtSetOperationMode( nMchId, false)
return 0, sErr
end
end
-- se fine faccia non tagliato completamente o faccia non tagliata completamente e abbastanza lunga, inserisco un ripasso con sega a catena
if ( vFace[i].Type & 2) ~= 0 or ( vFace[i].Type == 4 and ( vFace[i].Edges > 3 and not vFace[i].Is3EdgesApprox) and vFace[i].Len > dSawDiam + 1) then
-- inserisco la lavorazione
local sName = 'Free_' .. ( EgtGetName( Proc.PartId) or tostring( Proc.PartId))
local nMchId = WM.AddMachining( Proc, sName, sSawing)
if not nMchId then
local sErr = 'Error adding machining ' .. sName .. '-' .. sSawing
EgtOutLog( sErr)
return 0, sErr
end
EgtSetInfo( nMchId, 'Part', Proc.PartId)
-- calcolo l'affondamento
local dDepth = vFace[i].Width + min( WD.CUT_EXTRA, -WD.MIN_Z_SAW)
dThick = vFace[i].Width
-- se affondamento superiore ai limiti della sega a catena
if dDepth > dMaxDepth then
dDepth = dMaxDepth
bNotThrou = true
end
-- aggiungo geometria
EgtSetMachiningGeometry( {{ Proc.Id, vFace[i].Fac}})
local dSal = - dSawDiam / 2
local dEal = - dSawDiam / 2
if ( vFace[i].Type & 2) ~= 0 then
dSal = vFace[i].Whisk - vFace[i].Len - dSawDiam / 2
end
EgtSetMachiningParam( MCH_MP.STARTADDLEN, dSal)
EgtSetMachiningParam( MCH_MP.ENDADDLEN, dEal)
-- assegno utilizzo faccia
EgtSetMachiningParam( MCH_MP.FACEUSE, MCH_MILL_FU.PARAL_DOWN)
-- imposto angolo 3° asse rot
EgtSetMachiningParam( MCH_MP.BLOCKEDAXIS, sRot3Ang)
-- assegno affondamento
EgtSetMachiningParam( MCH_MP.DEPTH, dDepth)
-- assegno lato di lavoro e inversione direzione movimento
if vFace[i].Norm:getX() < 0.018 then
EgtSetMachiningParam( MCH_MP.INVERT, false)
EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.RIGHT)
else
EgtSetMachiningParam( MCH_MP.INVERT, true)
EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.LEFT)
end
-- posizione braccio porta testa
EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.NONE)
-- eseguo
if not EgtApplyMachining( true, false) then
local _, sErr = EgtGetLastMachMgrError()
EgtSetOperationMode( nMchId, false)
return 0, sErr
end
end
end
-- se fresature non sono passanti
if bNotThrou then
return 2, dSawThick, dThick
end
return 1, dSawThick, dThick
end
---------------------------------------------------------------------
local function AddCuts( sCutting, vFace, Proc, nRawId, b3Raw, dSawThick)
-- verifico se ciclo chiuso
local bClosed = ( abs( vFace[1].PrevAng) > 0.1)
-- ciclo di inserimento dei tagli sulle facce del contorno in esame
for i = 1, #vFace do
-- verifico se faccia da saltare, perchè macchina travi e faccia su bordo longitudinale esterno già finito
local bToSkip = ( WD.BEAM_MACHINE and IsPointOnRawLongEdges( vFace[i].Cen, b3Raw))
-- se non è faccia da saltare, inserisco il taglio di lama
if not bToSkip and vFace[i].Type ~= 4 then
-- indice del successivo
local j = EgtIf( i < #vFace, i + 1, 1)
-- indice del precedente
local h = EgtIf( i > 1, i - 1, EgtIf( bClosed, #vFace, nil))
-- inserisco la lavorazione
local sName = 'Cut_' .. ( EgtGetName( Proc.PartId) or tostring( Proc.PartId)) .. '_' .. tostring( i)
local nMchId = WM.AddMachining( Proc, sName, sCutting)
if not nMchId then
local sErr = 'Error adding machining ' .. sName .. '-' .. sCutting
EgtOutLog( sErr)
return false, sErr
end
EgtSetInfo( nMchId, 'Part', Proc.PartId)
local dSpeed = EgtGetMachiningParam( MCH_MP.SPEED)
local sHead = EgtTdbGetCurrToolParam( MCH_TP.HEAD)
local bGearbox = EgtGetInfo( EgtGetHeadId( sHead) or GDB_ID.NULL, 'Gearbox', 'b')
-- aggiungo geometria
EgtSetMachiningGeometry( { { Proc.Id, vFace[i].Fac}})
-- calcolo l'affondamento
local dDepth = vFace[i].Depth
local vtNz = vFace[i].Norm:getZ()
if WD.CHECK_MIN_Z_SAW then
if vtNz >= 0 then
dDepth = min( dDepth, -WD.MIN_Z_SAW)
else
dDepth = min( dDepth, -WD.MIN_Z_SAW + dSawThick * vtNz)
end
end
EgtSetMachiningParam( MCH_MP.DEPTH, dDepth)
-- verifico se va invertita la direzione di lavorazione perchè faccia verso l'alto (angolo maggiore di 0.01 deg)
local bInvert = ( vFace[i].Norm:getZ() > 0.0001745)
-- imposto inversione
EgtSetMachiningParam( MCH_MP.INVERT, bInvert)
-- imposto lato di lavoro
EgtSetMachiningParam( MCH_MP.WORKSIDE, EgtIf( bInvert, MCH_SAW_WS.LEFT, MCH_SAW_WS.RIGHT))
-- lato mandrino ( standard a sinistra se rotazione CCW, altrimenti a destra, oppure da funzione di macchina)
local nHeadSide = EgtIf( dSpeed < 0, MCH_SAW_HS.LEFT, MCH_SAW_HS.RIGHT)
if WD.GetSawHeadSide then nHeadSide = WD.GetSawHeadSide( dSpeed, sHead) end
EgtSetMachiningParam( MCH_MP.HEADSIDE, nHeadSide)
-- assegno i dati di attacco (sicurezza solo se angolo interno)
local nLeadIn = MCH_SAW_LI.CENT
if ( not bInvert and ( vFace[i].Type & 1) ~= 0) or ( bInvert and ( vFace[i].Type & 2) ~= 0) then
nLeadIn = MCH_SAW_LI.STRICT
end
EgtSetMachiningParam( MCH_MP.LEADINTYPE, nLeadIn)
local dSal = 0
if ( not bInvert and vFace[i].PrevAng < -0.1) or ( bInvert and vFace[j].PrevAng < -0.1) then
-- se faccia precedente inclinata verso il basso
if not bInvert and h and vFace[h].Norm:getZ() < -0.017 then
dSal = vFace[h].Width * vFace[h].Norm:getZ() - WHISK_SAFE
elseif bInvert and j and vFace[j].Norm:getZ() < -0.017 then
dSal = vFace[j].Width * vFace[j].Norm:getZ() - WHISK_SAFE
else
dSal = -WHISK_SAFE
end
end
EgtSetMachiningParam( MCH_MP.STARTADDLEN, dSal)
-- assegno i dati di uscita (sicurezza solo se angolo interno)
local nLeadOut = MCH_SAW_LO.CENT
if ( not bInvert and ( vFace[i].Type & 2) ~= 0) or ( bInvert and ( vFace[i].Type & 1) ~= 0) then
nLeadOut = MCH_SAW_LO.STRICT
end
EgtSetMachiningParam( MCH_MP.LEADOUTTYPE, nLeadOut)
local dEal = 0
if ( not bInvert and vFace[j].PrevAng < -0.1) or ( bInvert and vFace[i].PrevAng < -0.1) then
-- se faccia precedente inclinata verso il basso
if not bInvert and j and vFace[j].Norm:getZ() < -0.017 then
dEal = vFace[j].Width * vFace[j].Norm:getZ() - WHISK_SAFE
elseif bInvert and h and vFace[h].Norm:getZ() < -0.017 then
dEal = vFace[h].Width * vFace[h].Norm:getZ() - WHISK_SAFE
else
dEal = -WHISK_SAFE
end
end
EgtSetMachiningParam( MCH_MP.ENDADDLEN, dEal)
-- posizione braccio porta testa
if not bGearbox then
EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.NONE)
else
EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.ADIR_NEAR)
end
-- eseguo
if not EgtApplyMachining( true, false) then
-- provo a invertire direzione, lato di lavoro e attacco/uscita
EgtSetMachiningParam( MCH_MP.INVERT, not bInvert)
EgtSetMachiningParam( MCH_MP.WORKSIDE, EgtIf( not bInvert, MCH_SAW_WS.LEFT, MCH_SAW_WS.RIGHT))
EgtSetMachiningParam( MCH_MP.LEADINTYPE, EgtIf( nLeadOut == MCH_SAW_LO.STRICT, MCH_SAW_LI.STRICT, MCH_SAW_LI.CENT))
EgtSetMachiningParam( MCH_MP.STARTADDLEN, dEal)
EgtSetMachiningParam( MCH_MP.LEADOUTTYPE, EgtIf( nLeadIn == MCH_SAW_LI.STRICT, MCH_SAW_LO.STRICT, MCH_SAW_LO.CENT))
EgtSetMachiningParam( MCH_MP.ENDADDLEN, dSal)
-- ri-eseguo
if not EgtApplyMachining( true, false) then
local _, sErr = EgtGetLastMachMgrError()
EgtSetOperationMode( nMchId, false)
return false, sErr
end
end
-- se limite lunghezza di taglio e taglio lo supera
if WD.CUT_MAX_LENGTH and vFace[i].Len > WD.CUT_MAX_LENGTH then
-- sdoppio la lavorazione
local sSouName = EgtGetName( nMchId)
local nNewMchId = EgtCopyMachining( sSouName..'_B', sSouName)
--accorciamento iniziale della seconda
EgtSetMachiningParam( MCH_MP.LEADINTYPE, MCH_SAW_LI.STRICT)
EgtSetMachiningParam( MCH_MP.STARTADDLEN, -vFace[i].Len/2)
--accorciamento finale della prima
EgtSetCurrMachining( nMchId)
EgtSetMachiningParam( MCH_MP.LEADOUTTYPE, MCH_SAW_LO.STRICT)
EgtSetMachiningParam( MCH_MP.ENDADDLEN, -vFace[i].Len/2)
-- segnalo spezzatura lavorazione faccia
vFace[i].Split = true
end
end
end
return true
end
---------------------------------------------------------------------
local function MakeByCut( Proc, nRawId, b3Raw)
local sWarn = ''
-- ingombro del pezzo
local Ls = EgtGetFirstNameInGroup( Proc.PartId, 'Box')
local b3Solid = EgtGetBBoxGlob( Ls or GDB_ID.NULL, GDB_BB.STANDARD)
if not b3Solid then
local sErr = 'Error : part box not found'
EgtOutLog( sErr)
return false, sErr
end
-- recupero la curva associata
local bOpposite = false
local AuxId = EgtGetInfo( Proc.Id, 'AUXID', 'i')
if AuxId then
AuxId = AuxId + Proc.Id
local vtExtr= EgtCurveExtrusion( AuxId, GDB_RT.GLOB)
if vtExtr then
bOpposite = ( Proc.Grp == 4 and vtExtr:getZ() < 0) or ( Proc.Grp == 3 and vtExtr:getZ() > 0)
if GetFacesExternalSide( Proc, vtExtr) ~= Proc.Grp then
bOpposite = not bOpposite
end
end
end
-- altezza massima delle facce
local dWidth = 0
for i = 1, Proc.Fct do
local _, _, dFctW = WL.GetFaceHvRefDim( Proc.Id, i - 1)
dWidth = max( dWidth, dFctW)
end
-- lettura parametri (probabile/i parametro/i Q)
local nConeCut = VerifyCornerType( Proc)
-- recupero la lavorazione di taglio con lama e i suoi parametri (dapprima cerco quella che possa tagliare completamente)
local nTool_ID = EgtGetInfo( Proc.Id, 'CNT_DATA', 'i')
local sCutting, dSawDiam, dSawThick, dSawMaxDepth = WM.FindCutting( 'Standard', dWidth, nTool_ID)
if not sCutting then
sCutting, dSawDiam, dSawThick, dSawMaxDepth = WM.FindCutting( 'Standard', nil, nTool_ID)
sWarn = 'Warning : elevation bigger than max sawcut depth'
end
if not sCutting then
local sErr = 'Error : cutting not found in library'
EgtOutLog( sErr)
return false, sErr
end
-- gruppo ausiliario
local nAddGrpId = WL.GetAddGroup( Proc.PartId)
-- recupero i dati di tutte le facce
local vFace, dMaxWidth, nNewProc = GetFacesData( Proc, bOpposite, true, dSawDiam, dSawMaxDepth, dSawThick, nAddGrpId, b3Raw, nil)
-- inserimento dei tagli di lama
local bCtOk, sCtErr = AddCuts( sCutting, vFace, Proc, nRawId, b3Raw, dSawThick)
if not bCtOk then return bCtOk, sCtErr end
-- se richiesta solo lama, esco
local nCntType = EgtGetInfo( Proc.Id, 'CNT_TYPE', 'i') or 0
if nCntType == 1 and nTool_ID ~= 0 then return true, sWarn end
-- se ci sono facce inclinate, escludo la sega a catena
local bSlanting = false
for i = 1, #vFace do
if abs( vFace[i].Norm:getZ()) > 0.01 then
bSlanting = true
break
end
end
-- recupero la lavorazione con sega a catena
local sSawing = WM.FindSawing( 'Sawing')
-- recupero la lavorazione di fresatura
local sMilling, dMillMaxDepth = WM.FindMilling( 'FreeContour', dMaxWidth + WD.CUT_EXTRA, nil, nil, nil, nil, true)
local sMilling2 = WM.FindMilling( 'FreeContour', nil, nil, nil, nil, nil, true)
if not sMilling and ( not sSawing or bSlanting) then
-- se non trovo una fresa di lunghezza sufficiente, prendo la più lunga disponibile
local sMillingMaxLength = WM.FindMilling( 'FreeContour', 0.8 * ( dMaxWidth + WD.CUT_EXTRA), nil, nil, nil, nil, true) or
WM.FindMilling( 'FreeContour', 0.6 * ( dMaxWidth + WD.CUT_EXTRA), nil, nil, nil, nil, true) or
WM.FindMilling( 'FreeContour', 0.4 * ( dMaxWidth + WD.CUT_EXTRA), nil, nil, nil, nil, true) or
WM.FindMilling( 'FreeContour', 0.2 * ( dMaxWidth + WD.CUT_EXTRA), nil, nil, nil, nil, true) or
WM.FindMilling( 'FreeContour', nil, nil, nil, nil, nil, true)
sMilling = sMillingMaxLength
if not sMilling then
local sErr = 'Error : milling not found in library'
EgtOutLog( sErr)
return false, sErr
end
end
-- se possibile, inserimento delle fresature
local bDone = false
if sMilling then
local nMlOk, sMlErr, dThick = AddMillings( sMilling, vFace, Proc, nRawId, b3Raw, nConeCut, nAddGrpId)
if nMlOk == 0 then return false, sMlErr end
bDone = ( dThick ~= nil)
-- se ci sono almeno due facce e lavorato almeno un angolo
if Proc.Fct >= 2 and bDone then
-- se abilitata la lavorazione corner con stop macchina e lavorazione precedente passante e spessore sotto il limite
-- o con fresa cono piccola e spessore sotto il limite
if ( nConeCut == 1 and nMlOk == 1 and dThick <= ( WD.MAX_CLEAN_CRN60 + 20 * GEO.EPS_SMALL)) or
( nConeCut == 2 and dThick <= ( WD.MAX_CLEAN_CRN30 + 20 * GEO.EPS_SMALL)) then
local bMcok, sMcErr = AddMillCorner( nConeCut, vFace, Proc, nRawId, b3Raw,
sMlErr, nAddGrpId, dThick, nNewProc, 0, true)
if not bMcok then return bMcok, sMcErr end
else
-- messaggi nel log
if nConeCut == 1 then
if nMlOk ~= 1 then
local sErr = 'Clean corner 60° not applid because Milling not thru the thickness'
EgtOutLog( sErr)
else
local sErr = 'Clean corner 60° not applid because thickness: ' .. EgtNumToString( dThick, 2) ..
' is bigger than parameter MAX_CLEAN_CRN60: ' .. EgtNumToString( WD.MAX_CLEAN_CRN60 , 2)
EgtOutLog( sErr)
end
elseif nConeCut == 2 then
local sErr = 'Clean corner 30° not applid because thickness: ' .. EgtNumToString( dThick, 2) ..
' is bigger than parameter MAX_CLEAN_CRN30: ' .. EgtNumToString( WD.MAX_CLEAN_CRN30 , 2)
EgtOutLog( sErr)
end
end
end
-- altrimenti provo con la sega a catena
elseif sSawing then
local nCsOk, sCsErr, dThick = AddSawings( sSawing, vFace, Proc, nRawId, b3Raw)
if nCsOk == 0 then return false, sCsErr end
bDone = ( dThick ~= nil)
-- se ci sono almeno due facce e lavorato almeno un angolo
if Proc.Fct >= 2 and bDone then
-- se abilitata la lavorazione corner con stop macchina e lavorazione precedente passante e spessore sotto il limite
if nConeCut == 1 and nCsOk == 1 and dThick <= ( WD.MAX_CLEAN_CRN60 + 20 * GEO.EPS_SMALL) then
local bMcok, sMcErr = AddMillCorner( nConeCut, vFace, Proc, nRawId, b3Raw,
sCSErr, nAddGrpId, nil, nNewProc, 0, true)
if not bMcok then return bMcok, sMcErr end
else
if nConeCut == 1 then
if nCsOk ~= 1 then
local sErr = 'Clean corner 60° not applied because Chainsawing not thru the thickness'
EgtOutLog( sErr)
else
local sErr = 'Clean corner 60° not applid because thickness: ' .. EgtNumToString( dThick, 2) ..
' is bigger than parameter MAX_CLEAN_CRN60: ' .. EgtNumToString( WD.MAX_CLEAN_CRN60 , 2)
EgtOutLog( sErr)
end
elseif nConeCut == 2 then
local sErr = 'Not possible apply Clean corner 30° after use sawing'
EgtOutLog( sErr)
end
end
end
end
-- altrimenti provo con fresa ad affondamento ridotto
if not bDone then
local nMlOk, sMlErr, dThick = AddMillings( sMilling2, vFace, Proc, nRawId, b3Raw, nConeCut, nAddGrpId)
if nMlOk == 0 then return false, sMlErr end
-- se ci sono almeno due facce e lavorato almeno un angolo
if Proc.Fct >= 2 and dThick then
-- se abilitata la lavorazione corner con stop macchina e lavorazione precedente passante e spessore sotto il limite
-- o con fresa cono piccola e spessore sotto il limite
if ( nConeCut == 1 and nMlOk == 1 and dThick <= ( WD.MAX_CLEAN_CRN60 + 20 * GEO.EPS_SMALL)) or
( nConeCut == 2 and dThick <= ( WD.MAX_CLEAN_CRN30 + 20 * GEO.EPS_SMALL)) then
local bMcok, sMcErr = AddMillCorner( nConeCut, vFace, Proc, nRawId, b3Raw,
sMlErr, nAddGrpId, dThick, nNewProc, 0, true)
if not bMcok then return bMcok, sMcErr end
else
-- messaggi nel log
if nConeCut == 1 then
if nMlOk ~= 1 then
local sErr = 'Clean corner 60° not applid because Milling not thru the thickness'
EgtOutLog( sErr)
else
local sErr = 'Clean corner 60° not applid because thickness: ' .. EgtNumToString( dThick, 2) ..
' is bigger than parameter MAX_CLEAN_CRN60: ' .. EgtNumToString( WD.MAX_CLEAN_CRN60 , 2)
EgtOutLog( sErr)
end
elseif nConeCut == 2 then
local sErr = 'Clean corner 30° not applid because thickness: ' .. EgtNumToString( dThick, 2) ..
' is bigger than parameter MAX_CLEAN_CRN30: ' .. EgtNumToString( WD.MAX_CLEAN_CRN30 , 2)
EgtOutLog( sErr)
end
end
sWarn = 'Depth reduced to mill capabilities'
end
end
return true, sWarn
end
---------------------------------------------------------------------
local function MakeByMill( Proc, nRawId, b3Raw)
-- ingombro del pezzo
local Ls = EgtGetFirstNameInGroup( Proc.PartId, 'Box')
local b3Solid = EgtGetBBoxGlob( Ls or GDB_ID.NULL, GDB_BB.STANDARD)
if not b3Solid then
local sErr = 'Error : part box not found'
EgtOutLog( sErr)
return false, sErr
end
-- recupero e verifico l'entità curva
local AuxId = EgtGetInfo( Proc.Id, 'AUXID', 'i') or 0
if AuxId then AuxId = AuxId + Proc.Id end
if not AuxId or ( EgtGetType( AuxId) & GDB_FY.GEO_CURVE) == 0 then
local sErr = 'Error : missing profile geometry'
EgtOutLog( sErr)
return false, sErr
end
-- recupero i dati della curva e del profilo
local dDepth = abs( EgtCurveThickness( AuxId))
local vtExtr = EgtCurveExtrusion( AuxId, GDB_RT.GLOB)
local b3Aux = EgtGetBBoxGlob( AuxId, GDB_BB.STANDARD)
local bToolInv = ( vtExtr:getZ() < -0.1)
local nTool_ID = EgtGetInfo( Proc.Id, 'CNT_DATA', 'i')
-- lettura parametri (probabile/i parametro/i Q)
local nConeCut = VerifyCornerType( Proc)
-- recupero la lavorazione
local bTipFeed = EgtIf( nTool_ID, false, true)
local sMilling = WM.FindMilling( 'FreeContour', nil, nil, nTool_ID, nil, nil, bTipFeed)
if not sMilling then
local sErr = 'Error : milling not found in library'
if nTool_ID then sErr = sErr .. ' (Tool_ID=' .. tostring( nTool_ID) .. ')' end
EgtOutLog( sErr)
return false, sErr
end
-- recupero i dati dell'utensile
local dMillDiam = 20
local dMaxDepth = 0
if EgtMdbSetCurrMachining( sMilling) then
local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID)
if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then
dMillDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dMillDiam
dMaxDepth = EgtIf( WD.MILL_MAX_DEPTH_AS_MAT, EgtTdbGetCurrToolParam( MCH_TP.MAXMAT), EgtTdbGetCurrToolMaxDepth()) or dMaxDepth
end
end
-- verifiche per affondamento
if b3Aux:getDimZ() > b3Raw:getDimZ() - 1.0 then
dDepth = min( dDepth, b3Raw:getDimZ())
end
dDepth = dDepth + WD.CUT_EXTRA
local bReducedDepth = ( dDepth > dMaxDepth)
if bReducedDepth then
dDepth = dMaxDepth
end
-- inserisco la lavorazione
local sName = 'Free_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id))
local nMchId = WM.AddMachining( Proc, sName, sMilling)
if not nMchId then
local sErr = 'Error adding machining ' .. sName .. '-' .. sMilling
EgtOutLog( sErr)
return false, sErr
end
EgtSetInfo( nMchId, 'Part', Proc.PartId)
-- aggiungo geometria
EgtSetMachiningGeometry( {{ AuxId, -1}})
-- percorso da non invertire
EgtSetMachiningParam( MCH_MP.INVERT, false)
-- se estrusione da sotto, inverto direzione fresa
if bToolInv then
EgtSetMachiningParam( MCH_MP.TOOLINVERT, true)
end
-- tolgo i Tabs se non passante o devo rimuovere lo sfrido
if bReducedDepth or nConeCut == 1 then EgtSetMachiningParam( MCH_MP.LEAVETAB, false) end
-- assegno affondamento
EgtSetMachiningParam( MCH_MP.DEPTH, dDepth)
-- assegno lato di lavoro
if Proc.Grp == 0 then
EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.CENTER)
elseif ( Proc.Grp == 3 and not bToolInv) or ( Proc.Grp == 4 and bToolInv) then
EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.LEFT)
elseif ( Proc.Grp == 3 and bToolInv) or ( Proc.Grp == 4 and not bToolInv) then
EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.RIGHT)
end
-- se lamatura affondata speciale, setto attacco e stacco al centro
local bIsRecessedCounterBore = ( Proc.Box:getMax():getZ() < b3Raw:getMax():getZ() + 10 * GEO.EPS_SMALL) and
( nTool_ID == WD.RECESSED_COUNTERBORE_TOOLID or 0) and
( EgtCurveIsACircle( AuxId))
if bIsRecessedCounterBore then
local _, _, _, dContourRadius = EgtCurveIsACircle( AuxId)
-- setto attacco
EgtSetMachiningParam( MCH_MP.LEADINTYPE, MCH_MILL_LI.TANGENT)
EgtSetMachiningParam( MCH_MP.STARTADDLEN, 0)
EgtSetMachiningParam( MCH_MP.LITANG, 0)
EgtSetMachiningParam( MCH_MP.LIPERP, dContourRadius - 0.5 * dMillDiam)
EgtSetMachiningParam( MCH_MP.LIELEV, 0)
-- setto stacco
EgtSetMachiningParam( MCH_MP.LEADOUTTYPE, MCH_MILL_LO.LINEAR)
EgtSetMachiningParam( MCH_MP.ENDADDLEN, 0)
EgtSetMachiningParam( MCH_MP.LOTANG, 0)
EgtSetMachiningParam( MCH_MP.LOPERP, dContourRadius - 0.5 * dMillDiam)
EgtSetMachiningParam( MCH_MP.LOELEV, 0)
-- imposto step
local dMaxMat = EgtTdbGetCurrToolParam( MCH_TP.MAXMAT) or 0
local dStep = EgtGetMachiningParam( MCH_MP.STEP)
if dStep < GEO.EPS_SMALL then dStep = 0.75 * dMaxMat end
local nStep = ceil( ( dDepth - dMaxMat) / dStep)
dStep = max( ( dDepth - dMaxMat) / max( nStep, 1), 0)
local dMaxElev = max( ( nStep + 1) * dStep - GEO.EPS_SMALL, 0)
EgtSetMachiningParam( MCH_MP.STEP, dStep)
-- imposto elevazione e forzo attacco dal lato aperto
EgtSetMachiningParam( MCH_MP.USERNOTES, 'MaxElev=' .. EgtNumToString( dMaxElev, 1) .. ';OutRaw=3;')
end
-- posizione braccio porta testa
local nSCC = MCH_SCC.ADIR_ZP
if AreSameOrOppositeVectorApprox( vtExtr, Z_AX()) then
nSCC = EgtIf( Proc.Box:getDimX() >= Proc.Box:getDimY(), MCH_SCC.ADIR_YP, MCH_SCC.ADIR_XP)
end
EgtSetMachiningParam( MCH_MP.SCC, nSCC)
-- eseguo
if not EgtApplyMachining( true, false) then
local _, sErr = EgtGetLastMachMgrError()
EgtSetOperationMode( nMchId, false)
return false, sErr
end
-- se abilitata la lavorazione corner con stop macchina, ci sono almeno due facce e fresata passante per consentire eliminazione sfrido
if nConeCut == 1 and Proc.Fct >= 2 and not bReducedDepth then
-- gruppo ausiliario
local nAddGrpId = WL.GetAddGroup( Proc.PartId)
-- recupero i dati di tutte le facce
local vFace, dMaxWidth, nNewProc = GetFacesData( Proc, bOpposite, false, dMillDiam, dMaxDepth, (dMillDiam/2), nAddGrpId, b3Raw)
-- se affondamento non superiore al limite
if dDepth <= ( WD.MAX_CLEAN_CRN60 + 20 * GEO.EPS_SMALL) then
local bMcok, sMcErr = AddMillCorner( nConeCut, vFace, Proc, nRawId, b3Raw,
dMillDiam, nAddGrpId, nil, nNewProc, 0, true)
if not bMcok then return bMcok, sMcErr end
else
EgtErase( nNewProc)
if nConeCut == 1 then
local sErr = 'Clean corner 60° not applid because thickness: ' .. EgtNumToString( dThick, 2) ..
' is bigger than parameter MAX_CLEAN_CRN60: ' .. EgtNumToString( WD.MAX_CLEAN_CRN60 , 2)
EgtOutLog( sErr)
end
end
elseif nConeCut == 2 then
local sErr = 'Clean corner 30° is not applied on milling'
EgtOutLog( sErr)
elseif nConeCut == 3 then
local sErr = 'Clean corner with undercut is not applied on milling'
EgtOutLog( sErr)
end
return true
end
---------------------------------------------------------------------
local function MakeByMark( Proc, nRawId, b3Raw)
-- ingombro del pezzo
local Ls = EgtGetFirstNameInGroup( Proc.PartId, 'Box')
local b3Solid = EgtGetBBoxGlob( Ls or GDB_ID.NULL, GDB_BB.STANDARD)
if not b3Solid then
local sErr = 'Error : part box not found'
EgtOutLog( sErr)
return false, sErr
end
-- recupero e verifico l'entità curva
local AuxId = EgtGetInfo( Proc.Id, 'AUXID', 'i') or 0
if AuxId then AuxId = AuxId + Proc.Id end
if not AuxId or ( EgtGetType( AuxId) & GDB_FY.GEO_CURVE) == 0 then
local sErr = 'Error : missing profile geometry'
EgtOutLog( sErr)
return false, sErr
end
-- recupero i dati della curva e del profilo
local dDepth = abs( EgtCurveThickness( AuxId))
local vtExtr = EgtCurveExtrusion( AuxId, GDB_RT.GLOB)
local b3Aux = EgtGetBBoxGlob( AuxId, GDB_BB.STANDARD)
local bToolInv = ( vtExtr:getZ() < -0.1)
local nTool_ID = EgtGetInfo( Proc.Id, 'CNT_DATA', 'i')
-- recupero la lavorazione
local sMilling = WM.FindMilling( 'Text', nil, nil, nTool_ID)
if not sMilling then
local sErr = 'Error : milling not found in library'
if nTool_ID then sErr = sErr .. ' (Tool_ID=' .. tostring( nTool_ID) .. ')' end
EgtOutLog( sErr)
return false, sErr
end
-- inserisco la lavorazione
local sName = 'FreeMark_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id))
local nMchId = WM.AddMachining( Proc, sName, sMilling)
if not nMchId then
local sErr = 'Error adding machining ' .. sName .. '-' .. sMilling
EgtOutLog( sErr)
return false, sErr
end
EgtSetInfo( nMchId, 'Part', Proc.PartId)
-- aggiungo geometria
EgtSetMachiningGeometry( {{ AuxId, -1}})
-- se estrusione da sotto, inverto direzione fresa
if bToolInv then
EgtSetMachiningParam( MCH_MP.TOOLINVERT, true)
end
-- posizione braccio porta testa
local nSCC = MCH_SCC.ADIR_ZP
if AreSameOrOppositeVectorApprox( vtExtr, Z_AX()) then
nSCC = EgtIf( Proc.Box:getDimX() >= Proc.Box:getDimY(), MCH_SCC.ADIR_YP, MCH_SCC.ADIR_XP)
end
EgtSetMachiningParam( MCH_MP.SCC, nSCC)
-- eseguo
if not EgtApplyMachining( true, false) then
local _, sErr = EgtGetLastMachMgrError()
EgtSetOperationMode( nMchId, false)
return false, sErr
end
return true
end
---------------------------------------------------------------------
local function MakeByNail( Proc, nRawId, b3Raw)
-- ingombro del pezzo
local Ls = EgtGetFirstNameInGroup( Proc.PartId, 'Box')
local b3Solid = EgtGetBBoxGlob( Ls or GDB_ID.NULL, GDB_BB.STANDARD)
if not b3Solid then
local sErr = 'Error : part box not found'
EgtOutLog( sErr)
return false, sErr
end
-- recupero e verifico l'entità curva
local AuxId = EgtGetInfo( Proc.Id, 'AUXID', 'i') or 0
if AuxId then AuxId = AuxId + Proc.Id end
if not AuxId or ( EgtGetType( AuxId) & GDB_FY.GEO_CURVE) == 0 then
local sErr = 'Error : missing profile geometry'
EgtOutLog( sErr)
return false, sErr
end
-- recupero i dati della curva e del profilo
local dDepth = abs( EgtCurveThickness( AuxId))
local vtExtr = EgtCurveExtrusion( AuxId, GDB_RT.GLOB)
local b3Aux = EgtGetBBoxGlob( AuxId, GDB_BB.STANDARD)
local bToolInv = ( vtExtr:getZ() < -0.1)
local nCntData = EgtGetInfo( Proc.Id, 'CNT_DATA', 'i') or 0
if nCntData < 10 then
nCntData = nCntData + 10
end
local dCntPar = EgtGetInfo( Proc.Id, 'CNT_PAR', 'd') or 100
-- recupero la lavorazione
local sNailing = WM.FindNailing( nCntData)
if not sNailing then
local sErr = 'Error : nailing not found in library'
EgtOutLog( sErr)
return false, sErr
end
-- inserisco la lavorazione
local sName = 'Nail_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id))
local nMchId = WM.AddMachining( Proc, sName, sNailing)
if not nMchId then
local sErr = 'Error adding machining ' .. sName .. '-' .. sNailing
EgtOutLog( sErr)
return false, sErr
end
EgtSetInfo( nMchId, 'Part', Proc.PartId)
-- aggiungo geometria
EgtSetMachiningGeometry( {{ AuxId, -1}})
-- percorso da non invertire
EgtSetMachiningParam( MCH_MP.INVERT, false)
-- se estrusione da sotto, inverto direzione fresa
if bToolInv then
EgtSetMachiningParam( MCH_MP.TOOLINVERT, true)
end
-- assegno affondamento
EgtSetMachiningParam( MCH_MP.DEPTH, 10)
-- assegno lato di lavoro
EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.CENTER)
-- se in doppio lungo Y, devo dimezzare opportunamente la lavorazione
local dExtraDelta = 0
if Proc.Double == 2 then
dExtraDelta = 0.45 * dCntPar
if Proc.Delta > 0 then
EgtSetMachiningParam( MCH_MP.ENDADDLEN, -Proc.DblAcc - dExtraDelta)
else
EgtSetMachiningParam( MCH_MP.STARTADDLEN, -Proc.DblAcc - dExtraDelta)
end
end
-- assegno parametri a note utente
local sUserNotes = 'Par=' .. EgtNumToString( dCntPar, 0) .. ';'
if Proc.Double and Proc.Double > 0 then
sUserNotes = sUserNotes .. 'Dbl=' .. EgtNumToString( Proc.Double, 0) .. ';' ..
'Dlt=' .. EgtNumToString( abs( Proc.Delta) + dExtraDelta, 0) .. ';'
end
EgtSetMachiningParam( MCH_MP.USERNOTES, sUserNotes)
-- eseguo
if not EgtApplyMachining( true, false) then
local _, sErr = EgtGetLastMachMgrError()
EgtSetOperationMode( nMchId, false)
return false, sErr
end
return true
end
---------------------------------------------------------------------
local function MakeByPocket( Proc, nRawId, b3Raw)
-- recupero e verifico l'entità curva
local bOpposite = false
local AuxId = EgtGetInfo( Proc.Id, 'AUXID', 'i') or 0
local vtExtr
if AuxId then
AuxId = AuxId + Proc.Id
vtExtr = EgtCurveExtrusion( AuxId, GDB_RT.GLOB)
if vtExtr then
bOpposite = ( Proc.Grp == 4 and vtExtr:getZ() < 0) or ( Proc.Grp == 3 and vtExtr:getZ() > 0)
if GetFacesExternalSide( Proc, vtExtr) ~= Proc.Grp then
bOpposite = not bOpposite
end
end
end
if not AuxId or ( EgtGetType( AuxId) & GDB_FY.GEO_CURVE) == 0 then
local sErr = 'Error : missing profile geometry'
EgtOutLog( sErr)
return false, sErr
end
local bPocketBotface = false
-- se la curva è aperta non la svuoto
if not EgtCurveIsClosed( AuxId) then
bPocketBotface = true
end
-- cerco la faccia di fondo della superfice (deve avere direzione circa quella di estrusione della curva)
local nFacet
for i = 1, Proc.Fct do
local vtN = EgtSurfTmFacetNormVersor( Proc.Id, i-1, GDB_ID.ROOT)
if abs( vtN * vtExtr) > 0.99 then
nFacet = i - 1
break
end
end
if not nFacet then
return MakeByMill( Proc, nRawId, b3Raw)
end
-- se la faccia di fondo ha confini aperti, devo lavorarla direttamente
vAdj = EgtSurfTmFacetAdjacencies( Proc.Id, nFacet)[1] or {}
for i = 1, #vAdj do
if vAdj[i] == - 1 then
bPocketBotface = true
break
end
end
-- recupero i dati della curva e del profilo
local dDepth = EgtIf( bPocketBotface, 0, abs( EgtCurveThickness( AuxId)))
local dOriDepth = dDepth
-- dati della faccia di fondo
local _, dH, dV = EgtSurfTmFacetMinAreaRectangle( Proc.Id, nFacet, GDB_ID.ROOT)
local dDiam = min( dH, dV)
local dElev = WL.GetFaceElevation( Proc.Id, nFacet, nRawId)
-- gruppo ausiliario
local nAddGrpId = WL.GetAddGroup( Proc.PartId)
local nNewProc, nNumFacet = RemoveBottomFaceAndReorder( Proc, nAddGrpId, nFacet)
-- se ho forma a L
local bIsL = ( nNumFacet == 2 or TestElleShape3( nNewProc, nNumFacet) or TestElleShape4( nNewProc, nNumFacet) == 2)
-- verifico se U
local bIsU = ( nNumFacet == 3 and not TestElleShape3( nNewProc, nNumFacet))
local dMiddleFacetLength = 0
if bIsU then
local _, dH2, dV2 = EgtSurfTmFacetMinAreaRectangle( nNewProc, 1, GDB_ID.ROOT)
-- prendo la linea di base
if abs( dElev - dH2) < 1 and abs( dElev - dV2) > 1 then
dMiddleFacetLength = dV2
elseif abs( dElev - dV2) < 1 and abs( dElev - dH2) > 1 then
dMiddleFacetLength = dH2
end
end
if Proc.Fct < 5 and (( bIsL and not bIsU) or ( bIsU and dMiddleFacetLength > dDiam * 2)) then dDiam = dDiam * 2 end
local nTool_ID = EgtGetInfo( Proc.Id, 'CNT_DATA', 'i')
-- recupero la lavorazione
local sPocketing = WM.FindPocketing( 'Pocket', dDiam, dDepth, nTool_ID)
if not sPocketing then
local sErr = 'Error : pocketing not found in library'
if nTool_ID then sErr = sErr .. ' (Tool_ID=' .. tostring( nTool_ID) .. ')' end
EgtOutLog( sErr)
return false, sErr
end
-- recupero i dati dell'utensile
local dMillDiam = 20
local dMaxDepth = 0
local dThDiam = 100
if EgtMdbSetCurrMachining( sPocketing) then
local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID)
if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then
dMillDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dMillDiam
dMaxDepth = EgtIf( WD.MILL_MAX_DEPTH_AS_MAT, EgtTdbGetCurrToolParam( MCH_TP.MAXMAT), EgtTdbGetCurrToolMaxDepth()) or dMaxDepth
dThDiam = EgtTdbGetCurrToolThDiam() or dThDiam
end
end
-- inserisco la lavorazione di svuotatura
local sName = 'Pock_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id))
local nMchFId = WM.AddMachining( Proc, sName, sPocketing)
if not nMchFId then
local sErr = 'Error adding machining ' .. sName .. '-' .. sPocketing
EgtOutLog( sErr)
return false, sErr
end
EgtSetInfo( nMchFId, 'Part', Proc.PartId)
-- aggiungo geometria
if bPocketBotface then
EgtSetMachiningGeometry( {{ Proc.Id, nFacet}})
else
EgtSetMachiningGeometry( {{ AuxId, -1}})
end
-- imposto posizione braccio porta testa
local nSCC = MCH_SCC.ADIR_ZP
if AreSameVectorApprox( vtExtr, Z_AX()) then
nSCC = EgtIf( Proc.Box:getDimX() >= Proc.Box:getDimY(), MCH_SCC.ADIR_YP, MCH_SCC.ADIR_XP)
end
EgtSetMachiningParam( MCH_MP.SCC, nSCC)
local sWarn = ''
if bPocketBotface then
local dThElev = dThDiam / 2 * sqrt( vtExtr:getX() * vtExtr:getX() + vtExtr:getY() * vtExtr:getY())
if dElev + dThElev > dMaxDepth + 10 * GEO.EPS_SMALL then
dDepth = dMaxDepth - dElev - dThElev
sWarn = 'Warning : elevation bigger than max tool depth'
EgtOutLog( sWarn)
end
else
-- se elevazione superiore a massimo affondamento della fresa, riduco opportunamente
if dDepth > dMaxDepth + 10 * GEO.EPS_SMALL then
dDepth = dMaxDepth
sWarn = 'Warning : elevation bigger than max tool depth'
EgtOutLog( sWarn)
end
end
EgtSetMachiningParam( MCH_MP.DEPTH, dDepth)
-- imposto elevazione
EgtSetMachiningParam( MCH_MP.USERNOTES, 'MaxElev=' .. EgtNumToString( EgtIf( bPocketBotface, min( dElev, dMaxDepth), dMaxDepth), 1) .. ';')
-- eseguo
local bAppOk = EgtApplyMachining( true, false)
if not bAppOk and not bPocketBotface then
bPocketBotface = true
EgtSetMachiningGeometry( {{ Proc.Id, nFacet}})
dDepth = 0
local dThElev = dThDiam / 2 * sqrt( vtExtr:getX() * vtExtr:getX() + vtExtr:getY() * vtExtr:getY())
if dElev + dThElev > dMaxDepth + 10 * GEO.EPS_SMALL then
dDepth = dMaxDepth - dElev - dThElev
sWarn = 'Warning : elevation bigger than max tool depth'
EgtOutLog( sWarn)
end
EgtSetMachiningParam( MCH_MP.DEPTH, dDepth)
bAppOk = EgtApplyMachining( true, false)
end
if not bAppOk then
local _, sErr = EgtGetLastMachMgrError()
EgtSetOperationMode( nMchFId, false)
return false, sErr
end
-- lettura parametri (probabile/i parametro/i Q)
local nConeCut = VerifyCornerType( Proc)
-- recupero i dati di tutte le facce
local vFace, dMaxWidth
vFace, dMaxWidth, nNewProc = GetFacesData( Proc, bOpposite, false, dMillDiam, dMaxDepth, (dMillDiam/2), nAddGrpId, b3Raw, nNewProc)
-- se ci sono almeno due facce più quella di fondo
if Proc.Fct >= 3 then
-- se abilitata la lavorazione corner con stop macchina e affondamento non superiore al limite
local dDepthMach = EgtIf( bPocketBotface, dDepth, ( dDepth - dOriDepth))
if nConeCut == 1 and dDepthMach <= ( WD.MAX_CLEAN_CRN60 + 20 * GEO.EPS_SMALL) then
local bMcok, sMcErr = AddMillCorner( nConeCut, vFace, Proc, nRawId, b3Raw,
dMillDiam, nAddGrpId, nil, nNewProc, dDepthMach)
if not bMcok then return bMcok, sMcErr end
else
EgtErase( nNewProc)
if nConeCut == 1 then
local sErr = 'Clean corner 60° not applid because thickness: ' .. EgtNumToString( dThick, 2) ..
' is bigger than parameter MAX_CLEAN_CRN60: ' .. EgtNumToString( WD.MAX_CLEAN_CRN60 , 2)
EgtOutLog( sErr)
elseif nConeCut == 2 then
local sErr = 'Clean corner 30° is not applied on pocketing'
EgtOutLog( sErr)
end
end
end
return true, sWarn
end
---------------------------------------------------------------------
-- Applicazione della lavorazione
function WPF.Make( Proc, nRawId, b3Raw)
-- recupero la tipologia (contorno o tasca)
local bPocket = ( EgtGetInfo( Proc.Id, 'PCKT', 'i') == 1)
-- se svuotatura
if bPocket then
return MakeByPocket( Proc, nRawId, b3Raw)
-- altrimenti contorno
else
-- riordino le facce
ReorderFaces( Proc.Id, EgtSurfTmFacetCount( Proc.Id))
-- recupero il tipo di lavorazione
local nCntType = EgtGetInfo( Proc.Id, 'CNT_TYPE', 'i') or 0
-- se fresatura
if nCntType == 2 then
return MakeByMill( Proc, nRawId, b3Raw)
-- se marcatura
elseif nCntType == 10 then
return MakeByMark( Proc, nRawId, b3Raw)
-- se chiodatura
elseif nCntType == 20 then
return MakeByNail( Proc, nRawId, b3Raw)
-- area vietata
elseif nCntType == 200 then
return true, 'Lock-out area Ignored'
-- altrimenti, taglio con lama e pulizia angoli con fresa
else
return MakeByCut( Proc, nRawId, b3Raw)
end
end
end
---------------------------------------------------------------------
return WPF