From 2482338a12b642fffff1418642c6482d027cdf84 Mon Sep 17 00:00:00 2001 From: "luca.mazzoleni" Date: Mon, 29 Aug 2022 12:52:57 +0200 Subject: [PATCH] BugFix/DoubleCutCollision: inDoubleCut implementata la fresatura di lato nel caso di lavorazione con lama problematica --- LuaLibs/ProcessDoubleCut.lua | 369 ++++++++++++++++++++++++++++++++++- 1 file changed, 365 insertions(+), 4 deletions(-) diff --git a/LuaLibs/ProcessDoubleCut.lua b/LuaLibs/ProcessDoubleCut.lua index 1853d1b..d1efb0b 100644 --- a/LuaLibs/ProcessDoubleCut.lua +++ b/LuaLibs/ProcessDoubleCut.lua @@ -188,6 +188,369 @@ local function MakeChamfer( Proc, nPhase, nRawId, nPartId, dOvmHead) return true end +--------------------------------------------------------------------- +local function VerifyPocket( Proc, dDiam, dDepth, dMaxTotLen, sMchFindMaster, bPocketDown) + -- tipo di svuotatura + local sMchFind = EgtIf( sMchFindMaster and #sMchFindMaster > 0, sMchFindMaster, 'Pocket') + -- ricerca della svuotatura + local sPocketing + if dDepth then + sPocketing = ML.FindPocketing( sMchFind, dDiam, dDepth, dMaxTotLen, not bPocketDown, bPocketDown) or + ML.FindPocketing( sMchFind, dDiam, 0.8 * dDepth, dMaxTotLen, not bPocketDown, bPocketDown) or + ML.FindPocketing( sMchFind, dDiam, 0.6 * dDepth, dMaxTotLen, not bPocketDown, bPocketDown) or + ML.FindPocketing( sMchFind, dDiam, 0.4 * dDepth, dMaxTotLen, not bPocketDown, bPocketDown) or + ML.FindPocketing( sMchFind, dDiam, 0, dMaxTotLen) + else + sPocketing = ML.FindPocketing( sMchFind, dDiam, 0, dMaxTotLen) + end + if not sPocketing then + return false + end + -- recupero i dati dell'utensile + local bUsePocketing = false + local dMaxDepth = 0 + local dToolDiam = 0 + if EgtMdbSetCurrMachining( sPocketing) then + local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID) + if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then + dToolDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dToolDiam + dMaxDepth = EgtTdbGetCurrToolMaxDepth() or dMaxDepth + end + bUsePocketing = true + end + return bUsePocketing, sPocketing, dMaxDepth, dToolDiam +end + +--------------------------------------------------------------------- +local function GetTunnelDimension( Proc, nPartId) + -- sono necessarie almeno due facce + if Proc.Fct < 2 then return 0, 0, 0 end + -- recupero l'ingombro della trave + 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, Proc.Fct do + ptC[i], vtN[i] = EgtSurfTmFacetCenter( Proc.Id, i - 1, GDB_ID.ROOT) + end + -- calcolo l'orientamento del tunnel + local vtOrtho + local bAdj = EgtSurfTmFacetsContact( Proc.Id, 0, 1) + if bAdj then + vtOrtho = vtN[1] ^ vtN[2] + else + if Proc.Fct >= 3 then + vtOrtho = vtN[1] ^ vtN[3] + else + return 0, 0, 0 + end + end + -- ottengo il boundingBox e prendo le dimensioni lungo la direzione (Z locale) che rappresenta la profondità della fessura + local frFc = Frame3d( ptC[1], vtOrtho) ; + local b3BoxLoc = EgtGetBBoxRef( Proc.Id, GDB_BB.STANDARD, frFc) + local dDepth = b3BoxLoc:getDimZ() + -- recupero gruppo per geometria addizionale + local nAddGrpId = BL.GetAddGroup( nPartId) + if not nAddGrpId then + EgtOutLog( 'Error : missing AddGroup') + return 0, 0, 0 + end + -- centro del bounding box locale + local ptCen = b3BoxLoc:getCenter() + ptCen:toGlob( frFc) + -- creo superficie intermedia + local nSurfInt = EgtSurfTmPlaneInBBox( nAddGrpId, ptCen, vtOrtho, b3Solid, GDB_ID.ROOT) + if not nSurfInt then return 0, 0, 0 end + -- ritaglio la superficie con le facce della fessura + for i = 1, Proc.Fct do + EgtCutSurfTmPlane( nSurfInt, ptC[i], -vtN[i], false, GDB_ID.ROOT) + end + local frSurfInt, dDimMax, dDimMin = EgtSurfTmFacetMinAreaRectangle( nSurfInt, 0, GDB_ID.ROOT) + -- cerco la faccia con larghezza pari a dimensione massima della fessura + local nLongIdFace = 0 + for i = 1, Proc.Fct do + if abs( vtN[i] * frSurfInt:getVersX()) < 0.5 then + nLongIdFace = i - 1 + break + end + end + return dDimMin, dDimMax, dDepth, vtOrtho, nLongIdFace, nSurfInt +end + +--------------------------------------------------------------------- +local function SetOpenSide( nPathInt, vtOrtho, b3Solid, nAddGrpId) + -- fondo tra loro le curve compatibili + EgtMergeCurvesInCurveCompo( nPathInt) + local nStartIdEnt, nNumEnt = EgtCurveDomain( nPathInt) + local pLastPIni, pLastPEnd + -- faccio una copia della curva e la esplodo + if nStartIdEnt then + -- ciclo i lati della curva e controllo per ognuno se giace in uno dei piani limite del pezzo: se sì allora il lato è aperto + for i = 1, nNumEnt do + local pPini = EgtUP( nPathInt, (i-1), GDB_RT.GLOB) + local pPend = EgtUP( nPathInt, EgtIf( i == nNumEnt, 0, i), GDB_RT.GLOB) + if ( abs( pPini:getX() - b3Solid:getMax():getX()) < 10 * GEO.EPS_SMALL and abs( pPend:getX() - b3Solid:getMax():getX()) < 10 * GEO.EPS_SMALL) or + ( abs( pPini:getX() - b3Solid:getMin():getX()) < 10 * GEO.EPS_SMALL and abs( pPend:getX() - b3Solid:getMin():getX()) < 10 * GEO.EPS_SMALL) or + ( abs( pPini:getY() - b3Solid:getMax():getY()) < 10 * GEO.EPS_SMALL and abs( pPend:getY() - b3Solid:getMax():getY()) < 10 * GEO.EPS_SMALL) or + ( abs( pPini:getY() - b3Solid:getMin():getY()) < 10 * GEO.EPS_SMALL and abs( pPend:getY() - b3Solid:getMin():getY()) < 10 * GEO.EPS_SMALL) or + ( abs( pPini:getZ() - b3Solid:getMax():getZ()) < 10 * GEO.EPS_SMALL and abs( pPend:getZ() - b3Solid:getMax():getZ()) < 10 * GEO.EPS_SMALL) or + ( abs( pPini:getZ() - b3Solid:getMin():getZ()) < 10 * GEO.EPS_SMALL and abs( pPend:getZ() - b3Solid:getMin():getZ()) < 10 * GEO.EPS_SMALL) then + -- scrivo nelle proprietà della curva quali sono i lati aperti + local sActInfo = EgtGetInfo( nPathInt, 'OPEN', 's') or '' + if #sActInfo > 0 then + -- se ci sono già altri lati aperti + EgtSetInfo( nPathInt, 'OPEN', sActInfo .. ',' .. (i-1)) + else + -- se è l'unico + EgtSetInfo( nPathInt, 'OPEN', (i-1)) + end + end + end + end + return false +end + +--------------------------------------------------------------------- +local function CalcCollisionSafety( vtDir) + local dCollSic = 10 * BD.COLL_SIC + if abs( vtDir:getX()) > 0.999 or abs( vtDir:getY()) > 0.999 or abs( vtDir:getZ()) > 0.999 then + dCollSic = 0 + elseif abs( vtDir:getX()) > 0.996 or abs( vtDir:getY()) > 0.996 or abs( vtDir:getZ()) > 0.996 then + dCollSic = 1 * BD.COLL_SIC + elseif abs( vtDir:getX()) > 0.89 or abs( vtDir:getY()) > 0.89 or abs( vtDir:getZ()) > 0.89 then + dCollSic = 2.5 * BD.COLL_SIC + elseif abs( vtDir:getX()) > 0.86 or abs( vtDir:getY()) > 0.86 or abs( vtDir:getZ()) > 0.86 then + dCollSic = 4 * BD.COLL_SIC + elseif abs( vtDir:getX()) > 0.707 or abs( vtDir:getY()) > 0.707 or abs( vtDir:getZ()) > 0.707 then + dCollSic = 5.5 * BD.COLL_SIC + end + return dCollSic +end + +--------------------------------------------------------------------- +local function MakeBySidePocket( Proc, nPhase, nRawId, nPartId, nAddGrpId, b3Solid) +-- nOk, sErr, dDimMin, dDimMax, dDepth, vtOrtho, nLundIdFace, dDiamTool, bDoubleSide, nPathInt, nSurfInt, bOneShot, bMillDown, nFirstMachId, +-- bOrthoFaces = MakeByPockets( Proc, nPhase, nRawId, nPartId, NO nChamfer, NO dDepthCham, nAddGrpId, NO sMyMchFind, NO bIs3Faces, b3Solid, NO bOrthoFacesMaster, NO bMillDown, NO bSetOpenBorders) + + local nFirstMachId + local sWarn + local sMchFind = 'OpenPocket' + local dDimMin, dDimMax, dDepth, vtOrtho, nLundIdFace, nSurfInt + local bBadMach = false + + -- ottengo le dimensioni del tunnel + dDimMin, dDimMax, dDepth, vtOrtho, nLundIdFace, nSurfInt = GetTunnelDimension( Proc, nPartId) + -- posso utilizzare utensile con diametro doppio della dimensione minima + dDimMin = min( 2 * dDimMin, BD.MAXDIAM_POCK_CORNER) + local nPathInt + -- calcolo se è lavorabile da sotto + bMillDown = ( BD.DOWN_HEAD == true and abs( vtOrtho:getZ()) >= 0.707) + -- verifico se può essere fatto con svuotatura + local bMakePocket, sPocketing, dMaxDepth, dDiamTool = VerifyPocket( Proc, dDimMin, dDepth / 2, nil, sMchFind) + local bMakePocketDn, sPocketingDn, dMaxDepthDn, dDiamToolDn + if bMillDown then + bMakePocketDn, sPocketingDn, dMaxDepthDn, dDiamToolDn = VerifyPocket( Proc, dDimMin, dDepth / 2, nil, sMchFind, true) + -- se è negativo inverto il versore e la faccia + if vtOrtho:getZ() < 0 then + vtOrtho = -vtOrtho + EgtInvertSurf( nSurfInt) + end + end + if bMakePocket then + -- gestione svuotatura da un solo lato o anche dal lato opposto (se non verticale) + -- estraggo il contorno dalla superfice per evitare i problemi con la svuotatura + -- e assegno l'estrusione + nPathInt = EgtExtractSurfTmLoops( nSurfInt, nAddGrpId) + EgtModifyCurveExtrusion( nPathInt, vtOrtho, GDB_RT.GLOB) + SetOpenSide( nPathInt, vtOrtho, b3Solid, nAddGrpId) + -- variabili per parametri lavorazione + local dMachDepth + local dElev = 0 + local bDoubleSide + local bOneShot + local bComplete = true + -- imposto altezza aggiuntiva di elevazione + local dCollSic = CalcCollisionSafety( vtOrtho) + -- se possibile svuotare completamente da una sola parte + if dMaxDepth > ( dDepth + BD.CUT_EXTRA + dCollSic) then + dMachDepth = ( dDepth / 2) + BD.CUT_EXTRA + dElev = dDepth + BD.CUT_EXTRA + bOneShot = true + else + -- se direzione verso la verticale setto max affondamento possibile ed + -- emetto messaggio di warning perché non lavorabile interamente + if abs( vtOrtho:getZ()) >= 0.707 and not BD.DOWN_HEAD then + dMachDepth = dMaxDepth - ( dDepth / 2) - dCollSic + dElev = dMaxDepth + sWarn = 'Warning : elevation bigger than max tool depth' + EgtOutLog( sWarn) + bComplete = false + -- altrimenti setto il flag per fare la svuotatura da due parti + else + -- se l'altezza utensile riesce a lavorare completamente da due parti + if dMaxDepth > ( dDepth / 2) + dCollSic + BD.CUT_EXTRA_MIN then + dMachDepth = BD.CUT_EXTRA_MIN + dElev = ( dDepth / 2) + BD.CUT_EXTRA_MIN + -- altrimenti non si riesce in due passate, limito la profondità e setto l'elevazione + else + dMachDepth = dMaxDepth - ( dDepth / 2) - dCollSic + dElev = dMaxDepth + -- se molto inclinato rispetto alla normale della faccia di riferimento, lavorazione non idonea per probabili collisioni + local vtRef = Y_AX() + if abs( vtOrtho:getX()) > abs( vtOrtho:getY()) and abs( vtOrtho:getX()) > abs( vtOrtho:getZ()) then + vtRef = X_AX() + elseif abs( vtOrtho:getZ()) > abs( vtOrtho:getX()) and abs( vtOrtho:getZ()) > abs( vtOrtho:getY()) then + vtRef = Z_AX() + end + if abs( vtOrtho * vtRef) < 0.5 then + bBadMach = true + end + end + bDoubleSide = true + end + end + -- inserisco la lavorazione di svuotatura + local sName = 'Pock_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) + local nMchFId = EgtAddMachining( sName, sPocketing) + if not nMchFId then + local sErr = 'Error adding machining ' .. sName .. '-' .. sPocketing + EgtOutLog( sErr) + return -1, sErr + end + -- prendo l'id della prima lavorazione inserita + if not nFirstMachId then + nFirstMachId = nMchFId + end + -- aggiungo geometria + EgtSetMachiningGeometry( {{ nPathInt, -1}}) + -- verifico se devo invertire direzione utensile (in caso di direzione verso la verticale) + local bInvertMach + if vtOrtho:getZ() < BD.NZ_MINA and abs(vtOrtho:getZ()) >= 0.707 and not BD.DOWN_HEAD then + EgtSetMachiningParam( MCH_MP.TOOLINVERT, true) + bInvertMach = true + -- altrimenti se da fare in una sola volta e direzionato verso Y+ lo inverto per lavorarlo davanti + elseif not bDoubleSide and vtOrtho:getY() > GEO.EPS_SMALL and not ( -(vtOrtho:getZ()) < BD.NZ_MINA) then + EgtSetMachiningParam( MCH_MP.TOOLINVERT, true) + bInvertMach = true + end + -- imposto posizione braccio porta testa + local nSCC = MCH_SCC.NONE + if not BD.C_SIMM then + if AreSameOrOppositeVectorApprox( vtOrtho, Z_AX()) then + nSCC = MCH_SCC.ADIR_YM + elseif abs( vtOrtho:getX()) < 0.1 then + nSCC = EgtIf( BL.IsPartFinalPhase( nPhase), MCH_SCC.ADIR_XM, MCH_SCC.ADIR_XP) + elseif vtOrtho:getY() < GEO.EPS_SMALL then + nSCC = EgtIf( bInvertMach, MCH_SCC.ADIR_YP, MCH_SCC.ADIR_YM) + else + nSCC = EgtIf( bInvertMach, MCH_SCC.ADIR_YM, MCH_SCC.ADIR_YP) + end + end + EgtSetMachiningParam( MCH_MP.SCC, nSCC) + EgtSetMachiningParam( MCH_MP.SUBTYPE, MCH_POCK_SUB.SPIRALIN) + -- inverto il percorso di lavorazione per lavorare sinistro + EgtSetMachiningParam( MCH_MP.INVERT, true) + -- imposto affondamento + EgtSetMachiningParam( MCH_MP.DEPTH, dMachDepth) + -- imposto elevazione e dichiaro non si generano sfridi per VMill + local sNotes = 'MaxElev=' .. EgtNumToString( dElev, 1) .. ';' + sNotes = sNotes .. 'VMRS=0;' + EgtSetMachiningParam( MCH_MP.USERNOTES, sNotes) + -- eseguo + if not ML.ApplyMachining( true, false) then + -- provo ad allargare leggermente la tasca + EgtSetMachiningParam( MCH_MP.OFFSR, -0.1) + if not ML.ApplyMachining( true, false) then + local _, sErr = EgtGetLastMachMgrError() + EgtSetOperationMode( nMchFId, false) + return -1, sErr + end + end + -- se posso applicare la svuotatura sul lato opposto + if bDoubleSide then + -- se ho la lavorazione da sotto ricalcolo in base a questa lavorazione + if bMakePocketDn then + -- sPocketing = sPocketingDn + -- dMaxDepth = dMaxDepthDn + -- dDiamTool = dDiamToolDn + -- se l'altezza utensile riesce a lavorare completamente da due parti + if dMaxDepthDn > ( dDepth / 2) + dCollSic + BD.CUT_EXTRA_MIN then + dMachDepth = BD.CUT_EXTRA_MIN + dElev = ( dDepth / 2) + BD.CUT_EXTRA_MIN + -- altrimenti non si riesce in due passate, limito la profondità e setto l'elevazione + else + dMachDepth = dMaxDepthDn - ( dDepth / 2) - dCollSic + dElev = dMaxDepthDn + bComplete = false + sWarn = 'Warning : elevation bigger than max tool depth' + EgtOutLog( sWarn) + end + else + -- se anche lavorando dal lato opposto non riesco a svuotare completamente la fessura + -- setto i parametri affondamento ed emetto warning + if dMaxDepth < ( dDepth / 2) + BD.CUT_EXTRA + dCollSic then + dMachDepth = dMaxDepth - (dDepth / 2) - dCollSic + dElev = dMaxDepth + bComplete = false + sWarn = 'Warning : elevation bigger than max tool depth' + EgtOutLog( sWarn) + end + end + -- inserisco la lavorazione di svuotatura + local sName = 'PockOppo_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) + local nMchFId = EgtAddMachining( sName, EgtIf( bMakePocketDn, sPocketingDn, sPocketing)) + if not nMchFId then + local sErr = 'Error adding machining ' .. sName .. '-' .. EgtIf( bMakePocketDn, sPocketingDn, sPocketing) + EgtOutLog( sErr) + return -1, sErr + end + -- prendo l'id della prima lavorazione inserita + if not nFirstMachId then + nFirstMachId = nMchFId + end + -- aggiungo geometria + EgtSetMachiningGeometry( {{ nPathInt, -1}}) + -- imposto direzione utensile opposta + EgtSetMachiningParam( MCH_MP.TOOLINVERT, true) + -- imposto posizione braccio porta testa + local nSCC = MCH_SCC.NONE + if not BD.C_SIMM then + if AreSameVectorApprox( vtOrtho, Z_AX()) then + nSCC = MCH_SCC.ADIR_YM + elseif abs( vtOrtho:getX()) < 0.1 then + nSCC = EgtIf( BL.IsPartFinalPhase( nPhase), MCH_SCC.ADIR_XM, MCH_SCC.ADIR_XP) + elseif vtOrtho:getY() < GEO.EPS_SMALL then + nSCC = MCH_SCC.ADIR_YP + else + nSCC = MCH_SCC.ADIR_YM + end + end + EgtSetMachiningParam( MCH_MP.SCC, nSCC) + EgtSetMachiningParam( MCH_MP.SUBTYPE, MCH_POCK_SUB.SPIRALIN) + -- inverto il percorso di lavorazione per lavorare sinistro + EgtSetMachiningParam( MCH_MP.INVERT, true) + -- imposo affondamento + EgtSetMachiningParam( MCH_MP.DEPTH, dMachDepth) + -- imposto elevazione e dichiaro non si generano sfridi per VMill + local sNotes = 'MaxElev=' .. EgtNumToString( dElev, 1) .. ';' + sNotes = sNotes .. 'VMRS=0;' + EgtSetMachiningParam( MCH_MP.USERNOTES, sNotes) + -- eseguo + if not ML.ApplyMachining( true, false) then + -- provo ad allargare leggermente la tasca + EgtSetMachiningParam( MCH_MP.OFFSR, -0.1) + if not ML.ApplyMachining( true, false) then + local _, sErr = EgtGetLastMachMgrError() + EgtSetOperationMode( nMchFId, false) + return -1, sErr + end + end + end + return 1, sWarn, dDimMin, dDimMax, dDepth, vtOrtho, nLundIdFace, dDiamTool, bDoubleSide, nPathInt, nSurfInt, bOneShot, bMillDown, nFirstMachId + end + return 0, sWarn, dDimMin, dDimMax, dDepth, vtOrtho, nLundIdFace, dDiamTool, bDoubleSide, nPathInt, nSurfInt, bOneShot, bMillDown, nFirstMachId, bOrthoFaces +end + --------------------------------------------------------------------- -- Applicazione della lavorazione function ProcessDoubleCut.Make( Proc, nPhase, nRawId, nPartId, dOvmHead) @@ -293,10 +656,8 @@ function ProcessDoubleCut.Make( Proc, nPhase, nRawId, nPartId, dOvmHead) local bFace1TooLongForBlade, bFace2TooLongForBlade = ( dDimV1 >= dMaxDepth), ( dDimV2 >= dMaxDepth) local dFace1Ang, dFace2Ang = vtN[1]:getZ(), vtN[2]:getZ() if bFace1TooLongForBlade and dFace1Ang < -0.485 or bFace2TooLongForBlade and dFace2Ang < -0.485 then - -- local bOk, sErr = LapJoint.Make( Proc, nPhase, nRawId, nPartId, dOvmHead) - -- if not bOk then - -- return bOk, sErr - -- end + local bOk, sErr = MakeBySidePocket( Proc, nPhase, nRawId, nPartId, nAddGrpId, b3Solid) + return bOk, sErr end end