-- CalcPaths.lua by Egaltech s.r.l. 2022/06/28 -- Calcolo percorsi di lavoro per Stampa 3d -- Tabella per definizione modulo local CalcPaths = {} -- Intestazioni require( 'EgtBase') EgtOutLog( ' CalcPaths started', 1) -- Dati local AMD = require( 'AddManData') --------------------------------------------------------------------- local s_nPartId local s_dOffsCorr = 10 * GEO.EPS_SMALL --------------------------------------------------------------------- local function GetLayerParamsForPathCalc() local LayerParams = {} LayerParams.bSpiralVase = EgtGetInfo( s_nPartId, KEY_SPIRAL_VASE, 'b') or false LayerParams.nShellsNbr = EgtGetInfo( s_nPartId, KEY_SHELLS_NBR, 'i') LayerParams.dStrand = EgtGetInfo( s_nPartId, KEY_STRAND, 'd') LayerParams.nStrandOverlap = EgtGetInfo( s_nPartId, KEY_STRAND_OVERLAP, 'i') or 0 LayerParams.dOffs = EgtGetInfo( s_nPartId, KEY_OFFSET_SLICE, 'd') LayerParams.nFloorNbr = EgtGetInfo( s_nPartId, KEY_FLOOR_NBR, 'i') or 0 LayerParams.nFloorType = EgtGetInfo( s_nPartId, KEY_FLOOR_TYPE, 'i') or INFILL_TYPE.ZIGZAG LayerParams.nCeilNbr = EgtGetInfo( s_nPartId, KEY_CEIL_NBR, 'i') or 0 LayerParams.nCeilType = EgtGetInfo( s_nPartId, KEY_CEIL_TYPE, 'i') or INFILL_TYPE.ZIGZAG LayerParams.vtSlicing = EgtGetInfo( s_nPartId, KEY_SLICING_DIR, 'v') LayerParams.bPrintInvert = ( EgtGetInfo( s_nPartId, KEY_PRINT_DIRECTION, 'i') == PRINT_DIRECTION.CW) -- parametri costolature LayerParams.bRibsInvertOrder = EgtGetInfo( s_nPartId, KEY_RIBS_INVERT_ORDER, 'b') LayerParams.bRibsDoLinkFirst = EgtGetInfo( s_nPartId, KEY_RIBS_DO_LINK_FIRST, 'b') or false -- parametri regioni con diverse passate LayerParams.dShellNbrCoasting = EgtGetInfo( s_nPartId, KEY_SHELL_NBR_COASTING, 'd') LayerParams.dShellNbrWipe = EgtGetInfo( s_nPartId, KEY_SHELL_NBR_WIPE, 'd') LayerParams.dShellNbrWipeDir = EgtGetInfo( s_nPartId, KEY_SHELL_NBR_WIPE_DIR, 'd') -- eventuale modifica dei parametri per gestire correttamente il caso spiral vase if LayerParams.bSpiralVase then LayerParams.nShellsNbr = 1 LayerParams.nFloorNbr = 0 LayerParams.nCeilNbr = 0 end return LayerParams end -------------------------------------------------------------------------------------------- local function CopyInfo( nSouId, nDestId, sInfo, sType) local info = EgtGetInfo( nSouId, sInfo, sType) EgtSetInfo( nDestId, sInfo, info) end ---------------------------------------------------------------------- local function ComputeSurfOffset( nSrf, nGrpId, dOffs, vtSlicing) -- gruppo temporaneo locale local nGrpTmp = EgtGroup( nGrpId, Frame3d( ORIG(), vtSlicing, GDB_RT.GLOB)) local nCopySrf = EgtCopyGlob( nSrf, nGrpTmp) or GDB_ID.NULL local bOk = EgtSurfFrOffset( nCopySrf, dOffs) local bExists = EgtSurfFrChunkCount( nCopySrf) > 0 if not bOk or not bExists then EgtErase( nCopySrf) nCopySrf = EgtCopyGlob( nSrf, nGrpTmp) or GDB_ID.NULL bOk = EgtSurfFrOffset( nCopySrf, dOffs + 0.05) bExists = EgtSurfFrChunkCount( nCopySrf) > 0 end EgtRelocateGlob( nCopySrf, nGrpId) EgtErase( nGrpTmp) return bOk, bExists, nCopySrf end --------------------------------------------------------------------- local function GetLayerStartPoint( nLayId, vtSlicing) -- recupero quota layer local dZ = EgtGetInfo( nLayId, KEY_SLICE_REAL_Z, 'd') local dDeltaZ = EgtGetInfo( nLayId, KEY_SLICE_DELTAZ, 'd') local frSlicing = Frame3d( ORIG(), vtSlicing) local ptOn = Point3d( 0, 0, dZ + dDeltaZ) ptOn:toGlob( frSlicing) -- gruppo temporaneo dove salvo i risultati local nGrpTmp = EgtGroup( nLayId) local vPtStart = {} local nMachStartGrp = EgtGetFirstNameInGroup( s_nPartId, LAY_MACH_START) local nStartId = EgtGetFirstInGroup( nMachStartGrp) while nStartId do local nType = EgtGetType( nStartId) -- se punto if nType == GDB_TY.GEO_POINT then table.insert( vPtStart, EgtSP( nStartId)) else -- se curva interseco con il piano local nId, nCnt = EgtPlaneCurveInters( ptOn, vtSlicing, nStartId, nGrpTmp, GDB_RT.GLOB) if nId then for i = nId, nId + nCnt - 1 do table.insert( vPtStart, EgtSP( i)) end end end nStartId = EgtGetNext( nStartId) end EgtErase( nGrpTmp) return vPtStart end --------------------------------------------------------------------- local function ModifyStartPoint( nCrvId, vPtStart) -- cerco lo start point più vicino tra quelli possibili if vPtStart and #vPtStart > 0 then local nMinIdx = -1 local dMinDist = GEO.INFINITO for i = 1, #vPtStart do local dDist = EgtPointCurveDist( vPtStart[i], nCrvId) if dDist < dMinDist - 10 * GEO.EPS_SMALL then dMinDist = dDist nMinIdx = i end end EgtChangeClosedCurveStartPoint( nCrvId, vPtStart[nMinIdx]) end end --------------------------------------------------------------------- local function GetPathsFromSurf( nSrfId, sName, nType, nGrpId, vPtStart) local vIds = {} local nChunks = EgtSurfFrChunkCount( nSrfId) for nC = 0, nChunks - 1 do -- estraggo i contorni local nCrvId, nCrvCnt = EgtExtractSurfFrChunkLoops( nSrfId, nC, nGrpId) for nInd = 0, nCrvCnt - 1 do EgtSetName( nCrvId + nInd, sName) EgtSetInfo( nCrvId + nInd, KEY_TYPE, nType) -- se è loop interno lo inverto per averlo orientato in senso antiorario if nInd > 0 then EgtInvertCurve( nCrvId + nInd) end -- verifico soddisfi i requisiti (lunghezza e area) local dLen = EgtCurveLength( nCrvId + nInd) local _ , _ , dArea = EgtCurveArea( nCrvId + nInd) if dLen < MIN_LEN or dArea < MIN_AREA then EgtErase( nCrvId + nInd) return end table.insert( vIds, nCrvId + nInd) ModifyStartPoint( nCrvId + nInd, vPtStart) end end return vIds end ---------------------------------------------------------------------- local function VerifyPath( nCrvId, dStrand, vtSlicing, nGrp) local _, _, dArea = EgtCurveArea( nCrvId) -- verifico se esiste l'offset (permetto una piccola sovrapposizione) local dAllowedOverlap = 1 local nRes, nCnt = EgtOffsetCurveAdv( nCrvId, - dStrand / 2 + dAllowedOverlap) -- se errore ritento con valore leggermente modificato if not nRes then nRes, nCnt = EgtOffsetCurveAdv( nCrvId, - dStrand / 2 + 0.05) if not nRes then return false end end for j = nRes, nRes + nCnt - 1 do EgtErase( j) end if nRes == GDB_ID.NULL or not dArea or dArea < GEO.EPS_SMALL then -- verifico se fattibile con una sola passata -- TODO da sistemare con medial axis per curva generica local bSingleStrand = false if EgtCurveIsClosed( nCrvId) then local nGrpTmp = EgtGroup( nGrp, Frame3d( ORIG(), vtSlicing), GDB_RT.GLOB) EgtRelocateGlob( nCrvId, nGrpTmp) local frLoc, dDimX, dDimY = EgtCurveMinAreaRectangleXY( nCrvId) if dDimY < 0.5 then -- TODO curva generica local dZ = EgtSP( nCrvId):getZ() -- creo la curva che corrisponde alla sigola passata local ptS = frLoc:getOrigin() - dDimX / 2 * frLoc:getVersX() + dZ * Z_AX() local ptE = frLoc:getOrigin() + dDimX / 2 * frLoc:getVersX() + dZ * Z_AX() if dist( ptS, ptE) > 5 then local nId = EgtCurveCompoFromPoints( nGrpTmp, { ptS, ptE}) local sName = EgtGetName( nCrvId) if sName then EgtSetName( nId, sName) end local nType = EgtGetInfo( nCrvId, KEY_TYPE, 'i') if nType then EgtSetInfo( nId, KEY_TYPE, nType) end EgtErase( nCrvId) EgtChangeId( nId, nCrvId) bSingleStrand = true end end EgtRelocateGlob( nCrvId, nGrp, GDB_IN.LAST_SON) EgtErase( nGrpTmp) end -- se non è fattibile con unica passata lo cancello if not bSingleStrand then EgtErase( nCrvId) return false end end 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 ---------------------------- -------------------------------------------------------------------- local function AdjustSurfForFloorCeil( nStrandDiff, nSrfTrim, nShellNbrSurfGrp) if EgtSurfFrChunkCount( nSrfTrim) == 0 then return end local nSurf = EgtCopyGlob( nSrfTrim, EgtGetParent( nSrfTrim)) if nShellNbrSurfGrp then local nIdx = nStrandDiff local nShellSurf = EgtGetFirstNameInGroup( nShellNbrSurfGrp, SHELL_NBR_SURF .. tostring( nIdx)) while nShellSurf do EgtSurfFrSubtract( nSurf, nShellSurf) nIdx = nIdx + 1 nShellSurf = EgtGetFirstNameInGroup( nShellNbrSurfGrp, SHELL_NBR_SURF .. tostring( nIdx)) end end return nSurf end -------------------------------------------------------------------- local function ReorderPath( vOldIds, vNewIds) if not vNewIds then return end if #vOldIds == 1 and #vNewIds == 1 then EgtRelocateGlob( vNewIds[1], vOldIds[1], GDB_IN.AFTER) return end -- associo ad ogni elemento di vOldIds gli elementi di vNewIds che contiene local vOrdered = {} if #vOldIds == 1 then vOrdered[vOldIds[1]] = vNewIds else local nGrp = EgtGetParent( vOldIds[1]) -- creo le superifici a partire dalle curve in vOldIds local vOldSurf = {} for i = 1, #vOldIds do local nSrf = EgtSurfFlatRegion( nGrp, {vOldIds[i]}) table.insert( vOldSurf, EgtIf( nSrf, nSrf, GDB_ID.NULL)) end for i = 1, #vNewIds do for j = 1, #vOldSurf do if vOldSurf[j] ~= GDB_ID.NULL then if not EgtSurfFrTestExternal( vOldSurf[j], vNewIds[i]) then if vOrdered[vOldIds[j]] then table.insert( vOrdered[vOldIds[j]], vNewIds[i]) else vOrdered[vOldIds[j]] = {vNewIds[i]} end break end end end end for i = 1, #vOldSurf do EgtErase( vOldSurf[i]) end end -- riordino for nParentIdx, vChildren in pairs( vOrdered) do if #vChildren == 1 then -- se racchiude solo una curva EgtRelocateGlob( vChildren[1], nParentIdx, GDB_IN.AFTER) else EgtSpInit() -- se racchiude più curve uso shortest path per ordinarle for j = 1, #vChildren do local pt = EgtGP( vChildren[j]) EgtSpAddPoint( pt:getX(), pt:getY(), pt:getZ(), 0, 0, pt:getX(), pt:getY(), pt:getZ(), 0, 0) end local ptS = EgtSP( nParentIdx) EgtSpSetOpenBound( true, SHP_OB.NEAR_PNT, ptS:getX(), ptS:getY(), ptS:getZ(), 0, 0) local vOrd, _ = EgtSpCalculate( SHP_TY.OPEN) EgtSpTerminate() for j = #vOrd, 1, -1 do EgtRelocateGlob( vChildren[vOrd[j]], nParentIdx, GDB_IN.AFTER) end end end end --------------------------------------------------------------------------- local function ComputeOffsetInfill( nSrf, dStrand, vtSlicing, sName, nType, vPtStart, nGrp) local nChunk = EgtSurfFrChunkCount( nSrf) if nChunk == 0 then return end -- estraggo i contorni della superficie local vOldIds = GetPathsFromSurf( nSrf, sName, nType, nGrp, vPtStart) local dOffs = - dStrand local bOk, bExists, nSrfOffs = ComputeSurfOffset( nSrf, nGrp, dOffs, vtSlicing) while bOk and bExists do -- estraggo i contorni local vNewIds = GetPathsFromSurf( nSrfOffs, sName, nType, nGrp, vPtStart) if vNewIds then -- riordino ReorderPath( vOldIds, vNewIds) -- verifico fattibilità local k = 1 while k <= #vNewIds do if VerifyPath( vNewIds[k], dStrand, vtSlicing, nGrp) then k = k + 1 else -- se non è fattibile lo rimuovo dalla table per non ritrovarlo nello step successivo table.remove( vNewIds, k) end end vOldIds = vNewIds end EgtErase( nSrfOffs) -- offset successivo dOffs = dOffs - dStrand bOk, bExists, nSrfOffs = ComputeSurfOffset( nSrf, nGrp, dOffs, vtSlicing) end end -------------------------------------------------------------------------------- local function ComputeZigZagInfill( nSrf, dStrand, vtSlicing, sName, nType, vPtStart, nGrp) local nChunk = EgtSurfFrChunkCount( nSrf) if nChunk == 0 then return end local nCopySrf = EgtCopyGlob( nSrf, nGrp) if EgtSurfFrChunkCount( nSrf) == 0 then return end 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) -- 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 end end end EgtErase( nGrpTmp) 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) end local vtS = EgtSV( nInd) EgtErase( nId) end end ------------------------------------------------------------------- --------------------------- RIBS ----------------------------------- -------------------------------------------------------------------- local function ComputeTrimSurfWithOverlapsForRibs( vIds, nSrfBase, nSrfExt, dOffs, dStrand, nGrp, vtSlicing) -- per ogni tipologia e overlap creo le superfici con cui fare i trim local tSurfOffs = {{}, {}, {}} for i = 1, #vIds do local nOverlap = EgtGetInfo( vIds[i], KEY_RIBS_OVERLAP, 'i') local nType = EgtGetInfo( vIds[i], KEY_RIBS_TYPE, 'i') if not tSurfOffs[nType][nOverlap] then if nType == RIB_TYPE.INTERNAL then if nSrfBase then local dNewOffs = nOverlap / 100 * dStrand local bOk, bExists, nSrfOffs = ComputeSurfOffset( nSrfBase, nGrp, dNewOffs, vtSlicing) if bOk then tSurfOffs[nType][nOverlap] = nSrfOffs end end elseif nType == RIB_TYPE.EXTERNAL then if nSrfExt then local dNewOffs = dOffs + ( 0.5 - nOverlap / 100) * dStrand local bOk, bExists, nSrfOffs = ComputeSurfOffset( nSrfExt, nGrp, dNewOffs, vtSlicing) if bOk then tSurfOffs[nType][nOverlap] = nSrfOffs EgtSetName( nSrfOffs, TOT_SHELL_TRIM_SURF) end end else tSurfOffs[nType][nOverlap] = GDB_ID.NULL end end end return tSurfOffs end -------------------------------------------------------------------- local function VerifyRibsIntersection( ptInt, nType1, nType2, nSrf1, nSrf2, nGrp) local bValid = false local nPtId = EgtPoint( nGrp, ptInt) if nType1 == RIB_TYPE.INTERNAL or nType2 == RIB_TYPE.INTERNAL then -- l'intersezione deve essere interna if nSrf1 and not EgtSurfFrTestExternal( nSrf1, nPtId) then bValid = true end elseif nType1 == RIB_TYPE.EXTERNAL or nType2 == RIB_TYPE.EXTERNAL then -- l'intersezione deve essere esterna if nSrf2 and EgtSurfFrTestExternal( nSrf2, nPtId) then bValid = true end else bValid = true end return bValid end --------------------------------------------------------------------------------- -- Funzione che sistema le intersezioni fra costolature nel caso generico local function AdjustRibsOffsetForIntersection( nCrv1, nCrv2, LayerParams, nOffsGrp) -- calcolo gli offset della curva principale ( nCrv1) da usare per trim local nShells = EgtGetInfo( nCrv1, KEY_RIBS_SHELLS_NBR, 'i') local nOverlap1 = EgtGetInfo( nCrv1, KEY_RIBS_OVERLAP, 'i') local nOverlap2 = EgtGetInfo( nCrv2, KEY_RIBS_OVERLAP, 'i') local nOverlap = min( nOverlap1, nOverlap2) local dOffs = ( nShells - 1) * LayerParams.dStrand / 2 local nSrf = EgtSurfFrFatCurve( nOffsGrp, nCrv1, dOffs + ( 1 - nOverlap / 100) * LayerParams.dStrand, false) if not nSrf then return end -- trim degli offset della curva secondaria ( nCrv2) local vOffs2 = EgtGetNameInGroup( nOffsGrp, EgtGetName( nCrv2)) for i = 1, #vOffs2 do local nId, nCnt = EgtTrimCurveWithRegion( vOffs2[i], nSrf, false, true) EgtChangeId( nId, vOffs2[i]) -- aggiorno ordine di split copiandolo da nCrv2 CopyInfo( nCrv2, vOffs2[i], KEY_SPLIT_ORDER, 'i') if nCnt > 1 then EgtSetInfo( nId + 1, KEY_SPLIT_RIB, vOffs2[i]) -- curva da cui deriva CopyInfo( nCrv2, nId + 1, KEY_SPLIT_ORDER, 'i') -- ordine di split EgtRelocateGlob( nId + 1, nOffsGrp, GDB_IN.LAST_SON) end end EgtErase( nSrf) end -------------------------------------------------------------------- -- Funzione che sistema le intersezioni fra costolature nel caso di 2 passate local function AdjustRibsOffsetForIntersection2Shells( nCrv1, nCrv2, LayerParams, nOffsGrp) -- costruisco le superfici da usare per trim local nSrf1 = EgtSurfFrFatCurve( nOffsGrp, nCrv1, LayerParams.dStrand / 2, false) local vtN1 = EgtSurfFrNormVersor( nSrf1, GDB_ID.ROOT) if LayerParams.vtSlicing * vtN1 < 0 then EgtInvertSurf( nSrf1) end local nSrf2 = EgtSurfFrFatCurve( nOffsGrp, nCrv2, LayerParams.dStrand / 2, false) local vtN2 = EgtSurfFrNormVersor( nSrf2, GDB_ID.ROOT) if LayerParams.vtSlicing * vtN2 < 0 then EgtInvertSurf( nSrf2) end -- trim degli offset di nCrv1 local vOffs1 = EgtGetNameInGroup( nOffsGrp, EgtGetName( nCrv1)) for i = 1, #vOffs1 do local nId, nCnt = EgtTrimCurveWithRegion( vOffs1[i], nSrf2, false, true) end -- trim degli offset di nCrv2 local vOffs2 = EgtGetNameInGroup( nOffsGrp, EgtGetName( nCrv2)) for i = 1, #vOffs2 do local nId, nCnt = EgtTrimCurveWithRegion( vOffs2[i], nSrf1, false, true) end EgtErase( nSrf1) EgtErase( nSrf2) end ------------------------------------------------------------------ local function UpdateSplitOrder( nCrv, tInters, nOffsGrp) local nOrder = EgtGetInfo( nCrv, KEY_SPLIT_ORDER, 'i') or 0 local nNewOrder = nOrder + 1 -- aggiorno tutte le curve che dipendono da nCrv if tInters[nCrv] then for i = 1, #tInters[nCrv] do local nOldOrder = EgtGetInfo( tInters[nCrv][i], KEY_SPLIT_ORDER, 'i') if nOldOrder < nNewOrder then EgtSetInfo( tInters[nCrv][i], KEY_SPLIT_ORDER, nNewOrder) -- aggiorno i suoi offset local vOffs = EgtGetNameInGroup( nOffsGrp, EgtGetName( tInters[nCrv][i])) for j = 1, #vOffs do EgtSetInfo( vOffs[j], KEY_SPLIT_ORDER, nNewOrder) end -- aggiorno eventuali dipendenze UpdateSplitOrder( tInters[nCrv][i], tInters, nOffsGrp) end end end end -------------------------------------------------------------------- local function HandleRibsIntersections( nRibsGrp, LayerParams, nOffsGrp, nRibsPathGrp, bAllTwoStrands) local nCrvGrp = EgtGetParent( nRibsPathGrp) -- copio gli offset delle costolature nel RibsPathGrp local vOffsRib = EgtGetAllInGroup( nOffsGrp) for i = 1, #vOffsRib do EgtCopyGlob( vOffsRib[i], nRibsPathGrp) end -- copio i setti in un gruppo con frame locale per calcolare le intersezioni local frLoc = Frame3d( ORIG(), LayerParams.vtSlicing) local nGrpTmp = EgtGroup( nRibsGrp, frLoc, GDB_RT.GLOB) local vOrigRibsIds = EgtGetNameInGroup( nRibsGrp, RIBS_CRV .. '*') local vRibsIds = {} for i = 1, #vOrigRibsIds do table.insert( vRibsIds, EgtCopyGlob( vOrigRibsIds[i], nGrpTmp)) end -- calcolo le regioni nella quali ha senso considerare l'intersezione local nSrfOffs1, nSrfOffs2 local bOk, bExists local nSrf1 = EgtGetFirstNameInGroup( nCrvGrp, TOT_SHELL_TRIM_SURF) if nSrf1 then bOk, bExists, nSrfOffs1 = ComputeSurfOffset( nSrf1, nCrvGrp, 2 * LayerParams.dStrand, LayerParams.vtSlicing) if not bOk or not bExists then nSrfOffs1 = EgtCopyGlob( nSrf1, nCrvGrp) end end local nSrf2 = EgtGetFirstNameInGroup( nCrvGrp, LAYER_SRF) if nSrf2 then bOk, bExists, nSrfOffs2 = ComputeSurfOffset( nSrf2, nCrvGrp, - 2 * LayerParams.dStrand, LayerParams.vtSlicing) if not bOk or not bExists then nSrfOffs2 = EgtCopyGlob( nSrf2, nCrvGrp) end end local bInters = false local vSplit = {} local tInters = {} -- tabella che tiene traccia delle intersezioni trovate for i = 1, #vRibsIds do local nType1 = EgtGetInfo( vRibsIds[i], KEY_RIBS_TYPE, 'i') -- verifico se interseca uno dei setti successivi for j = i + 1, #vRibsIds do -- verifico se i due setti possono intersecarsi in base alla loro tipologia local nType2 = EgtGetInfo( vRibsIds[j], KEY_RIBS_TYPE, 'i') if not ( ( nType1 == RIB_TYPE.INTERNAL and nType2 == RIB_TYPE.EXTERNAL) or ( nType1 == RIB_TYPE.EXTERNAL and nType2 == RIB_TYPE.INTERNAL)) then local ptInt = EgtIP( vRibsIds[i], vRibsIds[j], ORIG()) if ptInt then -- verifico se l'interserzione è valida if VerifyRibsIntersection( ptInt, nType1, nType2, nSrfOffs1, nSrfOffs2, nGrpTmp) then bInters = true local dPar1 = EgtCurveParamAtPoint( vRibsIds[i], ptInt) local dPar2 = EgtCurveParamAtPoint( vRibsIds[j], ptInt) local _, dParE1 = EgtCurveDomain( vRibsIds[i]) local _, dParE2 = EgtCurveDomain( vRibsIds[j]) local nCrv1 = vOrigRibsIds[i] -- curva principale che non viene tagliata local nCrv2 = vOrigRibsIds[j] -- curve secondaria da modificare local nSplitOrder1 = EgtGetInfo( nCrv1, KEY_SPLIT_ORDER, 'i') or 0 local nSplitOrder2 = EgtGetInfo( nCrv2, KEY_SPLIT_ORDER, 'i') or 0 if dPar1 < 10 * GEO.EPS_SMALL or abs( dPar1 - dParE1) < 10 * GEO.EPS_SMALL then nCrv1, nCrv2 = nCrv2, nCrv1 nSplitOrder1, nSplitOrder2 = nSplitOrder2, nSplitOrder1 else -- prediligo setto già splittato più volte if nSplitOrder1 > nSplitOrder2 then nCrv1, nCrv2 = nCrv2, nCrv1 nSplitOrder1, nSplitOrder2 = nSplitOrder2, nSplitOrder1 end end -- aggiorno tabella delle intersezioni if tInters[nCrv1] then table.insert( tInters[nCrv1], nCrv2) else tInters[nCrv1] = {nCrv2} end -- aggiorno ordine di split if nSplitOrder2 < nSplitOrder1 + 1 then EgtSetInfo( nCrv2, KEY_SPLIT_ORDER, nSplitOrder1 + 1) UpdateSplitOrder( nCrv2, tInters, nRibsPathGrp) end if bAllTwoStrands then -- nel caso di 2 passate gestione speciale AdjustRibsOffsetForIntersection2Shells( nCrv1, nCrv2, LayerParams, nRibsPathGrp) else AdjustRibsOffsetForIntersection( nCrv1, nCrv2, LayerParams, nRibsPathGrp) end end EgtErase( nPtId) end end end end EgtErase( nSrfOffs1) EgtErase( nSrfOffs2) EgtErase( nGrpTmp) return bInters end -------------------------------------------------------------------- local function ShortestPathForRibs( vIds, nGrp, bInvertOrder) if not vIds or #vIds == 0 then return end -- se solo un setto ordinamento banale if #vIds == 1 then EgtRelocateGlob( vIds[1], nGrp, GDB_IN.LAST_SON) return elseif #vIds == 2 then EgtRelocateGlob( vIds[1], nGrp, GDB_IN.LAST_SON) EgtRelocateGlob( vIds[2], vIds[1], EgtIf( bInvertOrder, GDB_IN.BEFORE, GDB_IN.AFTER)) return else -- se più setti ordinamento con shortest path EgtSpInit() for i = 1, #vIds do local pt = EgtMP( vIds[i], GDB_RT.GLOB) EgtSpAddPoint( pt:getX(), pt:getY(), pt:getZ(), 0, 0, pt:getX(), pt:getY(), pt:getZ(), 0, 0) end local vOrd, dLen = EgtSpCalculate( SHP_TY.OPEN) EgtSpTerminate() EgtRelocateGlob( vIds[vOrd[1]], nGrp, GDB_IN.LAST_SON) for i = 2, #vOrd do EgtRelocateGlob( vIds[vOrd[i]], vIds[vOrd[i-1]], EgtIf( bInvertOrder, GDB_IN.BEFORE, GDB_IN.AFTER)) end end end --------------------------------------------------------------------- -- Funzione che riordina le costolature nel caso generico local function ReorderRibs( nGrp, bInvertOrder, bDoLinkFirst, dStrand, nMaxNbr) -- raggruppo per tipologia local tRibs = {{}, {}, {}} local vIds = EgtGetNameInGroup( nGrp, RIBS_CRV .. '*') if not vIds or #vIds == 0 then return end for i = 1, #vIds do local nType = EgtGetInfo( vIds[i], KEY_RIBS_TYPE, 'i') table.insert( tRibs[nType], vIds[i]) end -- riordino ogni tipologia con shortest path local vSplitRibs = {} for i = 1, 3 do local tSplitOrder = {} local nMax = -1 -- raggruppo i ribs for j = 1, #tRibs[i] do local nInfoSplit = EgtGetInfo( tRibs[i][j], KEY_SPLIT_RIB, 'i') local nShells = EgtGetInfo( tRibs[i][j], KEY_RIBS_SHELLS_NBR, 'i') if nInfoSplit and nShells == 1 then -- se è ottenuto dalla divisione di una costolatura table.insert( vSplitRibs, tRibs[i][j]) else -- classifico in base all'ordine di split e al link local nSplitOrder = EgtGetInfo( tRibs[i][j], KEY_SPLIT_ORDER, 'i') or 0 local bLink = EgtGetInfo( tRibs[i][j], KEY_RIBS_LINK, 'b') or false if nSplitOrder > nMax then nMax = nSplitOrder end if not tSplitOrder[nSplitOrder] then tSplitOrder[nSplitOrder]= {{}, {}} end if bLink then table.insert( tSplitOrder[nSplitOrder][2], tRibs[i][j]) else table.insert( tSplitOrder[nSplitOrder][1], tRibs[i][j]) end end end local bLinkFirst = bDoLinkFirst -- riordino ogni ordine di split for k = 0, nMax do ShortestPathForRibs( EgtIf( bLinkFirst, tSplitOrder[k][2], tSplitOrder[k][1]), nGrp, bInvertOrder) ShortestPathForRibs( EgtIf( bLinkFirst, tSplitOrder[k][1], tSplitOrder[k][2]), nGrp, bInvertOrder) -- eventuale aggiornamento di bLinkFirst per l'ordine successivo if not ( ( not bLinkFirst and #tSplitOrder[k][2] == 0) or ( bLinkFirst and #tSplitOrder[k][1] == 0)) then bLinkFirst = not bLinkFirst end end end -- sistemo nomi local kMax = nMaxNbr + 1 local dTol = 500 * GEO.EPS_SMALL for i = 1, nMaxNbr do local vIds = EgtGetNameInGroup( nGrp, RIBS_CRV .. tostring(i)) or {} for j = 2, #vIds do local dDistS = EgtPointCurveDist( EgtSP( vIds[j]), vIds[j-1]) local dDistM = EgtPointCurveDist( EgtMP( vIds[j]), vIds[j-1]) local dDistE = EgtPointCurveDist( EgtEP( vIds[j]), vIds[j-1]) if abs( dDistS - dStrand) < dTol or abs( dDistM - dStrand) < dTol or abs( dDistE - dStrand) < dTol then -- se le costolatura è vicina alla precedente avrà lo stesso nome EgtSetName( vIds[j], EgtGetName( vIds[j-1])) EgtRelocateGlob( vIds[j], vIds[j-1], GDB_IN.AFTER) else -- se la costolatura dista troppo dalla precedente le cambio il nome EgtSetName( vIds[j], RIBS_CRV .. tostring( kMax)) kMax = kMax + 1 end end end -- aggiusto tutte le costolature divise for i = 1, #vSplitRibs do local nPrevId = EgtGetInfo( vSplitRibs[i], KEY_SPLIT_RIB, 'i') local bInverted = EgtGetInfo( vSplitRibs[i], KEY_INVERTED_CRV, 'b') or false -- aggiungo come successiva alla costolatura da cui si è generata EgtRelocateGlob( vSplitRibs[i], nPrevId, EgtIf( bInverted, GDB_IN.BEFORE, GDB_IN.AFTER)) -- se necessario rinomino if EgtGetName( vSplitRibs[i]) == EgtGetName(nPrevId) then EgtSetName( vSplitRibs[i], RIBS_CRV .. tostring( kMax)) kMax = kMax + 1 end -- correggo le info per gestire correttamente nel calcolo toolpath local nPrevInfo = EgtGetInfo( nPrevId, KEY_SPLIT_RIB, 'i') if bInverted and not nPrevInfo then EgtRemoveInfo( vSplitRibs[i], KEY_SPLIT_RIB) EgtSetInfo( nPrevId, KEY_SPLIT_RIB, vSplitRibs[i]) end end end -------------------------------------------------------------------------------------------- local function ReassignInfo( nCrv, nCnt, vOrig) for nId = nCrv, nCrv + nCnt - 1 do local ptS = EgtSP( nId) local ptE = EgtEP( nId) -- info overlap local nOverlap = EgtGetInfo( s_nPartId, KEY_RIBS_OVERLAP, 'i') EgtSetInfo( nId, KEY_RIBS_OVERLAP, nOverlap) local bStart = false local bEnd = false while not bStart and not bEnd do -- scorro le curve originarie per capire da quali deriva for i = 1, #vOrig do local ptSOrig = EgtSP( vOrig[i]) local ptEOrig = EgtEP( vOrig[i]) -- verifico se corrisponde al suo start if AreSamePointApprox( ptS, ptSOrig) or AreSamePointApprox( ptS, ptEOrig) then CopyInfo( vOrig[i], nId, KEY_RIBS_LEAD_IN_INVERT, 'b') CopyInfo( vOrig[i], nId, KEY_RIBS_LEAD_IN_LEN, 'd') CopyInfo( vOrig[i], nId, KEY_ASSOCIATED_SURF, 'i') CopyInfo( vOrig[i], nId, KEY_RIBS_TYPE, 'i') bStart = true end -- verifico se corrisponde al suo end if AreSamePointApprox( ptE, ptSOrig) or AreSamePointApprox( ptE, ptEOrig) then CopyInfo( vOrig[i], nId, KEY_RIBS_LEAD_OUT_INVERT, 'b') CopyInfo( vOrig[i], nId, KEY_RIBS_LEAD_OUT_LEN, 'd') CopyInfo( vOrig[i], nId, KEY_RIBS_LEAD_OUT_COASTING, 'd') CopyInfo( vOrig[i], nId, KEY_RIBS_LEAD_OUT_WIPE, 'd') CopyInfo( vOrig[i], nId, KEY_RIBS_LEAD_OUT_WIPE_DIR, 'd') bEnd = true end end end end -- dopo aver salvato le info è inutile conservare le curve originali for i = 1, #vOrig do EgtErase( vOrig[i]) end end --------------------------------------------------------------------------------------------- -- Funzione che riordina le costolature nel caso di intersezioni e 2 passate local function ReorderRibsInters2Shells( nOffsGrp, dStrand) local vOffs = EgtGetNameInGroup( nOffsGrp, RIBS_CRV .. '*') local bUnboundedRib = false -- copio le curve originali ( per recuperarne le info) local vCopy = {} for i = 1, #vOffs do local nNewId = EgtCopy( vOffs[i], nOffsGrp) table.insert( vCopy, nNewId) local nType = EgtGetInfo( nNewId, KEY_RIBS_TYPE, 'i') if nType == RIB_TYPE.UNBOUNDED then bUnboundedRib = true end end -- concateno le curve local nCrv, nCnt = EgtCurveCompoByChain( nOffsGrp, vOffs, ORIG()) local vIds = {} for i = nCrv, nCrv + nCnt - 1 do EgtSetInfo( i, KEY_TYPE, TYPE.RIB) table.insert( vIds, i) end local k = 0 -- indice da utilizzare per i nomi while #vIds > 0 do k = k + 1 -- prendo la prima tra le curve a disposizione nCurrCrv = vIds[1] table.remove( vIds, 1) EgtSetName( nCurrCrv, RIBS_CRV .. tostring(k)) local pt = EgtEP( nCurrCrv) local _, dParE = EgtCurveDomain( nCurrCrv) local nCnt = 0 -- scorro alla ricerca di una curva che posso collegare alla corrente while nCurrCrv do local bFound = false for j = 1, #vIds do if vIds[j] ~= nCrv and not EgtCurveIsClosed(vIds[j]) then -- verifico se il collegamento è possibile local bAdd = false local bInvert = false local dDist, _, dParMinDist = EgtPointCurveDist( pt, vIds[j]) if dDist < dStrand + 10 * GEO.EPS_SMALL then -- controllo che sia vicino ad uno degli estremi local dParS, dParE = EgtCurveDomain( vIds[j]) if abs( dParMinDist - dParS) < 500 * GEO.EPS_SMALL then bAdd = true elseif abs( dParMinDist - dParE) < 500 * GEO.EPS_SMALL then bAdd = true -- è se necessaria inversione di vIds[j] bInvert = true end end if not bAdd then -- check sullo start point di vIds[j] local dDist, _, dParMinDist = EgtPointCurveDist( EgtSP( vIds[j]), nCurrCrv) if dDist < dStrand + 10 * GEO.EPS_SMALL then bInvert = false -- controllo sia vicino all'end point della curva corrente if dParE - dParMinDist < 500 * GEO.EPS_SMALL then bAdd = true -- altrimenti può essere vicino allo start elseif dParMinDist < 500 * GEO.EPS_SMALL and nCnt == 0 then bAdd = true EgtInvertCurve( nCurrCrv) end end -- se non è aggiunto check con end point di vIds[j] if not bAdd then local dDist, _, dParMinDist = EgtPointCurveDist( EgtEP( vIds[j]), nCurrCrv) if dDist < dStrand + 10 * GEO.EPS_SMALL then bInvert = true if dParE - dParMinDist < 500 * GEO.EPS_SMALL then bAdd = true elseif dParMinDist < 500 * GEO.EPS_SMALL and nCnt == 0 then bAdd = true EgtInvertCurve( nCurrCrv) end end end end if bAdd then bFound = true nCnt = nCnt + 1 EgtRelocateGlob( vIds[j], nCurrCrv, GDB_IN.AFTER) EgtSetName( vIds[j], RIBS_CRV .. tostring( k)) -- eventuale inversione della curva if bInvert then EgtInvertCurve( vIds[j]) end -- aggiorno per collegamento successivo pt = EgtEP( vIds[j]) _, dParE = EgtCurveDomain( vIds[j]) nCurrCrv = vIds[j] -- elimino la curva dal vettore di curve da considerare table.remove( vIds, j) break end end end -- se non ho più curve da collegare if not bFound and nCnt == 0 then -- se era la prima curva faccio un tentativo invertendola nCnt = 1 EgtInvertCurve( nCurrCrv) pt = EgtEP( nCurrCrv) elseif not bFound then nCurrCrv = nil end end end -- Recupero le info dalle curve originali ReassignInfo( nCrv, nCnt, vCopy) -- riordino per tipologia ( prima iterni poi esterni) nel caso senza unbounded if not bUnboundedRib then local vCrvs = EgtGetNameInGroup( nOffsGrp, RIBS_CRV .. '*') for nId = 1, #vCrvs do local nType = EgtGetInfo( vCrvs[nId], KEY_RIBS_TYPE, 'i') if nType == RIB_TYPE.EXTERNAL then EgtRelocateGlob( vCrvs[nId], EgtGetParent( nCrv), GDB_IN.LAST_SON) end end end end ------------------------------------------------------------------- local function UpdateRibSplitInfo( nGrp, tIds, tRemoved) local vIds = EgtGetNameInGroup( nGrp, RIBS_CRV .. '*') if not vIds then return end for i = 1, #vIds do -- info SplitRib local nInfo = EgtGetInfo( vIds[i], KEY_SPLIT_RIB, 'i') if nInfo then -- verifico se va aggiornata ereditandola da rib che sono stati eliminati per vincolo sulla lunghezza while tRemoved[nInfo] do nInfo = tRemoved[nInfo] end if tIds[nInfo] and #tIds[nInfo] > 0 then -- aggiorno info con nuovo id della costolatura da cui deriva local nLast = #tIds[nInfo] EgtSetInfo( vIds[i], KEY_SPLIT_RIB, tIds[nInfo][nLast]) else -- se la costolatura da cui deriva è stata eliminata, tolgo l'info che le associava EgtRemoveInfo( vIds[i], KEY_SPLIT_RIB) end end end end -------------------------------------------------------------------- local function CalcRibsPaths( nSliceGrp, nRibsGrp, LayerParams, nIdx) local vRibs = EgtGetNameInGroup( nRibsGrp, RIBS_CRV .. '*') -- verifico se tutte le costolature vengono fatte con 2 passate local bAllTwoStrands = true for i = 1, #vRibs do local nStrand = EgtGetInfo( vRibs[i], KEY_RIBS_SHELLS_NBR, 'i') if nStrand ~= 2 then bAllTwoStrands = false break end end local nLast = EgtGetLastNameInGroup( nRibsGrp, RIBS_CRV .. '*') local sLastName = EgtGetName( nLast) local nMaxNbr = tonumber( string.sub( sLastName, 4)) -- calcolo gli offset local nOffsGrp = EgtGroup( nRibsGrp) for i = 1, #vRibs do local nShellsNbr = EgtGetInfo( vRibs[i], KEY_RIBS_SHELLS_NBR, 'i') local dOffs = ( nShellsNbr - 1) * LayerParams.dStrand / 2 for k = 0, nShellsNbr - 1 do local nNewId = EgtOffsetCurveAdv( vRibs[i], - dOffs + k * LayerParams.dStrand) EgtSetName( nNewId, EgtGetName( vRibs[i])) EgtSetInfo( nNewId, KEY_TYPE, TYPE.RIB) EgtRelocateGlob( nNewId, nOffsGrp) end end -- scorro i gruppi di curve local dOffs = 0.5 * LayerParams.dStrand - LayerParams.dOffs + ( LayerParams.nShellsNbr - 1) * LayerParams.dStrand local nCrvGrp = EgtGetFirstNameInGroup( nSliceGrp, CONTOUR_GRP .. '*') while nCrvGrp do -- creo o svuoto il gruppo local nRibsPathGrp = EgtGetFirstNameInGroup( nCrvGrp, RIBS_GRP) if not nRibsPathGrp then nRibsPathGrp = EgtGroup( nCrvGrp) EgtSetName( nRibsPathGrp, RIBS_GRP) EgtSetStatus( nRibsPathGrp, GDB_ST.OFF) else EgtEmptyGroup( nRibsPathGrp) end -- creo le superfici con cui fare i trim local nSrfBase = EgtGetFirstNameInGroup( nCrvGrp, TOT_SHELL_TRIM_SURF) local nSrfExt = EgtGetFirstNameInGroup( nCrvGrp, LAYER_SRF) local tSurfOffs = ComputeTrimSurfWithOverlapsForRibs( vRibs, nSrfBase, nSrfExt, LayerParams.dOffs, LayerParams.dStrand, nRibsPathGrp, LayerParams.vtSlicing) -- gestisco eventuali intersezioni fra costolature local bInters = HandleRibsIntersections( nRibsGrp, LayerParams, nOffsGrp, nRibsPathGrp, bAllTwoStrands) EgtSetInfo( nRibsPathGrp or GDB_ID.NULL, KEY_RIBS_INTERS, bInters) EgtSetInfo( nRibsPathGrp or GDB_ID.NULL, KEY_RIBS_TWO_STRANDS, bAllTwoStrands) -- eseguo il trim delle costole con la regione offsettata local tOldNewIds = {} local tRemoved = {} local vOrderedRibs = EgtGetNameInGroup( nRibsPathGrp, RIBS_CRV ..'*') for i = 1, #vOrderedRibs do -- trim con superficie opportuna local nOverlap = EgtGetInfo( vOrderedRibs[i], KEY_RIBS_OVERLAP, 'i') local nType = EgtGetInfo( vOrderedRibs[i], KEY_RIBS_TYPE, 'i') if not tSurfOffs[nType][nOverlap] then -- la costolatura non è fattibile EgtOutLog( 'Warning: Ribs not possibile (layer '..tostring( nIdx)..') - CalcPaths') EgtErase( vOrderedRibs[i]) else local nCrv, nCnt if tSurfOffs[nType][nOverlap] == GDB_ID.NULL then -- caso unbounded nCrv = vOrderedRibs[i] nCnt = 1 else nCrv, nCnt = EgtTrimCurveWithRegion( vOrderedRibs[i], tSurfOffs[nType][nOverlap], EgtIf( nType == RIB_TYPE.INTERNAL, true, false), false) end tOldNewIds[ vOrderedRibs[i]] = {} -- elimino tratti troppo corti for nInd = 0, nCnt - 1 do local dLen = EgtCurveLength( nCrv + nInd) if dLen < MIN_RIBS_LEN then -- conservo eventuale info di split local nSplitRib = EgtGetInfo( nCrv + nInd, KEY_SPLIT_RIB, 'i') if nSplitRib then tRemoved[vOrderedRibs[i]] = nSplitRib end -- cancello la curva EgtErase( nCrv + nInd) else table.insert( tOldNewIds[ vOrderedRibs[i]], nCrv + nInd) -- controllo la direzione (consideriamo inclinazione solo lungo X) local vtDir = EgtMV( nCrv + nInd) local dXl = sqrt( sqr( vtDir:getX()) + sqr( vtDir:getZ())) local dYl = abs( vtDir:getY()) local dVal = EgtIf( dXl > dYl - GEO.EPS_SMALL, vtDir:getX(), vtDir:getY()) local bInvert = dVal < - GEO.EPS_SMALL -- inversione della curva local bInvertInfo = EgtGetInfo( nCrv + nInd, KEY_RIBS_INVERT_DIR, 'b') or false if bInvert ~= bInvertInfo then EgtInvertCurve( nCrv + nInd) EgtSetInfo( nCrv + nInd, KEY_INVERTED_CRV, 1) end -- salvo info della superficie di trim associata EgtSetInfo( nCrv + nInd, KEY_ASSOCIATED_SURF, tSurfOffs[nType][nOverlap]) if nInd > 0 then EgtRemoveInfo( nCrv + nInd, KEY_SPLIT_RIB) end end end end end -- aggiorno le info di split con i nuovi id UpdateRibSplitInfo( nRibsPathGrp, tOldNewIds, tRemoved) -- riordino le costolature if bAllTwoStrands and bInters then -- gestione caso speciale di intersezione e 2 passate ReorderRibsInters2Shells( nRibsPathGrp, LayerParams.dStrand) else ReorderRibs( nRibsPathGrp, LayerParams.bRibsInvertOrder, LayerParams.bRibsDoLinkFirst, LayerParams.dStrand, nMaxNbr) end if not EgtGetFirstNameInGroup( nRibsPathGrp, RIBS_CRV .. '*') then EgtErase( nRibsPathGrp) end nCrvGrp = EgtGetNextName( nCrvGrp, CONTOUR_GRP .. '*') end end -------------------------------------------------------------------- ----------------- REGIONI CON DIVERSE PASSATE ---------------------- -------------------------------------------------------------------- local function CreateShellNbrSurfaces( nGrp, nShellsNbr) if not nGrp then return end local tDiffCrvs = {} local nMaxShellNbrDiff = 0 local nCrvId = EgtGetFirstNameInGroup( nGrp, SHELL_NBR_CRV .. '*') while nCrvId do if EgtCurveIsClosed( nCrvId) then -- recupero info sul gap local nShellNbrDiff = EgtGetInfo( nCrvId, KEY_SHELL_NBR_DIFF, 'i') -- aggiorno eventuale massimo if nMaxShellNbrDiff < nShellNbrDiff then nMaxShellNbrDiff = nShellNbrDiff end -- salvo gli id delle curve if not tDiffCrvs[nShellNbrDiff] then tDiffCrvs[nShellNbrDiff] = { nCrvId} else table.insert( tDiffCrvs[nShellNbrDiff], nCrvId) end end nCrvId = EgtGetNextName( nCrvId, SHELL_NBR_CRV .. '*') end -- eventuale correzione del numero massimo in base al numero di passate nMaxShellNbrDiff = min( nMaxShellNbrDiff, nShellsNbr) -- costruisco per ogni valore la superficie complessiva local nSrfGrp = EgtGroup( nGrp) for nDiff = 1, nMaxShellNbrDiff do -- recupero gli id delle curve coinvolte local vCrvIds = {} for nG, vIds in pairs( tDiffCrvs) do if nG >= nDiff then for k = 1, #vIds do table.insert( vCrvIds, vIds[k]) end end end -- costruisco la surf local nSrfId = EgtSurfFlatRegion( nSrfGrp, vCrvIds[1]) for i = 2, #vCrvIds do local nSrfTmp = EgtSurfFlatRegion( nSrfGrp, vCrvIds[i]) EgtSurfFrAdd( nSrfId, nSrfTmp) EgtErase( nSrfTmp) end EgtSetName( nSrfId, SHELL_NBR_SURF .. tostring( nDiff)) -- salvo come info gli id delle curve che la definiscono EgtSetInfo( nSrfId, KEY_ASSOCIATED_CRVS, vCrvIds) end end -------------------------------------------------------------------- local function ComputeMaxShellNbrDiff( nSrf, nShellNbrSurfGrp) local nMaxShellNbrDiff = 0 if nShellNbrSurfGrp then local nId = 1 local nShellNbrSrf = EgtGetFirstNameInGroup( nShellNbrSurfGrp, SHELL_NBR_SURF .. tostring( nId)) while nShellNbrSrf do -- se interessa la regione considerata aggiorno il nMaxShellNbrDiff if not EgtSurfFrTestExternal( nSrf, nShellNbrSrf) then nMaxShellNbrDiff = nId end -- passo al successivo nId = nId + 1 nShellNbrSrf = EgtGetFirstNameInGroup( nShellNbrSurfGrp, SHELL_NBR_SURF .. tostring( nId)) end end return nMaxShellNbrDiff end ---------------------------------------------------------------- local function FindExtraShellRetractionParams( ptP, vIds, LayerParams) local dCoasting, dWipe, dWipeDir -- cerco la curva sulla quale si ferma for i = 1, #vIds do local dPar = EgtCurveParamAtPoint( vIds[i], ptP, 10 * GEO.EPS_SMALL) if dPar then dCoasting = EgtGetInfo( vIds[i], KEY_SHELL_NBR_COASTING, 'd') dWipe = EgtGetInfo( vIds[i], KEY_SHELL_NBR_WIPE, 'd') dWipeDir = EgtGetInfo( vIds[i], KEY_SHELL_NBR_WIPE_DIR, 'd') break end end if not dCoasting then -- se non ho trovato una curva considero i parametri generali return LayerParams.dShellNbrCoasting, LayerParams.dShellNbrWipe, LayerParams.dShellNbrWipeDir else return dCoasting, dWipe, dWipeDir end end ----------------------------------------------------------------- local function TrimOuterCurveForExtraShellCalc( nOuterCrv, nSrfDiff, nGrpId, vPtStart, LayerParams) local nCopy = EgtCopyGlob( nOuterCrv, nGrpId) ModifyStartPoint( nCopy, vPtStart) -- recupero tutte le curve delle ShellNumber coinvolte local vShellNbrCrvs = EgtGetInfo( nSrfDiff, KEY_ASSOCIATED_CRVS, 'vi') -- trim della curva local nCrv, nCnt = EgtTrimCurveWithRegion( nCopy, nSrfDiff, false, false) if nCrv and nCnt ~= 0 then -- verifico se prima e ultima curva possono essere unite if nCnt > 1 and AreSamePointApprox( EgtEP( nCrv + nCnt - 1), EgtSP( nCrv)) then local nNewId = EgtCurveCompo( nGrpId, { nCrv + nCnt - 1, nCrv}) EgtChangeId( nNewId, nCrv) nCnt = nCnt - 1 end -- assegno le info in base alla curva che li delimita for nId = nCrv, nCrv + nCnt - 1 do local ptS = EgtSP( nId) local dCoastingS, dWipeS, dWipeDirS = FindExtraShellRetractionParams( ptS, vShellNbrCrvs, LayerParams) local ptE = EgtEP( nId) local dCoastingE, dWipeE, dWipeDirE = FindExtraShellRetractionParams( ptE, vShellNbrCrvs, LayerParams) EgtSetInfo( nId, KEY_EXTRA_SHELL_COASTING, {dCoastingS, dCoastingE}) EgtSetInfo( nId, KEY_EXTRA_SHELL_WIPE, {dWipeS, dWipeE}) EgtSetInfo( nId, KEY_EXTRA_SHELL_WIPE_DIR, {dWipeDirS, dWipeDirE}) end return nCrv, nCnt else return nOuterCrv, 0 end end -------------------------------------------------------------------- local function UpdateTotalShellSurf( nSrf, nCrv, dStrand, nGrpId) local nSrfExtraShell = EgtSurfFrFatCurve( nGrpId, nCrv, dStrand - s_dOffsCorr, false) if nSrfExtraShell then local vtSrfN = EgtSurfFrNormVersor( nSrf, GDB_ID.ROOT) local vtSrfExShN = EgtSurfFrNormVersor( nSrfExtraShell, GDB_ID.ROOT) if vtSrfExShN * vtSrfN < 0 then EgtInvertSurf( nSrfExtraShell) end EgtSurfFrSubtract( nSrf, nSrfExtraShell) EgtErase( nSrfExtraShell) end end --------------------------------------------------------------------- local function ReorderExtraShells( nPathGrp, dStrand, vPtStart, bPrintInvert) -- verifico se posso unire due tratti consecutivi della stessa shell local nFirst = EgtGetFirstNameInGroup( nPathGrp, EXTRA_SHELL_CRV .. '*') while nFirst do -- recupero tratti appartenenti alla stessa shell local vShells = EgtGetNameInGroup( nPathGrp, EgtGetName( nFirst)) local nCurr = vShells[1] for i = 2, #vShells do if dist( EgtEP( nCurr), EgtSP( vShells[i])) < dStrand + GEO.EPS_SMALL then -- unisco le curve EgtAddCurveCompoLine( nCurr, EgtSP( vShells[i])) EgtAddCurveCompoCurve( nCurr, vShells[i]) else nCurr = vShells[i] end end -- check su prima e ultima curva if nCurr ~= nFirst and dist( EgtEP( nCurr), EgtSP( nFirst)) < dStrand + GEO.EPS_SMALL then -- unisco le curve EgtAddCurveCompoLine( nCurr, EgtSP( nFirst)) EgtAddCurveCompoCurve( nCurr, nFirst) end nFirst = EgtGetNextName( nCurr, EXTRA_SHELL_CRV .. '*') end local vIds = EgtGetNameInGroup( nPathGrp, EXTRA_SHELL_CRV .. '*') if not vIds then return end -- eventuale inversione di tutte le curve if bPrintInvert then for i = 1, #vIds do EgtInvertCurve( vIds[i]) EgtSetInfo( vIds[i], KEY_INVERTED_CRV, 1) end end -- cerco di creare percorsi local k = 0 -- indice da utilizzare per i nomi while #vIds > 0 do k = k + 1 -- prendo la prima tra le curve a disposizione nCurrCrv = vIds[1] table.remove( vIds, 1) EgtSetName( nCurrCrv, EXTRA_SHELL_CRV .. tostring(k)) local ptSCurr = EgtSP( nCurrCrv) local ptECurr = EgtEP( nCurrCrv) local nCnt = 0 -- se curva è chiusa if EgtCurveIsClosed( nCurrCrv) then ModifyStartPoint( nCurrCrv, vPtStart) -- setto a nil per ripartire subito con curva successiva nCurrCrv = nil end -- scorro alla ricerca di una curva che posso collegare alla corrente while nCurrCrv do local bFound = false for j = 1, #vIds do if not EgtCurveIsClosed( vIds[j]) then local ptS = EgtSP( vIds[j]) local ptE = EgtEP( vIds[j]) local bLink = dist( ptS, ptECurr) < 1.5 * dStrand if dist( ptE, ptECurr) < 1.5 * dStrand then -- congiungo end-end EgtInvertCurve( vIds[j]) EgtSetInfo( vIds[j], KEY_INVERTED_CRV, EgtIf( bPrintInvert, 0, 1)) bLink = true elseif nCnt == 0 and dist( ptS, ptSCurr) < 1.5 * dStrand then -- congiungo start-start EgtInvertCurve( nCurrCrv) EgtSetInfo( nCurrCrv, KEY_INVERTED_CRV, EgtIf( bPrintInvert, 0, 1)) bLink = true end if bLink then nCnt = nCnt + 1 EgtRelocateGlob( vIds[j], nCurrCrv, GDB_IN.AFTER) EgtSetName( vIds[j], EXTRA_SHELL_CRV .. tostring( k)) -- aggiorno per collegamento successivo bFound = true nCurrCrv = vIds[j] ptSCurr = EgtSP( vIds[j]) ptECurr = EgtEP( vIds[j]) table.remove( vIds, j) break end end end -- se non ho più curve da collegare if not bFound then nCurrCrv = nil end end end end -------------------------------------------------------------------- local function CalcExtraShellsPath( nMaxShellNbrDiff, nShellNbrGrp, nCrvGrpId, dOffs, LayerParams, nIdx, vPtStart) local nGrpId = EgtGetFirstNameInGroup( nCrvGrpId, PATH_GRP) -- recupero la superficie occupata dalle shell per trim local nSrfTrim = EgtGetFirstNameInGroup( nCrvGrpId, TOT_SHELL_TRIM_SURF) if not nSrfTrim then EgtOutLog( 'Warning : ExtraInnerShells not possible (layer '..tostring( nIdx)..') - CalcPaths') return end for nInd = nMaxShellNbrDiff, 1, -1 do dOffs = dOffs + LayerParams.dStrand * ( 1 - EgtIf( nInd == LayerParams.nShellsNbr, 0, LayerParams.nStrandOverlap / 100)) local nSrfDiff = EgtGetFirstNameInGroup( nShellNbrGrp, SHELL_NBR_SURF .. tostring( nInd)) local nOuterCrv = EgtGetFirstNameInGroup( nCrvGrpId, OUTER_CRV) while nOuterCrv do -- trim della curva con la superficie local nTrimCrv, nTrimCnt = TrimOuterCurveForExtraShellCalc( nOuterCrv, nSrfDiff, nGrpId, vPtStart, LayerParams) for nCrvT = nTrimCrv, nTrimCrv + nTrimCnt - 1 do -- calcolo offset della curva ( è il percorso della shell) EgtModifyCurveExtrusion( nCrvT, LayerParams.vtSlicing, GDB_RT.GLOB) local nOffs, nOffsCnt = EgtOffsetCurveAdv( nCrvT, - dOffs) EgtErase( nCrvT) for nCrvOffs = nOffs, nOffs + nOffsCnt - 1 do -- trim con la regione già occupata dal altre shell local nCrv, nCnt = EgtTrimCurveWithRegion( nCrvOffs, nSrfTrim, true, true) if nCrv and nCnt ~= 0 then for nId = nCrv, nCrv + nCnt - 1 do local dLen = EgtCurveLength( nId) local bValid = true if EgtCurveIsClosed( nId) then bValid = VerifyPath( nId, LayerParams.dStrand, LayerParams.vtSlicing, nGrpId) end -- verifico se soddisfa vincolo sulla lunghezza if dLen > MIN_LEN and bValid then EgtModifyCurveExtrusion( nId, LayerParams.vtSlicing, GDB_RT.GLOB) EgtSetName( nId, EXTRA_SHELL_CRV .. tostring( nMaxShellNbrDiff - nInd + 1)) if nInd == LayerParams.nShellsNbr then EgtSetInfo( nId, KEY_TYPE, TYPE.EXTRA_OUTER_SHELL) else EgtSetInfo( nId, KEY_TYPE, TYPE.EXTRA_SHELL) end -- aggiorno la superficie occupata dalle shell con quella appena calcolata (tenendo conto dell'overlap) UpdateTotalShellSurf( nSrfTrim, nId, ( 1 - LayerParams.nStrandOverlap / 100) * LayerParams.dStrand, nGrpId) -- se la superficie si annulla non è possibile realizzare altro, quindi cancello tutte le curve rimaste if EgtSurfFrChunkCount( nSrfTrim) == 0 then for j = nId + 1, nCrv + nCnt - 1 do EgtErase( j) end for j = nCrvT + 1, nTrimCrv + nTrimCnt - 1 do EgtErase( j) end -- aggiorno superficie EgtSurfFrOffset( nSrfTrim, - LayerParams.nStrandOverlap / 100 * LayerParams.dStrand) -- riordino le curve appena create e se possibile creo percorsi chiusi ReorderExtraShells( nGrpId, LayerParams.dStrand, vPtStart, LayerParams.bPrintInvert) return end else EgtErase( nId) end end end end end nOuterCrv = EgtGetNextName( nOuterCrv, OUTER_CRV) end end -- aggiorno superificie EgtSurfFrOffset( nSrfTrim, - LayerParams.nStrandOverlap / 100 * LayerParams.dStrand) -- riordino le curve appena create e se possibile creo percorsi chiusi ReorderExtraShells( nGrpId, LayerParams.dStrand, vPtStart, LayerParams.bPrintInvert) end -------------------------------------------------------------------- ------------------ AUX SOLIDS ------------------------------------- -------------------------------------------------------------------- local function UpdateTrimSurfWithAuxSolidsOffset( nSrfSolid, nSrfBase, dStrand, nCrvGrp, vtSlicing) -- offset della superifice del solido local bOk, bExists, nSrfOffs = ComputeSurfOffset( nSrfSolid, nCrvGrp, dStrand, vtSlicing) if nSrfOffs then EgtSurfFrSubtract( nSrfBase, nSrfOffs) EgtErase( nSrfOffs) end end -------------------------------------------------------------------- local function UpdateTrimSurfWithAuxSolidsZigZag( nAuxSolidsGrp, sName, nSrfBase, dStrand, nSrf) local nGrpTmp = EgtGroup( nAuxSolidsGrp) -- gruppo temporaneo per conti -- recupero le curve associate local vCrvs = EgtGetNameInGroup( nAuxSolidsGrp, sName) for i = 1, #vCrvs do local vtDir = EgtSV( vCrvs[i]) -- costruisco percorso associato local nCopyCrv = EgtCopyGlob( vCrvs[i], nGrpTmp) local nCopy2 = EgtCopyGlob( vCrvs[i], nGrpTmp) EgtInvertCurve( nCopy2) EgtAddCurveCompoCurve( nCopyCrv, nCopy2) local nOffsP = EgtOffsetCurveAdv( nCopyCrv, dStrand, GDB_OT.FILLET) local nFirst, nCnt = EgtExplodeCurveCompo( nOffsP, nGrpTmp) -- cerco tratti lineari orientati ortogonalmente alla direzione di svuotatura local nRes = EgtCurveCompo( nGrpTmp, {nFirst}) local nInd = nFirst + 1 while nInd < nFirst + nCnt do local vtCurrDir = EgtSV( nInd) local nType = EgtGetType( nInd) -- se è linea ortognale alla direzione della svuotatura la approssimo if nType == GDB_TY.CRV_LINE and abs( vtDir * vtCurrDir) < 10 * GEO.EPS_SMALL then -- cerco ultima curva con lo stesso orientamento local nLastValidId = nInd local nInd2 = nInd + 1 while nInd2 < nFirst + nCnt do nType = EgtGetType( nInd2) if nType == GDB_TY.CRV_LINE then if AreSameVectorApprox( EgtSV( nInd2), vtCurrDir) then nLastValidId = nInd2 else break end end nInd2 = nInd2 + 1 end -- aggiungo l'approssimazione lineare EgtAddCurveCompoLine( nRes, EgtEP( nLastValidId)) -- setto l'indice per ripartire correttamente dopo l'approssimazione nInd = nLastValidId else -- se arco o linea inclinata, aggiungo direttamente al percorso EgtAddCurveCompoCurve( nRes, nInd) end nInd = nInd + 1 end -- utilizzo la curva per creare superficie local nSrfZigZag = EgtSurfFlatRegion( nGrpTmp, {nRes}) if nSrfZigZag then EgtSurfFrSubtract( nSrfBase, nSrfZigZag) else EgtSurfFrSubtract( nSrfBase, nSrf) end end EgtErase( nGrpTmp) end ------------------------------------------------------------------- local function AddExtraZigZag( nSrf, sName, dStrand, vtSlicing, nGrp, nSrfTrim) local vIds = EgtGetNameInGroup( nGrp, sName) local vtDir = EgtSV( vIds[1], GDB_ID.ROOT) local vtYLoc = vtSlicing ^ vtDir local nOuterLoop = EgtExtractSurfFrChunkLoops( nSrf, 0, nGrp) for i = 1, #vIds do local _, dParE = EgtCurveDomain( vIds[i]) local ptS = EgtUP( vIds[i], dParE - 1, GDB_ID.ROOT) + dStrand * vtYLoc local ptE = EgtEP( vIds[i], GDB_ID.ROOT) + dStrand * vtYLoc 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 -- verifico se si trova nella regione ammissibile if EgtCurveWithRegionClassify( nExtraCrv, nSrfTrim) == GDB_CRC.IN then EgtInvertCurve( nExtraCrv) EgtAddCurveCompoLine( vIds[i], ptE, GDB_RT.GLOB) EgtAddCurveCompoCurve( vIds[i], nExtraCrv) end end EgtErase( nExtraCrv) end EgtErase( nOuterLoop) end -------------------------------------------------------------------- local function CalcAuxSolidsPaths( nSliceGrp, nSolidGrp, LayerParams, vPtStart) -- recupero i solidi ausiliari local vSolidIds = EgtGetAllInGroup( nSolidGrp) -- scorro i gruppi di curve local nCrvGrp = EgtGetFirstNameInGroup( nSliceGrp, CONTOUR_GRP .. '*') while nCrvGrp do -- creo o svuoto il gruppo per i solidi ausiliari local nSolidPathGrp = EgtGetFirstNameInGroup( nCrvGrp, AUX_SOLIDS_GRP) if not nSolidPathGrp then nSolidPathGrp = EgtGroup( nCrvGrp) EgtSetName( nSolidPathGrp, AUX_SOLIDS_GRP) EgtSetStatus( nSolidPathGrp, GDB_ST.OFF) else EgtEmptyGroup( nSolidPathGrp) end -- creo le superfici con cui fare i trim local nSrfBase = EgtGetFirstNameInGroup( nCrvGrp, TOT_SHELL_TRIM_SURF) 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) 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 nSrfId = EgtSurfFlatRegion( nSolidPathGrp, vSolidIds[i]) EgtSetName( nSrfId, AUX_SOLIDS_SRF) -- trim con la superficie di offset EgtSurfFrIntersect( nSrfId, vSurfOffs[nOverlap]) 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') 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) -- aggiungo eventuale passata extra AddExtraZigZag( nFirst + j, sNewName, LayerParams.dStrand, LayerParams.vtSlicing, nSolidPathGrp, vSurfOffs[nOverlap]) -- aggiorno la trim surf UpdateTrimSurfWithAuxSolidsZigZag( nSolidPathGrp, sNewName, nSrfBase, LayerParams.dStrand, nFirst + j) 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 if not EgtGetFirstNameInGroup( nSolidPathGrp, AUX_SOLIDS_CRV .. '*') then EgtErase( nSolidPathGrp) end -- passo al gruppo di contorni successivo nCrvGrp = EgtGetNextName( nCrvGrp, CONTOUR_GRP .. '*') end end --------------------------------------------------------------------- function CalcPaths.Exec( nPartId) s_nPartId = nPartId local vLayIds = EgtGetNameInGroup( s_nPartId, SLICE_LAYER.."*") if not vLayIds then EgtOutBox( 'Error no slice', 'PathCalc') return end -- recupero i parametri per calcolo dei path local LayerParams = GetLayerParamsForPathCalc() -- scorro tutti i suoi layer for nIdx = 1, #vLayIds do local nRibsGrp = EgtGetFirstNameInGroup( vLayIds[nIdx], RIBS_GRP) local nAuxSolidsGrp = EgtGetFirstNameInGroup( vLayIds[nIdx], AUX_SOLIDS_GRP) -- regioni con diverso numero di passate local nShellNbrGrp = EgtGetFirstNameInGroup( vLayIds[nIdx], SHELL_NBR_GRP) local nMaxShell = max( LayerParams.nShellsNbr, LayerParams.nFloorNbr, LayerParams.nCeilNbr) CreateShellNbrSurfaces( nShellNbrGrp, nMaxShell) local nShellNbrSurfGrp = EgtGetFirstGroupInGroup( nShellNbrGrp or GDB_ID.NULL) -- recupero gli start point per il layer local vPtStart = GetLayerStartPoint( vLayIds[nIdx], LayerParams.vtSlicing) -- scorro tutti i gruppi di contorni local nCrvGrpId = EgtGetFirstNameInGroup( vLayIds[nIdx], CONTOUR_GRP.."*") or GDB_ID.NULL while nCrvGrpId ~= GDB_ID.NULL do -- verifico se il path è già stato calcolato local nGrpId = EgtGetFirstNameInGroup( nCrvGrpId, PATH_GRP) or GDB_ID.NULL if nGrpId == GDB_ID.NULL then nGrpId = EgtGroup( nCrvGrpId) EgtSetName( nGrpId, PATH_GRP) else EgtEmptyGroup( nGrpId) EgtSetStatus( nGrpId, GDB_ST.ON) end -- recupero la superficie ottenuta dallo slicing local nSrf = EgtGetFirstNameInGroup( nCrvGrpId, LAYER_SRF) if nSrf then local nMaxShellNbrDiff = ComputeMaxShellNbrDiff( nSrf, nShellNbrSurfGrp) nMaxShellNbrDiff = min( nMaxShellNbrDiff, LayerParams.nShellsNbr) -- parete esterna local dOffs = - LayerParams.dOffs - 0.5 * LayerParams.dStrand if nMaxShellNbrDiff < LayerParams.nShellsNbr then dOffs = dOffs + LayerParams.dStrand local bOk, bExists, nSrfId = ComputeSurfOffset( nSrf, nCrvGrpId, - dOffs, LayerParams.vtSlicing) if not bOk then EgtOutLog( 'Error on ExtOffset (layer '..tostring( nIdx)..') - CalcPaths') elseif not bExists then EgtOutLog( 'Warning : ExtOffset not possible (layer '..tostring( nIdx)..') - CalcPaths') else -- se offset riuscito, estraggo i contorni (pareti esterne) GetPathsFromSurf( nSrfId, SHELL_CRV ..'0', TYPE.OUTER_SHELL, nGrpId, vPtStart) end EgtErase( nSrfId) end local vPtInnerStart = {} local vOuterShell = EgtGetNameInGroup( nGrpId, SHELL_CRV .. '0') or {} for i = 1, #vOuterShell do table.insert( vPtInnerStart, EgtSP( vOuterShell[i])) end if #vPtInnerStart == 0 then vPtInnerStart = vPtStart end -- pareti interne complete for nInd = 1, LayerParams.nShellsNbr - 1 - nMaxShellNbrDiff do -- offset della superficie originale dOffs = dOffs + LayerParams.dStrand * ( 1 - LayerParams.nStrandOverlap / 100) local bOk, bExists, nSrfId = ComputeSurfOffset( nSrf, nCrvGrpId, - dOffs, LayerParams.vtSlicing) if not bOk then EgtOutLog( 'Error on IntOffset (layer '..tostring( nIdx)..') - CalcPaths') elseif not bExists then EgtOutLog( 'Warning : IntOffset not possible (layer '..tostring( nIdx)..') - CalcPaths') else -- se offset riuscito, estraggo i contorni ( pareti interne) GetPathsFromSurf( nSrfId, SHELL_CRV..tostring( nInd), TYPE.INNER_SHELL, nGrpId, vPtInnerStart) end EgtErase( nSrfId) end -- preparo superficie occupata dalle shell da usare per trim local dSurfTrimOffs = dOffs + LayerParams.dStrand if nMaxShellNbrDiff > 0 then -- se hai extra shell tieni conto anche dell'overlap ammesso dSurfTrimOffs = dOffs + ( 1 - LayerParams.nStrandOverlap / 100) * LayerParams.dStrand - s_dOffsCorr end local bOkTrim, bExistsTrim, nSrfTrim = ComputeSurfOffset( nSrf, nCrvGrpId, - dSurfTrimOffs, LayerParams.vtSlicing) if not bOkTrim then EgtOutLog( 'Error on IntOffset (layer '..tostring( nIdx)..') - CalcPaths') elseif bExistsTrim then EgtSetName( nSrfTrim, TOT_SHELL_TRIM_SURF) EgtSetStatus( nSrfTrim, GDB_ST.OFF) end -- eventuali pareti interne coinvolte dal diverso numero di passate if nMaxShellNbrDiff > 0 then CalcExtraShellsPath( nMaxShellNbrDiff, nShellNbrSurfGrp, nCrvGrpId, dOffs, LayerParams, nIdx, vPtInnerStart) end -- gestione eventuale floor/ceil if nIdx <= LayerParams.nFloorNbr then local nSurfInfill = AdjustSurfForFloorCeil( LayerParams.nFloorNbr - nIdx + 1, nSrfTrim, nShellNbrSurfGrp) or nSrfTrim 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) end EgtErase( nSurfInfill) elseif nIdx > #vLayIds - LayerParams.nCeilNbr then local nSurfInfill = AdjustSurfForFloorCeil( LayerParams.nCeilNbr - ( #vLayIds - nIdx), nSrfTrim, nShellNbrSurfGrp) or nSrfTrim if LayerParams.nCeilType == INFILL_TYPE.OFFSET then ComputeOffsetInfill( nSurfInfill, LayerParams.dStrand, LayerParams.vtSlicing, INFILL_CRV, TYPE.INFILL, vPtStart, nGrpId) elseif LayerParams.nCeilType == INFILL_TYPE.ZIGZAG then ComputeZigZagInfill( nSurfInfill, LayerParams.dStrand, LayerParams.vtSlicing, INFILL_CRV, TYPE.INFILL, vPtStart, nGrpId) end EgtErase( nSurfInfill) end end -- passo al gruppo di contorni successivo nCrvGrpId = EgtGetNextName( nCrvGrpId, CONTOUR_GRP.."*") or GDB_ID.NULL end if nIdx > LayerParams.nFloorNbr and nIdx <= #vLayIds - LayerParams.nCeilNbr then -- sistemo eventuali solidi ausiliari if nAuxSolidsGrp then CalcAuxSolidsPaths( vLayIds[nIdx], nAuxSolidsGrp, LayerParams, vPtStart) end -- sistemo eventuali costolature if nRibsGrp then CalcRibsPaths( vLayIds[nIdx], nRibsGrp, LayerParams, nIdx) end end if EgtProcessEvents( EgtIf( PRINT, 200, 0) + nIdx / #vLayIds * 100, 0) == 1 then EgtDraw() return end end end --------------------------------------------------------------------- return CalcPaths