-- CalcToolPath.lua by Egaltech s.r.l. 2022/12/20 -- Calcolo percorsi di lavoro per Stampa 3d -- Tabella per definizione modulo local CalcToolPath = {} -- Intestazioni require( 'EgtBase') EgtOutLog( ' CalcToolPath started', 1) -- Dati local AMD = require( 'AddManData') --------------------------------------------------------------------- local s_nPartId local s_nDefaultWipeAng = -90 -- angolo = 0° per wipe significa che esce ortogonalmente alla direzione del movimento local s_dHMin --------------------------------------------------------------------- local function GetLayerParamsForToolPathCalc() local LayerParams = {} LayerParams.bSpiralVase = EgtGetInfo( s_nPartId, KEY_SPIRAL_VASE, 'b') or false LayerParams.dStrand = EgtGetInfo( s_nPartId, KEY_STRAND, 'd') LayerParams.dLayHeight = EgtGetInfo( s_nPartId, KEY_SLICE_STEP, 'd') LayerParams.dOffs = EgtGetInfo( s_nPartId, KEY_OFFSET_SLICE, 'd') LayerParams.bInvert = ( EgtGetInfo( s_nPartId, KEY_PRINT_DIRECTION, 'i') == PRINT_DIRECTION.CW) LayerParams.nOrder = EgtGetInfo( s_nPartId, KEY_STRAND_ORDER, 'i') LayerParams.vPrintOrder = EgtGetInfo( s_nPartId, KEY_PRINT_ORDER, 'vi') or { 1, 2, 3, 4, 5} LayerParams.nLinkType = EgtGetInfo( s_nPartId, KEY_LINK_TYPE, 'i') LayerParams.dLinkParam = EgtGetInfo( s_nPartId, KEY_LINK_PARAM, 'd') LayerParams.nLeadInType = EgtGetInfo( s_nPartId, KEY_LEAD_IN_TYPE, 'i') LayerParams.dLeadInTangDist = EgtGetInfo( s_nPartId, KEY_LEAD_IN_TANG_DIST, 'd') LayerParams.dLeadInOrthoDist = EgtGetInfo( s_nPartId, KEY_LEAD_IN_ORTHO_DIST, 'd') LayerParams.nLeadOutType = EgtGetInfo( s_nPartId, KEY_LEAD_OUT_TYPE, 'i') LayerParams.dLeadOutTangDist = EgtGetInfo( s_nPartId, KEY_LEAD_OUT_TANG_DIST, 'd') LayerParams.dLeadOutOrthoDist = EgtGetInfo( s_nPartId, KEY_LEAD_OUT_ORTHO_DIST, 'd') LayerParams.dOffsetLP = EgtGetInfo( s_nPartId, KEY_OFFSET_LEAD_POINT, 'd') LayerParams.dSPOffs = EgtGetInfo( s_nPartId, KEY_SP_OFFSET_ON_SLICE, 'd') LayerParams.dCoastingLen = EgtGetInfo( s_nPartId, KEY_COASTING_LEN, 'd') LayerParams.dWipeLen = EgtGetInfo( s_nPartId, KEY_WIPE_LEN, 'd') LayerParams.dWipeDir = EgtGetInfo( s_nPartId, KEY_WIPE_DIR, 'd') or 0.0 LayerParams.vtSlicing = EgtGetInfo( s_nPartId, KEY_SLICING_DIR, 'v') LayerParams.dTDiam = EgtGetInfo( s_nPartId, KEY_TOOL_DIAM, 'd') return LayerParams end -------------------------------------------------------------------- local function ComputeZCorrection( LayerParams) -- direzione dell'estrusore local vtN = LayerParams.vtSlicing local dNxy = sqrt( vtN:getX() * vtN:getX() + vtN:getY() * vtN:getY()) local dNz = vtN:getZ() -- altezza necessaria per ugello s_dHMin = LayerParams.dTDiam / 2 * dNxy -- correzione per l'offset local dCorr1 = LayerParams.dOffs * dNxy -- correzione per il diametro dell'ugello local dCorr2 = ( LayerParams.dOffs - LayerParams.dStrand / 2 + LayerParams.dTDiam / 2) * dNxy - LayerParams.dLayHeight * dNz -- massimo tra le due return max( dCorr1, dCorr2) end ------------------------------------------------------------------- local function AddCurvesToToolPath( vEntIds, nTpathGrpId, nOrder, bInvert, vtSlicing, dLayHeight, dCorrZ) local vIds = {} -- vettore con gli id ordinati delle curve nel gruppo dei ToolPath local nStart = EgtIf( nOrder == PRINT_ORDER.EXT_INT, 1, #vEntIds) local nEnd = EgtIf( nOrder == PRINT_ORDER.EXT_INT, #vEntIds, 1) local nStep = EgtIf( nOrder == PRINT_ORDER.EXT_INT, 1, -1) local nIdx = 1 for i = nStart, nEnd, nStep do -- copio nel gruppo toolpath if i == nStart then vIds[nIdx] = EgtCopyGlob( vEntIds[i], nTpathGrpId, GDB_IN.LAST_SON) else vIds[nIdx] = EgtCopyGlob( vEntIds[i], vIds[nIdx-1], GDB_IN.AFTER) end -- correggo posizione in Z ( per essere sicuri di appoggiare sul piano) EgtMove( vIds[nIdx], dCorrZ * Z_AX(), GDB_RT.GLOB) -- mi sposto dell'altezza layer EgtMove( vIds[nIdx], dLayHeight * vtSlicing, GDB_RT.GLOB) if EgtCurveIsClosed( vIds[nIdx]) then EgtSetInfo( vIds[nIdx], KEY_CLOSED_CRV, 1) -- eventuale inversione if bInvert then EgtInvertCurve( vIds[nIdx]) EgtSetInfo( vIds[nIdx], KEY_INVERTED_CRV, 1) end end EgtModifyCurveExtrusion( vIds[nIdx], vtSlicing, GDB_RT.GLOB) EgtSetColor( vIds[nIdx], EgtStdColor('GRAY')) EgtSetStatus( vIds[nIdx], GDB_ST.ON) nIdx = nIdx + 1 end return vIds end ------------------------------------------------------------------- local function AddLink( vCrv, nTpathGrpId, nLinkType, dLinkParam, dSPOffs, dStrand, vtSlicing) if not vCrv or #vCrv == 0 then return end local k = 0 local bPrevClosed = EgtGetInfo( vCrv[1], KEY_CLOSED_CRV, 'b') or false for i = 2, #vCrv do -- il link ha senso solo su curve chiuse local bCurrClosed = EgtCurveIsClosed( vCrv[i]) if bCurrClosed and bPrevClosed then -- aggiorno k per calcolo dell'offset local sPrevName = EgtGetName( vCrv[i-1]) local sCurrName = EgtGetName( vCrv[i]) local nType = EgtGetInfo( vCrv[i], KEY_TYPE, 'i') if sPrevName ~= sCurrName or nType == TYPE.INFILL or nType == TYPE.AUX_SOLID then k = k + 1 end -- se nessun raccordo modifico solo lo start point della curva if nLinkType == LINK_TYPE.NONE then local dLen = k * dSPOffs if dSPOffs < 0 then dLen = EgtCurveLength( vCrv[i]) + dLen end local dPar = EgtCurveParamAtLength( vCrv[i], dLen) if dPar then EgtChangeClosedCurveStart( vCrv[i], dPar) end else -- altrimenti verifico se ha senso creare raccordo -- local dDist = dist( EgtEP( vCrv[i-1]), EgtSP( vCrv[i])) local dDist = EgtPointCurveDist( EgtEP( vCrv[i-1]), vCrv[i]) if dDist < dStrand + 10 * GEO.EPS_SMALL then local nLinkId -- modifico lo start point local dLen = EgtCurveLength( vCrv[i-1]) - EgtIf( k > 1, abs( dSPOffs), 0) EgtTrimCurveEndAtLen( vCrv[i-1], dLen) EgtChangeClosedCurveStartPoint( vCrv[i], EgtEP( vCrv[i-1])) -- aggiungo il raccordo EgtTrimCurveEndAtLen( vCrv[i-1], EgtCurveLength( vCrv[i-1]) - dLinkParam / 2) EgtTrimCurveStartAtLen( vCrv[i], dLinkParam / 2) if nLinkType == LINK_TYPE.LINEAR then nLinkId = EgtCurveCompoFromPoints( nTpathGrpId, {EgtEP( vCrv[i-1]), EgtSP( vCrv[i])}) elseif nLinkType == LINK_TYPE.BIARC then local frLoc = Frame3d( ORIG(), vtSlicing) local nGrpTmp = EgtGroup( nTpathGrpId, frLoc, GDB_RT.GLOB) local _, _, dAngIni = SphericalFromVector( EgtEV( vCrv[i-1], nGrpTmp)) local _, _, dAngFin = SphericalFromVector( EgtSV( vCrv[i], nGrpTmp)) nLinkId = EgtBiArc( nGrpTmp, EgtEP( vCrv[i-1], nGrpTmp), EgtSP( vCrv[i], nGrpTmp), dAngIni, dAngFin, 0.5) EgtRelocateGlob( nLinkId, nTpathGrpId, GDB_IN.LAST_SON) EgtErase( nGrpTmp) end if nLinkId then EgtRelocate( nLinkId, vCrv[i], GDB_IN.BEFORE) EgtModifyCurveExtrusion( nLinkId, vtSlicing, GDB_RT.GLOB) EgtSetInfo( nLinkId, KEY_TYPE, TYPE.LINK) EgtSetName( nLinkId, LINK_CRV) end end end end bPrevClosed = bCurrClosed end end -------------------------------------------------------------------- local function AddLeadIn( nCrvId, LayerParams, nGrpId) local ptE = EgtSP( nCrvId, GDB_ID.ROOT) local vtTang = EgtSV( nCrvId, GDB_ID.ROOT) local vtOrtho = Vector3d( vtTang) local dAng = 90 if ( LayerParams.bInvert and LayerParams.nOrder == PRINT_ORDER.INT_EXT) or ( not LayerParams.bInvert and LayerParams.nOrder == PRINT_ORDER.EXT_INT) then dAng = - 90 end vtOrtho:rotate( LayerParams.vtSlicing, dAng) local ptS = ptE - LayerParams.dLeadInTangDist * vtTang + LayerParams.dLeadInOrthoDist * vtOrtho -- verifico che non affondi nella tavola if ptS:getZ() < s_dHMin + GEO.EPS_SMALL then return end local nLeadInCrv if LayerParams.nLeadInType == LEAD_TYPE.LINEAR then nLeadInCrv = EgtCurveCompoFromPoints( nGrpId, {ptS, ptE}, GDB_RT.GLOB) elseif LayerParams.nLeadInType == LEAD_TYPE.ARC then nLeadInCrv = EgtArc2PV( nGrpId, ptE, ptS, -vtTang, GDB_RT.GLOB) EgtInvertCurve( nLeadInCrv) end if nLeadInCrv then EgtRelocate( nLeadInCrv, nCrvId, GDB_IN.BEFORE) EgtModifyCurveExtrusion( nLeadInCrv, LayerParams.vtSlicing, GDB_RT.GLOB) EgtSetInfo( nLeadInCrv, KEY_TYPE, TYPE.LINK) EgtSetName( nLeadInCrv, LEAD_IN_CRV) end end -------------------------------------------------------------------- local function AddLeadOut( nCrvId, LayerParams, nGrpId) local ptS = EgtEP( nCrvId, GDB_ID.ROOT) local vtTang = EgtEV( nCrvId, GDB_ID.ROOT) local vtOrtho = Vector3d( vtTang) local dAng = - 90 if ( LayerParams.bInvert and LayerParams.nOrder == PRINT_ORDER.INT_EXT) or ( not LayerParams.bInvert and LayerParams.nOrder == PRINT_ORDER.EXT_INT) then dAng = 90 end vtOrtho:rotate( LayerParams.vtSlicing, dAng) local ptE = ptS + LayerParams.dLeadOutTangDist * vtTang + LayerParams.dLeadOutOrthoDist * vtOrtho local nLeadOutCrv if LayerParams.nLeadOutType == LEAD_TYPE.LINEAR then nLeadOutCrv = EgtCurveCompoFromPoints( nGrpId, {ptS, ptE}, GDB_RT.GLOB) elseif LayerParams.nLeadOutType == LEAD_TYPE.ARC then nLeadOutCrv = EgtArc2PV( nGrpId, ptS, ptE, vtTang, GDB_RT.GLOB) end if nLeadOutCrv then EgtRelocate( nLeadOutCrv, nCrvId, GDB_IN.AFTER) EgtModifyCurveExtrusion( nLeadOutCrv, LayerParams.vtSlicing, GDB_RT.GLOB) EgtSetInfo( nLeadOutCrv, KEY_TYPE, TYPE.LINK) EgtSetName( nLeadOutCrv, LEAD_OUT_CRV) end return nLeadOutCrv end -------------------------------------------------------------------- local function AddRetraction( nCrvId, vtSlicing, dCoastingLen, dWipeLen, dWipeDir) -- recupero i parametri per retrazione local nType = EgtGetInfo( nCrvId, KEY_TYPE, 'i') local bClosed = EgtGetInfo( nCrvId, KEY_CLOSED_CRV, 'b') or false local bInverted = EgtGetInfo( nCrvId, KEY_INVERTED_CRV, 'b') or false -- curva ausiliaria per generare correttamente wipe local nCopyId = EgtCopyGlob( nCrvId, nCrvId, GDB_IN.AFTER) if not EgtCurveIsClosed( nCopyId) then local ptNewStart = EgtEP( nCrvId) local dPar = EgtCurveParamAtPoint( nCopyId, ptNewStart) local _, dParE = EgtCurveDomain( nCopyId) if abs( dPar - dParE) < GEO.EPS_SMALL then EgtCloseCurveCompo( nCopyId) EgtChangeClosedCurveStartPoint( nCopyId, ptNewStart) else -- caso con sovrapposizione EgtTrimCurveStartAtParam( nCopyId, dPar) end end local nCoastingId if dCoastingLen > GEO.EPS_SMALL then nCoastingId = EgtCopyGlob( nCrvId, nCrvId, GDB_IN.AFTER) local dPar = EgtCurveParamAtLength( nCoastingId, EgtCurveLength( nCoastingId) - dCoastingLen) if not dPar then EgtErase( nCoastingId) nCoastingId = nil else EgtTrimCurveStartAtParam( nCoastingId, dPar) -- aggiorno la curva originale if dPar > GEO.EPS_SMALL then EgtTrimCurveEndAtParam( nCrvId, dPar) else EgtErase( nCrvId) end EgtModifyCurveExtrusion( nCoastingId, vtSlicing, GDB_RT.GLOB) EgtSetName( nCoastingId, COASTING_CRV) EgtSetInfo( nCoastingId, KEY_TYPE, TYPE.COASTING) EgtSetColor( nCoastingId, EgtStdColor('ORANGE')) end end if dWipeLen > GEO.EPS_SMALL then local nWipeId if bClosed then -- se era chiusa ( quindi analogo alle shell) nWipeId = nCopyId nCopyId = nil EgtTrimCurveEndAtLen( nWipeId, dWipeLen) else -- se extra shell, infill a zigzag, spiral vase o rib che non termina sulla parete local vtDir = EgtEV( nCoastingId or nCrvId, GDB_ID.ROOT) local dAng = dWipeDir + s_nDefaultWipeAng -- verifico se necessario cambiare il segno all'angolo local bChangeSign = false if nType == TYPE.INFILL or nType == TYPE.AUX_SOLID then local vtS = EgtGetInfo( nCrvId, KEY_ZIG_ZAG_DIR, 'v') local bSameDir = AreSameVectorApprox( vtS, vtDir) bChangeSign = ( bInverted == bSameDir) else bChangeSign = bInverted end vtDir:rotate( vtSlicing, EgtIf( bChangeSign, - dAng, dAng)) local ptS = EgtEP( nCoastingId or nCrvId, GDB_ID.ROOT) local ptE = ptS + vtDir * dWipeLen -- verifico soddisfi altezza minima per dimensioni utensile local k = 1 while ptE:getZ() < s_dHMin + GEO.EPS_SMALL and k < 36 do vtDir:rotate( vtSlicing, EgtIf( bChangeSign, 10, -10)) ptE = ptS + vtDir * dWipeLen k = k + 1 end nWipeId = EgtCurveCompoFromPoints( EgtGetParent( nCoastingId or nCrvId), {ptS, ptE}, GDB_RT.GLOB) EgtModifyCurveExtrusion( nWipeId, vtSlicing, GDB_RT.GLOB) EgtRelocateGlob( nWipeId, nCoastingId or nCrvId, GDB_IN.AFTER) end EgtSetName( nWipeId, WIPE_CRV) EgtSetInfo( nWipeId, KEY_TYPE, TYPE.WIPE) EgtSetColor( nWipeId, EgtStdColor('AQUA')) end if nCopyId then EgtErase( nCopyId) end return nCoastingId end -------------------------------------------------------------------- local function AddRetractionOnLastCrv( nCrvId, nTpathGrpId, LayerParams, dCoastingLen, dWipeLen, dWipeDir) if LayerParams.nLeadOutType == LEAD_TYPE.NONE then AddRetraction( nCrvId, LayerParams.vtSlicing, dCoastingLen, dWipeLen, dWipeDir) else local nLeadOutId = EgtGetLastInGroup( nTpathGrpId) local dLen = EgtCurveLength( nLeadOutId) if dLen > dCoastingLen - 500 * GEO.EPS_SMALL then -- coinvolge solo la curva di lead out local dNewCoastingLen = EgtIf( abs( dCoastingLen - dLen) < 500 * GEO.EPS_SMALL, dLen, dCoastingLen) -- verifico se interamente coinvolta AddRetraction( nLeadOutId, LayerParams.vtSlicing, dNewCoastingLen, dWipeLen, dWipeDir) else -- coinvolge parte dell'ultima shell crv local dNewCoastingLen = dCoastingLen - dLen local nCoastingId = AddRetraction( nCrvId, LayerParams.vtSlicing, dNewCoastingLen, 0.0, dWipeDir) EgtAddCurveCompoCurve( nCoastingId, nLeadOutId) EgtSetInfo( nCoastingId, KEY_CLOSED_CRV, 0) -- wipe AddRetraction( nCoastingId, LayerParams.vtSlicing, 0, dWipeLen, dWipeDir) end end end --------------------------------------------------------------------- local function CalcShellsToolPath( vEntIds, nTpathGrpId, LayerParams, dCorrZ) if not vEntIds then return end -- aggiungo le curve nel toolpath local vIds = AddCurvesToToolPath( vEntIds, nTpathGrpId, LayerParams.nOrder, LayerParams.bInvert, LayerParams.vtSlicing, LayerParams.dLayHeight, dCorrZ) local nFirstCopy = EgtCopyGlob( vIds[1], nTpathGrpId) -- aggiungo gli opportuni raccordi AddLink( vIds, nTpathGrpId, LayerParams.nLinkType, LayerParams.dLinkParam, LayerParams.dSPOffs, LayerParams.dStrand, LayerParams.vtSlicing) -- offset lead point curva iniziale if LayerParams.dOffsetLP > - GEO.EPS_SMALL then EgtTrimCurveStartAtLen( vIds[1], LayerParams.dOffsetLP) EgtErase( nFirstCopy) else -- devi aggiungere un tratto di curva EgtTrimCurveStartAtLen( nFirstCopy, EgtCurveLength( nFirstCopy) - abs( LayerParams.dOffsetLP)) EgtAddCurveCompoCurve( vIds[1], nFirstCopy, true, false) end -- aggiungo leadin/leadout if LayerParams.nLeadInType ~= LEAD_TYPE.NONE then AddLeadIn( vIds[1], LayerParams, nTpathGrpId) end if LayerParams.nLeadOutType ~= LEAD_TYPE.NONE then EgtTrimCurveEndAtLen( vIds[#vIds], EgtCurveLength( vIds[#vIds]) - LayerParams.dOffsetLP) AddLeadOut( vIds[#vIds], LayerParams, nTpathGrpId) end -- aggiungo coasting/wipe for i = 1, #vIds - 1 do local nNextId = EgtGetNext( vIds[i]) if EgtGetInfo( nNextId, KEY_TYPE, 'i') ~= TYPE.LINK then AddRetraction( vIds[i], LayerParams.vtSlicing, LayerParams.dCoastingLen, LayerParams.dWipeLen, LayerParams.dWipeDir) end end -- sull'ultima curva gestione speciale per eventuale lead out AddRetractionOnLastCrv( vIds[#vIds], nTpathGrpId, LayerParams, LayerParams.dCoastingLen, LayerParams.dWipeLen, LayerParams.dWipeDir) end --------------------------------------------------------------------- local function CalcExtraShellToolPath( vEntIds, nTpathGrpId, LayerParams, dCorrZ) if not vEntIds then return end -- aggiungo le curve nel toolpath local vIds = AddCurvesToToolPath( vEntIds, nTpathGrpId, PRINT_ORDER.EXT_INT, false, LayerParams.vtSlicing, LayerParams.dLayHeight, dCorrZ) -- aggiungo gli opportuni raccordi local sPrevName = EgtGetName( vIds[1]) for i = 2, #vIds do local sCurrName = EgtGetName( vIds[i]) -- se hanno lo stesso nome vanno collegate if sCurrName == sPrevName then local ptS = EgtEP( vIds[i-1]) local ptE = EgtSP( vIds[i]) local nLinkId = EgtCurveCompoFromPoints( nTpathGrpId, {ptS, ptE}) if nLinkId then EgtRelocateGlob( nLinkId, vIds[i], GDB_IN.BEFORE) EgtModifyCurveExtrusion( nLinkId, LayerParams.vtSlicing, GDB_RT.GLOB) EgtSetInfo( nLinkId, KEY_TYPE, TYPE.LINK) EgtSetName( nLinkId, LINK_CRV) end end sPrevName = sCurrName end -- aggiungo coasting/wipe for i = 1, #vIds do -- verifico non sia collegato al successivo tramite link local nNextId = EgtGetNext( vIds[i]) if not nNextId or EgtGetInfo( nNextId, KEY_TYPE, 'i') ~= TYPE.LINK then -- recupero i parametri local dCoastingLen, dWipeLen, dWipeDir local bClosed = EgtGetInfo( vIds[i], KEY_CLOSED_CRV, 'b') or false if not bClosed then local bInverted = EgtGetInfo( vIds[i], KEY_INVERTED_CRV, 'b') or false local vCoastLen = EgtGetInfo( vIds[i], KEY_EXTRA_SHELL_COASTING, 'vd') local vWipeLen = EgtGetInfo( vIds[i], KEY_EXTRA_SHELL_WIPE, 'vd') local vWipeDir = EgtGetInfo( vIds[i], KEY_EXTRA_SHELL_WIPE_DIR, 'vd') -- se curva è stata invertita devo prendere le info legate a quello che era il suo punto di inizio, altrimenti prendo le info legate al punto finale dCoastingLen = EgtIf( bInverted, vCoastLen[1], vCoastLen[2]) dWipeLen = EgtIf( bInverted, vWipeLen[1], vWipeLen[2]) dWipeDir = EgtIf( bInverted, vWipeDir[1], vWipeDir[2]) else -- se chiusa considero i parametri delle shell complete dCoastingLen = LayerParams.dCoastingLen dWipeLen = LayerParams.dWipeLen dWipeDir = LayerParams.dWipeDir end AddRetraction( vIds[i], LayerParams.vtSlicing, dCoastingLen, dWipeLen, dWipeDir) end end end --------------------------------------------------------------------- local function CalcInfillToolPath( vEntIds, nTpathGrpId, LayerParams, dCorrZ) if not vEntIds then return end -- aggiungo le curve nel toolpath local vIds = AddCurvesToToolPath( vEntIds, nTpathGrpId, LayerParams.nOrder, LayerParams.bInvert, LayerParams.vtSlicing, LayerParams.dLayHeight, dCorrZ) -- aggiungo eventuali link AddLink( vIds, nTpathGrpId, LayerParams.nLinkType, LayerParams.dLinkParam, LayerParams.dSPOffs, LayerParams.dStrand, LayerParams.vtSlicing) -- aggiungo coasting/wipe for i = 1, #vIds do local nNextId = EgtGetNext( vIds[i]) if not nNextId or EgtGetInfo( nNextId, KEY_TYPE, 'i') ~= TYPE.LINK then AddRetraction( vIds[i], LayerParams.vtSlicing, LayerParams.dCoastingLen, LayerParams.dWipeLen, LayerParams.dWipeDir) end end end --------------------------------------------------------------------- local function CalcAuxSolidsToolPath( nAuxSolidsGrp, nAuxSolidsPathGrp, nTpathGrpId, LayerParams, dCorrZ) if not nAuxSolidsGrp or not nAuxSolidsPathGrp then return end -- recupero le curve relative al primo solido ausiliario local sPrevName = AUX_SOLID_CRV local nSolidId = EgtGetFirstNameInGroup( nAuxSolidsGrp, AUX_SOLIDS_CRV .. '*') while nSolidId do local sName = EgtGetName( nSolidId) if sName ~= sPrevName then -- recupero tutti i percorsi relativi a quel solido local vEntIds = EgtGetNameInGroup( nAuxSolidsPathGrp, sName .. '*') if vEntIds then -- recupero i parametri relativi al solido local nOrder = EgtGetInfo( nSolidId, KEY_AUX_SOLIDS_PRINT_ORDER, 'i') local nLinkType = EgtGetInfo( nSolidId, KEY_AUX_SOLIDS_LINK_TYPE, 'i') local dLinkParam = EgtGetInfo( nSolidId, KEY_AUX_SOLIDS_LINK_PARAM, 'd') local dSPOffset = EgtGetInfo( nSolidId, KEY_AUX_SOLIDS_SP_OFFSET, 'd') local dCoastingLen = EgtGetInfo( nSolidId, KEY_AUX_SOLIDS_COASTING_LEN, 'd') local dWipeLen = EgtGetInfo( nSolidId, KEY_AUX_SOLIDS_WIPE_LEN, 'd') local dWipeDir = EgtGetInfo( nSolidId, KEY_AUX_SOLIDS_WIPE_DIR, 'd') -- copio i percorsi nel gruppo toolpath local vIds = AddCurvesToToolPath( vEntIds, nTpathGrpId, nOrder, LayerParams.bInvert, LayerParams.vtSlicing, LayerParams.dLayHeight, dCorrZ) -- aggiungo link AddLink( vIds, nTpathGrpId, nLinkType, dLinkParam, dSPOffset, LayerParams.dStrand, LayerParams.vtSlicing) -- coasting e wipe for i = 1, #vIds do local nNextId = EgtGetNext( vIds[i]) if not nNextId or EgtGetInfo( nNextId, KEY_TYPE, 'i') ~= TYPE.LINK then AddRetraction( vIds[i], LayerParams.vtSlicing, dCoastingLen, dWipeLen, dWipeDir) end end end end sPrevName = sName nSolidId = EgtGetNextName( nSolidId, AUX_SOLIDS_CRV .. '*') end end ------------------------------------------------------------------- --------------------------- RIBS ----------------------------------- -------------------------------------------------------------------- local function VerifyRibsLink( nLinkId, nCurr, nNext, dStrand, nGrpTmp) local nGrp = EgtGetParent( nCurr) -- verifico se il link interseca le due curve nell'altro estremo local ptS = EgtSP( nCurr) local ptE = EgtEP( nNext) local dParS = EgtCurveParamAtPoint( nLinkId, ptS) local dParE = EgtCurveParamAtPoint( nLinkId, ptE) if dParS or dParE then return false end -- verifico se si trova nella regione ammissibile local nSurfId = EgtGetInfo( nCurr, KEY_ASSOCIATED_SURF, 'i') local nRes = EgtCurveWithRegionClassify( nLinkId, nSurfId) local nType1 = EgtGetInfo( nCurr, KEY_RIBS_TYPE, 'i') local nType2 = EgtGetInfo( nNext, KEY_RIBS_TYPE, 'i') if ( nType1 == RIB_TYPE.INTERNAL or nType1 == RIB_TYPE.SUPPORT) and ( nType2 == RIB_TYPE.INTERNAL or nType2 == RIB_TYPE.SUPPORT) then if nRes == GDB_CRC.OUT or nRes == GDB_CRC.INTERS then return false end elseif nType1 == RIB_TYPE.EXTERNAL and nType2 == RIB_TYPE.EXTERNAL then if nRes == GDB_CRC.IN or nRes == GDB_CRC.INTERS then return false end end -- verifico se il link interseca una delle altre costolature local vRibsIds = EgtGetNameInGroup( nGrp, RIBS_CRV .. '*') local nLinkSrf = EgtSurfFrFatCurve( nGrpTmp, nLinkId, 0.5 * dStrand, false) or GDB_ID.NULL for i = 1, #vRibsIds do if vRibsIds[i] ~= nCurr and vRibsIds[i] ~= nNext then local nRes = EgtCurveWithRegionClassify( vRibsIds[i], nLinkSrf) if nRes == GDB_CRC.INTERS then return false end end end return true end -------------------------------------------------------------------- local function CalcRibsLink( nCurr, nNext, nLoopGrp, dStrand, bForceLink, vtSlicing, nGrpTmp) local ptS = EgtEP( nCurr) local ptE = EgtSP( nNext) local nCrvId = EgtGetFirstInGroup( nLoopGrp) -- recupero la curva di offset su cui calcolare link while nCrvId do local dParS = EgtCurveParamAtPoint( nCrvId, ptS) local dParE = EgtCurveParamAtPoint( nCrvId, ptE) if dParS and dParE then local bInvert = false local bClosed = EgtCurveIsClosed( nCrvId) if bClosed then -- se la curva è chiusa verifico i due percorsi possibili dParS->dParE e dParE->dParS local nCopyId1 = EgtCopyGlob( nCrvId, nCurr, GDB_IN.AFTER) local nCopyId2 = EgtCopyGlob( nCrvId, nCurr, GDB_IN.AFTER) EgtTrimCurveStartEndAtParam( nCopyId1, dParS, dParE) EgtTrimCurveStartEndAtParam( nCopyId2, dParE, dParS) EgtInvertCurve( nCopyId2) local dLen1 = EgtCurveLength( nCopyId1) local dLen2 = EgtCurveLength( nCopyId2) if dLen1 > dLen2 then bInvert = true dParS, dParE = dParE, dParS end EgtErase( nCopyId1) EgtErase( nCopyId2) end local nCopyId = EgtCopyGlob( nCrvId, nLoopGrp) local nLinkId = EgtCopyGlob( nCrvId, nCurr, GDB_IN.AFTER) if dParS > dParE and not bClosed then bInvert = true dParS, dParE = dParE, dParS end EgtTrimCurveStartEndAtParam( nLinkId, dParS, dParE) EgtSetInfo( nLinkId, KEY_TYPE, TYPE.RIB) EgtSetName( nLinkId, LINK_CRV) EgtModifyCurveExtrusion( nLinkId, vtSlicing, GDB_RT.GLOB) if bInvert then EgtInvertCurve( nLinkId) end -- verifico se è valido local bValid = VerifyRibsLink( nLinkId, nCurr, nNext, dStrand, nGrpTmp) if not bValid then EgtErase( nLinkId) EgtErase( nCopyId) return end if bClosed then EgtTrimCurveStartEndAtParam( nCrvId, dParE, dParS) EgtErase( nCopyId) else EgtTrimCurveEndAtParam( nCrvId, dParS) EgtTrimCurveStartAtParam( nCopyId, dParE) end return nLinkId end nCrvId = EgtGetNext( nCrvId) end -- se non ho trovato un collegamento sul bordo, creo una linea tra ptS e ptE if bForceLink then local nLinkId = EgtCurveCompoFromPoints( EgtGetParent( nCurr), {ptS, ptE}) local bValid = VerifyRibsLink( nLinkId, nCurr, nNext, dStrand, nGrpTmp) if bValid then EgtSetInfo( nLinkId, KEY_TYPE, TYPE.RIB) EgtSetName( nLinkId, LINK_CRV) EgtModifyCurveExtrusion( nLinkId, vtSlicing, GDB_RT.GLOB) EgtRelocateGlob( nLinkId, nCurr, GDB_IN.AFTER) else EgtErase( nLinkId) end end end -------------------------------------------------------------------- local function VerifyRibsLead( nId, nRibId, dStrand, bInVsOut, nGrpTmp) local nGrp = EgtGetParent( nRibId) local nLeadId = EgtCopyGlob( nId, nGrp) if bInVsOut then EgtExtendCurveStartByLen( nLeadId, dStrand * 0.5) else EgtExtendCurveEndByLen( nLeadId, dStrand * 0.5) end -- verifico che intersechi solo l'estrmo corretto local pt = EgtIf( bInVsOut, EgtEP( nRibId), EgtSP( nRibId)) local dPar = EgtCurveParamAtPoint( nLeadId, pt) if dPar then EgtErase( nLeadId) return false end local pt1 = EgtIf( bInVsOut, EgtSP( nLeadId), EgtEP( nLeadId)) local pt2 = EgtIf( bInVsOut, EgtEP( nRibId), EgtSP( nRibId)) if dist( pt1, pt2) < dStrand + GEO.EPS_SMALL then EgtErase( nLeadId) return false end local _, dParE = EgtCurveDomain( nLeadId) local vtDir = EgtMV( nRibId) local dParCrv = 1 local dTol = 10 * GEO.EPS_SMALL for dParCrv = 1, dParE do local vtS = EgtUV( nLeadId, dParCrv - 1, 1) local vtE = EgtUV( nLeadId, dParCrv, -1) -- se tratto lineare allineato con la direzione del setto verifico sia sufficientemente lontano if AreSameVectorApprox( vtS, vtE) and ( (vtS - vtDir):sqlen() < dTol * dTol or (vtS + vtDir):sqlen() < dTol * dTol) then local dDist = EgtPointCurveDist( EgtUP( nLeadId, dParCrv - 0.5), nRibId) if dDist < dStrand + GEO.EPS_SMALL then EgtErase( nLeadId) return false end end end -- verifico non intersechi altri setti local vRibsIds = EgtGetNameInGroup( EgtGetParent( nRibId), RIBS_CRV .. '*') local nLeadLoc = EgtCopyGlob( nLeadId, nGrpTmp) for i = 1, #vRibsIds do if vRibsIds[i] ~= nRibId then local nCrvLoc = EgtCopyGlob( vRibsIds[i], nGrpTmp) local ptInt = EgtIP( nLeadLoc, nCrvLoc, ORIG()) if ptInt then EgtErase( nLeadId) return false end end end -- se lead out verifico non si sovrapponga al lead in if not bInVsOut then -- recupero il lead in local nPrev = EgtGetPrev( nRibId) if nPrev and EgtGetName( nPrev) == LEAD_IN_CRV then local nSrfTot = EgtSurfFrFatCurve( EgtGetParent( nLeadId), nPrev, 0.5 * dStrand, false) if nSrfTot then local nRes = EgtCurveWithRegionClassify( nLeadId, nSrfTot) if nRes == GDB_CRC.IN or nRes == GDB_CRC.INTERS then EgtErase( nSrfTot) EgtErase( nLeadId) return false end else nSrfTot = EgtSurfFrFatCurve( EgtGetParent( nLeadId), nLeadId, 0.5 * dStrand, false) if nSrfTot then local nRes = EgtCurveWithRegionClassify( nPrev, nSrfTot) if nRes == GDB_CRC.IN or nRes == GDB_CRC.INTERS then EgtErase( nSrfTot) EgtErase( nLeadId) return false end end end EgtErase( nSrfTot) end end EgtErase( nLeadId) return true end ------------------------------------------------------------------- local function FindCorrectRibsLead( dPar, nCrv, nCrvOffs, bLeadInvert, dLeadLen, dStrand, bInVsOut, nGrpTmp) local nLeadId local bInvert = bLeadInvert -- valore di default è quello settato nel file dei parametri local _, dParEnd = EgtCurveDomain( nCrvOffs) local bClosed = EgtCurveIsClosed( nCrvOffs) local bOnlyOneCurve = not bClosed and ( dPar < GEO.EPS_SMALL or abs( dPar - dParEnd) < GEO.EPS_SMALL) local nMainCrv = nCrvOffs -- curva preferita da utilizzare per lead in local nOtherCrv -- altra possibile curva da ultizzare nel caso nMainCrv non sia adatta if bClosed then EgtChangeClosedCurveStart( nCrvOffs, dPar) nOtherCrv = nCrvOffs elseif not bOnlyOneCurve then nOtherCrv = EgtSplitCurveAtParam( nCrvOffs, dPar) end -- calcolo del parametro bInvert if bOnlyOneCurve then -- invert dipende dall'estremo da cui parte il setto bInvert = abs( dPar - dParEnd) < GEO.EPS_SMALL elseif not bClosed then -- invert può essere legato anche alla lunghezza dei tratti possibili local dLen1 = EgtCurveLength( nMainCrv) local dLen2 = EgtCurveLength( nOtherCrv) if dLen1 > dLeadLen - GEO.EPS_SMALL and dLen2 < dLeadLen - GEO.EPS_SMALL then bInvert = true elseif dLen1 < dLeadLen - GEO.EPS_SMALL and dLen2 > dLeadLen - GEO.EPS_SMALL then bInvert = false end if not bInvert then nMainCrv, nOtherCrv = nOtherCrv, nMainCrv end end -- primo tentativo con la curva favorita nLeadId = EgtCopyGlob( nMainCrv, nCrv, EgtIf( bInVsOut, GDB_IN.BEFORE, GDB_IN.AFTER)) if bInvert then EgtInvertCurve( nLeadId) end EgtTrimCurveEndAtLen( nLeadId, dLeadLen) if bInVsOut then EgtInvertCurve( nLeadId) end if VerifyRibsLead( nLeadId, nCrv, dStrand, bInVsOut, nGrpTmp) then -- se valido aggiorno le curve per prossimi lead in/out if bInvert then EgtTrimCurveEndAtLen( nMainCrv, EgtCurveLength( nCrvOffs) - dLeadLen) else EgtTrimCurveStartAtLen( nMainCrv, dLeadLen) end elseif not nOtherCrv then -- se non è valido e non ho altre curve possibili cancello EgtErase( nLeadId) return nil else -- se non è valido ma ho altra curva possibile, tento con quella EgtErase( nLeadId) nLeadId = EgtCopyGlob( nOtherCrv, nCrv, EgtIf( bInVsOut, GDB_IN.BEFORE, GDB_IN.AFTER)) if not bInvert then EgtInvertCurve( nLeadId) end EgtTrimCurveEndAtLen( nLeadId, dLeadLen) if bInVsOut then EgtInvertCurve( nLeadId) end if VerifyRibsLead( nLeadId, nCrv, dStrand, bInVsOut, nGrpTmp) then if bInvert then EgtTrimCurveStartAtLen( nOtherCrv, dLeadLen) else EgtTrimCurveEndAtLen( nOtherCrv, EgtCurveLength( nCrvOffs) - dLeadLen) end else EgtErase( nLeadId) bInvert = not bInvert return nil end -- aggiorno parametro bInvert bInvert = not bInvert end return nLeadId, bInvert end -------------------------------------------------------------------- local function AddRibsLeadIn( nCrv, nLoopsGrp, dStrand, vtSlicing, nGrpTmp) local dLILen = EgtGetInfo( nCrv, KEY_RIBS_LEAD_IN_LEN, 'd') local bLIInvert = EgtGetInfo( nCrv, KEY_RIBS_LEAD_IN_INVERT, 'b') if dLILen < GEO.EPS_SMALL then return end -- recupero la curva di offset su cui calcolare leadin local ptS = EgtSP( nCrv) local nCrvOffs = EgtGetFirstInGroup( nLoopsGrp) while nCrvOffs do local dParS = EgtCurveParamAtPoint( nCrvOffs, ptS) if dParS then local nLeadIn = FindCorrectRibsLead( dParS, nCrv, nCrvOffs, bLIInvert, dLILen, dStrand, true, nGrpTmp) -- se lead in possibile if nLeadIn then EgtModifyCurveExtrusion( nLeadIn, vtSlicing, GDB_RT.GLOB) EgtSetInfo( nLeadIn, KEY_TYPE, TYPE.RIB) EgtSetName( nLeadIn, LEAD_IN_CRV) end return end nCrvOffs = EgtGetNext( nCrvOffs) end end -------------------------------------------------------------------- local function AddRibsLeadOut( nCrv, nTPathGrp, nLoopsGrp, vtSlicing, dStrand, nGrpTmp) local dRibsLOLen = EgtGetInfo( nCrv, KEY_RIBS_LEAD_OUT_LEN, 'd') local dRibsLOCoasting = EgtGetInfo( nCrv, KEY_RIBS_LEAD_OUT_COASTING, 'd') local dRibsLOWipe = EgtGetInfo( nCrv, KEY_RIBS_LEAD_OUT_WIPE, 'd') local dRibsLOWipeAng = EgtGetInfo( nCrv, KEY_RIBS_LEAD_OUT_WIPE_DIR, 'd') local bRibsLOInvert = EgtGetInfo( nCrv, KEY_RIBS_LEAD_OUT_INVERT, 'b') if abs( dRibsLOLen) < GEO.EPS_SMALL and abs( dRibsLOCoasting) < GEO.EPS_SMALL and abs( dRibsLOWipe) < GEO.EPS_SMALL then return end local ptE = EgtEP( nCrv, GDB_ID.ROOT) local vtE = EgtEV( nCrv, GDB_ID.ROOT) -- recupero la curva di offset su cui calcolare lead out local nCrvOffs = EgtGetFirstInGroup( nLoopsGrp) while nCrvOffs do local dParE = EgtCurveParamAtPoint( nCrvOffs, ptE, GEO.EPS_SMALL, GDB_RT.GLOB) if dParE then local nCrvLO local nCoasting local nWipe -- trovo curva opportuna per lead out local nCrvRef, bInvert = FindCorrectRibsLead( dParE, nCrv, nCrvOffs, bRibsLOInvert, dRibsLOLen + dRibsLOCoasting, dStrand, false, nGrpTmp) if nCrvRef then -- verifico se la curva ha lunghezza sufficiente local dLen = EgtCurveLength( nCrvRef) local bSkip = ( dLen - dRibsLOLen - dRibsLOCoasting < - GEO.EPS_SMALL) -- primo tratto ( segue offset con flusso aperto) if dRibsLOLen > GEO.EPS_SMALL and not bSkip then nCrvLO = EgtCopyGlob( nCrvRef, nCrv, GDB_IN.AFTER) EgtTrimCurveEndAtLen( nCrvLO, dRibsLOLen) EgtModifyCurveExtrusion( nCrvLO, vtSlicing, GDB_RT.GLOB) EgtSetInfo( nCrvLO, KEY_TYPE, TYPE.RIB) EgtSetName( nCrvLO, LEAD_OUT_CRV) -- aggiorno ptE e vtE ptE = EgtEP( nCrvLO, GDB_ID.ROOT) vtE = EgtEV( nCrvLO, GDB_ID.ROOT) end -- secondo tratto ( segue offset con flusso chiuso) if dRibsLOCoasting > GEO.EPS_SMALL then nCoasting = EgtCopyGlob( nCrvRef, nCrvLO or nCrv, GDB_IN.AFTER) EgtTrimCurveStartAtLen( nCoasting, dRibsLOLen) EgtTrimCurveEndAtLen( nCoasting, dRibsLOCoasting) EgtModifyCurveExtrusion( nCoasting, vtSlicing, GDB_RT.GLOB) EgtSetName( nCoasting, COASTING_CRV) EgtSetInfo( nCoasting, KEY_TYPE, TYPE.COASTING) EgtSetColor( nCoasting, EgtStdColor('ORANGE')) -- aggiorno ptE e vtE ptE = EgtEP( nCoasting, GDB_ID.ROOT) vtE = EgtEV( nCoasting, GDB_ID.ROOT) end EgtErase( nCrvRef) -- terzo tratto ( diretto verso esterno con ugello chiuso) if dRibsLOWipe > GEO.EPS_SMALL then local dAng = dRibsLOWipeAng + s_nDefaultWipeAng local nType = EgtGetInfo( nCrv, KEY_RIBS_TYPE, 'i') if nType == RIB_TYPE.EXTERNAL then dAng = - dAng end vtE:rotate( vtSlicing, EgtIf( bInvert, - dAng, dAng)) local ptFinal = ptE + vtE * dRibsLOWipe -- verifico soddisfi altezza minima per dimensioni utensile local k = 1 while ptFinal:getZ() < s_dHMin + GEO.EPS_SMALL and k < 36 do vtE:rotate( vtSlicing, EgtIf( bInvert, - 10, 10)) ptFinal = ptE + vtE * dRibsLOWipe k = k + 1 end nWipe = EgtCurveCompoFromPoints( nTPathGrp, { ptE, ptFinal}, GDB_RT.GLOB) EgtModifyCurveExtrusion( nWipe, vtSlicing, GDB_RT.GLOB) EgtRelocateGlob( nWipe, nCoasting or nCrvLO or nCrv, GDB_IN.AFTER) EgtSetName( nWipe, WIPE_CRV) EgtSetInfo( nWipe, KEY_TYPE, TYPE.WIPE) EgtSetColor( nWipe, EgtStdColor('AQUA')) end else -- aggiungo coasting e wipe come sulle shell normali AddRetraction( nCrv, vtSlicing, dRibsLOCoasting, dRibsLOWipe, dRibsLOWipeAng) end return end nCrvOffs = EgtGetNext( nCrvOffs) end -- se non ho trovato curva sul bordo su cui fare il lead out aggiungo coasting e wipe come sulle shell normali AddRetraction( nCrv, vtSlicing, dRibsLOCoasting, dRibsLOWipe, dRibsLOWipeAng) end --------------------------------------------------------------------- local function CalcRibsToolPath( nRibsGrp, nTpathGrpId, LayerParams, dCorrZ) if not nRibsGrp then return end -- gruppo temporaneo con sistema di riferimento locale per conti local frLoc = Frame3d( ORIG(), LayerParams.vtSlicing) local nGrpTmp = EgtGroup( nRibsGrp, frLoc, GDB_RT.GLOB) -- aggiungo le costolature nel toolpath local vEntIds = EgtGetNameInGroup( nRibsGrp, RIBS_CRV .. '*') for i = 1, #vEntIds do -- copio entità nel gruppo toolpath local nNewEntId = EgtCopyGlob( vEntIds[i], nTpathGrpId, GDB_IN.LAST_SON) -- correggo posizione in Z ( per essere sicuri di appoggiare sul piano) EgtMove( nNewEntId, dCorrZ * Z_AX(), GDB_RT.GLOB) -- mi sposto dell'altezza layer EgtMove( nNewEntId, LayerParams.dLayHeight * LayerParams.vtSlicing, GDB_RT.GLOB) EgtModifyCurveExtrusion( nNewEntId, LayerParams.vtSlicing, GDB_RT.GLOB) EgtSetColor( nNewEntId, EgtStdColor('MAROON')) end -- estraggo i contorni di tutte le superfici di offset local nLoopGrp = EgtGroup( nRibsGrp) local nSrfId = EgtGetFirstNameInGroup( nRibsGrp, TOT_SHELL_TRIM_SURF) while nSrfId do EgtMove( nSrfId, dCorrZ * Z_AX(), GDB_RT.GLOB) -- mi sposto dell'altezza layer EgtMove( nSrfId, LayerParams.dLayHeight * LayerParams.vtSlicing, GDB_RT.GLOB) local nChunksNbr = EgtSurfFrChunkCount( nSrfId) for i = 0, nChunksNbr do local nRes, nCnt = EgtExtractSurfFrChunkLoops( nSrfId, i, nLoopGrp) end nSrfId = EgtGetNextName( nSrfId, TOT_SHELL_TRIM_SURF) end -- recupero i gruppi delle costolature local tabRibs = {} local nFirst = EgtGetFirstNameInGroup( nTpathGrpId, RIBS_CRV .. '*') while nFirst do local sName = EgtGetName( nFirst) local vIds = EgtGetNameInGroup( nTpathGrpId, sName) table.insert( tabRibs, vIds) nFirst = EgtGetNextName( vIds[#vIds], RIBS_CRV .. '*') end local bInters = EgtGetInfo( nRibsGrp, KEY_RIBS_INTERS, 'b') or false local bAllTwoStrands = EgtGetInfo( nRibsGrp, KEY_RIBS_TWO_STRANDS, 'b') or false local bSpecialCase = bInters and bAllTwoStrands local bSwap = false local bInvert = false -- curve già orientate in CalcPaths if not bSpecialCase then for i = 1, #tabRibs do local nInfo = EgtGetInfo( tabRibs[i][1], KEY_SPLIT_RIB, 'i') local nShellsNbr = EgtGetInfo( tabRibs[i][1], KEY_RIBS_SHELLS_NBR, 'i') if i > 1 then -- verifico se link local bPrevLink = EgtGetInfo( tabRibs[i-1][1], KEY_RIBS_LINK, 'b') local bCurrLink = EgtGetInfo( tabRibs[i][1], KEY_RIBS_LINK, 'b') if bPrevLink and bCurrLink then nPrevType = EgtGetInfo( tabRibs[i-1][1], KEY_RIBS_TYPE, 'i') nCurrType = EgtGetInfo( tabRibs[i][1], KEY_RIBS_TYPE, 'i') -- se cambio tipologia di setto, l'orientamento della curva è già corretto if nPrevType ~= nCurrType then bInvert = false elseif not nInfo then -- aggiorno bInvert per il gruppo di costolature corrente in modo da essere coerente con il collegamento local nPrevShellsNbr = EgtGetInfo( tabRibs[i-1][1], KEY_RIBS_SHELLS_NBR, 'i') if nPrevShellsNbr % 2 == 1 then bInvert = not bInvert end end else bInvert = false end end if nShellsNbr == 1 and nInfo and bInvert then -- se inverto direzione di costolature divise allora devo invertirne anche l'ordine di realizzazione bSwap = true EgtRelocateGlob( tabRibs[i][1], tabRibs[i-1][1], GDB_IN.BEFORE) end -- oriento tutte le passate relative ad una stessa costolatura if not EgtCurveIsClosed( tabRibs[i][1]) then for j = 1, #tabRibs[i] do if ( bInvert and j % 2 == 1) or ( not bInvert and j % 2 == 0) then EgtInvertCurve( tabRibs[i][j]) end end end end end -- Link -- se modifiche nell'ordine ricalcolo i gruppi di costolature if bSwap then tabRibs = {} nFirst = EgtGetFirstNameInGroup( nTpathGrpId, RIBS_CRV .. '*') while nFirst do local sName = EgtGetName( nFirst) local vIds = EgtGetNameInGroup( nTpathGrpId, sName) table.insert( tabRibs, vIds) nFirst = EgtGetNextName( vIds[#vIds], RIBS_CRV .. '*') end end -- collego le passate di una stessa costolatura for i = 1, #tabRibs do if EgtCurveIsClosed( tabRibs[i][1]) then -- AddLink( tabRibs[i], nTpathGrpId, LayerParams.nLinkType, LayerParams.dLinkParam, LayerParams.dSPOffs, LayerParams.dStrand, LayerParams.vtSlicing) else for j = 1, #tabRibs[i] - 1 do CalcRibsLink( tabRibs[i][j], tabRibs[i][j + 1], nLoopGrp, LayerParams.dStrand, true, LayerParams.vtSlicing, nGrpTmp) if not bSpecialCase then -- creo link fittizio per eliminare tratto corrispondente sulla curva di offset local nFakeLink = CalcRibsLink( tabRibs[i][j + 1], tabRibs[i][j], nLoopGrp, LayerParams.dStrand, false, LayerParams.vtSlicing, nGrpTmp) EgtErase( nFakeLink) end end if bSpecialCase then local nFakeLink = CalcRibsLink( tabRibs[i][#tabRibs[i]], tabRibs[i][1], nLoopGrp, LayerParams.dStrand, false, LayerParams.vtSlicing, nGrpTmp) EgtErase( nFakeLink) end end end -- se necessario collego le diverse costolature for i = 1, #tabRibs - 1 do local bLink1 = EgtGetInfo( tabRibs[i][1], KEY_RIBS_LINK, 'b') local bLink2 = EgtGetInfo( tabRibs[i + 1][1], KEY_RIBS_LINK, 'b') local nType1 = EgtGetInfo( tabRibs[i][1], KEY_RIBS_TYPE, 'i') local nType2 = EgtGetInfo( tabRibs[i + 1][1], KEY_RIBS_TYPE, 'i') if bLink1 and bLink2 and nType1 == nType2 then local nCnt = #tabRibs[i] CalcRibsLink( tabRibs[i][nCnt], tabRibs[i + 1][1], nLoopGrp, LayerParams.dStrand, false, LayerParams.vtSlicing, nGrpTmp) end end -- leadin/leadout local nCrvRib = EgtGetFirstNameInGroup( nTpathGrpId, RIBS_CRV .. '*') while nCrvRib do -- verifico se necessario lead in local nPrev = EgtGetPrev( nCrvRib) if not nPrev or EgtGetName( nPrev) ~= LINK_CRV then AddRibsLeadIn( nCrvRib, nLoopGrp, LayerParams.dStrand, LayerParams.vtSlicing, nGrpTmp) end -- verifico se necessario lead out local nNext = EgtGetNext( nCrvRib) if not nNext or EgtGetName( nNext) ~= LINK_CRV then AddRibsLeadOut( nCrvRib, nTpathGrpId, nLoopGrp, LayerParams.vtSlicing, LayerParams.dStrand, nGrpTmp) end nCrvRib = EgtGetNextName( nCrvRib, RIBS_CRV .. '*') end EgtErase( nGrpTmp) end ------------------------------------------------------------------- ------------------------- SPIRAL VASE ------------------------------ -------------------------------------------------------------------- local function AddSpiralVaseLeadOut( nOldId, LayerParams) if LayerParams.nLeadOutType ~= LEAD_TYPE.NONE then EgtTrimCurveEndAtLen( nOldId, EgtCurveLength( nOldId) - LayerParams.dOffsetLP) local nLeadOut = AddLeadOut( nOldId, LayerParams, EgtGetParent( nOldId)) if nLeadOut then local dDelta = LayerParams.dLayHeight / EgtCurveLength( nOldId) * EgtCurveLength( nLeadOut) EgtSpiralizeCurveAlongExtrusion( nLeadOut, dDelta) end AddRetractionOnLastCrv( nOldId, EgtGetParent( nOldId), LayerParams, LayerParams.dCoastingLen, LayerParams.dWipeLen, LayerParams.dWipeDir) else AddRetraction( nOldId, LayerParams.vtSlicing, LayerParams.dCoastingLen, LayerParams.dWipeLen, LayerParams.dWipeDir) end end --------------------------------------------------------------------- local function SpiralVase( vLayIds, dCorrZ, LayerParams) local nOldId, nOldPathId local bFirst = true local nSlicingType = EgtGetInfo( s_nPartId, KEY_SLICING_TYPE, 'i') -- copio ultimo layer if nSlicingType ~= SLICING_TYPE.DEG45_X and nSlicingType ~= SLICING_TYPE.DEG45_Y then local nNewLay = EgtCopyGlob( vLayIds[#vLayIds], vLayIds[#vLayIds], GDB_IN.AFTER) table.insert( vLayIds, nNewLay) EgtMove( nNewLay, LayerParams.dLayHeight * LayerParams.vtSlicing, GDB_RT.GLOB) -- aggiorno nome e info local sOldIdx = string.sub( EgtGetName( vLayIds[#vLayIds]), 6) local nNewIdx = tonumber( sOldIdx) + 1 EgtSetName( nNewLay, SLICE_LAYER .. EgtNumToString( nNewIdx)) EgtSetInfo( nNewLay, KEY_SLICE_NBR, nNewIdx) local dZOld = EgtGetInfo( vLayIds[#vLayIds], KEY_SLICE_Z, 'd') or 0 EgtSetInfo( nNewLay, KEY_SLICE_Z, dZOld + LayerParams.dLayHeight) end -- ciclo sui layer for nIdx = 1, #vLayIds do -- cerco i gruppi di contorni local vCrvGrpIds = EgtGetNameInGroup( vLayIds[ nIdx], CONTOUR_GRP.."*") if #vCrvGrpIds > 1 then -- se più di un gruppo di curve warning EgtOutLog( 'Warning : in spiral vase mode more than one curve (layer '..tostring( nIdx)..') - CalcToolPath') end for i = 1, #vCrvGrpIds do -- recupero il gruppo dei percorsi local nPathGrpId = EgtGetFirstNameInGroup( vCrvGrpIds[i], PATH_GRP) if not nPathGrpId then EgtOutBox( 'Error missing paths', 'ToolPathCalc') return else EgtSetStatus( nPathGrpId, GDB_ST.OFF) end -- recupero il gruppo dei percorsi utensile local nTpathGrpId = EgtGetFirstNameInGroup( vCrvGrpIds[i], TOOLPATH_GRP) if not nTpathGrpId then nTpathGrpId = EgtGroup( vCrvGrpIds[i]) EgtSetName( nTpathGrpId, TOOLPATH_GRP) else EgtEmptyGroup( nTpathGrpId) end -- creo il percorso di lavoro : local nEntId = EgtGetFirstInGroup( nPathGrpId) while nEntId do local nNewEntId = EgtCopyGlob( nEntId, nTpathGrpId, GDB_IN.LAST_SON) -- correggo la posizione del toolpath local vtMove = dCorrZ * Z_AX() if nSlicingType == SLICING_TYPE.DEG45_X or nSlicingType == SLICING_TYPE.DEG45_Y then -- eventuale spostamento dell'altezza layer vtMove = vtMove + LayerParams.dLayHeight * LayerParams.vtSlicing end EgtMove( nNewEntId, vtMove, GDB_RT.GLOB) EgtModifyCurveExtrusion( nNewEntId, LayerParams.vtSlicing, GDB_RT.GLOB) -- eventuale inversione if LayerParams.bInvert then EgtInvertCurve( nNewEntId) EgtSetInfo( nNewEntId, KEY_INVERTED_CRV, 1) end EgtSetColor( nNewEntId, EgtStdColor('GRAY')) -- se primo layer if bFirst and nNewEntId then -- mi sposto dell'altezza layer EgtMove( nNewEntId, LayerParams.dLayHeight * LayerParams.vtSlicing, GDB_RT.GLOB) -- eventuale lead in if LayerParams.nLeadInType ~= LEAD_TYPE.NONE then EgtTrimCurveStartAtLen( nNewEntId, LayerParams.dOffsetLP) AddLeadIn( nNewEntId, LayerParams, nTpathGrpId) end bFirst = false else local ptOld = EgtEP( nOldId, GDB_ID.ROOT) local ptNew = EgtSP( nNewEntId, GDB_ID.ROOT) if dist( ptNew, ptOld) < LayerParams.dStrand then -- se i punti sono vicini ma non coincidenti modifico la curva per avere transizione più uniforme if not AreSamePointApprox( ptOld, ptNew) then -- recupero la curva da usare come guida local nGuideId = EgtCopyGlob( nOldPathId, nTpathGrpId) -- la porto alla stessa quota del toolpath EgtMove( nGuideId, vtMove + LayerParams.dLayHeight * LayerParams.vtSlicing, GDB_RT.GLOB) EgtChangeClosedCurveStartPoint( nGuideId, ptOld, GDB_RT.GLOB) EgtSpiralizeCurveAlongGuide( nNewEntId, nGuideId) EgtErase( nGuideId) end else EgtOutLog( 'Warning : in spiral vase mode no link betweeen toolpaths (layer '..tostring( nIdx)..') - CalcToolPath') -- aggiungo uscita, coasting e wipe sulla curva precedente AddSpiralVaseLeadOut( nOldId, LayerParams) end EgtSpiralizeCurveAlongExtrusion( nNewEntId, LayerParams.dLayHeight) end nOldPathId = nEntId nOldId = nNewEntId nEntId = EgtGetNext( nEntId) end end if EgtProcessEvents( EgtIf( PRINT, 300, 0) + nIdx / #vLayIds * 100, 0) == 1 then EgtDraw() return end end -- aggiungo uscita, coasting e wipe su ultima curva AddSpiralVaseLeadOut( nOldId, LayerParams) end --------------------------------------------------------------------- function CalcToolPath.Exec( nPartId) s_nPartId = nPartId -- Verifico il pezzo if not s_nPartId then EgtOutBox( 'Error missing part', 'ToolPathCalc') return end -- Recupero i layer da processare local vLayIds = EgtGetNameInGroup( s_nPartId, SLICE_LAYER.."*") if not vLayIds then EgtOutBox( 'Error missing slices', 'ToolPathCalc') return end -- recupero i parametri per calcolo dei toolpath local LayerParams = GetLayerParamsForToolPathCalc() local dCorrZ = ComputeZCorrection( LayerParams) -- se necessario sposto anche il solido di partenza if dCorrZ > 10 * GEO.EPS_SMALL then local vtMove = Vector3d( 0, 0, dCorrZ) -- se slicing a 45° aggiungo correzione anche in direzione dello slicing local nSlicingType = EgtGetInfo( s_nPartId, KEY_SLICING_TYPE, 'i') or 1 if nSlicingType == SLICING_TYPE.DEG45_X or nSlicingType == SLICING_TYPE.DEG45_Y then vtMove = vtMove + LayerParams.dLayHeight / 2 * LayerParams.vtSlicing end local SolidLayId = EgtGetFirstNameInGroup( s_nPartId, PRINT_SOLID) if SolidLayId then EgtSetInfo( s_nPartId, KEY_MOVED_PART, vtMove) local EntId = EgtGetFirstInGroup( SolidLayId) while EntId do EgtMove( EntId, vtMove, GDB_RT.GLOB) EntId = EgtGetNext( EntId) end end end -- caso spiral vase if LayerParams.bSpiralVase then SpiralVase( vLayIds, dCorrZ, LayerParams) return end -- Ciclo sui layer for nIdx = 1, #vLayIds do -- scorro tutti i gruppi di contorni local nCrvGrpId = EgtGetFirstNameInGroup( vLayIds[ nIdx], CONTOUR_GRP.."*") while nCrvGrpId do -- recupero il gruppo dei percorsi local nPathGrpId = EgtGetFirstNameInGroup( nCrvGrpId, PATH_GRP) if not nPathGrpId then EgtOutBox( 'Error missing paths', 'ToolPathCalc') return else EgtSetStatus( nPathGrpId, GDB_ST.OFF) end -- recupero il gruppo dei percorsi utensile local nTpathGrpId = EgtGetFirstNameInGroup( nCrvGrpId, TOOLPATH_GRP) if not nTpathGrpId then nTpathGrpId = EgtGroup( nCrvGrpId) EgtSetName( nTpathGrpId, TOOLPATH_GRP) else EgtEmptyGroup( nTpathGrpId) end -- realizzo le diverse tipologie in base all'ordine selezionato for j = 1, #LayerParams.vPrintOrder do if LayerParams.vPrintOrder[j] == PRINT_ELEMENT.SHELL then -- shell local vShellIds = EgtGetNameInGroup( nPathGrpId, SHELL_CRV .. '*') CalcShellsToolPath( vShellIds, nTpathGrpId, LayerParams, dCorrZ) elseif LayerParams.vPrintOrder[j] == PRINT_ELEMENT.EXTRA_SHELL then -- extra shell local vExtraShellIds = EgtGetNameInGroup( nPathGrpId, EXTRA_SHELL_CRV .. '*') CalcExtraShellToolPath( vExtraShellIds, nTpathGrpId, LayerParams, dCorrZ) elseif LayerParams.vPrintOrder[j] == PRINT_ELEMENT.INFILL then -- infill local vInfillIds = EgtGetNameInGroup( nPathGrpId, INFILL_CRV .. '*') CalcInfillToolPath( vInfillIds, nTpathGrpId, LayerParams, dCorrZ) elseif LayerParams.vPrintOrder[j] == PRINT_ELEMENT.AUX_SOLID then -- solidi ausiliari local nAuxSolidsGrp = EgtGetFirstNameInGroup( vLayIds[nIdx], AUX_SOLIDS_GRP) local nAuxSolidsPathGrp = EgtGetFirstNameInGroup( nCrvGrpId, AUX_SOLIDS_GRP) CalcAuxSolidsToolPath( nAuxSolidsGrp, nAuxSolidsPathGrp, nTpathGrpId, LayerParams, dCorrZ) else -- costolature local nRibsGrp = EgtGetFirstNameInGroup( nCrvGrpId, RIBS_GRP) CalcRibsToolPath( nRibsGrp, nTpathGrpId, LayerParams, dCorrZ) end end -- passo al gruppo di contorni successivo nCrvGrpId = EgtGetNextName( nCrvGrpId, CONTOUR_GRP.."*") end if EgtProcessEvents( EgtIf( PRINT, 300, 0) + nIdx / #vLayIds * 100, 0) == 1 then EgtDraw() return end end end --------------------------------------------------------------------- return CalcToolPath