diff --git a/LuaLibs/AddManData.lua b/LuaLibs/AddManData.lua index c88cf18..d4f4067 100644 --- a/LuaLibs/AddManData.lua +++ b/LuaLibs/AddManData.lua @@ -45,6 +45,8 @@ SEC_DEFAULT = "Default" KEY_PARAMS = "Params" KEY_CALC_SOLIDS = "CalcSolids" KEY_SPIRAL_VASE = "SpiralVase" +KEY_SPIRAL_VASE_LEN = 'SpiralVaseLen' +KEY_SPIRAL_VASE_INTERP_LEN = 'SpiralVaseInterpLen' KEY_SLICING_TYPE = "SlicingType" KEY_SLICING_DIR = "SlicingDir" KEY_SLICE_STEP = "StrandH" diff --git a/LuaLibs/CalcToolPath.lua b/LuaLibs/CalcToolPath.lua index db7fe88..d812767 100644 --- a/LuaLibs/CalcToolPath.lua +++ b/LuaLibs/CalcToolPath.lua @@ -14,12 +14,12 @@ 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_nDefaultWipeAng = -90 -- angolo = 0° per wipe significa che esce ortogonalmente alla direzione del movimento local s_dApproxTol = 0.1 local s_dHSafeWipe = 2 local s_nCurrIdx -local s_dSpiralVaseMaxLen = 10 -local s_dSpralVaseFirstDelta = 30 -- lunghezza del tratto sul primo layer che va alzato +local s_dSpiralVaseMaxLen = 10 -- lunghezza massima dei tratti per calcolo SpiralizeAlongGuide +local s_dSpralVaseFirstDelta = 30 -- lunghezza del tratto sul primo layer che va alzato nella modalità SpiralVaseFull --------------------------------------------------------------------- local function GetLayerParamsForToolPathCalc() @@ -63,8 +63,9 @@ local function GetLayerParamsForToolPathCalc() -- parametri da file ini del programma local sIniFile = EgtGetIniFile() - LayerParams.dSpiralVaseInterpLen = EgtGetNumberFromIni( '3dPrinting', 'SpiralVaseInterpLen', 100.0, sIniFile) - + LayerParams.dSpiralVaseInterpLen = EgtGetNumberFromIni( '3dPrinting', KEY_SPIRAL_VASE_INTERP_LEN, 100.0, sIniFile) + LayerParams.dSpiralVaseLen = EgtGetNumberFromIni( '3dPrinting', KEY_SPIRAL_VASE_LEN, 0.0, sIniFile) + return LayerParams end @@ -2009,17 +2010,18 @@ local function AddSpiralVaseLeadOut( nOldId, LayerParams) else AddRetraction( nOldId, LayerParams.vtSlicing, LayerParams.dCoastingLen, LayerParams.dWipeLen, LayerParams.dWipeDir) end - end --------------------------------------------------------------------- -local function SpiralVase( vLayIds, LayerParams) +local function SpiralVaseFull( vLayIds, LayerParams) + -- la differenza in altezza tra due layers viene distribuita uniformemente lungo tutto il percorso + -- la continuità tra i layers viene risolta sul layer corrente ( uniformemente su tutto il tratto o solo nella parte iniziale di lunghezza dSpiralVaseInterpLen) + -- gestione speciale dei primi layers per gestione dell'altezza e feed local nOldId, nOldPathId - local bFirst = true local nRealLayer = 1 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) @@ -2033,8 +2035,7 @@ local function SpiralVase( vLayIds, LayerParams) 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 @@ -2046,189 +2047,338 @@ local function SpiralVase( vLayIds, LayerParams) return false 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 vEntIds = EgtGetAllInGroup( nPathGrpId) - if #vEntIds > 1 then - EgtOutBox( 'Error in spiral vase : layer ' .. tostring( nIdx) .. ' has more than one toolpath', 'ToolPathCalc') - return false - end - - local nNewEntId = EgtCopyGlob( vEntIds[1] or GDB_ID.NULL, nTpathGrpId, GDB_IN.LAST_SON) - - if nNewEntId then - - 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 + -- recupero il gruppo dei percorsi + local nPathGrpId = EgtGetFirstNameInGroup( vCrvGrpIds[1], PATH_GRP) + if not nPathGrpId then + EgtOutBox( 'Error missing paths', 'ToolPathCalc') + return + else + EgtSetStatus( nPathGrpId, GDB_ST.OFF) + end - EgtModifyCurveExtrusion( nNewEntId, LayerParams.vtSlicing, GDB_RT.GLOB) - EgtSetInfo( nNewEntId, KEY_CRV_STRAND, LayerParams.dStrand) - - -- eventuale inversione - if LayerParams.bInvert then - EgtInvertCurve( nNewEntId) - EgtSetInfo( nNewEntId, KEY_INVERTED_CRV, 1) + -- recupero il gruppo dei percorsi utensile + local nTpathGrpId = EgtGetFirstNameInGroup( vCrvGrpIds[1], TOOLPATH_GRP) + if not nTpathGrpId then + nTpathGrpId = EgtGroup( vCrvGrpIds[1]) + EgtSetName( nTpathGrpId, TOOLPATH_GRP) + else + EgtEmptyGroup( nTpathGrpId) + end + + -- creo il percorso di lavoro : + local vEntIds = EgtGetAllInGroup( nPathGrpId) + if #vEntIds > 1 then + EgtOutBox( 'Error in spiral vase : layer ' .. tostring( nIdx) .. ' has more than one toolpath', 'ToolPathCalc') + return false + end + + local nNewEntId = EgtCopyGlob( vEntIds[1] or GDB_ID.NULL, nTpathGrpId, GDB_IN.LAST_SON) + if nNewEntId then + + 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) + EgtSetInfo( nNewEntId, KEY_CRV_STRAND, LayerParams.dStrand) + + -- eventuale inversione + if LayerParams.bInvert then + EgtInvertCurve( nNewEntId) + EgtSetInfo( nNewEntId, KEY_INVERTED_CRV, 1) + end + EgtSetColor( nNewEntId, EgtStdColor('GRAY')) + + -- se primo layer + if nRealLayer == 1 then + -- mi sposto dell'altezza layer + EgtMove( nNewEntId, LayerParams.dLayHeight * LayerParams.vtSlicing, GDB_RT.GLOB) + -- modifico altezza ultimo tratto + local dTrimPar = EgtCurveParamAtLength( nNewEntId, EgtCurveLength( nNewEntId) - s_dSpralVaseFirstDelta) + local nNewPart = EgtSplitCurveAtParam( nNewEntId, dTrimPar) + EgtSpiralizeCurveAlongExtrusion( nNewPart, 0.5 * LayerParams.dLayHeight) + + if LayerParams.bLinearApprox then + EgtApproxCurve( nNewEntId, GDB_CA.LINES, LayerParams.dLinearApproxTol) + EgtApproxCurve( nNewPart, GDB_CA.LINES, LayerParams.dLinearApproxTol) end - EgtSetColor( nNewEntId, EgtStdColor('GRAY')) - -- se primo layer - if nRealLayer == 1 then - -- mi sposto dell'altezza layer - EgtMove( nNewEntId, LayerParams.dLayHeight * LayerParams.vtSlicing, GDB_RT.GLOB) - -- modifico altezza ultimo tratto - local dTrimPar = EgtCurveParamAtLength( nNewEntId, EgtCurveLength( nNewEntId) - s_dSpralVaseFirstDelta) - local nNewPart = EgtSplitCurveAtParam( nNewEntId, dTrimPar) - EgtSpiralizeCurveAlongExtrusion( nNewPart, 0.5 * LayerParams.dLayHeight) - - if LayerParams.bLinearApprox then - EgtApproxCurve( nNewEntId, GDB_CA.LINES, LayerParams.dLinearApproxTol) - EgtApproxCurve( nNewPart, GDB_CA.LINES, LayerParams.dLinearApproxTol) - end - - -- eventuale lead in - if LayerParams.nLeadInType ~= LEAD_TYPE.NONE then - EgtTrimCurveStartAtLen( nNewEntId, LayerParams.dOffsetLP) - local nLeadInCrv = AddLeadIn( nNewEntId, LayerParams, nTpathGrpId) - if nLeadInCrv and LayerParams.bLinearApprox then - EgtApproxCurve( nLeadInCrv, GDB_CA.LINES, LayerParams.dLinearApproxTol) - end - end - else - -- a) garantisco continuità con layer precedente - local ptOld = EgtEP( nOldId, GDB_ID.ROOT) - if nRealLayer == 2 then - -- aggiusto la quota per confronto sensato - ptOld = ptOld - 0.5 * LayerParams.dLayHeight * LayerParams.vtSlicing - end - local ptNew = EgtSP( nNewEntId, GDB_ID.ROOT) - - -- se il punto di inizio non coincide con quello finale del percorso calcolato fino ad ora, modifico la curva per avere una transizione più uniforme tra i due layers - if not AreSamePointApprox( ptOld, ptNew) then - -- recupero la curva da usare come guida - local nGuideId = EgtCopyGlob( nOldPathId, nPathGrpId) - -- la rendo coerente con il toolpath - EgtMove( nGuideId, vtMove + LayerParams.dLayHeight * LayerParams.vtSlicing, GDB_RT.GLOB) - if LayerParams.bInvert then - EgtInvertCurve( nGuideId) - end - -- approssimo con tratti lineari imponendo lunghezza massima per migliorare spiralize - EgtApproxCurve( nGuideId, GDB_CA.SPECIAL_LINES, 0.01, s_dSpiralVaseMaxLen) - EgtApproxCurve( nNewEntId, GDB_CA.SPECIAL_LINES, 0.01, s_dSpiralVaseMaxLen) - -- modifico i punti iniziali affinchè coincidano con il punto finale del percorso precedente - EgtChangeClosedCurveStartPoint( nGuideId, ptOld, GDB_RT.GLOB) - EgtChangeClosedCurveStartPoint( nNewEntId, ptOld, GDB_RT.GLOB) - - -- distribuisco la differenza sulla curva - local dLen = EgtCurveLength( nNewEntId) - if LayerParams.dSpiralVaseInterpLen < GEO.EPS_SMALL or LayerParams.dSpiralVaseInterpLen > dLen - GEO.EPS_SMALL then - -- la differenza deve essere distribuita su tutta la curva - EgtSpiralizeCurveAlongGuide( nNewEntId, nGuideId) - -- forzo il punto di inizio a coincidere con il layer precedente ( non è garantito dallo spiralize con il path a causa dell'approx - -- con gli archi che potrebbe modificare il punto finale del tpath rispetto a quello del path associato) - EgtModifyCurveStartPoint( nNewEntId, ptOld, GDB_RT.GLOB) - - else - -- la differenza deve essere distribuita solo su un sottotratto di lunghezza LayerParams.dSpiralVaseAdjLen - local dParSplit = EgtCurveParamAtLength( nNewEntId, LayerParams.dSpiralVaseInterpLen) - local nNewEndId2 = EgtSplitCurveAtParam( nNewEntId, dParSplit) - -- trim della curva guida - local _, _, dParMinDist = EgtPointCurveDist( EgtEP( nNewEntId, GDB_ID.ROOT), nGuideId, GDB_RT.GLOB) - local nGuideId2 = EgtSplitCurveAtParam( nGuideId, dParMinDist) - EgtErase( nGuideId2) - -- spiralize solo del primo pezzo - EgtSpiralizeCurveAlongGuide( nNewEntId, nGuideId) - EgtModifyCurveStartPoint( nNewEntId, ptOld, GDB_RT.GLOB) - EgtModifyCurveEndPoint( nNewEntId, EgtSP( nNewEndId2, GDB_ID.ROOT), GDB_RT.GLOB) - -- riassemblo la curva - EgtAddCurveCompoCurve( nNewEntId, nNewEndId2) - end - - EgtErase( nGuideId) - end - - -- b) approssimo - local ptS = EgtSP( nNewEntId, GDB_ID.ROOT) - EgtApproxCurve( nNewEntId, GDB_CA.ARCS, s_dApproxTol) - if LayerParams.bLinearApprox then - EgtApproxCurve( nNewEntId, GDB_CA.LINES, LayerParams.dLinearApproxTol) - end - if EgtCurveIsClosed( nNewEntId) then - EgtChangeClosedCurveStartPoint( nNewEntId, ptS, GDB_RT.GLOB) - end - - -- c) modifica graduale dell'altezza - if nRealLayer == 2 then - -- se seconda passata la prima metà deve essere a quota costante 0.5 * dLayHeight, la seconda metà deve salire gradualmente di 0.5 * dLayHeight - EgtMove( nNewEntId, 0.5 * LayerParams.dLayHeight * LayerParams.vtSlicing, GDB_RT.GLOB) - local nNewId = EgtSplitCurve( nNewEntId, 2) - EgtSpiralizeCurveAlongExtrusion( nNewId + 1, 0.5 * LayerParams.dLayHeight) - else - EgtSpiralizeCurveAlongExtrusion( nNewEntId, LayerParams.dLayHeight) + -- eventuale lead in + if LayerParams.nLeadInType ~= LEAD_TYPE.NONE then + EgtTrimCurveStartAtLen( nNewEntId, LayerParams.dOffsetLP) + local nLeadInCrv = AddLeadIn( nNewEntId, LayerParams, nTpathGrpId) + if nLeadInCrv and LayerParams.bLinearApprox then + EgtApproxCurve( nLeadInCrv, GDB_CA.LINES, LayerParams.dLinearApproxTol) end end - - local vTPathsCrvs = EgtGetAllInGroup( nTpathGrpId) - nOldPathId = vEntIds[1] - nOldId = vTPathsCrvs[#vTPathsCrvs] - - -- moltiplicatore per feed + else + -- a) garantisco continuità con layer precedente + local ptOld = EgtEP( nOldId, GDB_ID.ROOT) if nRealLayer == 2 then - -- il primo tratto si trova a metà altezza rispetto allo strato precedente, quindi il coefficiente moltiplicativo è due - EgtSetInfo( vTPathsCrvs[1], KEY_FEED_COEFF, 2) - -- nel secondo tratto l'altezza è variabile quindi devo calcolare il coefficiente per ogni sottotratto - local dLenTot = EgtCurveLength( vTPathsCrvs[1]) + EgtCurveLength( vTPathsCrvs[2]) - local dLen = EgtCurveLength( vTPathsCrvs[1]) - local nFirst, nCnt = EgtExplodeCurveCompo( vTPathsCrvs[2]) - for nId = nFirst, nFirst + nCnt - 1 do - -- calcolo l'altezza effettiva basandomi sulla lunghezza parziale ( viene mimato il conto fatto in EgtSpiralizeCurveAlongExtrusion) - dLen = dLen + EgtCurveLength( nId) - local dHEff = LayerParams.dLayHeight * dLen / dLenTot - local dFeedCoeff = LayerParams.dLayHeight / dHEff - EgtSetInfo( nId, KEY_FEED_COEFF, dFeedCoeff) + -- aggiusto la quota per confronto sensato + ptOld = ptOld - 0.5 * LayerParams.dLayHeight * LayerParams.vtSlicing + end + local ptNew = EgtSP( nNewEntId, GDB_ID.ROOT) + + -- se il punto di inizio non coincide con quello finale del percorso calcolato fino ad ora, modifico la curva per avere una transizione più uniforme tra i due layers + if not AreSamePointApprox( ptOld, ptNew) then + -- recupero la curva da usare come guida + local nGuideId = EgtCopyGlob( nOldPathId, nPathGrpId) + -- la rendo coerente con il toolpath + EgtMove( nGuideId, vtMove + LayerParams.dLayHeight * LayerParams.vtSlicing, GDB_RT.GLOB) + if LayerParams.bInvert then + EgtInvertCurve( nGuideId) + end + -- approssimo con tratti lineari imponendo lunghezza massima per migliorare spiralize + EgtApproxCurve( nGuideId, GDB_CA.SPECIAL_LINES, 0.01, s_dSpiralVaseMaxLen) + EgtApproxCurve( nNewEntId, GDB_CA.SPECIAL_LINES, 0.01, s_dSpiralVaseMaxLen) + -- modifico i punti iniziali affinchè coincidano con il punto finale del percorso precedente + EgtChangeClosedCurveStartPoint( nGuideId, ptOld, GDB_RT.GLOB) + EgtChangeClosedCurveStartPoint( nNewEntId, ptOld, GDB_RT.GLOB) + + -- distribuisco la differenza sulla curva + local dLen = EgtCurveLength( nNewEntId) + if LayerParams.dSpiralVaseInterpLen < GEO.EPS_SMALL or LayerParams.dSpiralVaseInterpLen > dLen - GEO.EPS_SMALL then + -- la differenza deve essere distribuita su tutta la curva + EgtSpiralizeCurveAlongGuide( nNewEntId, nGuideId) + -- forzo il punto di inizio a coincidere con il layer precedente ( non è garantito dallo spiralize con il path a causa dell'approx + -- con gli archi che potrebbe modificare il punto finale del tpath rispetto a quello del path associato) + EgtModifyCurveStartPoint( nNewEntId, ptOld, GDB_RT.GLOB) + + else + -- la differenza deve essere distribuita solo su un sottotratto di lunghezza LayerParams.dSpiralVaseAdjLen + local dParSplit = EgtCurveParamAtLength( nNewEntId, LayerParams.dSpiralVaseInterpLen) + local nNewEndId2 = EgtSplitCurveAtParam( nNewEntId, dParSplit) + -- trim della curva guida + local _, _, dParMinDist = EgtPointCurveDist( EgtEP( nNewEntId, GDB_ID.ROOT), nGuideId, GDB_RT.GLOB) + local nGuideId2 = EgtSplitCurveAtParam( nGuideId, dParMinDist) + EgtErase( nGuideId2) + -- spiralize solo del primo pezzo + EgtSpiralizeCurveAlongGuide( nNewEntId, nGuideId) + EgtModifyCurveStartPoint( nNewEntId, ptOld, GDB_RT.GLOB) + EgtModifyCurveEndPoint( nNewEntId, EgtSP( nNewEndId2, GDB_ID.ROOT), GDB_RT.GLOB) + -- riassemblo la curva + EgtAddCurveCompoCurve( nNewEntId, nNewEndId2) end - nOldId = nFirst + nCnt - 1 - elseif nRealLayer == 3 then - -- solo la prima metà si trova ad un'altezza variabile rispetto allo strato precedente - local dLenTot = EgtCurveLength( vTPathsCrvs[1]) - local dLen = 0 - local nNewId = EgtSplitCurve( vTPathsCrvs[1], 2) - local nFirst, nCnt = EgtExplodeCurveCompo( nNewId) - for nId = nFirst, nFirst + nCnt - 1 do - dLen = dLen + EgtCurveLength( nId) - local dHeff = LayerParams.dLayHeight * ( dLen / dLenTot + 0.5) - local dFeedCoeff = LayerParams.dLayHeight / dHeff - EgtSetInfo( nId, KEY_FEED_COEFF, dFeedCoeff) - end - nOldId = nNewId + 1 + EgtErase( nGuideId) + end + + -- b) approssimo + local ptS = EgtSP( nNewEntId, GDB_ID.ROOT) + EgtApproxCurve( nNewEntId, GDB_CA.ARCS, s_dApproxTol) + if LayerParams.bLinearApprox then + EgtApproxCurve( nNewEntId, GDB_CA.LINES, LayerParams.dLinearApproxTol) + end + if EgtCurveIsClosed( nNewEntId) then + EgtChangeClosedCurveStartPoint( nNewEntId, ptS, GDB_RT.GLOB) end - nRealLayer = nRealLayer + 1 - -- aggiorno il box dei toolpath - local b3Box = ComputeToolPathBox( nTpathGrpId) - b3Tot:Add( b3Box) + -- c) modifica graduale dell'altezza + if nRealLayer == 2 then + -- se seconda passata la prima metà deve essere a quota costante 0.5 * dLayHeight, la seconda metà deve salire gradualmente di 0.5 * dLayHeight + EgtMove( nNewEntId, 0.5 * LayerParams.dLayHeight * LayerParams.vtSlicing, GDB_RT.GLOB) + local nNewId = EgtSplitCurve( nNewEntId, 2) + EgtSpiralizeCurveAlongExtrusion( nNewId + 1, 0.5 * LayerParams.dLayHeight) + else + EgtSpiralizeCurveAlongExtrusion( nNewEntId, LayerParams.dLayHeight) + end + end + + local vTPathsCrvs = EgtGetAllInGroup( nTpathGrpId) + nOldPathId = vEntIds[1] + nOldId = vTPathsCrvs[#vTPathsCrvs] + + -- moltiplicatore per feed + if nRealLayer == 2 then + -- il primo tratto si trova a metà altezza rispetto allo strato precedente, quindi il coefficiente moltiplicativo è due + EgtSetInfo( vTPathsCrvs[1], KEY_FEED_COEFF, 2) + -- nel secondo tratto l'altezza è variabile quindi devo calcolare il coefficiente per ogni sottotratto + local dLenTot = EgtCurveLength( vTPathsCrvs[1]) + EgtCurveLength( vTPathsCrvs[2]) + local dLen = EgtCurveLength( vTPathsCrvs[1]) + local nFirst, nCnt = EgtExplodeCurveCompo( vTPathsCrvs[2]) + for nId = nFirst, nFirst + nCnt - 1 do + -- calcolo l'altezza effettiva basandomi sulla lunghezza parziale ( viene mimato il conto fatto in EgtSpiralizeCurveAlongExtrusion) + dLen = dLen + EgtCurveLength( nId) + local dHEff = LayerParams.dLayHeight * dLen / dLenTot + local dFeedCoeff = LayerParams.dLayHeight / dHEff + EgtSetInfo( nId, KEY_FEED_COEFF, dFeedCoeff) + end + nOldId = nFirst + nCnt - 1 + + elseif nRealLayer == 3 then + -- solo la prima metà si trova ad un'altezza variabile rispetto allo strato precedente + local dLenTot = EgtCurveLength( vTPathsCrvs[1]) + local dLen = 0 + local nNewId = EgtSplitCurve( vTPathsCrvs[1], 2) + local nFirst, nCnt = EgtExplodeCurveCompo( nNewId) + for nId = nFirst, nFirst + nCnt - 1 do + dLen = dLen + EgtCurveLength( nId) + local dHeff = LayerParams.dLayHeight * ( dLen / dLenTot + 0.5) + local dFeedCoeff = LayerParams.dLayHeight / dHeff + EgtSetInfo( nId, KEY_FEED_COEFF, dFeedCoeff) + end + nOldId = nNewId + 1 + end + + nRealLayer = nRealLayer + 1 + end + + if EgtProcessEvents( EgtIf( PRINT, 300, 0) + nIdx / #vLayIds * 100, 0) == 1 then + EgtDraw() + return false + end + end + + return true +end + +--------------------------------------------------------------------- +local function SpiralVasePartial( vLayIds, LayerParams) + -- la differenza in altezza tra due layers viene distribuita solo lungo il tratto finale di lunghezza dSpiralVaseLen + -- la continuità tra i layers viene risolta sul tratto finale del layer percedente + + local bFirst = true + -- individuo l'ultimo layer ( alcuni potrebbero essere vuoti) + local nLastLay = 1 + for nIdx = #vLayIds, 1, -1 do + local nCrvGrp = EgtGetFirstNameInGroup( vLayIds[ nIdx], CONTOUR_GRP.."*") + local nPathGrpId = EgtGetFirstNameInGroup( nCrvGrp, PATH_GRP) or GDB_ID_NULL + if EgtGetGroupObjs( nPathGrpId) > 0 then + nLastLay = nIdx + break + end + end + + -- ciclo sui layer + local nOldId + 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 errore + EgtOutBox( 'Error in spiral vase : layer ' .. tostring( nIdx) .. ' has more than one toolpath', 'ToolPathCalc') + return false + end + + -- recupero il gruppo dei percorsi + local nPathGrpId = EgtGetFirstNameInGroup( vCrvGrpIds[1], PATH_GRP) + if not nPathGrpId then + EgtOutBox( 'Error missing paths', 'ToolPathCalc') + return false + else + EgtSetStatus( nPathGrpId, GDB_ST.OFF) + end + + -- recupero il gruppo dei percorsi utensile + local nTpathGrpId = EgtGetFirstNameInGroup( vCrvGrpIds[1], TOOLPATH_GRP) + if not nTpathGrpId then + nTpathGrpId = EgtGroup( vCrvGrpIds[1]) + EgtSetName( nTpathGrpId, TOOLPATH_GRP) + else + EgtEmptyGroup( nTpathGrpId) + end + + -- creo il percorso di lavoro + local vEntIds = EgtGetAllInGroup( nPathGrpId) + if #vEntIds > 1 then + EgtOutBox( 'Error in spiral vase : layer ' .. tostring( nIdx) .. ' has more than one toolpath', 'ToolPathCalc') + return false + end + + local nNewEntId = EgtCopyGlob( vEntIds[1] or GDB_ID.NULL, nTpathGrpId, GDB_IN.LAST_SON) + if nNewEntId then + + EgtModifyCurveExtrusion( nNewEntId, LayerParams.vtSlicing, GDB_RT.GLOB) + EgtSetInfo( nNewEntId, KEY_CRV_STRAND, LayerParams.dStrand) + if LayerParams.bInvert then + EgtInvertCurve( nNewEntId) + EgtSetInfo( nNewEntId, KEY_INVERTED_CRV, 1) + end + EgtSetColor( nNewEntId, EgtStdColor('GRAY')) + + -- sistemo il tratto finale del percorso precedente + if not bFirst then + local ptSOld = EgtSP( nOldId, GDB_ID.ROOT) + local ptEOld = EgtEP( nOldId, GDB_ID.ROOT) + + -- modifico il punto iniziale corrente per avvicinarmi il più possibile alla fine del percorso precedente + EgtChangeClosedCurveStartPoint( nNewEntId, ptEOld, GDB_RT.GLOB) + local ptNew = EgtSP( nNewEntId, GDB_ID.ROOT) + + -- a) verifico continuità tra i layers + if not AreSamePointApprox( ptEOld, ptNew) then + -- se il punto finale del percorso precedente non coincide con quello iniziale del percorso corrente modifico il tratto finale del percorso precedente che va alzato sin modo + -- che termini esattamente sull'inizio del percorso corrente + local _, _, dStartGuide = EgtPointCurveDist( ptSOld, nNewEntId, GDB_ID.ROOT) + local _, dEndGuide = EgtCurveDomain( nNewEntId) + local nGuideId = EgtCopyParamRange( nNewEntId, dStartGuide, dEndGuide, nTpathGrpId) + EgtModifyCurveExtrusion( nGuideId, LayerParams.vtSlicing, GDB_RT.GLOB) + + -- approssimo con tratti lineari imponendo lunghezza massima per migliorare spiralize + EgtApproxCurve( nGuideId, GDB_CA.SPECIAL_LINES, 0.01, s_dSpiralVaseMaxLen) + EgtApproxCurve( nOldId, GDB_CA.SPECIAL_LINES, 0.01, s_dSpiralVaseMaxLen) + + -- SpiralizeAlongGuide effettua una transizione dalla guida alla curva corrente, qui serve in contrario ( la curva deve arrivare sulla guida non partire da essa) + -- quindi bisogna lavorare con le curve invertite + EgtInvertCurve( nGuideId) + EgtInvertCurve( nOldId) + EgtSpiralizeCurveAlongGuide( nOldId, nGuideId) + EgtInvertCurve( nOldId) + EgtErase( nGuideId) + + -- approssimo la curva + EgtApproxCurve( nOldId, GDB_CA.ARCS, s_dApproxTol) + if LayerParams.bLinearApprox then + EgtApproxCurve( nOldId, GDB_CA.LINES, LayerParams.dLinearApproxTol) + end + -- forzo punti per garantire continuità + EgtModifyCurveStartPoint( nOldId, ptSOld, GDB_RT.GLOB) + EgtModifyCurveEndPoint( nOldId, ptNew, GDB_RT.GLOB) + end + + -- b) modifica graduale dell'altezza + EgtSpiralizeCurveAlongExtrusion( nOldId, LayerParams.dLayHeight) + end + + -- spostamento dell'altezza layer + local vtMove = LayerParams.dLayHeight * LayerParams.vtSlicing + EgtMove( nNewEntId, vtMove, GDB_RT.GLOB) + + -- approssimazione + if LayerParams.bLinearApprox then + local ptS = EgtSP( nNewEntId, GDB_ID.ROOT) + EgtApproxCurve( nNewEntId, GDB_CA.LINES, LayerParams.dLinearApproxTol) + if EgtCurveIsClosed( nNewEntId) then + EgtChangeClosedCurveStartPoint( nNewEntId, ptS, GDB_RT.GLOB) + end + end + + -- eventuale lead in + if bFirst then + bFirst = false + if LayerParams.nLeadInType ~= LEAD_TYPE.NONE then + EgtTrimCurveStartAtLen( nNewEntId, LayerParams.dOffsetLP) + local nLeadInCrv = AddLeadIn( nNewEntId, LayerParams, nTpathGrpId) + if nLeadInCrv and LayerParams.bLinearApprox then + EgtApproxCurve( nLeadInCrv, GDB_CA.LINES, LayerParams.dLinearApproxTol) + end + end + end + + -- separo l'ultimo tratto che farà da collegamento con il layer successivo + if nIdx ~= nLastLay then + local dTrimLen = EgtCurveLength( nNewEntId) - LayerParams.dSpiralVaseLen + if dTrimLen < GEO.EPS_SMALL then + -- se lunghezza di trim maggiore delle dimensioni forzo un valore accettabile + dTrimLen = 0.5 * EgtCurveLength( nNewEntId) + end + local dTrimPar = EgtCurveParamAtLength( nNewEntId, dTrimLen) + nOldId = EgtSplitCurveAtParam( nNewEntId, dTrimPar) end end @@ -2238,12 +2388,43 @@ local function SpiralVase( vLayIds, LayerParams) end end + return true +end + +--------------------------------------------------------------------- +local function SpiralVase( vLayIds, LayerParams) + + -- verifico quale modalità di spiral vase applicare : + -- 1) dSpiralVaseLen = 0 : la differenza in altezza tra due layers ( dLayHeight) viene distribuita uniformemente sull'intero percorso + -- 2) dSpiralVaseLen > 0 : la differenza in altezza tra due layers viene distribuita solo lungo il tratto finale di lunghezza dSpiralVaseLen + + if abs( LayerParams.dSpiralVaseLen) < GEO.EPS_SMALL then + if not SpiralVaseFull( vLayIds, LayerParams) then + return false + end + else + if not SpiralVasePartial( vLayIds, LayerParams) then + return false + end + end + + -- calcolo il box dei percorsi + local b3Tot = BBox3d() + local nLastTPath + for i = 1, #vLayIds do + local vCrvGrpIds = EgtGetNameInGroup( vLayIds[i], CONTOUR_GRP.."*") + local nTpathGrpId = EgtGetFirstNameInGroup( vCrvGrpIds[1], TOOLPATH_GRP) + nLastTPath = EgtGetLastInGroup( nTpathGrpId) + local b3Box = ComputeToolPathBox( nTpathGrpId) + b3Tot:Add( b3Box) + end + -- aggiungo uscita, coasting e wipe su ultima curva - AddSpiralVaseLeadOut( nOldId, LayerParams) + AddSpiralVaseLeadOut( nLastTPath, LayerParams) -- correzione in z AddZCorrection( b3Tot, LayerParams) - + return true end