-- 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 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_SLICING_DIR, 'v') return LayerParams end --------------------------------------------------------------------- local function CalcSectionParams( dStrand, dH) local dL = dStrand local dLm = dStrand / 10 local dHm = dH / 6 local dD1 = 0.5 * dL - dLm local dD2 = 0.5 * dL - dD1 local dD3 = dHm local dD4 = dH - 2 * dD3 return dD1, dD2, dD3, dD4 end --------------------------------------------------------------------- local function CreateSection( ptS, vtDir, dStrand, dH, vtSlicing, nSolidGrp) local dD1, dD2, dD3, dD4 = CalcSectionParams( dStrand, dH) local ptA = ptS - dH * vtSlicing + dD1 * vtDir local ptB = ptA + dD2 * vtDir + dD3 *vtSlicing local ptC = ptB + dD4 * vtSlicing local ptD = ptA + dH * vtSlicing local ptE = ptD - 2 * dD1 * vtDir local ptF = ptC - 2 * ( dD1 + dD2) * vtDir local ptG = ptB - 2 * ( dD1 + dD2) * vtDir local ptH = ptA - 2 * dD1 * vtDir local nId = EgtCurveCompoFromPoints( nSolidGrp, {ptA, ptB, ptC, ptD, ptE, ptF, ptG, ptH, ptA}, GDB_RT.GLOB) EgtInvertCurve( nId) return nId end --------------------------------------------------------------------- local function CreateHalfSection( ptS, vtDir, dStrand, dH, vtSlicing, nSolidGrp) local dD1, dD2, dD3, dD4 = CalcSectionParams( dStrand, dH) local ptA = ptS - dH * vtSlicing + dD1 * vtDir local ptB = ptA + dD2 * vtDir + dD3 * vtSlicing local ptC = ptB + dD4 * vtSlicing local ptD = ptA + dH * vtSlicing local nId = EgtCurveCompoFromPoints( nSolidGrp, { ptS - dH * vtSlicing, ptA, ptB, ptC, ptD, ptS}, GDB_RT.GLOB) return nId end ------------------------------------------------------------------------------ local function CreateSpiralVaseCap( nSectId, vtDir, nSolidGrp) local vPt = {} for i = 0, 7 do vPt[i + 1] = EgtUP( nSectId, i, GDB_ID.ROOT) end local vCrvs = {} 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) vCrvs[5] = EgtCurveCompo( nSolidGrp, {vCrvs[1]}, false, GDB_RT.GLOB) EgtCloseCurveCompo( vCrvs[5]) vCrvs[6] = EgtCurveCompo( nSolidGrp, {vCrvs[4]}, false, GDB_RT.GLOB) EgtCloseCurveCompo( vCrvs[6]) local nSurf1 = EgtSurfTmRuled( nSolidGrp, vCrvs[1], vCrvs[2], GDB_RUL.ISOPAR, s_dTol) local nSurf2 = EgtSurfTmRuled( nSolidGrp, vCrvs[2], vCrvs[3], GDB_RUL.ISOPAR, s_dTol) local nSurf3 = EgtSurfTmRuled( nSolidGrp, vCrvs[3], vCrvs[4], GDB_RUL.ISOPAR, s_dTol) local nSurf4 = EgtSurfTmByRegion( nSolidGrp, vCrvs[5], s_dTol) local nSurf5 = EgtSurfTmByRegion( nSolidGrp, vCrvs[6], s_dTol) local nCapSrf = EgtSurfTmBySewing( nSolidGrp, {nSurf1, nSurf2, nSurf3, nSurf4, nSurf5}) for i = 1, #vCrvs do EgtErase( vCrvs[i]) end return nCapSrf end ------------------------------------------------------------------------------- local function CreateSpiralVaseSolid( nCrvId, nSolidGrp, LayerParams, dStrand) -- gruppo temporaneo per conti local nGrpTmp = EgtGroup( nSolidGrp) 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) -- appiattisco la curva local nCrvCopy = EgtCopyGlob( nCrvId, nGrpTmp) local dDelta = ( ptE - ptS) * LayerParams.vtSlicing EgtSpiralizeCurveAlongExtrusion( nCrvCopy, - dDelta) EgtMergeCurvesInCurveCompo( nCrvCopy) EgtChangeClosedCurveStartPoint( nCrvCopy, ptS, GDB_RT.GLOB) -- calcolo la sezione iniziale local vtDir = EgtSV( nCrvCopy, GDB_ID.ROOT) vtDir:rotate( LayerParams.vtSlicing, 90) local nSectId = CreateSection( ptS, vtDir, dStrand, LayerParams.dLayHeight, LayerParams.vtSlicing, nGrpTmp) -- creo la sezione finale local vtDir2 = EgtEV( nCrvCopy, GDB_ID.ROOT) vtDir2:rotate( LayerParams.vtSlicing, 90) local nSectE = CreateSection( ptE, vtDir2, dStrand, LayerParams.dLayHeight, LayerParams.vtSlicing, nGrpTmp) -- 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) * LayerParams.vtSlicing EgtMove( vCrvs[i+1], LayerParams.vtSlicing * dMove, GDB_RT.GLOB) EgtSpiralizeCurveAlongExtrusion( vCrvs[i+1], dDelta) -- modifico la curva per congiungerla ai caps EgtAddCurveCompoLine( vCrvs[i+1], ptRef, false, GDB_RT.GLOB) local ptRefEnd = EgtUP( nSectE, i, GDB_ID.ROOT) EgtAddCurveCompoLine( vCrvs[i+1], ptRefEnd, true, GDB_RT.GLOB) end local vSurfs = {} for i = 1, #vCrvs - 1 do vSurfs[i] = EgtSurfTmRuled( nGrpTmp, vCrvs[i], vCrvs[i+1], GDB_RUL.MINDIST, s_dTol) if not vSurfs[i] or vSurfs[i] == GDB_ID.NULL then EgtErase( nGrpTmp) return nil end end local nSrfId = EgtSurfTmBySewing( nSolidGrp, vSurfs) -- creazione del mezzo disco iniziale local nCap1 = CreateSpiralVaseCap( nSectId, - vtS, nSolidGrp) -- creazione del mezzo disco finale local nCap2 = CreateSpiralVaseCap( nSectE, vtE, nSolidGrp) EgtInvertSurf( nCap2) -- cancello le curve usate per la costruzione EgtErase( nGrpTmp) return EgtSurfTmBySewing( nSolidGrp, { nSrfId, nCap1, nCap2}) end ---------------------------------------------------------------------- local function CreateStandardSolid( nCrvId, nSolidGrp, LayerParams, dStrand) local dD1, dD2, dD3, dD4 = CalcSectionParams( dStrand, LayerParams.dLayHeight) local nSrfId = EgtSurfTmRectSwept( nSolidGrp, dStrand, LayerParams.dLayHeight, dD2, dD3, nCrvId, GDB_RSCT.BEVEL, s_dTol) return nSrfId end -------------------------------------------------------------------------------------- local function CreateSolid( nCrvId, nSolidGrp, LayerParams, dStrand) if LayerParams.bSpiralVase then return CreateSpiralVaseSolid( nCrvId, nSolidGrp, LayerParams, dStrand) else return CreateStandardSolid( nCrvId, nSolidGrp, LayerParams, dStrand) end end --------------------------------------------------------------------- local function CreateDirectionArrow( nCrvId, nSolidGrp, vtSlicing, dStrand, nLayer) 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, nLayer) EgtSetStatus( nSrf, GDB_ST.OFF) EgtSetMode( nSrf, GDB_MD.HIDDEN) EgtSetName( nSrf, DIR_ARROW) end --------------------------------------------------------------------- local function CreateSolidFromCurve( nCrvId, nSolidGrp, LayerParams, nLayer) 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 local dStrand = EgtGetInfo( nCrvId, KEY_CRV_STRAND, 'd') local nCopyId = EgtCopyGlob( nCrvId, nSolidGrp) local nId = GDB_ID.NULL 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 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 -- 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, nLayer) end if nId == GDB_ID.NULL then return false end local bOk = true for nInd = 0, nParts - 1 do local nGuideId = nId + nInd local nSrfId = CreateSolid( nGuideId, nSolidGrp, LayerParams, dStrand - 5 * GEO.EPS_SMALL) if not nSrfId then EgtOutLog( 'Warning : CreateSolid failed '.. '(layer '..tostring( nLayer)..', curve '..tostring( nCrvId)..')') -- se non ultima, provo a spostare l'estremità finale if nInd < nParts - 1 then local nCopyId = EgtCopy( nGuideId + 1, nGuideId, GDB_IN.AFTER) if nCopyId then local LEN_TRIM = 10 local bOk1 = EgtTrimCurveEndAtLen( nCopyId, LEN_TRIM) local bOk2 = EgtAddCurveCompoCurve( nGuideId, nCopyId) local bOk3 = EgtTrimCurveStartAtLen( nGuideId + 1, LEN_TRIM) nSrfId = CreateSolid( nGuideId, nSolidGrp, LayerParams, dStrand - 5 * GEO.EPS_SMALL) if not nSrfId then nSrfId = CreateSolid( nGuideId, nSolidGrp, LayerParams, dStrand - 50 * GEO.EPS_SMALL) end end end -- ritento spezzando la curva if not nSrfId then EgtOutLog( 'Warning : CreateSolid_2 failed') local nGrp = EgtGroup( nSolidGrp, Frame3d( ORIG(), LayerParams.vtSlicing), GDB_RT.GLOB) EgtRelocateGlob( nGuideId, nGrp) EgtApproxCurve( nGuideId, GDB_CA.LINES, 100 * GEO.EPS_SMALL) EgtRelocateGlob( nGuideId, nSolidGrp) local nFirstCrv, nCrvNbr = EgtSplitCurveAtCorners( nGuideId, 30) if nFirstCrv and nCrvNbr > 1 then local nSrfIds = {} for nInd2 = 0, nCrvNbr-1 do local nSrfId2 = CreateSolid( nFirstCrv + nInd2, nSolidGrp, LayerParams, dStrand - 50 * GEO.EPS_SMALL) EgtErase( nFirstCrv + nInd2) if nSrfId2 then table.insert( nSrfIds, nSrfId2) end end if #nSrfIds == nCrvNbr then nSrfId = EgtSurfTmBySewing( nSolidGrp, nSrfIds) else EgtOutLog( 'Warning : CreateSolid_3 failed') end else EgtErase( nFirstCrv) end EgtErase( nGrp) end end if nSrfId then EgtSetColor( nSrfId, Color) EgtSetInfo( nSrfId, KEY_TYPE, nType) EgtSetInfo( nSrfId, KEY_SLICE_NBR, nLayer) else bOk = false EgtOutLog( 'Warning : CreateSolid_Sewing failed') end EgtErase( nGuideId) end return bOk end --------------------------------------------------------------------- function RunCalcSolids.Exec() -- per determinare il tempo di calcolo EgtStartCounter() local nPartIndex = 1 local nPartId = EgtGetFirstNameInGroup( GDB_ID.ROOT, PART .. nPartIndex) or EgtGetFirstNameInGroup( GDB_ID.ROOT, PART) while nPartId do 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 then EgtOutBox( 'No sliced part in this project!', 'Error', 'ERROR') return end EgtSetInfo( nPartId, KEY_HAS_SOLIDS, 1) -- recupero i parametri necessari al calcolo dei solidi local LayerParams = GetLayerParamsForSolidCalc( nPartId) for nIdx = 1, #vLayIds do -- flag di interruzione perchè trovati solidi già ok local bSolidsOk = false -- indice layer (per log) local nLayer = EgtGetInfo( vLayIds[ nIdx], KEY_SLICE_NBR, 'i') -- scorro tutti i gruppi di contorni local nCrvGrpId = EgtGetFirstNameInGroup( vLayIds[ nIdx], CONTOUR_GRP.."*") or GDB_ID.NULL 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) -- scorro le curve del percorso utensile local nId = EgtGetFirstInGroup( nTPathGrpId) while nId do local bOk = CreateSolidFromCurve( nId, nSolidGrpId, LayerParams, nLayer) nId = EgtGetNext( nId) 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 = EgtGetNameInGroup( 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