-- BeamLib.lua by Egaltech s.r.l. 2020/06/18 -- Libreria globale per Travi -- Tabella per definizione modulo local BeamLib = {} -- Include require( 'EgtBase') EgtOutLog( ' BeamLib started', 1) ------------------------------------------------------------------------------------------------------------- ------------------------------------------------------------------------------------------------------------- function BeamLib.GetAddGroup( PartId) -- recupero il nome del gruppo di lavoro corrente local sMchGrp = EgtGetMachGroupName( EgtGetCurrMachGroup() or GDB_ID.NULL) if not sMchGrp then return nil, nil end -- cerco il gruppo aggiuntivo omonimo nel pezzo e se esiste lo restituisco local AddGrpId = EgtGetFirstNameInGroup( PartId or GDB_ID.NULL, sMchGrp) -- restituisco Id e Nome return AddGrpId, sMchGrp end ------------------------------------------------------------------------------------------------------------- function BeamLib.CreateOrEmptyAddGroup( PartId) -- recupero i dati del gruppo aggiuntivo local AddGrpId, sMchGrp = BeamLib.GetAddGroup( PartId) if not sMchGrp then return false end -- se esiste lo svuoto if AddGrpId then return EgtEmptyGroup( AddGrpId) end -- altrimenti lo creo AddGrpId = EgtGroup( PartId or GDB_ID.NULL) if not AddGrpId then return false end -- assegno nome, flag di layer per gruppo di lavoro e colore EgtSetName( AddGrpId, sMchGrp) EgtSetInfo( AddGrpId, GDB_SI.MGRPONLY, EgtGetCurrMachGroup()) EgtSetColor( AddGrpId, Color3d( 80, 160, 160, 50)) return true end ------------------------------------------------------------------------------------------------------------- function BeamLib.AddPartStartFace( PartId, b3Solid) -- recupero gruppo per geometria aggiuntiva local AddGrpId = BeamLib.GetAddGroup( PartId) if not AddGrpId then local sErr = 'Error on process StartFace impossible to find AddGroup' EgtOutLog( sErr) return false, sErr end -- aggiungo nuovo taglio iniziale local nStmId = EgtSurfTmPlaneInBBox( AddGrpId, b3Solid:getMax(), X_AX(), b3Solid, GDB_RT.GLOB) if not nStmId then local sErr = 'Error on process StartFace impossible to create Face' EgtOutLog( sErr) return false, sErr end -- applico gli opportuni attributi di feature EgtSetName( nStmId, 'StartCut') EgtSetInfo( nStmId, 'GRP', 1) EgtSetInfo( nStmId, 'PRC', 340) -- verifico se sostituisce un taglio di testa già presente local nProcId = EgtGetFirstInGroup( EgtGetFirstNameInGroup( PartId, 'Processings') or GDB_ID.NULL) while nProcId do local nGrp = EgtGetInfo( nProcId, 'GRP', 'i') or 0 local nProc = EgtGetInfo( nProcId, 'PRC', 'i') or 0 if ( nGrp == 1 or nGrp == 2) and nProc == 10 then local ptC, vtN = EgtSurfTmFacetCenter( nProcId, 0, GDB_ID.ROOT) if ptC and vtN and AreSameVectorApprox( vtN, X_AX()) and abs( ptC:getX() - b3Solid:getMax():getX()) < 10 * GEO.EPS_SMALL then EgtSetInfo( nStmId, 'ORI', nProcId) end end nProcId = EgtGetNext( nProcId) end return true end ------------------------------------------------------------------------------------------------------------- function BeamLib.AddPartEndFace( PartId, b3Solid) -- recupero gruppo per geometria aggiuntiva local AddGrpId = BeamLib.GetAddGroup( PartId) if not AddGrpId then local sErr = 'Error on process EndFace impossible to find AddGroup' EgtOutLog( sErr) return false, sErr end -- aggiungo nuovo taglio finale local nStmId = EgtSurfTmPlaneInBBox( AddGrpId, b3Solid:getMin(), -X_AX(), b3Solid, GDB_RT.GLOB) if not nStmId then local sErr = 'Error on process EndFace impossible to create Face' EgtOutLog( sErr) return false, sErr end -- applico gli opportuni attributi di feature EgtSetName( nStmId, 'EndCut') EgtSetInfo( nStmId, 'GRP', 2) EgtSetInfo( nStmId, 'PRC', 350) -- verifico se sostituisce un taglio di coda già presente local nProcId = EgtGetFirstInGroup( EgtGetFirstNameInGroup( PartId, 'Processings') or GDB_ID.NULL) while nProcId do local nGrp = EgtGetInfo( nProcId, 'GRP', 'i') or 0 local nProc = EgtGetInfo( nProcId, 'PRC', 'i') or 0 if ( nGrp == 1 or nGrp == 2) and nProc == 10 then local ptC, vtN = EgtSurfTmFacetCenter( nProcId, 0, GDB_ID.ROOT) if ptC and vtN and AreSameVectorApprox( vtN, -X_AX()) and abs( ptC:getX() - b3Solid:getMin():getX()) < 10 * GEO.EPS_SMALL then EgtSetInfo( nStmId, 'ORI', nProcId) end end nProcId = EgtGetNext( nProcId) end return true end ------------------------------------------------------------------------------------------------------------- function BeamLib.AddPhaseWithRawParts( nFirstRawId, OriTR, dDeltaSucc) EgtAddPhase() local nRawId = nFirstRawId local dRawMove = 0 while nRawId do EgtKeepRawPart( nRawId) EgtMoveToCornerRawPart( nRawId, OriTR, MCH_CR.TR) EgtMoveRawPart( nRawId, Vector3d( - dRawMove, 0, 0)) if dRawMove == 0 then dRawMove = dRawMove + dDeltaSucc end dRawMove = dRawMove + EgtGetRawPartBBox( nRawId):getDimX() nRawId = EgtGetNextRawPart( nRawId) end end ------------------------------------------------------------------------------------------------------------- function BeamLib.PutStartOnTop( nCrvId) -- verifico che la curva sia chiusa if not EgtCurveIsClosed( nCrvId) then return false end -- cerco l'estremo più alto e lo imposto come inizio local dUmax = 0 local dZmax = - GEO.INFINITO local dUi, dUf = EgtCurveDomain( nCrvId) for dU = dUi, dUf, 0.5 do local ptP = EgtUP( nCrvId, dU, GDB_ID.ROOT) if ptP and ptP:getZ() > dZmax + GEO.EPS_SMALL then dZmax = ptP:getZ() dUmax = dU end end if abs( dUmax - dUi) > GEO.EPS_ZERO then EgtChangeClosedCurveStart( nCrvId, dUmax) end return true end ------------------------------------------------------------------------------------------------------------- function BeamLib.PutStartOnLonger( nCrvId) -- verifico che la curva sia chiusa if not EgtCurveIsClosed( nCrvId) then return false end -- cerco l'entità più lunga e la imposto come inizio local dUmax = 0 local dLmax = - GEO.INFINITO local dUi, dUf = EgtCurveDomain( nCrvId) for dU = dUi, dUf - 1 do local ptP1 = EgtUP( nCrvId, dU, GDB_ID.ROOT) local ptP2 = EgtUP( nCrvId, dU + 0.5, GDB_ID.ROOT) local ptP3 = EgtUP( nCrvId, dU + 1.0, GDB_ID.ROOT) local dL = dist( ptP1, ptP2) + dist( ptP2, ptP3) if dL > dLmax + GEO.EPS_SMALL then dLmax = dL dUmax = dU end end if abs( dUmax - dUi) > GEO.EPS_ZERO then EgtChangeClosedCurveStart( nCrvId, dUmax) end return true end ------------------------------------------------------------------------------------------------------------- function BeamLib.PutStartNearestToEdge( nCrvId, b3Raw) -- verifico che la curva sia chiusa if not EgtCurveIsClosed( nCrvId) then return false end -- recupero il versore normale al piano di lavoro o estrusione local vtN = EgtCurveExtrusion( nCrvId, GDB_ID.ROOT) -- coefficienti per riportare la distanza nel piano di lavoro local dCoeffX = 1 / ( sqrt( 1 - vtN:getX() * vtN:getX())) local dCoeffY = 1 / ( sqrt( 1 - vtN:getY() * vtN:getY())) local dCoeffZ = 1 / ( sqrt( 1 - vtN:getZ() * vtN:getZ())) -- cerco l'estremo più vicino al box e lo imposto come inizio (escluso Zmin) local dUopt = 0 local dDopt = GEO.INFINITO local dUi, dUf = EgtCurveDomain( nCrvId) for dU = dUi, dUf, 0.5 do local ptP = EgtUP( nCrvId, dU, GDB_ID.ROOT) if ptP then local vtMin = ptP - b3Raw:getMin() local vtMax = ptP - b3Raw:getMax() local dD = abs( vtMin:getX()) * dCoeffX dD = min( abs( vtMax:getX()) * dCoeffX, dD) dD = min( abs( vtMin:getY()) * dCoeffY, dD) dD = min( abs( vtMax:getY()) * dCoeffY, dD) dD = min( abs( vtMax:getZ()) * dCoeffZ, dD) if dD < dDopt + GEO.EPS_SMALL then dDopt = dD dUopt = dU end end end if abs( dUopt - dUi) > GEO.EPS_ZERO then EgtChangeClosedCurveStart( nCrvId, dUopt) end return true end ------------------------------------------------------------------------------------------------------------- function BeamLib.GetPointDirDepth( nPartId, ptP, vtDir) -- recupero il solido del grezzo local nSolId = EgtGetFirstNameInGroup( EgtGetFirstNameInGroup( nPartId, 'Box') or GDB_ID.NULL, 'Box') if not nSolId then return end -- interseco con la retta local bOk, vType, vPar = EgtLineSurfTmInters( ptP, vtDir, nSolId, GDB_RT.GLOB) if not bOk then return end if not vPar or #vPar == 0 then return -2 end local dLenIn, dLenOut for i = 1, #vPar do if vPar[i] < 0 then if vType[i] == GDB_SLT.IN or vType[i] == GDB_SLT.TG_INI then dLenIn = -1 end if vType[i] == GDB_SLT.OUT or vType[i] == GDB_SLT.TG_FIN then dLenIn = -2 end else if vType[i] == GDB_SLT.IN or vType[i] == GDB_SLT.TG_INI then dLenIn = vPar[i] end if vType[i] == GDB_SLT.OUT or vType[i] == GDB_SLT.TG_FIN or vType[i] == GDB_SLT.TOUCH then dLenOut = vPar[i] end end end return dLenIn, dLenOut end --------------------------------------------------------------------- function BeamLib.GetNearestParalOpposite( vtRef) -- devo confrontare la componente orizzontale con quella verticale local dHorSq = vtRef:getX() * vtRef:getX() + vtRef:getY() * vtRef:getY() local dVertSq =vtRef:getZ() * vtRef:getZ() -- se prevalente la componente orizzontale if dHorSq >= dVertSq then if abs( vtRef:getX()) > abs( vtRef:getY()) then if vtRef:getX() > 0 then return MCH_MILL_FU.PARAL_LEFT else return MCH_MILL_FU.PARAL_RIGHT end else if vtRef:getY() > 0 then return MCH_MILL_FU.PARAL_FRONT else return MCH_MILL_FU.PARAL_BACK end end -- altrimenti prevale la verticale else if vtRef:getZ() > 0 then return MCH_MILL_FU.PARAL_DOWN else return MCH_MILL_FU.PARAL_TOP end end return nil end --------------------------------------------------------------------- function BeamLib.GetNearestOrthoOpposite( vtRef) -- devo confrontare la componente orizzontale con quella verticale local dHorSq = vtRef:getX() * vtRef:getX() + vtRef:getY() * vtRef:getY() local dVertSq =vtRef:getZ() * vtRef:getZ() -- se prevalente la componente orizzontale if dHorSq >= dVertSq then if abs( vtRef:getX()) >= abs( vtRef:getY()) then if vtRef:getX() > 0 then return MCH_MILL_FU.ORTHO_LEFT else return MCH_MILL_FU.ORTHO_RIGHT end else if vtRef:getY() > 0 then return MCH_MILL_FU.ORTHO_FRONT else return MCH_MILL_FU.ORTHO_BACK end end -- altrimenti prevale la verticale else if vtRef:getZ() > 0 then return MCH_MILL_FU.ORTHO_DOWN else return MCH_MILL_FU.ORTHO_TOP end end return nil end --------------------------------------------------------------------- function BeamLib.GetOrtupOpposite( nOrthoOpposite) if nOrthoOpposite == MCH_MILL_FU.ORTHO_LEFT then return MCH_MILL_FU.ORTUP_LEFT elseif nOrthoOpposite == MCH_MILL_FU.ORTHO_RIGHT then return MCH_MILL_FU.ORTUP_RIGHT elseif nOrthoOpposite == MCH_MILL_FU.ORTHO_FRONT then return MCH_MILL_FU.ORTUP_FRONT elseif nOrthoOpposite == MCH_MILL_FU.ORTHO_BACK then return MCH_MILL_FU.ORTUP_BACK elseif nOrthoOpposite == MCH_MILL_FU.ORTHO_DOWN then return MCH_MILL_FU.ORTUP_DOWN elseif nOrthoOpposite == MCH_MILL_FU.ORTHO_TOP then return MCH_MILL_FU.ORTUP_TOP end return nil end --------------------------------------------------------------------- function BeamLib.GetVersRef( nOrthoOpposite) if nOrthoOpposite == MCH_MILL_FU.ORTHO_LEFT then return X_AX() elseif nOrthoOpposite == MCH_MILL_FU.ORTHO_RIGHT then return -X_AX() elseif nOrthoOpposite == MCH_MILL_FU.ORTHO_FRONT then return Y_AX() elseif nOrthoOpposite == MCH_MILL_FU.ORTHO_BACK then return -Y_AX() elseif nOrthoOpposite == MCH_MILL_FU.ORTHO_DOWN then return Z_AX() elseif nOrthoOpposite == MCH_MILL_FU.ORTHO_TOP then return -Z_AX() end return nil end --------------------------------------------------------------------- function BeamLib.GetBoxFaceNorm( b3Box, ptP, vtV) local vtNx = V_NULL() if abs( ptP:getX() - b3Box:getMin():getX()) < 10 * GEO.EPS_SMALL then vtNx = -X_AX() elseif abs( ptP:getX() - b3Box:getMax():getX()) < 10 * GEO.EPS_SMALL then vtNx = X_AX() end local vtNy = V_NULL() if abs( ptP:getY() - b3Box:getMin():getY()) < 10 * GEO.EPS_SMALL then vtNy = -Y_AX() elseif abs( ptP:getY() - b3Box:getMax():getY()) < 10 * GEO.EPS_SMALL then vtNy = Y_AX() end local vtNz = V_NULL() if abs( ptP:getZ() - b3Box:getMin():getZ()) < 10 * GEO.EPS_SMALL then vtNz = -Z_AX() elseif abs( ptP:getZ() - b3Box:getMax():getZ()) < 10 * GEO.EPS_SMALL then vtNz = Z_AX() end local dNxDotV = vtNx * vtV local dNyDotV = vtNy * vtV local dNzDotV = vtNz * vtV if dNxDotV > dNyDotV and dNxDotV > dNzDotV then return vtNx elseif dNyDotV > dNzDotV and dNyDotV > dNxDotV then return vtNy else return vtNz end end --------------------------------------------------------------------- function BeamLib.GetFaceElevation( nSurfId, nFac, nPartId) local ptC, vtN = EgtSurfTmFacetCenter( nSurfId, nFac, GDB_ID.ROOT) if not ptC or not vtN then return 0 end local frOCS = Frame3d( ptC, vtN) ; local b3Box = EgtGetBBoxRef( nSurfId, GDB_BB.STANDARD, frOCS) local dElev = b3Box:getDimZ() if nPartId then local _, dCenElev = BeamLib.GetPointDirDepth( nPartId, ptC, vtN) if dCenElev and dCenElev > dElev then dElev = dCenElev end end return dElev end --------------------------------------------------------------------- function BeamLib.GetFaceWithMostAdj( nSurfId, nPartId, bCompare3Fc, dCosSideAng) -- recupero il numero di facce local nFacCnt = EgtSurfTmFacetCount( nSurfId) if not dCosSideAng then dCosSideAng = -0.09 end -- recupero le normali delle facce local vvtN = {} for i = 1, nFacCnt do local _, vtN = EgtSurfTmFacetCenter( nSurfId, i - 1, GDB_ID.ROOT) vvtN[i] = vtN ; end -- adiacenze e sottosquadra delle facce local vAdj = {} local vUcut = {} local vOrtho = {} for i = 1, nFacCnt do -- recupero le adiacenze del loop esterno local vFacAdj = EgtSurfTmFacetAdjacencies( nSurfId, 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 -- ne determino eventuale sottosquadra ( dal valore passato o - 3deg) e ortogonalità local bUcut = false local bOrtho = true for j = 1, #vFacAdj do if vFacAdj[j] >= 0 then local vtN = vvtN[i] local vtN2 = vvtN[vFacAdj[j]+1] local dResV = vtN * vtN2 if dResV < dCosSideAng - GEO.EPS_SMALL then bUcut = true end if abs( dResV) > 2 * GEO.EPS_SMALL then bOrtho = false end end end vUcut[i] = bUcut vOrtho[i] = bOrtho end -- se 4 facce tutte con adiacenza 2, allora è un tunnel if nFacCnt == 4 then if vAdj[1] == 2 and vAdj[2] == 2 and vAdj[3] == 2 and vAdj[4] == 2 then -- se tutte le facce sono ortogonali tra loro esco con un flag che ne indica questa propietà if vOrtho[1] == true and vOrtho[2] == true and vOrtho[3] == true and vOrtho[4] == true then return -1, GEO.INFINITO, true else return -1, GEO.INFINITO end end end -- se 3 facce con una che ha 2 adiacenze e le altre hanno 1 adiacenza, allora è una semi-fessura if bCompare3Fc and nFacCnt == 3 then local nCount2Adc = 0 local nCount1Adc = 0 -- ottengo il numero di facce con due adiacenze e il numero di facce con una adiacenza for i = 1, #vAdj do if vAdj[i] == 2 then nCount2Adc = nCount2Adc + 1 elseif vAdj[i] == 1 then nCount1Adc = nCount1Adc + 1 end end -- se il numero di adiacenze corrisponde if nCount2Adc == 1 and nCount1Adc == 2 then if vOrtho[1] == true and vOrtho[2] == true and vOrtho[3] == true then return -1, GEO.INFINITO, true else return -1, GEO.INFINITO end end end -- recupero le facce non in sottosquadra e con il maggior numero di adiacenze local nFacInd = {} local nMaxAdj = -1 local nSupAdj = -1 for i = 1, nFacCnt do if not vUcut[i] then if vAdj[i] > nMaxAdj then nFacInd = {} nFacInd[1] = i - 1 nMaxAdj = vAdj[i] elseif vAdj[i] == nMaxAdj and nMaxAdj > 0 then table.insert( nFacInd, i - 1) end end if vAdj[i] > nSupAdj then nSupAdj = vAdj[i] end end -- verifico non ci sia una faccia in sottosquadra con adiacenza superiore if nSupAdj > nMaxAdj then return -2, GEO.INFINITO end -- premio la faccia con minore elevazione local nFacOpt, nFacOpt2 local dMinElev, dMinElev2 = GEO.INFINITO, GEO.INFINITO for i = 1, #nFacInd do local dElev = BeamLib.GetFaceElevation( nSurfId, nFacInd[i], nPartId) if dElev < dMinElev then if dMinElev < dMinElev2 then nFacOpt2 = nFacOpt dMinElev2 = dMinElev end nFacOpt = nFacInd[i] dMinElev = dElev elseif dElev < dMinElev2 then nFacOpt2 = nFacInd[i] dMinElev2 = dElev end end return nFacOpt, dMinElev, nFacOpt2, dMinElev2 end --------------------------------------------------------------------- function BeamLib.GetFaceHvRefDim( nSurfId, nFacet) -- recupero centro e normale della faccia local ptC, vtN = EgtSurfTmFacetCenter( nSurfId, nFacet, GDB_ID.ROOT) if not ptC or not vtN then return end -- riferimento tipo OCS della faccia (X orizz, Y max pendenza, Z normale) local frHV = Frame3d( ptC, vtN) if frHV:getVersY():getZ() < 0 then frHV:rotate( ptC, vtN, 180) end -- determino l'ingombro in questo riferimento local b3HV = EgtSurfTmGetFacetBBoxRef( nSurfId, nFacet, GDB_BB.STANDARD, frHV) -- restituisco i valori calcolati return frHV, b3HV:getDimX(), b3HV:getDimY() end --------------------------------------------------------------------- function BeamLib.CalcLeadInOutGeom( 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 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)) -- Attacco local dLiTang = 10000 local dLiPerp = 10000 local bLiOk, _, vLiPar = EgtLineBoxInters( ptP1, vtLi, b3Box) if bLiOk and #vLiPar > 0 then -- con la prima faccia di uscita local dLen = vLiPar[#vLiPar] local ptInt = ptP1 + vtLi * dLen local vtFN = BeamLib.GetBoxFaceNorm( b3Box, 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( b3Box) ; b3Mod:Add( ptInt + 1000 * vtFN) local bLiOk2, _, vLiPar2 = EgtLineBoxInters( ptP1, vtLi, b3Mod) if bLiOk2 and #vLiPar2 > 0 then local dLen2 = vLiPar2[#vLiPar2] local vtFN2 = BeamLib.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, b3Box) if bLoOk and #vLoPar > 0 then -- con la prima faccia di uscita local dLen = vLoPar[#vLoPar] local ptInt = ptP2 + vtLo * dLen local vtFN = BeamLib.GetBoxFaceNorm( b3Box, 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( b3Box) ; b3Mod:Add( ptInt + 1000 * vtFN) local bLoOk2, _, vLoPar2 = EgtLineBoxInters( ptP2, vtLo, b3Mod) if bLoOk2 and #vLoPar2 > 0 then local dLen2 = vLoPar2[#vLoPar2] local vtFN2 = BeamLib.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 BeamLib.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 -- Attacco local dLiTang = 10000 local dLiPerp = 0 local bLiOk, _, vLiPar = EgtLineBoxInters( ptP1, vtTg, b3Box) if bLiOk and #vLiPar > 0 then local dLen = vLiPar[1] local ptInt = ptP1 + vtTg * dLen local vtFN = BeamLib.GetBoxFaceNorm( b3Box, 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( b3Box) ; b3Mod:Add( ptInt + 1000 * vtFN) local bLiOk2, _, vLiPar2 = EgtLineBoxInters( ptP1, vtTg, b3Mod) if bLiOk2 and #vLiPar2 > 0 then local dLen2 = vLiPar2[1] local vtFN2 = BeamLib.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, b3Box) if bLoOk and #vLoPar > 0 then local dLen = vLoPar[#vLoPar] local ptInt = ptP2 + vtTg * dLen local vtFN = BeamLib.GetBoxFaceNorm( b3Box, 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( b3Box) ; b3Mod:Add( ptInt + 1000 * vtFN) local bLoOk2, _, vLoPar2 = EgtLineBoxInters( ptP2, vtTg, b3Mod) if bLoOk2 and #vLoPar2 > 0 then local dLen2 = vLoPar2[#vLoPar2] local vtFN2 = BeamLib.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 --------------------------------------------------------------------- function BeamLib.MakeOneFaceBySaw( nSurfId, nFacet, sCutting, dSawDiam, Par5, dVzLimDwnUp, dCutExtra, dCutSic, dCutOffset, dAccStart, sNotes, b3Raw) -- risolvo paramentro ambiguo local nOrthoOpposite local vtOrthO if isVector3d( Par5) then nOrthoOpposite = BeamLib.GetNearestOrthoOpposite( Par5) vtOrthO = Vector3d( Par5) else nOrthoOpposite = Par5 vtOrthO = BeamLib.GetVersRef( Par5) end -- dati della faccia local ptC, vtN = EgtSurfTmFacetCenter( nSurfId, nFacet, GDB_ID.ROOT) -- 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, BeamLib.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 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) --if dDist1 * ( vtTg1 ^ vtOrthO):len() > dDist2 * ( vtTg2 ^ vtOrthO):len() then if abs( vtTg1 * vtOrthO) < abs( vtTg2 * vtOrthO) then ptP2 = Point3d( ptPm) dAllEnd = - dDist2 - 10 * GEO.EPS_SMALL else ptP1 = Point3d( ptPm) dAllStart = - dDist1 - 10 * GEO.EPS_SMALL end vtTg = ptP2 - ptP1 ; vtTg:normalize() end -- verifico se lavorazione con lama sotto e testa sopra if not dVzLimDwnUp then dVzLimDwnUp = -0.5 end local bDownUp = ( vtN:getZ() < dVzLimDwnUp) local nFaceUse = nOrthoOpposite if bDownUp then nFaceUse = BeamLib.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 dLiTang, dLiPerp, dLoTang, dLoPerp local ptP1act = ptP1 + vtN * dCutOffset local ptP2act = ptP2 + vtN * dCutOffset if ( vtV1:getZ() > -0.5 or vtV2:getZ() > -0.5) and ( abs( vtV1:getY()) > 0.707 or abs( vtV2:getY()) > 0.707 or vtN:getZ() < 0.95) then dLiTang, dLiPerp, dLoTang, dLoPerp = BeamLib.CalcLeadInOutGeom( ptP1act, ptP2act, vtV1, vtV2, vtN, dSawDiam/2, vtRef, dCutExtra, b3Box) else dLiTang, dLiPerp, dLoTang, dLoPerp = BeamLib.CalcLeadInOutTangGeom( ptP1act, ptP2act, vtN, dSawDiam/2, vtRef, dCutExtra, b3Box) end -- posizione braccio EgtOutLog( 'vtN=' .. tostring( vtN) .. ' vtRef=' .. tostring( vtRef) .. ' vtOut=' .. tostring( vtOut) .. ' vtAux=' .. tostring( vtAux), 3) local nSCC = MCH_SCC.NONE if abs( vtAux:getX()) > abs( vtAux:getY()) then nSCC = EgtIf( ( vtAux:getX() > 0), MCH_SCC.ADIR_XP, MCH_SCC.ADIR_XM) else nSCC = EgtIf( ( vtAux:getY() > 0), MCH_SCC.ADIR_YP, MCH_SCC.ADIR_YM) 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) -- 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 end ------------------------------------------------------------------------------------------------------------- function BeamLib.UpdateHCING( nRawId, dHCI, dDist) local dOldHCI = EgtGetInfo( nRawId, 'HCING', 'd') or 0 if dDist and dDist > dOldHCI + 10 then return end if dHCI > dOldHCI then EgtSetInfo( nRawId, 'HCING', dHCI) end end ------------------------------------------------------------------------------------------------------------- function BeamLib.UpdateTCING( nRawId, dTCI) local dOldTCI = EgtGetInfo( nRawId, 'TCING', 'd') or 0 if dTCI > dOldTCI then EgtSetInfo( nRawId, 'TCING', dTCI) end end ------------------------------------------------------------------------------------------------------------- function BeamLib.GetNzLimDownUp( b3Raw) return EgtIf( b3Raw:getDimZ() < 200, -0.5, -0.258) end ------------------------------------------------------------------------------------------------------------- return BeamLib