e18e57e7c2
- modifiche e migliorie per calcolo solidi con uso della nuova funzione lua EgtSurfTmRectSwept.
390 lines
15 KiB
Lua
390 lines
15 KiB
Lua
-- 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.dStrand = EgtGetInfo( nPartId, KEY_STRAND, '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
|
|
EgtSpiralizeCurve( nCrvCopy, - dDelta)
|
|
|
|
-- calcolo la sezione
|
|
local vtDir = EgtSV( nCrvCopy, GDB_ID.ROOT)
|
|
vtDir:rotate( LayerParams.vtSlicing, 90)
|
|
local nSectId = CreateSection( ptS, vtDir, 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 = ( ptRef - ptS) * 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)
|
|
EgtSpiralizeCurve( vCrvs[i+1], dDelta)
|
|
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)
|
|
EgtInvertSurf( nSrfId)
|
|
|
|
-- creazione del mezzo disco iniziale
|
|
local nCap1 = CreateSpiralVaseCap( nSectId, - vtS, nSolidGrp)
|
|
-- creazione del mezzo disco finale
|
|
local vtDir2 = EgtEV( nCrvCopy, GDB_ID.ROOT)
|
|
vtDir2:rotate( LayerParams.vtSlicing, 90)
|
|
local nSectE = CreateSection( ptE, vtDir2, dStrand, LayerParams.dLayHeight, LayerParams.vtSlicing, nGrpTmp)
|
|
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 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.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, 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, LayerParams.dStrand - 5 * GEO.EPS_SMALL)
|
|
if not nSrfId then
|
|
nSrfId = CreateSolid( nGuideId, nSolidGrp, LayerParams, 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, 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)
|
|
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 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
|
|
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
|