-- 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, 6, 7, 8} 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 ComputeToolPathBox( nTpathGrpId) -- calcolo il box del toolpath (escludendo i wipe) local b3Box = BBox3d() local nEntId = EgtGetFirstInGroup( nTpathGrpId) while nEntId do if EgtGetInfo( nEntId, KEY_TYPE, 'i') ~= TYPE.WIPE then local b3Ent = EgtGetBBoxGlob( nEntId, GDB_BB.STANDARD) b3Box:Add( b3Ent) end nEntId = EgtGetNext( nEntId) end return b3Box end ------------------------------------------------------------------ local function AddZCorrection( b3Box, LayerParams) local dNxy = sqrt( LayerParams.vtSlicing:getX() * LayerParams.vtSlicing:getX() + LayerParams.vtSlicing:getY() * LayerParams.vtSlicing:getY()) local dNz = LayerParams.vtSlicing:getZ() -- altezza necessaria per lo strand local dHStrand = 0.5 * LayerParams.dStrand * dNxy + LayerParams.dLayHeight * dNz -- altezza necessaria per il tool local dHTool = LayerParams.dTDiam / 2 * dNxy -- altezza disponibile local dHBox = EgtGetInfo( s_nPartId, KEY_BOX_MIN_Z, 'i') or 0 local dHDisp = b3Box:getMin():getZ() - dHBox local dCorrZ = max( 0, max( dHStrand, dHTool) - dHDisp) -- applico la correzione al pezzo local vtMove = dCorrZ * Z_AX() EgtMove( s_nPartId, vtMove, GDB_RT.GLOB) EgtSetInfo( s_nPartId, KEY_MOVED_PART2, vtMove) -- correggo la posizione del riferimento local nFrameId = EgtGetFirstNameInGroup( s_nPartId, LAY_FRAME) EgtMove( nFrameId, - vtMove, GDB_RT.GLOB) end ------------------------------------------------------------------ local function FindWipeEndPoint( ptS, vtDir, dLen, vtSlicing) local ptE = ptS + vtDir * dLen -- verifico soddisfi altezza minima per non entrare nella tavola local k = 1 while ptE:getZ() < s_dHMin + GEO.EPS_SMALL and k < 36 do vtDir:rotate( vtSlicing, 10) ptE = ptS + vtDir * dLen k = k + 1 end return ptE end ------------------------------------------------------------------- local function AddCurvesToToolPath( vEntIds, nTpathGrpId, nOrder, bInvert, vtSlicing, dLayHeight) 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 -- 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 or nType == TYPE.RIB 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 AddOffsetLeadPoint( vIds, nFirstCopy, dOffsetLP, nLinkType) -- se link va fatto solo sulla shell esterna local nLast = EgtIf( nLinkType == LINK_TYPE.NONE, #vIds, 1) if abs( dOffsetLP) > GEO.EPS_SMALL then for i = 1, nLast do if dOffsetLP > GEO.EPS_SMALL then -- taglio curva EgtTrimCurveStartAtLen( vIds[i], dOffsetLP) else -- è necessario aggiungere un tratto local nAddCrv = EgtCopyGlob( EgtIf( i == 1, nFirstCopy, vIds[i]), vIds[1], GDB_IN.AFTER) EgtTrimCurveStartAtLen( nAddCrv, EgtCurveLength( nAddCrv) - abs( dOffsetLP)) EgtAddCurveCompoCurve( vIds[i], nAddCrv, true, false) end end end -- elimino curva aux usata per prima shell EgtErase( nFirstCopy) 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 = FindWipeEndPoint( ptS, vtDir, dWipeLen, vtSlicing) 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) if not vEntIds then return end -- aggiungo le curve nel toolpath local vIds = AddCurvesToToolPath( vEntIds, nTpathGrpId, LayerParams.nOrder, LayerParams.bInvert, LayerParams.vtSlicing, LayerParams.dLayHeight) local nFirstCopy = EgtCopyGlob( vIds[1], nTpathGrpId) -- necessaria per corretto offset lead point sulla shell esterna -- aggiungo gli opportuni raccordi AddLink( vIds, nTpathGrpId, LayerParams.nLinkType, LayerParams.dLinkParam, LayerParams.dSPOffs, LayerParams.dStrand, LayerParams.vtSlicing) -- offset lead point AddOffsetLeadPoint( vIds, nFirstCopy, LayerParams.dOffsetLP, LayerParams.nLinkType) -- 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) 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) -- 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) if not vEntIds then return end -- aggiungo le curve nel toolpath local vIds = AddCurvesToToolPath( vEntIds, nTpathGrpId, LayerParams.nOrder, LayerParams.bInvert, LayerParams.vtSlicing, LayerParams.dLayHeight) -- 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) 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) -- 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 nCurr ~= nNext and ( 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 = EgtGetFirstNameInGroup( nLoopGrp, TRIM_SURF_LOOP) -- recupero la curva di offset su cui calcolare link while nCrvId do local dParS = EgtCurveParamAtPoint( nCrvId, ptS, 10 * GEO.EPS_SMALL) local dParE = EgtCurveParamAtPoint( nCrvId, ptE, 10 * GEO.EPS_SMALL) 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 -- elimino dalle curve di contorno il link appena trovato if bClosed then EgtTrimCurveStartEndAtParam( nCrvId, dParE, dParS) EgtErase( nCopyId) else if dParS < GEO.EPS_SMALL then -- forzare la fine della curva nel suo inizio significa cancellarla completamente EgtErase( nCrvId) else EgtTrimCurveEndAtParam( nCrvId, dParS) end local _, dEnd = EgtCurveDomain( nCopyId) if abs( dParE - dEnd) < GEO.EPS_SMALL then -- forzare l'inizio della curva nella sua fine significa cancellarla completamente EgtErase( nCopyId) else EgtTrimCurveStartAtParam( nCopyId, dParE) end end return nLinkId end nCrvId = EgtGetNextName( nCrvId, TRIM_SURF_LOOP) 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'estremo corretto if not EgtCurveIsClosed( nRibId) then local pt = EgtIf( bInVsOut, EgtEP( nRibId), EgtSP( nRibId)) local dPar = EgtCurveParamAtPoint( nLeadId, pt) if dPar then EgtErase( nLeadId) return false end 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, bForceNoBorder) 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 -- se setto chiuso oppure non deve stare sul bordo (rib unbounded) applico la stessa uscita delle shell if EgtCurveIsClosed( nCrv) or bForceNoBorder then return AddRetraction( nCrv, vtSlicing, dRibsLOCoasting, dRibsLOWipe, dRibsLOWipeAng) 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 = FindWipeEndPoint( ptE, vtE, dRibsLOWipe, vtSlicing) 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( vEntIds, nRibsGrp, nTpathGrpId, LayerParams) if not vEntIds or #vEntIds == 0 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 nNewFirstEnt for i = 1, #vEntIds do -- copio entità nel gruppo toolpath local nNewEntId = EgtCopyGlob( vEntIds[i], nTpathGrpId, GDB_IN.LAST_SON) -- 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')) if i == 1 then nNewFirstEnt = nNewEntId end end -- recupero i gruppi delle costolature local tabRibs = {} local nFirst = nNewFirstEnt while nFirst do local sName = EgtGetName( nFirst) local vIds = EgtGetNameInGroup( nTpathGrpId, sName) table.insert( tabRibs, vIds) nFirst = EgtGetNextName( vIds[#vIds], RIBS_CRV .. '*') end local bSpecialCase = EgtGetInfo( nRibsGrp, KEY_RIBS_SPECIAL_CASE, 'b') or false -- Link local nLoopGrp = EgtGetFirstGroupInGroup( nRibsGrp) -- collego le passate di una stessa costolatura for i = 1, #tabRibs do if EgtCurveIsClosed( tabRibs[i][1]) then AddLink( tabRibs[i], nTpathGrpId, LINK_TYPE.NONE, LayerParams.dLinkParam, LayerParams.dSPOffs, LayerParams.dStrand, LayerParams.vtSlicing) else local bLoopRib = EgtGetInfo( tabRibs[i][1], KEY_LOOP_RIB, 'b') or false for j = 1, #tabRibs[i] - 1 do local bUserLink = EgtGetInfo( tabRibs[i][j], KEY_RIBS_USER_LINK, 'b') or false local nOrig1 = EgtGetInfo( tabRibs[i][j], KEY_ORIGINAL_RIB, 'i') or 0 local nOrig2 = EgtGetInfo( tabRibs[i][j + 1], KEY_ORIGINAL_RIB, 'i') or 0 local nSplitId1 = EgtGetInfo( tabRibs[i][j], KEY_SPLIT_ID, 'i') or 0 local nSplitId2 = EgtGetInfo( tabRibs[i][j + 1], KEY_SPLIT_ID, 'i') or 0 local bForceLink = ( nOrig1 == nOrig2) if ( nOrig1 ~= nOrig2 and bUserLink) or ( nSplitId1 == nSplitId2 and nOrig1 == nOrig2) then local nLinkId = CalcRibsLink( tabRibs[i][j], tabRibs[i][j + 1], nLoopGrp, LayerParams.dStrand, bForceLink, LayerParams.vtSlicing, nGrpTmp) -- creo link fittizio per eliminare tratto corrispondente sulla curva di offset if not bSpecialCase and bForceLink then local nFakeLink = CalcRibsLink( tabRibs[i][j + 1], tabRibs[i][j], nLoopGrp, LayerParams.dStrand, false, LayerParams.vtSlicing, nGrpTmp) EgtErase( nFakeLink) end -- se LoopRib congiungo i setti in unico percorso if bLoopRib and nLinkId then EgtAddCurveCompoCurve( tabRibs[i][j], nLinkId) EgtAddCurveCompoCurve( tabRibs[i][j], tabRibs[i][j + 1]) tabRibs[i][j+1] = tabRibs[i][j] -- aggiorno id nel vettore dei setti per gestire correttamente la curva allo step successivo end end end -- se LoopRib aggiungo collegamento tra primo e ultimo setto del gruppo if bLoopRib then local nTotCrv = #tabRibs[i] local nLinkId = CalcRibsLink( tabRibs[i][nTotCrv], tabRibs[i][1], nLoopGrp, LayerParams.dStrand, false, LayerParams.vtSlicing, nGrpTmp) if nLinkId then -- se curva unica if tabRibs[i][nTotCrv] == tabRibs[i][1] then EgtAddCurveCompoCurve( tabRibs[i][1], nLinkId) -- setto info di curva chiusa per gestire correttamente il wipe EgtSetInfo( tabRibs[i][1], KEY_CLOSED_CRV, 1) -- modifica dello start point ( considera quello delle shell) local nCrvGrp = EgtGetParent( nTpathGrpId) local ptStart = EgtGetInfo( nCrvGrp, KEY_START_POINT, 'p') if ptStart then EgtChangeClosedCurveStartPoint( tabRibs[i][1], ptStart) end else EgtAddCurveCompoCurve( tabRibs[i][1], nLinkId, true, false) EgtAddCurveCompoCurve( tabRibs[i][1], tabRibs[i][nTotCrv], true, false) tabRibs[i][nTotCrv] = tabRibs[i][1] end 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') if bLink1 and bLink2 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 bForceNoBorder = false local nType = EgtGetInfo( vEntIds[1], KEY_RIBS_TYPE, 'i') if nType == RIB_TYPE.UNBOUNDED then bForceNoBorder = true end local nCrvRib = nNewFirstEnt while nCrvRib do -- verifico se necessario lead in local nPrev = EgtGetPrev( nCrvRib) if ( not nPrev or EgtGetName( nPrev) ~= LINK_CRV) and not bForceNoBorder 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, bForceNoBorder) 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, 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 local b3Tot = BBox3d() -- 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) local vtMove = V_NULL() -- eventuale spostamento dell'altezza layer if nSlicingType == SLICING_TYPE.DEG45_X or nSlicingType == SLICING_TYPE.DEG45_Y then vtMove = LayerParams.dLayHeight * LayerParams.vtSlicing EgtMove( nNewEntId, vtMove, GDB_RT.GLOB) end 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 -- aggiorno il box dei toolpath local b3Box = ComputeToolPathBox( nTpathGrpId) b3Tot:Add( b3Box) end if EgtProcessEvents( EgtIf( PRINT, 300, 0) + nIdx / #vLayIds * 100, 0) == 1 then EgtDraw() return false end end -- aggiungo uscita, coasting e wipe su ultima curva AddSpiralVaseLeadOut( nOldId, LayerParams) -- correzione in z AddZCorrection( b3Tot, LayerParams) return true end --------------------------------------------------------------------- function CalcToolPath.Exec( nPartId) s_nPartId = nPartId -- Recupero i layer da processare local vLayIds = EgtGetNameInGroup( s_nPartId, SLICE_LAYER.."*") if not vLayIds then EgtOutBox( 'Error missing slices', 'ToolPathCalc') return true end -- recupero i parametri per calcolo dei toolpath local LayerParams = GetLayerParamsForToolPathCalc() -- altezza necessaria per correzione wipe local dNxy = sqrt( LayerParams.vtSlicing:getX() * LayerParams.vtSlicing:getX() + LayerParams.vtSlicing:getY() * LayerParams.vtSlicing:getY()) local dHBox = EgtGetInfo( s_nPartId, KEY_BOX_MIN_Z, 'i') or 0 s_dHMin = LayerParams.dTDiam / 2 * dNxy + dHBox -- caso spiral vase if LayerParams.bSpiralVase then return SpiralVase( vLayIds, LayerParams) end local b3Tot = BBox3d() -- box dei toolpath -- 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 -- suddivido i ribs per tipologia local nRibsGrp = EgtGetFirstNameInGroup( nCrvGrpId, RIBS_GRP) local tRibs = {{}, {}, {}, {}} local vRibsIds = EgtGetNameInGroup( nRibsGrp, RIBS_CRV .. '*') or {} for i = 1, #vRibsIds do local nType = EgtGetInfo( vRibsIds[i], KEY_RIBS_TYPE, 'i') or 1 table.insert( tRibs[nType], vRibsIds[i]) 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) elseif LayerParams.vPrintOrder[j] == PRINT_ELEMENT.EXTRA_SHELL then -- extra shell local vExtraShellIds = EgtGetNameInGroup( nPathGrpId, EXTRA_SHELL_CRV .. '*') CalcExtraShellToolPath( vExtraShellIds, nTpathGrpId, LayerParams) elseif LayerParams.vPrintOrder[j] == PRINT_ELEMENT.INFILL then -- infill local vInfillIds = EgtGetNameInGroup( nPathGrpId, INFILL_CRV .. '*') CalcInfillToolPath( vInfillIds, nTpathGrpId, LayerParams) 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) -- costolature elseif LayerParams.vPrintOrder[j] == PRINT_ELEMENT.RIB_UNBOUNDED then CalcRibsToolPath( tRibs[RIB_TYPE.UNBOUNDED], nRibsGrp, nTpathGrpId, LayerParams) elseif LayerParams.vPrintOrder[j] == PRINT_ELEMENT.RIB_INTERNAL then CalcRibsToolPath( tRibs[RIB_TYPE.INTERNAL], nRibsGrp, nTpathGrpId, LayerParams) elseif LayerParams.vPrintOrder[j] == PRINT_ELEMENT.RIB_SUPPORT then CalcRibsToolPath( tRibs[RIB_TYPE.SUPPORT], nRibsGrp, nTpathGrpId, LayerParams) elseif LayerParams.vPrintOrder[j] == PRINT_ELEMENT.RIB_EXTERNAL then CalcRibsToolPath( tRibs[RIB_TYPE.EXTERNAL], nRibsGrp, nTpathGrpId, LayerParams) end end -- aggiorno il box dei toolpath local b3Box = ComputeToolPathBox( nTpathGrpId) b3Tot:Add( b3Box) -- 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 -- correzione in z AddZCorrection( b3Tot, LayerParams) return true end --------------------------------------------------------------------- return CalcToolPath