From a7c7bd63edff26686bf98894bc884035a04731a9 Mon Sep 17 00:00:00 2001 From: SaraP Date: Tue, 21 Mar 2023 12:14:39 +0100 Subject: [PATCH] 3dPrinting : - migliorie nei riempimenti a zigzag per SolidFill - gestione SolidFill con buchi. --- LuaLibs/CalcPaths.lua | 223 +++++++++++++++++++++++++----------------- 1 file changed, 134 insertions(+), 89 deletions(-) diff --git a/LuaLibs/CalcPaths.lua b/LuaLibs/CalcPaths.lua index 5347226..084277e 100644 --- a/LuaLibs/CalcPaths.lua +++ b/LuaLibs/CalcPaths.lua @@ -226,24 +226,6 @@ local function VerifyPath( nCrvId, dStrand, vtSlicing, nGrp) return true end -------------------------------------------------------------------- -local function ComputeTrimSurfWithOverlaps( vIds, nSrfBase, sKeyOverlap, dStrand, nGrp, vtSlicing) - - -- per ogni overlap creo le superfici con cui fare i trim - local vSurfOffs = {} - for i = 1, #vIds do - local nOverlap = EgtGetInfo( vIds[i], sKeyOverlap, 'i') - if not vSurfOffs[nOverlap] then - local dNewOffs = nOverlap / 100 * dStrand - local bOk, bExists, nSrfOffs = ComputeSurfOffset( nSrfBase, nGrp, dNewOffs, vtSlicing) - if bOk then - vSurfOffs[nOverlap] = nSrfOffs - end - end - end - return vSurfOffs -end - -------------------------------------------------------------------- --------------------- RIEMPIMENTI PIENI ---------------------------- -------------------------------------------------------------------- @@ -369,71 +351,109 @@ local function ComputeOffsetInfill( nSrf, dStrand, vtSlicing, sName, nType, vPtS end --------------------------------------------------------------------------------- -local function ComputeZigZagInfill( nSrf, dStrand, vtSlicing, sName, nType, vPtStart, nGrp) - - local nChunk = EgtSurfFrChunkCount( nSrf) - if nChunk == 0 then return end +------------------------------------------------------------------ +local function FindOptimalZigZagDirection( nSrfId, nBorderSurf, dStrand, nGrp, frLoc) - local nCopySrf = EgtCopyGlob( nSrf, nGrp) - if EgtSurfFrChunkCount( nSrf) == 0 then return end + -- come direzione ottimale scelgo quella del lato più vicino al bordo oppure quella del + -- lato più lungo nel caso in cui i lati fossero tutti sufficientemente lontani ( distanza > dStrand) dal bordo - local nFirst, nCnt = EgtExplodeSurf( nCopySrf) - local frLoc = Frame3d( ORIG(), vtSlicing) - local vIds = {} - for nId = nFirst, nFirst + nCnt - 1 do - local nGrpTmp = EgtGroup( nGrp, frLoc, GDB_RT.GLOB) - - -- recupero outer curve - local nCrvGrpId = EgtGetParent( nGrp) - local nOuterCrv = EgtGetFirstNameInGroup( nCrvGrpId, OUTER_CRV) - local nCopyOuterCrv = EgtCopyGlob( nOuterCrv, nGrpTmp) + local nGrpTmp = EgtGroup( nGrp, frLoc, GDB_RT.GLOB) -- gruppo temporaneo per i conti + local dTol = 1 + GEO.EPS_SMALL + + -- recupero i contorni della curva di bordo + local vBorderIds = GetPathsFromSurf( nBorderSurf, 'TmpBorder', 0, nGrpTmp) + + -- recupero tutti i lati della superficie da riempire + local vCrvIds = GetPathsFromSurf( nSrfId, 'Tmp', 0, nGrpTmp) + local nId, nCnt = EgtExplodeCurveCompo( vCrvIds[1]) + + -- individuo i lati a distanza minima dal bordo tra cui cercare quello a lunghezza massima + local vCheckIds = {} + local vAllIds = {} + local dMinDist = GEO.INFINITO + for i = nId, nId + nCnt - 1 do - -- cerco il lato più lungo - local vCrvIds = GetPathsFromSurf( nId, 'Tmp', nType, nGrpTmp) - local dMaxLen = - GEO.INFINITO - local dDist = GEO.INFINITO - local vtDir - - for j = 1, #vCrvIds do - local nId, nCnt = EgtExplodeCurveCompo( vCrvIds[j]) - - -- cerco il lato più lungo - for k = nId, nId + nCnt - 1 do - local dCurrLen = EgtCurveLength( k) - if dCurrLen > dMaxLen + GEO.EPS_SMALL then - dMaxLen = dCurrLen - end - end - -- tra i lati più lunghi scelgo quello più vicino al bordo - for k = nId, nId + nCnt - 1 do - local dCurrLen = EgtCurveLength( k) - if abs( dMaxLen - dCurrLen) < 10 then - local dCurrDist = EgtPointCurveDist( EgtMP( k), nCopyOuterCrv) - if dCurrDist < dDist + 10 * GEO.EPS_SMALL then - vtDir = EgtSV( k) - dDist = dCurrDist - end + -- trovo la distanza minima dalle curve di bordo + local dDist + if #vBorderIds == 1 then + dDist = EgtPointCurveDist( EgtMP( i), vBorderIds[1]) + else + dDist = GEO.INFINITO + for j = 1, #vBorderIds do + local dCurrDist = EgtPointCurveDist( EgtMP( i), vBorderIds[j]) + if dCurrDist < dDist then + dDist = dCurrDist end end end - EgtErase( nGrpTmp) + -- se tratto sufficientemente vicino al bordo verifico se a distanza minima ( entro tolleranza dTol) + if dDist < dStrand + GEO.EPS_SMALL then + if abs( dDist - dMinDist) < dTol then + table.insert( vCheckIds, i) + elseif dDist < dMinDist - dTol then + dMinDist = dDist + vCheckIds = {i} + end + end + + table.insert( vAllIds, i) + end + + -- se non ci sono curve sufficientemente vicine al bordo allora cerco il più lungo tra tutti i lati indipendentemente dalla loro distanza dal bordo + if #vCheckIds == 0 then + vCheckIds = vAllIds + end + + -- cerco il lato più lungo tra quelli selezionati + local vtDir + if #vCheckIds == 1 then + vtDir = EgtSV( vCheckIds[1]) + else + local dLen = - GEO.INFINITO + for k = 1, #vCheckIds do + local dCurrLen = EgtCurveLength( vCheckIds[k]) + if dCurrLen > dLen + GEO.EPS_SMALL then + dLen = dCurrLen + vtDir = EgtSV( vCheckIds[k]) + end + end + end + + EgtErase( nGrpTmp) + return vtDir +end + +-------------------------------------------------------------------- +local function ComputeZigZagInfill( nSrf, dStrand, vtSlicing, sName, nType, vPtStart, nGrp, nBorderSurf) + + if EgtSurfFrChunkCount( nSrf) == 0 then return end + + local nCopySrf = EgtCopyGlob( nSrf, nGrp) + local frLoc = Frame3d( ORIG(), vtSlicing) + + -- analizzo tutti i chunk della superifice da riempire + local nFirst, nSrfCnt = EgtExplodeSurf( nCopySrf) + local vIds = {} + for nSrfId = nFirst, nFirst + nSrfCnt - 1 do + + -- trovo la direzione ottimale per la svuotatura in frLoc + local vtDir = FindOptimalZigZagDirection( nSrfId, nBorderSurf, dStrand, nGrp, frLoc) local _, _, dAng = SphericalFromVector( vtDir) vtDir:toGlob( frLoc) - local nInd, nCnt = EgtGetSurfFrZigZagInfill( nId, nGrp, dStrand, dAng, false, false) - if not nInd then return end - for j = nInd, nInd + nCnt - 1 do - EgtSetName( j, sName) - EgtSetInfo( j, KEY_TYPE, nType) - EgtSetInfo( j, KEY_ZIG_ZAG_DIR, vtDir) - EgtSetInfo( j, KEY_ZIG_ZAG_INFILL, 1) - EgtModifyCurveExtrusion( j, vtSlicing, GDB_RT.GLOB) - table.insert( vIds, j) + local nInd, nCnt = EgtGetSurfFrZigZagInfill( nSrfId, nGrp, dStrand, dAng, false, false) + if nInd then + for j = nInd, nInd + nCnt - 1 do + EgtSetName( j, sName) + EgtSetInfo( j, KEY_TYPE, nType) + EgtSetInfo( j, KEY_ZIG_ZAG_DIR, vtDir) + EgtSetInfo( j, KEY_ZIG_ZAG_INFILL, 1) + EgtModifyCurveExtrusion( j, vtSlicing, GDB_RT.GLOB) + table.insert( vIds, j) + end end - local vtS = EgtSV( nInd) - EgtErase( nId) + EgtErase( nSrfId) end end @@ -1951,6 +1971,25 @@ end -------------------------------------------------------------------- ------------------ AUX SOLIDS ------------------------------------- -------------------------------------------------------------------- +-------------------------------------------------------------------- +local function ComputeTrimSurfWithOverlapsForAuxSolids( vIds, nSrfBase, dStrand, nGrp, vtSlicing) + + -- per ogni valore di overlap creo le superfici con cui fare i trim + local vSurfOffs = {} + for i = 1, #vIds do + local nOverlap = EgtGetInfo( vIds[i][1], KEY_AUX_SOLIDS_OVERLAP, 'i') + if not vSurfOffs[nOverlap] then + local dNewOffs = nOverlap / 100 * dStrand + local bOk, bExists, nSrfOffs = ComputeSurfOffset( nSrfBase, nGrp, dNewOffs, vtSlicing) + if bOk then + vSurfOffs[nOverlap] = nSrfOffs + end + end + end + return vSurfOffs +end + +----------------------------------------------------------------------- local function UpdateTrimSurfWithAuxSolidsOffset( nSrfSolid, nSrfBase, dStrand, nCrvGrp, vtSlicing) -- offset della superifice del solido @@ -2033,10 +2072,11 @@ end local function AddExtraZigZag( nSrf, sName, dStrand, vtSlicing, nGrp, nSrfTrim) local vIds = EgtGetNameInGroup( nGrp, sName) + if not vIds then return end local vtDir = EgtSV( vIds[1], GDB_ID.ROOT) local vtYLoc = vtSlicing ^ vtDir - local nOuterLoop = EgtExtractSurfFrChunkLoops( nSrf, 0, nGrp) + local nOuterLoop, nCnt = EgtExtractSurfFrChunkLoops( nSrf, 0, nGrp) for i = 1, #vIds do local _, dParE = EgtCurveDomain( vIds[i]) @@ -2045,7 +2085,7 @@ local function AddExtraZigZag( nSrf, sName, dStrand, vtSlicing, nGrp, nSrfTrim) local nExtraCrv = EgtLine( nGrp, ptS, ptE, GDB_RT.GLOB) -- verifico se la linea aggiuntiva serve local dDist = EgtPointCurveDist( EgtMP( nExtraCrv), nOuterLoop) - if dDist < dStrand - 1 then + if dDist < 0.5 * dStrand - 100 * GEO.EPS_SMALL then -- verifico se si trova nella regione ammissibile if EgtCurveWithRegionClassify( nExtraCrv, nSrfTrim) == GDB_CRC.IN then EgtInvertCurve( nExtraCrv) @@ -2056,14 +2096,24 @@ local function AddExtraZigZag( nSrf, sName, dStrand, vtSlicing, nGrp, nSrfTrim) EgtErase( nExtraCrv) end - EgtErase( nOuterLoop) + for nId = nOuterLoop, nOuterLoop + nCnt - 1 do + EgtErase( nId) + end + end -------------------------------------------------------------------- local function CalcAuxSolidsPaths( nSliceGrp, nSolidGrp, LayerParams, vPtStart) - -- recupero i solidi ausiliari - local vSolidIds = EgtGetAllInGroup( nSolidGrp) + -- recupero i solidi ausiliari dividendoli per nome + local vSolidIds = {} + local nFirst = EgtGetFirstInGroup( nSolidGrp) + while nFirst do + local sName = EgtGetName( nFirst) + local vIds = EgtGetNameInGroup( nSolidGrp, sName) + table.insert( vSolidIds, vIds) + nFirst = EgtGetNext( vIds[#vIds]) + end -- scorro i gruppi di curve local nCrvGrp = EgtGetFirstNameInGroup( nSliceGrp, CONTOUR_GRP .. '*') @@ -2084,12 +2134,12 @@ local function CalcAuxSolidsPaths( nSliceGrp, nSolidGrp, LayerParams, vPtStart) if not nSrfBase then EgtOutLog( 'Warning : AuxSolids not possible (layer '..tostring( nIdx)..') - CalcPaths') else - local vSurfOffs = ComputeTrimSurfWithOverlaps( vSolidIds, nSrfBase, KEY_AUX_SOLIDS_OVERLAP, LayerParams.dStrand, nSolidPathGrp, LayerParams.vtSlicing) - + local vSurfOffs = ComputeTrimSurfWithOverlapsForAuxSolids( vSolidIds, nSrfBase, LayerParams.dStrand, nSolidPathGrp, LayerParams.vtSlicing) + for i = 1, #vSolidIds do -- creo la flat region corrispondente al solido ausiliario - local sName = EgtGetName( vSolidIds[i]) - local nOverlap = EgtGetInfo( vSolidIds[i], KEY_AUX_SOLIDS_OVERLAP, 'i') + local sName = EgtGetName( vSolidIds[i][1]) + local nOverlap = EgtGetInfo( vSolidIds[i][1], KEY_AUX_SOLIDS_OVERLAP, 'i') local nSrfId = EgtSurfFlatRegion( nSolidPathGrp, vSolidIds[i]) EgtSetName( nSrfId, AUX_SOLIDS_SRF) -- trim con la superficie di offset @@ -2098,13 +2148,13 @@ local function CalcAuxSolidsPaths( nSliceGrp, nSolidGrp, LayerParams, vPtStart) local nFirst, nCnt = EgtExplodeSurf( nSrfId) for j = 0, nCnt - 1 do local sNewName = sName .. EgtIf( j == 0, '', '_' .. tostring( j)) - local nInfillType = EgtGetInfo( vSolidIds[i], KEY_AUX_SOLIDS_INFILL, 'i') + local nInfillType = EgtGetInfo( vSolidIds[i][1], KEY_AUX_SOLIDS_INFILL, 'i') if nInfillType == INFILL_TYPE.OFFSET then ComputeOffsetInfill( nFirst + j, LayerParams.dStrand, LayerParams.vtSlicing, sNewName, TYPE.AUX_SOLID, vPtStart, nSolidPathGrp) -- aggiorno la trim surf UpdateTrimSurfWithAuxSolidsOffset( nFirst + j, nSrfBase, LayerParams.dStrand, nSolidPathGrp, LayerParams.vtSlicing) else - ComputeZigZagInfill( nFirst + j, LayerParams.dStrand, LayerParams.vtSlicing, sNewName, TYPE.AUX_SOLID, vPtStart, nSolidPathGrp) + ComputeZigZagInfill( nFirst + j, LayerParams.dStrand, LayerParams.vtSlicing, sNewName, TYPE.AUX_SOLID, vPtStart, nSolidPathGrp, vSurfOffs[nOverlap]) -- aggiungo eventuale passata extra AddExtraZigZag( nFirst + j, sNewName, LayerParams.dStrand, LayerParams.vtSlicing, nSolidPathGrp, vSurfOffs[nOverlap]) -- aggiorno la trim surf @@ -2112,11 +2162,6 @@ local function CalcAuxSolidsPaths( nSliceGrp, nSolidGrp, LayerParams, vPtStart) end end end - - -- elimino le superfici utilizzate per il trim - for k, v in pairs( vSurfOffs) do - EgtErase( v) - end end -- verifico se il gruppo contine qualcosa @@ -2243,7 +2288,7 @@ function CalcPaths.Exec( nPartId) if LayerParams.nFloorType == INFILL_TYPE.OFFSET then ComputeOffsetInfill( nSurfInfill, LayerParams.dStrand, LayerParams.vtSlicing, INFILL_CRV, TYPE.INFILL, vPtStart, nGrpId) elseif LayerParams.nFloorType == INFILL_TYPE.ZIGZAG then - ComputeZigZagInfill( nSurfInfill, LayerParams.dStrand, LayerParams.vtSlicing, INFILL_CRV, TYPE.INFILL, vPtStart, nGrpId) + ComputeZigZagInfill( nSurfInfill, LayerParams.dStrand, LayerParams.vtSlicing, INFILL_CRV, TYPE.INFILL, vPtStart, nGrpId, nSurfInfill) end EgtErase( nSurfInfill) elseif nIdx > #vLayIds - LayerParams.nCeilNbr then