-- FacesBySaw.lua by Egaltech s.r.l. 2022/04/12 -- Gestione taglio con lama di feature con una o due facce -- 2021/01/06 Cambiato limite per attacco Tg con lama e CalcLeadInOutGeom rinominata in CalcLeadInOutPerpGeom. -- 2021/02/03 In taglio lama si accettano anche due lati con deviazione minore di 20deg. -- 2021/02/09 In taglio lama con PF si preferisce testa in Y- quindi SCC di conseguenza. -- 2021/02/26 In taglio lama consento attacco anche da sotto (grazie a migliorie in MachKernel). -- 2021/03/22 Attacchi e uscite di tagli longitudinali da sotto con lama solo ortogonali. -- 2021/04/27 Migliorati controlli per attacchi e uscite Tg con lama. -- 2021/07/08 Modifiche in MakeOneFaceBySaw per gestione taglio con due segmenti. -- 2021/08/03 In MakeOneFaceBySaw mgliorata gestione tagli con normale verso il basso e da sopra. -- 2021/08/31 DS Aggiunta gestione nessun limite direzione da sotto per testa da sotto. -- 2021/11/26 DS Spostate qui MakeOneFaceBySaw (ora MakeOne), CalcLeadInOutPerpGeom e CalcLeadInOutTangGeom. -- 2022/04/12 DS Aggiunta gestione speciale cubetti con fresa da sotto. -- Tabella per definizione modulo local FacesBySaw = {} -- Include require( 'EgtBase') local BL = require( 'BeamLib') local DC = require( 'DiceCut') EgtOutLog( ' FacesBySaw started', 1) -- Dati local BD = require( 'BeamData') local ML = require( 'MachiningLib') --------------------------------------------------------------------- function FacesBySaw.MakeOne( nSurfId, nFacet, sCutting, dSawDiam, Par5, dVzLimDwnUp, dCutExtra, dCutSic, dCutOffset, dAccStart, dAccEnd, sNotes, b3Raw) -- dati della faccia local ptC, vtN = EgtSurfTmFacetCenter( nSurfId, nFacet, GDB_ID.ROOT) -- risolvo parametro ambiguo local nOrthoOpposite local vtOrthO if isVector3d( Par5) then nOrthoOpposite = BL.GetNearestOrthoOpposite( Par5, vtN) vtOrthO = Vector3d( Par5) else nOrthoOpposite = Par5 vtOrthO = BL.GetVersRef( Par5) end -- verifico se testa da sotto local bDownHead = ( dVzLimDwnUp and dVzLimDwnUp < - 1.5) -- linea o bilinea di lavorazione (qui uso nOrthoOpposite per ripetere esattamente il calcolo del Mach) local ptP1, ptPm, ptP2, vtV1, vtV2, dLen, dWidth = EgtSurfTmFacetOppositeSide( nSurfId, nFacet, BL.GetVersRef( nOrthoOpposite), GDB_ID.ROOT) if not dLen or dLen < 1.1 or not dWidth or dWidth < 1.1 then local sWarn = 'Face ' .. string.format( '%d,%d', nSurfId, nFacet) .. ' skipped : too small' EgtOutLog( sWarn, 1) return true, '' end vtV1 = - vtV1 local bInvert = ( ptP2:getZ() < ptP1:getZ() - 100 * GEO.EPS_SMALL) if bInvert then ptP1, ptP2 = ptP2, ptP1 vtV1, vtV2 = vtV2, vtV1 end local vtTg = ptP2 - ptP1 ; vtTg:normalize() local dAllStart = 0 local dAllEnd = 0 -- se bilinea, scarto la parte più allineata con la direzione ortogonale (se deviazione angolare oltre 20 deg o lunghezza minore di dSawDiam/2 * cos( 20/2)) ma maggiore di un minimo if ( ( ptPm - ptP1) - ( ptPm - ptP1) * vtTg * vtTg):len() > 100 * GEO.EPS_SMALL then local vtTg1 = ptPm - ptP1 ; vtTg1:normalize() local vtTg2 = ptP2 - ptPm ; vtTg2:normalize() local dDist1 = dist( ptP1, ptPm) local dDist2 = dist( ptP2, ptPm) local dCosMax = 0.951 -- cos( 18°) local dLenMin = 30 local dLenMax = max( 0.5 * dSawDiam * 0.17365 + 1, 2 * dLenMin) --if vtTg1 * vtTg2 < dCosMax or ( dDist1 < dLenMax and dDist1 > dLenMin) or ( dDist2 < dLenMax and dDist2 > dLenMin) then if vtTg1 * vtTg2 < dCosMax then local dOrtho1 = abs( vtTg1 * vtOrthO) local dOrtho2 = abs( vtTg2 * vtOrthO) if dOrtho1 < dOrtho2 or ( abs( dOrtho1 - dOrtho2) < 0.1 and dDist1 > 4 * dDist2) then if dDist1 > dLenMin or dDist1 > 0.5 * dDist2 then ptP2 = Point3d( ptPm) dAllEnd = - dDist2 - 10 * GEO.EPS_SMALL end else if dDist2 > dLenMin or dDist2 > 0.5 * dDist1 then ptP1 = Point3d( ptPm) dAllStart = - dDist1 - 10 * GEO.EPS_SMALL end end vtTg = ptP2 - ptP1 ; vtTg:normalize() end end -- verifico se lavorazione con lama sotto e testa sopra if not dVzLimDwnUp then dVzLimDwnUp = BL.GetNzLimDownUp( b3Raw, vtN, vtOrthO) end local bDownUp = ( vtN:getZ() < dVzLimDwnUp) local nFaceUse = nOrthoOpposite if bDownUp then nFaceUse = BL.GetOrtupOpposite( nOrthoOpposite) end local bWsRight = ( bInvert ~= bDownUp) local nWorkSide = EgtIf( bWsRight, MCH_MILL_WS.RIGHT, MCH_MILL_WS.LEFT) -- Versore di riferimento local vtRef = Vector3d( vtTg) vtRef:rotate( vtN, EgtIf( bInvert, -90, 90)) -- Versore esterno local vtOut = vtRef - vtRef * vtTg * vtTg ; vtOut:normalize() -- Versore ausiliario (direzione braccio) local vtAux = Vector3d( vtN:getX(), vtN:getY(), 0) ; vtAux:normalize() vtAux:rotate( Z_AX(), EgtIf( bWsRight, 90, -90)) if vtAux:isSmall() then vtAux = Vector3d( vtOut:getX(), vtOut:getY(), 0) ; vtAux:normalize() else if abs( vtAux * vtOut) < GEO.EPS_SMALL then if abs( vtTg:getZ()) > 0.5 then if vtAux * vtRef < 0 then vtAux = - vtAux end elseif vtAux * vtTg > 0 then vtAux = - vtAux end elseif vtAux * vtOut < 0 then vtAux = - vtAux end end -- parametri di attacco/uscita local b3Box = BBox3d( b3Raw) b3Box:expand( dCutSic) local ptP1act = ptP1 + vtN * dCutOffset local ptP2act = ptP2 + vtN * dCutOffset -- attacco perpendicolare local dLiTang, dLiPerp, dLoTang, dLoPerp = FacesBySaw.CalcLeadInOutPerpGeom( ptP1act, ptP2act, vtV1, vtV2, vtN, dSawDiam/2, vtRef, dCutExtra, b3Box) local dLenLi = sqrt( dLiTang * dLiTang + dLiPerp * dLiPerp) local dLenLo = sqrt( dLoTang * dLoTang + dLoPerp * dLoPerp) -- attacco tangente local dLi2Tang, dLi2Perp, dLo2Tang, dLo2Perp = FacesBySaw.CalcLeadInOutTangGeom( ptP1act, ptP2act, vtN, dSawDiam/2, vtRef, dCutExtra, b3Box) local dLenLi2 = abs( dLi2Tang) local dLenLo2 = abs( dLo2Tang) -- scelgo l'attacco più conveniente (se non taglio praticamente longitudinale) local Ktp = 1.1 if BD.KIOTP then Ktp = BD.KIOTP end if ( not bDownUp or abs( vtTg:getY()) > 0.5) and ( not bDownHead or abs( vtTg:getZ()) < 0.51) and abs( vtTg:getX()) < 0.9848 and ( ( abs( vtTg:getZ()) < 0.17 and ( vtV1:getZ() < -0.5 or vtV2:getZ() < -0.5)) or ( abs( vtTg:getZ()) < 0.51 and b3Box:getDimZ() > 300 and BD.C_SIMM and BD.MAX_HEIGHT > 450) or ( Ktp * dLenLi2 < dLenLi and Ktp * dLenLo2 < dLenLo) or Ktp * ( dLenLi2 + dLenLo2) < ( dLenLi + dLenLo)) then dLiTang, dLiPerp, dLoTang, dLoPerp = dLi2Tang, dLi2Perp, dLo2Tang, dLo2Perp end -- posizione braccio EgtOutLog( 'vtN=' .. tostring( vtN) .. ' vtRef=' .. tostring( vtRef) .. ' vtOut=' .. tostring( vtOut) .. ' vtAux=' .. tostring( vtAux), 3) local nSCC = MCH_SCC.NONE if not BD.TURN then if abs( vtAux:getX()) > abs( vtAux:getY()) - GEO.EPS_SMALL then nSCC = EgtIf( ( vtAux:getX() > -GEO.EPS_SMALL), MCH_SCC.ADIR_XP, MCH_SCC.ADIR_XM) else nSCC = EgtIf( ( vtAux:getY() > -GEO.EPS_SMALL), MCH_SCC.ADIR_YP, MCH_SCC.ADIR_YM) end else nSCC = MCH_SCC.ADIR_ZP end -- inserisco la lavorazione di taglio local sName = 'Cut_' .. ( EgtGetName( nSurfId) or tostring( nSurfId)) .. '_' .. tostring( nFacet + 1) local nMchFId = EgtAddMachining( sName, sCutting) if not nMchFId then local sErr = 'Error adding machining ' .. sName .. '-' .. sCutting EgtOutLog( sErr) return false, sErr end sName = EgtGetOperationName( nMchFId) -- aggiungo geometria EgtSetMachiningGeometry( {{ nSurfId, nFacet}}) -- imposto uso faccia EgtSetMachiningParam( MCH_MP.FACEUSE, nFaceUse) -- imposto posizione braccio porta testa EgtSetMachiningParam( MCH_MP.SCC, nSCC) -- imposto inversione e lato correzione EgtSetMachiningParam( MCH_MP.INVERT, bInvert) EgtSetMachiningParam( MCH_MP.WORKSIDE, nWorkSide) -- affondamento aggiuntivo EgtSetMachiningParam( MCH_MP.OFFSR, -dCutExtra) -- offset longitudinale EgtSetMachiningParam( MCH_MP.OFFSL, EgtIf( bDownUp, -dCutOffset, dCutOffset)) -- imposto attacco/uscita EgtSetMachiningParam( MCH_MP.LITANG, dLiTang) EgtSetMachiningParam( MCH_MP.LIPERP, dLiPerp) EgtSetMachiningParam( MCH_MP.LOTANG, dLoTang) EgtSetMachiningParam( MCH_MP.LOPERP, dLoPerp) -- imposto allungamenti iniziale e finale EgtSetMachiningParam( MCH_MP.STARTADDLEN, dAllStart - dAccStart) EgtSetMachiningParam( MCH_MP.ENDADDLEN, dAllEnd - dAccEnd) -- eventuali note if sNotes and #sNotes > 0 then EgtSetMachiningParam( MCH_MP.USERNOTES, sNotes) end -- eseguo if not EgtApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchFId, false) return false, sErr end return true, sName, nMchFId end --------------------------------------------------------------------- function FacesBySaw.MakeTwo( Proc, nPhase, nRawId, nPartId, dOvmHead, sCutType, bUpdateIng, bDownHead) -- bUpdateIng : parametro opzionale con default true if bUpdateIng == nil then bUpdateIng = true end -- recupero l'ingombro del grezzo di appartenenza local b3Raw = EgtGetRawPartBBox( nRawId) -- ingombro del pezzo local Ls = EgtGetFirstNameInGroup( nPartId, '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 -- verifico il numero di facce if Proc.Fct < 2 then local sErr = 'Error : TwoFacesBySaw facet number not supported' EgtOutLog( sErr) return false, sErr end -- dati delle facce local ptC = {} local vtN = {} ptC[1], vtN[1] = EgtSurfTmFacetCenter( Proc.Id, 0, GDB_ID.ROOT) ptC[2], vtN[2] = EgtSurfTmFacetCenter( Proc.Id, 1, GDB_ID.ROOT) -- verifico non siano orientate verso il basso local bFaceOk = {} bFaceOk[1] = ( vtN[1]:getZ() >= BD.NZ_MINB) bFaceOk[2] = ( vtN[2]:getZ() >= BD.NZ_MINB) if not bDownHead and not bFaceOk[1] and not bFaceOk[2] then local sErr = 'Error : TwoFacesBySaw from bottom impossible' EgtOutLog( sErr) return false, sErr end -- recupero dati su giunzione tra facce local bTouch, ptT1, ptT2, dAngT = EgtSurfTmFacetsContact( Proc.Id, 0, 1, GDB_ID.ROOT) if not bTouch then local sErr = 'Error : TwoFacesBySaw faces not touching' EgtOutLog( sErr) return false, sErr end -- calcolo direzione di lavoro local vtRef = {} local vtTg = ptT2 - ptT1 ; vtRef[1] = vtN[1] ^ vtTg if vtRef[1] * vtN[2] < 0 then vtRef[1] = - vtRef[1] end vtRef[1]:normalize() vtRef[2] = vtN[2] ^ vtTg if vtRef[2] * vtN[1] < 0 then vtRef[2] = - vtRef[2] end vtRef[2]:normalize() -- determino quale faccia è più grande local ptPs = ( ptT1 + ptT2) / 2 local dSqDim1 = ( ptC[1] - ptPs):sqlen() local dSqDim2 = ( ptC[2] - ptPs):sqlen() local nBigInd = EgtIf( dSqDim1 > dSqDim2 - 1., 1, 2) local nSmaInd = 3 - nBigInd local nUpInd = EgtIf( vtN[1]:getZ() > vtN[2]:getZ() - GEO.EPS_SMALL, 1, 2) local nOtInd = 3 - nUpInd -- metto in relazione la scelta facce con il confronto del versore Z con la scelta in base alla grandezza faccia -- se la faccia più grande è messa secondaria e il suo versore Z non è negativo if nOtInd == nBigInd and vtN[nBigInd]:getZ() > -5 * GEO.EPS_SMALL and vtN[nSmaInd]:getZ() < 0.866 then nOtInd = nSmaInd nUpInd = nBigInd end -- recupero la lavorazione local sCutting = ML.FindCutting( sCutType) if not sCutting then local sErr = 'Error on process ' .. tostring( Proc.Id) .. ' cutting not found in library' EgtOutLog( sErr) return false, sErr end -- recupero i dati dell'utensile local dSawDiam = 400 local dSawThick = 5 if EgtMdbSetCurrMachining( sCutting) 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 end end -- calcolo extra taglio local dCutExtra = 0 if dAngT < -91 and dAngT > -179 then dCutExtra = - dSawThick / tan( 180 + dAngT) end -- sistemo direzione limite da sotto (con testa da sotto limite Vz Down Up messo a -2 per non farlo mai intervenire) local dNzLimDwnUp if bDownHead then dNzLimDwnUp = - 2 end -- verifico se necessari tagli supplementari local vCuts = DC.GetDice( EgtGetParent( Proc.Id), b3Solid, ptC[nUpInd], vtN[nUpInd], false, ptC[nOtInd], vtN[nOtInd]) --DC.PrintOrderCut( vCuts) if #vCuts > 0 then -- recupero gruppo per geometria addizionale local nAddGrpId = BL.GetAddGroup( nPartId) if not nAddGrpId then local sErr = 'Error : missing AddGroup' EgtOutLog( sErr) return false, sErr end -- sistemo posizione nel DB e nome for i = 1, #vCuts do for j = 1, #vCuts[i] do EgtRelocateGlob( vCuts[i][j], nAddGrpId) EgtSetName( vCuts[i][j], 'AddCut_' .. tostring( Proc.Id)) EgtSetInfo( vCuts[i][j], 'TASKID', Proc.TaskId) end end -- con testa da sopra if not bDownHead then -- eseguo for i = 1, #vCuts do -- assegno il modo di tagliare local vtOrthO = EgtIf( ( i % 2) == 1, vtRef[nOtInd], vtRef[nUpInd]) -- lavoro la faccia for j = 1, #vCuts[i] do -- se FAST, pezzo alto e ultimo taglio verticale -> allungo uscita per consentire eventuale rotazione B sul posto local dAccEnd = 0 if not BD.C_SIMM and BD.MAX_HEIGHT_ROT_B_ABOVE and b3Raw:getDimZ() > BD.MAX_HEIGHT_ROT_B_ABOVE and vtOrthO:getZ() > 0.866 and j == #vCuts[i] then dAccEnd = - ( dSawDiam / 2 + BD.CUT_SIC) end local bOk, sErr = FacesBySaw.MakeOne( vCuts[i][j], 0, sCutting, dSawDiam, vtOrthO, dNzLimDwnUp, dCutExtra, BD.CUT_SIC, 0, 0, dAccEnd, nil, b3Raw) if not bOk then return bOk, sErr end end end -- altrimenti con testa da sotto else -- eseguo (facendo di seguito i due tagli di ogni singolo cubetto) for i = 1, #vCuts, 2 do -- determino il modo di tagliare dei perpendicolari local vtOrthoO_1 = Vector3d( vtN[nUpInd]) -- determino il modo di tagliare dei paralleli local vtOrthoO_2 local bNoPerpCuts_2 = false local vtO if #vCuts[i] > 0 then vtO = EgtSurfTmFacetNormVersor( vCuts[i][1], 0, GDB_ID.ROOT) elseif vCuts[i+2] and #vCuts[i+2] > 0 then -- lunghezza faccia nell'eventuale direzione ortogonale local asseX = EgtSurfTmFacetNormVersor( vCuts[i+2][1], 0, GDB_ID.ROOT) local asseY = asseX ^ vtN[nUpInd] local Frame = Frame3d( ptC, ptC + asseX, ptC + asseY) local b3Fac = EgtGetBBoxRef( vCuts[i+1][1], GDB_BB.STANDARD, Frame) -- se lunghezza inferiore al limite, accetto la direzione if b3Fac:getDimX() < dMaxDepth - BD.CUT_EXTRA then vtO = asseX else bNoPerpCuts_2 = true end else bNoPerpCuts_2 = true end if vtO then vtOrthoO_2 = Vector3d( vtO) else if bHorizCut then vtOrthoO_2 = -Z_AX() elseif vtN:getY() > -0.02 then if not Proc.Head then vtOrthoO_2 = -Y_AX() else vtOrthoO_2 = Y_AX() end else vtOrthoO_2 = -Y_AX() end end -- lavoro le coppie di facce del singolo cubetto for j = 1, max( #vCuts[i], #vCuts[i+1]) do -- extra taglio per perpendicolari local dExtraCut_1 = -0.1 -- extra taglio per paralleli local dExtraCut_2 = -0.1 -- se non ci sono tagli ortogonali devo affondare if bNoPerpCuts_2 then dExtraCut_2 = BD.CUT_EXTRA end -- taglio perpendicolare (limite Vz Down Up messo a -2 per non farlo mai intervenire) if vCuts[i][j] then local bOk, sErr = FacesBySaw.MakeOne( vCuts[i][j], 0, sCutting, dSawDiam, vtOrthoO_1, -2, dExtraCut_1, BD.CUT_SIC, 0, 0, 0, nil, b3Raw) if not bOk then return bOk, sErr end end -- taglio parallelo (limite Vz Down Up messo a -2 per non farlo mai intervenire) if vCuts[i+1][j] then local bOk, sErr = FacesBySaw.MakeOne( vCuts[i+1][j], 0, sCutting, dSawDiam, vtOrthoO_2, -2, dExtraCut_2, BD.CUT_SIC, 0, 0, 0, nil, b3Raw) if not bOk then return bOk, sErr end end end end end else nUpInd = EgtIf( vtN[1]:getZ() > vtN[2]:getZ() - GEO.EPS_SMALL, 1, 2) nOtInd = 3 - nUpInd -- se prima faccia lavorata è da sotto scambio le facce if vtN[nOtInd]:getZ() < -0.5 then nUpInd, nOtInd = nOtInd, nUpInd end -- lavoro la prima faccia local bOk, sErr = FacesBySaw.MakeOne( Proc.Id, nOtInd-1, sCutting, dSawDiam, vtRef[nOtInd], dNzLimDwnUp, dCutExtra, BD.CUT_SIC, 0, 0, 0, nil, b3Raw) if not bOk then return bOk, sErr end -- lavoro seconda faccia bOk, sErr = FacesBySaw.MakeOne( Proc.Id, nUpInd-1, sCutting, dSawDiam, vtRef[nUpInd], dNzLimDwnUp, dCutExtra, BD.CUT_SIC, 0, 0, 0, nil, b3Raw) if not bOk then return bOk, sErr end end -- eventuale segnalazione ingombro di testa o coda local dMinHIng = min( 0.5 * BD.VICE_MINH, 0.5 * b3Raw:getDimZ()) if bUpdateIng and Proc.Box:getDimZ() > dMinHIng and Proc.Box:getMin():getZ() < b3Raw:getMin():getZ() + dMinHIng and not ( abs( vtN[nBigInd]:getX()) < 0.05 and vtN[nBigInd]:getY() < 0 and Proc.Box:getDimX() > 500) then if Proc.Head then local dOffs = b3Solid:getMax():getX() - Proc.Box:getMin():getX() BL.UpdateHCING( nRawId, dOffs) elseif Proc.Tail then local dOffs = Proc.Box:getMax():getX() - b3Solid:getMin():getX() BL.UpdateTCING( nRawId, dOffs) elseif Proc.Box:getCenter():getX() > b3Solid:getCenter():getX() then local dOffs = b3Solid:getMax():getX() - Proc.Box:getMin():getX() local dDist = b3Solid:getMax():getX() - Proc.Box:getMax():getX() -- se concavo aumento la distanza (rimane una punta...) if dAngT < 0 then dDist = dDist + 10 end BL.UpdateHCING( nRawId, dOffs, dDist) end end return true end --------------------------------------------------------------------- function FacesBySaw.CalcLeadInOutPerpGeom( ptP1, ptP2, vtV1, vtV2, vtN, dRad, vtRef, dCutExtra, b3Box) -- Mi assicuro che i vettori ingresso/uscita giacciano nel piano vtV1 = vtV1 - vtV1 * vtN * vtN ; vtV1:normalize() vtV2 = vtV2 - vtV2 * vtN * vtN ; vtV2:normalize() -- Versore tangente al taglio local vtTg = ptP2 - ptP1 ; vtTg = vtTg - vtTg * vtN * vtN ; vtTg:normalize() -- Sistema di riferimento intrinseco al taglio local vtX = vtTg ^ vtN local frFace = Frame3d( ptP1, vtX, vtTg, vtN) EgtOutLog( 'Vref=' .. tostring( vtRef) .. ' V1=' .. tostring( vtV1) .. ' V2=' .. tostring( vtV2), 3) -- Versori di attacco e uscita local dCos1 = vtV1 * vtRef local dCos2 = vtV2 * vtRef local vtLi, vtLo if abs( dCos1 - dCos2) < 0.001 then if abs( vtV1:getZ()) < abs( vtV2:getZ()) then vtLi = vtV1 vtLo = vtV1 else vtLi = vtV2 vtLo = vtV2 end elseif dCos1 > dCos2 then vtLi = vtV1 vtLo = vtV1 else vtLi = vtV2 vtLo = vtV2 end local bRight = ( vtX * vtLi > 0) -- Versori di attacco e uscita nel riferimento intrinseco al taglio local vtLiL = Vector3d( vtLi) ; vtLiL:toLoc( frFace) local vtLoL = Vector3d( vtLo) ; vtLoL:toLoc( frFace) -- Spostamento punti per effetto dell'extra o della deficienza di taglio ptP1 = ptP1 + vtX * ( EgtIf( bRight, - dCutExtra, dCutExtra)) ptP2 = ptP2 + vtX * ( EgtIf( bRight, - dCutExtra, dCutExtra)) -- Non va considerata l'uscita dalla faccia sotto, pertanto va abbassata -- 2021/02/26 Abilito anche uscita sotto local b3MyBox = BBox3d( b3Box) ; --b3MyBox:Add( b3MyBox:getMin() - 1000 * Z_AX()) -- Attacco local dLiTang = 10000 local dLiPerp = 10000 local bLiOk, _, vLiPar = EgtLineBoxInters( ptP1, vtLi, b3MyBox) if bLiOk and #vLiPar > 0 then -- con la prima faccia di uscita local dLen = vLiPar[#vLiPar] local ptInt = ptP1 + vtLi * dLen local vtFN = BL.GetBoxFaceNorm( b3MyBox, ptInt, vtLi) EgtOutLog( 'LiFaceNorm=' .. tostring( vtFN), 3) local dAddLen = dRad * ( sqrt( 1 - ( vtN * vtFN) * ( vtN * vtFN)) - abs( vtX * vtFN)) / ( vtLi * vtFN) local dLiLen = dLen + dAddLen EgtOutLog( 'LeadIn Dist=' .. EgtNumToString( dLiLen), 3) dLiTang = - dLiLen * vtLiL:getY() dLiPerp = EgtIf( bRight, dLiLen, - dLiLen) * vtLiL:getX() -- verifico se miglioro calcolando con faccia successiva local b3Mod = BBox3d( b3MyBox) ; b3Mod:Add( ptInt + 1000 * vtFN) local bLiOk2, _, vLiPar2 = EgtLineBoxInters( ptP1, vtLi, b3Mod) if bLiOk2 and #vLiPar2 > 0 then local dLen2 = vLiPar2[#vLiPar2] local vtFN2 = BL.GetBoxFaceNorm( b3Mod, ptP1 + vtLi * dLen2, vtLi) EgtOutLog( 'LiFaceNorm2=' .. tostring( vtFN2), 3) local dAddLen2 = dRad * ( sqrt( 1 - ( vtN * vtFN2) * ( vtN * vtFN2)) - abs( vtX * vtFN2)) / ( vtLi * vtFN2) local dLiLen2 = dLen2 + dAddLen2 EgtOutLog( 'LeadIn Dist2=' .. EgtNumToString( dLiLen2), 3) local dLiTang2 = - dLiLen2 * vtLiL:getY() local dLiPerp2 = EgtIf( bRight, dLiLen2, - dLiLen2) * vtLiL:getX() if dLiLen2 < dLiLen then dLiTang = dLiTang2 dLiPerp = dLiPerp2 end end end -- Lunghezza di uscita local dLoTang = 10000 local dLoPerp = 10000 local bLoOk, _, vLoPar = EgtLineBoxInters( ptP2, vtLo, b3MyBox) if bLoOk and #vLoPar > 0 then -- con la prima faccia di uscita local dLen = vLoPar[#vLoPar] local ptInt = ptP2 + vtLo * dLen local vtFN = BL.GetBoxFaceNorm( b3MyBox, ptInt, vtLo) EgtOutLog( 'LoFaceNorm=' .. tostring( vtFN), 3) local dAddLen = dRad * ( sqrt( 1 - ( vtN * vtFN) * ( vtN * vtFN)) - abs( vtX * vtFN)) / ( vtLo * vtFN) local dLoLen = dLen + dAddLen EgtOutLog( 'LeadOut Dist=' .. EgtNumToString( dLoLen), 3) dLoTang = dLoLen * vtLoL:getY() dLoPerp = EgtIf( bRight, dLoLen, - dLoLen) * vtLoL:getX() -- verifico se miglioro calcolando con faccia successiva local b3Mod = BBox3d( b3MyBox) ; b3Mod:Add( ptInt + 1000 * vtFN) local bLoOk2, _, vLoPar2 = EgtLineBoxInters( ptP2, vtLo, b3Mod) if bLoOk2 and #vLoPar2 > 0 then local dLen2 = vLoPar2[#vLoPar2] local vtFN2 = BL.GetBoxFaceNorm( b3Mod, ptP2 + vtLo * dLen2, vtLo) EgtOutLog( 'LoFaceNorm2=' .. tostring( vtFN2), 3) local dAddLen2 = dRad * ( sqrt( 1 - ( vtN * vtFN2) * ( vtN * vtFN2)) - abs( vtX * vtFN2)) / ( vtLo * vtFN2) local dLoLen2 = dLen2 + dAddLen2 EgtOutLog( 'LeadOut Dist2=' .. EgtNumToString( dLoLen2), 3) local dLoTang2 = dLoLen2 * vtLoL:getY() local dLoPerp2 = EgtIf( bRight, dLoLen2, - dLoLen2) * vtLoL:getX() if dLoLen2 < dLoLen then dLoTang = dLoTang2 dLoPerp = dLoPerp2 end end end return dLiTang, dLiPerp, dLoTang, dLoPerp end --------------------------------------------------------------------- function FacesBySaw.CalcLeadInOutTangGeom( ptP1, ptP2, vtN, dRad, vtRef, dCutExtra, b3Box) -- Versore tangente al taglio local vtTg = ptP2 - ptP1 ; vtTg = vtTg - vtTg * vtN * vtN ; vtTg:normalize() -- Sistema di riferimento intrinseco al taglio local vtX = vtTg ^ vtN local frFace = Frame3d( ptP1, vtX, vtTg, vtN) if ( vtX * vtRef < 0) then vtX = - vtX end EgtOutLog( 'Vref=' .. tostring( vtRef) .. ' V1=' .. tostring( vtV1) .. ' V2=' .. tostring( vtV2), 3) -- Spostamento punti per effetto dell'extra o della deficienza di taglio ptP1 = ptP1 - vtX * dCutExtra ptP2 = ptP2 - vtX * dCutExtra -- Non va considerata l'uscita dalla faccia sotto, pertanto va abbassata -- 2021/02/26 Abilito anche uscita sotto local b3MyBox = BBox3d( b3Box) ; --b3MyBox:Add( b3MyBox:getMin() - 1000 * Z_AX()) -- Attacco local dLiTang = 10000 local dLiPerp = 0 local bLiOk, _, vLiPar = EgtLineBoxInters( ptP1, vtTg, b3MyBox) if bLiOk and #vLiPar > 0 then local dLen = vLiPar[1] local ptInt = ptP1 + vtTg * dLen local vtFN = BL.GetBoxFaceNorm( b3MyBox, ptInt, -vtTg) EgtOutLog( 'LiFaceNorm=' .. tostring( vtFN), 3) local dAddLen = dRad * ( sqrt( 1 - ( vtN * vtFN) * ( vtN * vtFN)) - ( vtX * vtFN)) / ( vtTg * vtFN) local dLiLen = dLen + dAddLen EgtOutLog( 'LeadIn Dist=' .. EgtNumToString( dLiLen), 3) dLiTang = - dLiLen -- verifico se miglioro calcolando con faccia successiva local b3Mod = BBox3d( b3MyBox) ; b3Mod:Add( ptInt + 1000 * vtFN) local bLiOk2, _, vLiPar2 = EgtLineBoxInters( ptP1, vtTg, b3Mod) if bLiOk2 and #vLiPar2 > 0 then local dLen2 = vLiPar2[1] local vtFN2 = BL.GetBoxFaceNorm( b3Mod, ptP1 + vtTg * dLen2, -vtTg) EgtOutLog( 'LiFaceNorm2=' .. tostring( vtFN2), 3) local dAddLen2 = dRad * ( sqrt( 1 - ( vtN * vtFN2) * ( vtN * vtFN2)) - ( vtX * vtFN2)) / ( vtTg * vtFN2) local dLiLen2 = dLen2 + dAddLen2 EgtOutLog( 'LeadIn Dist2=' .. EgtNumToString( dLiLen2), 3) if -dLiLen2 < -dLiLen then dLiTang = - dLiLen2 end end end -- Lunghezza di uscita local dLoTang = 10000 local dLoPerp = 0 local bLoOk, _, vLoPar = EgtLineBoxInters( ptP2, vtTg, b3MyBox) if bLoOk and #vLoPar > 0 then local dLen = vLoPar[#vLoPar] local ptInt = ptP2 + vtTg * dLen local vtFN = BL.GetBoxFaceNorm( b3MyBox, ptInt, vtTg) EgtOutLog( 'LoFaceNorm=' .. tostring( vtFN), 3) local dAddLen = dRad * ( sqrt( 1 - ( vtN * vtFN) * ( vtN * vtFN)) - ( vtX * vtFN)) / ( vtTg * vtFN) local dLoLen = dLen + dAddLen EgtOutLog( 'LeadOut Dist=' .. EgtNumToString( dLoLen), 3) dLoTang = dLoLen -- verifico se miglioro calcolando con faccia successiva local b3Mod = BBox3d( b3MyBox) ; b3Mod:Add( ptInt + 1000 * vtFN) local bLoOk2, _, vLoPar2 = EgtLineBoxInters( ptP2, vtTg, b3Mod) if bLoOk2 and #vLoPar2 > 0 then local dLen2 = vLoPar2[#vLoPar2] local vtFN2 = BL.GetBoxFaceNorm( b3Mod, ptP2 + vtTg * dLen2, vtTg) EgtOutLog( 'LoFaceNorm2=' .. tostring( vtFN2), 3) local dAddLen2 = dRad * ( sqrt( 1 - ( vtN * vtFN2) * ( vtN * vtFN2)) - ( vtX * vtFN2)) / ( vtTg * vtFN2) local dLoLen2 = dLen2 + dAddLen2 EgtOutLog( 'LeadOut Dist2=' .. EgtNumToString( dLoLen2), 3) if dLoLen2 < dLoLen then dLoTang = dLoLen2 end end end return dLiTang, dLiPerp, dLoTang, dLoPerp end return FacesBySaw