31be25313a
- corretto errore calcolo lead in nel caso di primi layers mancanti.
3150 lines
139 KiB
Lua
3150 lines
139 KiB
Lua
-- CalcToolPath.lua by Egaltech s.r.l. 2026/02/16
|
|
-- 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_dApproxTol = 0.1
|
|
local s_dHSafeWipe = 2
|
|
local s_nCurrIdx
|
|
local s_dSpiralVaseMaxLen = 10 -- lunghezza massima dei tratti per calcolo SpiralizeAlongGuide
|
|
local s_dSpralVaseFirstDelta = 30 -- lunghezza del tratto sul primo layer che va alzato nella modalità SpiralVaseFull
|
|
|
|
---------------------------------------------------------------------
|
|
local function GetLayerParamsForToolPathCalc()
|
|
local LayerParams = {}
|
|
LayerParams.bSpiralVase = EgtGetInfo( s_nPartId, KEY_SPIRAL_VASE, 'b') or false
|
|
LayerParams.dSpiralVaseLen = EgtGetInfo( s_nPartId, KEY_SPIRAL_VASE_LEN, 'd') or 0
|
|
LayerParams.dStrand = EgtGetInfo( s_nPartId, KEY_STRAND, 'd')
|
|
LayerParams.dInnerStrand = EgtGetInfo( s_nPartId, KEY_INNER_STRAND, 'd') or LayerParams.dStrand
|
|
if LayerParams.dInnerStrand < GEO.EPS_SMALL then LayerParams.dInnerStrand = LayerParams.dStrand end
|
|
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.bSingleLeadIn = EgtGetInfo( s_nPartId, KEY_SINGLE_LEAD_IN, 'b') or false
|
|
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_SLICE_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
|
|
if LayerParams.dInfillStrand < GEO.EPS_SMALL then LayerParams.dInfillStrand = LayerParams.dStrand end
|
|
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
|
|
|
|
-- parametri dal file macchina per eventuale approssimazione lineare dei percorsi
|
|
local sMachIni = EgtGetCurrMachineDir() .. '\\' .. EgtGetCurrMachineName() .. '.ini'
|
|
LayerParams.bLinearApprox = ( EgtGetNumberFromIni( SEC_3DPRINTING, KEY_LINEAR_APPROX, 0, sMachIni) == 1)
|
|
LayerParams.dLinearApproxTol = EgtGetNumberFromIni( SEC_3DPRINTING, KEY_LINEAR_TOL, 0.1, sMachIni)
|
|
|
|
-- parametri da file ini del programma
|
|
local sIniFile = EgtGetIniFile()
|
|
LayerParams.dSpiralVaseInterpLen = EgtGetNumberFromIni( '3dPrinting', KEY_SPIRAL_VASE_INTERP_LEN, 100.0, sIniFile)
|
|
|
|
return LayerParams
|
|
end
|
|
|
|
------------------------------------------------------------------
|
|
local function ComputeToolPathBox( nLayerId)
|
|
-- calcolo il box di tutti i toolpath del layer escludendo i wipe
|
|
local b3Box = BBox3d()
|
|
local vCrvGrpIds = EgtGetNameInGroup( nLayerId, CONTOUR_GRP .. '*')
|
|
for i = 1, #vCrvGrpIds do
|
|
-- recupero tutti gli elementi del toolpath
|
|
local nTPathGrpId = EgtGetFirstNameInGroup( vCrvGrpIds[i], TOOLPATH_GRP)
|
|
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
|
|
end
|
|
return b3Box
|
|
end
|
|
|
|
------------------------------------------------------------------
|
|
local function AddZCorrection( LayerParams)
|
|
|
|
local vLayIds = EgtGetNameInGroup( s_nPartId, SLICE_LAYER.."*")
|
|
local nSlicingType = EgtGetInfo( s_nPartId, KEY_SLICING_TYPE, 'i')
|
|
|
|
-- 1) correzione per il pezzo
|
|
local dHBox = EgtGetInfo( s_nPartId, KEY_BOX_MIN_Z, 'd') or 0
|
|
local dCorrZ = 0
|
|
|
|
-- se slicing multiplanare vtSlicing cambia ad ogni layer quindi la correzione deve essere calcolata sul singolo layer
|
|
if nSlicingType == SLICING_TYPE.MULTIPLANAR or nSlicingType == SLICING_TYPE.MULTIPLANAR_DEG45 or nSlicingType == SLICING_TYPE.MULTIPLANAR_HOR then
|
|
|
|
for i = 1, #vLayIds do
|
|
-- calcolo i valori legati a vtSlicing per il layer corrente
|
|
local vtSlicing = EgtGetInfo( vLayIds[i], KEY_SLICE_DIR, 'v')
|
|
local dNxy = sqrt( vtSlicing:getX() * vtSlicing:getX() + vtSlicing:getY() * vtSlicing:getY())
|
|
local dNz = vtSlicing:getZ()
|
|
local b3Layer = ComputeToolPathBox( vLayIds[i])
|
|
if not b3Layer:isEmpty() then
|
|
-- altezza necessaria per lo strand
|
|
local dHStrand = 0
|
|
-- nel caso multiplanar con partenza verticale l'altezza necessaria per lo strand non serve perchè l'altezza viene adattata lungo il percorso
|
|
if nSlicingType == SLICING_TYPE.MULTIPLANAR_DEG45 then
|
|
-- nel caso multiplanar 45° si considera come altezza strand quella settata nei parametri visto che varia lungo il percorso ( euristico)
|
|
dHStrand = 0.5 * LayerParams.dStrand * dNxy + LayerParams.dLayHeight * dNz
|
|
elseif nSlicingType == SLICING_TYPE.MULTIPLANAR_HOR then
|
|
dHStrand = 0.5 * LayerParams.dStrand
|
|
end
|
|
-- altezza necessaria per il tool
|
|
local dHTool = LayerParams.dTDiam / 2 * dNxy
|
|
-- altezza disponibile
|
|
local dHDisp = b3Layer:getMin():getZ() - max( dHBox, 0)
|
|
local dCurrCorrZ = max( 0, max( dHStrand, dHTool) - dHDisp)
|
|
dCorrZ = max( dCorrZ, dCurrCorrZ)
|
|
end
|
|
end
|
|
|
|
-- se slicing standard la correzione può essere calcolata sull'intero pezzo
|
|
else
|
|
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
|
|
-- calcolo il box complessivo dei percorsi
|
|
local b3Tot = BBox3d()
|
|
for i = 1, #vLayIds do
|
|
local b3Curr = ComputeToolPathBox( vLayIds[i])
|
|
b3Tot:Add( b3Curr)
|
|
end
|
|
local dHDisp = b3Tot:getMin():getZ() - max( dHBox, 0)
|
|
|
|
dCorrZ = max( 0, max( dHStrand, dHTool) - dHDisp)
|
|
end
|
|
|
|
-- applico la correzione al pezzo
|
|
if dCorrZ > GEO.EPS_SMALL then
|
|
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
|
|
|
|
-- 2) correzione per i wipe
|
|
-- altezza minima necessaria per i wipe. Se slicing multiplanare l'altezza minima per il wipe cambia ad ogni layer, altrimenti è un valore comune
|
|
local dHMinWipe
|
|
if nSlicingType ~= SLICING_TYPE.MULTIPLANAR and nSlicingType ~= SLICING_TYPE.MULTIPLANAR_DEG45 and nSlicingType ~= SLICING_TYPE.MULTIPLANAR_HOR then
|
|
local dNxy = sqrt( LayerParams.vtSlicing:getX() * LayerParams.vtSlicing:getX() + LayerParams.vtSlicing:getY() * LayerParams.vtSlicing:getY())
|
|
dHMinWipe = LayerParams.dTDiam / 2 * dNxy + max( dHBox, 0) + s_dHSafeWipe
|
|
end
|
|
|
|
for i = 1, #vLayIds do
|
|
if nSlicingType == SLICING_TYPE.MULTIPLANAR or nSlicingType == SLICING_TYPE.MULTIPLANAR_DEG45 or nSlicingType == SLICING_TYPE.MULTIPLANAR_HOR then
|
|
local vtSlicing = EgtGetInfo( vLayIds[i], KEY_SLICE_DIR, 'v')
|
|
local dNxy = sqrt( vtSlicing:getX() * vtSlicing:getX() + vtSlicing:getY() * vtSlicing:getY())
|
|
dHMinWipe = LayerParams.dTDiam / 2 * dNxy + max( dHBox, 0) + s_dHSafeWipe
|
|
end
|
|
|
|
local vCrvGrps = EgtGetNameInGroup( vLayIds[i], CONTOUR_GRP.."*")
|
|
for j = 1, #vCrvGrps do
|
|
local nTPath = EgtGetFirstNameInGroup( vCrvGrps[j], TOOLPATH_GRP)
|
|
if nTPath then
|
|
local vIds = EgtGetAllInGroup( nTPath)
|
|
for k = 1, #vIds do
|
|
-- se wipe verifico se ha lunghezza sensata per non finire nella tavola
|
|
if EgtGetInfo( vIds[k], KEY_TYPE, 'i') == TYPE.WIPE then
|
|
-- da controllare solo se non segue l'andamento di una curva chiusa
|
|
local bOnCurve = EgtGetInfo( vIds[k], KEY_WIPE_ON_CRV, 'b') or false
|
|
if not bOnCurve then
|
|
local dLen = EgtCurveLength( vIds[k])
|
|
local vtDir = EgtSV( vIds[k], GDB_ID.ROOT)
|
|
local ptE = EgtEP( vIds[k], GDB_ID.ROOT)
|
|
if ptE:getZ() < dHMinWipe then
|
|
-- modifico la lunghezza per non finire nella tavola
|
|
local dDiffLen = abs( ( dHMinWipe - ptE:getZ()) / vtDir:getZ())
|
|
if dDiffLen > dLen - GEO.EPS_SMALL then
|
|
-- l'intero tratto di wipe va eliminato
|
|
EgtErase( vIds[k])
|
|
EgtOutLog( 'Warning : wipe was removed due to wrong direction (layer '..tostring( i)..') - CalcToolPath')
|
|
else
|
|
EgtTrimCurveEndAtLen( vIds[k], dLen - dDiffLen)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
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
|
|
|
|
-- approssimo la curva e ne risetto il punto iniziale
|
|
local ptS = EgtSP( vIds[nIdx], GDB_ID.ROOT)
|
|
EgtApproxCurve( vIds[nIdx], GDB_CA.ARCS, s_dApproxTol)
|
|
if EgtCurveIsClosed( vIds[nIdx]) then
|
|
EgtChangeClosedCurveStartPoint( vIds[nIdx], ptS, GDB_RT.GLOB)
|
|
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
|
|
|
|
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)
|
|
EgtSetColor( nLeadInCrv, EgtStdColor('GRAY'))
|
|
local dStrand = EgtGetInfo( nCrvId, KEY_CRV_STRAND, 'd')
|
|
EgtSetInfo( nLeadInCrv, KEY_CRV_STRAND, dStrand)
|
|
end
|
|
|
|
return nLeadInCrv
|
|
end
|
|
|
|
--------------------------------------------------------------------
|
|
local function AddLeadOut( nCrvId, LayerParams, nGrpId)
|
|
|
|
local vtSlicing = EgtCurveExtrusion( nCrvId, GDB_ID.ROOT)
|
|
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( 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, vtSlicing, GDB_RT.GLOB)
|
|
EgtSetInfo( nLeadOutCrv, KEY_TYPE, TYPE.LINK)
|
|
EgtSetName( nLeadOutCrv, LEAD_OUT_CRV)
|
|
EgtSetColor( nLeadOutCrv, EgtStdColor('GRAY'))
|
|
local dStrand = EgtGetInfo( nCrvId, KEY_CRV_STRAND, 'd')
|
|
EgtSetInfo( nLeadOutCrv, KEY_CRV_STRAND, dStrand)
|
|
end
|
|
return nLeadOutCrv
|
|
end
|
|
|
|
--------------------------------------------------------------------
|
|
local function AddRetraction( nCrvId, dCoastingLen, dWipeLen, dWipeDir)
|
|
|
|
-- recupero i parametri per retrazione
|
|
local vtSlicing = EgtCurveExtrusion( nCrvId, GDB_ID.ROOT)
|
|
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
|
|
local dStrand = EgtGetInfo( nCrvId, KEY_CRV_STRAND, 'd')
|
|
|
|
-- curva ausiliaria per generare correttamente wipe
|
|
local nCopyId = EgtCopyGlob( nCrvId, nCrvId, GDB_IN.AFTER)
|
|
if not EgtCurveIsClosed( nCopyId) and EgtCurveIsFlat( nCopyId) then
|
|
local ptNewStart = EgtEP( nCopyId, GDB_ID.ROOT)
|
|
-- mi posiziono in un frame locale per fare i conti
|
|
local nGrp = EgtGroup( EgtGetParent( nCrvId), Frame3d( ORIG(), vtSlicing), GDB_RT.GLOB)
|
|
EgtRelocateGlob( nCopyId, nGrp)
|
|
local nInters = EgtCurveSelfIntersCount( nCopyId)
|
|
local nCrvCnt
|
|
if nInters > 0 then
|
|
-- caso con sovrapposizione
|
|
nCopyId, nCrvCnt = EgtSplitCurveAtSelfInters( nCopyId)
|
|
for nIdx = 1, nCrvCnt - 2 do
|
|
EgtAddCurveCompoCurve( nCopyId, nCopyId + nIdx)
|
|
end
|
|
if nCrvCnt > 1 then
|
|
EgtErase( nCopyId + nCrvCnt - 1)
|
|
end
|
|
end
|
|
EgtCloseCurveCompo( nCopyId)
|
|
EgtChangeClosedCurveStartPoint( nCopyId, ptNewStart, GDB_RT.GLOB)
|
|
EgtRelocateGlob( nCopyId, nCrvId, GDB_IN.AFTER)
|
|
EgtErase( nGrp)
|
|
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)
|
|
EgtSetInfo( nWipeId, KEY_WIPE_ON_CRV, true)
|
|
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 = ptS + vtDir * dWipeLen
|
|
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, dStrand)
|
|
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, 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, dNewCoastingLen, dWipeLen, dWipeDir)
|
|
else
|
|
-- coinvolge parte dell'ultima shell crv
|
|
local dNewCoastingLen = dCoastingLen - dLen
|
|
local nCoastingId = AddRetraction( nCrvId, dNewCoastingLen, 0.0, dWipeDir)
|
|
EgtAddCurveCompoCurve( nCoastingId, nLeadOutId)
|
|
EgtSetInfo( nCoastingId, KEY_CLOSED_CRV, 0)
|
|
-- wipe
|
|
AddRetraction( nCoastingId, 0, dWipeLen, dWipeDir)
|
|
end
|
|
end
|
|
end
|
|
|
|
---------------------------------------------------------------------
|
|
local function CalcShellsToolPath( vEntIds, nTpathGrpId, bFirst, LayerParams)
|
|
|
|
if not vEntIds or #vEntIds == 0 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
|
|
if bFirst or not LayerParams.bSingleLeadIn then
|
|
AddLeadIn( vIds[1], LayerParams, nTpathGrpId)
|
|
end
|
|
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.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 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
|
|
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], 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.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.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 and #vShellIds > 0 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 #vExtraShells > 0 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 and #vEntIds > 0 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], 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 AddFillet( nCrv1, nCrv2, dFillet, vtSlicing)
|
|
|
|
if dFillet < GEO.EPS_SMALL then
|
|
return
|
|
end
|
|
|
|
local nRefPosId = EgtGetPrev( nCrv1)
|
|
local nRefGrpId = EgtGetParent( nCrv1)
|
|
local vsInfo1 = EgtGetAllInfo( nCrv1)
|
|
local vsInfo2 = EgtGetAllInfo( nCrv2)
|
|
|
|
-- creo un gruppo con riferimento locale allo slicing per i conti del fillet
|
|
local nGrpTmp = EgtGroup( EgtGetParent( nCrv1), Frame3d( ORIG(), vtSlicing), GDB_RT.GLOB)
|
|
|
|
-- creo il fillet
|
|
local dParRef1 = EgtCurveParamAtLength( nCrv1, EgtCurveLength( nCrv1) - 100 * GEO.EPS_SMALL)
|
|
local dParRef2 = EgtCurveParamAtLength( nCrv2, 100 * GEO.EPS_SMALL)
|
|
local nFillet = EgtCurveFillet( nGrpTmp, nCrv1, EgtUP( nCrv1, dParRef1, nGrpTmp), nCrv2, EgtUP( nCrv2, dParRef2, nGrpTmp), dFillet, true, GDB_RT.LOC)
|
|
if not nFillet then
|
|
-- ritento con valore di fillet leggermente inferiore
|
|
nFillet = EgtCurveFillet( nGrpTmp, nCrv1, EgtUP( nCrv1, dParRef1, nGrpTmp), nCrv2, EgtUP( nCrv2, dParRef2, nGrpTmp), dFillet - 50 * GEO.EPS_SMALL, true, GDB_RT.LOC)
|
|
end
|
|
|
|
-- spezzo a metà il fillet per assegnarlo alle due curve
|
|
if nFillet then
|
|
|
|
local nNewFillet = EgtSplitCurve( nFillet, 2)
|
|
|
|
-- aggiungo a nCrv1
|
|
if EgtExistsObj( nCrv1) then
|
|
EgtAddCurveCompoArcTg( nCrv1, EgtEP( nNewFillet, GDB_ID.ROOT), true, GDB_RT.GLOB)
|
|
EgtErase( nNewFillet)
|
|
else
|
|
-- nCrv1 viene sostituita completamente dal fillet
|
|
local nNewCrv = EgtCurveCompo( nRefGrpId, {nNewFillet})
|
|
-- riposiziono dopo il precedente di nCrv1 ( se esiste) oppure in testa al gruppo
|
|
if nRefPosId ~= GDB_ID.NULL then
|
|
EgtRelocateGlob( nNewFillet, nRefPosId, GDB_IN.AFTER)
|
|
else
|
|
EgtRelocateGlob( nNewFillet, nRefGrpId, GDB_IN.FIRST_SON)
|
|
end
|
|
-- modifico l'id per conservare quello di nCrv1
|
|
EgtChangeId( nNewCrv, nCrv1)
|
|
-- riassegno le info
|
|
for i = 1, #vsInfo1 do
|
|
local vsInfo = EgtSplitString( vsInfo1[i], '=')
|
|
EgtSetInfo( nCrv1, vsInfo[1], vsInfo[2])
|
|
end
|
|
end
|
|
|
|
-- aggiungo a nCrv2
|
|
if EgtExistsObj( nCrv2) then
|
|
EgtAddCurveCompoArcTg( nCrv2, EgtSP( nNewFillet + 1, GDB_ID.ROOT), false, GDB_RT.GLOB)
|
|
EgtErase( nNewFillet + 1)
|
|
else
|
|
-- nCrv2 viene sostituita completamente dal fillet
|
|
local nNewCrv = EgtCurveCompo( nRefGrpId, {nNewFillet + 1})
|
|
EgtRelocateGlob( nNewCrv, nCrv1, GDB_IN.AFTER)
|
|
EgtChangeId( nNewCrv, nCrv2)
|
|
for i = 1, #vsInfo2 do
|
|
local vsInfo = EgtSplitString( vsInfo2[i], '=')
|
|
EgtSetInfo( nCrv2, vsInfo[1], vsInfo[2])
|
|
end
|
|
end
|
|
else
|
|
EgtOutLog( 'Warning : ribs fillet not possible (layer '..tostring( s_nCurrIdx)..') - CalcToolPath')
|
|
end
|
|
|
|
EgtErase( nGrpTmp)
|
|
end
|
|
|
|
--------------------------------------------------------------------
|
|
local function VerifyRibsLink( nLinkId, nCurr, nNext, nGrpTmp, dStrand)
|
|
|
|
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)
|
|
|
|
-- 1) verifico che non entri nella tavola
|
|
local b3Box = EgtGetBBoxGlob( nLinkId, GDB_BB.STANDARD)
|
|
if b3Box:getMin():getZ() < - GEO.EPS_SMALL then
|
|
return false
|
|
end
|
|
|
|
-- 2) verifica con setti coinvolti dal link
|
|
if nCurr ~= nNext then
|
|
-- verifico non passi per estremo errato
|
|
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
|
|
|
|
-- verifico non intersechi i setti in altri punti oltre agli estremi
|
|
local nCurrLoc = EgtCopyGlob( nCurr, nGrpTmp)
|
|
local nNextLoc = EgtCopyGlob( nNext, nGrpTmp)
|
|
local nLinkLoc = EgtCopyGlob( nLinkId, nGrpTmp)
|
|
EgtTrimCurveEndAtLen( nLinkLoc, EgtCurveLength( nLinkLoc) - 100 * GEO.EPS_SMALL)
|
|
EgtTrimCurveStartAtLen( nLinkLoc, 100 * GEO.EPS_SMALL)
|
|
if EgtIP( nLinkLoc, nCurrLoc, ORIG()) or EgtIP( nLinkLoc, nNextLoc, ORIG()) then
|
|
return false
|
|
end
|
|
|
|
-- se collegamento non ottimale verifico che abbia una parte esterna alla regione occupata dai setti abbsatanza lunga ( > 20% della lunghezza totale)
|
|
if dist( EgtEP( nCurr, GDB_ID.ROOT), EgtSP( nNext, GDB_ID.ROOT)) > dist( EgtEP( nCurr, GDB_ID.ROOT), EgtEP( nNext, GDB_ID.ROOT)) + 1000 * GEO.EPS_SMALL then
|
|
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)
|
|
-- EgtSetStatus( nSrfRibs, GDB_ST.OFF)
|
|
-- EgtSetStatus( nSrfRibs2, GDB_ST.OFF)
|
|
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 < 0.2 * dLen - GEO.EPS_SMALL then
|
|
return false
|
|
end
|
|
end
|
|
end
|
|
|
|
-- 3) verifiche con 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
|
|
-- verifico se sovrapposizione tra le passate
|
|
local dCurrStrand = EgtGetInfo( vRibsIds[i], KEY_RIBS_STRAND, 'd')
|
|
local nOrigId = EgtGetInfo( vRibsIds[i], KEY_ORIGINAL_RIB, 'i')
|
|
local dOffs
|
|
if nOrigId == nOrigCurr or nOrigId == nOrigNext then
|
|
-- se passata relativa ad un setto coinvolto nel link verifico soltanto che il percorso del link non entri nella regione occupata dal setto
|
|
local dStrandOverlap = EgtGetInfo( vRibsIds[i], KEY_RIBS_STRAND_OVERLAP, 'd')
|
|
dOffs = dCurrStrand * ( 0.5 - dStrandOverlap / 100)
|
|
else
|
|
-- altrimenti verifico che le regioni del link e del setto non si sovrappongono ( a meno dell'overlap fissato)
|
|
dOffs = dCurrStrand * 0.5 + ( 0.5 - dOverlap / 100) * dStrand - 50 * GEO.EPS_SMALL
|
|
end
|
|
|
|
if dOffs > GEO.EPS_SMALL then
|
|
local nSrfCurr = EgtSurfFrFatCurve( nGrpTmp, vRibsIds[i], dOffs, false)
|
|
if nSrfCurr then
|
|
-- EgtSetStatus( nSrfCurr, GDB_ST.OFF)
|
|
local nRes = EgtCurveWithRegionClassify( nLinkLoc, nSrfCurr)
|
|
if nRes ~= GDB_CRC.OUT then
|
|
return false
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
-- 4) verifico se si trova in almeno 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)
|
|
-- EgtSetStatus( nSrfLoc, GDB_ST.OFF)
|
|
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)
|
|
|
|
local nParentId = EgtGetParent( nCrvId)
|
|
|
|
local nShortest = EgtCopyGlob( nCrvId, nParentId, GDB_IN.AFTER)
|
|
local nLongest = EgtCopyGlob( nCrvId, nParentId, GDB_IN.AFTER)
|
|
EgtTrimCurveStartEndAtParam( nShortest, dParS, dParE)
|
|
EgtTrimCurveStartEndAtParam( nLongest, dParE, dParS)
|
|
EgtInvertCurve( nLongest)
|
|
if EgtCurveLength( nShortest) > EgtCurveLength( nLongest) + GEO.EPS_SMALL then
|
|
nShortest, nLongest = nLongest, nShortest
|
|
end
|
|
|
|
-- verifico il percorso più corto
|
|
if VerifyRibsLink( nShortest, nCurr, nNext, nGrpTmp, dStrand) then
|
|
EgtErase( nLongest)
|
|
return nShortest
|
|
else
|
|
-- se non valido tento con il percorso più lungo
|
|
EgtErase( nShortest)
|
|
if VerifyRibsLink( nLongest, nCurr, nNext, nGrpTmp, dStrand) then
|
|
return nLongest
|
|
else
|
|
EgtErase( nLongest)
|
|
return
|
|
end
|
|
end
|
|
end
|
|
|
|
--------------------------------------------------------------------
|
|
local function ComputeRibsLinkOnDiffCrvs( nCrvS, nCrvE, dParS, dParE, nCurr, nNext, nGrpTmp, dStrand)
|
|
|
|
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) 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) then
|
|
return nCrv2
|
|
else
|
|
EgtErase( nCrv2)
|
|
return
|
|
end
|
|
end
|
|
end
|
|
|
|
--------------------------------------------------------------------
|
|
local function CalcRibsLink( nCurr, nNext, nLoopGrp, bForceLink, 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 dFillet1 = EgtGetInfo( nCurr, KEY_RIBS_LINK_FILLET, 'd')
|
|
local dFillet2 = EgtGetInfo( nNext, KEY_RIBS_LINK_FILLET, 'd')
|
|
if bForceLink then
|
|
local dStrandOverlap1 = EgtGetInfo( nCurr, KEY_RIBS_STRAND_OVERLAP, 'd')
|
|
local dStrandOverlap2 = EgtGetInfo( nNext, KEY_RIBS_STRAND_OVERLAP, 'd')
|
|
dFillet1 = min( dFillet1, ( 1 - dStrandOverlap1 / 100) * dStrand1 * 0.5)
|
|
dFillet2 = min( dFillet2, ( 1 - dStrandOverlap2 / 100) * dStrand2 * 0.5)
|
|
end
|
|
|
|
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)
|
|
else
|
|
-- link tra due curve distinte
|
|
nLinkId = ComputeRibsLinkOnDiffCrvs( vCrvIds[vIdsS[i]], vCrvIds[vIdsE[j]], vParS[i], vParE[j], nCurr, nNext, nGrpTmp, dStrand)
|
|
end
|
|
|
|
if nLinkId then
|
|
-- fillet
|
|
AddFillet( nCurr, nLinkId, dFillet1, vtSlicing)
|
|
AddFillet( nLinkId, nNext, dFillet2, vtSlicing)
|
|
-- assegno le info
|
|
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})
|
|
-- assegno le info
|
|
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)
|
|
if bValid then
|
|
-- fillet
|
|
AddFillet( nCurr, nLinkId, dFillet1, vtSlicing)
|
|
AddFillet( nLinkId, nNext, dFillet2, vtSlicing)
|
|
return nLinkId
|
|
else
|
|
EgtErase( nLinkId)
|
|
return
|
|
end
|
|
end
|
|
|
|
return
|
|
end
|
|
|
|
--------------------------------------------------------------------
|
|
local function CalcLoopRibLink( nCurr, nNext, nLoopGrp, vtSlicing, nGrpTmp, bForceLink)
|
|
|
|
local ptS = EgtEP( nCurr)
|
|
local ptE = EgtSP( nNext)
|
|
if AreSamePointApprox( ptS, ptE) then return end
|
|
local dStrand = EgtGetInfo( nCurr, KEY_CRV_STRAND, 'd')
|
|
local dFillet = EgtGetInfo( nCurr, KEY_RIBS_LINK_FILLET, '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) then
|
|
-- fillet
|
|
if bForceLink then
|
|
dFillet = min( dFillet, dStrand * 0.5)
|
|
end
|
|
AddFillet( nCurr, nLinkId, dFillet, vtSlicing)
|
|
AddFillet( nLinkId, nNext, dFillet, vtSlicing)
|
|
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 dShellOverlap = EgtGetInfo( nRibId, KEY_RIBS_OVERLAP, 'd')
|
|
local dStrandOverlap = EgtGetInfo( nRibId, KEY_RIBS_STRAND_OVERLAP, 'd')
|
|
local dOverlap = max( dShellOverlap, dStrandOverlap)
|
|
local nOrigRib = EgtGetInfo( nRibId, KEY_ORIGINAL_RIB, 'i')
|
|
local dLen = EgtCurveLength( nId)
|
|
local nParentId = EgtGetParent( nId)
|
|
|
|
-- porto il lead nel gruppo locale
|
|
EgtRelocateGlob( nId, nGrpTmp)
|
|
|
|
-- 1) verifico se interseca altri setti, lead in, lead out o collegamenti
|
|
-- recupero gli id degli elementi da controllare
|
|
local vCheckIds = {}
|
|
local nCurrId = EgtGetFirstInGroup( EgtGetParent( nRibId))
|
|
while nCurrId do
|
|
if nCurrId ~= nRibId and nCurrId ~= nId then
|
|
-- considero solo i setti e gli elementi a loro associati ( tranne i wipe perchè non corrispondono a materiale depositato)
|
|
local nType = EgtGetInfo( nCurrId, KEY_TYPE, 'i')
|
|
if nType == TYPE.RIB or ( nType == TYPE.COASTING and EgtGetInfo( EgtGetPrev( nCurrId), KEY_TYPE, 'i') == TYPE.RIB) then
|
|
-- controllo che non sia un elemento relativo ad un'altra passata del setto corrente
|
|
if EgtGetName( nCurrId) == LEAD_IN_CRV then
|
|
-- il setto di riferimento è l'elemento successivo
|
|
local nCurrOrigRib = EgtGetInfo( EgtGetNext( nCurrId), KEY_ORIGINAL_RIB, 'i') or -1
|
|
if nOrigRib ~= nCurrOrigRib then
|
|
table.insert( vCheckIds, nCurrId)
|
|
end
|
|
elseif EgtGetName( nCurrId) == LINK_CRV then
|
|
-- il link va controllato se non congiunge due passate del setto corrente
|
|
local nOrigRib1 = EgtGetInfo( EgtGetPrev( nCurrId), KEY_ORIGINAL_RIB, 'i') or -1
|
|
local nOrigRib2 = EgtGetInfo( EgtGetNext( nCurrId), KEY_ORIGINAL_RIB, 'i') or -1
|
|
if nOrigRib ~= nOrigRib1 or nOrigRib ~= nOrigRib2 then
|
|
table.insert( vCheckIds, nCurrId)
|
|
end
|
|
else
|
|
local nRibType = EgtGetInfo( nCurrId, KEY_RIBS_TYPE, 'i')
|
|
if nRibType ~= RIB_TYPE.UNBOUNDED then
|
|
local nCurrOrigRib = EgtGetInfo( nCurrId, KEY_ORIGINAL_RIB, 'i')
|
|
if nOrigRib ~= nCurrOrigRib then
|
|
table.insert( vCheckIds, nCurrId)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
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
|
|
|
|
-- creo la superficie occupata dagli id da controllare
|
|
local nSrf
|
|
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 - 50 * GEO.EPS_SMALL
|
|
if dCurrOffs > GEO.EPS_SMALL then
|
|
local nSrfCurr = EgtSurfFrFatCurve( nGrpTmp, vCheckIds[i], dCurrOffs, false)
|
|
if not nSrf then
|
|
nSrf = nSrfCurr
|
|
else
|
|
EgtSurfFrAdd( nSrf, nSrfCurr)
|
|
end
|
|
end
|
|
end
|
|
|
|
-- verifico di avere un tratto esterno consecutivo al setto
|
|
if nSrf then
|
|
local nOrigLead = EgtCopyGlob( nId, nGrpTmp)
|
|
local nRes, nCnt = EgtTrimCurveWithRegion( nId, nSrf, false, false)
|
|
if not nRes or nCnt == 0 then
|
|
return false
|
|
end
|
|
-- la curva di interesse è la prima se lead out o l'ultima se lead in
|
|
local nNewCrv = EgtIf( bInVsOut, nRes + nCnt - 1, nRes)
|
|
local ptRes = EgtIf( bInVsOut, EgtEP( nNewCrv, GDB_ID.ROOT), EgtSP( nNewCrv, GDB_ID.ROOT))
|
|
local ptRib = EgtIf( bInVsOut, EgtSP( nRibId, GDB_ID.ROOT), EgtEP( nRibId, GDB_ID.ROOT))
|
|
if not AreSamePointApprox( ptRes, ptRib) then
|
|
return false
|
|
end
|
|
EgtChangeId( nNewCrv, nId)
|
|
end
|
|
|
|
-- 2) verifiche con il setto corrente
|
|
-- verifico non passi da altro estremo
|
|
local dParTest = EgtCurveParamAtPoint( nId, 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 interrompere in corrispondenza di tratti lineari paralleli al setto che non sono sufficientemente lontani
|
|
local _, dParE = EgtCurveDomain( nId)
|
|
local nRibLoc = EgtCopyGlob( nRibId, nGrpTmp)
|
|
local vtDir = EgtMV( nRibLoc)
|
|
local dParRef = -1
|
|
local dParCrv = 1
|
|
for dParCrv = 0, dParE - 1 do
|
|
local vtS = EgtUV( nId, dParCrv, 1)
|
|
local vtE = EgtUV( nId, dParCrv + 1, -1)
|
|
local dLenCrv = EgtCurveCompoLength( nId, dParCrv)
|
|
if AreSameVectorApprox( vtS, vtE) and vtS * vtDir < - 1 + GEO.EPS_SMALL and dLenCrv > dStrand + GEO.EPS_SMALL then
|
|
local vtDist = EgtUP( nId, dParCrv + 0.5) - EgtMP( nRibLoc)
|
|
local vtOrthoDist = vtDist - ( vtDist * vtDir) * vtDir
|
|
local dDist = vtOrthoDist:len()
|
|
if dDist < dStrand + GEO.EPS_SMALL then
|
|
dParRef = dParCrv
|
|
if not bInVsOut then
|
|
break
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
if dParRef > - GEO.EPS_SMALL then
|
|
if bInVsOut then
|
|
local _, dE = EgtCurveDomain( nId)
|
|
if abs( dParRef + 1 - dE) < GEO.EPS_SMALL then -- la curva si cancella completamente
|
|
return false
|
|
end
|
|
EgtTrimCurveStartAtParam( nId, dParRef + 1)
|
|
else
|
|
if dParRef < GEO.EPS_SMALL then -- la curva si cancella completamente
|
|
return false
|
|
end
|
|
EgtTrimCurveEndAtParam( nId, dParRef)
|
|
end
|
|
end
|
|
|
|
-- 3) verifiche con eventuale lead in
|
|
if not bInVsOut then
|
|
local nCurrLI = EgtGetPrev( nRibId)
|
|
if nCurrLI and EgtGetName( nCurrLI) == LEAD_IN_CRV then
|
|
local nLeadInLoc = EgtCopyGlob( nCurrLI, nGrpTmp)
|
|
-- verifico se intersezione fra curve
|
|
local _, nPnt, nCrv = EgtCurveCurveInters( nId, 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
|
|
-- EgtSetStatus( nSrfLeadIn, GDB_ST.OFF)
|
|
-- 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
|
|
end
|
|
|
|
local dNewLen = EgtCurveLength( nId)
|
|
if dNewLen < 100 * GEO.EPS_SMALL then
|
|
return false
|
|
end
|
|
if abs( dLen - dNewLen) > GEO.EPS_SMALL then
|
|
EgtOutLog( 'Warning : ' .. EgtGetName( nRibId) .. ' Lead' .. EgtIf( bInVsOut, 'In', 'Out') .. ' is shortened. Len = ' .. EgtNumToString( dNewLen) ..
|
|
', SetLen = ' .. EgtNumToString( dLen) .. ' ( layer '.. tostring( s_nCurrIdx)..') - CalcToolPath' )
|
|
end
|
|
|
|
EgtRelocateGlob( nId, nParentId)
|
|
return true
|
|
end
|
|
|
|
---------------------------------------------------------------------------------
|
|
local function PrepareRibLead( nCrvOffs, nRib, bInvert, bInVsOut, dPar, dLeadLen)
|
|
|
|
local nLeadId = EgtCopyGlob( nCrvOffs, nRib, 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)
|
|
|
|
if dLeadLen < GEO.EPS_SMALL then
|
|
return
|
|
end
|
|
|
|
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')
|
|
local nSplitId1 = EgtGetInfo( nRib, KEY_SPLIT_ID, 'i') or 0
|
|
local nSplitId2 = EgtGetInfo( nOtherRib, KEY_SPLIT_ID, 'i') or 0
|
|
if nOrigRib1 ~= nOrigRib2 or ( nOrigRib1 == nOrigRib2 and nSplitId1 ~= nSplitId2) 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
|
|
|
|
EgtRelocateGlob( nLeadId, nRib, EgtIf( bInVsOut, GDB_IN.BEFORE, GDB_IN.AFTER))
|
|
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')
|
|
local dFillet = EgtGetInfo( nCrv, KEY_RIBS_LEAD_FILLET, '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, 100 * GEO.EPS_SMALL)
|
|
if dParS then
|
|
local nLeadIn = FindCorrectRibLead( dParS, nCrv, vCrvOffs[i], bLIInvert, dLILen, true, nGrpTmp, bSpecialCase)
|
|
-- se lead in possibile
|
|
if nLeadIn then
|
|
AddFillet( nLeadIn, nCrv, dFillet, vtSlicing)
|
|
|
|
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')
|
|
local dFillet = EgtGetInfo( nCrv, KEY_RIBS_LEAD_FILLET, '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, 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
|
|
|
|
-- aggiungo il fillet ( potrebbe coinvolgere sia lead out sia coasting)
|
|
AddFillet( nCrv, nCrvRef, dFillet, vtSlicing)
|
|
-- calcolo la nuova lunghezza per il lead out per conservare la lunghezza del coasting dopo il fillet
|
|
dRibsLOLen = EgtCurveLength( nCrvRef) - dRibsLOCoasting
|
|
|
|
-- 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 = ptE + vtE * dRibsLOWipe
|
|
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, dStrand)
|
|
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, 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 nLastEnt = EgtGetLastInGroup( nTpathGrpId) or GDB_ID.NULL
|
|
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)
|
|
|
|
-- approssimo la curva e ne risetto punto iniziale (se chiusa)
|
|
local ptS = EgtSP( nNewEntId, GDB_ID.ROOT)
|
|
EgtApproxCurve( nNewEntId, GDB_CA.ARCS, s_dApproxTol)
|
|
if EgtCurveIsClosed( nNewEntId) then
|
|
EgtChangeClosedCurveStartPoint( nNewEntId, ptS, GDB_RT.GLOB)
|
|
end
|
|
|
|
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)
|
|
end
|
|
|
|
-- recupero i gruppi delle costolature
|
|
local tabRibs = {}
|
|
local nFirst = EgtGetNext( nLastEnt) or EgtGetFirstInGroup( nTpathGrpId)
|
|
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 bSplitAfterTrim = ( EgtGetInfo( tabRibs[i][j], KEY_SPLIT_AFTER_TRIM, 'b') or false) and ( EgtGetInfo( tabRibs[i][j+1], KEY_SPLIT_AFTER_TRIM, '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)
|
|
|
|
-- creo collegamento se userlink, passate dello stesso setto o passate divise dopo trim
|
|
if ( nOrig1 ~= nOrig2 and bUserLink) or ( nSplitId1 == nSplitId2 and nOrig1 == nOrig2) or ( nOrig1 == nOrig2 and bSplitAfterTrim) then
|
|
if not bLoopRib then
|
|
CalcRibsLink( tabRibs[i][j], tabRibs[i][j + 1], nLoopGrp, bForceLink, LayerParams.vtSlicing, nGrpTmp)
|
|
else
|
|
local nLinkId = CalcLoopRibLink( tabRibs[i][j], tabRibs[i][j + 1], nLoopGrp, LayerParams.vtSlicing, nGrpTmp, bForceLink)
|
|
-- se collegamento congiungo i setti in unico percorso
|
|
if nLinkId then
|
|
EgtAddCurveCompoCurve( tabRibs[i][j+1], nLinkId, true, false)
|
|
EgtAddCurveCompoCurve( tabRibs[i][j+1], tabRibs[i][j], true, false)
|
|
-- aggiorno id nel vettore dei setti per gestire correttamente le curve negli step successivi
|
|
for k = 0, j do
|
|
if tabRibs[i][k] == tabRibs[i][j] then
|
|
tabRibs[i][k] = tabRibs[i][j+1]
|
|
end
|
|
end
|
|
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, false)
|
|
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, 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 = EgtGetNext( nLastEnt)
|
|
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
|
|
if LayerParams.bLinearApprox then
|
|
EgtApproxCurve( nLeadOut, GDB_CA.LINES, LayerParams.dLinearApproxTol)
|
|
end
|
|
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.dCoastingLen, LayerParams.dWipeLen, LayerParams.dWipeDir)
|
|
end
|
|
end
|
|
|
|
---------------------------------------------------------------------
|
|
local function SpiralVaseFullMultiPlanar( vLayIds, LayerParams)
|
|
-- la differenza in altezza viene distribuita uniformemente lungo tutto il percorso. Tale differenza non è costante per tutti i punti della curva ma varia da punto a punto
|
|
-- la continuità tra i layers viene risolta sul layer corrente ( uniformemente su tutto il tratto o solo nella parte iniziale di lunghezza dSpiralVaseInterpLen)
|
|
-- gestione speciale per i primi due layers
|
|
-- aggiunta passata extra finale piana alla quota dell'ultimo layer
|
|
|
|
local nOldId, nOldPathId
|
|
local nRealLayer = 1
|
|
|
|
-- ciclo sui layer
|
|
for nIdx = 1, #vLayIds do
|
|
|
|
-- recupero il piano di slicing
|
|
local vtSlicing = EgtGetInfo( vLayIds[nIdx], KEY_SLICE_DIR, 'v')
|
|
local ptSlicing = EgtGetInfo( vLayIds[nIdx], KEY_SLICE_POS, 'p')
|
|
|
|
-- cerco i gruppi di contorni
|
|
local vCrvGrpIds = EgtGetNameInGroup( vLayIds[ nIdx], CONTOUR_GRP.."*")
|
|
if #vCrvGrpIds > 1 then
|
|
-- se più di un gruppo di curve errore
|
|
EgtOutBox( 'Error in spiral vase : layer ' .. tostring( nIdx) .. ' has more than one toolpath', 'ToolPathCalc')
|
|
return false
|
|
end
|
|
|
|
-- recupero il gruppo dei percorsi
|
|
local nPathGrpId = EgtGetFirstNameInGroup( vCrvGrpIds[1], 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[1], TOOLPATH_GRP)
|
|
if not nTpathGrpId then
|
|
nTpathGrpId = EgtGroup( vCrvGrpIds[1])
|
|
EgtSetName( nTpathGrpId, TOOLPATH_GRP)
|
|
else
|
|
EgtEmptyGroup( nTpathGrpId)
|
|
end
|
|
|
|
-- creo il percorso di lavoro :
|
|
local vEntIds = EgtGetAllInGroup( nPathGrpId)
|
|
if #vEntIds > 1 then
|
|
EgtOutBox( 'Error in spiral vase : layer ' .. tostring( nIdx) .. ' has more than one toolpath', 'ToolPathCalc')
|
|
return false
|
|
end
|
|
|
|
local nNewEntId = EgtCopyGlob( vEntIds[1] or GDB_ID.NULL, nTpathGrpId, GDB_IN.LAST_SON)
|
|
if nNewEntId then
|
|
|
|
EgtModifyCurveExtrusion( nNewEntId, 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 nRealLayer == 1 then
|
|
-- mi sposto dell'altezza layer
|
|
EgtMove( nNewEntId, LayerParams.dLayHeight * vtSlicing, GDB_RT.GLOB)
|
|
|
|
-- eventuale lead in
|
|
if LayerParams.nLeadInType ~= LEAD_TYPE.NONE then
|
|
EgtTrimCurveStartAtLen( nNewEntId, LayerParams.dOffsetLP)
|
|
local nLeadInCrv = AddLeadIn( nNewEntId, LayerParams, nTpathGrpId)
|
|
if nLeadInCrv and LayerParams.bLinearApprox then
|
|
EgtApproxCurve( nLeadInCrv, GDB_CA.LINES, LayerParams.dLinearApproxTol)
|
|
end
|
|
end
|
|
|
|
else
|
|
-- recupero il piano precedente
|
|
local vtSlicingPrev = EgtGetInfo( vLayIds[nIdx-1], KEY_SLICE_DIR, 'v')
|
|
local ptSlicingPrev = EgtGetInfo( vLayIds[nIdx-1], KEY_SLICE_POS, 'p') + LayerParams.dLayHeight * vtSlicingPrev
|
|
local dCosAng = vtSlicing * vtSlicingPrev
|
|
|
|
-- a) continuità dei percorsi
|
|
local ptEPrev = EgtEP( nOldId, GDB_ID.ROOT)
|
|
local ptEProj = ptEPrev - ( ptEPrev - ptSlicing) * vtSlicing * vtSlicing
|
|
|
|
-- tento di creare la continuità spostando il punto ( caso in cui ptEProj poggia su nNewEntId)
|
|
EgtChangeClosedCurveStartPoint( nNewEntId, ptEProj, GDB_RT.GLOB)
|
|
if not AreSamePointApprox( ptEPrev, EgtSP( nNewEntId, GDB_ID.ROOT)) then
|
|
-- se i percorsi non sono in continuità modifico percorso corrente usando come guida la proiezione ortogonale del percorso precedente
|
|
-- sul piano corrente ( SpiralizeAlongGuide lavora con curve piane complanari)
|
|
|
|
local nProjCrv = EgtCopyGlob( nOldPathId, nPathGrpId)
|
|
if LayerParams.bInvert then
|
|
EgtInvertCurve( nProjCrv)
|
|
end
|
|
EgtMove( nProjCrv, LayerParams.dLayHeight * vtSlicingPrev, GDB_RT.GLOB)
|
|
EgtProjectCurveOnPlane( nProjCrv, ptSlicing, vtSlicing, GDB_RT.GLOB)
|
|
EgtChangeClosedCurveStartPoint( nProjCrv, ptEProj, GDB_RT.GLOB)
|
|
|
|
-- approssimo con tratti lineari imponendo lunghezza massima per migliorare spiralize
|
|
EgtApproxCurve( nProjCrv, GDB_CA.SPECIAL_LINES, 0.01, s_dSpiralVaseMaxLen)
|
|
EgtApproxCurve( nNewEntId, GDB_CA.SPECIAL_LINES, 0.01, s_dSpiralVaseMaxLen)
|
|
|
|
-- 1) la differenza va distribuita su tutta la curva
|
|
local dLen = EgtCurveLength( nNewEntId)
|
|
if LayerParams.dSpiralVaseInterpLen < GEO.EPS_SMALL or LayerParams.dSpiralVaseInterpLen > dLen - GEO.EPS_SMALL then
|
|
EgtSpiralizeCurveAlongGuide( nNewEntId, nProjCrv)
|
|
|
|
-- 2) la differenza va distribuita solo su un sottotratto
|
|
else
|
|
local dParSplit = EgtCurveParamAtLength( nNewEntId, LayerParams.dSpiralVaseInterpLen)
|
|
local nNewEndId2 = EgtSplitCurveAtParam( nNewEntId, dParSplit)
|
|
-- trim della curva guida
|
|
local _, _, dParMinDist = EgtPointCurveDist( EgtEP( nNewEntId, GDB_ID.ROOT), nProjCrv, GDB_RT.GLOB)
|
|
local nGuideId2 = EgtSplitCurveAtParam( nProjCrv, dParMinDist)
|
|
EgtErase( nGuideId2)
|
|
-- spiralize solo del primo pezzo e riassemblo la curva
|
|
EgtSpiralizeCurveAlongGuide( nNewEntId, nProjCrv)
|
|
EgtAddCurveCompoCurve( nNewEntId, nNewEndId2)
|
|
end
|
|
-- forzo il punto
|
|
EgtModifyCurveStartPoint( nNewEntId, ptEProj, GDB_RT.GLOB)
|
|
EgtErase( nProjCrv)
|
|
end
|
|
|
|
-- b) spostamento verticale : alzo la curva e, per creare una transizione uniforme dal layer precedente, abbasso i suoi punti in modo graduale sul valore della distanza dal
|
|
-- dal layer precedente
|
|
EgtMove( nNewEntId, LayerParams.dLayHeight * vtSlicing, GDB_RT.GLOB)
|
|
|
|
-- approssimazione lineare per migliorare il calcolo delle quote
|
|
EgtApproxCurve( nNewEntId, GDB_CA.SPECIAL_LINES, 0.01, s_dSpiralVaseMaxLen)
|
|
|
|
if nRealLayer == 2 then
|
|
-- per non collassare sul layer precedente che è piatto alzo la prima metà della curva sempre di 0.5 * Delta
|
|
local dLen = EgtCurveLength( nNewEntId)
|
|
local dParMid = EgtCurveParamAtLength( nNewEntId, 0.5 * dLen)
|
|
EgtAddCurveCompoJoint( nNewEntId, dParMid)
|
|
local vDelta = {}
|
|
local _, dE = EgtCurveDomain( nNewEntId)
|
|
for dU = 0, dE - 1 do
|
|
local ptCurr = EgtUP( nNewEntId, dU, GDB_ID.ROOT)
|
|
local dDist = ( ( ptCurr - ptSlicingPrev) * vtSlicingPrev) / dCosAng -- distanza dal piano precedente lungo vtSlicing
|
|
local dCurrLen = EgtCurveLengthAtParam( nNewEntId, dU)
|
|
if dCurrLen < 0.5 * dLen then
|
|
vDelta[dU] = - dDist * 0.5
|
|
else
|
|
vDelta[dU] = - dDist * ( dLen - dCurrLen) / dLen
|
|
end
|
|
end
|
|
|
|
EgtModifyCurveStartPoint( nNewEntId, EgtSP( nNewEntId, GDB_ID.ROOT) + vDelta[0] * vtSlicing, GDB_RT.GLOB)
|
|
for dU = 1, dE - 1 do
|
|
local ptCurr = EgtUP( nNewEntId, dU, GDB_ID.ROOT)
|
|
EgtModifyCurveCompoJoint( nNewEntId, dU, ptCurr + vDelta[dU] * vtSlicing, GDB_RT.GLOB)
|
|
end
|
|
|
|
-- alzo l'ultimo tratto del layer precedente con una proiezione ortogonale "graduale" sul piano corrente
|
|
-- ricavo il tratto sulla curva precedente da alzare
|
|
local dTrimPar = EgtCurveParamAtLength( nOldId, EgtCurveLength( nOldId) - s_dSpralVaseFirstDelta)
|
|
local nLastId = EgtSplitCurveAtParam( nOldId, dTrimPar)
|
|
EgtApproxCurve( nLastId, GDB_CA.SPECIAL_LINES, 0.01, s_dSpiralVaseMaxLen)
|
|
-- alzo in maniera graduale
|
|
local _, dEOld = EgtCurveDomain( nLastId)
|
|
local vDeltaOld = {}
|
|
local dLenOld = EgtCurveLength( nLastId)
|
|
for dU = 0, dEOld do
|
|
local dCurrLen = EgtCurveLengthAtParam( nLastId, dU)
|
|
vDeltaOld[dU] = abs( vDelta[0]) * dCurrLen / dLenOld
|
|
end
|
|
for dU = 0, dEOld - 1 do
|
|
local ptCurr = EgtUP( nLastId, dU, GDB_ID.ROOT)
|
|
EgtModifyCurveCompoJoint( nLastId, dU, ptCurr + vDeltaOld[dU] * vtSlicing, GDB_RT.GLOB)
|
|
end
|
|
EgtModifyCurveEndPoint( nLastId, EgtEP( nLastId, GDB_ID.ROOT) + vDeltaOld[dEOld] * vtSlicing, GDB_RT.GLOB)
|
|
|
|
-- approssimo
|
|
EgtApproxCurve( nLastId, GDB_CA.ARCS, s_dApproxTol)
|
|
if LayerParams.bLinearApprox then
|
|
EgtApproxCurve( nLastId, GDB_CA.LINES, LayerParams.dLinearApproxTol)
|
|
end
|
|
EgtModifyCurveEndPoint( nLastId, EgtSP( nNewEntId, GDB_ID.ROOT), GDB_RT.GLOB)
|
|
|
|
else
|
|
|
|
local dLen = EgtCurveLength( nNewEntId)
|
|
local _, dE = EgtCurveDomain( nNewEntId)
|
|
local vDelta = {}
|
|
for dU = 0, dE - 1 do
|
|
local dCurrLen = EgtCurveLengthAtParam( nNewEntId, dU)
|
|
local ptCurr = EgtUP( nNewEntId, dU, GDB_ID.ROOT)
|
|
local dDist = ( ( ptCurr - ptSlicingPrev) * vtSlicingPrev) / dCosAng -- distanza dal piano precedente lungo vtSlicing
|
|
vDelta[dU] = - dDist * ( dLen - dCurrLen) / dLen
|
|
end
|
|
|
|
EgtModifyCurveStartPoint( nNewEntId, EgtSP( nNewEntId, GDB_ID.ROOT) + vDelta[0] * vtSlicing, GDB_RT.GLOB)
|
|
for dU = 1, dE - 1 do
|
|
local ptCurr = EgtUP( nNewEntId, dU, GDB_ID.ROOT)
|
|
EgtModifyCurveCompoJoint( nNewEntId, dU, ptCurr + vDelta[dU] * vtSlicing, GDB_RT.GLOB)
|
|
end
|
|
end
|
|
|
|
-- c) approssimo
|
|
local ptS = EgtSP( nNewEntId, GDB_ID.ROOT)
|
|
EgtApproxCurve( nNewEntId, GDB_CA.ARCS, s_dApproxTol)
|
|
if LayerParams.bLinearApprox then
|
|
EgtApproxCurve( nNewEntId, GDB_CA.LINES, LayerParams.dLinearApproxTol)
|
|
end
|
|
if EgtCurveIsClosed( nNewEntId) then
|
|
EgtChangeClosedCurveStartPoint( nNewEntId, ptS, GDB_RT.GLOB)
|
|
end
|
|
end
|
|
|
|
local vTPathsCrvs = EgtGetAllInGroup( nTpathGrpId)
|
|
nOldId = vTPathsCrvs[#vTPathsCrvs]
|
|
nOldPathId = vEntIds[1]
|
|
nRealLayer = nRealLayer + 1
|
|
end
|
|
|
|
if EgtProcessEvents( EgtIf( PRINT, 300, 0) + nIdx / #vLayIds * 100, 0) == 1 then
|
|
EgtDraw()
|
|
return false
|
|
end
|
|
end
|
|
|
|
-- creo un un layer extra piano alla quota finale
|
|
local nLastLay = EgtCopyGlob( vLayIds[#vLayIds], vLayIds[#vLayIds], GDB_IN.AFTER)
|
|
-- aggiorno nome e numero slice
|
|
local nSliceNbr = EgtGetInfo( nLastLay, KEY_SLICE_NBR, 'i') + 1
|
|
EgtSetName( nLastLay, SLICE_LAYER .. EgtNumToString( nSliceNbr))
|
|
EgtSetInfo( nLastLay, KEY_SLICE_NBR, nSliceNbr)
|
|
-- creo la curva di toolpath alla quota finale
|
|
local nCrvGrpId = EgtGetFirstNameInGroup( nLastLay, CONTOUR_GRP.."*")
|
|
local nPathGrpId = EgtGetFirstNameInGroup( nCrvGrpId, PATH_GRP)
|
|
local nTpathGrpId = EgtGetFirstNameInGroup( nCrvGrpId, TOOLPATH_GRP)
|
|
EgtEmptyGroup( nTpathGrpId)
|
|
local nId = EgtCopyGlob( EgtGetFirstInGroup( nPathGrpId), nTpathGrpId)
|
|
local vtSlicing = EgtGetInfo( nLastLay, KEY_SLICE_DIR, 'v')
|
|
EgtMove( nId, LayerParams.dLayHeight * vtSlicing, GDB_RT.GLOB)
|
|
|
|
local ptS = EgtEP( nOldId, GDB_ID.ROOT)
|
|
EgtChangeClosedCurveStartPoint( nId, ptS, GDB_RT.GLOB)
|
|
EgtModifyCurveExtrusion( nId, vtSlicing, GDB_RT.GLOB)
|
|
EgtSetInfo( nId, KEY_CRV_STRAND, LayerParams.dStrand)
|
|
if LayerParams.bInvert then
|
|
EgtInvertCurve( nId)
|
|
EgtSetInfo( nId, KEY_INVERTED_CRV, 1)
|
|
end
|
|
EgtSetColor( nId, EgtStdColor('GRAY'))
|
|
|
|
-- approssimo
|
|
EgtApproxCurve( nId, GDB_CA.ARCS, s_dApproxTol)
|
|
if LayerParams.bLinearApprox then
|
|
EgtApproxCurve( nId, GDB_CA.LINES, LayerParams.dLinearApproxTol)
|
|
end
|
|
if EgtCurveIsClosed( nId) then
|
|
EgtChangeClosedCurveStartPoint( nId, ptS, GDB_RT.GLOB)
|
|
end
|
|
|
|
return true
|
|
end
|
|
|
|
---------------------------------------------------------------------
|
|
local function SpiralVaseFull( vLayIds, LayerParams)
|
|
-- la differenza in altezza tra due layers viene distribuita uniformemente lungo tutto il percorso
|
|
-- la continuità tra i layers viene risolta sul layer corrente ( uniformemente su tutto il tratto o solo nella parte iniziale di lunghezza dSpiralVaseInterpLen)
|
|
-- gestione speciale dei primi layers per gestione dell'altezza e feed
|
|
|
|
local nSlicingType = EgtGetInfo( s_nPartId, KEY_SLICING_TYPE, 'i')
|
|
if nSlicingType == SLICING_TYPE.MULTIPLANAR or nSlicingType == SLICING_TYPE.MULTIPLANAR_DEG45 or nSlicingType == SLICING_TYPE.MULTIPLANAR_HOR then
|
|
return SpiralVaseFullMultiPlanar( vLayIds, LayerParams)
|
|
end
|
|
|
|
local nOldId, nOldPathId
|
|
local nRealLayer = 1
|
|
|
|
-- 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)
|
|
-- aggiorno nome e numero slice
|
|
local nSliceNbr = EgtGetInfo( nNewLay, KEY_SLICE_NBR, 'i') + 1
|
|
EgtSetName( nNewLay, SLICE_LAYER .. EgtNumToString( nSliceNbr))
|
|
EgtSetInfo( nNewLay, KEY_SLICE_NBR, nSliceNbr)
|
|
-- porto alla nuova quota
|
|
EgtMove( nNewLay, LayerParams.dLayHeight * LayerParams.vtSlicing, GDB_RT.GLOB)
|
|
local ptSlice = EgtGetInfo( nNewLay, KEY_SLICE_POS, 'p')
|
|
ptSlice = ptSlice + LayerParams.dLayHeight * LayerParams.vtSlicing
|
|
EgtSetInfo( nNewLay, KEY_SLICE_POS, ptSlice)
|
|
end
|
|
|
|
-- 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
|
|
EgtOutBox( 'Error in spiral vase : layer ' .. tostring( nIdx) .. ' has more than one toolpath', 'ToolPathCalc')
|
|
return false
|
|
end
|
|
|
|
-- recupero il gruppo dei percorsi
|
|
local nPathGrpId = EgtGetFirstNameInGroup( vCrvGrpIds[1], 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[1], TOOLPATH_GRP)
|
|
if not nTpathGrpId then
|
|
nTpathGrpId = EgtGroup( vCrvGrpIds[1])
|
|
EgtSetName( nTpathGrpId, TOOLPATH_GRP)
|
|
else
|
|
EgtEmptyGroup( nTpathGrpId)
|
|
end
|
|
|
|
-- creo il percorso di lavoro :
|
|
local vEntIds = EgtGetAllInGroup( nPathGrpId)
|
|
if #vEntIds > 1 then
|
|
EgtOutBox( 'Error in spiral vase : layer ' .. tostring( nIdx) .. ' has more than one toolpath', 'ToolPathCalc')
|
|
return false
|
|
end
|
|
|
|
local nNewEntId = EgtCopyGlob( vEntIds[1] or GDB_ID.NULL, nTpathGrpId, GDB_IN.LAST_SON)
|
|
if nNewEntId then
|
|
|
|
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 nRealLayer == 1 then
|
|
-- mi sposto dell'altezza layer
|
|
EgtMove( nNewEntId, LayerParams.dLayHeight * LayerParams.vtSlicing, GDB_RT.GLOB)
|
|
-- modifico altezza ultimo tratto
|
|
local dTrimPar = EgtCurveParamAtLength( nNewEntId, EgtCurveLength( nNewEntId) - s_dSpralVaseFirstDelta)
|
|
local nNewPart = EgtSplitCurveAtParam( nNewEntId, dTrimPar)
|
|
EgtSpiralizeCurveAlongExtrusion( nNewPart, 0.5 * LayerParams.dLayHeight)
|
|
|
|
if LayerParams.bLinearApprox then
|
|
EgtApproxCurve( nNewEntId, GDB_CA.LINES, LayerParams.dLinearApproxTol)
|
|
EgtApproxCurve( nNewPart, GDB_CA.LINES, LayerParams.dLinearApproxTol)
|
|
end
|
|
|
|
-- eventuale lead in
|
|
if LayerParams.nLeadInType ~= LEAD_TYPE.NONE then
|
|
EgtTrimCurveStartAtLen( nNewEntId, LayerParams.dOffsetLP)
|
|
local nLeadInCrv = AddLeadIn( nNewEntId, LayerParams, nTpathGrpId)
|
|
if nLeadInCrv and LayerParams.bLinearApprox then
|
|
EgtApproxCurve( nLeadInCrv, GDB_CA.LINES, LayerParams.dLinearApproxTol)
|
|
end
|
|
end
|
|
else
|
|
-- a) garantisco continuità con layer precedente
|
|
local ptOld = EgtEP( nOldId, GDB_ID.ROOT)
|
|
if nRealLayer == 2 then
|
|
-- aggiusto la quota per confronto sensato
|
|
ptOld = ptOld - 0.5 * LayerParams.dLayHeight * LayerParams.vtSlicing
|
|
end
|
|
local ptNew = EgtSP( nNewEntId, GDB_ID.ROOT)
|
|
|
|
-- se il punto di inizio non coincide con quello finale del percorso calcolato fino ad ora, modifico la curva per avere una transizione più uniforme tra i due layers
|
|
if not AreSamePointApprox( ptOld, ptNew) then
|
|
-- recupero la curva da usare come guida
|
|
local nGuideId = EgtCopyGlob( nOldPathId, nPathGrpId)
|
|
-- la rendo coerente con il toolpath
|
|
EgtMove( nGuideId, vtMove + LayerParams.dLayHeight * LayerParams.vtSlicing, GDB_RT.GLOB)
|
|
if LayerParams.bInvert then
|
|
EgtInvertCurve( nGuideId)
|
|
end
|
|
-- approssimo con tratti lineari imponendo lunghezza massima per migliorare spiralize
|
|
EgtApproxCurve( nGuideId, GDB_CA.SPECIAL_LINES, 0.01, s_dSpiralVaseMaxLen)
|
|
EgtApproxCurve( nNewEntId, GDB_CA.SPECIAL_LINES, 0.01, s_dSpiralVaseMaxLen)
|
|
-- modifico i punti iniziali affinchè coincidano con il punto finale del percorso precedente
|
|
EgtChangeClosedCurveStartPoint( nGuideId, ptOld, GDB_RT.GLOB)
|
|
EgtChangeClosedCurveStartPoint( nNewEntId, ptOld, GDB_RT.GLOB)
|
|
|
|
-- distribuisco la differenza sulla curva
|
|
local dLen = EgtCurveLength( nNewEntId)
|
|
if LayerParams.dSpiralVaseInterpLen < GEO.EPS_SMALL or LayerParams.dSpiralVaseInterpLen > dLen - GEO.EPS_SMALL then
|
|
-- la differenza deve essere distribuita su tutta la curva
|
|
EgtSpiralizeCurveAlongGuide( nNewEntId, nGuideId)
|
|
-- forzo il punto di inizio a coincidere con il layer precedente ( non è garantito dallo spiralize con il path a causa dell'approx
|
|
-- con gli archi che potrebbe modificare il punto finale del tpath rispetto a quello del path associato)
|
|
EgtModifyCurveStartPoint( nNewEntId, ptOld, GDB_RT.GLOB)
|
|
|
|
else
|
|
-- la differenza deve essere distribuita solo su un sottotratto di lunghezza LayerParams.dSpiralVaseAdjLen
|
|
local dParSplit = EgtCurveParamAtLength( nNewEntId, LayerParams.dSpiralVaseInterpLen)
|
|
local nNewEndId2 = EgtSplitCurveAtParam( nNewEntId, dParSplit)
|
|
-- trim della curva guida
|
|
local _, _, dParMinDist = EgtPointCurveDist( EgtEP( nNewEntId, GDB_ID.ROOT), nGuideId, GDB_RT.GLOB)
|
|
local nGuideId2 = EgtSplitCurveAtParam( nGuideId, dParMinDist)
|
|
EgtErase( nGuideId2)
|
|
-- spiralize solo del primo pezzo
|
|
EgtSpiralizeCurveAlongGuide( nNewEntId, nGuideId)
|
|
EgtModifyCurveStartPoint( nNewEntId, ptOld, GDB_RT.GLOB)
|
|
EgtModifyCurveEndPoint( nNewEntId, EgtSP( nNewEndId2, GDB_ID.ROOT), GDB_RT.GLOB)
|
|
-- riassemblo la curva
|
|
EgtAddCurveCompoCurve( nNewEntId, nNewEndId2)
|
|
end
|
|
|
|
EgtErase( nGuideId)
|
|
end
|
|
|
|
-- b) approssimo
|
|
local ptS = EgtSP( nNewEntId, GDB_ID.ROOT)
|
|
EgtApproxCurve( nNewEntId, GDB_CA.ARCS, s_dApproxTol)
|
|
if LayerParams.bLinearApprox then
|
|
EgtApproxCurve( nNewEntId, GDB_CA.LINES, LayerParams.dLinearApproxTol)
|
|
end
|
|
if EgtCurveIsClosed( nNewEntId) then
|
|
EgtChangeClosedCurveStartPoint( nNewEntId, ptS, GDB_RT.GLOB)
|
|
end
|
|
|
|
-- c) modifica graduale dell'altezza
|
|
if nRealLayer == 2 then
|
|
-- se seconda passata la prima metà deve essere a quota costante 0.5 * dLayHeight, la seconda metà deve salire gradualmente di 0.5 * dLayHeight
|
|
EgtMove( nNewEntId, 0.5 * LayerParams.dLayHeight * LayerParams.vtSlicing, GDB_RT.GLOB)
|
|
local nNewId = EgtSplitCurve( nNewEntId, 2)
|
|
EgtSpiralizeCurveAlongExtrusion( nNewId + 1, 0.5 * LayerParams.dLayHeight)
|
|
else
|
|
EgtSpiralizeCurveAlongExtrusion( nNewEntId, LayerParams.dLayHeight)
|
|
end
|
|
end
|
|
|
|
local vTPathsCrvs = EgtGetAllInGroup( nTpathGrpId)
|
|
nOldPathId = vEntIds[1]
|
|
nOldId = vTPathsCrvs[#vTPathsCrvs]
|
|
|
|
-- moltiplicatore per feed
|
|
if nRealLayer == 2 then
|
|
-- il primo tratto si trova a metà altezza rispetto allo strato precedente, quindi il coefficiente moltiplicativo è due
|
|
EgtSetInfo( vTPathsCrvs[1], KEY_FEED_COEFF, 2)
|
|
-- nel secondo tratto l'altezza è variabile quindi devo calcolare il coefficiente per ogni sottotratto
|
|
local dLenTot = EgtCurveLength( vTPathsCrvs[1]) + EgtCurveLength( vTPathsCrvs[2])
|
|
local dLen = EgtCurveLength( vTPathsCrvs[1])
|
|
local nFirst, nCnt = EgtExplodeCurveCompo( vTPathsCrvs[2])
|
|
for nId = nFirst, nFirst + nCnt - 1 do
|
|
-- calcolo l'altezza effettiva basandomi sulla lunghezza parziale ( viene mimato il conto fatto in EgtSpiralizeCurveAlongExtrusion)
|
|
dLen = dLen + EgtCurveLength( nId)
|
|
local dHEff = LayerParams.dLayHeight * dLen / dLenTot
|
|
local dFeedCoeff = LayerParams.dLayHeight / dHEff
|
|
EgtSetInfo( nId, KEY_FEED_COEFF, dFeedCoeff)
|
|
end
|
|
nOldId = nFirst + nCnt - 1
|
|
|
|
elseif nRealLayer == 3 then
|
|
-- solo la prima metà si trova ad un'altezza variabile rispetto allo strato precedente
|
|
local dLenTot = EgtCurveLength( vTPathsCrvs[1])
|
|
local dLen = 0
|
|
local nNewId = EgtSplitCurve( vTPathsCrvs[1], 2)
|
|
local nFirst, nCnt = EgtExplodeCurveCompo( nNewId)
|
|
for nId = nFirst, nFirst + nCnt - 1 do
|
|
dLen = dLen + EgtCurveLength( nId)
|
|
local dHeff = LayerParams.dLayHeight * ( dLen / dLenTot + 0.5)
|
|
local dFeedCoeff = LayerParams.dLayHeight / dHeff
|
|
EgtSetInfo( nId, KEY_FEED_COEFF, dFeedCoeff)
|
|
end
|
|
nOldId = nNewId + 1
|
|
end
|
|
|
|
nRealLayer = nRealLayer + 1
|
|
end
|
|
|
|
if EgtProcessEvents( EgtIf( PRINT, 300, 0) + nIdx / #vLayIds * 100, 0) == 1 then
|
|
EgtDraw()
|
|
return false
|
|
end
|
|
end
|
|
|
|
return true
|
|
end
|
|
|
|
---------------------------------------------------------------------
|
|
local function SpiralVasePartialMultiPlanar( vLayIds, LayerParams)
|
|
-- la differenza in altezza tra due layers viene distribuita solo lungo il tratto finale di lunghezza dSpiralVaseLen
|
|
-- la continuità tra i layers viene risolta sul tratto finale del layer percedente
|
|
|
|
local bFirst = true
|
|
-- individuo l'ultimo layer ( alcuni potrebbero essere vuoti)
|
|
local nLastLay = 1
|
|
for nIdx = #vLayIds, 1, -1 do
|
|
local nCrvGrp = EgtGetFirstNameInGroup( vLayIds[ nIdx], CONTOUR_GRP.."*")
|
|
local nPathGrpId = EgtGetFirstNameInGroup( nCrvGrp, PATH_GRP) or GDB_ID_NULL
|
|
if EgtGetGroupObjs( nPathGrpId) > 0 then
|
|
nLastLay = nIdx
|
|
break
|
|
end
|
|
end
|
|
|
|
-- ciclo sui layer
|
|
local nOldId
|
|
for nIdx = 1, #vLayIds do
|
|
|
|
-- piano di slicing
|
|
local vtSlicing = EgtGetInfo( vLayIds[nIdx], KEY_SLICE_DIR, 'v')
|
|
local ptSlicing = EgtGetInfo( vLayIds[nIdx], KEY_SLICE_POS, 'p')
|
|
|
|
-- cerco i gruppi di contorni
|
|
local vCrvGrpIds = EgtGetNameInGroup( vLayIds[ nIdx], CONTOUR_GRP.."*")
|
|
if #vCrvGrpIds > 1 then
|
|
-- se più di un gruppo di curve errore
|
|
EgtOutBox( 'Error in spiral vase : layer ' .. tostring( nIdx) .. ' has more than one toolpath', 'ToolPathCalc')
|
|
return false
|
|
end
|
|
|
|
-- recupero il gruppo dei percorsi
|
|
local nPathGrpId = EgtGetFirstNameInGroup( vCrvGrpIds[1], PATH_GRP)
|
|
if not nPathGrpId then
|
|
EgtOutBox( 'Error missing paths', 'ToolPathCalc')
|
|
return false
|
|
else
|
|
EgtSetStatus( nPathGrpId, GDB_ST.OFF)
|
|
end
|
|
|
|
-- recupero il gruppo dei percorsi utensile
|
|
local nTpathGrpId = EgtGetFirstNameInGroup( vCrvGrpIds[1], TOOLPATH_GRP)
|
|
if not nTpathGrpId then
|
|
nTpathGrpId = EgtGroup( vCrvGrpIds[1])
|
|
EgtSetName( nTpathGrpId, TOOLPATH_GRP)
|
|
else
|
|
EgtEmptyGroup( nTpathGrpId)
|
|
end
|
|
|
|
-- creo il percorso di lavoro
|
|
local vEntIds = EgtGetAllInGroup( nPathGrpId)
|
|
if #vEntIds > 1 then
|
|
EgtOutBox( 'Error in spiral vase : layer ' .. tostring( nIdx) .. ' has more than one toolpath', 'ToolPathCalc')
|
|
return false
|
|
end
|
|
|
|
local nNewEntId = EgtCopyGlob( vEntIds[1] or GDB_ID.NULL, nTpathGrpId, GDB_IN.LAST_SON)
|
|
if nNewEntId then
|
|
|
|
EgtModifyCurveExtrusion( nNewEntId, vtSlicing, GDB_RT.GLOB)
|
|
EgtSetInfo( nNewEntId, KEY_CRV_STRAND, LayerParams.dStrand)
|
|
if LayerParams.bInvert then
|
|
EgtInvertCurve( nNewEntId)
|
|
EgtSetInfo( nNewEntId, KEY_INVERTED_CRV, 1)
|
|
end
|
|
EgtSetColor( nNewEntId, EgtStdColor('GRAY'))
|
|
|
|
-- sistemo il tratto finale del percorso precedente
|
|
if not bFirst then
|
|
|
|
local ptSOld = EgtSP( nOldId, GDB_ID.ROOT)
|
|
local ptEOld = EgtEP( nOldId, GDB_ID.ROOT)
|
|
-- proiezione ortogonale dei punti sul piano di slicing corrente
|
|
local ptSProj = ptSOld - ( ( ptSOld - ptSlicing) * vtSlicing) * vtSlicing
|
|
local ptEProj = ptEOld - ( ( ptEOld - ptSlicing) * vtSlicing) * vtSlicing
|
|
|
|
-- a) continuità tra i layers
|
|
-- modifico il punto iniziale corrente per avvicinarmi il più possibile alla fine del percorso precedente
|
|
EgtChangeClosedCurveStartPoint( nNewEntId, ptEProj, GDB_RT.GLOB)
|
|
local ptCurrStart = EgtSP( nNewEntId, GDB_ID.ROOT)
|
|
if not AreSamePointApprox( ptEProj, ptCurrStart) then
|
|
-- se i percorsi non sono in continuità modifico il tratto finale del percorso precedente in modo da farlo arrivare sul punto di inizio del percorso corrente
|
|
-- usando come guida la proiezione obliqua del percorso corrente sul piano precedente ( SpiralizeAlongGuide lavora con curve piane complanari)
|
|
|
|
local nProjCrv = EgtCopyGlob( vEntIds[1], nPathGrpId)
|
|
if LayerParams.bInvert then
|
|
EgtInvertCurve( nProjCrv)
|
|
end
|
|
-- conservo solo il sottotratto corrispondente a nOldId
|
|
local _, _, dStartGuide = EgtPointCurveDist( ptSProj, nProjCrv, GDB_ID.ROOT)
|
|
local _, _, dEndGuide = EgtPointCurveDist( ptEProj, nProjCrv, GDB_ID.ROOT)
|
|
EgtTrimCurveStartEndAtParam( nProjCrv, dStartGuide, dEndGuide)
|
|
-- proiezione sul piano precedente ( ptSlicingPrev, vtSlicingPrev) lungo vtSlicing
|
|
local vtSlicingPrev = EgtGetInfo( vLayIds[nIdx-1], KEY_SLICE_DIR, 'v')
|
|
local ptSlicingPrev = EgtGetInfo( vLayIds[nIdx-1], KEY_SLICE_POS, 'p') + LayerParams.dLayHeight * vtSlicingPrev
|
|
local _, dE = EgtCurveDomain( nProjCrv)
|
|
for dU = 0, dE do
|
|
local pt = EgtUP( nProjCrv, dU, GDB_ID.ROOT)
|
|
local dDist = ( pt - ptSlicingPrev) * vtSlicingPrev / ( vtSlicingPrev * vtSlicing)
|
|
EgtModifyCurveCompoJoint( nProjCrv, dU, pt - dDist * vtSlicing, GDB_RT.GLOB)
|
|
end
|
|
-- approssimazione dei tratti per migliorare la qualità dello spiralize
|
|
EgtApproxCurve( nProjCrv, GDB_CA.SPECIAL_LINES, 0.01, s_dSpiralVaseMaxLen)
|
|
EgtApproxCurve( nOldId, GDB_CA.SPECIAL_LINES, 0.01, s_dSpiralVaseMaxLen)
|
|
-- spiralize
|
|
EgtInvertCurve( nProjCrv)
|
|
EgtInvertCurve( nOldId)
|
|
EgtSpiralizeCurveAlongGuide( nOldId, nProjCrv)
|
|
EgtInvertCurve( nOldId)
|
|
|
|
EgtErase( nProjCrv)
|
|
end
|
|
|
|
-- b) proiezione ortogonale graduale sul piano corrente
|
|
-- delta che va applicato ( è la distanza ortogonale del punto finale di nOldId dal piano del toolpath corrente)
|
|
local dDist = ( EgtEP( nOldId, GDB_ID.ROOT) - ( ptSlicing + LayerParams.dLayHeight * vtSlicing)) * vtSlicing
|
|
EgtApproxCurve( nOldId, GDB_CA.SPECIAL_LINES, 0.01, s_dSpiralVaseMaxLen)
|
|
local _, dE = EgtCurveDomain( nOldId)
|
|
local vDelta = {}
|
|
local dLen = EgtCurveLength( nOldId)
|
|
for dU = 0, dE do
|
|
local dCurrLen = EgtCurveLengthAtParam( nOldId, dU)
|
|
vDelta[dU] = abs( dDist) * dCurrLen / dLen
|
|
end
|
|
for dU = 0, dE do
|
|
local ptCurr = EgtUP( nOldId, dU, GDB_ID.ROOT)
|
|
EgtModifyCurveCompoJoint( nOldId, dU, ptCurr + vDelta[dU] * vtSlicing, GDB_RT.GLOB)
|
|
end
|
|
|
|
-- c) approssimazione della curva
|
|
EgtApproxCurve( nOldId, GDB_CA.ARCS, s_dApproxTol)
|
|
if LayerParams.bLinearApprox then
|
|
EgtApproxCurve( nOldId, GDB_CA.LINES, LayerParams.dLinearApproxTol)
|
|
end
|
|
-- forzo punti per garantire continuità
|
|
EgtModifyCurveStartPoint( nOldId, ptSOld, GDB_RT.GLOB)
|
|
EgtModifyCurveEndPoint( nOldId, ptCurrStart + LayerParams.dLayHeight * vtSlicing, GDB_RT.GLOB)
|
|
end
|
|
|
|
-- spostamento dell'altezza layer
|
|
local vtMove = LayerParams.dLayHeight * vtSlicing
|
|
EgtMove( nNewEntId, vtMove, GDB_RT.GLOB)
|
|
EgtCopyGlob( nNewEntId, nPathGrpId)
|
|
|
|
-- approssimazione
|
|
if LayerParams.bLinearApprox then
|
|
local ptS = EgtSP( nNewEntId, GDB_ID.ROOT)
|
|
EgtApproxCurve( nNewEntId, GDB_CA.LINES, LayerParams.dLinearApproxTol)
|
|
if EgtCurveIsClosed( nNewEntId) then
|
|
EgtChangeClosedCurveStartPoint( nNewEntId, ptS, GDB_RT.GLOB)
|
|
end
|
|
end
|
|
|
|
-- eventuale lead in
|
|
if bFirst then
|
|
bFirst = false
|
|
if LayerParams.nLeadInType ~= LEAD_TYPE.NONE then
|
|
EgtTrimCurveStartAtLen( nNewEntId, LayerParams.dOffsetLP)
|
|
local nLeadInCrv = AddLeadIn( nNewEntId, LayerParams, nTpathGrpId)
|
|
if nLeadInCrv and LayerParams.bLinearApprox then
|
|
EgtApproxCurve( nLeadInCrv, GDB_CA.LINES, LayerParams.dLinearApproxTol)
|
|
end
|
|
end
|
|
end
|
|
|
|
-- separo l'ultimo tratto che farà da collegamento con il layer successivo
|
|
if nIdx ~= nLastLay then
|
|
local dTrimLen = EgtCurveLength( nNewEntId) - LayerParams.dSpiralVaseLen
|
|
if dTrimLen < GEO.EPS_SMALL then
|
|
-- se lunghezza di trim maggiore delle dimensioni forzo un valore accettabile
|
|
dTrimLen = 0.5 * EgtCurveLength( nNewEntId)
|
|
end
|
|
local dTrimPar = EgtCurveParamAtLength( nNewEntId, dTrimLen)
|
|
nOldId = EgtSplitCurveAtParam( nNewEntId, dTrimPar)
|
|
end
|
|
end
|
|
|
|
if EgtProcessEvents( EgtIf( PRINT, 300, 0) + nIdx / #vLayIds * 100, 0) == 1 then
|
|
EgtDraw()
|
|
return false
|
|
end
|
|
end
|
|
|
|
return true
|
|
end
|
|
|
|
---------------------------------------------------------------------
|
|
local function SpiralVasePartial( vLayIds, LayerParams)
|
|
-- la differenza in altezza tra due layers viene distribuita solo lungo il tratto finale di lunghezza dSpiralVaseLen
|
|
-- la continuità tra i layers viene risolta sul tratto finale del layer percedente
|
|
|
|
local nSlicingType = EgtGetInfo( s_nPartId, KEY_SLICING_TYPE, 'i')
|
|
if nSlicingType == SLICING_TYPE.MULTIPLANAR or nSlicingType == SLICING_TYPE.MULTIPLANAR_DEG45 or nSlicingType == SLICING_TYPE.MULTIPLANAR_HOR then
|
|
return SpiralVasePartialMultiPlanar( vLayIds, LayerParams)
|
|
end
|
|
|
|
local bFirst = true
|
|
-- individuo l'ultimo layer ( alcuni potrebbero essere vuoti)
|
|
local nLastLay = 1
|
|
for nIdx = #vLayIds, 1, -1 do
|
|
local nCrvGrp = EgtGetFirstNameInGroup( vLayIds[ nIdx], CONTOUR_GRP.."*")
|
|
local nPathGrpId = EgtGetFirstNameInGroup( nCrvGrp, PATH_GRP) or GDB_ID_NULL
|
|
if EgtGetGroupObjs( nPathGrpId) > 0 then
|
|
nLastLay = nIdx
|
|
break
|
|
end
|
|
end
|
|
|
|
-- ciclo sui layer
|
|
local nOldId
|
|
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 errore
|
|
EgtOutBox( 'Error in spiral vase : layer ' .. tostring( nIdx) .. ' has more than one toolpath', 'ToolPathCalc')
|
|
return false
|
|
end
|
|
|
|
-- recupero il gruppo dei percorsi
|
|
local nPathGrpId = EgtGetFirstNameInGroup( vCrvGrpIds[1], PATH_GRP)
|
|
if not nPathGrpId then
|
|
EgtOutBox( 'Error missing paths', 'ToolPathCalc')
|
|
return false
|
|
else
|
|
EgtSetStatus( nPathGrpId, GDB_ST.OFF)
|
|
end
|
|
|
|
-- recupero il gruppo dei percorsi utensile
|
|
local nTpathGrpId = EgtGetFirstNameInGroup( vCrvGrpIds[1], TOOLPATH_GRP)
|
|
if not nTpathGrpId then
|
|
nTpathGrpId = EgtGroup( vCrvGrpIds[1])
|
|
EgtSetName( nTpathGrpId, TOOLPATH_GRP)
|
|
else
|
|
EgtEmptyGroup( nTpathGrpId)
|
|
end
|
|
|
|
-- creo il percorso di lavoro
|
|
local vEntIds = EgtGetAllInGroup( nPathGrpId)
|
|
if #vEntIds > 1 then
|
|
EgtOutBox( 'Error in spiral vase : layer ' .. tostring( nIdx) .. ' has more than one toolpath', 'ToolPathCalc')
|
|
return false
|
|
end
|
|
|
|
local nNewEntId = EgtCopyGlob( vEntIds[1] or GDB_ID.NULL, nTpathGrpId, GDB_IN.LAST_SON)
|
|
if nNewEntId then
|
|
|
|
EgtModifyCurveExtrusion( nNewEntId, LayerParams.vtSlicing, GDB_RT.GLOB)
|
|
EgtSetInfo( nNewEntId, KEY_CRV_STRAND, LayerParams.dStrand)
|
|
if LayerParams.bInvert then
|
|
EgtInvertCurve( nNewEntId)
|
|
EgtSetInfo( nNewEntId, KEY_INVERTED_CRV, 1)
|
|
end
|
|
EgtSetColor( nNewEntId, EgtStdColor('GRAY'))
|
|
|
|
-- sistemo il tratto finale del percorso precedente
|
|
if not bFirst then
|
|
local ptSOld = EgtSP( nOldId, GDB_ID.ROOT)
|
|
local ptEOld = EgtEP( nOldId, GDB_ID.ROOT)
|
|
|
|
-- modifico il punto iniziale corrente per avvicinarmi il più possibile alla fine del percorso precedente
|
|
EgtChangeClosedCurveStartPoint( nNewEntId, ptEOld, GDB_RT.GLOB)
|
|
local ptNew = EgtSP( nNewEntId, GDB_ID.ROOT)
|
|
|
|
-- a) verifico continuità tra i layers
|
|
if not AreSamePointApprox( ptEOld, ptNew) then
|
|
-- se il punto finale del percorso precedente non coincide con quello iniziale del percorso corrente modifico il tratto finale del percorso precedente che va alzato sin modo
|
|
-- che termini esattamente sull'inizio del percorso corrente
|
|
local _, _, dStartGuide = EgtPointCurveDist( ptSOld, nNewEntId, GDB_ID.ROOT)
|
|
local _, dEndGuide = EgtCurveDomain( nNewEntId)
|
|
local nGuideId = EgtCopyParamRange( nNewEntId, dStartGuide, dEndGuide, nTpathGrpId)
|
|
EgtModifyCurveExtrusion( nGuideId, LayerParams.vtSlicing, GDB_RT.GLOB)
|
|
|
|
-- approssimo con tratti lineari imponendo lunghezza massima per migliorare spiralize
|
|
EgtApproxCurve( nGuideId, GDB_CA.SPECIAL_LINES, 0.01, s_dSpiralVaseMaxLen)
|
|
EgtApproxCurve( nOldId, GDB_CA.SPECIAL_LINES, 0.01, s_dSpiralVaseMaxLen)
|
|
|
|
-- SpiralizeAlongGuide effettua una transizione dalla guida alla curva corrente, qui serve in contrario ( la curva deve arrivare sulla guida non partire da essa)
|
|
-- quindi bisogna lavorare con le curve invertite
|
|
EgtInvertCurve( nGuideId)
|
|
EgtInvertCurve( nOldId)
|
|
EgtSpiralizeCurveAlongGuide( nOldId, nGuideId)
|
|
EgtInvertCurve( nOldId)
|
|
EgtErase( nGuideId)
|
|
|
|
-- approssimo la curva
|
|
EgtApproxCurve( nOldId, GDB_CA.ARCS, s_dApproxTol)
|
|
if LayerParams.bLinearApprox then
|
|
EgtApproxCurve( nOldId, GDB_CA.LINES, LayerParams.dLinearApproxTol)
|
|
end
|
|
-- forzo punti per garantire continuità
|
|
EgtModifyCurveStartPoint( nOldId, ptSOld, GDB_RT.GLOB)
|
|
EgtModifyCurveEndPoint( nOldId, ptNew, GDB_RT.GLOB)
|
|
end
|
|
|
|
-- b) modifica graduale dell'altezza
|
|
EgtSpiralizeCurveAlongExtrusion( nOldId, LayerParams.dLayHeight)
|
|
end
|
|
|
|
-- spostamento dell'altezza layer
|
|
local vtMove = LayerParams.dLayHeight * LayerParams.vtSlicing
|
|
EgtMove( nNewEntId, vtMove, GDB_RT.GLOB)
|
|
|
|
-- approssimazione
|
|
if LayerParams.bLinearApprox then
|
|
local ptS = EgtSP( nNewEntId, GDB_ID.ROOT)
|
|
EgtApproxCurve( nNewEntId, GDB_CA.LINES, LayerParams.dLinearApproxTol)
|
|
if EgtCurveIsClosed( nNewEntId) then
|
|
EgtChangeClosedCurveStartPoint( nNewEntId, ptS, GDB_RT.GLOB)
|
|
end
|
|
end
|
|
|
|
-- eventuale lead in
|
|
if bFirst then
|
|
bFirst = false
|
|
if LayerParams.nLeadInType ~= LEAD_TYPE.NONE then
|
|
EgtTrimCurveStartAtLen( nNewEntId, LayerParams.dOffsetLP)
|
|
local nLeadInCrv = AddLeadIn( nNewEntId, LayerParams, nTpathGrpId)
|
|
if nLeadInCrv and LayerParams.bLinearApprox then
|
|
EgtApproxCurve( nLeadInCrv, GDB_CA.LINES, LayerParams.dLinearApproxTol)
|
|
end
|
|
end
|
|
end
|
|
|
|
-- separo l'ultimo tratto che farà da collegamento con il layer successivo
|
|
if nIdx ~= nLastLay then
|
|
local dTrimLen = EgtCurveLength( nNewEntId) - LayerParams.dSpiralVaseLen
|
|
if dTrimLen < GEO.EPS_SMALL then
|
|
-- se lunghezza di trim maggiore delle dimensioni forzo un valore accettabile
|
|
dTrimLen = 0.5 * EgtCurveLength( nNewEntId)
|
|
end
|
|
local dTrimPar = EgtCurveParamAtLength( nNewEntId, dTrimLen)
|
|
nOldId = EgtSplitCurveAtParam( nNewEntId, dTrimPar)
|
|
end
|
|
end
|
|
|
|
if EgtProcessEvents( EgtIf( PRINT, 300, 0) + nIdx / #vLayIds * 100, 0) == 1 then
|
|
EgtDraw()
|
|
return false
|
|
end
|
|
end
|
|
|
|
return true
|
|
end
|
|
|
|
---------------------------------------------------------------------
|
|
local function SpiralVase( vLayIds, LayerParams)
|
|
|
|
-- verifico quale modalità di spiral vase applicare :
|
|
-- 1) dSpiralVaseLen = 0 : la differenza in altezza tra due layers ( dLayHeight) viene distribuita uniformemente sull'intero percorso
|
|
-- 2) dSpiralVaseLen > 0 : la differenza in altezza tra due layers viene distribuita solo lungo il tratto finale di lunghezza dSpiralVaseLen
|
|
|
|
if abs( LayerParams.dSpiralVaseLen) < GEO.EPS_SMALL then
|
|
if not SpiralVaseFull( vLayIds, LayerParams) then
|
|
return false
|
|
end
|
|
else
|
|
if not SpiralVasePartial( vLayIds, LayerParams) then
|
|
return false
|
|
end
|
|
end
|
|
|
|
-- aggiungo uscita, coasting e wipe su ultima curva
|
|
local nLastLayer = EgtGetLastNameInGroup( s_nPartId, SLICE_LAYER .. '*')
|
|
local vCrvGrpIds = EgtGetNameInGroup( nLastLayer, CONTOUR_GRP.."*")
|
|
local nTpathGrpId = EgtGetFirstNameInGroup( vCrvGrpIds[1], TOOLPATH_GRP)
|
|
local nLastTPath = EgtGetLastInGroup( nTpathGrpId)
|
|
AddSpiralVaseLeadOut( nLastTPath, LayerParams)
|
|
|
|
-- correzione in z
|
|
AddZCorrection( 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 or #vLayIds == 0 then
|
|
EgtOutBox( 'Error missing slices', 'ToolPathCalc')
|
|
return true
|
|
end
|
|
|
|
-- recupero i parametri per calcolo dei toolpath
|
|
local LayerParams = GetLayerParamsForToolPathCalc()
|
|
local nSlicingType = EgtGetInfo( s_nPartId, KEY_SLICING_TYPE, 'i')
|
|
local bFirst = true
|
|
|
|
-- caso spiral vase
|
|
if LayerParams.bSpiralVase then
|
|
return SpiralVase( vLayIds, LayerParams)
|
|
end
|
|
|
|
local nLayCnt = 1
|
|
-- Ciclo sui layer
|
|
for nIdx = 1, #vLayIds do
|
|
|
|
s_nCurrIdx = nIdx
|
|
|
|
if nSlicingType == SLICING_TYPE.MULTIPLANAR or nSlicingType == SLICING_TYPE.MULTIPLANAR_DEG45 or nSlicingType == SLICING_TYPE.MULTIPLANAR_HOR then
|
|
LayerParams.vtSlicing = EgtGetInfo( vLayIds[nIdx], KEY_SLICE_DIR, 'v')
|
|
end
|
|
|
|
-- 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, bFirst, 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
|
|
|
|
-- verifico non sia vuoto per aggiornare il numero di layers
|
|
if EgtGetFirstInGroup( nTpathGrpId) then
|
|
nLayCnt = nIdx
|
|
end
|
|
|
|
-- eventuale approssimazione delle curve
|
|
if LayerParams.bLinearApprox then
|
|
local nCrvId = EgtGetFirstInGroup( nTpathGrpId)
|
|
while nCrvId do
|
|
EgtApproxCurve( nCrvId, GDB_CA.LINES, LayerParams.dLinearApproxTol)
|
|
nCrvId = EgtGetNext( nCrvId)
|
|
end
|
|
end
|
|
|
|
if bFirst and EgtGetGroupObjs( nTpathGrpId) > 0 then
|
|
bFirst = false
|
|
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( LayerParams)
|
|
|
|
-- setto info con numero di layers effettivi
|
|
EgtSetInfo( nPartId, KEY_LAYER_CNT, nLayCnt)
|
|
|
|
return true
|
|
end
|
|
|
|
---------------------------------------------------------------------
|
|
return CalcToolPath
|