-- RunCalcSolids.lua by Egaltech s.r.l. 2022/11/02 -- Calcolo percorsi di lavoro per Stampa 3d -- Tabella per definizione modulo local RunCalcSolids = {} -- Intestazioni require( 'EgtBase') EgtOutLog( ' RunCalcSolids started', 1) -- Dati local AMD = require( 'AddManData') -------------------------------------------------------------------- local s_dTol = 0.1 local s_nSimplifiedSection = 0 local s_dMultiPlanarH = 0 local s_dColorFactor = 0.9 local s_nPartId --------------------------------------------------------------------- local function GetLayerParamsForSolidCalc( nPartId) local LayerParams = {} LayerParams.bSpiralVase = EgtGetInfo( nPartId, KEY_SPIRAL_VASE, 'b') or false LayerParams.dLayHeight = EgtGetInfo( nPartId, KEY_SLICE_STEP, 'd') LayerParams.vtSlicing = EgtGetInfo( nPartId, KEY_SLICE_DIR, 'v') or EgtGetInfo( nPartId, 'SlicingDir', 'v') LayerParams.dStrand = EgtGetInfo( nPartId, KEY_STRAND, 'd') LayerParams.vtCorr = EgtGetInfo( nPartId, KEY_MOVED_PART2, 'v') or V_NULL() return LayerParams end --------------------------------------------------------------------- local function CalcSectionParams( dStrand, dH) local dBevelX = 0 local dBevelY = 0 if s_nSimplifiedSection == 0 then -- sezione ottagonale dBevelX = dStrand / 10 dBevelY = dH / 6 end return dBevelX, dBevelY end ---------------------------------------------------------------------- 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 --------------------------------------------------------------------- local function CreateSection( ptS, vtDir, dStrand, dH, vtSlicing, nSolidGrp) local dBevelX, dBevelY = CalcSectionParams( dStrand, dH) local ptA = ptS - dH * vtSlicing + ( 0.5 * dStrand - dBevelX) * vtDir local ptB = ptA + dBevelY * vtSlicing + dBevelX * vtDir local ptC = ptB + ( dH - 2 * dBevelY) * vtSlicing local ptD = ptA + dH * vtSlicing local ptE = ptD - ( dStrand - 2 * dBevelX) * vtDir local ptF = ptC - dStrand * vtDir local ptG = ptB - dStrand * vtDir local ptH = ptA - ( dStrand - 2 * dBevelX) * vtDir local nId = EgtCurveCompoFromPoints( nSolidGrp, {ptA, ptB, ptC, ptD, ptE, ptF, ptG, ptH, ptA}, GDB_RT.GLOB) EgtInvertCurve( nId) return nId end ------------------------------------------------------------------------------ local function CreateSpiralVaseCap( nSectId, vtDir, nSolidGrp) local vPt = {} local nLast = EgtIf( s_nSimplifiedSection == 1, 3, 7) for i = 0, nLast do vPt[i + 1] = EgtUP( nSectId, i, GDB_ID.ROOT) end local vCrvs = {} -- calcolo gli archi che definiscono la superficie laterale if s_nSimplifiedSection == 1 then -- sezione quadrata vCrvs[1] = EgtArc2PV( nSolidGrp, vPt[1], vPt[2], vtDir, GDB_RT.GLOB) vCrvs[2] = EgtArc2PV( nSolidGrp, vPt[4], vPt[3], vtDir, GDB_RT.GLOB) else -- sezione ottagonale vCrvs[1] = EgtArc2PV( nSolidGrp, vPt[1], vPt[2], vtDir, GDB_RT.GLOB) vCrvs[2] = EgtArc2PV( nSolidGrp, vPt[8], vPt[3], vtDir, GDB_RT.GLOB) vCrvs[3] = EgtArc2PV( nSolidGrp, vPt[7], vPt[4], vtDir, GDB_RT.GLOB) vCrvs[4] = EgtArc2PV( nSolidGrp, vPt[6], vPt[5], vtDir, GDB_RT.GLOB) end -- creo le rigate local vSurfs = {} for i = 1, #vCrvs - 1 do vSurfs[i] = EgtSurfTmRuled( nSolidGrp, vCrvs[i], vCrvs[i+1], GDB_RUL.ISOPAR, s_dTol) end -- calcolo le superfici top e bottom del cap local nCrvBottom = EgtCurveCompo( nSolidGrp, {vCrvs[1]}, false, GDB_RT.GLOB) EgtCloseCurveCompo( nCrvBottom) local nSurfBottom = EgtSurfTmByRegion( nSolidGrp, nCrvBottom, s_dTol) local nCrvTop = EgtCurveCompo( nSolidGrp, {vCrvs[#vCrvs]}, false, GDB_RT.GLOB) EgtCloseCurveCompo( nCrvTop) local nSurfTop = EgtSurfTmByRegion( nSolidGrp, nCrvTop, s_dTol) table.insert( vSurfs, nSurfTop) table.insert( vSurfs, nSurfBottom) local nCapSrf = EgtSurfTmByTriangles( nSolidGrp, vSurfs) -- cancello curve di costruzione EgtErase( vCrvs) EgtErase( nCrvTop) EgtErase( nCrvBottom) return nCapSrf end ------------------------------------------------------------------------------- local function CreateSpiralVaseSolid( nCrvId, nSolidGrp, vtSlicing, dH, dStrand) -- gruppo temporaneo per conti 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) EgtTrimCurveEndAtLen( nCrvId, dLen - 20 * GEO.EPS_SMALL) local ptS = EgtSP( nCrvId, GDB_ID.ROOT) 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) * vtSlicing -- se non è vero spiral vase, chiamo funzione standard if dDelta < GEO.EPS_SMALL then EgtErase( nGrpTmp) return CreateStandardSolid( nCrvId, nSolidGrp, dH, dStrand) end -- appiattisco la curva local nCrvCopy = EgtCopyGlob( nCrvId, nGrpTmp) 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( vtSlicing, 90) local nSectId = CreateSection( ptS, vtDir, dStrand, dH, vtSlicing, nGrpTmp) -- creo la sezione finale local vtDir2 = EgtEV( nCrvCopy, GDB_ID.ROOT) vtDir2:rotate( vtSlicing, 90) local nSectE = CreateSection( ptE, vtDir2, dStrand, dH, vtSlicing, nGrpTmp) -- creo il solido aperto (tubo) 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( nCrvCopy, dOffs) if not vCrvs[i+1] or vCrvs[i+1] == GDB_ID.NULL then EgtErase( nGrpTmp) return nil end 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 EgtApproxCurve( vCrvs[i+1], GDB_CA.LINES, s_dTol) EgtModifyCurveStartPoint( vCrvs[i+1], ptRef, GDB_RT.GLOB) local ptRefEnd = EgtUP( nSectE, i, GDB_ID.ROOT) local _, _, dParMinDist = EgtPointCurveDist( ptRefEnd, vCrvs[i+1], GDB_ID.ROOT) local _, dParE = EgtCurveDomain( vCrvs[i+1]) if abs( dParE - dParMinDist) > GEO.EPS_SMALL and dParMinDist > 0.5 * dParE then EgtTrimCurveEndAtParam( vCrvs[i+1], dParMinDist) end EgtModifyCurveEndPoint( vCrvs[i+1], ptRefEnd, 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 -- creazione del mezzo disco iniziale vSurfs[#vCrvs] = CreateSpiralVaseCap( nSectId, - vtS, nSolidGrp) -- creazione del mezzo disco finale vSurfs[#vCrvs+1] = CreateSpiralVaseCap( nSectE, vtE, nSolidGrp) EgtInvertSurf( vSurfs[#vCrvs+1]) local nSolidId = EgtSurfTmByTriangles( nSolidGrp, vSurfs) -- cancello le curve usate per la costruzione EgtErase( nGrpTmp) return nSolidId end -------------------------------------------------------------------------------------- local function CreateSolid( nCrvId, nSolidGrp, LayerParams, dH, dStrand) if LayerParams.bSpiralVase then return CreateSpiralVaseSolid( nCrvId, nSolidGrp, LayerParams.vtSlicing, dH, dStrand) else return CreateStandardSolid( nCrvId, nSolidGrp, dH, dStrand) end end --------------------------------------------------------------------- local function CreateDirectionArrow( nCrvId, nSolidGrp, vtSlicing, dStrand, nSliceNbr) local ptS = EgtSP( nCrvId, GDB_RT.GLOB) local vtS = EgtSV( nCrvId, GDB_RT.GLOB) local dCrvLen = EgtCurveLength( nCrvId) if dCrvLen > 2 * dStrand then local dPar = EgtCurveParamAtLength( nCrvId, 4/5 * dStrand) ptS = EgtUP( nCrvId, dPar, GDB_RT.GLOB) vtS = EgtUV( nCrvId, dPar, -1, GDB_RT.GLOB) end local vt2 = Vector3d( vtS) vt2:rotate( vtSlicing, 90) local dLen = 4/5 * dStrand local pt1 = ptS + 0.5 * dLen * vt2 local pt2 = ptS - 0.5 * dLen * vt2 local pt3 = ptS + vtS * dLen local nCompo = EgtCurveCompoFromPoints( nSolidGrp, { pt1, pt2, pt3, pt1}, GDB_RT.GLOB) EgtMove( nCompo, 100 * GEO.EPS_SMALL * vtSlicing, GDB_RT.GLOB) local nSrf = EgtSurfFlatRegion( nSolidGrp, { nCompo}) EgtErase( nCompo) EgtSetColor( nSrf, RED()) EgtSetInfo( nSrf, KEY_SLICE_NBR, nSliceNbr) EgtSetStatus( nSrf, GDB_ST.OFF) EgtSetMode( nSrf, GDB_MD.HIDDEN) EgtSetName( nSrf, DIR_ARROW) end --------------------------------------------------------------------- local function CreateRecursiveSolid( nCrvId, vSurfs, nSolidGrp, LayerParams, dH, dStrand) -- tento la creazione del solido local nSurf = CreateSolid( nCrvId, nSolidGrp, LayerParams, dH, dStrand - 50 * GEO.EPS_SMALL) if nSurf then EgtErase( nCrvId) table.insert( vSurfs, nSurf) return true else -- se curva singola esco perchè non è possibile spezzare ulteriormente local _, dParE = EgtCurveDomain( nCrvId) if abs( dParE - 1) < GEO.EPS_SMALL then EgtErase( nCrvId) return false end -- se non si tratta di curva singola, spezzo a metà e tento sulle due sottocurve local dParSplit = floor( dParE / 2 + 0.5) local nCrvSplit = EgtSplitCurveAtParam( nCrvId, dParSplit) if not nCrvSplit then -- errore nello split EgtErase( nCrvId) return false end 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 CalcSolidGuides( nCrvId, dStrand, nSolidGrp) -- suddivido la curva in modo opportuno local nCopyId = EgtCopyGlob( nCrvId, nSolidGrp) local nId local nParts = 1 local LEN_REF = 100 local bZigZagInfill = EgtGetInfo( nCopyId, KEY_ZIG_ZAG_INFILL, 'b') or false if bZigZagInfill then nId, nParts = EgtSplitCurveAtCorners( nCopyId, 80) else local nType = EgtGetInfo( nCrvId, KEY_TYPE, 'i') local dLen = EgtCurveLength( nCrvId) if dLen > LEN_REF and nType ~= TYPE.LINK and nType ~= TYPE.COASTING then nParts = EgtClamp( floor( dLen / LEN_REF), 1, 10) end nId = EgtSplitCurve( nCopyId, nParts) end if not nId then return end -- verifico in modo euristico se la curva torna indietro su se stessa come se fossero due shell collegate ( verifico se è presente un sottotratto di lunghezza -- circa pari allo strand non in tangenza con i sottotratti vicini). Nel caso la spezzo per evitare problemi nel calcolo di solidi swept local vGuideIds = {} for nInd = 0, nParts - 1 do local nGuideId = nId + nInd table.insert( vGuideIds, nGuideId) if EgtGetType( nGuideId) == GDB_TY.CRV_COMPO then local _, dE = EgtCurveDomain( nGuideId) for dU = 1, dE - 2 do local dLen = EgtCurveCompoLength( nGuideId, dU) if abs( dLen - dStrand) < 500 * GEO.EPS_SMALL then -- verifico gli angoli local vtPrev = EgtUV( nGuideId, dU, -1, GDB_ID.ROOT) local vtCurrS = EgtUV( nGuideId, dU, 1, GDB_ID.ROOT) local vtCurrE = EgtUV( nGuideId, dU + 1, -1, GDB_ID.ROOT) local vtNext = EgtUV( nGuideId, dU + 1, 1, GDB_ID.ROOT) if vtPrev * vtCurrS < GEO.EPS_SMALL and vtCurrE * vtNext < GEO.EPS_SMALL then local nNewId = EgtSplitCurveAtParam( nGuideId, dU + 0.5) table.insert( vGuideIds, nNewId) break end end end end end return vGuideIds end --------------------------------------------------------------------- local function CreateSolidFromCurve( nCrvId, nSolidGrp, LayerParams, nSliceNbr, dLayerH) local nType = EgtGetInfo( nCrvId, KEY_TYPE, 'i') if nType == TYPE.WIPE then return true end -- scelta del colore local Color = EgtStdColor( 'GRAY') if nType == TYPE.OUTER_SHELL or nType == TYPE.EXTRA_OUTER_SHELL then Color = EgtStdColor( 'TEAL') elseif nType == TYPE.INNER_SHELL or nType == TYPE.EXTRA_SHELL then Color = EgtStdColor( 'ORANGE') elseif nType == TYPE.LINK then Color = EgtStdColor( 'GRAY') elseif nType == TYPE.INFILL then Color = EgtStdColor( 'YELLOW') elseif nType == TYPE.COASTING then Color = EgtStdColor( 'BLUE') elseif nType == TYPE.RIB then Color = EgtStdColor( 'OLIVE') elseif nType == TYPE.AUX_SOLID then Color = EgtStdColor( 'AQUA') end if s_nSimplifiedSection == 1 and nSliceNbr % 2 == 0 then Color = Color3d( s_dColorFactor * Color:getRed(), s_dColorFactor * Color:getGreen(), s_dColorFactor * Color:getBlue()) end -- parametri della passata local dStrand = EgtGetInfo( nCrvId, KEY_CRV_STRAND, 'd') or LayerParams.dStrand local dH = dLayerH or LayerParams.dLayHeight -- freccia direzionale local sName = EgtGetName( nCrvId) if nType ~= TYPE.COASTING and nType ~= TYPE.LINK and sName ~= LEAD_IN_CRV and sName ~= LEAD_OUT_CRV and sName ~= LINK_CRV then CreateDirectionArrow( nCrvId, nSolidGrp, LayerParams.vtSlicing, dStrand, nSliceNbr) end -- spezzo la curva guida in diversi sottotratti per i quali calcolare i solidi local vGuideIds = CalcSolidGuides( nCrvId, dStrand, nSolidGrp) if not vGuideIds then return false end local bOk = true for i = 1, #vGuideIds do local nSrfId = CreateSolid( vGuideIds[i], nSolidGrp, LayerParams, dH, dStrand - 5 * GEO.EPS_SMALL) if not nSrfId then EgtOutLog( 'Warning : CreateSolid failed '.. '(layer '..tostring( nSliceNbr)..', curve '..tostring( nCrvId)..')') -- ritento con strand più piccolo nSrfId = CreateSolid( vGuideIds[i], nSolidGrp, LayerParams, dH, dStrand - 50 * GEO.EPS_SMALL) if not nSrfId then EgtOutLog( 'Warning : CreateSolid_1 failed '.. '(layer '..tostring( nSliceNbr)..', curve '..tostring( nCrvId)..')') -- se non ultima, provo a spostare l'estremità finale if i < #vGuideIds then local nCopyId = EgtCopy( vGuideIds[i] + 1, vGuideIds[i], GDB_IN.AFTER) if nCopyId then local LEN_TRIM = 10 local bOk1 = EgtTrimCurveEndAtLen( nCopyId, LEN_TRIM) local bOk2 = EgtAddCurveCompoCurve( vGuideIds[i], nCopyId) local bOk3 = EgtTrimCurveStartAtLen( vGuideIds[i] + 1, LEN_TRIM) nSrfId = CreateSolid( vGuideIds[i], nSolidGrp, LayerParams, dH, dStrand - 5 * GEO.EPS_SMALL) if not nSrfId then nSrfId = CreateSolid( vGuideIds[i], nSolidGrp, LayerParams, dH, dStrand - 50 * GEO.EPS_SMALL) end end end end -- ritento spezzando la curva in modo ricorsivo fino ad inidividuare delle sottocurve su cui è possibile calcolare il solido if not nSrfId then EgtOutLog( 'Warning : CreateSolid_2 failed') local nGrp = EgtGroup( nSolidGrp, Frame3d( ORIG(), LayerParams.vtSlicing), GDB_RT.GLOB) EgtRelocateGlob( vGuideIds[i], nGrp) EgtApproxCurve( vGuideIds[i], GDB_CA.LINES, 100 * GEO.EPS_SMALL) EgtRelocateGlob( vGuideIds[i], nSolidGrp) local vSurfs = {} local bOk = CreateRecursiveSolid( vGuideIds[i], vSurfs, nSolidGrp, LayerParams, dH, dStrand) if #vSurfs > 0 then nSrfId = EgtSurfTmByTriangles( nSolidGrp, vSurfs) end if not nSrfId or bOk == false then EgtOutLog( 'Warning : CreateSolid_3 failed') end EgtErase( nGrp) end end if nSrfId then EgtSetColor( nSrfId, Color) EgtSetInfo( nSrfId, KEY_TYPE, nType) EgtSetInfo( nSrfId, KEY_SLICE_NBR, nSliceNbr) else bOk = false EgtOutLog( 'Warning : CreateSolid_Sewing failed') end EgtErase( vGuideIds[i]) end return bOk end -------------------------------------------------------------------- ------------------------- MULTIPLANAR ------------------------------ -------------------------------------------------------------------- local function CreateMultiPlanarSolids( vIds, nSolidGrpId, LayerParams, nLayerId, bFirst) -- 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( bFirst, 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 not bFirst then local ptSlicing = EgtGetInfo( nLayerId, KEY_SLICE_POS, 'p') + LayerParams.vtSlicing * LayerParams.dLayHeight + LayerParams.vtCorr local nPrevLayerId = EgtGetPrev( nLayerId) local vtSlicingPrev = EgtGetInfo( nPrevLayerId, KEY_SLICE_DIR, 'v') local ptSlicingPrev = EgtGetInfo( nPrevLayerId, KEY_SLICE_POS, 'p') + vtSlicingPrev * LayerParams.dLayHeight + LayerParams.vtCorr local dCosAng = vtSlicingPrev * LayerParams.vtSlicing 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 / dCosAng -- 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, bFirst) -- 1) le prime curve sono solidi multiplanari standard for i = 1, #vIds - 1 do CreateMultiPlanarSolids( { vIds[i]}, nSolidGrpId, LayerParams, nLayerId, bFirst) end -- 2) l'ultima curva è il tratto che si alza fino al layer successivo local nGrpTmp = EgtGroup( nSolidGrpId) local dStrand = EgtGetInfo( vIds[#vIds], KEY_CRV_STRAND, 'd') or LayerParams.dStrand -- a) calcolo il solido -- 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 + LayerParams.vtCorr local nProjCrv = EgtCopyGlob( vIds[#vIds], 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[#vIds], GDB_ID.ROOT) local ptE = EgtEP( vIds[#vIds], 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 le guide per il solido aperto ( tubo) local dMaxDist = ( EgtEP( vIds[#vIds], 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 -- creazione delle superfici del tubo 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 false end end -- creazione del mezzo disco iniziale e finale vSurfs[#vCrvs] = CreateSpiralVaseCap( nSectId, - EgtSV( vIds[#vIds], GDB_ID.ROOT), nSolidGrpId) vSurfs[#vCrvs + 1] = CreateSpiralVaseCap( nSectE, EgtEV( vIds[#vIds], GDB_ID.ROOT), nSolidGrpId) EgtInvertSurf( vSurfs[#vSurfs]) local nSolidId = EgtSurfTmByTriangles( nSolidGrpId, vSurfs) -- b) deformo il solido per limitarlo al piano di slicing precedente local ptSlicingPrev local vtSlicingPrev local nSliceNbr = EgtGetInfo( nLayerId, KEY_SLICE_NBR, 'i') if nSliceNbr == 1 then vtSlicingPrev = LayerParams.vtSlicing ptSlicingPrev = EgtGetInfo( nLayerId, KEY_SLICE_POS, 'p') + LayerParams.vtCorr else local nPrevLayId = EgtGetPrev( nLayerId) vtSlicingPrev = EgtGetInfo( nPrevLayId, KEY_SLICE_DIR, 'v') ptSlicingPrev = EgtGetInfo( nPrevLayId, KEY_SLICE_POS, 'p') + vtSlicingPrev * LayerParams.dLayHeight + LayerParams.vtCorr end local dCosAng = vtSlicingPrev * LayerParams.vtSlicing -- estendo la curva proiettata per gestire correttamente la deformazione dei caps local nProjExtCrv = EgtCopyGlob( nProjCrv, nGrpTmp) EgtExtendCurveStartByLen( nProjExtCrv, dStrand) EgtExtendCurveEndByLen( nProjExtCrv, dStrand) local dLen = EgtCurveLength( nProjCrv) local nVertexCnt = EgtSurfTmVertexCount( nSolidId) for j = 0, nVertexCnt - 1 do local ptVertex = EgtSurfTmGetVertex( nSolidId, j, GDB_RT.GLOB) -- calcolo la distanza dal piano precedente lungo vtSlicing local dDistPrevPlane = ( ptVertex - ptSlicingPrev) * vtSlicingPrev / dCosAng -- calcolo la distanza approssimata dalla curva del toolpath local _, ptMinDist, dMinPar = EgtPointCurveDist( ptVertex, nProjExtCrv, GDB_ID.ROOT) local dCurrLen = EgtCurveLengthAtParam( nProjExtCrv, dMinPar) - dStrand local ptRef = ptMinDist + dMaxDist * dCurrLen / dLen * vtSlicingNext local dDistCrv = ( ptRef - ptVertex) * LayerParams.vtSlicing -- calcolo la nuova posizione sapendo che l'altezza dello strand passa da s_dMultiPlanarH a dNewH local dNewH = dDistCrv + dDistPrevPlane local dDelta = dDistCrv - dDistCrv * dNewH / s_dMultiPlanarH local ptNew = ptVertex + dDelta * LayerParams.vtSlicing EgtSurfTmMoveVertex( nSolidId, j, ptNew, GDB_RT.GLOB, ( j == nVertexCnt - 1)) end local Color = EgtStdColor( 'TEAL') if s_nSimplifiedSection == 1 and nSliceNbr % 2 == 0 then Color = Color3d( s_dColorFactor * Color:getRed(), s_dColorFactor * Color:getGreen(), s_dColorFactor * Color:getBlue()) end EgtSetColor( nSolidId, Color) EgtErase( nGrpTmp) end --------------------------------------------------------------------- local function CreateFullSpiralVaseMultiPlanarSolids( vIds, nSolidGrpId, LayerParams, nLayerId) local nSliceNbr = EgtGetInfo( nLayerId, KEY_SLICE_NBR, 'i') local ptSlicing = EgtGetInfo( nLayerId, KEY_SLICE_POS, 'p') + LayerParams.dLayHeight * LayerParams.vtSlicing + LayerParams.vtCorr -- recupero il piano precedente e il suo toolpath local nPrevLayerId = EgtGetPrev( nLayerId) local vtSlicingPrev = EgtGetInfo( nPrevLayerId, KEY_SLICE_DIR, 'v') local ptSlicingPrev = EgtGetInfo( nPrevLayerId, KEY_SLICE_POS, 'p') + LayerParams.dLayHeight * vtSlicingPrev + LayerParams.vtCorr local dCosAng = vtSlicingPrev * LayerParams.vtSlicing local nPrevCrvGrp = EgtGetFirstNameInGroup( nPrevLayerId, CONTOUR_GRP .. '*') local nPrevTPathGrp = EgtGetFirstNameInGroup( nPrevCrvGrp, TOOLPATH_GRP) local nPrevTPath = EgtGetFirstNameInGroup( nPrevTPathGrp, SHELL_CRV .. '*') -- gruppo temporaneo per conti local nGrpTmp = EgtGroup( nSolidGrpId) for i = 1, #vIds do local dStrand = EgtGetInfo( vIds[i], KEY_CRV_STRAND, 'd') or LayerParams.dStrand -- creo la freccia direzionale CreateDirectionArrow( vIds[i], nSolidGrpId, LayerParams.vtSlicing, dStrand, nSliceNbr) -- appiattisco la curva ( proiezione sul piano di slicing) local nProjCrv = EgtCopyGlob( vIds[i], nGrpTmp) EgtProjectCurveOnPlane( nProjCrv, ptSlicing, LayerParams.vtSlicing, GDB_RT.GLOB) local dLen = EgtCurveLength( nProjCrv) -- suddivido la curva piana local vGuideIds = CalcSolidGuides( nProjCrv, dStrand, nGrpTmp) local dCumLen = 0 for k = 1, #vGuideIds do -- calcolo il solido sulla porzione della curva di proiezione local nSolidId = CreateStandardSolid( vGuideIds[k], nSolidGrpId, s_dMultiPlanarH, dStrand) -- estendo la guida per gestire al meglio i caps local nCrvRef = EgtCopyGlob( vGuideIds[k], nGrpTmp) EgtExtendCurveStartByLen( nCrvRef, dStrand) EgtExtendCurveEndByLen( nCrvRef, dStrand) -- recupero la curva precedente. Se estremi la limito per gestire al meglio la corrispondenza tra i toolpath local nPrevTPathRef = nPrevTPath if k == 1 then nPrevTPathRef = EgtCopyGlob( nPrevTPath, nGrpTmp) EgtTrimCurveEndAtLen( nPrevTPathRef, 0.5 * EgtCurveLength( nPrevTPathRef)) elseif k == #vGuideIds then nPrevTPathRef = EgtCopyGlob( nPrevTPath, nGrpTmp) EgtTrimCurveStartAtLen( nPrevTPathRef, 0.5 * EgtCurveLength( nPrevTPathRef)) end -- deformo i solidi : -- 1) traslazione dei vertici per portarli alla quota corretta del toolpath corrente -- 2) deformazione della sezione in base alla distanza dal toolpath precedente local nVertexCnt = EgtSurfTmVertexCount( nSolidId) for j = 0, nVertexCnt - 1 do local ptVertex = EgtSurfTmGetVertex( nSolidId, j, GDB_RT.GLOB) -- ricavo il punto di riferimento sulla proiezione del toolpath local _, ptMinDist, dParMinDist = EgtPointCurveDist( ptVertex, nCrvRef, GDB_ID.ROOT) local dCurrLen = EgtCurveLengthAtParam( nCrvRef, dParMinDist) - dStrand + dCumLen -- 1) proietto il punto sul piano corrente e calcolo la traslazione da applicare in base alla distanza dal piano precedente ( analogamente a CalcToolPath) local dDistCrv = ( ptSlicing - ptVertex) * LayerParams.vtSlicing local ptProj = ptVertex + dDistCrv * LayerParams.vtSlicing local dDistPlanePrev = ( ptProj - ptSlicingPrev) * vtSlicingPrev / dCosAng local dDeltaPos if nSliceNbr == 2 and dCurrLen < 0.5 * dLen then dDeltaPos = 0.5 * dDistPlanePrev else dDeltaPos = dDistPlanePrev * ( dLen - dCurrLen) / dLen end -- 2) per calcolare la vera altezza del solido calcolo la distanza dal toolpath precedente guardando il punto di riferimento sul percorso corrente local dNewH if nSliceNbr == 2 then -- il primo layer è ad altezza costante quindi è semplice distanza dal piano precedente lungo vtSlicing dNewH = ( ptProj - ptSlicingPrev) * vtSlicingPrev / dCosAng - dDeltaPos else local _, ptMinDistPrev = EgtPointCurveDist( ptMinDist, nPrevTPathRef, GDB_ID.ROOT) local dDistPlanePrev2 = ( ptMinDist - ptSlicingPrev) * vtSlicingPrev / dCosAng local dDeltaPos2 if nSliceNbr == 2 and dCurrLen < 0.5 * dLen then dDeltaPos2 = 0.5 * dDistPlanePrev2 else dDeltaPos2 = dDistPlanePrev2 * ( dLen - dCurrLen) / dLen end dNewH = ( ptMinDist - ptMinDistPrev) * LayerParams.vtSlicing - dDeltaPos2 -- aggiungo un piccolo extra per tener conto che la distanza è stata calcolata sulle curve centrali del solido local dExtra = ( LayerParams.vtSlicing ^ vtSlicingPrev):len() / dCosAng * dStrand * 0.5 dNewH = dNewH + dExtra end local dDelta = dDistCrv - dDistCrv * dNewH / s_dMultiPlanarH local ptNew = ptVertex + ( dDelta - dDeltaPos) * LayerParams.vtSlicing EgtSurfTmMoveVertex( nSolidId, j, ptNew, GDB_RT.GLOB, ( j == nVertexCnt - 1)) end -- imposto colore local Color = EgtStdColor( 'TEAL') if s_nSimplifiedSection == 1 and nSliceNbr % 2 == 0 then Color = Color3d( s_dColorFactor * Color:getRed(), s_dColorFactor * Color:getGreen(), s_dColorFactor * Color:getBlue()) end EgtSetColor( nSolidId, Color) dCumLen = dCumLen + EgtCurveLength( vGuideIds[i]) end end EgtErase( nGrpTmp) end --------------------------------------------------------------------- local function CreateFullSpiralVaseMultiPlanarSolidsLastLayer( vIds, nSolidGrpId, LayerParams, nLayerId) -- le curve sono piane quindi i solidi possono essere calcolati nel modo classico -- i solidi della shell sono deformati in base alla distanza dalla curva precedente -- eventuali solidi di lead out e coasting sono calcolati con un valore di altezza costante pari all'ultimo valore di altezza dei solidi della shell local nSliceNbr = EgtGetInfo( nLayerId, KEY_SLICE_NBR, 'i') local nPrevLayerId = EgtGetPrev( EgtGetPrev( nLayerId)) local vtSlicingPrev = EgtGetInfo( nPrevLayerId, KEY_SLICE_DIR, 'v') local ptSlicingPrev = EgtGetInfo( nPrevLayerId, KEY_SLICE_POS, 'p') + vtSlicingPrev * LayerParams.dLayHeight + LayerParams.vtCorr local ptSlicing = EgtGetInfo( nLayerId, KEY_SLICE_POS, 'p') + LayerParams.vtSlicing * LayerParams.dLayHeight + LayerParams.vtCorr local dCosAng = vtSlicingPrev * LayerParams.vtSlicing -- 1) curva shell local nGrpTmp = EgtGroup( nSolidGrpId) local dStrand = EgtGetInfo( vIds[1], KEY_CRV_STRAND, 'd') or LayerParams.dStrand local vShellGuides = CalcSolidGuides( vIds[1], dStrand, nGrpTmp) local dLen = EgtCurveLength( vIds[1]) -- se non c'è lead out alla lunghezza totale della shell devo aggiungere anche quella del coasting if EgtGetInfo( s_nPartId, KEY_LEAD_OUT_TYPE, 'i') == LEAD_TYPE.NONE then dLen = dLen + EgtGetInfo( s_nPartId, KEY_COASTING_LEN, 'd') end local dCumLen = 0 -- creo la freccia direzionale CreateDirectionArrow( vIds[1], nSolidGrpId, LayerParams.vtSlicing, dStrand, nSliceNbr) for i = 1, #vShellGuides do -- calcolo il solido associato local nSolidId = CreateStandardSolid( vShellGuides[i], nSolidGrpId, s_dMultiPlanarH, dStrand) -- estensione della guida per gestire meglio i caps local nCrvRef = EgtCopyGlob( vShellGuides[i], nGrpTmp) EgtExtendCurveStartByLen( nCrvRef, dStrand) EgtExtendCurveEndByLen( nCrvRef, dStrand) -- deformo in base alla distanza dalla curva precedente local nVertexCnt = EgtSurfTmVertexCount( nSolidId) for j = 0, nVertexCnt - 1 do local ptVertex = EgtSurfTmGetVertex( nSolidId, j, GDB_RT.GLOB) -- ricavo il punto di riferimento sulla guida local _, _, dParMinDist = EgtPointCurveDist( ptVertex, nCrvRef, GDB_ID.ROOT) local dCurrLen = EgtCurveLengthAtParam( nCrvRef, dParMinDist) - dStrand + dCumLen -- calcolo la nuova altezza del solido in base alla distanza dalla curva precedente local dDistCurr = ( ptSlicing - ptVertex) * LayerParams.vtSlicing local ptProj = ptVertex + dDistCurr * LayerParams.vtSlicing local dDistPrev = ( ptProj - ptSlicingPrev) * vtSlicingPrev / dCosAng local dNewH = dDistPrev * ( dLen - dCurrLen) / dLen dNewH = max( dNewH, 500 * GEO.EPS_SMALL) -- calcolo la nuova posizione sapendo che l'altezza dello strand passa da s_dMultiPlanarH a dNewH local dDelta = dDistCurr - dDistCurr * dNewH / s_dMultiPlanarH local ptNew = ptVertex + dDelta * LayerParams.vtSlicing EgtSurfTmMoveVertex( nSolidId, j, ptNew, GDB_RT.GLOB, ( j == nVertexCnt - 1)) end dCumLen = dCumLen + EgtCurveLength( vShellGuides[i]) -- imposto colore local Color = EgtStdColor( 'TEAL') if s_nSimplifiedSection == 1 and nSliceNbr % 2 == 0 then Color = Color3d( s_dColorFactor * Color:getRed(), s_dColorFactor * Color:getGreen(), s_dColorFactor * Color:getBlue()) end EgtSetColor( nSolidId, Color) end -- 2) curve di uscita -- calcolo altezza finale del solido shell local ptE = EgtEP( vIds[1], GDB_ID.ROOT) local dH = ( ( ptE - ptSlicingPrev) * vtSlicingPrev / dCosAng) * ( dLen - EgtCurveLength( vIds[1])) / dLen dH = max( dH, 500 * GEO.EPS_SMALL) for i = 2, #vIds do CreateSolidFromCurve( vIds[i], nSolidGrpId, LayerParams, nSliceNbr, dH) end EgtErase( nGrpTmp) end --------------------------------------------------------------------- function RunCalcSolids.Exec() -- per determinare il tempo di calcolo EgtStartCounter() -- verifico se richiesta sezione semplificata ( rettangolare) local sIniFile = EgtGetIniFile() s_nSimplifiedSection = EgtGetNumberFromIni( 'Solids', 'SimplifiedSection', 0, sIniFile) local nPartIndex = 1 local nPartId = EgtGetFirstNameInGroup( GDB_ID.ROOT, PART .. nPartIndex) or EgtGetFirstNameInGroup( GDB_ID.ROOT, PART) while nPartId do s_nPartId = nPartId if EgtGetInfo( nPartId, KEY_PART_ON_TABLE, 'b') then -- verifico se necessario calcolare il solido local bCalcSolid = EgtGetInfo( nPartId, KEY_CALC_SOLIDS, 'b') or false if bCalcSolid then -- recupero il suo frame local nFrameId = EgtGetFirstNameInGroup( EgtGetFirstNameInGroup( nPartId, 'Frame'), 'FramePart') local ptOrig = EgtSP( nFrameId or GDB_ID.NULL, GDB_ID.ROOT) EgtSetInfo( nPartId, KEY_ORIG_REF, ptOrig) -- recupero i suoi slice local vLayIds = EgtGetNameInGroup( nPartId, SLICE_LAYER .. '*') if not vLayIds or #vLayIds == 0 then EgtOutBox( 'No sliced part in this project!', 'Error', 'ERROR') return end EgtSetInfo( nPartId, KEY_HAS_SOLIDS, 1) local nSlicingType = EgtGetInfo( nPartId, KEY_SLICING_TYPE, 'i') -- 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 or nSlicingType == SLICING_TYPE.MULTIPLANAR_DEG45 or nSlicingType == SLICING_TYPE.MULTIPLANAR_HOR then local sMachIni = EgtGetCurrMachineDir() .. '\\' .. EgtGetCurrMachineName() .. '.ini' local dMaxFactor = EgtGetNumberFromIni( '3dPrinting', KEY_MAX_STRANDH_FACTOR, 2, sMachIni) s_dMultiPlanarH = min( dMaxFactor, 5) * LayerParams.dLayHeight end local bFirst = true for nIdx = 1, #vLayIds do -- flag di interruzione perchè trovati solidi già ok local bSolidsOk = false -- indice layer ( per log) local nSliceNbr = EgtGetInfo( vLayIds[ nIdx], KEY_SLICE_NBR, 'i') -- scorro tutti i gruppi di contorni local nCrvGrpId = EgtGetFirstNameInGroup( vLayIds[ nIdx], CONTOUR_GRP.."*") or GDB_ID.NULL while nCrvGrpId ~= GDB_ID.NULL do -- recupero il gruppo dei percorsi utensile local nTPathGrpId = EgtGetFirstNameInGroup( nCrvGrpId, TOOLPATH_GRP) or GDB_ID.NULL if nTPathGrpId == GDB_ID.NULL then EgtOutBox( 'Error no tool paths', 'SolidCalc') return end -- recupero il gruppo dei solidi local nSolidGrpId = EgtGetFirstNameInGroup( nCrvGrpId, SOLID_GRP) or GDB_ID.NULL if nSolidGrpId == GDB_ID.NULL then nSolidGrpId = EgtGroup( nCrvGrpId) EgtSetName( nSolidGrpId, SOLID_GRP) EgtSetLevel( nSolidGrpId, GDB_LV.TEMP) local vIds = EgtGetAllInGroup( nTPathGrpId) if #vIds > 0 then -- slicing multiplanare if nSlicingType == SLICING_TYPE.MULTIPLANAR or nSlicingType == SLICING_TYPE.MULTIPLANAR_DEG45 or nSlicingType == SLICING_TYPE.MULTIPLANAR_HOR 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 -- a) spiral vase completo ( con transizione in altezza su tutto il layer) if dTransitionLen < GEO.EPS_SMALL then if bFirst then -- il primo layer va gestito come uno spiral vase con transizione parziale ( curva a quota costante e ultimo tratto che si alza) CreatePartialSpiralVaseMultiPlanarSolids( vIds, nSolidGrpId, LayerParams, vLayIds[nIdx], bFirst) elseif nIdx == #vLayIds then -- gestione speciale per lead out e coasting CreateFullSpiralVaseMultiPlanarSolidsLastLayer( vIds, nSolidGrpId, LayerParams, vLayIds[nIdx]) else CreateFullSpiralVaseMultiPlanarSolids( vIds, nSolidGrpId, LayerParams, vLayIds[nIdx]) end -- b) spiral vase con transizione parziale else if nIdx == #vLayIds then -- ultimo layer è un multiplanare standard perchè non ha tratto finale che si alza CreateMultiPlanarSolids( vIds, nSolidGrpId, LayerParams, vLayIds[nIdx], false) else CreatePartialSpiralVaseMultiPlanarSolids( vIds, nSolidGrpId, LayerParams, vLayIds[nIdx], bFirst) end end -- c) multiplanare standard else CreateMultiPlanarSolids( vIds, nSolidGrpId, LayerParams, vLayIds[nIdx], bFirst) 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 = {} for i = 1, #vIds do local sName = EgtGetName( vIds[i]) local dDelta = ( EgtEP( vIds[i], GDB_ID.ROOT) - EgtSP( vIds[i], GDB_ID.ROOT)) * LayerParams.vtSlicing if abs( dDelta) < GEO.EPS_SMALL or sName == LEAD_IN_CRV or sName == LEAD_OUT_CRV or sName == COASTING_CRV or sName == WIPE_CRV then -- inserisco il gruppo di tratti da concatenare e lo resetto if #vTmpIds > 0 then table.insert( vChainedIds, vTmpIds) vTmpIds = {} end -- inserisco la curva singola corrente table.insert( vChainedIds, { vIds[i]}) else table.insert( vTmpIds, vIds[i]) end end -- inserisco ultimo gruppo if #vTmpIds > 0 then table.insert( vChainedIds, vTmpIds) end for i = 1, #vChainedIds do if #vChainedIds[i] == 1 then CreateSolidFromCurve( vChainedIds[i][1], nSolidGrpId, LayerParams, nSliceNbr) else local nNewCrv = EgtCurveCompo( nSolidGrpId, vChainedIds[i], false) local dStrand = EgtGetInfo( vChainedIds[i][1], KEY_CRV_STRAND, 'd') or LayerParams.dStrand EgtSetInfo( nNewCrv, KEY_CRV_STRAND, dStrand) EgtSetInfo( nNewCrv, KEY_TYPE, TYPE.OUTER_SHELL) CreateSolidFromCurve( nNewCrv, nSolidGrpId, LayerParams, nSliceNbr) EgtErase( nNewCrv) end end -- slicing standard else for i = 1, #vIds do CreateSolidFromCurve( vIds[i], nSolidGrpId, LayerParams, nSliceNbr) end end bFirst = false end else bSolidsOk = true break end --passo al gruppo di contorni successivo nCrvGrpId = EgtGetNextName( nCrvGrpId, CONTOUR_GRP.."*") or GDB_ID.NULL end if bSolidsOk then break end local nStep = 10 if nIdx > 400 then nStep = 80 elseif nIdx > 200 then nStep = 40 elseif nIdx > 100 then nStep = 20 end if ( nIdx % nStep) == 0 then EgtDraw() end if EgtProcessEvents( EgtIf( PRINT, 400, 0) + nIdx / #vLayIds * 100, 0) == 1 then -- se interrompo cancello i solidi realizzati for i = 1, #vLayIds do local vGrpId = EgtGetNameInGroup( vLayIds[i], CONTOUR_GRP .. '*') or {} for j = 1, #vGrpId do local nSolidId = EgtGetFirstNameInGroup( vGrpId[j], SOLID_GRP .. '*') or GDB_ID.NULL EgtErase( nSolidId) end end -- rimuovo info della presenza solidi EgtSetInfo( nPartId, KEY_HAS_SOLIDS, false) EgtDraw() return end end -- eventuale aggiornamento delle ViewInfo local nViewId = EgtGetFirstNameInGroup( GDB_ID.ROOT, VIEWPARAMS) if nViewId then EgtSetInfo( nViewId, SOLID_GRP, true) end end end nPartIndex = nPartIndex + 1 nPartId = EgtGetFirstNameInGroup( GDB_ID.ROOT, PART .. nPartIndex) or EgtGetNextName( nPartId, PART) end EgtDraw() -- report tempo di calcolo in log EgtOutLog( string.format( ' CalcSolidsTime = %.2f ms', EgtStopCounter())) end --------------------------------------------------------------------- return RunCalcSolids