Files
3dprinting/LuaLibs/CalcToolPath.lua
T
SaraP a595fcdb98 3dPrinting :
- corretto collegamento fra ribs esterni che passa sotto il solido.
2023-08-30 09:52:28 +02:00

2078 lines
87 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.dInnerStrand = EgtGetInfo( s_nPartId, KEY_INNER_STRAND, 'd') or LayerParams.dStrand
LayerParams.dInnerStrand = EgtClamp( LayerParams.dInnerStrand, 0.5 * LayerParams.dStrand, 1.5 * LayerParams.dStrand)
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')
-- parametri infill
LayerParams.dInfillStrand = EgtGetInfo( s_nPartId, KEY_INFILL_STRAND, 'd') or LayerParams.dStrand
LayerParams.dInfillStrand = EgtClamp( LayerParams.dInfillStrand, 0.5 * LayerParams.dStrand, 1.5 * LayerParams.dStrand)
LayerParams.bInfillLink = EgtGetInfo( s_nPartId, KEY_INFILL_LINK, 'b') or false
LayerParams.dInfillCoasting = EgtGetInfo( s_nPartId, KEY_INFILL_COASTING, 'd') or 0
LayerParams.dInfillWipe = EgtGetInfo( s_nPartId, KEY_INFILL_WIPE, 'd') or 0
LayerParams.dInfillWipeDir = EgtGetInfo( s_nPartId, KEY_INFILL_WIPE_DIR, 'd') or 0
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
EgtSetInfo( vEntIds[i], KEY_ASSOCIATED_TP_CRV, vIds[nIdx])
EgtSetInfo( vIds[nIdx], KEY_ASSOCIATED_P_CRV, vEntIds[i])
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 AddStartPointOffsetOnLayer( nCrv, nCrvPrev, dSPOffs, nOrder, vtSlicing, dLayH)
if not EgtCurveIsClosed( nCrv) then return end
local dStrand = EgtGetInfo( nCrv, KEY_CRV_STRAND, 'd')
-- individuo eventuale curva di toolpath precendente da cui prendere il punto di partenza
local nPrev
local vPrevPath = EgtGetInfo( nCrv, EgtIf( nOrder == PRINT_ORDER.EXT_INT, KEY_PREV_CRV, KEY_NEXT_CRVS), 'vi')
if vPrevPath then
local nAssociatedPathCrv = EgtGetInfo( nCrv, KEY_ASSOCIATED_P_CRV, 'i')
local nPrevFirst = EgtGetInfo( vPrevPath[1], KEY_ASSOCIATED_TP_CRV, 'i')
local dOtherStrand = EgtGetInfo( nPrevFirst, KEY_CRV_STRAND, 'd')
for j = 1, #vPrevPath do
-- verifico se gli start point delle path curve sono sufficientemente vicini
if dist( EgtSP( vPrevPath[j], GDB_ID.ROOT), EgtSP( nAssociatedPathCrv, GDB_ID.ROOT)) < ( dStrand + dOtherStrand) * 0.5 + 100 * GEO.EPS_SMALL then
nPrev = EgtGetInfo( vPrevPath[j], KEY_ASSOCIATED_TP_CRV, 'i')
break
end
end
elseif nCrvPrev then
-- caso ribs chiuse in cui manca info sul precedente/successivo ( TODO da migliorare!)
nPrev = nCrvPrev
end
if not nPrev then return end
-- recupero punto di partenza originale prima di eventuale OffsetLeadPoint
local ptS = EgtGetInfo( nPrev, KEY_ORIGINAL_START_POINT, 'p') or EgtSP( nPrev, GDB_ID.ROOT)
EgtChangeClosedCurveStartPoint( nCrv, ptS, GDB_RT.GLOB)
local dLen = dSPOffs
if dSPOffs < 0 then
dLen = EgtCurveLength( nCrv) + dLen
end
local dPar = EgtCurveParamAtLength( nCrv, dLen)
if dPar then
EgtChangeClosedCurveStart( nCrv, dPar)
end
end
-------------------------------------------------------------------
local function AddLink( vCrv, nTpathGrpId, nLinkType, dLinkParam, dSPOffs, nOrder, vtSlicing)
if not vCrv or #vCrv == 0 then return end
if nLinkType == LINK_TYPE.NONE and abs( dSPOffs) > GEO.EPS_SMALL then
-- se nessun raccordo modifico solo lo start point delle curve
for i = 1, #vCrv do
AddStartPointOffsetOnLayer( vCrv[i], vCrv[i-1], dSPOffs, nOrder)
end
elseif nLinkType ~= LINK_TYPE.NONE then
-- modifico lo start point della prima curva
AddStartPointOffsetOnLayer( vCrv[1], nil, dSPOffs, nOrder)
local dPrevStrand = EgtGetInfo( vCrv[1], KEY_CRV_STRAND, 'd')
-- creo i raccordi
for i = 2, #vCrv do
-- il link ha senso solo su curva chiusa
if EgtCurveIsClosed( vCrv[i]) then
-- verifico se ha senso creare raccordo
local dDist = EgtPointCurveDist( EgtEP( vCrv[i-1]), vCrv[i])
local dCurrStrand = EgtGetInfo( vCrv[i], KEY_CRV_STRAND, 'd')
if dDist < ( dCurrStrand + dPrevStrand) * 0.5 + 10 * GEO.EPS_SMALL then
local nLinkId
-- modifico lo start point
local dLen = EgtCurveLength( vCrv[i-1]) - EgtIf( i > 2, 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)
EgtSetInfo( nLinkId, KEY_CRV_STRAND, max( dCurrStrand, dPrevStrand))
end
dPrevStrand = dCurrStrand
else
-- se raccordo non sensato perchè curve troppo distanti modifico lo start point
AddStartPointOffsetOnLayer( vCrv[i], vCrv[i-1], dSPOffs, nOrder)
end
end
end
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
-- conservo lo start point originale per AddStartPointOffsetOnLayer
EgtSetInfo( vIds[i], KEY_ORIGINAL_START_POINT, EgtSP( vIds[i], GDB_ID.ROOT))
if dOffsetLP > GEO.EPS_SMALL then
-- taglio curva
EgtTrimCurveStartAtLen( vIds[i], dOffsetLP)
else
-- è necessario aggiungere un tratto
local nAddCrv = EgtCopyGlob( EgtIf( i == 1 and nLinkType ~= LINK_TYPE.NONE, nFirstCopy, vIds[i]), vIds[1], GDB_IN.AFTER)
EgtTrimCurveStartAtLen( nAddCrv, EgtCurveLength( nAddCrv) - abs( dOffsetLP))
if not EgtAddCurveCompoCurve( vIds[i], nAddCrv, true, false) then
-- se fallisce cancello il tratto da aggiungere
EgtErase( nAddCrv)
end
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)
local dStrand = EgtGetInfo( nCrvId, KEY_CRV_STRAND, 'd')
EgtSetInfo( nLeadInCrv, KEY_CRV_STRAND, dStrand)
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)
local dStrand = EgtGetInfo( nCrvId, KEY_CRV_STRAND, 'd')
EgtSetInfo( nLeadOutCrv, KEY_CRV_STRAND, dStrand)
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 dLenTrim = EgtCurveLength( nCoastingId) - dCoastingLen
dLenTrim = max( dLenTrim, MIN_LEN)
local dPar = EgtCurveParamAtLength( nCoastingId, dLenTrim)
if not dPar then
dPar = EgtCurveParamAtLength( nCoastingId, MIN_LEN) or 0
end
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
if dWipeLen > GEO.EPS_SMALL then
local nWipeId
if bClosed then
-- se chiusa ( shell, SolidFill di tipo offset, ribs chiusi)
nWipeId = nCopyId
nCopyId = nil
EgtTrimCurveEndAtLen( nWipeId, dWipeLen)
else
-- se extra shell, infill, spiral vase o rib che non termina sulla parete
local ptS = EgtEP( nCoastingId or nCrvId, GDB_ID.ROOT)
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
-- riempimento
if nType == TYPE.INFILL or nType == TYPE.AUX_SOLID then
local vtS = EgtGetInfo( nCrvId, KEY_ZIG_ZAG_DIR, 'v')
if vtS then
-- solidfill a zigzag
if AreOppositeVectorApprox( vtS, vtDir) then bChangeSign = true end
else
-- riempimento generico ( linee, griglie, nido d'ape)
local nGrpLoc = EgtGroup( EgtGetParent( nCopyId), Frame3d( ORIG(), vtSlicing))
local nAuxSurf = EgtGetInfo( nCrvId, KEY_ASSOCIATED_SURF, 'i') or GDB_ID.NULL
-- verifico se direzione di default punta verso esterno del solido
local vtDirTest = Vector3d( vtDir)
vtDirTest:rotate( vtSlicing, s_nDefaultWipeAng)
local nCrvTest = EgtCurveCompoFromPoints( nGrpLoc, { ptS + 10 * GEO.EPS_SMALL * vtDirTest, ptS + vtDirTest}, GDB_RT.GLOB)
local nRes = EgtCurveWithRegionClassify( nCrvTest, nAuxSurf)
if nRes ~= GDB_CRC.OUT then
-- se non punta verso esterno provo con la direzione opposta
EgtRotate( nCrvTest, ptS, vtSlicing, 180, GDB_RT.GLOB)
nRes = EgtCurveWithRegionClassify( nCrvTest, nAuxSurf)
if nRes == GDB_CRC.OUT then
bChangeSign = true
end
end
EgtErase( nGrpLoc)
end
-- rib
elseif nType == TYPE.RIB then
local bInvertStrandOrder = EgtGetInfo( nCrvId, KEY_RIBS_INVERT_STRAND_ORDER, 'b') or false
local bInvertDir = EgtGetInfo( nCrvId, KEY_RIBS_INVERT_DIR, 'b') or false
bChangeSign = ( bInvertDir ~= bInvertStrandOrder)
-- extra shell
elseif nType == TYPE.EXTRA_SHELL or nType == TYPE.EXTRA_OUTER_SHELL then
bChangeSign = bInverted
end
vtDir:rotate( vtSlicing, EgtIf( bChangeSign, - dAng, dAng))
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
if nWipeId then
EgtSetName( nWipeId, WIPE_CRV)
EgtSetInfo( nWipeId, KEY_TYPE, TYPE.WIPE)
EgtSetInfo( nWipeId, KEY_CRV_STRAND, 0)
EgtSetColor( nWipeId, EgtStdColor('AQUA'))
end
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
-- assegno lo strand
for i = 1, #vIds do
local nType = EgtGetInfo( vIds[i], KEY_TYPE, 'i')
if nType == TYPE.OUTER_SHELL then
EgtSetInfo( vIds[i], KEY_CRV_STRAND, LayerParams.dStrand)
elseif nType == TYPE.INNER_SHELL then
EgtSetInfo( vIds[i], KEY_CRV_STRAND, LayerParams.dInnerStrand)
else -- infill
EgtSetInfo( vIds[i], KEY_CRV_STRAND, LayerParams.dInfillStrand)
end
end
-- aggiungo gli opportuni raccordi
AddLink( vIds, nTpathGrpId, LayerParams.nLinkType, LayerParams.dLinkParam, LayerParams.dSPOffs, LayerParams.nOrder, 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)
-- assegno strand
for i = 1, #vIds do
local nType = EgtGetInfo( vIds[i], KEY_TYPE, 'i')
if nType == TYPE.EXTRA_OUTER_SHELL then
EgtSetInfo( vIds[i], KEY_CRV_STRAND, LayerParams.dStrand)
else
EgtSetInfo( vIds[i], KEY_CRV_STRAND, LayerParams.dInnerStrand)
end
end
-- 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)
local dStrand1 = EgtGetInfo( vIds[i], KEY_CRV_STRAND, 'd')
local dStrand2 = EgtGetInfo( vIds[i-1], KEY_CRV_STRAND, 'd')
EgtSetInfo( nLinkId, KEY_CRV_STRAND, max( dStrand1, dStrand2))
end
else
-- se nome diverso ma chiuse applico lo start point
if EgtCurveIsClosed( vIds[i]) and EgtCurveIsClosed( vIds[i-1]) then
AddStartPointOffsetOnLayer( vIds[i], vIds[i-1], LayerParams.dSPOffs, PRINT_ORDER.EXT_INT, LayerParams.vtSlicing, LayerParams.dLayHeight)
end
end
sPrevName = sCurrName
end
-- aggiungo offset lead point sulle extra shell chiuse
for i = 1, #vIds do
if EgtCurveIsClosed( vIds[i]) then
local nCopy = EgtCopyGlob( nTpathGrpId, vIds[i])
AddOffsetLeadPoint( {vIds[i]}, nCopy, LayerParams.dOffsetLP, LINK_TYPE.NONE)
end
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
---------------------------------------------------------------------
----------------------- INFILL --------------------------------------
---------------------------------------------------------------------
local function ComputeShortestCrv( nCrvId, dParS, dParE)
local nParentId = EgtGetParent( nCrvId)
-- verifico i due percorsi possibili dParS->dParE e dParE->dParS
local nCopyId1 = EgtCopyGlob( nCrvId, nParentId, GDB_IN.AFTER)
local nCopyId2 = EgtCopyGlob( nCrvId, nParentId, 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
EgtErase( nCopyId1)
return nCopyId2
else
EgtErase( nCopyId2)
return nCopyId1
end
end
-----------------------------------------------------------------------
local function VerifyInfillLink( nLinkId, nCurr, nNext, vIds, dStrand, nGrpTmp)
-- regione occupata dal link
local dOffs = dStrand * 0.5
local nLinkSurf = EgtSurfFrFatCurve( nGrpTmp, nLinkId, dOffs, false)
if not nLinkSurf then return true end
-- verifico non intersechi altre curve di infill
for i = 1, #vIds do
if vIds[i] ~= nCurr and vIds[i] ~= nNext then
-- con curva
local nRes = EgtCurveCurveInters( vIds[i], nLinkId, nGrpTmp)
if nRes then return false end
-- con regione occupata
local nClassif = EgtCurveWithRegionClassify( vIds[i], nLinkSurf)
if nClassif == GDB_CRC.INTERS or nClassif == GDB_CRC.IN then
return false
end
end
end
-- verifica con le curve coinvolte dal link
if nLinkSurf then
local nCurrCopy = EgtCopyGlob( nCurr, nGrpTmp)
local _, nCnt = EgtTrimCurveWithRegion( nCurrCopy, nLinkSurf, true, false)
if nCnt > 1 then return false end
local nNextCopy = EgtCopyGlob( nNext, nGrpTmp)
_, nCnt = EgtTrimCurveWithRegion( nNextCopy, nLinkSurf, true, false)
if nCnt > 1 then return false end
-- verifico se tratti lineari paralleli al setto sono sufficientemente lontani
local dMinDist = dStrand * 0.5
local nLinkLoc = EgtCopyGlob( nLinkId, nGrpTmp)
local _, dParELink = EgtCurveDomain( nLinkLoc)
local nCurrLoc = EgtCopyGlob( nCurr, nGrpTmp)
local _, dParE = EgtCurveDomain( nCurrLoc)
for dPar = dParE, max( 1, dParE - 3), -1 do
local vtDirCurr = EgtUV( nCurrLoc, dPar - 0.5, -1)
for dParCrv = 1, dParELink do
local vtS = EgtUV( nLinkLoc, dParCrv - 1, 1)
local vtE = EgtUV( nLinkLoc, dParCrv, -1)
-- se tratto lineare allineato come curva corrente
if AreSameVectorApprox( vtS, vtE) and vtS * vtDirCurr < - 1 + GEO.EPS_SMALL then
-- verifico distanza
local nCrvTest = EgtCurveCompoFromPoints( nGrpTmp, { EgtUP( nCurrLoc, dPar-1), EgtUP( nCurrLoc, dPar)})
local dDist = EgtPointCurveDist( EgtUP( nLinkLoc, dParCrv - 0.5), nCrvTest)
if dDist < dMinDist + GEO.EPS_SMALL then
return false
end
end
end
end
local nNextLoc = EgtCopyGlob( nNext, nGrpTmp)
_, dParE = EgtCurveDomain( nNextLoc)
for dPar = 0, min( dParE - 1, 3) do
local vtDirCurr = EgtUV( nNextLoc, dPar + 0.5, -1)
for dParCrv = 1, dParELink do
local vtS = EgtUV( nLinkLoc, dParCrv - 1, 1)
local vtE = EgtUV( nLinkLoc, dParCrv, -1)
-- se tratto lineare allineato come curva corrente
if AreSameVectorApprox( vtS, vtE) and vtS * vtDirCurr < - 1 + GEO.EPS_SMALL then
-- verifico distanza
local nCrvTest = EgtCurveCompoFromPoints( nGrpTmp, { EgtUP( nNextLoc, dPar), EgtUP( nNextLoc, dPar + 1)})
local dDist = EgtPointCurveDist( EgtUP( nLinkLoc, dParCrv - 0.5), nCrvTest)
if dDist < dMinDist + GEO.EPS_SMALL then
return false
end
end
end
end
end
return true
end
---------------------------------------------------------------------
local function CalcInfillLink( vIds, nInfillGrp, dStrand, LayerParams)
if #vIds == 0 then return end
-- estraggo i loop delle superfici usate per trim
local nLoopGrp = EgtGroup( nInfillGrp)
local tSurfs = {}
for i = 1, #vIds do
local nTrimSurf = EgtGetInfo( vIds[i], KEY_ASSOCIATED_SURF, 'i')
-- controllo di non aver già estratto il suo loop
if not tSurfs[nTrimSurf] then
EgtMove( nTrimSurf, LayerParams.dLayHeight * LayerParams.vtSlicing, GDB_RT.GLOB)
local nChunks = EgtSurfFrChunkCount( nTrimSurf)
for i = 0, nChunks - 1 do
EgtExtractSurfFrChunkLoops( nTrimSurf, i, nLoopGrp)
end
tSurfs[nTrimSurf] = 1
end
end
local vCrvIds = EgtGetAllInGroup( nLoopGrp)
-- creo gruppo temporaneo per conti
local frLoc = Frame3d( ORIG(), LayerParams.vtSlicing)
local nGrpTmp = EgtGroup( nInfillGrp, frLoc, GDB_RT.GLOB)
-- creo vettore corrispondente a vIds per indicare quando la curva viene utilizzata nei link
local vUsed = {}
for i = 1, #vIds do
vUsed[i] = false
end
-- scorro le curve per creare link
local nCurr = vIds[1]
vUsed[1] = true
while nCurr do
local bFound = false
-- cerco tra le curve non utilizzate quale può essere usata per link
for i = 1, #vIds do
if bFound then break end
if not vUsed[i] then
local nNext = vIds[i]
local ptS = EgtEP( nCurr)
local ptE = EgtSP( nNext)
if not AreSamePointApprox( ptS, ptE) then
-- cerco di creare il link
for k = 1, #vCrvIds do
local dParS = EgtCurveParamAtPoint( vCrvIds[k], ptS, 10 * GEO.EPS_SMALL)
local dParE = EgtCurveParamAtPoint( vCrvIds[k], ptE, 10 * GEO.EPS_SMALL)
if dParS and dParE then
local nLinkId = ComputeShortestCrv( vCrvIds[k], dParS, dParE)
if nLinkId then
local bValid = VerifyInfillLink( nLinkId, nCurr, nNext, vIds, dStrand, nGrpTmp)
if not bValid then
EgtErase( nLinkId)
else
bFound = true
-- riposiziono le curve collegate
EgtRelocateGlob( nLinkId, nCurr, GDB_IN.AFTER)
EgtRelocateGlob( nNext, nLinkId, GDB_IN.AFTER)
-- sistemo le info del link
EgtSetInfo( nLinkId, KEY_TYPE, TYPE.INFILL)
EgtSetName( nLinkId, LINK_CRV)
EgtModifyCurveExtrusion( nLinkId, LayerParams.vtSlicing, GDB_RT.GLOB)
EgtSetInfo( nLinkId, KEY_CRV_STRAND, dStrand)
-- aggiorno per iterazione successiva
nCurr = vIds[i]
vUsed[i] = true
break
end
end
end
end
end
end
end
-- se link non è stato realizzato cerco il primo tratto non utilizzato da cui ripartire
if not bFound then
for i = 1, #vIds do
if not vUsed[i] then
nCurr = vIds[i]
vUsed[i] = true
bFound = true
break
end
end
-- se tutti i tratti utilizzati ho finito
if not bFound then nCurr = nil end
end
end
EgtErase( nGrpTmp)
end
---------------------------------------------------------------------
local function CalcInfillToolPath( nInfillGrp, nTpathGrpId, LayerParams)
local vEntIds = EgtGetNameInGroup( nInfillGrp, INFILL_CRV ..'*')
if not vEntIds or #vEntIds == 0 then return end
-- aggiungo le curve nel toolpath
local vIds = AddCurvesToToolPath( vEntIds, nTpathGrpId, PRINT_ORDER.EXT_INT, false, LayerParams.vtSlicing, LayerParams.dLayHeight)
-- assegno strand
for i = 1, #vIds do
EgtSetInfo( vIds[i], KEY_CRV_STRAND, LayerParams.dInfillStrand)
end
-- eventuale creazione dei link
if LayerParams.bInfillLink then
CalcInfillLink( vIds, nInfillGrp, LayerParams.dInfillStrand, LayerParams)
end
-- aggiungo coasting e wipe
for i = 1, #vIds do
local nNext = EgtGetNext( vIds[i])
if not nNext or EgtGetName( nNext) ~= LINK_CRV then
AddRetraction( vIds[i], LayerParams.vtSlicing, LayerParams.dInfillCoasting, LayerParams.dInfillWipe, LayerParams.dInfillWipeDir)
end
end
end
---------------------------------------------------------------------
----------------------- SOLID FILL ----------------------------------
---------------------------------------------------------------------
local function CalcSolidFillToolPath( nInfillGrp, nTpathGrpId, LayerParams)
local vEntIds = EgtGetNameInGroup( nInfillGrp, INFILL_CRV ..'*')
if not vEntIds or #vEntIds == 0 then return end
local nSolidFillType = EgtGetInfo( nInfillGrp, KEY_FILL_TYPE, 'i') or FILL_TYPE.ZIG_ZAG
local nOrder = PRINT_ORDER.EXT_INT
local bInvert = false
if nSolidFillType == FILL_TYPE.OFFSET then
-- copio i valori per le shell
nOrder = LayerParams.nOrder
bInvert = LayerParams.bInvert
end
-- aggiungo le curve nel toolpath
local vIds = AddCurvesToToolPath( vEntIds, nTpathGrpId, nOrder, bInvert, LayerParams.vtSlicing, LayerParams.dLayHeight)
-- assegno strand
for i = 1, #vIds do
EgtSetInfo( vIds[i], KEY_CRV_STRAND, LayerParams.dInfillStrand)
end
-- se riempimento ad offset sistemo come nel caso delle shell
if nSolidFillType == FILL_TYPE.OFFSET then
local nFirstCopy = EgtCopyGlob( vIds[1], nTpathGrpId)
-- aggiungo gli opportuni raccordi
AddLink( vIds, nTpathGrpId, LayerParams.nLinkType, LayerParams.dLinkParam, LayerParams.dSPOffs, LayerParams.nOrder, LayerParams.vtSlicing)
-- offset lead point
AddOffsetLeadPoint( vIds, nFirstCopy, LayerParams.dOffsetLP, LayerParams.nLinkType)
end
-- 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.dInfillCoasting, LayerParams.dInfillWipe, LayerParams.dInfillWipeDir)
end
end
end
--------------------------------------------------------------------------------------
local function JoinShellsAndSolidFills( nInfillGrp, vShellIds, vExtraShells, LayerParams, tabRibs)
local nFillType = EgtGetInfo( nInfillGrp, KEY_FILL_TYPE, 'i') or FILL_TYPE.NONE
if nFillType == FILL_TYPE.OFFSET and vShellIds then
-- cerco indice di realizzazione dei vari elementi di stampa
local vTypeSequence = {}
for i = 1, #LayerParams.vPrintOrder do
vTypeSequence[LayerParams.vPrintOrder[i]] = i
end
local nMin = vTypeSequence[PRINT_ELEMENT.SHELL]
local nMax = vTypeSequence[PRINT_ELEMENT.INFILL]
local bShellFirst = true
if nMin > nMax then
nMin, nMax = nMax, nMin
bShellFirst = false
end
-- verifico se extra shell realizzate tra shell e infill
if vExtraShells and nMin < vTypeSequence[PRINT_ELEMENT.EXTRA_SHELL] and vTypeSequence[PRINT_ELEMENT.EXTRA_SHELL] < nMax then
return
end
-- verifico se esistono setti esterni o unbounded realizzati tra le shell e gli infill
if #tabRibs[RIB_TYPE.UNBOUNDED] > 0 and nMin < vTypeSequence[PRINT_ELEMENT.RIB_UNBOUNDED] and vTypeSequence[PRINT_ELEMENT.RIB_UNBOUNDED] < nMax then
return
elseif #tabRibs[RIB_TYPE.EXTERNAL] > 0 and nMin < vTypeSequence[PRINT_ELEMENT.RIB_EXTERNAL] and vTypeSequence[PRINT_ELEMENT.RIB_EXTERNAL] < nMax then
return
end
-- verifico se ordinamento di shell e infill è coerente con PrintOrder
if ( bShellFirst and LayerParams.nOrder == PRINT_ORDER.INT_EXT) or ( not bShellFirst and LayerParams.nOrder == PRINT_ORDER.EXT_INT) then
return
end
-- aggiungo le curve di infill a quelle di shell
local nPathGrp = EgtGetParent( vShellIds[1])
local vInfillCrvs = EgtGetNameInGroup( nInfillGrp, INFILL_CRV ..'*') or {}
for k = 1, #vInfillCrvs do
table.insert( vShellIds, vInfillCrvs[k])
-- le sposto nel PathGrp in modo da non gestirle una seconda volta quando vengono trattati gli infill
EgtRelocateGlob( vInfillCrvs[k], nPathGrp)
end
end
end
-------------------------------------------------------------------
----------------------- AUX SOLIDS -------------------------------
-------------------------------------------------------------------
local function CalcAuxSolidsToolPath( nAuxSolidsGrp, nAuxSolidsPathGrp, nTpathGrpId, LayerParams)
if not nAuxSolidsGrp or not nAuxSolidsPathGrp then return end
-- recupero le curve di slicing relative al primo solido ausiliario
local nSolidId = EgtGetFirstNameInGroup( nAuxSolidsGrp, AUX_SOLIDS_CRV .. '*')
while nSolidId do
-- recupero tutti i percorsi relativi a quel solido
local sName = EgtGetName( nSolidId)
local vEntIds = EgtGetNameInGroup( nAuxSolidsPathGrp, sName .. '*')
if vEntIds then
-- recupero i parametri relativi al solido dalla curva di slicing
local nFillType = EgtGetInfo( nSolidId, KEY_AUX_SOLIDS_INFILL, 'i')
local dStrand = EgtGetInfo( nSolidId, KEY_AUX_SOLIDS_STRAND, 'd')
local nOrder = EgtGetInfo( nSolidId, KEY_AUX_SOLIDS_PRINT_ORDER, 'i')
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)
-- assegno strand
for i = 1, #vIds do
EgtSetInfo( vIds[i], KEY_CRV_STRAND, dStrand)
end
-- distinguo le shell dal riempimento
local vShells = {}
local vInfill = {}
for i = 1, #vIds do
local nType = EgtGetInfo( vIds[i], KEY_TYPE, 'i')
local bZigZag = EgtGetInfo( vIds[i], KEY_ZIG_ZAG_INFILL, 'b') or false
if nType == TYPE.INFILL or bZigZag then
table.insert( vInfill, vIds[i])
else
table.insert( vShells, vIds[i])
end
end
-- aggiungo link e offset lead point sulle shell
if #vShells > 0 then
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 dLPOffset = EgtGetInfo( nSolidId, KEY_AUX_SOLIDS_LP_OFFSET, 'd')
local nFirstCopy = EgtCopyGlob( vShells[1], nTpathGrpId) -- necessaria per avere il corretto offset lead point sulla shell esterna nel caso di link
AddLink( vShells, nTpathGrpId, nLinkType, dLinkParam, dSPOffset, nOrder, LayerParams.vtSlicing)
AddOffsetLeadPoint( vShells, nFirstCopy, dLPOffset, nLinkType)
end
-- aggiungo eventuale link su infill
if nFillType & FILL_CATEGORY.INFILL ~= 0 then
local bInfillLink = EgtGetInfo( nSolidId, KEY_AUX_SOLIDS_INFILL_LINK, 'b')
if bInfillLink then
CalcInfillLink( vInfill, nAuxSolidsPathGrp, dStrand, LayerParams)
end
end
-- coasting e wipe
for i = 1, #vIds do
local nNextId = EgtGetNext( vIds[i])
if not nNextId or EgtGetName( nNextId) ~= LINK_CRV then
AddRetraction( vIds[i], LayerParams.vtSlicing, dCoastingLen, dWipeLen, dWipeDir)
end
end
end
-- recupero il solido successivo
local nLastSolidId = EgtGetLastNameInGroup( nAuxSolidsGrp, sName)
nSolidId = EgtGetNextName( nLastSolidId, AUX_SOLIDS_CRV .. '*')
end
end
--------------------------------------------------------------------
--------------------------- RIBS -----------------------------------
--------------------------------------------------------------------
local function VerifyRibsLink( nLinkId, nCurr, nNext, nGrpTmp, dStrand, bCheckLinked)
local dOverlap1 = EgtGetInfo( nCurr, KEY_RIBS_OVERLAP, 'd')
local dOverlap2 = EgtGetInfo( nNext, KEY_RIBS_OVERLAP, 'd')
local dOverlap = max( dOverlap1, dOverlap2)
local dLen = EgtCurveLength( nLinkId)
-- verifico che non entri nella tavola
local b3Box = EgtGetBBoxGlob( nLinkId, GDB_BB.STANDARD)
if b3Box:getMin():getZ() < - GEO.EPS_SMALL then
return false
end
-- eventuale verifica con setti coinvolti dal link
-- verifico non passi per estremo errato
if nCurr ~= nNext then
local dParTest1 = EgtCurveParamAtPoint( nLinkId, EgtSP( nCurr, GDB_ID.ROOT), 100 * GEO.EPS_SMALL, GDB_RT.GLOB)
local dParTest2 = EgtCurveParamAtPoint( nLinkId, EgtEP( nNext, GDB_ID.ROOT), 100 * GEO.EPS_SMALL, GDB_RT.GLOB)
if dParTest1 or dParTest2 then
return false
end
end
if bCheckLinked and dLen > 3 * dStrand then
-- regione occupata dai setti
local nSrfRibs = EgtSurfFrFatCurve( nGrpTmp, nCurr, dStrand, false) or GDB_ID.NULL
local nSrfRibs2 = EgtSurfFrFatCurve( nGrpTmp, nNext, dStrand, false) or GDB_ID.NULL
EgtSurfFrAdd( nSrfRibs, nSrfRibs2)
-- verifico che i tratti fuori abbiano lunghezza maggiore di quelli dentro
local nLinkLoc = EgtCopyGlob( nLinkId, nGrpTmp)
local nRes, nCnt = EgtTrimCurveWithRegion( nLinkLoc, nSrfRibs, false, false)
if nCnt == 0 then return false end
local dResLen = EgtCurveLength( nRes)
if dResLen < ( dLen - dResLen) - GEO.EPS_SMALL then
return false
end
end
-- verifico se interseca altri setti ( considerando anche le tipologie del PathGrp non ancora realizzate)
local nLinkLoc = EgtCopyGlob( nLinkId, nGrpTmp)
local nOrigCurr = EgtGetInfo( nCurr, KEY_ORIGINAL_RIB, 'i')
local nOrigNext = EgtGetInfo( nNext, KEY_ORIGINAL_RIB, 'i')
local vRibsIds = EgtGetNameInGroup( EgtGetParent( nCurr), RIBS_CRV .. '*')
local nCrvGrp = EgtGetParent( EgtGetParent( nCurr))
local nRibsPathGrp = EgtGetFirstNameInGroup( nCrvGrp, RIBS_GRP)
local vRibsPaths = EgtGetNameInGroup( nRibsPathGrp, RIBS_CRV .. '*')
for i = 1, #vRibsPaths do
local nTPath = EgtGetInfo( vRibsPaths[i], KEY_ASSOCIATED_TP_CRV, 'i')
if not nTPath then
table.insert( vRibsIds, vRibsPaths[i])
end
end
for i = 1, #vRibsIds do
if vRibsIds[i] ~= nCurr and vRibsIds[i] ~= nNext then
local dCurrStrand = EgtGetInfo( vRibsIds[i], KEY_RIBS_STRAND, 'd')
local nOrigId = EgtGetInfo( vRibsIds[i], KEY_ORIGINAL_RIB, 'i')
if nOrigId == nOrigCurr or nOrigId == nOrigNext then
-- se passate relative ad un setto coinvolto verifico se sovrapposizione con la curva
local ptS = EgtSP( vRibsIds[i], GDB_ID.ROOT)
local dParS = EgtCurveParamAtPoint( nLinkLoc, ptS, dCurrStrand * 0.5, GDB_RT.GLOB)
if dParS then return false end
local ptE = EgtEP( vRibsIds[i], GDB_ID.ROOT)
local dParE = EgtCurveParamAtPoint( nLinkLoc, ptE, dCurrStrand * 0.5, GDB_RT.GLOB)
if dParE then return false end
else
-- verifico se sovrapposizione con la passata
local dOffs = dCurrStrand * 0.5 + ( 0.5 - dOverlap / 100) * dStrand - 10 * GEO.EPS_SMALL
if dOffs > GEO.EPS_SMALL then
local nSrfCurr = EgtSurfFrFatCurve( nGrpTmp, vRibsIds[i], dOffs, false)
if nSrfCurr then
local nRes = EgtCurveWithRegionClassify( nLinkLoc, nSrfCurr)
if nRes ~= GDB_CRC.OUT then
return false
end
end
end
end
end
end
-- verifico se si trova almeno in una regione ammissibile ( per caso ForcedLink)
local nType = EgtGetInfo( nCurr, KEY_RIBS_TYPE, 'i')
local nOut = 0
for i = 1, 2 do
local nSurfId = EgtGetInfo( EgtIf( i == 1, nCurr, nNext), KEY_ASSOCIATED_SURF, 'i')
if nSurfId and nSurfId ~= -1 then
local nSrfLoc = EgtCopyGlob( nSurfId, nGrpTmp)
local nRes = EgtCurveWithRegionClassify( nLinkId, nSrfLoc)
if ( ( nType == RIB_TYPE.INTERNAL or nType == RIB_TYPE.SUPPORT) and ( nRes == GDB_CRC.OUT or nRes == GDB_CRC.INTERS)) or
( nType == RIB_TYPE.EXTERNAL and ( nRes == GDB_CRC.IN or nRes == GDB_CRC.INTERS)) then
nOut = nOut + 1
end
end
end
local nType1 = EgtGetInfo( nCurr, KEY_RIBS_TYPE, 'i')
local nType2 = EgtGetInfo( nNext, KEY_RIBS_TYPE, 'i')
if nType1 == RIB_TYPE.UNBOUNDED or nType2 == RIB_TYPE.UNBOUNDED then
-- deve essere nella regione ammissibile dell'altro setto
if nOut == 1 then return false end
else
-- deve essere nella regione ammissibile di uno dei due
if nOut == 2 then return false end
end
return true
end
--------------------------------------------------------------------
local function ComputeRibsLinkOnSameCrv( nCrvId, dParS, dParE, nCurr, nNext, nGrpTmp, dStrand, bCheckLinked)
local nParentId = EgtGetParent( nCrvId)
-- verifico il percorso dParS->dParE
local nCopyId = EgtCopyGlob( nCrvId, nParentId, GDB_IN.AFTER)
EgtTrimCurveStartEndAtParam( nCopyId, dParS, dParE)
if VerifyRibsLink( nCopyId, nCurr, nNext, nGrpTmp, dStrand, bCheckLinked) then
return nCopyId
else
-- se non valido tento con il percorso dParE->dParS
EgtErase( nCopyId)
nCopyId = EgtCopyGlob( nCrvId, nParentId, GDB_IN.AFTER)
EgtTrimCurveStartEndAtParam( nCopyId, dParE, dParS)
EgtInvertCurve( nCopyId)
if VerifyRibsLink( nCopyId, nCurr, nNext, nGrpTmp, dStrand, bCheckLinked) then
return nCopyId
else
return
end
end
end
--------------------------------------------------------------------
local function ComputeRibsLinkOnDiffCrvs( nCrvS, nCrvE, dParS, dParE, nCurr, nNext, nGrpTmp, dStrand, bCheckLinked)
local nParentId = EgtGetParent( nCrvS)
local _, _, dParFinal = EgtPointCurveDist( EgtUP( nCrvE, dParE, GDB_ID.ROOT), nCrvS, GDB_ID.ROOT)
local _, _, dParStart = EgtPointCurveDist( EgtUP( nCrvS, dParS, GDB_ID.ROOT), nCrvE, GDB_ID.ROOT)
-- tento con il tratto dParS->dParE
-- recupero il tratto interessato sulla curva1
local nCrv1 = EgtCopyGlob( nCrvS, nParentId, GDB_IN.AFTER)
EgtTrimCurveStartEndAtParam( nCrv1, dParS, dParFinal)
-- recupero il tratto interessato sulla curva2
local nCrv2 = EgtCopyGlob( nCrvE, nParentId, GDB_IN.AFTER)
EgtTrimCurveStartEndAtParam( nCrv2, dParStart, dParE)
-- modifico nCrv2 per avere una transizione uniforme da nCrv1
EgtSpiralizeCurveAlongGuide( nCrv2, nCrv1)
EgtErase( nCrv1)
-- verifico se valida
if VerifyRibsLink( nCrv2, nCurr, nNext, nGrpTmp, dStrand, bCheckLinked) then
return nCrv2
else
-- tento con il tratto dParE->dParS
EgtErase( nCrv2)
nCrv1 = EgtCopyGlob( nCrvS, nParentId, GDB_IN.AFTER) -- tratto interessato sulla curva1
EgtTrimCurveStartEndAtParam( nCrv1, dParFinal, dParS)
EgtInvertCurve( nCrv1)
nCrv2 = EgtCopyGlob( nCrvE, nParentId, GDB_IN.AFTER) -- tratto interessato sulla curva2
EgtTrimCurveStartEndAtParam( nCrv2, dParE, dParStart)
EgtInvertCurve( nCrv2)
EgtSpiralizeCurveAlongGuide( nCrv2, nCrv1) -- transizione uniforme da nCrv1
EgtErase( nCrv1)
if VerifyRibsLink( nCrv2, nCurr, nNext, nGrpTmp, dStrand, bCheckLinked) then
return nCrv2
else
EgtErase( nCrv2)
return
end
end
end
--------------------------------------------------------------------
local function CalcRibsLink( nCurr, nNext, nLoopGrp, bForceLink, bCheckLinked, vtSlicing, nGrpTmp)
local ptS = EgtEP( nCurr)
local ptE = EgtSP( nNext)
if AreSamePointApprox( ptS, ptE) then return end
local dStrand1 = EgtGetInfo( nCurr, KEY_CRV_STRAND, 'd')
local dStrand2 = EgtGetInfo( nNext, KEY_CRV_STRAND, 'd')
local dStrand = max( dStrand1, dStrand2)
local vCrvIds = EgtGetAllInGroup( nLoopGrp)
-- recupero le curve di bordo su cui poggiano i setti e i corrispondenti parametri
local vIdsS, vIdsE = {}, {}
local vParS, vParE = {}, {}
for i = 1, #vCrvIds do
local dParS = EgtCurveParamAtPoint( vCrvIds[i], ptS, 10 * GEO.EPS_SMALL)
if dParS then
table.insert( vIdsS, i)
table.insert( vParS, dParS)
end
local dParE = EgtCurveParamAtPoint( vCrvIds[i], ptE, 10 * GEO.EPS_SMALL)
if dParE then
table.insert( vIdsE, i)
table.insert( vParE, dParE)
end
end
-- verifico se possibile creare link basandosi sulle curve di bordo
for i = 1, #vIdsS do
for j = 1, #vIdsE do
local nLinkId
if vIdsS[i] == vIdsE[j] then
-- link su una sola curva
nLinkId = ComputeRibsLinkOnSameCrv( vCrvIds[vIdsS[i]], vParS[i], vParE[j], nCurr, nNext, nGrpTmp, dStrand, bCheckLinked)
else
-- link tra due curve distinte
nLinkId = ComputeRibsLinkOnDiffCrvs( vCrvIds[vIdsS[i]], vCrvIds[vIdsE[j]], vParS[i], vParE[j], nCurr, nNext, nGrpTmp, dStrand, bCheckLinked)
end
if nLinkId then
EgtRelocateGlob( nLinkId, nCurr, GDB_IN.AFTER)
EgtSetInfo( nLinkId, KEY_TYPE, TYPE.RIB)
EgtSetName( nLinkId, LINK_CRV)
EgtModifyCurveExtrusion( nLinkId, vtSlicing, GDB_RT.GLOB)
EgtSetInfo( nLinkId, KEY_CRV_STRAND, dStrand)
return nLinkId
end
end
end
-- se non ho trovato un collegamento lungo bordi ma link deve esserci creo una linea tra ptS e ptE
if bForceLink then
local nLinkId = EgtCurveCompoFromPoints( EgtGetParent( nCurr), {ptS, ptE})
EgtSetInfo( nLinkId, KEY_TYPE, TYPE.RIB)
EgtSetName( nLinkId, LINK_CRV)
EgtModifyCurveExtrusion( nLinkId, vtSlicing, GDB_RT.GLOB)
EgtRelocateGlob( nLinkId, nCurr, GDB_IN.AFTER)
EgtSetInfo( nLinkId, KEY_CRV_STRAND, dStrand)
local bValid = VerifyRibsLink( nLinkId, nCurr, nNext, nGrpTmp, dStrand, bCheckLinked)
if bValid then
return nLinkId
else
EgtErase( nLinkId)
return
end
end
return
end
--------------------------------------------------------------------
local function CalcLoopRibLink( nCurr, nNext, nLoopGrp, vtSlicing, nGrpTmp)
local ptS = EgtEP( nCurr)
local ptE = EgtSP( nNext)
if AreSamePointApprox( ptS, ptE) then return end
local dStrand = EgtGetInfo( nCurr, KEY_CRV_STRAND, 'd')
local vCrvIds = EgtGetAllInGroup( nLoopGrp)
-- scorro le curve di bordo e verifico se posso creare il link
for i = 1, #vCrvIds do
local dParS = EgtCurveParamAtPoint( vCrvIds[i], ptS, 10 * GEO.EPS_SMALL)
local dParE = EgtCurveParamAtPoint( vCrvIds[i], ptE, 10 * GEO.EPS_SMALL)
if dParS and dParE then
local nLinkId = ComputeShortestCrv( vCrvIds[i], dParS, dParE)
if nLinkId then
EgtRelocateGlob( nLinkId, nCurr, GDB_IN.AFTER)
EgtSetInfo( nLinkId, KEY_TYPE, TYPE.RIB)
EgtSetName( nLinkId, LINK_CRV)
EgtModifyCurveExtrusion( nLinkId, vtSlicing, GDB_RT.GLOB)
EgtSetInfo( nLinkId, KEY_CRV_STRAND, dStrand)
if VerifyRibsLink( nLinkId, nCurr, nNext, nGrpTmp, dStrand, false) then
return nLinkId
else
EgtErase( nLinkId)
end
end
end
end
return
end
--------------------------------------------------------------------
local function VerifyRibsLead( nId, nRibId, bInVsOut, nGrpTmp)
local dStrand = EgtGetInfo( nRibId, KEY_CRV_STRAND, 'd')
local dOverlap = EgtGetInfo( nRibId, KEY_RIBS_OVERLAP, 'd')
local dLen = EgtCurveLength( nId)
-- porto il lead nel gruppo locale
local nLeadLoc = EgtCopyGlob( nId, nGrpTmp)
-- individuo eventuale lead in o link relativo al setto corrente ( solo se collega due passate dello stesso setto)
local nCurrLI
local nCurrLink
if not bInVsOut then
local nPrev = EgtGetPrev( nRibId)
if nPrev and EgtGetName( nPrev) == LEAD_IN_CRV then
nCurrLI = nPrev
elseif nPrev and EgtGetName( nPrev) == LINK_CRV then
local nPrevRib = EgtGetPrev( nPrev)
local nOrigRib = EgtGetInfo( nRibId, KEY_ORIGINAL_RIB, 'i') or -1
local nOrigRibPrev = EgtGetInfo( nPrevRib, KEY_ORIGINAL_RIB, 'i') or -1
if nOrigRib == nOrigRibPrev then
nCurrLink = nPrev
end
end
end
-- verifico se interseca altri setti, lead in, lead out o collegamenti
-- recupero gli id degli elementi da controllare
local vCheckIds = {}
local nCurrId = EgtGetFirstNameInGroup( EgtGetParent( nRibId), RIBS_CRV .. '*')
-- verifico se il primo setto ha lead in da controllare
local nPrevId = EgtGetPrev( nCurrId)
if nPrevId and EgtGetName( nPrevId) == LEAD_IN_CRV then nCurrId = nPrevId end
while nCurrId do
-- salto i i wipe ( non sono materiale depositato) e i tratti relativi al setto corrente
if not EgtStartsWith( EgtGetName( nCurrId), WIPE_CRV) and nCurrId ~= nCurrLI and nCurrId ~= nRibId and nCurrId ~= nId and nCurrId ~= nCurrLink then
table.insert( vCheckIds, nCurrId)
end
nCurrId = EgtGetNext( nCurrId)
end
-- tra gli id da controllare devo aggiungere anche altri setti non ancora presenti nel toolpath ( tipologie di setti realizzate in seguito)
local nCrvGrp = EgtGetParent( EgtGetParent( nRibId))
local nRibsPathGrp = EgtGetFirstNameInGroup( nCrvGrp, RIBS_GRP)
local vRibsPaths = EgtGetNameInGroup( nRibsPathGrp, RIBS_CRV .. '*')
for i = 1, #vRibsPaths do
local nTPath = EgtGetInfo( vRibsPaths[i], KEY_ASSOCIATED_TP_CRV, 'i')
if not nTPath then
table.insert( vCheckIds, vRibsPaths[i])
end
end
-- controllo se intersezione
for i = 1, #vCheckIds do
local dCurrStrand = EgtGetInfo( vCheckIds[i], KEY_CRV_STRAND, 'd') or EgtGetInfo( vCheckIds[i], KEY_RIBS_STRAND, 'd')
local dCurrOffs = dCurrStrand * 0.5 + ( 0.5 - dOverlap / 100) * dStrand - 10 * GEO.EPS_SMALL
if dCurrOffs > GEO.EPS_SMALL then
local nSrfCurr = EgtSurfFrFatCurve( nGrpTmp, vCheckIds[i], dCurrOffs, false)
if nSrfCurr then
local nRes = EgtCurveWithRegionClassify( nLeadLoc, nSrfCurr)
if nRes ~= GDB_CRC.OUT then
return false
end
end
end
end
-- verifiche con il setto corrente
-- verifico non passi da altro estremo
local dParTest = EgtCurveParamAtPoint( nLeadLoc, EgtIf( bInVsOut, EgtEP( nRibId, GDB_ID.ROOT), EgtSP( nRibId, GDB_ID.ROOT)), 100 * GEO.EPS_SMALL, GDB_RT.GLOB)
if dParTest then
return false
end
-- verifico se tratti lineari paralleli al setto sono sufficientemente lontani
local _, dParE = EgtCurveDomain( nLeadLoc)
local nRibLoc = EgtCopyGlob( nRibId, nGrpTmp)
local vtDir = EgtMV( nRibLoc)
local dParCrv = 1
local dTol = 10 * GEO.EPS_SMALL
for dParCrv = 1, dParE do
local vtS = EgtUV( nLeadLoc, dParCrv - 1, 1)
local vtE = EgtUV( nLeadLoc, dParCrv, -1)
local dTol = 10 * GEO.EPS_SMALL
if AreSameVectorApprox( vtS, vtE) and vtS * vtDir < - 1 + GEO.EPS_SMALL then
local dDist = EgtPointCurveDist( EgtUP( nLeadLoc, dParCrv - 0.5), nRibLoc)
EgtCopyGlob( nLeadLoc, nGrpTmp)
if dDist < dStrand + GEO.EPS_SMALL then
return false
end
end
end
-- verifiche con eventuale lead in
if nCurrLI then
local nLeadInLoc = EgtCopyGlob( nCurrLI, nGrpTmp)
-- verifico se intersezione fra curve
local _, nPnt, nCrv = EgtCurveCurveInters( nLeadLoc, nLeadInLoc, nGrpTmp)
if nPnt ~= 0 or nCrv ~= 0 then
return false
end
local dLeadInLen = EgtCurveLength( nLeadInLoc)
if dLeadInLen > dStrand + GEO.EPS_SMALL then
local nSrfLeadIn = EgtSurfFrFatCurve( nGrpTmp, nId, dStrand * ( 1 - dOverlap / 100), false)
if nSrfLeadIn then
-- verifico di avere un solo tratto esterno di lunghezza sufficiente
local nRes, nCnt = EgtTrimCurveWithRegion( nLeadInLoc, nSrfLeadIn, false, false)
if nCnt ~= 1 then
return false
else
local dLen = EgtCurveLength( nRes)
if dLen < dStrand / 2 + GEO.EPS_SMALL then
return false
end
end
end
end
end
return true
end
---------------------------------------------------------------------------------
local function PrepareRibLead( nCrvOffs, nRib, bInvert, bInVsOut, dPar, dLeadLen)
local nLeadId = EgtCopyGlob( nCrvOffs, nRib, EgtIf( bInVsOut, GDB_IN.BEFORE, GDB_IN.AFTER))
EgtChangeClosedCurveStart( nLeadId, dPar)
-- oriento in modo che la curva parta da nRib
if bInvert then
EgtInvertCurve( nLeadId)
end
EgtTrimCurveEndAtLen( nLeadId, dLeadLen)
if bInVsOut then
-- se lead in la curva deve terminare in nRib
EgtInvertCurve( nLeadId)
end
return nLeadId
end
---------------------------------------------------------------------------------
local function FindCorrectRibLead( dPar, nRib, nCrvOffs, bLeadInvert, dLeadLen, bInVsOut, nGrpTmp, bSpecialCase)
local nLeadId
local bInvert = bLeadInvert -- valore di default è quello dei parametri
local bOnlyOneSide = false
local dParE
-- verifico se ho un solo lato possibile per la presenza di altre passate
local nOtherRib
if bSpecialCase then
local sName = EgtGetName( nRib)
local nFirst = EgtGetFirstNameInGroup( EgtGetParent( nRib), sName)
local nLast = EgtGetLastNameInGroup( EgtGetParent( nRib), sName)
if bInVsOut and nRib == nFirst then
nOtherRib = nLast
elseif not bInVsOut and nRib == nLast then
nOtherRib = nFirst
end
else
local nLinkId = EgtIf( bInVsOut, EgtGetNext( nRib), EgtGetPrev( nRib))
if nLinkId and EgtGetName( nLinkId) == LINK_CRV then
nOtherRib = EgtIf( bInVsOut, EgtGetNext( nLinkId), EgtGetPrev( nLinkId))
local nOrigRib1 = EgtGetInfo( nRib, KEY_ORIGINAL_RIB, 'i')
local nOrigRib2 = EgtGetInfo( nOtherRib, KEY_ORIGINAL_RIB, 'i')
if nOrigRib1 ~= nOrigRib2 then
nOtherRib = nil
end
end
end
if nOtherRib then
local ptOther = EgtIf( bInVsOut, EgtEP( nOtherRib, GDB_ID.ROOT), EgtSP( nOtherRib, GDB_ID.ROOT))
dParE = EgtCurveParamAtPoint( nCrvOffs, ptOther, 100 * GEO.EPS_SMALL, GDB_RT.GLOB)
if dParE then
bOnlyOneSide = true
end
end
-- se un solo lato possibile
if bOnlyOneSide then
-- verifico a quale valore di bInvert corrisponde l'unico lato possibile
local nCopyId1 = EgtCopyGlob( nCrvOffs, nGrpTmp)
local nCopyId2 = EgtCopyGlob( nCrvOffs, nGrpTmp)
EgtTrimCurveStartEndAtParam( nCopyId1, dPar, dParE)
EgtTrimCurveStartEndAtParam( nCopyId2, dParE, dPar)
local dLen1 = EgtCurveLength( nCopyId1)
local dLen2 = EgtCurveLength( nCopyId2)
bInvert = dLen1 < dLen2
nLeadId = PrepareRibLead( nCrvOffs, nRib, bInvert, bInVsOut, dPar, dLeadLen)
-- verifico se lead sensato
if not VerifyRibsLead( nLeadId, nRib, bInVsOut, nGrpTmp) then
EgtErase( nLeadId)
return
end
-- se due lati possibili
else
-- primo tentativo nella direzione individuata dal parametro bInvert
nLeadId = PrepareRibLead( nCrvOffs, nRib, bInvert, bInVsOut, dPar, dLeadLen)
if not VerifyRibsLead( nLeadId, nRib, bInVsOut, nGrpTmp) then
-- secondo tentativo nell'altra direzione
EgtErase( nLeadId)
bInvert = not bInvert
nLeadId = PrepareRibLead( nCrvOffs, nRib, bInvert, bInVsOut, dPar, dLeadLen)
if not VerifyRibsLead( nLeadId, nRib, bInVsOut, nGrpTmp) then
EgtErase( nLeadId)
return
end
end
end
return nLeadId, bInvert
end
--------------------------------------------------------------------
local function AddRibsLeadIn( nCrv, nLoopsGrp, vtSlicing, nGrpTmp, bForceNoSolidBorder, bSpecialCase)
local dLILen = EgtGetInfo( nCrv, KEY_RIBS_LEAD_IN_LEN, 'd')
local bLIInvert = EgtGetInfo( nCrv, KEY_RIBS_LEAD_IN_INVERT, 'b')
local dStrand = EgtGetInfo( nCrv, KEY_CRV_STRAND, 'd')
if dLILen < GEO.EPS_SMALL then return end
-- recupero la curva di offset su cui calcolare leadin
local ptS = EgtSP( nCrv)
local vCrvOffs = {}
if bForceNoSolidBorder then
vCrvOffs = EgtGetNameInGroup( nLoopsGrp, SURF_LOOP .. '*') or {}
else
vCrvOffs = EgtGetAllInGroup( nLoopsGrp) or {}
end
for i = 1, #vCrvOffs do
local dParS = EgtCurveParamAtPoint( vCrvOffs[i], ptS)
if dParS then
local nLeadIn = FindCorrectRibLead( dParS, nCrv, vCrvOffs[i], bLIInvert, dLILen, true, nGrpTmp, bSpecialCase)
-- se lead in possibile
if nLeadIn then
EgtModifyCurveExtrusion( nLeadIn, vtSlicing, GDB_RT.GLOB)
EgtSetInfo( nLeadIn, KEY_TYPE, TYPE.RIB)
EgtSetName( nLeadIn, LEAD_IN_CRV)
EgtSetInfo( nLeadIn, KEY_CRV_STRAND, dStrand)
return
end
end
end
end
--------------------------------------------------------------------
local function AddRibsLeadOut( nCrv, nLoopsGrp, vtSlicing, nGrpTmp, bForceNoSolidBorder, bSpecialCase)
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')
local dStrand = EgtGetInfo( nCrv, KEY_CRV_STRAND, 'd')
if abs( dRibsLOLen) < GEO.EPS_SMALL and
abs( dRibsLOCoasting) < GEO.EPS_SMALL and
abs( dRibsLOWipe) < GEO.EPS_SMALL then return end
-- se setto chiuso applico la stessa uscita delle shell
if EgtCurveIsClosed( nCrv) 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 vCrvOffs = {}
if bForceNoSolidBorder then
vCrvOffs = EgtGetNameInGroup( nLoopsGrp, SURF_LOOP .. '*') or {}
else
vCrvOffs = EgtGetAllInGroup( nLoopsGrp) or {}
end
for i = 1, #vCrvOffs do
local dParE = EgtCurveParamAtPoint( vCrvOffs[i], 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 = FindCorrectRibLead( dParE, nCrv, vCrvOffs[i], bRibsLOInvert, dRibsLOLen + dRibsLOCoasting, false, nGrpTmp, bSpecialCase)
if nCrvRef then
-- primo tratto ( segue offset con flusso aperto)
if dRibsLOLen > GEO.EPS_SMALL 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)
EgtSetInfo( nCrvLO, KEY_CRV_STRAND, dStrand)
-- 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'))
EgtSetInfo( nCoasting, KEY_CRV_STRAND, dStrand)
-- 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( EgtGetParent( nCrv), { ptE, ptFinal}, GDB_RT.GLOB)
if nWipe then
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)
EgtSetInfo( nWipe, KEY_CRV_STRAND, 0)
EgtSetColor( nWipe, EgtStdColor('AQUA'))
end
end
return
end
end
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'))
local dStrand = EgtGetInfo( vEntIds[i], KEY_RIBS_STRAND, 'd')
EgtSetInfo( nNewEntId, KEY_CRV_STRAND, dStrand)
EgtSetInfo( nNewEntId, KEY_ASSOCIATED_P_CRV, vEntIds[i])
EgtSetInfo( vEntIds[i], KEY_ASSOCIATED_TP_CRV, nNewEntId)
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.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) and ( EgtGetInfo( tabRibs[i][j+1], 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 and nSplitId1 == nSplitId2)
local bCheckLinkedRibs = not bForceLink and not bUserLink
if ( nOrig1 ~= nOrig2 and bUserLink) or ( nSplitId1 == nSplitId2 and nOrig1 == nOrig2) then
if not bLoopRib then
CalcRibsLink( tabRibs[i][j], tabRibs[i][j + 1], nLoopGrp, bForceLink, bCheckLinkedRibs, LayerParams.vtSlicing, nGrpTmp)
else
local nLinkId = CalcLoopRibLink( tabRibs[i][j], tabRibs[i][j + 1], nLoopGrp, LayerParams.vtSlicing, nGrpTmp)
-- se collegamento congiungo i setti in unico percorso
if 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
end
-- se LoopRib aggiungo collegamento tra primo e ultimo setto del gruppo
if bLoopRib then
local nTotCrv = #tabRibs[i]
local nLinkId = CalcLoopRibLink( tabRibs[i][nTotCrv], tabRibs[i][1], nLoopGrp, 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 usando lo stesso delle shell
local nCrvGrp = EgtGetParent( nTpathGrpId)
local nPathGrp = EgtGetFirstNameInGroup( nCrvGrp, PATH_GRP)
local nFirstShell = EgtGetFirstNameInGroup( nPathGrp, SHELL_CRV .. '*')
if nFirstShell then
-- verifico se già realizzato toolpath corrispondente
local nRefCrv = EgtGetInfo( nFirstShell, KEY_ASSOCIATED_TP_CRV, 'i') or nFirstShell
local ptStart = EgtSP( nFirstShell)
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
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')
local bLoop1 = EgtGetInfo( tabRibs[i][1], KEY_LOOP_RIB, 'b') or false
local bLoop2 = EgtGetInfo( tabRibs[i + 1][1], KEY_LOOP_RIB, 'b') or false
if bLink1 and bLink2 and not bLoop1 and not bLoop2 then
local nCnt = #tabRibs[i]
CalcRibsLink( tabRibs[i][nCnt], tabRibs[i + 1][1], nLoopGrp, false, true, LayerParams.vtSlicing, nGrpTmp)
end
end
-- leadin/leadout
local bForceNoSolidBorder = false
local nType = EgtGetInfo( vEntIds[1], KEY_RIBS_TYPE, 'i')
if nType == RIB_TYPE.UNBOUNDED then
bForceNoSolidBorder = 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 then
AddRibsLeadIn( nCrvRib, nLoopGrp, LayerParams.vtSlicing, nGrpTmp, bForceNoSolidBorder, bSpecialCase)
end
-- verifico se necessario lead out
local nNext = EgtGetNext( nCrvRib)
if not nNext or EgtGetName( nNext) ~= LINK_CRV then
AddRibsLeadOut( nCrvRib, nLoopGrp, LayerParams.vtSlicing, nGrpTmp, bForceNoSolidBorder, bSpecialCase)
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)
EgtSetInfo( nNewEntId, KEY_CRV_STRAND, LayerParams.dStrand)
-- 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
local nLayCnt = 1
-- 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
-- recupero gli elementi da stampare
local vShellIds = EgtGetNameInGroup( nPathGrpId, SHELL_CRV .. '*')
local vExtraShellIds = EgtGetNameInGroup( nPathGrpId, EXTRA_SHELL_CRV .. '*')
local nInfillGrp = EgtGetFirstNameInGroup( nCrvGrpId, INFILL_GRP) or GDB_ID.NULL
local nAuxSolidsGrp = EgtGetFirstNameInGroup( vLayIds[nIdx], AUX_SOLIDS_GRP)
local nAuxSolidsPathGrp = EgtGetFirstNameInGroup( nCrvGrpId, AUX_SOLIDS_GRP)
local nRibsGrp = EgtGetFirstNameInGroup( nCrvGrpId, RIBS_GRP)
-- suddivido i ribs per tipologia
local tRibs = {{}, {}, {}, {}}
local vRibsIds = EgtGetNameInGroup( nRibsGrp, RIBS_CRV .. '*') or {}
for i = 1, #vRibsIds do
local nType = EgtGetInfo( vRibsIds[i], KEY_RIBS_TYPE, 'i') or RIB_TYPE.INTERNAL
table.insert( tRibs[nType], vRibsIds[i])
end
-- eventuale unione delle shell e dei SolidFills
JoinShellsAndSolidFills( nInfillGrp, vShellIds, vExtraShellIds, LayerParams, tRibs)
-- realizzo le diverse tipologie in base all'ordine selezionato
for j = 1, #LayerParams.vPrintOrder do
-- shell
if LayerParams.vPrintOrder[j] == PRINT_ELEMENT.SHELL then
CalcShellsToolPath( vShellIds, nTpathGrpId, LayerParams)
-- extra shell
elseif LayerParams.vPrintOrder[j] == PRINT_ELEMENT.EXTRA_SHELL then
CalcExtraShellToolPath( vExtraShellIds, nTpathGrpId, LayerParams)
-- infill
elseif LayerParams.vPrintOrder[j] == PRINT_ELEMENT.INFILL then
local nFillType = EgtGetInfo( nInfillGrp, KEY_FILL_TYPE, 'i') or FILL_TYPE.NONE
if nFillType & FILL_CATEGORY.SOLID_FILL ~= 0 then
CalcSolidFillToolPath( nInfillGrp, nTpathGrpId, LayerParams)
else
CalcInfillToolPath( nInfillGrp, nTpathGrpId, LayerParams)
end
-- solidi ausiliari
elseif LayerParams.vPrintOrder[j] == PRINT_ELEMENT.AUX_SOLID then
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)
-- verifico non sia vuoto per aggiornare il numero di layers
if EgtGetFirstInGroup( nTpathGrpId) then
nLayCnt = nIdx
end
-- 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)
-- setto info con numero di layers effettivi
EgtSetInfo( nPartId, KEY_LAYER_CNT, nLayCnt)
return true
end
---------------------------------------------------------------------
return CalcToolPath