Files
3dprinting/LuaLibs/CalcToolPath.lua
SaraP 046431a2a9 3dPrinting :
- corretta la gestione delle uscite per setti chiusi con link disegnato dall'utente.
2023-03-20 11:49:15 +01:00

1396 lines
58 KiB
Lua

-- CalcToolPath.lua by Egaltech s.r.l. 2022/12/20
-- Calcolo percorsi di lavoro per Stampa 3d
-- Tabella per definizione modulo
local CalcToolPath = {}
-- Intestazioni
require( 'EgtBase')
EgtOutLog( ' CalcToolPath started', 1)
-- Dati
local AMD = require( 'AddManData')
---------------------------------------------------------------------
local s_nPartId
local s_nDefaultWipeAng = -90 -- angolo = 0° per wipe significa che esce ortogonalmente alla direzione del movimento
local s_dHMin
---------------------------------------------------------------------
local function GetLayerParamsForToolPathCalc()
local LayerParams = {}
LayerParams.bSpiralVase = EgtGetInfo( s_nPartId, KEY_SPIRAL_VASE, 'b') or false
LayerParams.dStrand = EgtGetInfo( s_nPartId, KEY_STRAND, 'd')
LayerParams.dLayHeight = EgtGetInfo( s_nPartId, KEY_SLICE_STEP, 'd')
LayerParams.dOffs = EgtGetInfo( s_nPartId, KEY_OFFSET_SLICE, 'd')
LayerParams.bInvert = ( EgtGetInfo( s_nPartId, KEY_PRINT_DIRECTION, 'i') == PRINT_DIRECTION.CW)
LayerParams.nOrder = EgtGetInfo( s_nPartId, KEY_STRAND_ORDER, 'i')
LayerParams.vPrintOrder = EgtGetInfo( s_nPartId, KEY_PRINT_ORDER, 'vi') or { 1, 2, 3, 4, 5, 6, 7, 8}
LayerParams.nLinkType = EgtGetInfo( s_nPartId, KEY_LINK_TYPE, 'i')
LayerParams.dLinkParam = EgtGetInfo( s_nPartId, KEY_LINK_PARAM, 'd')
LayerParams.nLeadInType = EgtGetInfo( s_nPartId, KEY_LEAD_IN_TYPE, 'i')
LayerParams.dLeadInTangDist = EgtGetInfo( s_nPartId, KEY_LEAD_IN_TANG_DIST, 'd')
LayerParams.dLeadInOrthoDist = EgtGetInfo( s_nPartId, KEY_LEAD_IN_ORTHO_DIST, 'd')
LayerParams.nLeadOutType = EgtGetInfo( s_nPartId, KEY_LEAD_OUT_TYPE, 'i')
LayerParams.dLeadOutTangDist = EgtGetInfo( s_nPartId, KEY_LEAD_OUT_TANG_DIST, 'd')
LayerParams.dLeadOutOrthoDist = EgtGetInfo( s_nPartId, KEY_LEAD_OUT_ORTHO_DIST, 'd')
LayerParams.dOffsetLP = EgtGetInfo( s_nPartId, KEY_OFFSET_LEAD_POINT, 'd')
LayerParams.dSPOffs = EgtGetInfo( s_nPartId, KEY_SP_OFFSET_ON_SLICE, 'd')
LayerParams.dCoastingLen = EgtGetInfo( s_nPartId, KEY_COASTING_LEN, 'd')
LayerParams.dWipeLen = EgtGetInfo( s_nPartId, KEY_WIPE_LEN, 'd')
LayerParams.dWipeDir = EgtGetInfo( s_nPartId, KEY_WIPE_DIR, 'd') or 0.0
LayerParams.vtSlicing = EgtGetInfo( s_nPartId, KEY_SLICING_DIR, 'v')
LayerParams.dTDiam = EgtGetInfo( s_nPartId, KEY_TOOL_DIAM, 'd')
return LayerParams
end
------------------------------------------------------------------
local function ComputeToolPathBox( nTpathGrpId)
-- calcolo il box del toolpath (escludendo i wipe)
local b3Box = BBox3d()
local nEntId = EgtGetFirstInGroup( nTpathGrpId)
while nEntId do
if EgtGetInfo( nEntId, KEY_TYPE, 'i') ~= TYPE.WIPE then
local b3Ent = EgtGetBBoxGlob( nEntId, GDB_BB.STANDARD)
b3Box:Add( b3Ent)
end
nEntId = EgtGetNext( nEntId)
end
return b3Box
end
------------------------------------------------------------------
local function AddZCorrection( b3Box, LayerParams)
local dNxy = sqrt( LayerParams.vtSlicing:getX() * LayerParams.vtSlicing:getX() + LayerParams.vtSlicing:getY() * LayerParams.vtSlicing:getY())
local dNz = LayerParams.vtSlicing:getZ()
-- altezza necessaria per lo strand
local dHStrand = 0.5 * LayerParams.dStrand * dNxy + LayerParams.dLayHeight * dNz
-- altezza necessaria per il tool
local dHTool = LayerParams.dTDiam / 2 * dNxy
-- altezza disponibile
local dHBox = EgtGetInfo( s_nPartId, KEY_BOX_MIN_Z, 'i') or 0
local dHDisp = b3Box:getMin():getZ() - dHBox
local dCorrZ = max( 0, max( dHStrand, dHTool) - dHDisp)
-- applico la correzione al pezzo
local vtMove = dCorrZ * Z_AX()
EgtMove( s_nPartId, vtMove, GDB_RT.GLOB)
EgtSetInfo( s_nPartId, KEY_MOVED_PART2, vtMove)
-- correggo la posizione del riferimento
local nFrameId = EgtGetFirstNameInGroup( s_nPartId, LAY_FRAME)
EgtMove( nFrameId, - vtMove, GDB_RT.GLOB)
end
------------------------------------------------------------------
local function FindWipeEndPoint( ptS, vtDir, dLen, vtSlicing)
local ptE = ptS + vtDir * dLen
-- verifico soddisfi altezza minima per non entrare nella tavola
local k = 1
while ptE:getZ() < s_dHMin + GEO.EPS_SMALL and k < 36 do
vtDir:rotate( vtSlicing, 10)
ptE = ptS + vtDir * dLen
k = k + 1
end
return ptE
end
-------------------------------------------------------------------
local function AddCurvesToToolPath( vEntIds, nTpathGrpId, nOrder, bInvert, vtSlicing, dLayHeight)
local vIds = {} -- vettore con gli id ordinati delle curve nel gruppo dei ToolPath
local nStart = EgtIf( nOrder == PRINT_ORDER.EXT_INT, 1, #vEntIds)
local nEnd = EgtIf( nOrder == PRINT_ORDER.EXT_INT, #vEntIds, 1)
local nStep = EgtIf( nOrder == PRINT_ORDER.EXT_INT, 1, -1)
local nIdx = 1
for i = nStart, nEnd, nStep do
-- copio nel gruppo toolpath
if i == nStart then
vIds[nIdx] = EgtCopyGlob( vEntIds[i], nTpathGrpId, GDB_IN.LAST_SON)
else
vIds[nIdx] = EgtCopyGlob( vEntIds[i], vIds[nIdx-1], GDB_IN.AFTER)
end
-- mi sposto dell'altezza layer
EgtMove( vIds[nIdx], dLayHeight * vtSlicing, GDB_RT.GLOB)
if EgtCurveIsClosed( vIds[nIdx]) then
EgtSetInfo( vIds[nIdx], KEY_CLOSED_CRV, 1)
-- eventuale inversione
if bInvert then
EgtInvertCurve( vIds[nIdx])
EgtSetInfo( vIds[nIdx], KEY_INVERTED_CRV, 1)
end
end
EgtModifyCurveExtrusion( vIds[nIdx], vtSlicing, GDB_RT.GLOB)
EgtSetColor( vIds[nIdx], EgtStdColor('GRAY'))
EgtSetStatus( vIds[nIdx], GDB_ST.ON)
nIdx = nIdx + 1
end
return vIds
end
-------------------------------------------------------------------
local function AddLink( vCrv, nTpathGrpId, nLinkType, dLinkParam, dSPOffs, dStrand, vtSlicing)
if not vCrv or #vCrv == 0 then return end
local k = 0
local bPrevClosed = EgtGetInfo( vCrv[1], KEY_CLOSED_CRV, 'b') or false
for i = 2, #vCrv do
-- il link ha senso solo su curve chiuse
local bCurrClosed = EgtCurveIsClosed( vCrv[i])
if bCurrClosed and bPrevClosed then
-- aggiorno k per calcolo dell'offset
local sPrevName = EgtGetName( vCrv[i-1])
local sCurrName = EgtGetName( vCrv[i])
local nType = EgtGetInfo( vCrv[i], KEY_TYPE, 'i')
if sPrevName ~= sCurrName or nType == TYPE.INFILL or nType == TYPE.AUX_SOLID or nType == TYPE.RIB then
k = k + 1
end
-- se nessun raccordo modifico solo lo start point della curva
if nLinkType == LINK_TYPE.NONE then
local dLen = k * dSPOffs
if dSPOffs < 0 then
dLen = EgtCurveLength( vCrv[i]) + dLen
end
local dPar = EgtCurveParamAtLength( vCrv[i], dLen)
if dPar then EgtChangeClosedCurveStart( vCrv[i], dPar) end
else
-- altrimenti verifico se ha senso creare raccordo
-- local dDist = dist( EgtEP( vCrv[i-1]), EgtSP( vCrv[i]))
local dDist = EgtPointCurveDist( EgtEP( vCrv[i-1]), vCrv[i])
if dDist < dStrand + 10 * GEO.EPS_SMALL then
local nLinkId
-- modifico lo start point
local dLen = EgtCurveLength( vCrv[i-1]) - EgtIf( k > 1, abs( dSPOffs), 0)
EgtTrimCurveEndAtLen( vCrv[i-1], dLen)
EgtChangeClosedCurveStartPoint( vCrv[i], EgtEP( vCrv[i-1]))
-- aggiungo il raccordo
EgtTrimCurveEndAtLen( vCrv[i-1], EgtCurveLength( vCrv[i-1]) - dLinkParam / 2)
EgtTrimCurveStartAtLen( vCrv[i], dLinkParam / 2)
if nLinkType == LINK_TYPE.LINEAR then
nLinkId = EgtCurveCompoFromPoints( nTpathGrpId, {EgtEP( vCrv[i-1]), EgtSP( vCrv[i])})
elseif nLinkType == LINK_TYPE.BIARC then
local frLoc = Frame3d( ORIG(), vtSlicing)
local nGrpTmp = EgtGroup( nTpathGrpId, frLoc, GDB_RT.GLOB)
local _, _, dAngIni = SphericalFromVector( EgtEV( vCrv[i-1], nGrpTmp))
local _, _, dAngFin = SphericalFromVector( EgtSV( vCrv[i], nGrpTmp))
nLinkId = EgtBiArc( nGrpTmp, EgtEP( vCrv[i-1], nGrpTmp), EgtSP( vCrv[i], nGrpTmp), dAngIni, dAngFin, 0.5)
EgtRelocateGlob( nLinkId, nTpathGrpId, GDB_IN.LAST_SON)
EgtErase( nGrpTmp)
end
if nLinkId then
EgtRelocate( nLinkId, vCrv[i], GDB_IN.BEFORE)
EgtModifyCurveExtrusion( nLinkId, vtSlicing, GDB_RT.GLOB)
EgtSetInfo( nLinkId, KEY_TYPE, TYPE.LINK)
EgtSetName( nLinkId, LINK_CRV)
end
end
end
end
bPrevClosed = bCurrClosed
end
end
---------------------------------------------------------------------
local function AddOffsetLeadPoint( vIds, nFirstCopy, dOffsetLP, nLinkType)
-- se link va fatto solo sulla shell esterna
local nLast = EgtIf( nLinkType == LINK_TYPE.NONE, #vIds, 1)
if abs( dOffsetLP) > GEO.EPS_SMALL then
for i = 1, nLast do
if dOffsetLP > GEO.EPS_SMALL then
-- taglio curva
EgtTrimCurveStartAtLen( vIds[i], dOffsetLP)
else
-- è necessario aggiungere un tratto
local nAddCrv = EgtCopyGlob( EgtIf( i == 1, nFirstCopy, vIds[i]), vIds[1], GDB_IN.AFTER)
EgtTrimCurveStartAtLen( nAddCrv, EgtCurveLength( nAddCrv) - abs( dOffsetLP))
EgtAddCurveCompoCurve( vIds[i], nAddCrv, true, false)
end
end
end
-- elimino curva aux usata per prima shell
EgtErase( nFirstCopy)
end
--------------------------------------------------------------------
local function AddLeadIn( nCrvId, LayerParams, nGrpId)
local ptE = EgtSP( nCrvId, GDB_ID.ROOT)
local vtTang = EgtSV( nCrvId, GDB_ID.ROOT)
local vtOrtho = Vector3d( vtTang)
local dAng = 90
if ( LayerParams.bInvert and LayerParams.nOrder == PRINT_ORDER.INT_EXT) or
( not LayerParams.bInvert and LayerParams.nOrder == PRINT_ORDER.EXT_INT) then
dAng = - 90
end
vtOrtho:rotate( LayerParams.vtSlicing, dAng)
local ptS = ptE - LayerParams.dLeadInTangDist * vtTang + LayerParams.dLeadInOrthoDist * vtOrtho
-- verifico che non affondi nella tavola
if ptS:getZ() < s_dHMin + GEO.EPS_SMALL then return end
local nLeadInCrv
if LayerParams.nLeadInType == LEAD_TYPE.LINEAR then
nLeadInCrv = EgtCurveCompoFromPoints( nGrpId, {ptS, ptE}, GDB_RT.GLOB)
elseif LayerParams.nLeadInType == LEAD_TYPE.ARC then
nLeadInCrv = EgtArc2PV( nGrpId, ptE, ptS, -vtTang, GDB_RT.GLOB)
EgtInvertCurve( nLeadInCrv)
end
if nLeadInCrv then
EgtRelocate( nLeadInCrv, nCrvId, GDB_IN.BEFORE)
EgtModifyCurveExtrusion( nLeadInCrv, LayerParams.vtSlicing, GDB_RT.GLOB)
EgtSetInfo( nLeadInCrv, KEY_TYPE, TYPE.LINK)
EgtSetName( nLeadInCrv, LEAD_IN_CRV)
end
end
--------------------------------------------------------------------
local function AddLeadOut( nCrvId, LayerParams, nGrpId)
local ptS = EgtEP( nCrvId, GDB_ID.ROOT)
local vtTang = EgtEV( nCrvId, GDB_ID.ROOT)
local vtOrtho = Vector3d( vtTang)
local dAng = - 90
if ( LayerParams.bInvert and LayerParams.nOrder == PRINT_ORDER.INT_EXT) or
( not LayerParams.bInvert and LayerParams.nOrder == PRINT_ORDER.EXT_INT) then
dAng = 90
end
vtOrtho:rotate( LayerParams.vtSlicing, dAng)
local ptE = ptS + LayerParams.dLeadOutTangDist * vtTang + LayerParams.dLeadOutOrthoDist * vtOrtho
local nLeadOutCrv
if LayerParams.nLeadOutType == LEAD_TYPE.LINEAR then
nLeadOutCrv = EgtCurveCompoFromPoints( nGrpId, {ptS, ptE}, GDB_RT.GLOB)
elseif LayerParams.nLeadOutType == LEAD_TYPE.ARC then
nLeadOutCrv = EgtArc2PV( nGrpId, ptS, ptE, vtTang, GDB_RT.GLOB)
end
if nLeadOutCrv then
EgtRelocate( nLeadOutCrv, nCrvId, GDB_IN.AFTER)
EgtModifyCurveExtrusion( nLeadOutCrv, LayerParams.vtSlicing, GDB_RT.GLOB)
EgtSetInfo( nLeadOutCrv, KEY_TYPE, TYPE.LINK)
EgtSetName( nLeadOutCrv, LEAD_OUT_CRV)
end
return nLeadOutCrv
end
--------------------------------------------------------------------
local function AddRetraction( nCrvId, vtSlicing, dCoastingLen, dWipeLen, dWipeDir)
-- recupero i parametri per retrazione
local nType = EgtGetInfo( nCrvId, KEY_TYPE, 'i')
local bClosed = EgtGetInfo( nCrvId, KEY_CLOSED_CRV, 'b') or false
local bInverted = EgtGetInfo( nCrvId, KEY_INVERTED_CRV, 'b') or false
-- curva ausiliaria per generare correttamente wipe
local nCopyId = EgtCopyGlob( nCrvId, nCrvId, GDB_IN.AFTER)
if not EgtCurveIsClosed( nCopyId) then
local ptNewStart = EgtEP( nCrvId)
local dPar = EgtCurveParamAtPoint( nCopyId, ptNewStart)
local _, dParE = EgtCurveDomain( nCopyId)
if abs( dPar - dParE) < GEO.EPS_SMALL then
EgtCloseCurveCompo( nCopyId)
EgtChangeClosedCurveStartPoint( nCopyId, ptNewStart)
else
-- caso con sovrapposizione
EgtTrimCurveStartAtParam( nCopyId, dPar)
end
end
local nCoastingId
if dCoastingLen > GEO.EPS_SMALL then
nCoastingId = EgtCopyGlob( nCrvId, nCrvId, GDB_IN.AFTER)
local dPar = EgtCurveParamAtLength( nCoastingId, EgtCurveLength( nCoastingId) - dCoastingLen)
if not dPar then
EgtErase( nCoastingId)
nCoastingId = nil
else
EgtTrimCurveStartAtParam( nCoastingId, dPar)
-- aggiorno la curva originale
if dPar > GEO.EPS_SMALL then
EgtTrimCurveEndAtParam( nCrvId, dPar)
else
EgtErase( nCrvId)
end
EgtModifyCurveExtrusion( nCoastingId, vtSlicing, GDB_RT.GLOB)
EgtSetName( nCoastingId, COASTING_CRV)
EgtSetInfo( nCoastingId, KEY_TYPE, TYPE.COASTING)
EgtSetColor( nCoastingId, EgtStdColor('ORANGE'))
end
end
if dWipeLen > GEO.EPS_SMALL then
local nWipeId
if bClosed then
-- se era chiusa ( quindi analogo alle shell)
nWipeId = nCopyId
nCopyId = nil
EgtTrimCurveEndAtLen( nWipeId, dWipeLen)
else
-- se extra shell, infill a zigzag, spiral vase o rib che non termina sulla parete
local vtDir = EgtEV( nCoastingId or nCrvId, GDB_ID.ROOT)
local dAng = dWipeDir + s_nDefaultWipeAng
-- verifico se necessario cambiare il segno all'angolo
local bChangeSign = false
if nType == TYPE.INFILL or nType == TYPE.AUX_SOLID then
local vtS = EgtGetInfo( nCrvId, KEY_ZIG_ZAG_DIR, 'v')
local bSameDir = AreSameVectorApprox( vtS, vtDir)
bChangeSign = ( bInverted == bSameDir)
else
bChangeSign = bInverted
end
vtDir:rotate( vtSlicing, EgtIf( bChangeSign, - dAng, dAng))
local ptS = EgtEP( nCoastingId or nCrvId, GDB_ID.ROOT)
local ptE = FindWipeEndPoint( ptS, vtDir, dWipeLen, vtSlicing)
nWipeId = EgtCurveCompoFromPoints( EgtGetParent( nCoastingId or nCrvId), {ptS, ptE}, GDB_RT.GLOB)
EgtModifyCurveExtrusion( nWipeId, vtSlicing, GDB_RT.GLOB)
EgtRelocateGlob( nWipeId, nCoastingId or nCrvId, GDB_IN.AFTER)
end
EgtSetName( nWipeId, WIPE_CRV)
EgtSetInfo( nWipeId, KEY_TYPE, TYPE.WIPE)
EgtSetColor( nWipeId, EgtStdColor('AQUA'))
end
if nCopyId then EgtErase( nCopyId) end
return nCoastingId
end
--------------------------------------------------------------------
local function AddRetractionOnLastCrv( nCrvId, nTpathGrpId, LayerParams, dCoastingLen, dWipeLen, dWipeDir)
if LayerParams.nLeadOutType == LEAD_TYPE.NONE then
AddRetraction( nCrvId, LayerParams.vtSlicing, dCoastingLen, dWipeLen, dWipeDir)
else
local nLeadOutId = EgtGetLastInGroup( nTpathGrpId)
local dLen = EgtCurveLength( nLeadOutId)
if dLen > dCoastingLen - 500 * GEO.EPS_SMALL then
-- coinvolge solo la curva di lead out
local dNewCoastingLen = EgtIf( abs( dCoastingLen - dLen) < 500 * GEO.EPS_SMALL, dLen, dCoastingLen) -- verifico se interamente coinvolta
AddRetraction( nLeadOutId, LayerParams.vtSlicing, dNewCoastingLen, dWipeLen, dWipeDir)
else
-- coinvolge parte dell'ultima shell crv
local dNewCoastingLen = dCoastingLen - dLen
local nCoastingId = AddRetraction( nCrvId, LayerParams.vtSlicing, dNewCoastingLen, 0.0, dWipeDir)
EgtAddCurveCompoCurve( nCoastingId, nLeadOutId)
EgtSetInfo( nCoastingId, KEY_CLOSED_CRV, 0)
-- wipe
AddRetraction( nCoastingId, LayerParams.vtSlicing, 0, dWipeLen, dWipeDir)
end
end
end
---------------------------------------------------------------------
local function CalcShellsToolPath( vEntIds, nTpathGrpId, LayerParams)
if not vEntIds then return end
-- aggiungo le curve nel toolpath
local vIds = AddCurvesToToolPath( vEntIds, nTpathGrpId, LayerParams.nOrder, LayerParams.bInvert, LayerParams.vtSlicing, LayerParams.dLayHeight)
local nFirstCopy = EgtCopyGlob( vIds[1], nTpathGrpId) -- necessaria per corretto offset lead point sulla shell esterna
-- aggiungo gli opportuni raccordi
AddLink( vIds, nTpathGrpId, LayerParams.nLinkType, LayerParams.dLinkParam, LayerParams.dSPOffs, LayerParams.dStrand, LayerParams.vtSlicing)
-- offset lead point
AddOffsetLeadPoint( vIds, nFirstCopy, LayerParams.dOffsetLP, LayerParams.nLinkType)
-- aggiungo leadin/leadout
if LayerParams.nLeadInType ~= LEAD_TYPE.NONE then
AddLeadIn( vIds[1], LayerParams, nTpathGrpId)
end
if LayerParams.nLeadOutType ~= LEAD_TYPE.NONE then
EgtTrimCurveEndAtLen( vIds[#vIds], EgtCurveLength( vIds[#vIds]) - LayerParams.dOffsetLP)
AddLeadOut( vIds[#vIds], LayerParams, nTpathGrpId)
end
-- aggiungo coasting/wipe
for i = 1, #vIds - 1 do
local nNextId = EgtGetNext( vIds[i])
if EgtGetInfo( nNextId, KEY_TYPE, 'i') ~= TYPE.LINK then
AddRetraction( vIds[i], LayerParams.vtSlicing, LayerParams.dCoastingLen, LayerParams.dWipeLen, LayerParams.dWipeDir)
end
end
-- sull'ultima curva gestione speciale per eventuale lead out
AddRetractionOnLastCrv( vIds[#vIds], nTpathGrpId, LayerParams, LayerParams.dCoastingLen, LayerParams.dWipeLen, LayerParams.dWipeDir)
end
---------------------------------------------------------------------
local function CalcExtraShellToolPath( vEntIds, nTpathGrpId, LayerParams)
if not vEntIds then return end
-- aggiungo le curve nel toolpath
local vIds = AddCurvesToToolPath( vEntIds, nTpathGrpId, PRINT_ORDER.EXT_INT, false, LayerParams.vtSlicing, LayerParams.dLayHeight)
-- aggiungo gli opportuni raccordi
local sPrevName = EgtGetName( vIds[1])
for i = 2, #vIds do
local sCurrName = EgtGetName( vIds[i])
-- se hanno lo stesso nome vanno collegate
if sCurrName == sPrevName then
local ptS = EgtEP( vIds[i-1])
local ptE = EgtSP( vIds[i])
local nLinkId = EgtCurveCompoFromPoints( nTpathGrpId, {ptS, ptE})
if nLinkId then
EgtRelocateGlob( nLinkId, vIds[i], GDB_IN.BEFORE)
EgtModifyCurveExtrusion( nLinkId, LayerParams.vtSlicing, GDB_RT.GLOB)
EgtSetInfo( nLinkId, KEY_TYPE, TYPE.LINK)
EgtSetName( nLinkId, LINK_CRV)
end
end
sPrevName = sCurrName
end
-- aggiungo coasting/wipe
for i = 1, #vIds do
-- verifico non sia collegato al successivo tramite link
local nNextId = EgtGetNext( vIds[i])
if not nNextId or EgtGetInfo( nNextId, KEY_TYPE, 'i') ~= TYPE.LINK then
-- recupero i parametri
local dCoastingLen, dWipeLen, dWipeDir
local bClosed = EgtGetInfo( vIds[i], KEY_CLOSED_CRV, 'b') or false
if not bClosed then
local bInverted = EgtGetInfo( vIds[i], KEY_INVERTED_CRV, 'b') or false
local vCoastLen = EgtGetInfo( vIds[i], KEY_EXTRA_SHELL_COASTING, 'vd')
local vWipeLen = EgtGetInfo( vIds[i], KEY_EXTRA_SHELL_WIPE, 'vd')
local vWipeDir = EgtGetInfo( vIds[i], KEY_EXTRA_SHELL_WIPE_DIR, 'vd')
-- se curva è stata invertita devo prendere le info legate a quello che era il suo punto di inizio, altrimenti prendo le info legate al punto finale
dCoastingLen = EgtIf( bInverted, vCoastLen[1], vCoastLen[2])
dWipeLen = EgtIf( bInverted, vWipeLen[1], vWipeLen[2])
dWipeDir = EgtIf( bInverted, vWipeDir[1], vWipeDir[2])
else
-- se chiusa considero i parametri delle shell complete
dCoastingLen = LayerParams.dCoastingLen
dWipeLen = LayerParams.dWipeLen
dWipeDir = LayerParams.dWipeDir
end
AddRetraction( vIds[i], LayerParams.vtSlicing, dCoastingLen, dWipeLen, dWipeDir)
end
end
end
---------------------------------------------------------------------
local function CalcInfillToolPath( vEntIds, nTpathGrpId, LayerParams)
if not vEntIds then return end
-- aggiungo le curve nel toolpath
local vIds = AddCurvesToToolPath( vEntIds, nTpathGrpId, LayerParams.nOrder, LayerParams.bInvert, LayerParams.vtSlicing, LayerParams.dLayHeight)
-- aggiungo eventuali link
AddLink( vIds, nTpathGrpId, LayerParams.nLinkType, LayerParams.dLinkParam, LayerParams.dSPOffs, LayerParams.dStrand, LayerParams.vtSlicing)
-- aggiungo coasting/wipe
for i = 1, #vIds do
local nNextId = EgtGetNext( vIds[i])
if not nNextId or EgtGetInfo( nNextId, KEY_TYPE, 'i') ~= TYPE.LINK then
AddRetraction( vIds[i], LayerParams.vtSlicing, LayerParams.dCoastingLen, LayerParams.dWipeLen, LayerParams.dWipeDir)
end
end
end
---------------------------------------------------------------------
local function CalcAuxSolidsToolPath( nAuxSolidsGrp, nAuxSolidsPathGrp, nTpathGrpId, LayerParams)
if not nAuxSolidsGrp or not nAuxSolidsPathGrp then return end
-- recupero le curve relative al primo solido ausiliario
local sPrevName = AUX_SOLID_CRV
local nSolidId = EgtGetFirstNameInGroup( nAuxSolidsGrp, AUX_SOLIDS_CRV .. '*')
while nSolidId do
local sName = EgtGetName( nSolidId)
if sName ~= sPrevName then
-- recupero tutti i percorsi relativi a quel solido
local vEntIds = EgtGetNameInGroup( nAuxSolidsPathGrp, sName .. '*')
if vEntIds then
-- recupero i parametri relativi al solido
local nOrder = EgtGetInfo( nSolidId, KEY_AUX_SOLIDS_PRINT_ORDER, 'i')
local nLinkType = EgtGetInfo( nSolidId, KEY_AUX_SOLIDS_LINK_TYPE, 'i')
local dLinkParam = EgtGetInfo( nSolidId, KEY_AUX_SOLIDS_LINK_PARAM, 'd')
local dSPOffset = EgtGetInfo( nSolidId, KEY_AUX_SOLIDS_SP_OFFSET, 'd')
local dCoastingLen = EgtGetInfo( nSolidId, KEY_AUX_SOLIDS_COASTING_LEN, 'd')
local dWipeLen = EgtGetInfo( nSolidId, KEY_AUX_SOLIDS_WIPE_LEN, 'd')
local dWipeDir = EgtGetInfo( nSolidId, KEY_AUX_SOLIDS_WIPE_DIR, 'd')
-- copio i percorsi nel gruppo toolpath
local vIds = AddCurvesToToolPath( vEntIds, nTpathGrpId, nOrder, LayerParams.bInvert, LayerParams.vtSlicing, LayerParams.dLayHeight)
-- aggiungo link
AddLink( vIds, nTpathGrpId, nLinkType, dLinkParam, dSPOffset, LayerParams.dStrand, LayerParams.vtSlicing)
-- coasting e wipe
for i = 1, #vIds do
local nNextId = EgtGetNext( vIds[i])
if not nNextId or EgtGetInfo( nNextId, KEY_TYPE, 'i') ~= TYPE.LINK then
AddRetraction( vIds[i], LayerParams.vtSlicing, dCoastingLen, dWipeLen, dWipeDir)
end
end
end
end
sPrevName = sName
nSolidId = EgtGetNextName( nSolidId, AUX_SOLIDS_CRV .. '*')
end
end
-------------------------------------------------------------------
--------------------------- RIBS -----------------------------------
--------------------------------------------------------------------
local function VerifyRibsLink( nLinkId, nCurr, nNext, dStrand, nGrpTmp)
local nGrp = EgtGetParent( nCurr)
-- verifico se il link interseca le due curve nell'altro estremo
local ptS = EgtSP( nCurr)
local ptE = EgtEP( nNext)
local dParS = EgtCurveParamAtPoint( nLinkId, ptS)
local dParE = EgtCurveParamAtPoint( nLinkId, ptE)
if nCurr ~= nNext and ( dParS or dParE) then
return false
end
-- verifico se si trova nella regione ammissibile
local nSurfId = EgtGetInfo( nCurr, KEY_ASSOCIATED_SURF, 'i')
local nRes = EgtCurveWithRegionClassify( nLinkId, nSurfId)
local nType1 = EgtGetInfo( nCurr, KEY_RIBS_TYPE, 'i')
local nType2 = EgtGetInfo( nNext, KEY_RIBS_TYPE, 'i')
if ( nType1 == RIB_TYPE.INTERNAL or nType1 == RIB_TYPE.SUPPORT) and ( nType2 == RIB_TYPE.INTERNAL or nType2 == RIB_TYPE.SUPPORT) then
if nRes == GDB_CRC.OUT or nRes == GDB_CRC.INTERS then
return false
end
elseif nType1 == RIB_TYPE.EXTERNAL and nType2 == RIB_TYPE.EXTERNAL then
if nRes == GDB_CRC.IN or nRes == GDB_CRC.INTERS then
return false
end
end
-- verifico se il link interseca una delle altre costolature
local vRibsIds = EgtGetNameInGroup( nGrp, RIBS_CRV .. '*')
local nLinkSrf = EgtSurfFrFatCurve( nGrpTmp, nLinkId, 0.5 * dStrand, false) or GDB_ID.NULL
for i = 1, #vRibsIds do
if vRibsIds[i] ~= nCurr and vRibsIds[i] ~= nNext then
local nRes = EgtCurveWithRegionClassify( vRibsIds[i], nLinkSrf)
if nRes == GDB_CRC.INTERS then
return false
end
end
end
return true
end
--------------------------------------------------------------------
local function CalcRibsLink( nCurr, nNext, nLoopGrp, dStrand, bForceLink, vtSlicing, nGrpTmp)
local ptS = EgtEP( nCurr)
local ptE = EgtSP( nNext)
local nCrvId = EgtGetFirstNameInGroup( nLoopGrp, TRIM_SURF_LOOP)
-- recupero la curva di offset su cui calcolare link
while nCrvId do
local dParS = EgtCurveParamAtPoint( nCrvId, ptS, 10 * GEO.EPS_SMALL)
local dParE = EgtCurveParamAtPoint( nCrvId, ptE, 10 * GEO.EPS_SMALL)
if dParS and dParE then
local bInvert = false
local bClosed = EgtCurveIsClosed( nCrvId)
if bClosed then
-- se la curva è chiusa verifico i due percorsi possibili dParS->dParE e dParE->dParS
local nCopyId1 = EgtCopyGlob( nCrvId, nCurr, GDB_IN.AFTER)
local nCopyId2 = EgtCopyGlob( nCrvId, nCurr, GDB_IN.AFTER)
EgtTrimCurveStartEndAtParam( nCopyId1, dParS, dParE)
EgtTrimCurveStartEndAtParam( nCopyId2, dParE, dParS)
EgtInvertCurve( nCopyId2)
local dLen1 = EgtCurveLength( nCopyId1)
local dLen2 = EgtCurveLength( nCopyId2)
if dLen1 > dLen2 then
bInvert = true
dParS, dParE = dParE, dParS
end
EgtErase( nCopyId1)
EgtErase( nCopyId2)
end
local nCopyId = EgtCopyGlob( nCrvId, nLoopGrp)
local nLinkId = EgtCopyGlob( nCrvId, nCurr, GDB_IN.AFTER)
if dParS > dParE and not bClosed then
bInvert = true
dParS, dParE = dParE, dParS
end
EgtTrimCurveStartEndAtParam( nLinkId, dParS, dParE)
EgtSetInfo( nLinkId, KEY_TYPE, TYPE.RIB)
EgtSetName( nLinkId, LINK_CRV)
EgtModifyCurveExtrusion( nLinkId, vtSlicing, GDB_RT.GLOB)
if bInvert then EgtInvertCurve( nLinkId) end
-- verifico se è valido
local bValid = VerifyRibsLink( nLinkId, nCurr, nNext, dStrand, nGrpTmp)
if not bValid then
EgtErase( nLinkId)
EgtErase( nCopyId)
return
end
-- elimino dalle curve di contorno il link appena trovato
if bClosed then
EgtTrimCurveStartEndAtParam( nCrvId, dParE, dParS)
EgtErase( nCopyId)
else
if dParS < GEO.EPS_SMALL then
-- forzare la fine della curva nel suo inizio significa cancellarla completamente
EgtErase( nCrvId)
else
EgtTrimCurveEndAtParam( nCrvId, dParS)
end
local _, dEnd = EgtCurveDomain( nCopyId)
if abs( dParE - dEnd) < GEO.EPS_SMALL then
-- forzare l'inizio della curva nella sua fine significa cancellarla completamente
EgtErase( nCopyId)
else
EgtTrimCurveStartAtParam( nCopyId, dParE)
end
end
return nLinkId
end
nCrvId = EgtGetNextName( nCrvId, TRIM_SURF_LOOP)
end
-- se non ho trovato un collegamento sul bordo, creo una linea tra ptS e ptE
if bForceLink then
local nLinkId = EgtCurveCompoFromPoints( EgtGetParent( nCurr), {ptS, ptE})
local bValid = VerifyRibsLink( nLinkId, nCurr, nNext, dStrand, nGrpTmp)
if bValid then
EgtSetInfo( nLinkId, KEY_TYPE, TYPE.RIB)
EgtSetName( nLinkId, LINK_CRV)
EgtModifyCurveExtrusion( nLinkId, vtSlicing, GDB_RT.GLOB)
EgtRelocateGlob( nLinkId, nCurr, GDB_IN.AFTER)
else
EgtErase( nLinkId)
end
end
end
--------------------------------------------------------------------
local function VerifyRibsLead( nId, nRibId, dStrand, bInVsOut, nGrpTmp)
local nGrp = EgtGetParent( nRibId)
local nLeadId = EgtCopyGlob( nId, nGrp)
if bInVsOut then
EgtExtendCurveStartByLen( nLeadId, dStrand * 0.5)
else
EgtExtendCurveEndByLen( nLeadId, dStrand * 0.5)
end
-- verifico che intersechi solo l'estremo corretto
if not EgtCurveIsClosed( nRibId) then
local pt = EgtIf( bInVsOut, EgtEP( nRibId), EgtSP( nRibId))
local dPar = EgtCurveParamAtPoint( nLeadId, pt)
if dPar then
EgtErase( nLeadId)
return false
end
end
local pt1 = EgtIf( bInVsOut, EgtSP( nLeadId), EgtEP( nLeadId))
local pt2 = EgtIf( bInVsOut, EgtEP( nRibId), EgtSP( nRibId))
if dist( pt1, pt2) < dStrand + GEO.EPS_SMALL then
EgtErase( nLeadId)
return false
end
local _, dParE = EgtCurveDomain( nLeadId)
local vtDir = EgtMV( nRibId)
local dParCrv = 1
local dTol = 10 * GEO.EPS_SMALL
for dParCrv = 1, dParE do
local vtS = EgtUV( nLeadId, dParCrv - 1, 1)
local vtE = EgtUV( nLeadId, dParCrv, -1)
-- se tratto lineare allineato con la direzione del setto verifico sia sufficientemente lontano
if AreSameVectorApprox( vtS, vtE) and ( (vtS - vtDir):sqlen() < dTol * dTol or (vtS + vtDir):sqlen() < dTol * dTol) then
local dDist = EgtPointCurveDist( EgtUP( nLeadId, dParCrv - 0.5), nRibId)
if dDist < dStrand + GEO.EPS_SMALL then
EgtErase( nLeadId)
return false
end
end
end
-- verifico non intersechi altri setti
local vRibsIds = EgtGetNameInGroup( EgtGetParent( nRibId), RIBS_CRV .. '*')
local nLeadLoc = EgtCopyGlob( nLeadId, nGrpTmp)
for i = 1, #vRibsIds do
if vRibsIds[i] ~= nRibId then
local nCrvLoc = EgtCopyGlob( vRibsIds[i], nGrpTmp)
local ptInt = EgtIP( nLeadLoc, nCrvLoc, ORIG())
if ptInt then
EgtErase( nLeadId)
return false
end
end
end
-- se lead out verifico non si sovrapponga al lead in
if not bInVsOut then
-- recupero il lead in
local nPrev = EgtGetPrev( nRibId)
if nPrev and EgtGetName( nPrev) == LEAD_IN_CRV then
local nSrfTot = EgtSurfFrFatCurve( EgtGetParent( nLeadId), nPrev, 0.5 * dStrand, false)
if nSrfTot then
local nRes = EgtCurveWithRegionClassify( nLeadId, nSrfTot)
if nRes == GDB_CRC.IN or nRes == GDB_CRC.INTERS then
EgtErase( nSrfTot)
EgtErase( nLeadId)
return false
end
else
nSrfTot = EgtSurfFrFatCurve( EgtGetParent( nLeadId), nLeadId, 0.5 * dStrand, false)
if nSrfTot then
local nRes = EgtCurveWithRegionClassify( nPrev, nSrfTot)
if nRes == GDB_CRC.IN or nRes == GDB_CRC.INTERS then
EgtErase( nSrfTot)
EgtErase( nLeadId)
return false
end
end
end
EgtErase( nSrfTot)
end
end
EgtErase( nLeadId)
return true
end
-------------------------------------------------------------------
local function FindCorrectRibsLead( dPar, nCrv, nCrvOffs, bLeadInvert, dLeadLen, dStrand, bInVsOut, nGrpTmp)
local nLeadId
local bInvert = bLeadInvert -- valore di default è quello settato nel file dei parametri
local _, dParEnd = EgtCurveDomain( nCrvOffs)
local bClosed = EgtCurveIsClosed( nCrvOffs)
local bOnlyOneCurve = not bClosed and ( dPar < GEO.EPS_SMALL or abs( dPar - dParEnd) < GEO.EPS_SMALL)
local nMainCrv = nCrvOffs -- curva preferita da utilizzare per lead in
local nOtherCrv -- altra possibile curva da ultizzare nel caso nMainCrv non sia adatta
if bClosed then
EgtChangeClosedCurveStart( nCrvOffs, dPar)
nOtherCrv = nCrvOffs
elseif not bOnlyOneCurve then
nOtherCrv = EgtSplitCurveAtParam( nCrvOffs, dPar)
end
-- calcolo del parametro bInvert
if bOnlyOneCurve then
-- invert dipende dall'estremo da cui parte il setto
bInvert = abs( dPar - dParEnd) < GEO.EPS_SMALL
elseif not bClosed then
-- invert può essere legato anche alla lunghezza dei tratti possibili
local dLen1 = EgtCurveLength( nMainCrv)
local dLen2 = EgtCurveLength( nOtherCrv)
if dLen1 > dLeadLen - GEO.EPS_SMALL and dLen2 < dLeadLen - GEO.EPS_SMALL then
bInvert = true
elseif dLen1 < dLeadLen - GEO.EPS_SMALL and dLen2 > dLeadLen - GEO.EPS_SMALL then
bInvert = false
end
if not bInvert then
nMainCrv, nOtherCrv = nOtherCrv, nMainCrv
end
end
-- primo tentativo con la curva favorita
nLeadId = EgtCopyGlob( nMainCrv, nCrv, EgtIf( bInVsOut, GDB_IN.BEFORE, GDB_IN.AFTER))
if bInvert then EgtInvertCurve( nLeadId) end
EgtTrimCurveEndAtLen( nLeadId, dLeadLen)
if bInVsOut then EgtInvertCurve( nLeadId) end
if VerifyRibsLead( nLeadId, nCrv, dStrand, bInVsOut, nGrpTmp) then
-- se valido aggiorno le curve per prossimi lead in/out
if bInvert then
EgtTrimCurveEndAtLen( nMainCrv, EgtCurveLength( nCrvOffs) - dLeadLen)
else
EgtTrimCurveStartAtLen( nMainCrv, dLeadLen)
end
elseif not nOtherCrv then
-- se non è valido e non ho altre curve possibili cancello
EgtErase( nLeadId)
return nil
else
-- se non è valido ma ho altra curva possibile, tento con quella
EgtErase( nLeadId)
nLeadId = EgtCopyGlob( nOtherCrv, nCrv, EgtIf( bInVsOut, GDB_IN.BEFORE, GDB_IN.AFTER))
if not bInvert then EgtInvertCurve( nLeadId) end
EgtTrimCurveEndAtLen( nLeadId, dLeadLen)
if bInVsOut then EgtInvertCurve( nLeadId) end
if VerifyRibsLead( nLeadId, nCrv, dStrand, bInVsOut, nGrpTmp) then
if bInvert then
EgtTrimCurveStartAtLen( nOtherCrv, dLeadLen)
else
EgtTrimCurveEndAtLen( nOtherCrv, EgtCurveLength( nCrvOffs) - dLeadLen)
end
else
EgtErase( nLeadId)
bInvert = not bInvert
return nil
end
-- aggiorno parametro bInvert
bInvert = not bInvert
end
return nLeadId, bInvert
end
--------------------------------------------------------------------
local function AddRibsLeadIn( nCrv, nLoopsGrp, dStrand, vtSlicing, nGrpTmp)
local dLILen = EgtGetInfo( nCrv, KEY_RIBS_LEAD_IN_LEN, 'd')
local bLIInvert = EgtGetInfo( nCrv, KEY_RIBS_LEAD_IN_INVERT, 'b')
if dLILen < GEO.EPS_SMALL then return end
-- recupero la curva di offset su cui calcolare leadin
local ptS = EgtSP( nCrv)
local nCrvOffs = EgtGetFirstInGroup( nLoopsGrp)
while nCrvOffs do
local dParS = EgtCurveParamAtPoint( nCrvOffs, ptS)
if dParS then
local nLeadIn = FindCorrectRibsLead( dParS, nCrv, nCrvOffs, bLIInvert, dLILen, dStrand, true, nGrpTmp)
-- se lead in possibile
if nLeadIn then
EgtModifyCurveExtrusion( nLeadIn, vtSlicing, GDB_RT.GLOB)
EgtSetInfo( nLeadIn, KEY_TYPE, TYPE.RIB)
EgtSetName( nLeadIn, LEAD_IN_CRV)
end
return
end
nCrvOffs = EgtGetNext( nCrvOffs)
end
end
--------------------------------------------------------------------
local function AddRibsLeadOut( nCrv, nTPathGrp, nLoopsGrp, vtSlicing, dStrand, nGrpTmp, bForceNoBorder)
local dRibsLOLen = EgtGetInfo( nCrv, KEY_RIBS_LEAD_OUT_LEN, 'd')
local dRibsLOCoasting = EgtGetInfo( nCrv, KEY_RIBS_LEAD_OUT_COASTING, 'd')
local dRibsLOWipe = EgtGetInfo( nCrv, KEY_RIBS_LEAD_OUT_WIPE, 'd')
local dRibsLOWipeAng = EgtGetInfo( nCrv, KEY_RIBS_LEAD_OUT_WIPE_DIR, 'd')
local bRibsLOInvert = EgtGetInfo( nCrv, KEY_RIBS_LEAD_OUT_INVERT, 'b')
if abs( dRibsLOLen) < GEO.EPS_SMALL and
abs( dRibsLOCoasting) < GEO.EPS_SMALL and
abs( dRibsLOWipe) < GEO.EPS_SMALL then return end
-- se setto chiuso oppure non deve stare sul bordo (rib unbounded) applico la stessa uscita delle shell
if EgtCurveIsClosed( nCrv) or bForceNoBorder then
return AddRetraction( nCrv, vtSlicing, dRibsLOCoasting, dRibsLOWipe, dRibsLOWipeAng)
end
local ptE = EgtEP( nCrv, GDB_ID.ROOT)
local vtE = EgtEV( nCrv, GDB_ID.ROOT)
-- recupero la curva di offset su cui calcolare lead out
local nCrvOffs = EgtGetFirstInGroup( nLoopsGrp)
while nCrvOffs do
local dParE = EgtCurveParamAtPoint( nCrvOffs, ptE, GEO.EPS_SMALL, GDB_RT.GLOB)
if dParE then
local nCrvLO
local nCoasting
local nWipe
-- trovo curva opportuna per lead out
local nCrvRef, bInvert = FindCorrectRibsLead( dParE, nCrv, nCrvOffs, bRibsLOInvert, dRibsLOLen + dRibsLOCoasting, dStrand, false, nGrpTmp)
if nCrvRef then
-- verifico se la curva ha lunghezza sufficiente
local dLen = EgtCurveLength( nCrvRef)
local bSkip = ( dLen - dRibsLOLen - dRibsLOCoasting < - GEO.EPS_SMALL)
-- primo tratto ( segue offset con flusso aperto)
if dRibsLOLen > GEO.EPS_SMALL and not bSkip then
nCrvLO = EgtCopyGlob( nCrvRef, nCrv, GDB_IN.AFTER)
EgtTrimCurveEndAtLen( nCrvLO, dRibsLOLen)
EgtModifyCurveExtrusion( nCrvLO, vtSlicing, GDB_RT.GLOB)
EgtSetInfo( nCrvLO, KEY_TYPE, TYPE.RIB)
EgtSetName( nCrvLO, LEAD_OUT_CRV)
-- aggiorno ptE e vtE
ptE = EgtEP( nCrvLO, GDB_ID.ROOT)
vtE = EgtEV( nCrvLO, GDB_ID.ROOT)
end
-- secondo tratto ( segue offset con flusso chiuso)
if dRibsLOCoasting > GEO.EPS_SMALL then
nCoasting = EgtCopyGlob( nCrvRef, nCrvLO or nCrv, GDB_IN.AFTER)
EgtTrimCurveStartAtLen( nCoasting, dRibsLOLen)
EgtTrimCurveEndAtLen( nCoasting, dRibsLOCoasting)
EgtModifyCurveExtrusion( nCoasting, vtSlicing, GDB_RT.GLOB)
EgtSetName( nCoasting, COASTING_CRV)
EgtSetInfo( nCoasting, KEY_TYPE, TYPE.COASTING)
EgtSetColor( nCoasting, EgtStdColor('ORANGE'))
-- aggiorno ptE e vtE
ptE = EgtEP( nCoasting, GDB_ID.ROOT)
vtE = EgtEV( nCoasting, GDB_ID.ROOT)
end
EgtErase( nCrvRef)
-- terzo tratto ( diretto verso esterno con ugello chiuso)
if dRibsLOWipe > GEO.EPS_SMALL then
local dAng = dRibsLOWipeAng + s_nDefaultWipeAng
local nType = EgtGetInfo( nCrv, KEY_RIBS_TYPE, 'i')
if nType == RIB_TYPE.EXTERNAL then dAng = - dAng end
vtE:rotate( vtSlicing, EgtIf( bInvert, - dAng, dAng))
local ptFinal = FindWipeEndPoint( ptE, vtE, dRibsLOWipe, vtSlicing)
nWipe = EgtCurveCompoFromPoints( nTPathGrp, { ptE, ptFinal}, GDB_RT.GLOB)
EgtModifyCurveExtrusion( nWipe, vtSlicing, GDB_RT.GLOB)
EgtRelocateGlob( nWipe, nCoasting or nCrvLO or nCrv, GDB_IN.AFTER)
EgtSetName( nWipe, WIPE_CRV)
EgtSetInfo( nWipe, KEY_TYPE, TYPE.WIPE)
EgtSetColor( nWipe, EgtStdColor('AQUA'))
end
else
-- aggiungo coasting e wipe come sulle shell normali
AddRetraction( nCrv, vtSlicing, dRibsLOCoasting, dRibsLOWipe, dRibsLOWipeAng)
end
return
end
nCrvOffs = EgtGetNext( nCrvOffs)
end
-- se non ho trovato curva sul bordo su cui fare il lead out aggiungo coasting e wipe come sulle shell normali
AddRetraction( nCrv, vtSlicing, dRibsLOCoasting, dRibsLOWipe, dRibsLOWipeAng)
end
---------------------------------------------------------------------
local function CalcRibsToolPath( vEntIds, nRibsGrp, nTpathGrpId, LayerParams)
if not vEntIds or #vEntIds == 0 then return end
-- gruppo temporaneo con sistema di riferimento locale per conti
local frLoc = Frame3d( ORIG(), LayerParams.vtSlicing)
local nGrpTmp = EgtGroup( nRibsGrp, frLoc, GDB_RT.GLOB)
-- aggiungo le costolature nel toolpath
local nNewFirstEnt
for i = 1, #vEntIds do
-- copio entità nel gruppo toolpath
local nNewEntId = EgtCopyGlob( vEntIds[i], nTpathGrpId, GDB_IN.LAST_SON)
-- mi sposto dell'altezza layer
EgtMove( nNewEntId, LayerParams.dLayHeight * LayerParams.vtSlicing, GDB_RT.GLOB)
EgtModifyCurveExtrusion( nNewEntId, LayerParams.vtSlicing, GDB_RT.GLOB)
EgtSetColor( nNewEntId, EgtStdColor('MAROON'))
if i == 1 then nNewFirstEnt = nNewEntId end
end
-- recupero i gruppi delle costolature
local tabRibs = {}
local nFirst = nNewFirstEnt
while nFirst do
local sName = EgtGetName( nFirst)
local vIds = EgtGetNameInGroup( nTpathGrpId, sName)
table.insert( tabRibs, vIds)
nFirst = EgtGetNextName( vIds[#vIds], RIBS_CRV .. '*')
end
local bSpecialCase = EgtGetInfo( nRibsGrp, KEY_RIBS_SPECIAL_CASE, 'b') or false
-- Link
local nLoopGrp = EgtGetFirstGroupInGroup( nRibsGrp)
-- collego le passate di una stessa costolatura
for i = 1, #tabRibs do
if EgtCurveIsClosed( tabRibs[i][1]) then
AddLink( tabRibs[i], nTpathGrpId, LINK_TYPE.NONE, LayerParams.dLinkParam, LayerParams.dSPOffs, LayerParams.dStrand, LayerParams.vtSlicing)
else
local bLoopRib = EgtGetInfo( tabRibs[i][1], KEY_LOOP_RIB, 'b') or false
for j = 1, #tabRibs[i] - 1 do
local bUserLink = EgtGetInfo( tabRibs[i][j], KEY_RIBS_USER_LINK, 'b') or false
local nOrig1 = EgtGetInfo( tabRibs[i][j], KEY_ORIGINAL_RIB, 'i') or 0
local nOrig2 = EgtGetInfo( tabRibs[i][j + 1], KEY_ORIGINAL_RIB, 'i') or 0
local nSplitId1 = EgtGetInfo( tabRibs[i][j], KEY_SPLIT_ID, 'i') or 0
local nSplitId2 = EgtGetInfo( tabRibs[i][j + 1], KEY_SPLIT_ID, 'i') or 0
local bForceLink = ( nOrig1 == nOrig2)
if ( nOrig1 ~= nOrig2 and bUserLink) or ( nSplitId1 == nSplitId2 and nOrig1 == nOrig2) then
local nLinkId = CalcRibsLink( tabRibs[i][j], tabRibs[i][j + 1], nLoopGrp, LayerParams.dStrand, bForceLink, LayerParams.vtSlicing, nGrpTmp)
-- creo link fittizio per eliminare tratto corrispondente sulla curva di offset
if not bSpecialCase and bForceLink then
local nFakeLink = CalcRibsLink( tabRibs[i][j + 1], tabRibs[i][j], nLoopGrp, LayerParams.dStrand, false, LayerParams.vtSlicing, nGrpTmp)
EgtErase( nFakeLink)
end
-- se LoopRib congiungo i setti in unico percorso
if bLoopRib and nLinkId then
EgtAddCurveCompoCurve( tabRibs[i][j], nLinkId)
EgtAddCurveCompoCurve( tabRibs[i][j], tabRibs[i][j + 1])
tabRibs[i][j+1] = tabRibs[i][j] -- aggiorno id nel vettore dei setti per gestire correttamente la curva allo step successivo
end
end
end
-- se LoopRib aggiungo collegamento tra primo e ultimo setto del gruppo
if bLoopRib then
local nTotCrv = #tabRibs[i]
local nLinkId = CalcRibsLink( tabRibs[i][nTotCrv], tabRibs[i][1], nLoopGrp, LayerParams.dStrand, false, LayerParams.vtSlicing, nGrpTmp)
if nLinkId then
-- se curva unica
if tabRibs[i][nTotCrv] == tabRibs[i][1] then
EgtAddCurveCompoCurve( tabRibs[i][1], nLinkId)
-- setto info di curva chiusa per gestire correttamente il wipe
EgtSetInfo( tabRibs[i][1], KEY_CLOSED_CRV, 1)
-- modifica dello start point ( considera quello delle shell)
local nCrvGrp = EgtGetParent( nTpathGrpId)
local ptStart = EgtGetInfo( nCrvGrp, KEY_START_POINT, 'p')
if ptStart then
EgtChangeClosedCurveStartPoint( tabRibs[i][1], ptStart)
end
else
EgtAddCurveCompoCurve( tabRibs[i][1], nLinkId, true, false)
EgtAddCurveCompoCurve( tabRibs[i][1], tabRibs[i][nTotCrv], true, false)
tabRibs[i][nTotCrv] = tabRibs[i][1]
end
end
end
if bSpecialCase then
local nFakeLink = CalcRibsLink( tabRibs[i][#tabRibs[i]], tabRibs[i][1], nLoopGrp, LayerParams.dStrand, false, LayerParams.vtSlicing, nGrpTmp)
EgtErase( nFakeLink)
end
end
end
-- se necessario collego le diverse costolature
for i = 1, #tabRibs - 1 do
local bLink1 = EgtGetInfo( tabRibs[i][1], KEY_RIBS_LINK, 'b')
local bLink2 = EgtGetInfo( tabRibs[i + 1][1], KEY_RIBS_LINK, 'b')
if bLink1 and bLink2 then
local nCnt = #tabRibs[i]
CalcRibsLink( tabRibs[i][nCnt], tabRibs[i + 1][1], nLoopGrp, LayerParams.dStrand, false, LayerParams.vtSlicing, nGrpTmp)
end
end
-- leadin/leadout
local bForceNoBorder = false
local nType = EgtGetInfo( vEntIds[1], KEY_RIBS_TYPE, 'i')
if nType == RIB_TYPE.UNBOUNDED then
bForceNoBorder = true
end
local nCrvRib = nNewFirstEnt
while nCrvRib do
-- verifico se necessario lead in
local nPrev = EgtGetPrev( nCrvRib)
if ( not nPrev or EgtGetName( nPrev) ~= LINK_CRV) and not bForceNoBorder then
AddRibsLeadIn( nCrvRib, nLoopGrp, LayerParams.dStrand, LayerParams.vtSlicing, nGrpTmp)
end
-- verifico se necessario lead out
local nNext = EgtGetNext( nCrvRib)
if not nNext or EgtGetName( nNext) ~= LINK_CRV then
AddRibsLeadOut( nCrvRib, nTpathGrpId, nLoopGrp, LayerParams.vtSlicing, LayerParams.dStrand, nGrpTmp, bForceNoBorder)
end
nCrvRib = EgtGetNextName( nCrvRib, RIBS_CRV .. '*')
end
EgtErase( nGrpTmp)
end
-------------------------------------------------------------------
------------------------- SPIRAL VASE ------------------------------
--------------------------------------------------------------------
local function AddSpiralVaseLeadOut( nOldId, LayerParams)
if LayerParams.nLeadOutType ~= LEAD_TYPE.NONE then
EgtTrimCurveEndAtLen( nOldId, EgtCurveLength( nOldId) - LayerParams.dOffsetLP)
local nLeadOut = AddLeadOut( nOldId, LayerParams, EgtGetParent( nOldId))
if nLeadOut then
local dDelta = LayerParams.dLayHeight / EgtCurveLength( nOldId) * EgtCurveLength( nLeadOut)
EgtSpiralizeCurveAlongExtrusion( nLeadOut, dDelta)
end
AddRetractionOnLastCrv( nOldId, EgtGetParent( nOldId), LayerParams, LayerParams.dCoastingLen, LayerParams.dWipeLen, LayerParams.dWipeDir)
else
AddRetraction( nOldId, LayerParams.vtSlicing, LayerParams.dCoastingLen, LayerParams.dWipeLen, LayerParams.dWipeDir)
end
end
---------------------------------------------------------------------
local function SpiralVase( vLayIds, LayerParams)
local nOldId, nOldPathId
local bFirst = true
local nSlicingType = EgtGetInfo( s_nPartId, KEY_SLICING_TYPE, 'i')
-- copio ultimo layer
if nSlicingType ~= SLICING_TYPE.DEG45_X and nSlicingType ~= SLICING_TYPE.DEG45_Y then
local nNewLay = EgtCopyGlob( vLayIds[#vLayIds], vLayIds[#vLayIds], GDB_IN.AFTER)
table.insert( vLayIds, nNewLay)
EgtMove( nNewLay, LayerParams.dLayHeight * LayerParams.vtSlicing, GDB_RT.GLOB)
-- aggiorno nome e info
local sOldIdx = string.sub( EgtGetName( vLayIds[#vLayIds]), 6)
local nNewIdx = tonumber( sOldIdx) + 1
EgtSetName( nNewLay, SLICE_LAYER .. EgtNumToString( nNewIdx))
EgtSetInfo( nNewLay, KEY_SLICE_NBR, nNewIdx)
local dZOld = EgtGetInfo( vLayIds[#vLayIds], KEY_SLICE_Z, 'd') or 0
EgtSetInfo( nNewLay, KEY_SLICE_Z, dZOld + LayerParams.dLayHeight)
end
local b3Tot = BBox3d()
-- ciclo sui layer
for nIdx = 1, #vLayIds do
-- cerco i gruppi di contorni
local vCrvGrpIds = EgtGetNameInGroup( vLayIds[ nIdx], CONTOUR_GRP.."*")
if #vCrvGrpIds > 1 then
-- se più di un gruppo di curve warning
EgtOutLog( 'Warning : in spiral vase mode more than one curve (layer '..tostring( nIdx)..') - CalcToolPath')
end
for i = 1, #vCrvGrpIds do
-- recupero il gruppo dei percorsi
local nPathGrpId = EgtGetFirstNameInGroup( vCrvGrpIds[i], PATH_GRP)
if not nPathGrpId then
EgtOutBox( 'Error missing paths', 'ToolPathCalc')
return
else
EgtSetStatus( nPathGrpId, GDB_ST.OFF)
end
-- recupero il gruppo dei percorsi utensile
local nTpathGrpId = EgtGetFirstNameInGroup( vCrvGrpIds[i], TOOLPATH_GRP)
if not nTpathGrpId then
nTpathGrpId = EgtGroup( vCrvGrpIds[i])
EgtSetName( nTpathGrpId, TOOLPATH_GRP)
else
EgtEmptyGroup( nTpathGrpId)
end
-- creo il percorso di lavoro :
local nEntId = EgtGetFirstInGroup( nPathGrpId)
while nEntId do
local nNewEntId = EgtCopyGlob( nEntId, nTpathGrpId, GDB_IN.LAST_SON)
local vtMove = V_NULL()
-- eventuale spostamento dell'altezza layer
if nSlicingType == SLICING_TYPE.DEG45_X or nSlicingType == SLICING_TYPE.DEG45_Y then
vtMove = LayerParams.dLayHeight * LayerParams.vtSlicing
EgtMove( nNewEntId, vtMove, GDB_RT.GLOB)
end
EgtModifyCurveExtrusion( nNewEntId, LayerParams.vtSlicing, GDB_RT.GLOB)
-- eventuale inversione
if LayerParams.bInvert then
EgtInvertCurve( nNewEntId)
EgtSetInfo( nNewEntId, KEY_INVERTED_CRV, 1)
end
EgtSetColor( nNewEntId, EgtStdColor('GRAY'))
-- se primo layer
if bFirst and nNewEntId then
-- mi sposto dell'altezza layer
EgtMove( nNewEntId, LayerParams.dLayHeight * LayerParams.vtSlicing, GDB_RT.GLOB)
-- eventuale lead in
if LayerParams.nLeadInType ~= LEAD_TYPE.NONE then
EgtTrimCurveStartAtLen( nNewEntId, LayerParams.dOffsetLP)
AddLeadIn( nNewEntId, LayerParams, nTpathGrpId)
end
bFirst = false
else
local ptOld = EgtEP( nOldId, GDB_ID.ROOT)
local ptNew = EgtSP( nNewEntId, GDB_ID.ROOT)
if dist( ptNew, ptOld) < LayerParams.dStrand then
-- se i punti sono vicini ma non coincidenti modifico la curva per avere transizione più uniforme
if not AreSamePointApprox( ptOld, ptNew) then
-- recupero la curva da usare come guida
local nGuideId = EgtCopyGlob( nOldPathId, nTpathGrpId)
-- la porto alla stessa quota del toolpath
EgtMove( nGuideId, vtMove + LayerParams.dLayHeight * LayerParams.vtSlicing, GDB_RT.GLOB)
EgtChangeClosedCurveStartPoint( nGuideId, ptOld, GDB_RT.GLOB)
EgtSpiralizeCurveAlongGuide( nNewEntId, nGuideId)
EgtErase( nGuideId)
end
else
EgtOutLog( 'Warning : in spiral vase mode no link betweeen toolpaths (layer '..tostring( nIdx)..') - CalcToolPath')
-- aggiungo uscita, coasting e wipe sulla curva precedente
AddSpiralVaseLeadOut( nOldId, LayerParams)
end
EgtSpiralizeCurveAlongExtrusion( nNewEntId, LayerParams.dLayHeight)
end
nOldPathId = nEntId
nOldId = nNewEntId
nEntId = EgtGetNext( nEntId)
end
-- aggiorno il box dei toolpath
local b3Box = ComputeToolPathBox( nTpathGrpId)
b3Tot:Add( b3Box)
end
if EgtProcessEvents( EgtIf( PRINT, 300, 0) + nIdx / #vLayIds * 100, 0) == 1 then
EgtDraw()
return false
end
end
-- aggiungo uscita, coasting e wipe su ultima curva
AddSpiralVaseLeadOut( nOldId, LayerParams)
-- correzione in z
AddZCorrection( b3Tot, LayerParams)
return true
end
---------------------------------------------------------------------
function CalcToolPath.Exec( nPartId)
s_nPartId = nPartId
-- Recupero i layer da processare
local vLayIds = EgtGetNameInGroup( s_nPartId, SLICE_LAYER.."*")
if not vLayIds then
EgtOutBox( 'Error missing slices', 'ToolPathCalc')
return true
end
-- recupero i parametri per calcolo dei toolpath
local LayerParams = GetLayerParamsForToolPathCalc()
-- altezza necessaria per correzione wipe
local dNxy = sqrt( LayerParams.vtSlicing:getX() * LayerParams.vtSlicing:getX() + LayerParams.vtSlicing:getY() * LayerParams.vtSlicing:getY())
local dHBox = EgtGetInfo( s_nPartId, KEY_BOX_MIN_Z, 'i') or 0
s_dHMin = LayerParams.dTDiam / 2 * dNxy + dHBox
-- caso spiral vase
if LayerParams.bSpiralVase then
return SpiralVase( vLayIds, LayerParams)
end
local b3Tot = BBox3d() -- box dei toolpath
-- Ciclo sui layer
for nIdx = 1, #vLayIds do
-- scorro tutti i gruppi di contorni
local nCrvGrpId = EgtGetFirstNameInGroup( vLayIds[ nIdx], CONTOUR_GRP.."*")
while nCrvGrpId do
-- recupero il gruppo dei percorsi
local nPathGrpId = EgtGetFirstNameInGroup( nCrvGrpId, PATH_GRP)
if not nPathGrpId then
EgtOutBox( 'Error missing paths', 'ToolPathCalc')
return
else
EgtSetStatus( nPathGrpId, GDB_ST.OFF)
end
-- recupero il gruppo dei percorsi utensile
local nTpathGrpId = EgtGetFirstNameInGroup( nCrvGrpId, TOOLPATH_GRP)
if not nTpathGrpId then
nTpathGrpId = EgtGroup( nCrvGrpId)
EgtSetName( nTpathGrpId, TOOLPATH_GRP)
else
EgtEmptyGroup( nTpathGrpId)
end
-- suddivido i ribs per tipologia
local nRibsGrp = EgtGetFirstNameInGroup( nCrvGrpId, RIBS_GRP)
local tRibs = {{}, {}, {}, {}}
local vRibsIds = EgtGetNameInGroup( nRibsGrp, RIBS_CRV .. '*') or {}
for i = 1, #vRibsIds do
local nType = EgtGetInfo( vRibsIds[i], KEY_RIBS_TYPE, 'i') or 1
table.insert( tRibs[nType], vRibsIds[i])
end
-- realizzo le diverse tipologie in base all'ordine selezionato
for j = 1, #LayerParams.vPrintOrder do
if LayerParams.vPrintOrder[j] == PRINT_ELEMENT.SHELL then
-- shell
local vShellIds = EgtGetNameInGroup( nPathGrpId, SHELL_CRV .. '*')
CalcShellsToolPath( vShellIds, nTpathGrpId, LayerParams)
elseif LayerParams.vPrintOrder[j] == PRINT_ELEMENT.EXTRA_SHELL then
-- extra shell
local vExtraShellIds = EgtGetNameInGroup( nPathGrpId, EXTRA_SHELL_CRV .. '*')
CalcExtraShellToolPath( vExtraShellIds, nTpathGrpId, LayerParams)
elseif LayerParams.vPrintOrder[j] == PRINT_ELEMENT.INFILL then
-- infill
local vInfillIds = EgtGetNameInGroup( nPathGrpId, INFILL_CRV .. '*')
CalcInfillToolPath( vInfillIds, nTpathGrpId, LayerParams)
elseif LayerParams.vPrintOrder[j] == PRINT_ELEMENT.AUX_SOLID then
-- solidi ausiliari
local nAuxSolidsGrp = EgtGetFirstNameInGroup( vLayIds[nIdx], AUX_SOLIDS_GRP)
local nAuxSolidsPathGrp = EgtGetFirstNameInGroup( nCrvGrpId, AUX_SOLIDS_GRP)
CalcAuxSolidsToolPath( nAuxSolidsGrp, nAuxSolidsPathGrp, nTpathGrpId, LayerParams)
-- costolature
elseif LayerParams.vPrintOrder[j] == PRINT_ELEMENT.RIB_UNBOUNDED then
CalcRibsToolPath( tRibs[RIB_TYPE.UNBOUNDED], nRibsGrp, nTpathGrpId, LayerParams)
elseif LayerParams.vPrintOrder[j] == PRINT_ELEMENT.RIB_INTERNAL then
CalcRibsToolPath( tRibs[RIB_TYPE.INTERNAL], nRibsGrp, nTpathGrpId, LayerParams)
elseif LayerParams.vPrintOrder[j] == PRINT_ELEMENT.RIB_SUPPORT then
CalcRibsToolPath( tRibs[RIB_TYPE.SUPPORT], nRibsGrp, nTpathGrpId, LayerParams)
elseif LayerParams.vPrintOrder[j] == PRINT_ELEMENT.RIB_EXTERNAL then
CalcRibsToolPath( tRibs[RIB_TYPE.EXTERNAL], nRibsGrp, nTpathGrpId, LayerParams)
end
end
-- aggiorno il box dei toolpath
local b3Box = ComputeToolPathBox( nTpathGrpId)
b3Tot:Add( b3Box)
-- passo al gruppo di contorni successivo
nCrvGrpId = EgtGetNextName( nCrvGrpId, CONTOUR_GRP.."*")
end
if EgtProcessEvents( EgtIf( PRINT, 300, 0) + nIdx / #vLayIds * 100, 0) == 1 then
EgtDraw()
return
end
end
-- correzione in z
AddZCorrection( b3Tot, LayerParams)
return true
end
---------------------------------------------------------------------
return CalcToolPath