diff --git a/LuaLibs/CalcToolPath.lua b/LuaLibs/CalcToolPath.lua index b4b40fd..a1e9731 100644 --- a/LuaLibs/CalcToolPath.lua +++ b/LuaLibs/CalcToolPath.lua @@ -401,9 +401,10 @@ local function AddLeadOut( nCrvId, LayerParams, nGrpId) end -------------------------------------------------------------------- -local function AddRetraction( nCrvId, vtSlicing, dCoastingLen, dWipeLen, dWipeDir) +local function AddRetraction( nCrvId, dCoastingLen, dWipeLen, dWipeDir) -- recupero i parametri per retrazione + local vtSlicing = EgtCurveExtrusion( nCrvId, GDB_ID.ROOT) 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 @@ -534,22 +535,22 @@ end local function AddRetractionOnLastCrv( nCrvId, nTpathGrpId, LayerParams, dCoastingLen, dWipeLen, dWipeDir) if LayerParams.nLeadOutType == LEAD_TYPE.NONE then - AddRetraction( nCrvId, LayerParams.vtSlicing, dCoastingLen, dWipeLen, dWipeDir) + AddRetraction( nCrvId, 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) + AddRetraction( nLeadOutId, dNewCoastingLen, dWipeLen, dWipeDir) else -- coinvolge parte dell'ultima shell crv local dNewCoastingLen = dCoastingLen - dLen - local nCoastingId = AddRetraction( nCrvId, LayerParams.vtSlicing, dNewCoastingLen, 0.0, dWipeDir) + local nCoastingId = AddRetraction( nCrvId, dNewCoastingLen, 0.0, dWipeDir) EgtAddCurveCompoCurve( nCoastingId, nLeadOutId) EgtSetInfo( nCoastingId, KEY_CLOSED_CRV, 0) -- wipe - AddRetraction( nCoastingId, LayerParams.vtSlicing, 0, dWipeLen, dWipeDir) + AddRetraction( nCoastingId, 0, dWipeLen, dWipeDir) end end end @@ -594,7 +595,7 @@ local function CalcShellsToolPath( vEntIds, nTpathGrpId, LayerParams) 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) + AddRetraction( vIds[i], LayerParams.dCoastingLen, LayerParams.dWipeLen, LayerParams.dWipeDir) end end -- sull'ultima curva gestione speciale per eventuale lead out @@ -678,7 +679,7 @@ local function CalcExtraShellToolPath( vEntIds, nTpathGrpId, LayerParams) dWipeDir = LayerParams.dWipeDir end - AddRetraction( vIds[i], LayerParams.vtSlicing, dCoastingLen, dWipeLen, dWipeDir) + AddRetraction( vIds[i], dCoastingLen, dWipeLen, dWipeDir) end end end @@ -905,7 +906,7 @@ local function CalcInfillToolPath( nInfillGrp, nTpathGrpId, LayerParams) for i = 1, #vIds do local nNext = EgtGetNext( vIds[i]) if not nNext or EgtGetName( nNext) ~= LINK_CRV then - AddRetraction( vIds[i], LayerParams.vtSlicing, LayerParams.dInfillCoasting, LayerParams.dInfillWipe, LayerParams.dInfillWipeDir) + AddRetraction( vIds[i], LayerParams.dInfillCoasting, LayerParams.dInfillWipe, LayerParams.dInfillWipeDir) end end end @@ -948,7 +949,7 @@ local function CalcSolidFillToolPath( nInfillGrp, nTpathGrpId, LayerParams) 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.dInfillCoasting, LayerParams.dInfillWipe, LayerParams.dInfillWipeDir) + AddRetraction( vIds[i], LayerParams.dInfillCoasting, LayerParams.dInfillWipe, LayerParams.dInfillWipeDir) end end end @@ -1071,7 +1072,7 @@ local function CalcAuxSolidsToolPath( nAuxSolidsGrp, nAuxSolidsPathGrp, nTpathGr for i = 1, #vIds do local nNextId = EgtGetNext( vIds[i]) if not nNextId or EgtGetName( nNextId) ~= LINK_CRV then - AddRetraction( vIds[i], LayerParams.vtSlicing, dCoastingLen, dWipeLen, dWipeDir) + AddRetraction( vIds[i], dCoastingLen, dWipeLen, dWipeDir) end end end @@ -1757,7 +1758,7 @@ local function AddRibsLeadOut( nCrv, nLoopsGrp, vtSlicing, nGrpTmp, bForceNoSoli -- se setto chiuso applico la stessa uscita delle shell if EgtCurveIsClosed( nCrv) then - return AddRetraction( nCrv, vtSlicing, dRibsLOCoasting, dRibsLOWipe, dRibsLOWipeAng) + return AddRetraction( nCrv, dRibsLOCoasting, dRibsLOWipe, dRibsLOWipeAng) end local ptE = EgtEP( nCrv, GDB_ID.ROOT) @@ -1844,7 +1845,7 @@ local function AddRibsLeadOut( nCrv, nLoopsGrp, vtSlicing, nGrpTmp, bForceNoSoli 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) + AddRetraction( nCrv, dRibsLOCoasting, dRibsLOWipe, dRibsLOWipeAng) end @@ -2015,7 +2016,7 @@ local function AddSpiralVaseLeadOut( nOldId, LayerParams) end AddRetractionOnLastCrv( nOldId, EgtGetParent( nOldId), LayerParams, LayerParams.dCoastingLen, LayerParams.dWipeLen, LayerParams.dWipeDir) else - AddRetraction( nOldId, LayerParams.vtSlicing, LayerParams.dCoastingLen, LayerParams.dWipeLen, LayerParams.dWipeDir) + AddRetraction( nOldId, LayerParams.dCoastingLen, LayerParams.dWipeLen, LayerParams.dWipeDir) end end @@ -2286,12 +2287,201 @@ local function SpiralVaseFull( vLayIds, LayerParams) end --------------------------------------------------------------------- -local function SpiralVasePartial( vLayIds, LayerParams) +local function SpiralVasePartialMultiPlanar( 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 + + -- piano di slicing + local vtSlicing = EgtGetInfo( vLayIds[nIdx], KEY_SLICE_DIR, 'v') + local ptSlicing = EgtGetInfo( vLayIds[nIdx], KEY_SLICE_POS, 'p') + + -- 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, 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) + -- proiezione ortogonale dei punti sul piano di slicing corrente + local ptSProj = ptSOld + ( ( ptSOld - ptSlicing) * vtSlicing) * vtSlicing + local ptEProj = ptEOld + ( ( ptEOld - ptSlicing) * vtSlicing) * vtSlicing + + -- modifico il punto iniziale corrente per avvicinarmi il più possibile alla fine del percorso precedente + EgtChangeClosedCurveStartPoint( nNewEntId, ptEProj, GDB_RT.GLOB) + local ptCurrStart = EgtSP( nNewEntId, GDB_ID.ROOT) + -- a) verifico continuità tra i layers + if not AreSamePointApprox( ptEProj, ptCurrStart) then + -- se i percorsi non sono in continuità modifico il tratto finale del percorso precedente in modo da farlo arrivare sul punto di inizio del percorso corrente + -- usando come guida la proiezione obliqua del percorso corrente sul piano precedente ( SpiralizeAlongGuide lavora con curve piane complanari) + + local nProjCrv = EgtCopyGlob( vEntIds[1], nPathGrpId) + -- conservo solo il sottotratto corrispondente a nOldId + local _, _, dStartGuide = EgtPointCurveDist( ptSProj, nProjCrv, GDB_ID.ROOT) + local _, _, dEndGuide = EgtPointCurveDist( ptEProj, nProjCrv, GDB_ID.ROOT) + EgtTrimCurveStartEndAtParam( nProjCrv, dStartGuide, dEndGuide) + -- proiezione sul piano precedente ( ptSlicingPrev, vtSlicingPrev) lungo vtSlicing + local vtSlicingPrev = EgtGetInfo( vLayIds[nIdx-1], KEY_SLICE_DIR, 'v') + local ptSlicingPrev = EgtGetInfo( vLayIds[nIdx-1], KEY_SLICE_POS, 'p') + LayerParams.dLayHeight * vtSlicingPrev + local _, dE = EgtCurveDomain( nProjCrv) + for dU = 0, dE do + local pt = EgtUP( nProjCrv, dU, GDB_ID.ROOT) + local dDist = ( pt - ptSlicingPrev) * vtSlicingPrev / ( vtSlicingPrev * vtSlicing) + EgtModifyCurveCompoJoint( nProjCrv, dU, pt - dDist * vtSlicing, GDB_RT.GLOB) + end + + -- approssimazione dei tratti per migliorare la qualità dello spiralize + EgtApproxCurve( nProjCrv, GDB_CA.SPECIAL_LINES, 0.01, s_dSpiralVaseMaxLen) + EgtApproxCurve( nOldId, GDB_CA.SPECIAL_LINES, 0.01, s_dSpiralVaseMaxLen) + + -- spiralize + EgtInvertCurve( nProjCrv) + EgtInvertCurve( nOldId) + EgtSpiralizeCurveAlongGuide( nOldId, nProjCrv) + EgtInvertCurve( nOldId) + end + + -- b) proiezione ortogonale graduale sul piano corrente + -- delta che va applicato ( è la distanza ortogonale del punto finale di nOldId dal piano del toolpath corrente) + local dDist = ( EgtEP( nOldId, GDB_ID.ROOT) - ( ptSlicing + LayerParams.dLayHeight * vtSlicing)) * vtSlicing + EgtApproxCurve( nOldId, GDB_CA.SPECIAL_LINES, 0.01, s_dSpiralVaseMaxLen) + local _, dE = EgtCurveDomain( nOldId) + local vDelta = {} + local dLen = EgtCurveLength( nOldId) + for dU = 0, dE do + local dCurrLen = EgtCurveLengthAtParam( nOldId, dU) + vDelta[dU] = abs( dDist) * dCurrLen / dLen + end + for dU = 0, dE do + local ptCurr = EgtUP( nOldId, dU, GDB_ID.ROOT) + EgtModifyCurveCompoJoint( nOldId, dU, ptCurr + vDelta[dU] * vtSlicing, GDB_RT.GLOB) + end + + -- c) approssimazione della 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, ptCurrStart + LayerParams.dLayHeight * vtSlicing, GDB_RT.GLOB) + end + + -- spostamento dell'altezza layer + local vtMove = LayerParams.dLayHeight * vtSlicing + EgtMove( nNewEntId, vtMove, GDB_RT.GLOB) + EgtCopyGlob( nNewEntId, nPathGrpId) + + -- 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 + + 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 nSlicingType = EgtGetInfo( s_nPartId, KEY_SLICING_TYPE, 'i') + if nSlicingType == SLICING_TYPE.MULTIPLANAR then + return SpiralVasePartialMultiPlanar( vLayIds, LayerParams) + end + + local bFirst = true -- individuo l'ultimo layer ( alcuni potrebbero essere vuoti) local nLastLay = 1 for nIdx = #vLayIds, 1, -1 do @@ -2307,9 +2497,9 @@ local function SpiralVasePartial( vLayIds, LayerParams) local nOldId for nIdx = 1, #vLayIds do - if nSlicingType == SLICING_TYPE.MULTIPLANAR then - LayerParams.vtSlicing = EgtGetInfo( vLayIds[nIdx], KEY_SLICE_DIR, 'v') - end + -- if nSlicingType == SLICING_TYPE.MULTIPLANAR then + -- LayerParams.vtSlicing = EgtGetInfo( vLayIds[nIdx], KEY_SLICE_DIR, 'v') + -- end -- cerco i gruppi di contorni local vCrvGrpIds = EgtGetNameInGroup( vLayIds[ nIdx], CONTOUR_GRP.."*") diff --git a/LuaLibs/RunCalcSolids.lua b/LuaLibs/RunCalcSolids.lua index e3e55ff..12985d0 100644 --- a/LuaLibs/RunCalcSolids.lua +++ b/LuaLibs/RunCalcSolids.lua @@ -15,6 +15,7 @@ local AMD = require( 'AddManData') -------------------------------------------------------------------- local s_dTol = 0.1 local s_nSimplifiedSection = 0 +local s_dMultiPlanarH = 0 --------------------------------------------------------------------- local function GetLayerParamsForSolidCalc( nPartId) @@ -39,10 +40,10 @@ local function CalcSectionParams( dStrand, dH) end ---------------------------------------------------------------------- -local function CreateStandardSolid( nCrvId, nSolidGrp, LayerParams, dStrand) - - local dBevelX, dBevelY = CalcSectionParams( dStrand, LayerParams.dLayHeight) - local nSrfId = EgtSurfTmRectSwept( nSolidGrp, dStrand, LayerParams.dLayHeight, dBevelX, dBevelY, nCrvId, GDB_RSCT.BEVEL, s_dTol) +local function CreateStandardSolid( nCrvId, nSolidGrp, dH, dStrand) + + local dBevelX, dBevelY = CalcSectionParams( dStrand, dH) + local nSrfId = EgtSurfTmRectSwept( nSolidGrp, dStrand, dH, dBevelX, dBevelY, nCrvId, GDB_RSCT.BEVEL, s_dTol) return nSrfId end @@ -115,10 +116,10 @@ local function CreateSpiralVaseCap( nSectId, vtDir, nSolidGrp) end ------------------------------------------------------------------------------- -local function CreateSpiralVaseSolid( nCrvId, nSolidGrp, LayerParams, dStrand) +local function CreateSpiralVaseSolid( nCrvId, nSolidGrp, vtSlicing, dH, dStrand) -- gruppo temporaneo per conti - local nGrpTmp = EgtGroup( nSolidGrp, Frame3d( ORIG(), LayerParams.vtSlicing, GDB_RT.GLOB)) + local nGrpTmp = EgtGroup( nSolidGrp, Frame3d( ORIG(), vtSlicing, GDB_RT.GLOB)) -- accorcio leggermente la curva per evitare problemi di inconsistent orientation nel solido local dLen = EgtCurveLength( nCrvId) @@ -128,28 +129,28 @@ local function CreateSpiralVaseSolid( nCrvId, nSolidGrp, LayerParams, dStrand) local vtS = EgtSV( nCrvId, GDB_ID.ROOT) local ptE = EgtEP( nCrvId, GDB_ID.ROOT) local vtE = EgtEV( nCrvId, GDB_ID.ROOT) - local dDelta = ( ptE - ptS) * LayerParams.vtSlicing + local dDelta = ( ptE - ptS) * vtSlicing -- se non è vero spiral vase, chiamo funzione standard if dDelta < GEO.EPS_SMALL then EgtErase( nGrpTmp) - return CreateStandardSolid( nCrvId, nSolidGrp, LayerParams, dStrand) + return CreateStandardSolid( nCrvId, nSolidGrp, dH, dStrand) end -- appiattisco la curva local nCrvCopy = EgtCopyGlob( nCrvId, nGrpTmp) - EgtModifyCurveExtrusion( nCrvCopy, LayerParams.vtSlicing, GDB_RT.GLOB) - EgtProjectCurveOnPlane( nCrvCopy, ptS, LayerParams.vtSlicing, GDB_RT.GLOB) + EgtModifyCurveExtrusion( nCrvCopy, vtSlicing, GDB_RT.GLOB) + EgtProjectCurveOnPlane( nCrvCopy, ptS, vtSlicing, GDB_RT.GLOB) EgtMergeCurvesInCurveCompo( nCrvCopy) EgtChangeClosedCurveStartPoint( nCrvCopy, ptS, GDB_RT.GLOB) -- calcolo la sezione iniziale local vtDir = EgtSV( nCrvCopy, GDB_ID.ROOT) - vtDir:rotate( LayerParams.vtSlicing, 90) - local nSectId = CreateSection( ptS, vtDir, dStrand, LayerParams.dLayHeight, LayerParams.vtSlicing, nGrpTmp) + vtDir:rotate( vtSlicing, 90) + local nSectId = CreateSection( ptS, vtDir, dStrand, dH, vtSlicing, nGrpTmp) -- creo la sezione finale local vtDir2 = EgtEV( nCrvCopy, GDB_ID.ROOT) - vtDir2:rotate( LayerParams.vtSlicing, 90) - local nSectE = CreateSection( ptE, vtDir2, dStrand, LayerParams.dLayHeight, LayerParams.vtSlicing, nGrpTmp) + vtDir2:rotate( vtSlicing, 90) + local nSectE = CreateSection( ptE, vtDir2, dStrand, dH, vtSlicing, nGrpTmp) -- creo il solido aperto (tubo) local vCrvs = {} @@ -162,8 +163,8 @@ local function CreateSpiralVaseSolid( nCrvId, nSolidGrp, LayerParams, dStrand) EgtErase( nGrpTmp) return nil end - local dMove = ( ptRef - ptS) * LayerParams.vtSlicing - EgtMove( vCrvs[i+1], LayerParams.vtSlicing * dMove, GDB_RT.GLOB) + local dMove = ( ptRef - ptS) * vtSlicing + EgtMove( vCrvs[i+1], vtSlicing * dMove, GDB_RT.GLOB) EgtSpiralizeCurveAlongExtrusion( vCrvs[i+1], dDelta) -- modifico la curva per congiungerla ai caps @@ -202,11 +203,11 @@ local function CreateSpiralVaseSolid( nCrvId, nSolidGrp, LayerParams, dStrand) end -------------------------------------------------------------------------------------- -local function CreateSolid( nCrvId, nSolidGrp, LayerParams, dStrand) +local function CreateSolid( nCrvId, nSolidGrp, LayerParams, dH, dStrand) if LayerParams.bSpiralVase then - return CreateSpiralVaseSolid( nCrvId, nSolidGrp, LayerParams, dStrand) + return CreateSpiralVaseSolid( nCrvId, nSolidGrp, LayerParams.vtSlicing, dH, dStrand) else - return CreateStandardSolid( nCrvId, nSolidGrp, LayerParams, dStrand) + return CreateStandardSolid( nCrvId, nSolidGrp, dH, dStrand) end end @@ -241,10 +242,10 @@ local function CreateDirectionArrow( nCrvId, nSolidGrp, vtSlicing, dStrand, nLay end --------------------------------------------------------------------- -local function CreateRecursiveSolid( nCrvId, vSurfs, nSolidGrp, LayerParams, dStrand) +local function CreateRecursiveSolid( nCrvId, vSurfs, nSolidGrp, LayerParams, dH, dStrand) -- tento la creazione del solido - local nSurf = CreateSolid( nCrvId, nSolidGrp, LayerParams, dStrand - 50 * GEO.EPS_SMALL) + local nSurf = CreateSolid( nCrvId, nSolidGrp, LayerParams, dH, dStrand - 50 * GEO.EPS_SMALL) if nSurf then EgtErase( nCrvId) table.insert( vSurfs, nSurf) @@ -264,16 +265,16 @@ local function CreateRecursiveSolid( nCrvId, vSurfs, nSolidGrp, LayerParams, dSt EgtErase( nCrvId) return false end - local bOk = CreateRecursiveSolid( nCrvId, vSurfs, nSolidGrp, LayerParams, dStrand) - bOk = bOk and CreateRecursiveSolid( nCrvSplit, vSurfs, nSolidGrp, LayerParams, dStrand) + local bOk = CreateRecursiveSolid( nCrvId, vSurfs, nSolidGrp, LayerParams, dH, dStrand) + bOk = bOk and CreateRecursiveSolid( nCrvSplit, vSurfs, nSolidGrp, LayerParams, dH, dStrand) return bOk end end --------------------------------------------------------------------- -local function CreateSolidFromCurve( nCrvId, nSolidGrp, LayerParams, nLayer) +local function CreateSolidFromCurve( nCrvId, nSolidGrp, LayerParams, nLayer, dLayerH) - local nType = EgtGetInfo( nCrvId, KEY_TYPE, 'i') + local nType = EgtGetInfo( nCrvId, KEY_TYPE, 'i') if nType == TYPE.WIPE then return true end -- scelta del colore local Color = EgtStdColor( 'GRAY') @@ -292,7 +293,10 @@ local function CreateSolidFromCurve( nCrvId, nSolidGrp, LayerParams, nLayer) elseif nType == TYPE.AUX_SOLID then Color = EgtStdColor( 'AQUA') end + + -- parametri della passata local dStrand = EgtGetInfo( nCrvId, KEY_CRV_STRAND, 'd') or LayerParams.dStrand + local dH = dLayerH or LayerParams.dLayHeight local nCopyId = EgtCopyGlob( nCrvId, nSolidGrp) local nId = GDB_ID.NULL @@ -319,11 +323,11 @@ local function CreateSolidFromCurve( nCrvId, nSolidGrp, LayerParams, nLayer) local bOk = true for nInd = 0, nParts - 1 do local nGuideId = nId + nInd - local nSrfId = CreateSolid( nGuideId, nSolidGrp, LayerParams, dStrand - 5 * GEO.EPS_SMALL) + local nSrfId = CreateSolid( nGuideId, nSolidGrp, LayerParams, dH, dStrand - 5 * GEO.EPS_SMALL) if not nSrfId then EgtOutLog( 'Warning : CreateSolid failed '.. '(layer '..tostring( nLayer)..', curve '..tostring( nCrvId)..')') -- ritento con strand più piccolo - nSrfId = CreateSolid( nGuideId, nSolidGrp, LayerParams, dStrand - 50 * GEO.EPS_SMALL) + nSrfId = CreateSolid( nGuideId, nSolidGrp, LayerParams, dH, dStrand - 50 * GEO.EPS_SMALL) if not nSrfId then EgtOutLog( 'Warning : CreateSolid_1 failed '.. '(layer '..tostring( nLayer)..', curve '..tostring( nCrvId)..')') @@ -335,9 +339,9 @@ local function CreateSolidFromCurve( nCrvId, nSolidGrp, LayerParams, nLayer) local bOk1 = EgtTrimCurveEndAtLen( nCopyId, LEN_TRIM) local bOk2 = EgtAddCurveCompoCurve( nGuideId, nCopyId) local bOk3 = EgtTrimCurveStartAtLen( nGuideId + 1, LEN_TRIM) - nSrfId = CreateSolid( nGuideId, nSolidGrp, LayerParams, dStrand - 5 * GEO.EPS_SMALL) + nSrfId = CreateSolid( nGuideId, nSolidGrp, LayerParams, dH, dStrand - 5 * GEO.EPS_SMALL) if not nSrfId then - nSrfId = CreateSolid( nGuideId, nSolidGrp, LayerParams, dStrand - 50 * GEO.EPS_SMALL) + nSrfId = CreateSolid( nGuideId, nSolidGrp, LayerParams, dH, dStrand - 50 * GEO.EPS_SMALL) end end end @@ -352,7 +356,7 @@ local function CreateSolidFromCurve( nCrvId, nSolidGrp, LayerParams, nLayer) EgtRelocateGlob( nGuideId, nSolidGrp) local vSurfs = {} - local bOk = CreateRecursiveSolid( nGuideId, vSurfs, nSolidGrp, LayerParams, dStrand) + local bOk = CreateRecursiveSolid( nGuideId, vSurfs, nSolidGrp, LayerParams, dH, dStrand) if #vSurfs > 0 then nSrfId = EgtSurfTmByTriangles( nSolidGrp, vSurfs) end @@ -377,6 +381,156 @@ local function CreateSolidFromCurve( nCrvId, nSolidGrp, LayerParams, nLayer) return bOk end +-------------------------------------------------------------------- +------------------------- MULTIPLANAR ------------------------------ +-------------------------------------------------------------------- +local function CreateMultiPlanarSolids( vIds, nSolidGrpId, LayerParams, nLayerId) + + -- creo solidi standard con spessore massimo ammesso ( tranne nel primo layer che viene fatto ad altezza costante) + local nSliceNbr = EgtGetInfo( nLayerId, KEY_SLICE_NBR, 'i') + local dH = EgtIf( nSliceNbr == 1, LayerParams.dLayHeight, s_dMultiPlanarH) + for i = 1, #vIds do + CreateSolidFromCurve( vIds[i], nSolidGrpId, LayerParams, nSliceNbr, dH) + end + + -- deformo i solidi per rispettare l'altezza reale della passata + if nSliceNbr > 1 then + local ptSlicing = EgtGetInfo( nLayerId, KEY_SLICE_POS, 'p') + LayerParams.vtSlicing * LayerParams.dLayHeight + local nPrevLayerId = EgtGetPrev( nLayerId) + local vtSlicingPrev = EgtGetInfo( nPrevLayerId, KEY_SLICE_DIR, 'v') + local ptSlicingPrev = EgtGetInfo( nPrevLayerId, KEY_SLICE_POS, 'p') + vtSlicingPrev * LayerParams.dLayHeight + + local vSolids = EgtGetAllInGroup( nSolidGrpId) + for i = 1, #vSolids do + local nVertexCnt = EgtSurfTmVertexCount( vSolids[i]) + for j = 0, nVertexCnt - 1 do + local ptVertex = EgtSurfTmGetVertex( vSolids[i], j, GDB_RT.GLOB) + -- distanza dal piano di slicing corrente e precedente lungo vtSlicing + local dDistCurr = abs( ( ptVertex - ptSlicing) * LayerParams.vtSlicing) + local dDistPrev = ( ptVertex - ptSlicingPrev) * vtSlicingPrev / ( vtSlicingPrev * LayerParams.vtSlicing) + -- calcolo la nuova posizione sapendo che l'altezza dello strand passa da s_dMultiPlanarH a dNewH + local dNewH = dDistCurr + dDistPrev + local dDelta = dDistCurr - dDistCurr * dNewH / s_dMultiPlanarH + local ptNew = ptVertex + dDelta * LayerParams.vtSlicing + EgtSurfTmMoveVertex( vSolids[i], j, ptNew, GDB_RT.GLOB, ( j == nVertexCnt - 1)) + end + end + end +end + +--------------------------------------------------------------------- +local function CreatePartialSpiralVaseMultiPlanarSolids( vIds, nSolidGrpId, LayerParams, nLayerId) + + -- 1) la prima curva è solido multiplanare standard + CreateMultiPlanarSolids( { vIds[1]}, nSolidGrpId, LayerParams, nLayerId) + + -- 2) la seconda curva è il tratto che si alza fino al layer successivo + local dStrand = EgtGetInfo( vIds[2], KEY_CRV_STRAND, 'd') or LayerParams.dStrand + -- gruppo temporaneo per conti + local nGrpTmp = EgtGroup( nSolidGrpId, Frame3d( ORIG(), LayerParams.vtSlicing, GDB_RT.GLOB)) + + -- appiattisco la curva ( proiezione obliqua sul piano corrente lungo vtSlicing del piano successivo) + local nNextLayerId = EgtGetNext( nLayerId) + local vtSlicingNext = EgtGetInfo( nNextLayerId, KEY_SLICE_DIR, 'v') + local ptSlicing = EgtGetInfo( nLayerId, KEY_SLICE_POS, 'p') + LayerParams.dLayHeight * LayerParams.vtSlicing + local nProjCrv = EgtCopyGlob( vIds[2], nGrpTmp) + local _, dE = EgtCurveDomain( nProjCrv) + for dU = 0, dE do + local ptCurr = EgtUP( nProjCrv, dU, GDB_ID.ROOT) + local dDist = ( ptCurr - ptSlicing) * LayerParams.vtSlicing / ( vtSlicingNext * LayerParams.vtSlicing) + EgtModifyCurveCompoJoint( nProjCrv, dU, ptCurr - dDist * vtSlicingNext, GDB_RT.GLOB) + end + + -- calcolo la sezione iniziale + local ptS = EgtSP( vIds[2], GDB_ID.ROOT) + local ptE = EgtEP( vIds[2], GDB_ID.ROOT) + local vtDir = EgtSV( nProjCrv, GDB_ID.ROOT) + vtDir:rotate( LayerParams.vtSlicing, 90) + local nSectId = CreateSection( ptS, vtDir, dStrand, s_dMultiPlanarH, LayerParams.vtSlicing, nGrpTmp) + -- creo la sezione finale + local vtDir2 = EgtEV( nProjCrv, GDB_ID.ROOT) + vtDir2:rotate( LayerParams.vtSlicing, 90) + local nSectE = CreateSection( ptE, vtDir2, dStrand, s_dMultiPlanarH, LayerParams.vtSlicing, nGrpTmp) + + -- creo il solido aperto ( tubo) + local dMaxDist = ( EgtEP( vIds[2], GDB_ID.ROOT) - ptSlicing) * LayerParams.vtSlicing / ( vtSlicingNext * LayerParams.vtSlicing) + local vCrvs = {} + local _, dParE = EgtCurveDomain( nSectId) + for i = 0, dParE do + local ptRef = EgtUP( nSectId, i, GDB_ID.ROOT) + local dOffs = ( ptS - ptRef) * vtDir + vCrvs[i+1] = EgtOffsetCurveAdv( nProjCrv, dOffs) + if not vCrvs[i+1] or vCrvs[i+1] == GDB_ID.NULL then + EgtErase( nGrpTmp) + return false + end + + -- proiezione obliqua "graduale" + EgtApproxCurve( vCrvs[i+1], GDB_CA.SPECIAL_LINES, 0.01) + local _, dE = EgtCurveDomain( vCrvs[i+1]) + local dLen = EgtCurveLength( vCrvs[i+1]) + local vDelta = {} + for dU = 0, dE do + local dCurrLen = EgtCurveLengthAtParam( vCrvs[i+1], dU) + vDelta[dU] = dMaxDist * dCurrLen / dLen + end + for dU = 0, dE do + local ptCurr = EgtUP( vCrvs[i+1], dU, GDB_ID.ROOT) + EgtModifyCurveCompoJoint( vCrvs[i+1], dU, ptCurr + vDelta[dU] * vtSlicingNext, GDB_RT.GLOB) + end + + local dMove = ( ptRef - ptS) * LayerParams.vtSlicing + EgtMove( vCrvs[i+1], LayerParams.vtSlicing * dMove, GDB_RT.GLOB) + end + local vSurfs = {} + for i = 1, #vCrvs - 1 do + vSurfs[i] = EgtSurfTmRuled( nGrpTmp, vCrvs[i], vCrvs[i+1], GDB_RUL.MINDIST, s_dTol) + if not vSurfs[i] or vSurfs[i] == GDB_ID.NULL then + EgtErase( nGrpTmp) + return nil + end + end + local nSrfId = EgtSurfTmByTriangles( nSolidGrpId, vSurfs) + + -- creazione del mezzo disco iniziale + local nCap1 = CreateSpiralVaseCap( nSectId, - EgtSV( vIds[2], GDB_ID.ROOT), nSolidGrpId) + -- creazione del mezzo disco finale + local nCap2 = CreateSpiralVaseCap( nSectE, EgtEV( vIds[2], GDB_ID.ROOT), nSolidGrpId) + EgtInvertSurf( nCap2) + + -- solido finale + local nSolidId = EgtSurfTmByTriangles( nSolidGrpId, { nSrfId, nCap1, nCap2}) + + -- limito il solido al piano di slicing precedente + local ptPrev + local vtPrev + if EgtGetInfo( nLayerId, KEY_SLICE_NBR, 'i') == 1 then + ptPrev = ptSlicing - LayerParams.dLayHeight * LayerParams.vtSlicing + vtPrev = LayerParams.vtSlicing + else + local nPrevLayId = EgtGetPrev( nLayerId) + vtPrev = EgtGetInfo( nPrevLayId, KEY_SLICE_DIR, 'v') + ptPrev = EgtGetInfo( nPrevLayId, KEY_SLICE_POS, 'p') + vtPrev * LayerParams.dLayHeight + end + + local nVertexCnt = EgtSurfTmVertexCount( nSolidId) + for j = 0, nVertexCnt - 1 do + local ptVertex = EgtSurfTmGetVertex( nSolidId, j, GDB_RT.GLOB) + local _, ptMinDist = EgtPointCurveDist( ptVertex, vIds[2], GDB_ID.ROOT) + local dDistCrv = abs( ( ptVertex - ptMinDist) * LayerParams.vtSlicing) + local dDistPlane = ( ptVertex - ptPrev) * vtPrev / ( vtPrev * LayerParams.vtSlicing) + -- calcolo la nuova posizione sapendo che l'altezza dello strand passa da s_dMultiPlanarH a dNewH + local dNewH = dDistCrv + dDistPlane + local dDelta = dDistCrv - dDistCrv * dNewH / s_dMultiPlanarH + local ptNew = ptVertex + dDelta * LayerParams.vtSlicing + EgtSurfTmMoveVertex( nSolidId, j, ptNew, GDB_RT.GLOB, ( j == nVertexCnt - 1)) + end + + EgtSetColor( nSolidId, EgtStdColor( 'TEAL')) + EgtErase( nGrpTmp) + return true +end + --------------------------------------------------------------------- function RunCalcSolids.Exec() @@ -414,16 +568,18 @@ function RunCalcSolids.Exec() -- recupero i parametri necessari al calcolo dei solidi local LayerParams = GetLayerParamsForSolidCalc( nPartId) + + -- se slicing multiplanare considero come altezza standard quella massima ammessa + if nSlicingType == SLICING_TYPE.MULTIPLANAR then + local dMaxFactor = EgtGetNumberFromIni( '3dPrinting', KEY_MAX_STRANDH_FACTOR, 2, EgtGetIniFile()) + s_dMultiPlanarH = min( dMaxFactor, 5) * LayerParams.dLayHeight + end for nIdx = 1, #vLayIds do - if nSlicingType == SLICING_TYPE.MULTIPLANAR then - LayerParams.vtSlicing = EgtGetInfo( vLayIds[nIdx], KEY_SLICE_DIR, 'v') - end - -- flag di interruzione perchè trovati solidi già ok local bSolidsOk = false - -- indice layer (per log) + -- indice layer ( per log) local nLayer = EgtGetInfo( vLayIds[ nIdx], KEY_SLICE_NBR, 'i') -- scorro tutti i gruppi di contorni local nCrvGrpId = EgtGetFirstNameInGroup( vLayIds[ nIdx], CONTOUR_GRP.."*") or GDB_ID.NULL @@ -442,10 +598,31 @@ function RunCalcSolids.Exec() nSolidGrpId = EgtGroup( nCrvGrpId) EgtSetName( nSolidGrpId, SOLID_GRP) EgtSetLevel( nSolidGrpId, GDB_LV.TEMP) + local vIds = EgtGetAllInGroup( nTPathGrpId) - -- spiral vase - if LayerParams.bSpiralVase then + -- multiplanare + if nSlicingType == SLICING_TYPE.MULTIPLANAR then + LayerParams.vtSlicing = EgtGetInfo( vLayIds[nIdx], KEY_SLICE_DIR, 'v') + + if LayerParams.bSpiralVase then + local dTransitionLen = EgtGetInfo( nPartId, KEY_SPIRAL_VASE_LEN, 'd') or 0 + if dTransitionLen < GEO.EPS_SMALL then + -- TO DO + else + if nIdx == #vLayIds then + -- ultimo layer non ha tratto finale rialzato quindi è un multiplanare standard + CreateMultiPlanarSolids( vIds, nSolidGrpId, LayerParams, vLayIds[nIdx]) + else + CreatePartialSpiralVaseMultiPlanarSolids( vIds, nSolidGrpId, LayerParams, vLayIds[nIdx]) + end + end + else + CreateMultiPlanarSolids( vIds, nSolidGrpId, LayerParams, vLayIds[nIdx]) + end + + -- slicing standard spiral vase + elseif LayerParams.bSpiralVase then -- i tratti di ingresso, uscita e quelli a quota costante vanno gestiti singolarmente, quelli a quota variabile vanno concatenati local vChainedIds = {} local vTmpIds = {} @@ -482,7 +659,7 @@ function RunCalcSolids.Exec() end end - -- caso standard + -- slicing standard else for i = 1, #vIds do CreateSolidFromCurve( vIds[i], nSolidGrpId, LayerParams, nLayer) diff --git a/LuaLibs/RunPrepareExport.lua b/LuaLibs/RunPrepareExport.lua index 014598e..bf061c8 100644 --- a/LuaLibs/RunPrepareExport.lua +++ b/LuaLibs/RunPrepareExport.lua @@ -100,7 +100,7 @@ local function CalcCurves( nSliceId, nDestGrp, vtSlicing, dStrandBase) end ------------------------------------------------------------------ -local function CalcSpiralVase( nSliceId, nDestGrp) +local function GetSolids( nSliceId, nDestGrp) -- scorro tutti i gruppi di curve local vCrvs = EgtGetNameInGroup( nSliceId, CONTOUR_GRP .. '*') @@ -160,6 +160,7 @@ function RunPrepareExport.Exec() EgtSetInfo( nPnt, "SlicingDir", vtSlicing) local bSpiralVase = EgtGetInfo( nPartId, KEY_SPIRAL_VASE, 'b') or false EgtSetInfo( nPnt, KEY_SPIRAL_VASE, bSpiralVase) + local nSlicingType = EgtGetInfo( nPartId, KEY_SLICING_TYPE, 'i') -- recupero lo strand dai parametri generale nel caso non fosse definito sulle singole curve local dStrandBase = EgtGetInfo( nPartId, KEY_STRAND, 'd') or 0 @@ -195,8 +196,9 @@ function RunPrepareExport.Exec() EgtSetName( nDestGrp, EgtGetName( vSlices[i])) EgtSetStatus( nDestGrp, GDB_ST.OFF) - if bSpiralVase then - CalcSpiralVase( vSlices[i], nDestGrp) + -- se multiplanare o spiral vase esporto direttamente i solidi altrimenti esporto le curve che verranno estruse nel visualizzatore + if nSlicingType == SLICING_TYPE.MULTIPLANAR or bSpiralVase then + GetSolids( vSlices[i], nDestGrp) else CalcCurves( vSlices[i], nDestGrp, vtSlicing, dStrandBase) end