From a85a302c54f917905557f30f71ff065247a1747d Mon Sep 17 00:00:00 2001 From: Dario Sassi Date: Thu, 14 Jan 2021 06:49:57 +0000 Subject: [PATCH] DataWall : - aggiunta ottimizzazione movimenti tra lavorazioni - aggiunta pulitura spigoli (con utensile conico o con foro). --- LuaLibs/WProcessFreeContour.lua | 1268 +++++++++++++++++++++++++++---- LuaLibs/WProcessLapJoint.lua | 715 ++++++++++++++++- LuaLibs/WallExec.lua | 85 ++- 3 files changed, 1889 insertions(+), 179 deletions(-) diff --git a/LuaLibs/WProcessFreeContour.lua b/LuaLibs/WProcessFreeContour.lua index caaadb7..4bbcad0 100644 --- a/LuaLibs/WProcessFreeContour.lua +++ b/LuaLibs/WProcessFreeContour.lua @@ -1,4 +1,4 @@ --- ProcessFreeContour.lua by Egaltech s.r.l. 2020/11/19 +-- ProcessFreeContour.lua by Egaltech s.r.l. 2020/12/01 -- Gestione calcolo profilo libero per Pareti -- Tabella per definizione modulo @@ -17,6 +17,15 @@ local WHISK_OFFS = 0.1 local WHISK_SAFE = 5 local MIN_LEN_CUT = 30 +-- 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) @@ -36,7 +45,7 @@ function WPF.Classify( Proc, b3Raw) -- se tasca if bPocket then local bDown = ( vtN:getZ() < - 0.5) - return false + return not bDown -- se altrimenti profilo orizzontale elseif abs( vtN:getZ()) < 0.5 then return false @@ -49,6 +58,76 @@ function WPF.Classify( Proc, b3Raw) end 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) + + local nConeCut = 0 + -- verifico il tipo di lavorazione su angolo. 0 : nessuna ripresa corner; 1: ripresa corner con pausa; + -- 2: ripresa corner senza pausa; 3: scarico corner + local nParamValue = EgtGetInfo( Proc.Id, sTypeCornerCut, 'i') or nConeCut + -- se tipo di lavorazione con fesa conica 60° con pausa + nConeCut = nParamValue + return nConeCut +end + --------------------------------------------------------------------- local function GetOtherRegions( nPartId) local vOthers = {} @@ -71,7 +150,817 @@ local function GetOtherRegions( nPartId) end --------------------------------------------------------------------- -local function AddMillings( sMilling, vFace, Proc, nRawId, b3Raw) +local function ReorderFaces( nIdSurf, nNumFacet) + local vAdj = {} + for i = 1, nNumFacet do + 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 + local nIdFace + local nAdjMin = 1000 + for i = #vAdj, 1, -1 do + if vAdj[i] <= nAdjMin then + nAdjMin = vAdj[i] + nIdFace = i + end + end + -- se il numero faccia minore con minori adiacenze è <> 1 faccio lo scambio + if nIdFace and nIdFace ~= 1 then + EgtSurfTmSwapFacets( nIdSurf, nIdFace-1, 0) + end + -- ordino il numero di facce in modo da avere una sequenza di facce concatenate + for i = 1, (nNumFacet-1) do + -- recupero l'angolo con la faccia precedente + local bAdj, _, _, _ = EgtSurfTmFacetsContact( nIdSurf, i-1, i, GDB_ID.ROOT) + -- se non ho adiacenza + if not bAdj then + for j = i+1, nNumFacet 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 + return nIdSurf +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) + nNewProc = ReorderFaces( nNewProc, nNumFacet) + return nNewProc, nNumFacet +end + +--------------------------------------------------------------------- +local function GetFacesData( Proc, bOpposite, bCalclForBlade, dToolDiam, dToolMaxDepth, dToolThick, nAddGrpId, bDeleteBottomface, nMasterNewProc) + + local nNewProc + if nMasterNewProc then + nNewProc = nMasterNewProc + else + nNewProc = EgtCopyGlob( Proc.Id, nAddGrpId) or GDB_ID.NULL + end + -- copio la superfice nel gruppo ausiliario + local nNumFacet + if bDeleteBottomface then + -- recupero la faccia che ha versore Z maggiore delle altre per escluderla + local dZMax = -1 + local dBottomFace = 0 + for i = 1, Proc.Fct do + local _, vtN = EgtSurfTmFacetCenter( nNewProc, i-1, GDB_ID.ROOT) + if vtN:getZ() > dZMax then + dZMax = vtN:getZ() + dBottomFace = i + end + end + if dBottomFace > 0 then + EgtSurfTmRemoveFacet( nNewProc, dBottomFace-1) + end + nNumFacet = EgtSurfTmFacetCount( nNewProc) + nNewProc = ReorderFaces( nNewProc, nNumFacet) + else + nNumFacet = EgtSurfTmFacetCount( nNewProc) + end + + local vFace = {} + -- recupero i dati di tutte le facce + for i = 1, nNumFacet do + -- indice faccia corrente e precedente + local nFac = EgtIf( bOpposite, nNumFacet - i, i - 1) + local nPrecFac + if bOpposite then + nPrecFac = EgtIf( i == 1, 0, nFac + 1) + else + nPrecFac = EgtIf( i == 1, nNumFacet - 1, i - 2) + end + -- recupero centro e normale della faccia + local ptCen, vtN = EgtSurfTmFacetCenter( nNewProc, nFac, GDB_ID.ROOT) + -- recupero le dimensioni della faccia + local _, dLen, dWidth = WL.GetFaceHvRefDim( nNewProc, nFac) + -- recupero l'angolo con la faccia precedente + local bAdj, _, _, dAng = EgtSurfTmFacetsContact( nNewProc, nPrecFac, nFac, GDB_ID.ROOT) + -- salvo i dati + vFace[i] = { Fac = nFac, Cen = ptCen, Norm = vtN, Len = dLen, Width = dWidth, AngPrev = EgtIf( bAdj, dAng, 0)} + 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 nType = 0 + if vFace[i].AngPrev < -0.1 then + dLen = dLen - EgtIf( bCalclForBlade, dWhisk, 0) + nType = nType + 1 + end + if vFace[EgtIf( i < nNumFacet, i + 1, 1)].AngPrev < -0.1 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 + vFace[i].Depth = dDepth + vFace[i].Whisk = dWhisk + vFace[i].Type = nType + 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 - WHISK_OFFS) * vtDir + local ptCross = ptDir + ( dToolThick - 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 - WHISK_OFFS) * vtDir + local ptCross = ptDir + ( dToolThick - 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 + -- 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.AngPrev, 1).. + ' D='..EgtNumToString( Face.Depth, 1)..' B='..EgtNumToString( Face.Whisk, 1)..' T='..tostring( Face.Type) + EgtOutLog( sOut) + end + + return vFace, dMaxWidth, nNewProc +end + +--------------------------------------------------------------------- +local function GetTunnelDimension( nId, nPartId, nAddGrpId) + -- ottengo i versori delle 4 facce e ottengo l'orientamento del tunnel + -- recupero il numero di facce + local nFacCnt = EgtSurfTmFacetCount( nId) + -- recupero l'ingombro della trave + local b3Solid = EgtGetBBoxGlob( EgtGetFirstNameInGroup( nPartId, 'Box') or GDB_ID.NULL, GDB_BB.STANDARD) + -- variabili dimensioni fessura e id faccia lunga + local dDimMin + local dDimMax + local nLongIdFace = 0 + local bNegFace + local bOppoFace = false + -- ottengo il versore ortogonale + local ptN1, vtN1 = EgtSurfTmFacetCenter( nId, 0, GDB_ID.ROOT) + local _, vtN2 = EgtSurfTmFacetCenter( nId, 1, GDB_ID.ROOT) + local vtOrtho = vtN1 ^ vtN2 + if vtOrtho:isSmall() then + _, vtN2 = EgtSurfTmFacetCenter( nId, 2, GDB_ID.ROOT) + vtOrtho = vtN1 ^ vtN2 + bOppoFace = true + end + vtOrtho:normalize() + if vtOrtho:getZ() < -0.5 then + vtOrtho = -vtOrtho + bNegFace = true + end + -- ottengo il boundingBox e prendo le dimensioni lungo la normale (Z locale) che rappresenta la profondità della fessura + local frFc = Frame3d( ptN1, vtOrtho) ; + local bBoxLoc = EgtGetBBoxRef( nId, GDB_BB.STANDARD, frFc) + local dDepth = bBoxLoc:getDimZ() + -- mi assicuro che la Z del punto utilizzato per creare la superficie sia alla Z inferiore del bounding box locale + local ptN2 = Point3d(ptN1) + ptN2:toLoc(frFc) + ptN2 = Point3d( ptN2:getX(), ptN2:getY(), bBoxLoc:getMin():getZ() + 2*GEO.EPS_SMALL) + ptN2:toGlob(frFc) + -- creo superficie intermedia + local nSurfInt = EgtSurfTmPlaneInBBox( nAddGrpId, ptN2, vtOrtho, b3Solid, GDB_ID.ROOT) + -- 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 (era su di 2 * GEO.EPS_SMALL) + EgtMove( nSurfInt, Point3d(0,0,-2*GEO.EPS_SMALL) - ORIG(), GDB_RT.GLOB) + -- mi faccio dare il contorno della superfice e la ricreo in modo più corretto + local nIdCont, nIdNum = EgtExtractSurfTmLoops( nSurfInt, nAddGrpId) + -- elimino le entità allineate dello stesso tipo + EgtMergeCurvesInCurveCompo( nIdCont, 2*GEO.EPS_SMALL) + EgtErase(nSurfInt) + nSurfInt = EgtSurfTmByFlatContour( nAddGrpId, nIdCont, 2*GEO.EPS_SMALL) + -- elimino il contorno + EgtErase(nIdCont) + -- se normale negativa inverto + _, vtN1 = EgtSurfTmFacetCenter( nSurfInt, 0, GDB_ID.ROOT) + if vtN1:getZ() < -0.5 then EgtInvertSurf( nSurfInt) end + local _, DimH, DimV = EgtSurfTmFacetMinAreaRectangle( nSurfInt, 0, GDB_ID.ROOT) + dDimMin = min( DimH, DimV) + dDimMax = max( DimH, DimV) + _, DimH, DimV = EgtSurfTmFacetMinAreaRectangle( nId, nFacCnt-1, GDB_ID.ROOT) + -- se faccia pari alla larghezza fessura + if abs(DimH - dDimMax) < GEO.EPS_SMALL or abs(DimV - dDimMax) < GEO.EPS_SMALL then + nLongIdFace = nFacCnt-1 + -- altrimenti verifico anche con la faccia precedente + else + local nFaceToCheck = EgtIf( bOppoFace, nFacCnt-3, nFacCnt-2) + -- prendo le dimensioni della faccia e poi confronto con il minimo + _, DimH, DimV = EgtSurfTmFacetMinAreaRectangle( nId, nFaceToCheck, GDB_ID.ROOT) + -- se trovato con il minimo, questa seconda faccia non è la più lunga + if abs(DimH - dDimMin) < GEO.EPS_SMALL or abs(DimV - dDimMin) < GEO.EPS_SMALL then + nLongIdFace = nFacCnt-1 + else + nLongIdFace = nFaceToCheck + end + end + if not dDimMax then + return dDimMin, dDimMax, dDepth, nil, nil + end + return dDimMin, dDimMax, dDepth, vtOrtho, 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) + + 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) + 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 and dThick <= ( WD.MAX_CLEAN_CRN30 + 20 * GEO.EPS_SMALL) 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[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 + if i < nIdCount 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[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, dDiamToolMax, nAuxPath, + bMakeExtPath, nAddGrpId, dThSurf, bNegZ, vtNZ) + + local nExtPath + if bMakeExtPath then + nExtPath = EgtCopyGlob( nAuxPath, nAddGrpId) or GDB_ID.NULL + else + nExtPath = EgtCopyGlob( nAuxPath, nAddGrpId) or GDB_ID.NULL + end + -- setto a 0 lo spessore + EgtModifyCurveThickness( nExtPath, 0) + -- se versore negativo devo spostare il percorso del suo spessore + if bNegZ then + -- setto griglia normale al percorso + EgtSetGridFrame( Frame3d( ptCentr, vtNZ)) + EgtMove( nExtPath, Point3d(0,0,dThSurf) - ORIG(), GDB_RT.GLOB) + EgtSetGridFrame() + end + -- setto griglia + EgtSetGridFrame( Frame3d( ptCentr, vtExtr)) + --creo il cerchio + local nIdCircle = EgtCircle( nAddGrpId, {0,0,0}, dDiamToolMax/2, GDB_RT.GRID) + -- verifico se c'è punto intersezione + local pPint = EgtIP( nIdCircle, nExtPath, {0,0,0}, GDB_RT.GRID) + -- riporto la griglia a globale + EgtSetGridFrame() + -- cancello il cerchio e il contorno + EgtErase( nExtPath) + EgtErase( nIdCircle) + if pPint then + return true + else + return false + end +end + +--------------------------------------------------------------------- +local function AddMillCornerMachining( nNewProc, nFacInd, tFacAdj, nTypeConeCut, nAddGrpId, + dToolDiam, dThick, sMilling, dOffsAng, dDepthMach, + nCheckPath, dDiamToolMax, bThruThick, dThSurf, bNegZ) + -- variabili costruzione geometria + local pAuxId = {} + local nAuxId + local ptApPoint + local AuxId + -- prendo il primo versore + local _, vtN1 = EgtSurfTmFacetCenter( nNewProc, nFacInd, GDB_ID.ROOT) + local _, vtN2 = EgtSurfTmFacetCenter( nNewProc, tFacAdj[1][1], GDB_ID.ROOT) + local _, vtN3 = EgtSurfTmFacetCenter( nNewProc, tFacAdj[1][2], GDB_ID.ROOT) + -- trovo il punto sulla superfice di riferimento + local _, ptLocP1, ptLocP2, _ = EgtSurfTmFacetsContact( nNewProc, nFacInd, tFacAdj[1][1], GDB_ID.ROOT) + local nIdIniPoint + local nIdEndPoint + if ptLocP1 and ptLocP2 then + if ( dist( ptLocP1, tFacAdj[1][4]) < GEO.EPS_SMALL) or ( dist( ptLocP2, tFacAdj[1][4]) < GEO.EPS_SMALL) then + nIdEndPoint = 4 + nIdIniPoint = 5 + elseif ( dist( ptLocP1, tFacAdj[1][5]) < GEO.EPS_SMALL) or ( dist( ptLocP2, tFacAdj[1][5]) < GEO.EPS_SMALL) then + nIdEndPoint = 5 + nIdIniPoint = 4 + end + end + -- versore direzione + local vtExtr = tFacAdj[1][nIdIniPoint] - tFacAdj[1][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 : clean corner milling from bottom impossible' + 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() + -- controllo se c'è collisione con le facce della superfice + if nTypeConeCut == 1 and CalcInterference( nNewProc, vtExtr, tFacAdj[1][nIdEndPoint] + Point3d( 0, 0, -dDepthMach), dDiamToolMax, nCheckPath, + false, nAddGrpId, dThSurf, bNegZ, vtN1) then + return true, '' + end + nAuxId = EgtLine( nAddGrpId, tFacAdj[1][nIdIniPoint], tFacAdj[1][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[1][nIdEndPoint], ptLocP1) < 10 * GEO.EPS_SMALL then + ptApPoint = ptLocP2 + else + ptApPoint = ptLocP1 + end + nAuxId = EgtLine( nAddGrpId, tFacAdj[1][nIdEndPoint] + Point3d( 0, 0, -dDepthMach), ptApPoint + Point3d( 0, 0, -dDepthMach), GDB_RT.GLOB) + local dLenTrimExt = dist( tFacAdj[1][nIdEndPoint], ptApPoint) - (( dToolDiam/2) + 2) + -- se la distanza dei due punti della linea è maggiore dal raggio fresa + delta, trimmo al raggio fresa + delta + if dLenTrimExt > 10 * GEO.EPS_SMALL then + EgtTrimExtendCurveByLen( nAuxId , -dLenTrimExt, ptApPoint + 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[1][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[1][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[1][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, _ = EgtSurfTmFacetsContact( nNewProc, nFacInd, tFacAdj[1][2], GDB_ID.ROOT) + if ptLocP1 and ptLocP2 then + -- se il punto finale corrisponde con il punto utilizzato in precedenza, uso l'altro + if dist( tFacAdj[1][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[1][nIdEndPoint] + Point3d( 0, 0, -dDepthMach), ptApPoint + Point3d( 0, 0, -dDepthMach), GDB_RT.GLOB) + local dLenTrimExt = dist( tFacAdj[1][nIdEndPoint], ptApPoint) - (( dToolDiam/2) + 2) + -- se la distanza dei due punti della linea è maggiore dal raggio fresa + delta, trimmo al raggio fresa + delta + if dLenTrimExt > 10 * GEO.EPS_SMALL then + EgtTrimExtendCurveByLen( nAuxId , -dLenTrimExt, ptApPoint + 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[1][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[1][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[1][nIdEndPoint] + Point3d( 0, 0, -dDepthMach), GDB_RT.GLOB) + table.insert( pAuxId, nAuxId) + end + -- ultima linea di distacco (5mm in direzione utensile) + local pEnd = tFacAdj[1][nIdEndPoint] + Point3d( 0, 0, -dDepthMach) + ( 5 * vtExtr) + nAuxId = EgtLine( nAddGrpId, tFacAdj[1][nIdEndPoint] + Point3d( 0, 0, -dDepthMach), pEnd, GDB_RT.GLOB) + table.insert( pAuxId, nAuxId) + else + -- linea di distacco (2mm in direzione utensile) + local pEnd = tFacAdj[1][nIdEndPoint] + ( 2 * vtExtr) + nAuxId = EgtLine( nAddGrpId, tFacAdj[1][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[1][nIdEndPoint], Z_AX(), dOffsAng, GDB_RT.GLOB) + end + -- inserisco la lavorazione + local sName = 'Clean_' .. ( EgtGetName( nNewProc) or tostring( nNewProc)) + local nMchId = EgtAddMachining( sName, sMilling) + if not nMchId then + local sErr = 'Error adding machining ' .. sName .. '-' .. sMilling + EgtOutLog( sErr) + return false, sErr + end + -- se flag lavorazione spessore passante setto la nota per spostarla dopo i tagli di lama + if bThruThick 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) + -- Note utente con dichiarazione nessuna generazione sfridi per Vmill + local sUserNotes = 'VMRS=0;' + -- aggiungo alle note massima elevazione +-- sUserNotes = sUserNotes .. 'MaxElev=' .. EgtNumToString( dMaxDepth, 1) .. ';' + 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, + AuxId, bThruThick, bNegZ) + + 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 dMillTotDiam = 20 + local dMillDiamTh = 20 + if EgtMdbSetCurrMachining( sMilling) then + local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID) + if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then + dMillTotDiam = EgtTdbGetCurrToolParam( MCH_TP.TOTDIAM) or dMillTotDiam + dMillDiamTh = EgtTdbGetCurrToolThDiam() or dMillDiamTh + 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 nFacInd + -- ottengo le dimensioni apertura, la normale e la faccia inferiore + local dDimMin, dDimMax, dDepth, vtOrtho, _, nSurfInt = GetTunnelDimension( nNewProc, Proc.PartId, nAddGrpId) + if nSurfInt then + -- uso la dimensione minima anche nel caso che la cava sborda perchè la lavorazione potrebbe collidere con un pezzo limitrofo + local dMinWidth = dDimMin +-- local dMinWidth = EgtIf( dMiddleFacetLength > 0.01, dMiddleFacetLength, dDimMin) + -- controllo le dimensioni della faccia, se dimensione minima al di sotto di un certo valore esco + -- per evitare collisioni +-- if dDepth >= dMinWidth / 2 or dMinWidth < WD.MIN_DIM_ALLOW_CLEAN + 100 * GEO.EPS_SMALL then +-- EgtErase( nNewProc) +-- return true +-- end + local nFacCntPre = EgtSurfTmFacetCount( nNewProc) + nNewProc = EgtSurfTmBySewing( nAddGrpId, {nNewProc,nSurfInt} , true) + -- riordino le facce + nNewProc = ReorderFacesFromTab( nNewProc, vFace) + -- acquisisco il numero della faccia + local nFacCnt = EgtSurfTmFacetCount( nNewProc) + nFacInd = nFacCnt - 1 + else + local sErr = 'Error : cannot create base surface' + EgtOutLog( sErr) + return false, sErr + end + -- verifico se ciclo chiuso + local bClosed = ( abs( vFace[1].AngPrev) > 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 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 + local tFacAdj = {} + local nFace1 = vFace[i].Fac + local nFace2 + -- aggiungo geometria + i = i + 1 + local j = EgtIf( i <= #vFace, i, EgtIf( bAllType4, nil, 1)) + nFace2 = vFace[j].Fac + -- 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 >= 90 creo istanza + if ptP1 and ptP2 and dAng < 0 and dAng > EgtIf( nTypeConeCut == 1, -(90 + 10 * GEO.EPS_SMALL), -(180-dAngleSmall + 10 * GEO.EPS_SMALL)) then + local dLen = dist( ptP1, ptP2) + table.insert( tFacAdj, { nFace1, nFace2, dLen, ptP1, ptP2, dAng}) + 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( nNewProc, nFacInd, tFacAdj, nTypeConeCut, nAddGrpId, + dToolDiam, dThick, sMilling, -dAngOffs, dDepthMach, + AuxId, max( dMillTotDiam, dMillDiamTh), bThruThick, dDepth, bNegZ) + if not bOk then return bOk, sErr end + -- secondo taglio + bOk, sErr = AddMillCornerMachining( nNewProc, nFacInd, tFacAdj, nTypeConeCut, nAddGrpId, + dToolDiam, dThick, sMilling, dAngOffs, dDepthMach, + AuxId, max( dMillTotDiam, dMillDiamTh), bThruThick, dDepth, bNegZ) + if not bOk then return bOk, sErr end + -- altrimenti ho un solo percorso + else + local bOk, sErr = AddMillCornerMachining( nNewProc, nFacInd, tFacAdj, nTypeConeCut, nAddGrpId, + dToolDiam, dThick, sMilling, 0, dDepthMach, + AuxId, max( dMillTotDiam, dMillDiamTh), bThruThick, dDepth, bNegZ) + 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 AddMillings( sMilling, vFace, Proc, nRawId, b3Raw, nConeCut, nAddGrpId) + -- flag per fresature non passanti + local bNotThrou + local dThick -- recupero i dati dell'utensile local dMillDiam = 20 local dMaxDepth = 0 @@ -108,10 +997,11 @@ local function AddMillings( sMilling, vFace, Proc, nRawId, b3Raw) if not nMchId then local sErr = 'Error adding machining ' .. sName .. '-' .. sMilling EgtOutLog( sErr) - return false, sErr + return 0, sErr end -- calcolo l'affondamento local dDepth = vFace[i].Width + WD.CUT_EXTRA + dThick = dDepth local vtNz = vFace[i].Norm:getZ() if vtNz < 0 then dDepth = dDepth - dMillDiam * abs( vtNz) / sqrt( 1 - vtNz * vtNz) @@ -121,6 +1011,7 @@ local function AddMillings( sMilling, vFace, Proc, nRawId, b3Raw) -- lo limito e tolgo eventuali Tabs dDepth = dMaxDepth EgtSetMachiningParam( MCH_MP.LEAVETAB, false) + bNotThrou = true end -- aggiungo geometria EgtSetMachiningGeometry( {{ Proc.Id, vFace[i].Fac}}) @@ -146,7 +1037,7 @@ local function AddMillings( sMilling, vFace, Proc, nRawId, b3Raw) if not EgtApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchId, false) - return false, sErr + return 0, sErr end end -- se tutta la faccia o la sua fine senza taglio, inserisco una fresatura @@ -157,10 +1048,11 @@ local function AddMillings( sMilling, vFace, Proc, nRawId, b3Raw) if not nMchId then local sErr = 'Error adding machining ' .. sName .. '-' .. sMilling EgtOutLog( sErr) - return false, sErr + return 0, sErr end -- calcolo l'affondamento local dDepth = vFace[i].Width + WD.CUT_EXTRA + dThick = dDepth local vtNz = vFace[i].Norm:getZ() if vtNz < 0 then dDepth = dDepth - dMillDiam * abs( vtNz) / sqrt( 1 - vtNz * vtNz) @@ -170,6 +1062,7 @@ local function AddMillings( sMilling, vFace, Proc, nRawId, b3Raw) -- lo limito e tolgo eventuali Tabs dDepth = dMaxDepth EgtSetMachiningParam( MCH_MP.LEAVETAB, false) + bNotThrou = true end -- aggiungo geometria local vGeom = {{ Proc.Id, vFace[i].Fac}} @@ -186,41 +1079,89 @@ local function AddMillings( sMilling, vFace, Proc, nRawId, b3Raw) i = i + 1 j = EgtIf( j + 1 <= #vFace, j + 1, EgtIf( bAllType4 or not bClosed, nil, 1)) end - EgtSetMachiningGeometry( vGeom) - 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 - EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.ADIR_XP) + -- se non devo scaricare l'angolo + if nConeCut <= 1 then + EgtSetMachiningGeometry( vGeom) + 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 + EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.ADIR_XP) + -- altrimenti se devo fare rientranza per inserimento utensile cono 30° + elseif nConeCut == 2 then + -- creo la costruzione del percorso + local nPathId, sErr = MakeCustomPath( vGeom, nConeCut, dMillDiam, nAddGrpId, dThick) + if nPathId == 0 then return false, 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) + -- 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 + -- creo la costruzione del percorso + local nPathId, sErr = MakeCustomPath( vGeom, nConeCut, dMillDiam, nAddGrpId) + if nPathId == 0 then return false, 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) + -- 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 false, sErr + return 0, sErr end else i = i + 1 end end - return true + -- 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 -- 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 @@ -234,10 +1175,16 @@ local function AddSawings( sSawing, vFace, Proc, nRawId, b3Raw) if not nMchId then local sErr = 'Error adding machining ' .. sName .. '-' .. sSawing EgtOutLog( sErr) - return false, sErr + return 0, sErr end -- calcolo l'affondamento - local dDepth = min( vFace[i].Width + WD.CUT_EXTRA, dMaxDepth) +-- local dDepth = min( vFace[i].Width + WD.CUT_EXTRA, dMaxDepth) + local dDepth = vFace[i].Width + WD.CUT_EXTRA + -- se affondamento superiore ai limiti della fresa + if dDepth > dMaxDepth then + dDepth = dMaxDepth + bNotThrou = true + end -- aggiungo geometria EgtSetMachiningGeometry( {{ Proc.Id, vFace[i].Fac}}) local dSal = - dSawDiam / 2 @@ -258,7 +1205,7 @@ local function AddSawings( sSawing, vFace, Proc, nRawId, b3Raw) if not EgtApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchId, false) - return false, sErr + 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 @@ -269,10 +1216,16 @@ local function AddSawings( sSawing, vFace, Proc, nRawId, b3Raw) if not nMchId then local sErr = 'Error adding machining ' .. sName .. '-' .. sSawing EgtOutLog( sErr) - return false, sErr + return 0, sErr end -- calcolo l'affondamento - local dDepth = min( vFace[i].Width + WD.CUT_EXTRA, dMaxDepth) +-- local dDepth = min( vFace[i].Width + WD.CUT_EXTRA, dMaxDepth) + local dDepth = vFace[i].Width + WD.CUT_EXTRA + -- se affondamento superiore ai limiti della fresa + if dDepth > dMaxDepth then + dDepth = dMaxDepth + bNotThrou = true + end -- aggiungo geometria EgtSetMachiningGeometry( {{ Proc.Id, vFace[i].Fac}}) local dSal = - dSawDiam / 2 @@ -296,11 +1249,15 @@ local function AddSawings( sSawing, vFace, Proc, nRawId, b3Raw) if not EgtApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchId, false) - return false, sErr + return 0, sErr end end end - return true + -- se fresature non sono passanti + if bNotThrou then + return 2, dSawThick + end + return 1, dSawThick end --------------------------------------------------------------------- @@ -368,7 +1325,7 @@ local function AddCuts( sCutting, vFace, Proc, nRawId, b3Raw, dSawThick) end --------------------------------------------------------------------- -local function MakeByCut( Proc, nRawId, b3Raw) +local function MakeByCut( Proc, nRawId, b3Raw, bDeleteBottomFacet) -- ingombro del pezzo local Ls = EgtGetFirstNameInGroup( Proc.PartId, 'Box') local b3Solid = EgtGetBBoxGlob( Ls or GDB_ID.NULL, GDB_BB.STANDARD) @@ -379,6 +1336,7 @@ local function MakeByCut( Proc, nRawId, b3Raw) end -- recupero la curva associata local bOpposite = false + local bNegZ = false local AuxId = EgtGetInfo( Proc.Id, 'AUXID', 'i') if AuxId then AuxId = AuxId + Proc.Id @@ -386,7 +1344,10 @@ local function MakeByCut( Proc, nRawId, b3Raw) if vtExtr then bOpposite = ( Proc.Grp == 4 and vtExtr:getZ() < 0) or ( Proc.Grp == 3 and vtExtr:getZ() > 0) end + if vtExtr:getZ() < 0 then bNegZ = true end end + -- lettura parametri (probabile/i parametro/i Q) + local nConeCut = VerifyCornerType( Proc) -- recupero la lavorazione di taglio con lama e i suoi parametri local sCutting, dSawDiam, dSawThick, dSawMaxDepth = WM.FindCutting( 'Standard') if not sCutting then @@ -394,130 +1355,10 @@ local function MakeByCut( Proc, nRawId, b3Raw) EgtOutLog( sErr) return false, sErr end - -- recupero i dati di tutte le facce - local vFace = {} - for i = 1, Proc.Fct do - -- indice faccia corrente e precedente - local nFac = EgtIf( bOpposite, Proc.Fct - i, i - 1) - local nPrecFac - if bOpposite then - nPrecFac = EgtIf( i == 1, 0, nFac + 1) - else - nPrecFac = EgtIf( i == 1, Proc.Fct - 1, i - 2) - end - -- recupero centro e normale della faccia - local ptCen, vtN = EgtSurfTmFacetCenter( Proc.Id, nFac, GDB_ID.ROOT) - -- recupero le dimensioni della faccia - local _, dLen, dWidth = WL.GetFaceHvRefDim( Proc.Id, nFac) - -- recupero l'angolo con la faccia precedente - local bAdj, _, _, dAng = EgtSurfTmFacetsContact( Proc.Id, nPrecFac, nFac, GDB_ID.ROOT) - -- salvo i dati - vFace[i] = { Fac = nFac, Cen = ptCen, Norm = vtN, Len = dLen, Width = dWidth, AngPrev = EgtIf( bAdj, dAng, 0)} - 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 > dSawMaxDepth then - dDepth = dSawMaxDepth - vFace[i].Width - end - -- lunghezza baffo - local dElev = vFace[i].Width + dDepth - local dWhisk = dElev * sqrt( dSawDiam / dElev - 1) + WHISK_SAFE - -- determino la lunghezza del taglio passante e il tipo di attacco e uscita - local dLen = vFace[i].Len - local nType = 0 - if vFace[i].AngPrev < -0.1 then - dLen = dLen - dWhisk - nType = nType + 1 - end - if vFace[EgtIf( i < Proc.Fct, i + 1, 1)].AngPrev < -0.1 then - dLen = dLen - dWhisk - nType = nType + 2 - end - -- se lunghezza non significativa, non va inserito il taglio - if dLen < MIN_LEN_CUT then - nType = 4 - end - vFace[i].Depth = dDepth - vFace[i].Whisk = dWhisk - vFace[i].Type = nType - end - -- recupero le regioni degli altri pezzi - local vOthers = GetOtherRegions( Proc.PartId) - -- verifico i baffi sporgenti dei tagli rispetto alle altre regioni + -- gruppo ausiliario local nAddGrpId = WL.GetAddGroup( Proc.PartId) - 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 - WHISK_OFFS) * vtDir - local ptCross = ptDir + ( dSawThick - 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 - WHISK_OFFS) * vtDir - local ptCross = ptDir + ( dSawThick - 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 - -- 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.AngPrev, 1).. - ' D='..EgtNumToString( Face.Depth, 1)..' B='..EgtNumToString( Face.Whisk, 1)..' T='..tostring( Face.Type) - EgtOutLog( sOut) - end + -- recupero i dati di tutte le facce + local vFace, dMaxWidth, nNewProc = GetFacesData( Proc, bOpposite, true, dSawDiam, dSawMaxDepth, dSawThick, nAddGrpId, bDeleteBottomFacet) -- inserimento dei tagli di lama local bCtOk, sCtErr = AddCuts( sCutting, vFace, Proc, nRawId, b3Raw, dSawThick) if not bCtOk then return bCtOk, sCtErr end @@ -535,12 +1376,27 @@ local function MakeByCut( Proc, nRawId, b3Raw) end -- se possibile, inserimento delle fresature if sMilling then - local bMlOk, sMlErr = AddMillings( sMilling, vFace, Proc, nRawId, b3Raw) - if not bMlOk then return bMlOk, sMlErr end + local nMlOk, sMlErr, dThick = AddMillings( sMilling, vFace, Proc, nRawId, b3Raw, nConeCut, nAddGrpId) + if nMlOk == 0 then return false, sMlErr end + -- se abilitata la lavorazione corner con stop macchina e lavorazione precedente passante + -- o con fresa cono piccola e spessore sotto il limite + if ( nConeCut == 1 and nMlOk == 1) 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, + AuxId, true, bNegZ) + if not bMcok then return bMcok, sMcErr end + end -- altrimenti provo con la sega a catena else - local bCsOk, sCSErr = AddSawings( sSawing, vFace, Proc, nRawId, b3Raw) - if not bCsOk then return bCsOk, sCsErr end + local nCsOk, sCSErr = AddSawings( sSawing, vFace, Proc, nRawId, b3Raw) + if nCsOk == 0 then return false, sCsErr end + -- se abilitata la lavorazione corner con stop macchina e lavorazione precedente passante + if nConeCut == 1 and nCsOk == 1 then + local bMcok, sMcErr = AddMillCorner( nConeCut, vFace, Proc, nRawId, b3Raw, + sCSErr, nAddGrpId, nil, nNewProc, 0, + AuxId, true, bNegZ) + if not bMcok then return bMcok, sMcErr end + end end return true end @@ -638,19 +1494,68 @@ 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 - if AuxId then AuxId = AuxId + Proc.Id end - if not AuxId or ( EgtGetType( AuxId) & GDB_FY.GEO_CURVE) == 0 then + local vtExtr + local bNegZ = false + 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) + end + if vtExtr:getZ() < 0 then bNegZ = true 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 -- recupero i dati della curva e del profilo - local dDepth = abs( EgtCurveThickness( AuxId)) - local vtExtr = EgtCurveExtrusion( AuxId, GDB_RT.GLOB) + local dDepth = EgtIf( bPocketBotface, 0, abs( EgtCurveThickness( AuxId))) + local dOriDepth = dDepth + local nFacet + local dDiam + local dElev + -- cerco la faccia di fondo della superfice per calcolare le dimensioni del rettangolo + for i = 1, Proc.Fct do + local _, vtN = EgtSurfTmFacetCenter( Proc.Id, i-1, GDB_ID.ROOT) + if AreSameVectorApprox( vtN, Z_AX()) or AreSameVectorApprox( -vtN, Z_AX()) then + nFacet = i-1 + break + end + end + if nFacet then + local _, dH, dV = EgtSurfTmFacetMinAreaRectangle( Proc.Id, nFacet, GDB_ID.ROOT) + dDiam = min( dH, dV) + dElev = WL.GetFaceElevation( Proc.Id, nFacet, nRawId) + end + -- 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 bToolInv = ( vtExtr:getZ() < -0.1) -- recupero la lavorazione - local sPocketing = WM.FindPocketing( 'Pocket', nil, dDepth) + local sPocketing = WM.FindPocketing( 'Pocket', dDiam, dDepth) if not sPocketing then local sErr = 'Error : pocketing not found in library' EgtOutLog( sErr) @@ -659,11 +1564,13 @@ local function MakeByPocket( Proc, nRawId, b3Raw) -- 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 = EgtTdbGetCurrToolMaxDepth() or dMaxDepth + dThDiam = EgtTdbGetCurrToolThDiam() or dThDiam end end -- inserisco la lavorazione di svuotatura @@ -675,28 +1582,53 @@ local function MakeByPocket( Proc, nRawId, b3Raw) return false, sErr end -- aggiungo geometria - EgtSetMachiningGeometry( {{ AuxId, -1}}) + 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) - -- se elevazione superiore a massimo affondamento della fresa, riduco opportunamente - if dDepth > dMaxDepth + 10 * GEO.EPS_SMALL then - dDepth = dMaxDepth - local sWarn = 'Warning : elevation bigger than max tool depth' - EgtOutLog( 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 + local 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( dMaxDepth, 1) .. ';') + EgtSetMachiningParam( MCH_MP.USERNOTES, 'MaxElev=' .. EgtNumToString( EgtIf( bPocketBotface, min( dElev, dMaxDepth), dMaxDepth), 1) .. ';') -- eseguo if not EgtApplyMachining( true, false) 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, false, nNewProc) + -- se abilitata la lavorazione corner con stop macchina e lavorazione precedente passante + if nConeCut == 1 then + local bMcok, sMcErr = AddMillCorner( nConeCut, vFace, Proc, nRawId, b3Raw, + dMillDiam, nAddGrpId, nil, nNewProc, EgtIf( bPocketBotface, dDepth, ( dDepth - dOriDepth)), + AuxId, nil, bNegZ) + if not bMcok then return bMcok, sMcErr end + end return true end diff --git a/LuaLibs/WProcessLapJoint.lua b/LuaLibs/WProcessLapJoint.lua index a5d5a76..37ead4b 100644 --- a/LuaLibs/WProcessLapJoint.lua +++ b/LuaLibs/WProcessLapJoint.lua @@ -14,6 +14,16 @@ EgtOutLog( ' WProcessLapJoint started', 1) -- Dati local WD = require( 'WallData') local WM = require( 'WMachiningLib') +local WHISK_OFFS = 0.1 +local WHISK_SAFE = 5 +local MIN_LEN_CUT = 30 + +-- variabili assegnazione parametri Q +local sTypeCornerCut = 'Q05' -- i +-- variabile settaggio doppia lavorazione su angoo > 90 +local bMakeTwinCut = true +-- angolo sottosquadra ammesso per fresa cono 30° +local dAngleSmall = 70 --------------------------------------------------------------------- -- Riconoscimento della feature @@ -103,6 +113,664 @@ function WPL.Classify( Proc, b3Raw) end 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) + + local nConeCut = 0 + -- verifico il tipo di lavorazione su angolo. 0 : nessuna ripresa corner; 1: ripresa corner con pausa; + -- 2: ripresa corner senza pausa; 3: scarico corner + local nParamValue = EgtGetInfo( Proc.Id, sTypeCornerCut, 'i') or nConeCut + -- se tipo di lavorazione con fesa conica 60° con pausa + nConeCut = nParamValue + return nConeCut +end + +--------------------------------------------------------------------- +local function GetOtherRegions( nPartId) + local vOthers = {} + local nOtherId = EgtGetFirstPartInRawPart( EgtGetFirstRawPart() or GDB_ID.NULL) + while nOtherId do + 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 + table.insert( vOthers, { PartId = nOtherId, RegId = nRegId, Box = b3Reg}) + end + end + nRegId = EgtGetNext( nRegId) + end + nOtherId = EgtGetNextPartInRawPart( nOtherId) + end + return vOthers +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) + -- ordino il numero di facce in modo da avere una sequenza di facce concatenate + for i = 1, (nNumFacet-1) do + -- recupero l'angolo con la faccia precedente + local bAdj, _, _, _ = EgtSurfTmFacetsContact( nNewProc, i-1, i, GDB_ID.ROOT) + -- se non ho adiacenza + if not bAdj then + for j = i+1, nNumFacet do + bAdj, _, _, _ = EgtSurfTmFacetsContact( nNewProc, i-1, j-1, GDB_ID.ROOT) + -- se ho adiacenza scambio le facce + if bAdj then + EgtSurfTmSwapFacets( nNewProc, i, (j-1)) + break + end + end + end + end + + return nNewProc, nNumFacet +end + +--------------------------------------------------------------------- +local function GetFacesData( nNewProc, bOpposite, bCalclForBlade, dToolDiam, dToolMaxDepth, dToolThick, nAddGrpId, nPartId) + + local nNumFacet = EgtSurfTmFacetCount( nNewProc) + local vFace = {} + -- recupero i dati di tutte le facce + for i = 1, nNumFacet do + -- indice faccia corrente e precedente + local nFac = EgtIf( bOpposite, nNumFacet - i, i - 1) + local nPrecFac + if bOpposite then + nPrecFac = EgtIf( i == 1, 0, nFac + 1) + else + nPrecFac = EgtIf( i == 1, nNumFacet - 1, i - 2) + end + -- recupero centro e normale della faccia + local ptCen, vtN = EgtSurfTmFacetCenter( nNewProc, nFac, GDB_ID.ROOT) + -- recupero le dimensioni della faccia + local _, dLen, dWidth = WL.GetFaceHvRefDim( nNewProc, nFac) + -- recupero l'angolo con la faccia precedente + local bAdj, _, _, dAng = EgtSurfTmFacetsContact( nNewProc, nPrecFac, nFac, GDB_ID.ROOT) + -- salvo i dati + vFace[i] = { Fac = nFac, Cen = ptCen, Norm = vtN, Len = dLen, Width = dWidth, AngPrev = EgtIf( bAdj, dAng, 0)} + 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 nType = 0 + if vFace[i].AngPrev < -0.1 then + dLen = dLen - EgtIf( bCalclForBlade, dWhisk, 0) + nType = nType + 1 + end + if vFace[EgtIf( i < nNumFacet, i + 1, 1)].AngPrev < -0.1 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 + vFace[i].Depth = dDepth + vFace[i].Whisk = dWhisk + vFace[i].Type = nType + end + -- recupero le regioni degli altri pezzi + local vOthers = GetOtherRegions( nPartId) + -- 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 - WHISK_OFFS) * vtDir + local ptCross = ptDir + ( dToolThick - 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 - WHISK_OFFS) * vtDir + local ptCross = ptDir + ( dToolThick - 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 + -- 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.AngPrev, 1).. + ' D='..EgtNumToString( Face.Depth, 1)..' B='..EgtNumToString( Face.Whisk, 1)..' T='..tostring( Face.Type) + EgtOutLog( sOut) + end + + return vFace, dMaxWidth, nNewProc +end + +--------------------------------------------------------------------- +local function GetTunnelDimension( nId, nPartId, nAddGrpId) + -- ottengo i versori delle 4 facce e ottengo l'orientamento del tunnel + -- recupero il numero di facce + local nFacCnt = EgtSurfTmFacetCount( nId) + -- recupero l'ingombro della trave + local b3Solid = EgtGetBBoxGlob( EgtGetFirstNameInGroup( nPartId, 'Box') or GDB_ID.NULL, GDB_BB.STANDARD) + -- variabili dimensioni fessura e id faccia lunga + local dDimMin + local dDimMax + local nLongIdFace = 0 + local bNegFace + local bOppoFace = false + -- ottengo il versore ortogonale + local ptN1, vtN1 = EgtSurfTmFacetCenter( nId, 0, GDB_ID.ROOT) + local _, vtN2 = EgtSurfTmFacetCenter( nId, 1, GDB_ID.ROOT) + local vtOrtho = vtN1 ^ vtN2 + if vtOrtho:isSmall() then + _, vtN2 = EgtSurfTmFacetCenter( nId, 2, GDB_ID.ROOT) + vtOrtho = vtN1 ^ vtN2 + bOppoFace = true + end + if vtOrtho:getZ() < -0.5 then + vtOrtho = -vtOrtho + bNegFace = true + end + -- ottengo il boundingBox e prendo le dimensioni lungo la normale (Z locale) che rappresenta la profondità della fessura + local frFc = Frame3d( ptN1, vtOrtho) ; + local bBoxLoc = EgtGetBBoxRef( nId, GDB_BB.STANDARD, frFc) + local dDepth = bBoxLoc:getDimZ() + -- mi assicuro che la Z del punto utilizzato per creare la superficie sia alla Z inferiore del bounding box locale + local ptN2 = Point3d(ptN1) + ptN2:toLoc(frFc) + ptN2 = Point3d( ptN2:getX(), ptN2:getY(), bBoxLoc:getMin():getZ() + 2*GEO.EPS_SMALL) + ptN2:toGlob(frFc) + -- creo superficie intermedia + local nSurfInt = EgtSurfTmPlaneInBBox( nAddGrpId, ptN2, vtOrtho, b3Solid, GDB_ID.ROOT) + -- 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 (era su di 2 * GEO.EPS_SMALL) + EgtMove( nSurfInt, Point3d(0,0,-2*GEO.EPS_SMALL) - ORIG(), GDB_RT.GLOB) + -- mi faccio dare il contorno della superfice e la ricreo in modo più corretto + local nIdCont, nIdNum = EgtExtractSurfTmLoops( nSurfInt, nAddGrpId) + -- elimino le entità allineate dello stesso tipo + EgtMergeCurvesInCurveCompo( nIdCont, 2*GEO.EPS_SMALL) + EgtErase(nSurfInt) + nSurfInt = EgtSurfTmByFlatContour( nAddGrpId, nIdCont, 2*GEO.EPS_SMALL) + -- elimino il contorno + EgtErase(nIdCont) + -- se normale negativa inverto + _, vtN1 = EgtSurfTmFacetCenter( nSurfInt, 0, GDB_ID.ROOT) + if vtN1:getZ() < -0.5 then EgtInvertSurf( nSurfInt) end + local _, DimH, DimV = EgtSurfTmFacetMinAreaRectangle( nSurfInt, 0, GDB_ID.ROOT) + dDimMin = min( DimH, DimV) + dDimMax = max( DimH, DimV) + _, DimH, DimV = EgtSurfTmFacetMinAreaRectangle( nId, nFacCnt-1, GDB_ID.ROOT) + -- se faccia pari alla larghezza fessura + if abs(DimH - dDimMax) < GEO.EPS_SMALL or abs(DimV - dDimMax) < GEO.EPS_SMALL then + nLongIdFace = nFacCnt-1 + -- altrimenti verifico anche con la faccia precedente + else + local nFaceToCheck = EgtIf( bOppoFace, nFacCnt-3, nFacCnt-2) + -- prendo le dimensioni della faccia e poi confronto con il minimo + _, DimH, DimV = EgtSurfTmFacetMinAreaRectangle( nId, nFaceToCheck, GDB_ID.ROOT) + -- se trovato con il minimo, questa seconda faccia non è la più lunga + if abs(DimH - dDimMin) < GEO.EPS_SMALL or abs(DimV - dDimMin) < GEO.EPS_SMALL then + nLongIdFace = nFacCnt-1 + else + nLongIdFace = nFaceToCheck + end + end + if not dDimMax then + return dDimMin, dDimMax, dDepth, nil, nil + end + return dDimMin, dDimMax, dDepth, vtOrtho, nLongIdFace, nSurfInt +end + +--------------------------------------------------------------------- +local function ReorderFaces( 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 AddMillCornerMachining( nNewProc, nFacInd, tFacAdj, nTypeConeCut, nAddGrpId, dToolDiam, dThick, sMilling, dOffsAng, dDepthMach) + -- variabili costruzione geometria + local pAuxId = {} + local nAuxId + local ptApPoint + local AuxId + -- prendo il primo versore + local _, vtN1 = EgtSurfTmFacetCenter( nNewProc, nFacInd, GDB_ID.ROOT) + local _, vtN2 = EgtSurfTmFacetCenter( nNewProc, tFacAdj[1][1], GDB_ID.ROOT) + local _, vtN3 = EgtSurfTmFacetCenter( nNewProc, tFacAdj[1][2], GDB_ID.ROOT) + -- trovo il punto sulla superfice di riferimento + local _, ptLocP1, ptLocP2, _ = EgtSurfTmFacetsContact( nNewProc, nFacInd, tFacAdj[1][1], GDB_ID.ROOT) + local nIdIniPoint + local nIdEndPoint + if ptLocP1 and ptLocP2 then + if ( dist( ptLocP1, tFacAdj[1][4]) < GEO.EPS_SMALL) or ( dist( ptLocP2, tFacAdj[1][4]) < GEO.EPS_SMALL) then + nIdEndPoint = 4 + nIdIniPoint = 5 + elseif ( dist( ptLocP1, tFacAdj[1][5]) < GEO.EPS_SMALL) or ( dist( ptLocP2, tFacAdj[1][5]) < GEO.EPS_SMALL) then + nIdEndPoint = 5 + nIdIniPoint = 4 + end + end + -- versore direzione + local vtExtr = tFacAdj[1][nIdIniPoint] - tFacAdj[1][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 : clean corner milling from bottom impossible' + 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() + nAuxId = EgtLine( nAddGrpId, tFacAdj[1][nIdIniPoint], tFacAdj[1][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[1][nIdEndPoint], ptLocP1) < 10 * GEO.EPS_SMALL then + ptApPoint = ptLocP2 + else + ptApPoint = ptLocP1 + end + nAuxId = EgtLine( nAddGrpId, tFacAdj[1][nIdEndPoint] + Point3d( 0, 0, -dDepthMach), ptApPoint + Point3d( 0, 0, -dDepthMach), GDB_RT.GLOB) + local dLenTrimExt = dist( tFacAdj[1][nIdEndPoint], ptApPoint) - (( dToolDiam/2) + 2) + -- se la distanza dei due punti della linea è maggiore dal raggio fresa + delta, trimmo al raggio fresa + delta + if dLenTrimExt > 10 * GEO.EPS_SMALL then + EgtTrimExtendCurveByLen( nAuxId , -dLenTrimExt, ptApPoint + 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[1][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[1][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[1][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, _ = EgtSurfTmFacetsContact( nNewProc, nFacInd, tFacAdj[1][2], GDB_ID.ROOT) + if ptLocP1 and ptLocP2 then + -- se il punto finale corrisponde con il punto utilizzato in precedenza, uso l'altro + if dist( tFacAdj[1][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[1][nIdEndPoint] + Point3d( 0, 0, -dDepthMach), ptApPoint + Point3d( 0, 0, -dDepthMach), GDB_RT.GLOB) + local dLenTrimExt = dist( tFacAdj[1][nIdEndPoint], ptApPoint) - (( dToolDiam/2) + 2) + -- se la distanza dei due punti della linea è maggiore dal raggio fresa + delta, trimmo al raggio fresa + delta + if dLenTrimExt > 10 * GEO.EPS_SMALL then + EgtTrimExtendCurveByLen( nAuxId , -dLenTrimExt, ptApPoint + 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[1][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[1][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[1][nIdEndPoint] + Point3d( 0, 0, -dDepthMach), GDB_RT.GLOB) + table.insert( pAuxId, nAuxId) + end + -- ultima linea di distacco (5mm in direzione utensile) + local pEnd = tFacAdj[1][nIdEndPoint] + Point3d( 0, 0, -dDepthMach) + ( 5 * vtExtr) + nAuxId = EgtLine( nAddGrpId, tFacAdj[1][nIdEndPoint] + Point3d( 0, 0, -dDepthMach), pEnd, GDB_RT.GLOB) + table.insert( pAuxId, nAuxId) + else + -- linea di distacco (2mm in direzione utensile) + local pEnd = tFacAdj[1][nIdEndPoint] + ( 2 * vtExtr) + nAuxId = EgtLine( nAddGrpId, tFacAdj[1][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[1][nIdEndPoint], Z_AX(), dOffsAng, GDB_RT.GLOB) + end + -- inserisco la lavorazione + local sName = 'Clean_' .. ( EgtGetName( nNewProc) or tostring( nNewProc)) + local nMchId = EgtAddMachining( sName, sMilling) + if not nMchId then + local sErr = 'Error adding machining ' .. sName .. '-' .. sMilling + EgtOutLog( sErr) + return false, sErr + end + -- aggiungo geometria + EgtSetMachiningGeometry( {{ 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) + -- Note utente con dichiarazione nessuna generazione sfridi per Vmill + local sUserNotes = 'VMRS=0;' + -- aggiungo alle note massima elevazione +-- sUserNotes = sUserNotes .. 'MaxElev=' .. EgtNumToString( dMaxDepth, 1) .. ';' + 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, dMiddleFacetLength) + + 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 + -- 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 nFacInd + -- ottengo le dimensioni apertura, la normale e la faccia inferiore + local dDimMin, dDimMax, dDepth, vtOrtho, _, nSurfInt = GetTunnelDimension( nNewProc, Proc.PartId, nAddGrpId) + if nSurfInt then + -- uso la dimensione minima anche nel caso che la cava sborda perchè la lavorazione potrebbe collidere con un pezzo limitrofo + local dMinWidth = dDimMin +-- local dMinWidth = EgtIf( dMiddleFacetLength > 0.01, dMiddleFacetLength, dDimMin) + -- controllo le dimensioni della faccia, se dimensione minima al di sotto di un certo valore esco + -- per evitare collisioni + if dDepth >= dMinWidth / 2 or dMinWidth < WD.MIN_DIM_ALLOW_CLEAN + 100 * GEO.EPS_SMALL then + EgtErase( nNewProc) + return true + end + local nFacCntPre = EgtSurfTmFacetCount( nNewProc) + nNewProc = EgtSurfTmBySewing( nAddGrpId, {nNewProc,nSurfInt} , true) + -- riordino le facce + nNewProc = ReorderFaces( nNewProc, vFace) + -- acquisisco il numero della faccia + local nFacCnt = EgtSurfTmFacetCount( nNewProc) + nFacInd = nFacCnt - 1 + else + local sErr = 'Error : cannot create base surface' + EgtOutLog( sErr) + return false, sErr + end + -- verifico se ciclo chiuso + local bClosed = ( abs( vFace[1].AngPrev) > 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 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 + local tFacAdj = {} + local nFace1 = vFace[i].Fac + local nFace2 + -- aggiungo geometria + i = i + 1 + local j = EgtIf( i <= #vFace, i, EgtIf( bAllType4, nil, 1)) + nFace2 = vFace[j].Fac + -- 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 >= 90 creo istanza + if ptP1 and ptP2 and dAng < 0 and dAng > EgtIf( nTypeConeCut == 1, -(90 + 10 * GEO.EPS_SMALL), -(180-dAngleSmall + 10 * GEO.EPS_SMALL)) then + local dLen = dist( ptP1, ptP2) + table.insert( tFacAdj, { nFace1, nFace2, dLen, ptP1, ptP2, dAng}) + 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( nNewProc, nFacInd, tFacAdj, nTypeConeCut, nAddGrpId, dToolDiam, dThick, sMilling, -dAngOffs, dDepthMach) + if not bOk then return bOk, sErr end + -- secondo taglio + bOk, sErr = AddMillCornerMachining( nNewProc, nFacInd, tFacAdj, nTypeConeCut, nAddGrpId, dToolDiam, dThick, sMilling, dAngOffs, dDepthMach) + if not bOk then return bOk, sErr end + -- altrimenti ho un solo percorso + else + local bOk, sErr = AddMillCornerMachining( nNewProc, nFacInd, tFacAdj, nTypeConeCut, nAddGrpId, dToolDiam, dThick, sMilling, 0, dDepthMach) + 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 MakeByChainSaw( Proc, nFacet, nRawId, b3Raw, dElev, dH, dV) local sWarn @@ -360,13 +1028,30 @@ local function MakeSideGrooveByMill( Proc, nFacet, nRawId, b3Raw) end --------------------------------------------------------------------- -local function MakeByPocketing( Proc, nFacet, nRawId, b3Raw) +local function MakeByPocketing( Proc, nFacet, nRawId, b3Raw, bCheckQPar) -- dati della faccia local ptC, vtN = EgtSurfTmFacetCenter( Proc.Id, nFacet, GDB_ID.ROOT) local dElev = WL.GetFaceElevation( Proc.Id, nFacet, nRawId) local _, dH, dV = EgtSurfTmFacetMinAreaRectangle( Proc.Id, nFacet, GDB_ID.ROOT) local dDiam = min( dH, dV) - if Proc.Fct < 5 then dDiam = dDiam * 2 end + -- 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 -- recupero la lavorazione local sPocketing = WM.FindPocketing( 'Pocket', dDiam, dElev) if not sPocketing then @@ -408,9 +1093,10 @@ local function MakeByPocketing( Proc, nFacet, nRawId, b3Raw) -- se elevazione superiore a massimo affondamento della fresa, riduco opportunamente local dThElev = dThDiam / 2 * sqrt( vtN:getX() * vtN:getX() + vtN:getY() * vtN:getY()) local dDepth = 0 + local sWarn = '' if dElev + dThElev > dMaxDepth + 10 * GEO.EPS_SMALL then dDepth = dMaxDepth - dElev - dThElev - local sWarn = 'Warning : elevation bigger than max tool depth' + sWarn = 'Warning : elevation bigger than max tool depth' EgtOutLog( sWarn) end EgtSetMachiningParam( MCH_MP.DEPTH, dDepth) @@ -422,7 +1108,26 @@ local function MakeByPocketing( Proc, nFacet, nRawId, b3Raw) EgtSetOperationMode( nMchFId, false) return false, sErr end - return true + -- verifica parametro Q per pulitura spigoli + if bCheckQPar then + -- lettura parametri (probabile/i parametro/i Q) + local nConeCut = VerifyCornerType( Proc) + -- recupero i dati di tutte le facce + local vFace, dMaxWidth = GetFacesData( nNewProc, false, false, dMillDiam, dMaxDepth, (dMillDiam/2), nAddGrpId, Proc.PartId) + -- se abilitata la lavorazione corner con stop macchina e lavorazione precedente passante + if nConeCut == 1 then + local bMcok, sMcErr = AddMillCorner( nConeCut, vFace, Proc, nRawId, b3Raw, dMillDiam, nAddGrpId, dMaxWidth, nNewProc, dDepth, dMiddleFacetLength) + if not bMcok then + EgtErase( nNewProc) + return bMcok, sMcErr + end + else + EgtErase( nNewProc) + end + else + EgtErase( nNewProc) + end + return true, sWarn end --------------------------------------------------------------------- @@ -585,7 +1290,7 @@ local function MakeMoreFaces( Proc, nRawId, b3Raw) end local nFacet = EgtIf( vtN:getZ() >= WD.NZ_MINA, nFacInd, nFacInd2) -- eseguo la svuotatura - return MakeByPocketing( Proc, nFacet, nRawId, b3Raw) + return MakeByPocketing( Proc, nFacet, nRawId, b3Raw, true) -- fessura verticale elseif Proc.Stype == 3 then -- riordino le facce come contorno libero da lavorare a destra (sono una U) diff --git a/LuaLibs/WallExec.lua b/LuaLibs/WallExec.lua index 929f3c1..9f93b8c 100644 --- a/LuaLibs/WallExec.lua +++ b/LuaLibs/WallExec.lua @@ -1,4 +1,4 @@ --- WallExec.lua by Egaltech s.r.l. 2020/11/12 +-- WallExec.lua by Egaltech s.r.l. 2020/12/23 -- Libreria esecuzione lavorazioni per Pareti -- Tabella per definizione modulo @@ -201,14 +201,15 @@ local function AddFeatureMachining( Proc, nRawId, b3Raw) end ------------------------------------------------------------------------------------------------------------- -local function MoveMachiningsAtEnd( nPhase, nType, sStartName) +local function MoveMachiningsAtEnd( nPhase, nType, sStartName, sProperty) local nOperId = EgtGetPhaseDisposition( nPhase) local nLastId = EgtGetLastOperation() local nInsertId = nLastId while nOperId do local nNextOperId = EgtGetNextOperation( nOperId) if EgtGetOperationPhase( nOperId) == nPhase and EgtGetOperationType( nOperId) == nType and - ( not sStartName or string.sub( EgtGetName( nOperId), 1, #sStartName) == sStartName) then + ( ( EgtGetInfo( nOperId, 'MOVE_AFTER', 'i') == 1 ) or + ( not sStartName or string.sub( EgtGetName( nOperId), 1, #sStartName) == sStartName)) then EgtRelocateGlob( nOperId, nInsertId, GDB_IN.AFTER) nInsertId = nOperId end @@ -217,16 +218,88 @@ local function MoveMachiningsAtEnd( nPhase, nType, sStartName) end nOperId = nNextOperId end +end +------ Ordinamento dei tagli, delle fresature e delle forature ------- +local function SortMach( nPhase, LastMch, nType, sStartName, bExistName, sInfo, bExistInfo) + -- dichiarazione tabella + local TabCut = {} + -- Recupero gli identificativi delle lavorazioni e annullo eventuali allungamenti e Id di altre lavorazioni rappresentate + local nOperId = EgtGetPhaseDisposition( nPhase) + while nOperId do + -- Se appartiene alla fase corrente e taglio con lama non da sopra (sempre su 1 sola entità) + if EgtGetOperationPhase( nOperId) == nPhase and EgtGetOperationType( nOperId) == nType and + ( not sStartName or ( string.sub( EgtGetName( nOperId), 1, #sStartName) == sStartName and bExistName) or + ( string.sub( EgtGetName( nOperId), 1, #sStartName) ~= sStartName and not bExistName)) and + ( not sInfo or ( EgtGetInfo( nOperId, sInfo, 'i') == 1 and bExistInfo) or + ( EgtGetInfo( nOperId, sInfo, 'i') ~= 1 and not bExistInfo)) then + -- rendo comunque attiva la lavorazione + EgtSetOperationMode( nOperId, true) + EgtSetCurrMachining( nOperId) + if not EgtIsMachiningEmpty() then + -- punto iniziale e finale e direzione della lavorazione + local ptStart = EgtGetMachiningStartPoint() + local ptEnd = EgtGetMachiningEndPoint() + table.insert( TabCut, {Mch=nOperId, Ent=nEntId, Start=ptStart, End=ptEnd}) + end + end + -- Passo alla operazione successiva + nOperId = EgtGetNextOperation( nOperId) + end + + -- ordino le lavorazioni + --EgtOutLog('Dati per ShortestPath :') + EgtSpInit() + for i = 1, #TabCut do + local ptS = TabCut[i].Start + local ptE = TabCut[i].End + EgtSpAddPoint( ptS:getX(), ptS:getY(), ptS:getZ(), 0, 0, + ptE:getX(), ptE:getY(), ptE:getZ(), 0, 0) + end + EgtSpSetAngularParams( 1000, 40, 2000, 60) + EgtSpSetOpenBound( true,SHP_OB.NEAR_PNT,-2000,0,0,90,90) + local vOrd = EgtSpCalculate( SHP_TY.OPEN) + EgtSpTerminate() + + -- applico ordinamento calcolato + if vOrd then + for i = 1, #vOrd do + EgtRelocateGlob( TabCut[vOrd[i]].Mch, LastMch, GDB_IN.AFTER) + LastMch = TabCut[vOrd[i]].Mch + end + end + + return LastMch end ------------------------------------------------------------------------------------------------------------- local function SortMachinings() + -- Recupero la fase corrente local nPhase = 1 + local LastMch = EgtGetLastOperation() + -- ordino i tagli di lama e li metto alla fine + LastMch = SortMach( nPhase, LastMch, MCH_OY.SAWING) + -- ordino i tagli con segacatena che non hanno nel nome la parte indicata + -- e li metto nelle prime posizioni + local LastMchMort = EgtGetPhaseDisposition( nPhase) + LastMchMort = SortMach( nPhase, LastMchMort, MCH_OY.MORTISING, 'Csaw_', false) + -- ordino i tagli con segacatena che hanno nel nome la parte indicata + -- e li metto nelle ultime + LastMch = SortMach( nPhase, LastMch, MCH_OY.MORTISING, 'Csaw_', true) + -- ordino le fresature che non hanno la nota indicata e le metto alla fine degli eventuali tagli di sega-catena + LastMchMort = SortMach( nPhase, LastMchMort, MCH_OY.MILLING, 'Clean_', false, 'MOVE_AFTER', false) + -- ordino le svuotature e le metto alla fine degli eventuali tagli di sega-catena + LastMchMort = SortMach( nPhase, LastMchMort, MCH_OY.POCKETING) + -- ordino le fresature che hanno la nota indicata e le metto alla fine + LastMch = SortMach( nPhase, LastMch, MCH_OY.MILLING, nil, nil, 'MOVE_AFTER', true) + -- lascio commentate gli spostamenti delle lavorazioni nel caso ci sarà qualche lavorazione + -- non ancora contemplata che richiede queste funzioni -- Sposto i tagli di lama alla fine - MoveMachiningsAtEnd( nPhase, MCH_OY.SAWING) - -- Sposto i tagli con sega a catena dopo i tagli di lama - MoveMachiningsAtEnd( nPhase, MCH_OY.MORTISING, 'Csaw_') +-- MoveMachiningsAtEnd( nPhase, MCH_OY.SAWING) + -- Sposto i tagli con sega a catena che hanno un certo nome dopo i tagli di lama (i tagli del freecontour con segacatena non vengono spostati perchè hanno un nome diverso) +-- MoveMachiningsAtEnd( nPhase, MCH_OY.MORTISING, 'Csaw_') + -- Sposto le lavorazioni di pulitura spigolo passanti dopo i tagli di lama e con sega a catena +-- MoveMachiningsAtEnd( nPhase, MCH_OY.MILLING, nil, 'MoveAfter') end -------------------------------------------------------------------------------------------------------------