-- RunCalcSolids.lua by Egaltech s.r.l. 2022/07/01 -- 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 function GetLayerParamsForSolidCalc( nPartId) local LayerParams = {} LayerParams.bInvert = EgtGetInfo( nPartId, KEY_PRINT_DIRECTION, 'b') LayerParams.dLayHeight = EgtGetInfo( nPartId, KEY_SLICE_STEP, 'd') LayerParams.dStrand = EgtGetInfo( nPartId, KEY_STRAND, 'd') LayerParams.nOrder = EgtGetInfo( nPartId, KEY_PRINT_ORDER, 'i') 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 -- recupero offset --local dOffs = EgtGetInfo( s_nPartId, KEY_OFFSET_SLICE, 'd') dOffs = 0 if dOffs and dOffs > 0 then -- calcolo area originale local dArea = ( dL * dH) - ( dLm * dHm) local dLM = ( dArea / dH) - ( dLm / 6) if dOffs / 2 <= ( dL - dLM) then dL = dL - dOffs / 2 dLm = dL / 10 dHm = (( dL * dH) - dArea) / dLm else EgtOutLog( 'Strand section not calculated on area. Too much overlap?') end end 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}) 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}) return nId end -------------------------------------------------------------------- local function CreateSolid( nCrvId, nSolidGrp, dStrand, dH, vtSlicing) -- punti e direzioni all'inizio e fine della curva guida local ptS = EgtSP( nCrvId) local vtS = EgtSV( nCrvId) vtS:rotate( vtSlicing, 90) local ptE = EgtEP( nCrvId) local vtE = EgtEV( nCrvId) vtE:rotate( vtSlicing, -90) -- creazione del solido aperto (tubo) local nSectId = CreateSection( ptS, vtS, dStrand, dH, vtSlicing, nSolidGrp) local nSrfId = EgtSurfTmSwept( nSolidGrp, nSectId, nCrvId, false, 0.1) EgtErase( nSectId) if not nSrfId then return nil end -- creazione del mezzo disco iniziale local nSectS = CreateHalfSection( ptS, vtS, dStrand, dH, vtSlicing, nSolidGrp) local nSrfS = EgtSurfTmByScrewing( nSolidGrp, nSectS, ptS, vtSlicing, 180, 0, false, 0.1) EgtErase( nSectS) if not nSrfS then return nil end -- creazione del mezzo disco finale local nSectE = CreateHalfSection( ptE, vtE, dStrand, dH, vtSlicing, nSolidGrp) local nSrfE = EgtSurfTmByScrewing( nSolidGrp, nSectE, ptE, vtSlicing, 180, 0, false, 0.1) EgtErase( nSectE) if not nSrfE then return nil end -- unione delle tre superfici return EgtSurfTmBySewing( nSolidGrp, { nSrfId, nSrfS, nSrfE}) end --------------------------------------------------------------------- local function CreateSolidFromCurve( nCrvId, nSolidGrp, LayerParams) 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.WIPE then Color = EgtStdColor( 'LIME') elseif nType == TYPE.RIB then Color = EgtStdColor( 'OLIVE') elseif nType == TYPE.AUX_SOLID then Color = EgtStdColor( 'AQUA') end 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 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 - 2 * GEO.EPS_SMALL, LayerParams.dLayHeight, LayerParams.vtSlicing) if not nSrfId then -- ritento con sezione leggermente modificata nSrfId = CreateSolid( nGuideId, nSolidGrp, LayerParams.dStrand - 100 * GEO.EPS_SMALL, LayerParams.dLayHeight, LayerParams.vtSlicing) if not nSrfId then nSrfId = CreateSolid( nGuideId, nSolidGrp, LayerParams.dStrand + 100 * GEO.EPS_SMALL, LayerParams.dLayHeight, LayerParams.vtSlicing) if not nSrfId then -- ritento spezzando la curva local nGrp = EgtGroup( nSolidGrp, Frame3d( ORIG(), LayerParams.vtSlicing)) 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 - 100 * GEO.EPS_SMALL, LayerParams.dLayHeight, LayerParams.vtSlicing) EgtErase( nFirstCrv + nInd2) if nSrfId2 then table.insert( nSrfIds, nSrfId2) end end if #nSrfIds == nCrvNbr then nSrfId = EgtSurfTmBySewing( nSolidGrp, nSrfIds) end end end end end if nSrfId then EgtSetColor( nSrfId, Color) EgtSetInfo( nSrfId, KEY_TYPE, nType) else bOk = false end EgtErase( nGuideId) end return bOk end --------------------------------------------------------------------- function RunCalcSolids.Exec() local nPartIndex = 1 local nPartId = EgtGetFirstNameInGroup( GDB_ID.ROOT, PART .. nPartIndex) 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 local bHasSolids = EgtGetInfo( nPartId, KEY_HAS_SOLIDS, 'b') or false if bCalcSolid and not bHasSolids then -- 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) local vErr = {} -- recupero i parametri necessari al calcolo dei solidi local LayerParams = GetLayerParamsForSolidCalc( nPartId) for nIdx = 1, #vLayIds do -- 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) else EgtEmptyGroup( nSolidGrpId) end -- scorro le curve del percorso utensile local nId = EgtGetFirstInGroup( nTPathGrpId) while nId do local bOk = CreateSolidFromCurve( nId, nSolidGrpId, LayerParams) if not bOk then table.insert( vErr, nIdx) end nId = EgtGetNext( nId) end -- processo gli eventi if ( nIdx % 20) == 0 then EgtDraw() if EgtProcessEvents( nIdx / #vLayIds * 100, 0) == 1 then return end end --passo al gruppo di contorni successivo nCrvGrpId = EgtGetNextName( nCrvGrpId, CONTOUR_GRP.."*") or GDB_ID.NULL end EgtDraw() if EgtProcessEvents( nIdx / #vLayIds * 100, 0) == 1 then return end end -- eventuale segnalazione errori -- if #vErr > 0 then -- EgtOutBox( 'Error on layers :\n' .. table.concat( vErr, ','), 'SolidCalc') -- end for i = 1, #vErr do EgtOutLog( 'Error on solid creation (layer ' .. vErr[i] .. ') - SolidCalc') 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) end end --------------------------------------------------------------------- return RunCalcSolids