Files
3dprinting/LuaLibs/CalcPaths.lua
T
SaraP 313e837f41 3dPrinting :
- modificato ordine di default per realizzazione setti ( unbounded fatti per primi).
2022-12-06 08:43:34 +01:00

1870 lines
75 KiB
Lua

-- CalcPaths.lua by Egaltech s.r.l. 2022/06/28
-- Calcolo percorsi di lavoro per Stampa 3d
-- Tabella per definizione modulo
local CalcPaths = {}
-- Intestazioni
require( 'EgtBase')
EgtOutLog( ' CalcPaths started', 1)
-- Dati
local AMD = require( 'AddManData')
---------------------------------------------------------------------
local s_nPartId
local s_dOffsCorr = 10 * GEO.EPS_SMALL
---------------------------------------------------------------------
local function GetLayerParamsForPathCalc()
local LayerParams = {}
LayerParams.bSpiralVase = EgtGetInfo( s_nPartId, KEY_SPIRAL_VASE, 'b') or false
LayerParams.nShellsNbr = EgtGetInfo( s_nPartId, KEY_SHELLS_NBR, 'i')
LayerParams.dStrand = EgtGetInfo( s_nPartId, KEY_STRAND, 'd')
LayerParams.nStrandOverlap = EgtGetInfo( s_nPartId, KEY_STRAND_OVERLAP, 'i') or 0
LayerParams.dOffs = EgtGetInfo( s_nPartId, KEY_OFFSET_SLICE, 'd')
LayerParams.nFloorNbr = EgtGetInfo( s_nPartId, KEY_FLOOR_NBR, 'i') or 0
LayerParams.nFloorType = EgtGetInfo( s_nPartId, KEY_FLOOR_TYPE, 'i') or INFILL_TYPE.ZIGZAG
LayerParams.nCeilNbr = EgtGetInfo( s_nPartId, KEY_CEIL_NBR, 'i') or 0
LayerParams.nCeilType = EgtGetInfo( s_nPartId, KEY_CEIL_TYPE, 'i') or INFILL_TYPE.ZIGZAG
LayerParams.vtSlicing = EgtGetInfo( s_nPartId, KEY_SLICING_DIR, 'v')
LayerParams.bPrintInvert = ( EgtGetInfo( s_nPartId, KEY_PRINT_DIRECTION, 'i') == PRINT_DIRECTION.CW)
-- parametri costolature
LayerParams.bRibsInvertOrder = EgtGetInfo( s_nPartId, KEY_RIBS_INVERT_ORDER, 'b')
LayerParams.bRibsDoLinkFirst = EgtGetInfo( s_nPartId, KEY_RIBS_DO_LINK_FIRST, 'b') or false
LayerParams.nRibsPrintOrder = EgtGetInfo( s_nPartId, KEY_RIBS_PRINT_ORDER, 'i') or 5
-- parametri regioni con diverse passate
LayerParams.dShellNbrCoasting = EgtGetInfo( s_nPartId, KEY_SHELL_NBR_COASTING, 'd')
LayerParams.dShellNbrWipe = EgtGetInfo( s_nPartId, KEY_SHELL_NBR_WIPE, 'd')
LayerParams.dShellNbrWipeDir = EgtGetInfo( s_nPartId, KEY_SHELL_NBR_WIPE_DIR, 'd')
-- eventuale modifica dei parametri per gestire correttamente il caso spiral vase
if LayerParams.bSpiralVase then
LayerParams.nShellsNbr = 1
LayerParams.nFloorNbr = 0
LayerParams.nCeilNbr = 0
end
return LayerParams
end
--------------------------------------------------------------------------------------------
local function CopyInfo( nSouId, nDestId, sInfo, sType)
local info = EgtGetInfo( nSouId, sInfo, sType)
EgtSetInfo( nDestId, sInfo, info)
end
----------------------------------------------------------------------
local function ComputeSurfOffset( nSrf, nGrpId, dOffs, vtSlicing)
-- gruppo temporaneo locale
local nGrpTmp = EgtGroup( nGrpId, Frame3d( ORIG(), vtSlicing, GDB_RT.GLOB))
local nCopySrf = EgtCopyGlob( nSrf, nGrpTmp) or GDB_ID.NULL
local bOk = EgtSurfFrOffset( nCopySrf, dOffs)
local bExists = EgtSurfFrChunkCount( nCopySrf) > 0
if not bOk or not bExists then
EgtErase( nCopySrf)
nCopySrf = EgtCopyGlob( nSrf, nGrpTmp) or GDB_ID.NULL
bOk = EgtSurfFrOffset( nCopySrf, dOffs + 0.05)
bExists = EgtSurfFrChunkCount( nCopySrf) > 0
end
EgtRelocateGlob( nCopySrf, nGrpId)
EgtErase( nGrpTmp)
return bOk, bExists, nCopySrf
end
---------------------------------------------------------------------
local function GetLayerStartPoint( nLayId, vtSlicing)
-- recupero quota layer
local dZ = EgtGetInfo( nLayId, KEY_SLICE_REAL_Z, 'd')
local dDeltaZ = EgtGetInfo( nLayId, KEY_SLICE_DELTAZ, 'd')
local frSlicing = Frame3d( ORIG(), vtSlicing)
local ptOn = Point3d( 0, 0, dZ + dDeltaZ)
ptOn:toGlob( frSlicing)
-- gruppo temporaneo dove salvo i risultati
local nGrpTmp = EgtGroup( nLayId)
local vPtStart = {}
local nMachStartGrp = EgtGetFirstNameInGroup( s_nPartId, LAY_MACH_START)
local nStartId = EgtGetFirstInGroup( nMachStartGrp)
while nStartId do
local nType = EgtGetType( nStartId)
-- se punto
if nType == GDB_TY.GEO_POINT then
table.insert( vPtStart, EgtSP( nStartId))
else
-- se curva interseco con il piano
local nId, nCnt = EgtPlaneCurveInters( ptOn, vtSlicing, nStartId, nGrpTmp, GDB_RT.GLOB)
if nId then
for i = nId, nId + nCnt - 1 do
table.insert( vPtStart, EgtSP( i))
end
end
end
nStartId = EgtGetNext( nStartId)
end
EgtErase( nGrpTmp)
return vPtStart
end
---------------------------------------------------------------------
local function ModifyStartPoint( nCrvId, vPtStart)
-- cerco lo start point più vicino tra quelli possibili
if vPtStart and #vPtStart > 0 then
local nMinIdx = -1
if #vPtStart == 1 then
nMinIdx = 1
else
local dMinDist = GEO.INFINITO
for i = 1, #vPtStart do
local dDist = EgtPointCurveDist( vPtStart[i], nCrvId)
if dDist < dMinDist - 10 * GEO.EPS_SMALL then
dMinDist = dDist
nMinIdx = i
end
end
end
EgtChangeClosedCurveStartPoint( nCrvId, vPtStart[nMinIdx])
end
end
---------------------------------------------------------------------
local function GetPathsFromSurf( nSrfId, sName, nType, nGrpId, vPtStart)
local vIds = {}
local nChunks = EgtSurfFrChunkCount( nSrfId)
for nC = 0, nChunks - 1 do
-- estraggo i contorni
local nCrvId, nCrvCnt = EgtExtractSurfFrChunkLoops( nSrfId, nC, nGrpId)
for nInd = 0, nCrvCnt - 1 do
EgtSetName( nCrvId + nInd, sName)
EgtSetInfo( nCrvId + nInd, KEY_TYPE, nType)
-- se è loop interno lo inverto per averlo orientato in senso antiorario
if nInd > 0 then
EgtInvertCurve( nCrvId + nInd)
end
-- verifico soddisfi i requisiti (lunghezza e area)
local dLen = EgtCurveLength( nCrvId + nInd)
local _ , _ , dArea = EgtCurveArea( nCrvId + nInd)
if dLen < MIN_LEN or dArea < MIN_AREA then
EgtErase( nCrvId + nInd)
return
end
table.insert( vIds, nCrvId + nInd)
ModifyStartPoint( nCrvId + nInd, vPtStart)
end
end
return vIds
end
----------------------------------------------------------------------
local function VerifyPath( nCrvId, dStrand, vtSlicing, nGrp)
local _, _, dArea = EgtCurveArea( nCrvId)
-- verifico se esiste l'offset (permetto una piccola sovrapposizione)
local dAllowedOverlap = 1
local nRes, nCnt = EgtOffsetCurveAdv( nCrvId, - dStrand / 2 + dAllowedOverlap)
-- se errore ritento con valore leggermente modificato
if not nRes then
nRes, nCnt = EgtOffsetCurveAdv( nCrvId, - dStrand / 2 + 0.05)
if not nRes then return false end
end
for j = nRes, nRes + nCnt - 1 do
EgtErase( j)
end
if nRes == GDB_ID.NULL or not dArea or dArea < GEO.EPS_SMALL then
-- verifico se fattibile con una sola passata
-- TODO da sistemare con medial axis per curva generica
local bSingleStrand = false
if EgtCurveIsClosed( nCrvId) then
local nGrpTmp = EgtGroup( nGrp, Frame3d( ORIG(), vtSlicing), GDB_RT.GLOB)
EgtRelocateGlob( nCrvId, nGrpTmp)
local frLoc, dDimX, dDimY = EgtCurveMinAreaRectangleXY( nCrvId)
if dDimY < 0.5 then
-- TODO curva generica
local dZ = EgtSP( nCrvId):getZ()
-- creo la curva che corrisponde alla sigola passata
local ptS = frLoc:getOrigin() - dDimX / 2 * frLoc:getVersX() + dZ * Z_AX()
local ptE = frLoc:getOrigin() + dDimX / 2 * frLoc:getVersX() + dZ * Z_AX()
if dist( ptS, ptE) > 5 then
local nId = EgtCurveCompoFromPoints( nGrpTmp, { ptS, ptE})
local sName = EgtGetName( nCrvId)
if sName then EgtSetName( nId, sName) end
local nType = EgtGetInfo( nCrvId, KEY_TYPE, 'i')
if nType then EgtSetInfo( nId, KEY_TYPE, nType) end
EgtErase( nCrvId)
EgtChangeId( nId, nCrvId)
bSingleStrand = true
end
end
EgtRelocateGlob( nCrvId, nGrp, GDB_IN.LAST_SON)
EgtErase( nGrpTmp)
end
-- se non è fattibile con unica passata lo cancello
if not bSingleStrand then
EgtErase( nCrvId)
return false
end
end
return true
end
-------------------------------------------------------------------
local function ComputeTrimSurfWithOverlaps( vIds, nSrfBase, sKeyOverlap, dStrand, nGrp, vtSlicing)
-- per ogni overlap creo le superfici con cui fare i trim
local vSurfOffs = {}
for i = 1, #vIds do
local nOverlap = EgtGetInfo( vIds[i], sKeyOverlap, 'i')
if not vSurfOffs[nOverlap] then
local dNewOffs = nOverlap / 100 * dStrand
local bOk, bExists, nSrfOffs = ComputeSurfOffset( nSrfBase, nGrp, dNewOffs, vtSlicing)
if bOk then
vSurfOffs[nOverlap] = nSrfOffs
end
end
end
return vSurfOffs
end
--------------------------------------------------------------------
--------------------- RIEMPIMENTI PIENI ----------------------------
--------------------------------------------------------------------
local function AdjustSurfForFloorCeil( nStrandDiff, nSrfTrim, nShellNbrSurfGrp)
if EgtSurfFrChunkCount( nSrfTrim) == 0 then return end
local nSurf = EgtCopyGlob( nSrfTrim, EgtGetParent( nSrfTrim))
if nShellNbrSurfGrp then
local nIdx = nStrandDiff
local nShellSurf = EgtGetFirstNameInGroup( nShellNbrSurfGrp, SHELL_NBR_SURF .. tostring( nIdx))
while nShellSurf do
EgtSurfFrSubtract( nSurf, nShellSurf)
nIdx = nIdx + 1
nShellSurf = EgtGetFirstNameInGroup( nShellNbrSurfGrp, SHELL_NBR_SURF .. tostring( nIdx))
end
end
return nSurf
end
--------------------------------------------------------------------
local function ReorderPath( vOldIds, vNewIds)
if not vNewIds then return end
if #vOldIds == 1 and #vNewIds == 1 then
EgtRelocateGlob( vNewIds[1], vOldIds[1], GDB_IN.AFTER)
return
end
-- associo ad ogni elemento di vOldIds gli elementi di vNewIds che contiene
local vOrdered = {}
if #vOldIds == 1 then
vOrdered[vOldIds[1]] = vNewIds
else
local nGrp = EgtGetParent( vOldIds[1])
-- creo le superifici a partire dalle curve in vOldIds
local vOldSurf = {}
for i = 1, #vOldIds do
local nSrf = EgtSurfFlatRegion( nGrp, {vOldIds[i]})
table.insert( vOldSurf, EgtIf( nSrf, nSrf, GDB_ID.NULL))
end
for i = 1, #vNewIds do
for j = 1, #vOldSurf do
if vOldSurf[j] ~= GDB_ID.NULL then
if not EgtSurfFrTestExternal( vOldSurf[j], vNewIds[i]) then
if vOrdered[vOldIds[j]] then
table.insert( vOrdered[vOldIds[j]], vNewIds[i])
else
vOrdered[vOldIds[j]] = {vNewIds[i]}
end
break
end
end
end
end
for i = 1, #vOldSurf do
EgtErase( vOldSurf[i])
end
end
-- riordino
for nParentIdx, vChildren in pairs( vOrdered) do
if #vChildren == 1 then
-- se racchiude solo una curva
EgtRelocateGlob( vChildren[1], nParentIdx, GDB_IN.AFTER)
else
EgtSpInit()
-- se racchiude più curve uso shortest path per ordinarle
for j = 1, #vChildren do
local pt = EgtGP( vChildren[j])
EgtSpAddPoint( pt:getX(), pt:getY(), pt:getZ(), 0, 0, pt:getX(), pt:getY(), pt:getZ(), 0, 0)
end
local ptS = EgtSP( nParentIdx)
EgtSpSetOpenBound( true, SHP_OB.NEAR_PNT, ptS:getX(), ptS:getY(), ptS:getZ(), 0, 0)
local vOrd, _ = EgtSpCalculate( SHP_TY.OPEN)
EgtSpTerminate()
for j = #vOrd, 1, -1 do
EgtRelocateGlob( vChildren[vOrd[j]], nParentIdx, GDB_IN.AFTER)
end
end
end
end
---------------------------------------------------------------------------
local function ComputeOffsetInfill( nSrf, dStrand, vtSlicing, sName, nType, vPtStart, nGrp)
local nChunk = EgtSurfFrChunkCount( nSrf)
if nChunk == 0 then return end
-- estraggo i contorni della superficie
local vOldIds = GetPathsFromSurf( nSrf, sName, nType, nGrp, vPtStart)
local dOffs = - dStrand
local bOk, bExists, nSrfOffs = ComputeSurfOffset( nSrf, nGrp, dOffs, vtSlicing)
while bOk and bExists do
-- estraggo i contorni
local vNewIds = GetPathsFromSurf( nSrfOffs, sName, nType, nGrp, vPtStart)
if vNewIds then
-- riordino
ReorderPath( vOldIds, vNewIds)
-- verifico fattibilità
local k = 1
while k <= #vNewIds do
if VerifyPath( vNewIds[k], dStrand, vtSlicing, nGrp) then
k = k + 1
else
-- se non è fattibile lo rimuovo dalla table per non ritrovarlo nello step successivo
table.remove( vNewIds, k)
end
end
vOldIds = vNewIds
end
EgtErase( nSrfOffs)
-- offset successivo
dOffs = dOffs - dStrand
bOk, bExists, nSrfOffs = ComputeSurfOffset( nSrf, nGrp, dOffs, vtSlicing)
end
end
--------------------------------------------------------------------------------
local function ComputeZigZagInfill( nSrf, dStrand, vtSlicing, sName, nType, vPtStart, nGrp)
local nChunk = EgtSurfFrChunkCount( nSrf)
if nChunk == 0 then return end
local nCopySrf = EgtCopyGlob( nSrf, nGrp)
if EgtSurfFrChunkCount( nSrf) == 0 then return end
local nFirst, nCnt = EgtExplodeSurf( nCopySrf)
local frLoc = Frame3d( ORIG(), vtSlicing)
local vIds = {}
for nId = nFirst, nFirst + nCnt - 1 do
local nGrpTmp = EgtGroup( nGrp, frLoc, GDB_RT.GLOB)
-- recupero outer curve
local nCrvGrpId = EgtGetParent( nGrp)
local nOuterCrv = EgtGetFirstNameInGroup( nCrvGrpId, OUTER_CRV)
local nCopyOuterCrv = EgtCopyGlob( nOuterCrv, nGrpTmp)
-- cerco il lato più lungo
local vCrvIds = GetPathsFromSurf( nId, 'Tmp', nType, nGrpTmp)
local dMaxLen = - GEO.INFINITO
local dDist = GEO.INFINITO
local vtDir
for j = 1, #vCrvIds do
local nId, nCnt = EgtExplodeCurveCompo( vCrvIds[j])
-- cerco il lato più lungo
for k = nId, nId + nCnt - 1 do
local dCurrLen = EgtCurveLength( k)
if dCurrLen > dMaxLen + GEO.EPS_SMALL then
dMaxLen = dCurrLen
end
end
-- tra i lati più lunghi scelgo quello più vicino al bordo
for k = nId, nId + nCnt - 1 do
local dCurrLen = EgtCurveLength( k)
if abs( dMaxLen - dCurrLen) < 10 then
local dCurrDist = EgtPointCurveDist( EgtMP( k), nCopyOuterCrv)
if dCurrDist < dDist + 10 * GEO.EPS_SMALL then
vtDir = EgtSV( k)
dDist = dCurrDist
end
end
end
end
EgtErase( nGrpTmp)
local _, _, dAng = SphericalFromVector( vtDir)
vtDir:toGlob( frLoc)
local nInd, nCnt = EgtGetSurfFrZigZagInfill( nId, nGrp, dStrand, dAng, false, false)
if not nInd then return end
for j = nInd, nInd + nCnt - 1 do
EgtSetName( j, sName)
EgtSetInfo( j, KEY_TYPE, nType)
EgtSetInfo( j, KEY_ZIG_ZAG_DIR, vtDir)
EgtSetInfo( j, KEY_ZIG_ZAG_INFILL, 1)
EgtModifyCurveExtrusion( j, vtSlicing, GDB_RT.GLOB)
table.insert( vIds, j)
end
local vtS = EgtSV( nInd)
EgtErase( nId)
end
end
-------------------------------------------------------------------
--------------------------- RIBS -----------------------------------
--------------------------------------------------------------------
local function ComputeTrimSurfWithOverlapsForRibs( vIds, nSrfBase, nSrfExt, dOffs, dStrand, nGrp, vtSlicing)
-- per ogni tipologia e overlap creo le superfici con cui fare i trim
local tSurfOffs = {{}, {}, {}}
for i = 1, #vIds do
local nOverlap = EgtGetInfo( vIds[i], KEY_RIBS_OVERLAP, 'i')
local nType = EgtGetInfo( vIds[i], KEY_RIBS_TYPE, 'i')
if not tSurfOffs[nType][nOverlap] then
if nType == RIB_TYPE.INTERNAL then
if nSrfBase then
local dNewOffs = nOverlap / 100 * dStrand
local bOk, bExists, nSrfOffs = ComputeSurfOffset( nSrfBase, nGrp, dNewOffs, vtSlicing)
if bOk then
tSurfOffs[nType][nOverlap] = nSrfOffs
end
end
elseif nType == RIB_TYPE.EXTERNAL then
if nSrfExt then
local dNewOffs = dOffs + ( 0.5 - nOverlap / 100) * dStrand
local bOk, bExists, nSrfOffs = ComputeSurfOffset( nSrfExt, nGrp, dNewOffs, vtSlicing)
if bOk then
tSurfOffs[nType][nOverlap] = nSrfOffs
EgtSetName( nSrfOffs, TOT_SHELL_TRIM_SURF)
end
end
else
tSurfOffs[nType][nOverlap] = GDB_ID.NULL
end
end
end
return tSurfOffs
end
--------------------------------------------------------------------
local function VerifyRibsIntersection( nRib1, nRib2, nType1, nType2, nSrf1, nSrf2, nGrp, nOffsGrp)
-- setti interni ed esterni non si possono intersecare per definizione
if ( nType1 == RIB_TYPE.INTERNAL and nType2 == RIB_TYPE.EXTERNAL) or ( nType1 == RIB_TYPE.EXTERNAL and nType2 == RIB_TYPE.INTERNAL) then
return false
end
-- se hanno lo stesso nome derivano dalla stessa costolatura quindi non ha senso controllare intersezione
if EgtGetName( nRib1) == EgtGetName( nRib2) then
return false
end
local bInters = false
local ptInt
-- porto le curve nel gruppo locale
local nCrv1 = EgtCopyGlob( nRib1, nGrp)
local nCrv2 = EgtCopyGlob( nRib2, nGrp)
-- verifico se si intersecano
ptInt = EgtIP( nCrv1, nCrv2, ORIG(), GDB_ID.ROOT)
-- se non si intersecano, verifico se si intersecano i loro offset
if not ptInt then
local bFound = false
local vOffs1 = EgtGetNameInGroup( nOffsGrp, EgtGetName( nCrv1))
local vOffs2 = EgtGetNameInGroup( nOffsGrp, EgtGetName( nCrv2))
for i = 1, #vOffs1 do
local nOffs1 = EgtCopyGlob( vOffs1[i], nGrp)
for j = 1, #vOffs2 do
-- porto nel gruppo locale e verifico se intersezione
local nOffs2 = EgtCopyGlob( vOffs2[j], nGrp)
ptInt = EgtIP( nOffs1, nOffs2, ORIG(), GDB_ID.ROOT)
if ptInt then
bFound = true
break
end
end
if bFound then break end
end
end
-- se intersezione verifico se valida
if ptInt then
local nPtId = EgtPoint( nGrp, ptInt, GDB_RT.GLOB)
if nType1 == RIB_TYPE.INTERNAL or nType2 == RIB_TYPE.INTERNAL then
-- l'intersezione deve essere interna
if nSrf1 and not EgtSurfFrTestExternal( nSrf1, nPtId) then bInters = true end
elseif nType1 == RIB_TYPE.EXTERNAL or nType2 == RIB_TYPE.EXTERNAL then
-- l'intersezione deve essere esterna
if nSrf2 and EgtSurfFrTestExternal( nSrf2, nPtId) then bInters = true end
else
-- nel caso unbounded l'intersezione può essere ovunque
bInters = true
end
end
return bInters, ptInt
end
---------------------------------------------------------------------------------
-- Funzione che sistema le intersezioni fra costolature nel caso generico
local function AdjustRibsOffsetForIntersection( nCrv1, nCrv2, LayerParams, nOffsGrp)
-- calcolo gli offset della curva principale ( nCrv1) da usare per trim
local nShells = EgtGetInfo( nCrv1, KEY_RIBS_SHELLS_NBR, 'i')
local nOverlap1 = EgtGetInfo( nCrv1, KEY_RIBS_OVERLAP, 'i')
local nOverlap2 = EgtGetInfo( nCrv2, KEY_RIBS_OVERLAP, 'i')
local nOverlap = min( nOverlap1, nOverlap2)
local dOffs = ( nShells - 1) * LayerParams.dStrand / 2
local nSrf = EgtSurfFrFatCurve( nOffsGrp, nCrv1, dOffs + ( 1 - nOverlap / 100) * LayerParams.dStrand, false)
if not nSrf then return end
-- trim degli offset della curva secondaria ( nCrv2)
local vOffs2 = EgtGetNameInGroup( nOffsGrp, EgtGetName( nCrv2)) or {}
for i = 1, #vOffs2 do
local nId, nCnt = EgtTrimCurveWithRegion( vOffs2[i], nSrf, false, true)
EgtChangeId( nId, vOffs2[i])
-- aggiorno ordine di split copiandolo da nCrv2
CopyInfo( nCrv2, vOffs2[i], KEY_SPLIT_ORDER, 'i')
if nCnt > 1 then
EgtSetInfo( nId + 1, KEY_SPLIT_RIB, vOffs2[i]) -- curva da cui deriva
CopyInfo( nCrv2, nId + 1, KEY_SPLIT_ORDER, 'i') -- ordine di split
EgtRelocateGlob( nId + 1, nOffsGrp, GDB_IN.LAST_SON)
end
end
EgtErase( nSrf)
end
--------------------------------------------------------------------
-- Funzione che sistema le intersezioni fra costolature nel caso di 2 passate
local function AdjustRibsOffsetForIntersection2Shells( nCrv1, nCrv2, LayerParams, nOffsGrp)
-- costruisco le superfici da usare per trim
local nSrf1 = EgtSurfFrFatCurve( nOffsGrp, nCrv1, LayerParams.dStrand / 2, false)
local vtN1 = EgtSurfFrNormVersor( nSrf1, GDB_ID.ROOT)
if LayerParams.vtSlicing * vtN1 < 0 then
EgtInvertSurf( nSrf1)
end
local nSrf2 = EgtSurfFrFatCurve( nOffsGrp, nCrv2, LayerParams.dStrand / 2, false)
local vtN2 = EgtSurfFrNormVersor( nSrf2, GDB_ID.ROOT)
if LayerParams.vtSlicing * vtN2 < 0 then
EgtInvertSurf( nSrf2)
end
-- trim degli offset di nCrv1
local vOffs1 = EgtGetNameInGroup( nOffsGrp, EgtGetName( nCrv1))
for i = 1, #vOffs1 do
local nId, nCnt = EgtTrimCurveWithRegion( vOffs1[i], nSrf2, false, true)
end
-- trim degli offset di nCrv2
local vOffs2 = EgtGetNameInGroup( nOffsGrp, EgtGetName( nCrv2))
for i = 1, #vOffs2 do
local nId, nCnt = EgtTrimCurveWithRegion( vOffs2[i], nSrf1, false, true)
end
EgtErase( nSrf1)
EgtErase( nSrf2)
end
------------------------------------------------------------------
local function UpdateSplitOrder( nCrv, tInters, nOffsGrp)
local nOrder = EgtGetInfo( nCrv, KEY_SPLIT_ORDER, 'i') or 0
local nNewOrder = nOrder + 1
-- aggiorno tutte le curve che dipendono da nCrv
if tInters[nCrv] then
for i = 1, #tInters[nCrv] do
local nOldOrder = EgtGetInfo( tInters[nCrv][i], KEY_SPLIT_ORDER, 'i')
if nOldOrder < nNewOrder then
EgtSetInfo( tInters[nCrv][i], KEY_SPLIT_ORDER, nNewOrder)
-- aggiorno i suoi offset
local vOffs = EgtGetNameInGroup( nOffsGrp, EgtGetName( tInters[nCrv][i]))
for j = 1, #vOffs do
EgtSetInfo( vOffs[j], KEY_SPLIT_ORDER, nNewOrder)
end
-- aggiorno eventuali dipendenze
UpdateSplitOrder( tInters[nCrv][i], tInters, nOffsGrp)
end
end
end
end
--------------------------------------------------------------------
local function HandleRibsIntersections( nRibsGrp, LayerParams, nOffsGrp, nRibsPathGrp, bAllTwoStrands)
local vRibsIds = EgtGetNameInGroup( nRibsGrp, RIBS_CRV .. '*')
-- copio gli offset delle costolature nel RibsPathGrp
local nCrvGrp = EgtGetParent( nRibsPathGrp)
local vOffsRib = EgtGetAllInGroup( nOffsGrp)
for i = 1, #vOffsRib do
EgtCopyGlob( vOffsRib[i], nRibsPathGrp)
end
-- creo un gruppo con frame locale per calcolare le intersezioni
local frLoc = Frame3d( ORIG(), LayerParams.vtSlicing)
local nGrpTmp = EgtGroup( nRibsGrp, frLoc, GDB_RT.GLOB)
-- calcolo le regioni nella quali ha senso considerare l'intersezione
local nSrfOffs1, nSrfOffs2
local bOk, bExists
local nSrf1 = EgtGetFirstNameInGroup( nCrvGrp, TOT_SHELL_TRIM_SURF)
if nSrf1 then
bOk, bExists, nSrfOffs1 = ComputeSurfOffset( nSrf1, nCrvGrp, 2 * LayerParams.dStrand, LayerParams.vtSlicing)
if not bOk or not bExists then
nSrfOffs1 = EgtCopyGlob( nSrf1, nCrvGrp)
end
end
local nSrf2 = EgtGetFirstNameInGroup( nCrvGrp, LAYER_SRF)
if nSrf2 then
bOk, bExists, nSrfOffs2 = ComputeSurfOffset( nSrf2, nCrvGrp, - 2 * LayerParams.dStrand, LayerParams.vtSlicing)
if not bOk or not bExists then
nSrfOffs2 = EgtCopyGlob( nSrf2, nCrvGrp)
end
end
local bInters = false
local vSplit = {}
local tInters = {} -- tabella che tiene traccia delle intersezioni trovate
for i = 1, #vRibsIds do
local nType1 = EgtGetInfo( vRibsIds[i], KEY_RIBS_TYPE, 'i')
-- verifico se interseca uno dei setti successivi
for j = i + 1, #vRibsIds do
local nType2 = EgtGetInfo( vRibsIds[j], KEY_RIBS_TYPE, 'i')
local bRibInters, ptInt = VerifyRibsIntersection( vRibsIds[i], vRibsIds[j], nType1, nType2, nSrfOffs1, nSrfOffs2, nGrpTmp, nOffsGrp)
if bRibInters then
bInters = true
local dPar1 = EgtCurveParamAtPoint( vRibsIds[i], ptInt, GEO.EPS_SMALL, GDB_RT.GLOB)
local dPar2 = EgtCurveParamAtPoint( vRibsIds[j], ptInt, GEO.EPS_SMALL, GDB_RT.GLOB)
local _, dParE1 = EgtCurveDomain( vRibsIds[i])
local _, dParE2 = EgtCurveDomain( vRibsIds[j])
local nCrv1 = vRibsIds[i] -- curva principale che non viene tagliata
local nCrv2 = vRibsIds[j] -- curve secondaria da modificare
local nSplitOrder1 = EgtGetInfo( nCrv1, KEY_SPLIT_ORDER, 'i') or 0
local nSplitOrder2 = EgtGetInfo( nCrv2, KEY_SPLIT_ORDER, 'i') or 0
local bCrv1OnExtr = dPar1 and ( dPar1 < 10 * GEO.EPS_SMALL or abs( dPar1 - dParE1) < 10 * GEO.EPS_SMALL)
local bCrv2OnExtr = dPar2 and ( dPar2 < 10 * GEO.EPS_SMALL or abs( dPar2 - dParE2) < 10 * GEO.EPS_SMALL)
if ( dPar1 and not dPar2) or ( bCrv1OnExtr and not bCrv2OnExtr) then
nCrv1, nCrv2 = nCrv2, nCrv1
nSplitOrder1, nSplitOrder2 = nSplitOrder2, nSplitOrder1
else
-- prediligo setto già splittato più volte
if nSplitOrder1 > nSplitOrder2 then
nCrv1, nCrv2 = nCrv2, nCrv1
nSplitOrder1, nSplitOrder2 = nSplitOrder2, nSplitOrder1
end
end
-- aggiorno tabella delle intersezioni
if tInters[nCrv1] then
table.insert( tInters[nCrv1], nCrv2)
else
tInters[nCrv1] = {nCrv2}
end
-- aggiorno ordine di split
if nSplitOrder2 < nSplitOrder1 + 1 then
EgtSetInfo( nCrv2, KEY_SPLIT_ORDER, nSplitOrder1 + 1)
UpdateSplitOrder( nCrv2, tInters, nRibsPathGrp)
end
if bAllTwoStrands and ( nType1 == nType2) then
-- nel caso di 2 passate e stessa tipologia gestione speciale per creare unico percorso
AdjustRibsOffsetForIntersection2Shells( nCrv1, nCrv2, LayerParams, nRibsPathGrp)
else
AdjustRibsOffsetForIntersection( nCrv1, nCrv2, LayerParams, nRibsPathGrp)
end
end
end
end
EgtErase( nSrfOffs1)
EgtErase( nSrfOffs2)
EgtErase( nGrpTmp)
return bInters
end
--------------------------------------------------------------------
local function ShortestPathForRibs( vIds, nGrp, bInvertOrder)
if not vIds or #vIds == 0 then return end
-- se solo un setto ordinamento banale
if #vIds == 1 then
EgtRelocateGlob( vIds[1], nGrp, GDB_IN.LAST_SON)
return
elseif #vIds == 2 then
EgtRelocateGlob( vIds[1], nGrp, GDB_IN.LAST_SON)
EgtRelocateGlob( vIds[2], vIds[1], EgtIf( bInvertOrder, GDB_IN.BEFORE, GDB_IN.AFTER))
return
else
-- se più setti ordinamento con shortest path
EgtSpInit()
for i = 1, #vIds do
local pt = EgtMP( vIds[i], GDB_RT.GLOB)
EgtSpAddPoint( pt:getX(), pt:getY(), pt:getZ(), 0, 0, pt:getX(), pt:getY(), pt:getZ(), 0, 0)
end
local vOrd, dLen = EgtSpCalculate( SHP_TY.OPEN)
EgtSpTerminate()
EgtRelocateGlob( vIds[vOrd[1]], nGrp, GDB_IN.LAST_SON)
for i = 2, #vOrd do
EgtRelocateGlob( vIds[vOrd[i]], vIds[vOrd[i-1]], EgtIf( bInvertOrder, GDB_IN.BEFORE, GDB_IN.AFTER))
end
end
end
---------------------------------------------------------------------
-- Funzione che riordina le costolature nel caso generico
local function ReorderRibs( nGrp, bInvertOrder, bDoLinkFirst, dStrand, nMaxNbr, vTypeSequence)
local vIds = EgtGetNameInGroup( nGrp, RIBS_CRV .. '*')
if not vIds or #vIds == 0 then return end
-- raggruppo per tipologia
local tRibs = {{}, {}, {}}
for i = 1, #vIds do
local nType = EgtGetInfo( vIds[i], KEY_RIBS_TYPE, 'i')
table.insert( tRibs[nType], vIds[i])
end
-- riordino ogni tipologia con shortest path
local vSplitRibs = {}
for i = 1, 3 do
local nCurrType = vTypeSequence[i]
local tSplitOrder = {}
local nMax = -1
-- raggruppo i ribs
for j = 1, #tRibs[nCurrType] do
local nInfoSplit = EgtGetInfo( tRibs[nCurrType][j], KEY_SPLIT_RIB, 'i')
local nShells = EgtGetInfo( tRibs[nCurrType][j], KEY_RIBS_SHELLS_NBR, 'i')
if nInfoSplit and nShells == 1 then
-- se è ottenuto dalla divisione di una costolatura
table.insert( vSplitRibs, tRibs[nCurrType][j])
else
-- classifico in base all'ordine di split e al link
local nSplitOrder = EgtGetInfo( tRibs[nCurrType][j], KEY_SPLIT_ORDER, 'i') or 0
local bLink = EgtGetInfo( tRibs[nCurrType][j], KEY_RIBS_LINK, 'b') or false
if nSplitOrder > nMax then nMax = nSplitOrder end
if not tSplitOrder[nSplitOrder] then
tSplitOrder[nSplitOrder]= {{}, {}}
end
if bLink then
table.insert( tSplitOrder[nSplitOrder][2], tRibs[nCurrType][j])
else
table.insert( tSplitOrder[nSplitOrder][1], tRibs[nCurrType][j])
end
end
end
local bLinkFirst = bDoLinkFirst
-- riordino ogni ordine di split
for k = 0, nMax do
if tSplitOrder[k] then
ShortestPathForRibs( EgtIf( bLinkFirst, tSplitOrder[k][2], tSplitOrder[k][1]), nGrp, bInvertOrder)
ShortestPathForRibs( EgtIf( bLinkFirst, tSplitOrder[k][1], tSplitOrder[k][2]), nGrp, bInvertOrder)
-- eventuale aggiornamento di bLinkFirst per l'ordine successivo
if not ( ( not bLinkFirst and #tSplitOrder[k][2] == 0) or ( bLinkFirst and #tSplitOrder[k][1] == 0)) then
bLinkFirst = not bLinkFirst
end
end
end
end
-- sistemo nomi
local kMax = nMaxNbr + 1
local dTol = 500 * GEO.EPS_SMALL
for i = 1, nMaxNbr do
local vIds = EgtGetNameInGroup( nGrp, RIBS_CRV .. tostring(i)) or {}
for j = 2, #vIds do
local dDistS = EgtPointCurveDist( EgtSP( vIds[j]), vIds[j-1])
local dDistM = EgtPointCurveDist( EgtMP( vIds[j]), vIds[j-1])
local dDistE = EgtPointCurveDist( EgtEP( vIds[j]), vIds[j-1])
if abs( dDistS - dStrand) < dTol or abs( dDistM - dStrand) < dTol or abs( dDistE - dStrand) < dTol then
-- se le costolatura è vicina alla precedente avrà lo stesso nome
EgtSetName( vIds[j], EgtGetName( vIds[j-1]))
EgtRelocateGlob( vIds[j], vIds[j-1], GDB_IN.AFTER)
else
-- se la costolatura dista troppo dalla precedente le cambio il nome
EgtSetName( vIds[j], RIBS_CRV .. tostring( kMax))
kMax = kMax + 1
end
end
end
-- aggiusto tutte le costolature divise
for i = 1, #vSplitRibs do
local nPrevId = EgtGetInfo( vSplitRibs[i], KEY_SPLIT_RIB, 'i')
local bInverted = EgtGetInfo( vSplitRibs[i], KEY_INVERTED_CRV, 'b') or false
-- aggiungo come successiva alla costolatura da cui si è generata
EgtRelocateGlob( vSplitRibs[i], nPrevId, EgtIf( bInverted, GDB_IN.BEFORE, GDB_IN.AFTER))
-- se necessario rinomino
if EgtGetName( vSplitRibs[i]) == EgtGetName(nPrevId) then
EgtSetName( vSplitRibs[i], RIBS_CRV .. tostring( kMax))
kMax = kMax + 1
end
-- correggo le info per gestire correttamente nel calcolo toolpath
local nPrevInfo = EgtGetInfo( nPrevId, KEY_SPLIT_RIB, 'i')
if bInverted and not nPrevInfo then
EgtRemoveInfo( vSplitRibs[i], KEY_SPLIT_RIB)
EgtSetInfo( nPrevId, KEY_SPLIT_RIB, vSplitRibs[i])
end
end
end
--------------------------------------------------------------------------------------------
local function ReassignInfo( nCrv, nCnt, vOrig)
for nId = nCrv, nCrv + nCnt - 1 do
local ptS = EgtSP( nId)
local ptE = EgtEP( nId)
EgtSetInfo( nId, KEY_TYPE, TYPE.RIB)
local bStart = false
local bEnd = false
while not bStart and not bEnd do
-- scorro le curve originarie per capire da quali deriva
for i = 1, #vOrig do
local ptSOrig = EgtSP( vOrig[i])
local ptEOrig = EgtEP( vOrig[i])
-- verifico se corrisponde al suo start
if AreSamePointApprox( ptS, ptSOrig) or AreSamePointApprox( ptS, ptEOrig) then
CopyInfo( vOrig[i], nId, KEY_RIBS_LEAD_IN_INVERT, 'b')
CopyInfo( vOrig[i], nId, KEY_RIBS_LEAD_IN_LEN, 'd')
CopyInfo( vOrig[i], nId, KEY_ASSOCIATED_SURF, 'i')
CopyInfo( vOrig[i], nId, KEY_RIBS_OVERLAP, 'i')
CopyInfo( vOrig[i], nId, KEY_RIBS_TYPE, 'i')
bStart = true
end
-- verifico se corrisponde al suo end
if AreSamePointApprox( ptE, ptSOrig) or AreSamePointApprox( ptE, ptEOrig) then
CopyInfo( vOrig[i], nId, KEY_RIBS_LEAD_OUT_INVERT, 'b')
CopyInfo( vOrig[i], nId, KEY_RIBS_LEAD_OUT_LEN, 'd')
CopyInfo( vOrig[i], nId, KEY_RIBS_LEAD_OUT_COASTING, 'd')
CopyInfo( vOrig[i], nId, KEY_RIBS_LEAD_OUT_WIPE, 'd')
CopyInfo( vOrig[i], nId, KEY_RIBS_LEAD_OUT_WIPE_DIR, 'd')
bEnd = true
end
end
end
end
-- dopo aver salvato le info è inutile conservare le curve originali
for i = 1, #vOrig do
EgtErase( vOrig[i])
end
end
---------------------------------------------------------------------------------------------
-- Funzione che riordina le costolature nel caso di intersezioni e 2 passate
local function ReorderRibsInters2Shells( nOffsGrp, dStrand, vTypeSequence)
local vOffs = EgtGetNameInGroup( nOffsGrp, RIBS_CRV .. '*')
-- copio le curve originali ( per recuperarne le info)
local vCopy = {}
for i = 1, #vOffs do
local nNewId = EgtCopy( vOffs[i], nOffsGrp)
table.insert( vCopy, nNewId)
end
-- concateno le curve
local nCrv, nCnt = EgtCurveCompoByChain( nOffsGrp, vOffs, ORIG())
local vIds = {}
for i = nCrv, nCrv + nCnt - 1 do
table.insert( vIds, i)
end
-- recupero le info dalle curve originali
ReassignInfo( nCrv, nCnt, vCopy)
local k = 0 -- indice da utilizzare per i nomi
while #vIds > 0 do
k = k + 1
-- prendo la prima tra le curve a disposizione
nCurrCrv = vIds[1]
table.remove( vIds, 1)
EgtSetName( nCurrCrv, RIBS_CRV .. tostring(k))
local pt = EgtEP( nCurrCrv)
local _, dParE = EgtCurveDomain( nCurrCrv)
local nCnt = 0
-- scorro alla ricerca di una curva che posso collegare alla corrente
while nCurrCrv do
local nCurrType = EgtGetInfo( nCurrCrv, KEY_RIBS_TYPE, 'i')
local bFound = false
for j = 1, #vIds do
local nType = EgtGetInfo( vIds[j], KEY_RIBS_TYPE, 'i')
if vIds[j] ~= nCrv and not EgtCurveIsClosed(vIds[j]) and nCurrType == nType then
-- verifico se il collegamento è possibile
local bAdd = false
local bInvert = false
local dDist, _, dParMinDist = EgtPointCurveDist( pt, vIds[j])
if dDist < dStrand + 10 * GEO.EPS_SMALL then
-- controllo che sia vicino ad uno degli estremi
local dParS, dParE = EgtCurveDomain( vIds[j])
if abs( dParMinDist - dParS) < 500 * GEO.EPS_SMALL then
bAdd = true
elseif abs( dParMinDist - dParE) < 500 * GEO.EPS_SMALL then
bAdd = true
-- è se necessaria inversione di vIds[j]
bInvert = true
end
end
if not bAdd then
-- check sullo start point di vIds[j]
local dDist, _, dParMinDist = EgtPointCurveDist( EgtSP( vIds[j]), nCurrCrv)
if dDist < dStrand + 10 * GEO.EPS_SMALL then
bInvert = false
-- controllo sia vicino all'end point della curva corrente
if dParE - dParMinDist < 500 * GEO.EPS_SMALL then
bAdd = true
-- altrimenti può essere vicino allo start
elseif dParMinDist < 500 * GEO.EPS_SMALL and nCnt == 0 then
bAdd = true
EgtInvertCurve( nCurrCrv)
end
end
-- se non è aggiunto check con end point di vIds[j]
if not bAdd then
local dDist, _, dParMinDist = EgtPointCurveDist( EgtEP( vIds[j]), nCurrCrv)
if dDist < dStrand + 10 * GEO.EPS_SMALL then
bInvert = true
if dParE - dParMinDist < 500 * GEO.EPS_SMALL then
bAdd = true
elseif dParMinDist < 500 * GEO.EPS_SMALL and nCnt == 0 then
bAdd = true
EgtInvertCurve( nCurrCrv)
end
end
end
end
if bAdd then
bFound = true
nCnt = nCnt + 1
EgtRelocateGlob( vIds[j], nCurrCrv, GDB_IN.AFTER)
EgtSetName( vIds[j], RIBS_CRV .. tostring( k))
-- eventuale inversione della curva
if bInvert then EgtInvertCurve( vIds[j]) end
-- aggiorno per collegamento successivo
pt = EgtEP( vIds[j])
_, dParE = EgtCurveDomain( vIds[j])
nCurrCrv = vIds[j]
-- elimino la curva dal vettore di curve da considerare
table.remove( vIds, j)
break
end
end
end
-- se non ho più curve da collegare
if not bFound and nCnt == 0 then
-- se era la prima curva faccio un tentativo invertendola
nCnt = 1
EgtInvertCurve( nCurrCrv)
pt = EgtEP( nCurrCrv)
elseif not bFound then
nCurrCrv = nil
end
end
end
-- classifico in base alla tipologia
local vCrvs = EgtGetNameInGroup( nOffsGrp, RIBS_CRV .. '*')
local tRibs = {{}, {}, {}}
for nId = 1, #vCrvs do
local nType = EgtGetInfo( vCrvs[nId], KEY_RIBS_TYPE, 'i')
table.insert( tRibs[nType], vCrvs[nId])
end
-- riordino per tipologia
for i = 1, 3 do
nCurrType = vTypeSequence[i]
for j = 1, #tRibs[nCurrType] do
EgtRelocateGlob( tRibs[nCurrType][j], nOffsGrp, GDB_IN.LAST_SON)
end
end
end
-------------------------------------------------------------------
local function UpdateRibSplitInfo( nGrp, tIds, tRemoved)
local vIds = EgtGetNameInGroup( nGrp, RIBS_CRV .. '*')
if not vIds then return end
for i = 1, #vIds do
-- info SplitRib
local nInfo = EgtGetInfo( vIds[i], KEY_SPLIT_RIB, 'i')
if nInfo then
-- verifico se va aggiornata ereditandola da rib che sono stati eliminati per vincolo sulla lunghezza
while tRemoved[nInfo] do
nInfo = tRemoved[nInfo]
end
if tIds[nInfo] and #tIds[nInfo] > 0 then
-- aggiorno info con nuovo id della costolatura da cui deriva
local nLast = #tIds[nInfo]
EgtSetInfo( vIds[i], KEY_SPLIT_RIB, tIds[nInfo][nLast])
else
-- se la costolatura da cui deriva è stata eliminata, tolgo l'info che le associava
EgtRemoveInfo( vIds[i], KEY_SPLIT_RIB)
end
end
end
end
--------------------------------------------------------------------
local function CalcRibsPaths( nSliceGrp, nRibsGrp, LayerParams, nIdx)
local vRibs = EgtGetNameInGroup( nRibsGrp, RIBS_CRV .. '*')
-- verifico se tutte le costolature vengono fatte con 2 passate
local bAllTwoStrands = true
for i = 1, #vRibs do
local nStrand = EgtGetInfo( vRibs[i], KEY_RIBS_SHELLS_NBR, 'i')
if nStrand ~= 2 then
bAllTwoStrands = false
break
end
end
local nLast = EgtGetLastNameInGroup( nRibsGrp, RIBS_CRV .. '*')
local sLastName = EgtGetName( nLast)
local nMaxNbr = tonumber( string.sub( sLastName, 4))
-- calcolo gli offset
local nOffsGrp = EgtGroup( nRibsGrp)
for i = 1, #vRibs do
local nShellsNbr = EgtGetInfo( vRibs[i], KEY_RIBS_SHELLS_NBR, 'i')
local dOffs = ( nShellsNbr - 1) * LayerParams.dStrand / 2
for k = 0, nShellsNbr - 1 do
local nNewId = EgtOffsetCurveAdv( vRibs[i], - dOffs + k * LayerParams.dStrand)
EgtSetName( nNewId, EgtGetName( vRibs[i]))
EgtSetInfo( nNewId, KEY_TYPE, TYPE.RIB)
EgtRelocateGlob( nNewId, nOffsGrp)
end
end
-- scorro i gruppi di curve
local dOffs = 0.5 * LayerParams.dStrand - LayerParams.dOffs + ( LayerParams.nShellsNbr - 1) * LayerParams.dStrand
local nCrvGrp = EgtGetFirstNameInGroup( nSliceGrp, CONTOUR_GRP .. '*')
while nCrvGrp do
-- creo o svuoto il gruppo
local nRibsPathGrp = EgtGetFirstNameInGroup( nCrvGrp, RIBS_GRP)
if not nRibsPathGrp then
nRibsPathGrp = EgtGroup( nCrvGrp)
EgtSetName( nRibsPathGrp, RIBS_GRP)
EgtSetStatus( nRibsPathGrp, GDB_ST.OFF)
else
EgtEmptyGroup( nRibsPathGrp)
end
-- creo le superfici con cui fare i trim
local nSrfBase = EgtGetFirstNameInGroup( nCrvGrp, TOT_SHELL_TRIM_SURF)
local nSrfExt = EgtGetFirstNameInGroup( nCrvGrp, LAYER_SRF)
local tSurfOffs = ComputeTrimSurfWithOverlapsForRibs( vRibs, nSrfBase, nSrfExt, LayerParams.dOffs, LayerParams.dStrand, nRibsPathGrp, LayerParams.vtSlicing)
-- gestisco eventuali intersezioni fra costolature
local bInters = HandleRibsIntersections( nRibsGrp, LayerParams, nOffsGrp, nRibsPathGrp, bAllTwoStrands)
EgtSetInfo( nRibsPathGrp or GDB_ID.NULL, KEY_RIBS_INTERS, bInters)
EgtSetInfo( nRibsPathGrp or GDB_ID.NULL, KEY_RIBS_TWO_STRANDS, bAllTwoStrands)
-- eseguo il trim delle costole con la regione offsettata
local tOldNewIds = {}
local tRemoved = {}
local vOrderedRibs = EgtGetNameInGroup( nRibsPathGrp, RIBS_CRV ..'*')
for i = 1, #vOrderedRibs do
-- trim con superficie opportuna
local nOverlap = EgtGetInfo( vOrderedRibs[i], KEY_RIBS_OVERLAP, 'i')
local nType = EgtGetInfo( vOrderedRibs[i], KEY_RIBS_TYPE, 'i')
if not tSurfOffs[nType][nOverlap] then
-- la costolatura non è fattibile
EgtOutLog( 'Warning: Ribs not possibile (layer '..tostring( nIdx)..') - CalcPaths')
EgtErase( vOrderedRibs[i])
else
local nCrv, nCnt
if tSurfOffs[nType][nOverlap] == GDB_ID.NULL then
-- caso unbounded
nCrv = vOrderedRibs[i]
nCnt = 1
else
nCrv, nCnt = EgtTrimCurveWithRegion( vOrderedRibs[i], tSurfOffs[nType][nOverlap], EgtIf( nType == RIB_TYPE.INTERNAL, true, false), false)
end
tOldNewIds[ vOrderedRibs[i]] = {}
-- elimino tratti troppo corti
for nInd = 0, nCnt - 1 do
local dLen = EgtCurveLength( nCrv + nInd)
if dLen < MIN_RIBS_LEN then
-- conservo eventuale info di split
local nSplitRib = EgtGetInfo( nCrv + nInd, KEY_SPLIT_RIB, 'i')
if nSplitRib then
tRemoved[vOrderedRibs[i]] = nSplitRib
end
-- cancello la curva
EgtErase( nCrv + nInd)
else
table.insert( tOldNewIds[ vOrderedRibs[i]], nCrv + nInd)
-- controllo la direzione (consideriamo inclinazione solo lungo X)
local vtDir = EgtMV( nCrv + nInd)
local dXl = sqrt( sqr( vtDir:getX()) + sqr( vtDir:getZ()))
local dYl = abs( vtDir:getY())
local dVal = EgtIf( dXl > dYl - GEO.EPS_SMALL, vtDir:getX(), vtDir:getY())
local bInvert = dVal < - GEO.EPS_SMALL
-- inversione della curva
local bInvertInfo = EgtGetInfo( nCrv + nInd, KEY_RIBS_INVERT_DIR, 'b') or false
if bInvert ~= bInvertInfo then
EgtInvertCurve( nCrv + nInd)
EgtSetInfo( nCrv + nInd, KEY_INVERTED_CRV, 1)
end
-- salvo info della superficie di trim associata
EgtSetInfo( nCrv + nInd, KEY_ASSOCIATED_SURF, tSurfOffs[nType][nOverlap])
if nInd > 0 then
EgtRemoveInfo( nCrv + nInd, KEY_SPLIT_RIB)
end
end
end
end
end
-- aggiorno le info di split con i nuovi id
UpdateRibSplitInfo( nRibsPathGrp, tOldNewIds, tRemoved)
-- stabilisco ordine di realizzazione delle varie tipologie
local vTypeSequence = {RIB_TYPE.INTERNAL, RIB_TYPE.EXTERNAL, RIB_TYPE.UNBOUNDED}
if LayerParams.nRibsPrintOrder == RIB_PRINT_ORDER.INT_UNBDD_EXT then
vTypeSequence = {RIB_TYPE.INTERNAL, RIB_TYPE.UNBOUNDED, RIB_TYPE.EXTERNAL}
elseif LayerParams.nRibsPrintOrder == RIB_PRINT_ORDER.EXT_INT_UNBDD then
vTypeSequence = {RIB_TYPE.EXTERNAL, RIB_TYPE.INTERNAL, RIB_TYPE.UNBOUNDED}
elseif LayerParams.nRibsPrintOrder == RIB_PRINT_ORDER.EXT_UNBDD_INT then
vTypeSequence = {RIB_TYPE.EXTERNAL, RIB_TYPE.UNBOUNDED, RIB_TYPE.INTERNAL}
elseif LayerParams.nRibsPrintOrder == RIB_PRINT_ORDER.UNBDD_INT_EXT then
vTypeSequence = {RIB_TYPE.UNBOUNDED, RIB_TYPE.INTERNAL, RIB_TYPE.EXTERNAL}
elseif LayerParams.nRibsPrintOrder == RIB_PRINT_ORDER.UNBDD_EXT_INT then
vTypeSequence = {RIB_TYPE.UNBOUNDED, RIB_TYPE.EXTERNAL, RIB_TYPE.INTERNAL}
end
-- riordino le costolature
if bAllTwoStrands and bInters then
-- gestione caso speciale di intersezione e 2 passate
ReorderRibsInters2Shells( nRibsPathGrp, LayerParams.dStrand, vTypeSequence)
else
ReorderRibs( nRibsPathGrp, LayerParams.bRibsInvertOrder, LayerParams.bRibsDoLinkFirst, LayerParams.dStrand, nMaxNbr, vTypeSequence)
end
if not EgtGetFirstNameInGroup( nRibsPathGrp, RIBS_CRV .. '*') then
EgtErase( nRibsPathGrp)
end
nCrvGrp = EgtGetNextName( nCrvGrp, CONTOUR_GRP .. '*')
end
end
--------------------------------------------------------------------
----------------- REGIONI CON DIVERSE PASSATE ----------------------
--------------------------------------------------------------------
local function CreateShellNbrSurfaces( nGrp, nShellsNbr)
if not nGrp then return end
local tDiffCrvs = {}
local nMaxShellNbrDiff = 0
local nCrvId = EgtGetFirstNameInGroup( nGrp, SHELL_NBR_CRV .. '*')
while nCrvId do
if EgtCurveIsClosed( nCrvId) then
-- recupero info sul gap
local nShellNbrDiff = EgtGetInfo( nCrvId, KEY_SHELL_NBR_DIFF, 'i')
-- aggiorno eventuale massimo
if nMaxShellNbrDiff < nShellNbrDiff then nMaxShellNbrDiff = nShellNbrDiff end
-- salvo gli id delle curve
if not tDiffCrvs[nShellNbrDiff] then
tDiffCrvs[nShellNbrDiff] = { nCrvId}
else
table.insert( tDiffCrvs[nShellNbrDiff], nCrvId)
end
end
nCrvId = EgtGetNextName( nCrvId, SHELL_NBR_CRV .. '*')
end
-- eventuale correzione del numero massimo in base al numero di passate
nMaxShellNbrDiff = min( nMaxShellNbrDiff, nShellsNbr)
-- costruisco per ogni valore la superficie complessiva
local nSrfGrp = EgtGroup( nGrp)
for nDiff = 1, nMaxShellNbrDiff do
-- recupero gli id delle curve coinvolte
local vCrvIds = {}
for nG, vIds in pairs( tDiffCrvs) do
if nG >= nDiff then
for k = 1, #vIds do
table.insert( vCrvIds, vIds[k])
end
end
end
-- costruisco la surf
local nSrfId = EgtSurfFlatRegion( nSrfGrp, vCrvIds[1])
for i = 2, #vCrvIds do
local nSrfTmp = EgtSurfFlatRegion( nSrfGrp, vCrvIds[i])
EgtSurfFrAdd( nSrfId, nSrfTmp)
EgtErase( nSrfTmp)
end
EgtSetName( nSrfId, SHELL_NBR_SURF .. tostring( nDiff))
-- salvo come info gli id delle curve che la definiscono
EgtSetInfo( nSrfId, KEY_ASSOCIATED_CRVS, vCrvIds)
end
end
--------------------------------------------------------------------
local function ComputeMaxShellNbrDiff( nSrf, nShellNbrSurfGrp)
local nMaxShellNbrDiff = 0
if nShellNbrSurfGrp then
local nId = 1
local nShellNbrSrf = EgtGetFirstNameInGroup( nShellNbrSurfGrp, SHELL_NBR_SURF .. tostring( nId))
while nShellNbrSrf do
-- se interessa la regione considerata aggiorno il nMaxShellNbrDiff
if not EgtSurfFrTestExternal( nSrf, nShellNbrSrf) then
nMaxShellNbrDiff = nId
end
-- passo al successivo
nId = nId + 1
nShellNbrSrf = EgtGetFirstNameInGroup( nShellNbrSurfGrp, SHELL_NBR_SURF .. tostring( nId))
end
end
return nMaxShellNbrDiff
end
----------------------------------------------------------------
local function FindExtraShellRetractionParams( ptP, vIds, LayerParams)
local dCoasting, dWipe, dWipeDir
-- cerco la curva sulla quale si ferma
for i = 1, #vIds do
local dPar = EgtCurveParamAtPoint( vIds[i], ptP, 10 * GEO.EPS_SMALL)
if dPar then
dCoasting = EgtGetInfo( vIds[i], KEY_SHELL_NBR_COASTING, 'd')
dWipe = EgtGetInfo( vIds[i], KEY_SHELL_NBR_WIPE, 'd')
dWipeDir = EgtGetInfo( vIds[i], KEY_SHELL_NBR_WIPE_DIR, 'd')
break
end
end
if not dCoasting then
-- se non ho trovato una curva considero i parametri generali
return LayerParams.dShellNbrCoasting, LayerParams.dShellNbrWipe, LayerParams.dShellNbrWipeDir
else
return dCoasting, dWipe, dWipeDir
end
end
-----------------------------------------------------------------
local function TrimOuterCurveForExtraShellCalc( nOuterCrv, nSrfDiff, nGrpId, vPtStart, LayerParams)
local nCopy = EgtCopyGlob( nOuterCrv, nGrpId)
ModifyStartPoint( nCopy, vPtStart)
-- recupero tutte le curve delle ShellNumber coinvolte
local vShellNbrCrvs = EgtGetInfo( nSrfDiff, KEY_ASSOCIATED_CRVS, 'vi')
-- trim della curva
local nCrv, nCnt = EgtTrimCurveWithRegion( nCopy, nSrfDiff, false, false)
if nCrv and nCnt ~= 0 then
-- verifico se prima e ultima curva possono essere unite
if nCnt > 1 and AreSamePointApprox( EgtEP( nCrv + nCnt - 1), EgtSP( nCrv)) then
local nNewId = EgtCurveCompo( nGrpId, { nCrv + nCnt - 1, nCrv})
EgtChangeId( nNewId, nCrv)
nCnt = nCnt - 1
end
-- assegno le info in base alla curva che li delimita
for nId = nCrv, nCrv + nCnt - 1 do
local ptS = EgtSP( nId)
local dCoastingS, dWipeS, dWipeDirS = FindExtraShellRetractionParams( ptS, vShellNbrCrvs, LayerParams)
local ptE = EgtEP( nId)
local dCoastingE, dWipeE, dWipeDirE = FindExtraShellRetractionParams( ptE, vShellNbrCrvs, LayerParams)
EgtSetInfo( nId, KEY_EXTRA_SHELL_COASTING, {dCoastingS, dCoastingE})
EgtSetInfo( nId, KEY_EXTRA_SHELL_WIPE, {dWipeS, dWipeE})
EgtSetInfo( nId, KEY_EXTRA_SHELL_WIPE_DIR, {dWipeDirS, dWipeDirE})
end
return nCrv, nCnt
else
return nOuterCrv, 0
end
end
--------------------------------------------------------------------
local function UpdateTotalShellSurf( nSrf, nCrv, dStrand, nGrpId)
local nSrfExtraShell = EgtSurfFrFatCurve( nGrpId, nCrv, dStrand - s_dOffsCorr, false)
if nSrfExtraShell then
local vtSrfN = EgtSurfFrNormVersor( nSrf, GDB_ID.ROOT)
local vtSrfExShN = EgtSurfFrNormVersor( nSrfExtraShell, GDB_ID.ROOT)
if vtSrfExShN * vtSrfN < 0 then
EgtInvertSurf( nSrfExtraShell)
end
EgtSurfFrSubtract( nSrf, nSrfExtraShell)
EgtErase( nSrfExtraShell)
end
end
---------------------------------------------------------------------
local function ReorderExtraShells( nPathGrp, dStrand, vPtStart, bPrintInvert)
-- verifico se posso unire due tratti consecutivi della stessa shell
local nFirst = EgtGetFirstNameInGroup( nPathGrp, EXTRA_SHELL_CRV .. '*')
while nFirst do
-- recupero tratti appartenenti alla stessa shell
local vShells = EgtGetNameInGroup( nPathGrp, EgtGetName( nFirst))
local nCurr = vShells[1]
for i = 2, #vShells do
if dist( EgtEP( nCurr), EgtSP( vShells[i])) < dStrand + GEO.EPS_SMALL then
-- unisco le curve
EgtAddCurveCompoLine( nCurr, EgtSP( vShells[i]))
EgtAddCurveCompoCurve( nCurr, vShells[i])
else
nCurr = vShells[i]
end
end
-- check su prima e ultima curva
if nCurr ~= nFirst and dist( EgtEP( nCurr), EgtSP( nFirst)) < dStrand + GEO.EPS_SMALL then
-- unisco le curve
EgtAddCurveCompoLine( nCurr, EgtSP( nFirst))
EgtAddCurveCompoCurve( nCurr, nFirst)
end
nFirst = EgtGetNextName( nCurr, EXTRA_SHELL_CRV .. '*')
end
local vIds = EgtGetNameInGroup( nPathGrp, EXTRA_SHELL_CRV .. '*')
if not vIds then return end
-- eventuale inversione di tutte le curve
if bPrintInvert then
for i = 1, #vIds do
EgtInvertCurve( vIds[i])
EgtSetInfo( vIds[i], KEY_INVERTED_CRV, 1)
end
end
-- cerco di creare percorsi
local k = 0 -- indice da utilizzare per i nomi
while #vIds > 0 do
k = k + 1
-- prendo la prima tra le curve a disposizione
nCurrCrv = vIds[1]
table.remove( vIds, 1)
EgtSetName( nCurrCrv, EXTRA_SHELL_CRV .. tostring(k))
local ptSCurr = EgtSP( nCurrCrv)
local ptECurr = EgtEP( nCurrCrv)
local nCnt = 0
-- se curva è chiusa
if EgtCurveIsClosed( nCurrCrv) then
ModifyStartPoint( nCurrCrv, vPtStart)
-- setto a nil per ripartire subito con curva successiva
nCurrCrv = nil
end
-- scorro alla ricerca di una curva che posso collegare alla corrente
while nCurrCrv do
local bFound = false
for j = 1, #vIds do
if not EgtCurveIsClosed( vIds[j]) then
local ptS = EgtSP( vIds[j])
local ptE = EgtEP( vIds[j])
local bLink = dist( ptS, ptECurr) < 1.5 * dStrand
if dist( ptE, ptECurr) < 1.5 * dStrand then
-- congiungo end-end
EgtInvertCurve( vIds[j])
EgtSetInfo( vIds[j], KEY_INVERTED_CRV, EgtIf( bPrintInvert, 0, 1))
bLink = true
elseif nCnt == 0 and dist( ptS, ptSCurr) < 1.5 * dStrand then
-- congiungo start-start
EgtInvertCurve( nCurrCrv)
EgtSetInfo( nCurrCrv, KEY_INVERTED_CRV, EgtIf( bPrintInvert, 0, 1))
bLink = true
end
if bLink then
nCnt = nCnt + 1
EgtRelocateGlob( vIds[j], nCurrCrv, GDB_IN.AFTER)
EgtSetName( vIds[j], EXTRA_SHELL_CRV .. tostring( k))
-- aggiorno per collegamento successivo
bFound = true
nCurrCrv = vIds[j]
ptSCurr = EgtSP( vIds[j])
ptECurr = EgtEP( vIds[j])
table.remove( vIds, j)
break
end
end
end
-- se non ho più curve da collegare
if not bFound then
nCurrCrv = nil
end
end
end
end
--------------------------------------------------------------------
local function CalcExtraShellsPath( nMaxShellNbrDiff, nShellNbrGrp, nCrvGrpId, dOffs, LayerParams, nIdx, vPtStart)
local nGrpId = EgtGetFirstNameInGroup( nCrvGrpId, PATH_GRP)
-- recupero la superficie occupata dalle shell per trim
local nSrfTrim = EgtGetFirstNameInGroup( nCrvGrpId, TOT_SHELL_TRIM_SURF)
if not nSrfTrim then
EgtOutLog( 'Warning : ExtraInnerShells not possible (layer '..tostring( nIdx)..') - CalcPaths')
return
end
for nInd = nMaxShellNbrDiff, 1, -1 do
dOffs = dOffs + LayerParams.dStrand * ( 1 - EgtIf( nInd == LayerParams.nShellsNbr, 0, LayerParams.nStrandOverlap / 100))
local nSrfDiff = EgtGetFirstNameInGroup( nShellNbrGrp, SHELL_NBR_SURF .. tostring( nInd))
local nOuterCrv = EgtGetFirstNameInGroup( nCrvGrpId, OUTER_CRV)
while nOuterCrv do
-- trim della curva con la superficie
local nTrimCrv, nTrimCnt = TrimOuterCurveForExtraShellCalc( nOuterCrv, nSrfDiff, nGrpId, vPtStart, LayerParams)
for nCrvT = nTrimCrv, nTrimCrv + nTrimCnt - 1 do
-- calcolo offset della curva ( è il percorso della shell)
EgtModifyCurveExtrusion( nCrvT, LayerParams.vtSlicing, GDB_RT.GLOB)
local nOffs, nOffsCnt = EgtOffsetCurveAdv( nCrvT, - dOffs)
EgtErase( nCrvT)
for nCrvOffs = nOffs, nOffs + nOffsCnt - 1 do
-- trim con la regione già occupata dal altre shell
local nCrv, nCnt = EgtTrimCurveWithRegion( nCrvOffs, nSrfTrim, true, true)
if nCrv and nCnt ~= 0 then
for nId = nCrv, nCrv + nCnt - 1 do
local dLen = EgtCurveLength( nId)
local bValid = true
if EgtCurveIsClosed( nId) then
bValid = VerifyPath( nId, LayerParams.dStrand, LayerParams.vtSlicing, nGrpId)
end
-- verifico se soddisfa vincolo sulla lunghezza
if dLen > MIN_LEN and bValid then
EgtModifyCurveExtrusion( nId, LayerParams.vtSlicing, GDB_RT.GLOB)
EgtSetName( nId, EXTRA_SHELL_CRV .. tostring( nMaxShellNbrDiff - nInd + 1))
if nInd == LayerParams.nShellsNbr then
EgtSetInfo( nId, KEY_TYPE, TYPE.EXTRA_OUTER_SHELL)
else
EgtSetInfo( nId, KEY_TYPE, TYPE.EXTRA_SHELL)
end
-- aggiorno la superficie occupata dalle shell con quella appena calcolata (tenendo conto dell'overlap)
UpdateTotalShellSurf( nSrfTrim, nId, ( 1 - LayerParams.nStrandOverlap / 100) * LayerParams.dStrand, nGrpId)
-- se la superficie si annulla non è possibile realizzare altro, quindi cancello tutte le curve rimaste
if EgtSurfFrChunkCount( nSrfTrim) == 0 then
for j = nId + 1, nCrv + nCnt - 1 do
EgtErase( j)
end
for j = nCrvT + 1, nTrimCrv + nTrimCnt - 1 do
EgtErase( j)
end
-- aggiorno superficie
EgtSurfFrOffset( nSrfTrim, - LayerParams.nStrandOverlap / 100 * LayerParams.dStrand)
-- riordino le curve appena create e se possibile creo percorsi chiusi
ReorderExtraShells( nGrpId, LayerParams.dStrand, vPtStart, LayerParams.bPrintInvert)
return
end
else
EgtErase( nId)
end
end
end
end
end
nOuterCrv = EgtGetNextName( nOuterCrv, OUTER_CRV)
end
end
-- aggiorno superificie
EgtSurfFrOffset( nSrfTrim, - LayerParams.nStrandOverlap / 100 * LayerParams.dStrand)
-- riordino le curve appena create e se possibile creo percorsi chiusi
ReorderExtraShells( nGrpId, LayerParams.dStrand, vPtStart, LayerParams.bPrintInvert)
end
--------------------------------------------------------------------
------------------ AUX SOLIDS -------------------------------------
--------------------------------------------------------------------
local function UpdateTrimSurfWithAuxSolidsOffset( nSrfSolid, nSrfBase, dStrand, nCrvGrp, vtSlicing)
-- offset della superifice del solido
local bOk, bExists, nSrfOffs = ComputeSurfOffset( nSrfSolid, nCrvGrp, dStrand, vtSlicing)
if nSrfOffs then
EgtSurfFrSubtract( nSrfBase, nSrfOffs)
EgtErase( nSrfOffs)
end
end
--------------------------------------------------------------------
local function UpdateTrimSurfWithAuxSolidsZigZag( nAuxSolidsGrp, sName, nSrfBase, dStrand, nSrf)
local nGrpTmp = EgtGroup( nAuxSolidsGrp) -- gruppo temporaneo per conti
-- recupero le curve associate
local vCrvs = EgtGetNameInGroup( nAuxSolidsGrp, sName)
for i = 1, #vCrvs do
local vtDir = EgtSV( vCrvs[i])
-- costruisco percorso associato
local nCopyCrv = EgtCopyGlob( vCrvs[i], nGrpTmp)
local nCopy2 = EgtCopyGlob( vCrvs[i], nGrpTmp)
EgtInvertCurve( nCopy2)
EgtAddCurveCompoCurve( nCopyCrv, nCopy2)
local nOffsP = EgtOffsetCurveAdv( nCopyCrv, dStrand, GDB_OT.FILLET)
local nFirst, nCnt = EgtExplodeCurveCompo( nOffsP, nGrpTmp)
-- cerco tratti lineari orientati ortogonalmente alla direzione di svuotatura
local nRes = EgtCurveCompo( nGrpTmp, {nFirst})
local nInd = nFirst + 1
while nInd < nFirst + nCnt do
local vtCurrDir = EgtSV( nInd)
local nType = EgtGetType( nInd)
-- se è linea ortognale alla direzione della svuotatura la approssimo
if nType == GDB_TY.CRV_LINE and abs( vtDir * vtCurrDir) < 10 * GEO.EPS_SMALL then
-- cerco ultima curva con lo stesso orientamento
local nLastValidId = nInd
local nInd2 = nInd + 1
while nInd2 < nFirst + nCnt do
nType = EgtGetType( nInd2)
if nType == GDB_TY.CRV_LINE then
if AreSameVectorApprox( EgtSV( nInd2), vtCurrDir) then
nLastValidId = nInd2
else
break
end
end
nInd2 = nInd2 + 1
end
-- aggiungo l'approssimazione lineare
EgtAddCurveCompoLine( nRes, EgtEP( nLastValidId))
-- setto l'indice per ripartire correttamente dopo l'approssimazione
nInd = nLastValidId
else
-- se arco o linea inclinata, aggiungo direttamente al percorso
EgtAddCurveCompoCurve( nRes, nInd)
end
nInd = nInd + 1
end
-- utilizzo la curva per creare superficie
local nSrfZigZag = EgtSurfFlatRegion( nGrpTmp, {nRes})
if nSrfZigZag then
EgtSurfFrSubtract( nSrfBase, nSrfZigZag)
else
EgtSurfFrSubtract( nSrfBase, nSrf)
end
end
EgtErase( nGrpTmp)
end
-------------------------------------------------------------------
local function AddExtraZigZag( nSrf, sName, dStrand, vtSlicing, nGrp, nSrfTrim)
local vIds = EgtGetNameInGroup( nGrp, sName)
local vtDir = EgtSV( vIds[1], GDB_ID.ROOT)
local vtYLoc = vtSlicing ^ vtDir
local nOuterLoop = EgtExtractSurfFrChunkLoops( nSrf, 0, nGrp)
for i = 1, #vIds do
local _, dParE = EgtCurveDomain( vIds[i])
local ptS = EgtUP( vIds[i], dParE - 1, GDB_ID.ROOT) + dStrand * vtYLoc
local ptE = EgtEP( vIds[i], GDB_ID.ROOT) + dStrand * vtYLoc
local nExtraCrv = EgtLine( nGrp, ptS, ptE, GDB_RT.GLOB)
-- verifico se la linea aggiuntiva serve
local dDist = EgtPointCurveDist( EgtMP( nExtraCrv), nOuterLoop)
if dDist < dStrand - 1 then
-- verifico se si trova nella regione ammissibile
if EgtCurveWithRegionClassify( nExtraCrv, nSrfTrim) == GDB_CRC.IN then
EgtInvertCurve( nExtraCrv)
EgtAddCurveCompoLine( vIds[i], ptE, GDB_RT.GLOB)
EgtAddCurveCompoCurve( vIds[i], nExtraCrv)
end
end
EgtErase( nExtraCrv)
end
EgtErase( nOuterLoop)
end
--------------------------------------------------------------------
local function CalcAuxSolidsPaths( nSliceGrp, nSolidGrp, LayerParams, vPtStart)
-- recupero i solidi ausiliari
local vSolidIds = EgtGetAllInGroup( nSolidGrp)
-- scorro i gruppi di curve
local nCrvGrp = EgtGetFirstNameInGroup( nSliceGrp, CONTOUR_GRP .. '*')
while nCrvGrp do
-- creo o svuoto il gruppo per i solidi ausiliari
local nSolidPathGrp = EgtGetFirstNameInGroup( nCrvGrp, AUX_SOLIDS_GRP)
if not nSolidPathGrp then
nSolidPathGrp = EgtGroup( nCrvGrp)
EgtSetName( nSolidPathGrp, AUX_SOLIDS_GRP)
EgtSetStatus( nSolidPathGrp, GDB_ST.OFF)
else
EgtEmptyGroup( nSolidPathGrp)
end
-- creo le superfici con cui fare i trim
local nSrfBase = EgtGetFirstNameInGroup( nCrvGrp, TOT_SHELL_TRIM_SURF)
if not nSrfBase then
EgtOutLog( 'Warning : AuxSolids not possible (layer '..tostring( nIdx)..') - CalcPaths')
else
local vSurfOffs = ComputeTrimSurfWithOverlaps( vSolidIds, nSrfBase, KEY_AUX_SOLIDS_OVERLAP, LayerParams.dStrand, nSolidPathGrp, LayerParams.vtSlicing)
for i = 1, #vSolidIds do
-- creo la flat region corrispondente al solido ausiliario
local sName = EgtGetName( vSolidIds[i])
local nOverlap = EgtGetInfo( vSolidIds[i], KEY_AUX_SOLIDS_OVERLAP, 'i')
local nSrfId = EgtSurfFlatRegion( nSolidPathGrp, vSolidIds[i])
EgtSetName( nSrfId, AUX_SOLIDS_SRF)
-- trim con la superficie di offset
EgtSurfFrIntersect( nSrfId, vSurfOffs[nOverlap])
local nFirst, nCnt = EgtExplodeSurf( nSrfId)
for j = 0, nCnt - 1 do
local sNewName = sName .. EgtIf( j == 0, '', '_' .. tostring( j))
local nInfillType = EgtGetInfo( vSolidIds[i], KEY_AUX_SOLIDS_INFILL, 'i')
if nInfillType == INFILL_TYPE.OFFSET then
ComputeOffsetInfill( nFirst + j, LayerParams.dStrand, LayerParams.vtSlicing, sNewName, TYPE.AUX_SOLID, vPtStart, nSolidPathGrp)
-- aggiorno la trim surf
UpdateTrimSurfWithAuxSolidsOffset( nFirst + j, nSrfBase, LayerParams.dStrand, nSolidPathGrp, LayerParams.vtSlicing)
else
ComputeZigZagInfill( nFirst + j, LayerParams.dStrand, LayerParams.vtSlicing, sNewName, TYPE.AUX_SOLID, vPtStart, nSolidPathGrp)
-- aggiungo eventuale passata extra
AddExtraZigZag( nFirst + j, sNewName, LayerParams.dStrand, LayerParams.vtSlicing, nSolidPathGrp, vSurfOffs[nOverlap])
-- aggiorno la trim surf
UpdateTrimSurfWithAuxSolidsZigZag( nSolidPathGrp, sNewName, nSrfBase, LayerParams.dStrand, nFirst + j)
end
end
end
-- elimino le superfici utilizzate per il trim
for k, v in pairs( vSurfOffs) do
EgtErase( v)
end
end
-- verifico se il gruppo contine qualcosa
if not EgtGetFirstNameInGroup( nSolidPathGrp, AUX_SOLIDS_CRV .. '*') then
EgtErase( nSolidPathGrp)
end
-- passo al gruppo di contorni successivo
nCrvGrp = EgtGetNextName( nCrvGrp, CONTOUR_GRP .. '*')
end
end
---------------------------------------------------------------------
function CalcPaths.Exec( nPartId)
s_nPartId = nPartId
local vLayIds = EgtGetNameInGroup( s_nPartId, SLICE_LAYER.."*")
if not vLayIds then
EgtOutBox( 'Error no slice', 'PathCalc')
return
end
-- recupero i parametri per calcolo dei path
local LayerParams = GetLayerParamsForPathCalc()
-- scorro tutti i suoi layer
for nIdx = 1, #vLayIds do
local nRibsGrp = EgtGetFirstNameInGroup( vLayIds[nIdx], RIBS_GRP)
local nAuxSolidsGrp = EgtGetFirstNameInGroup( vLayIds[nIdx], AUX_SOLIDS_GRP)
-- regioni con diverso numero di passate
local nShellNbrGrp = EgtGetFirstNameInGroup( vLayIds[nIdx], SHELL_NBR_GRP)
local nMaxShell = max( LayerParams.nShellsNbr, LayerParams.nFloorNbr, LayerParams.nCeilNbr)
CreateShellNbrSurfaces( nShellNbrGrp, nMaxShell)
local nShellNbrSurfGrp = EgtGetFirstGroupInGroup( nShellNbrGrp or GDB_ID.NULL)
-- recupero gli start point per il layer
local vPtStart = GetLayerStartPoint( vLayIds[nIdx], LayerParams.vtSlicing)
-- scorro tutti i gruppi di contorni
local nCrvGrpId = EgtGetFirstNameInGroup( vLayIds[nIdx], CONTOUR_GRP.."*") or GDB_ID.NULL
while nCrvGrpId ~= GDB_ID.NULL do
-- verifico se il path è già stato calcolato
local nGrpId = EgtGetFirstNameInGroup( nCrvGrpId, PATH_GRP) or GDB_ID.NULL
if nGrpId == GDB_ID.NULL then
nGrpId = EgtGroup( nCrvGrpId)
EgtSetName( nGrpId, PATH_GRP)
else
EgtEmptyGroup( nGrpId)
EgtSetStatus( nGrpId, GDB_ST.ON)
end
-- recupero la superficie ottenuta dallo slicing
local nSrf = EgtGetFirstNameInGroup( nCrvGrpId, LAYER_SRF)
if nSrf then
local nMaxShellNbrDiff = ComputeMaxShellNbrDiff( nSrf, nShellNbrSurfGrp)
nMaxShellNbrDiff = min( nMaxShellNbrDiff, LayerParams.nShellsNbr)
-- parete esterna
local dOffs = - LayerParams.dOffs - 0.5 * LayerParams.dStrand
if nMaxShellNbrDiff < LayerParams.nShellsNbr then
dOffs = dOffs + LayerParams.dStrand
local bOk, bExists, nSrfId = ComputeSurfOffset( nSrf, nCrvGrpId, - dOffs, LayerParams.vtSlicing)
if not bOk then
EgtOutLog( 'Error on ExtOffset (layer '..tostring( nIdx)..') - CalcPaths')
elseif not bExists then
EgtOutLog( 'Warning : ExtOffset not possible (layer '..tostring( nIdx)..') - CalcPaths')
else
-- se offset riuscito, estraggo i contorni (pareti esterne)
GetPathsFromSurf( nSrfId, SHELL_CRV ..'0', TYPE.OUTER_SHELL, nGrpId, vPtStart)
end
EgtErase( nSrfId)
end
local vPtInnerStart = {}
local vOuterShell = EgtGetNameInGroup( nGrpId, SHELL_CRV .. '0') or {}
for i = 1, #vOuterShell do
table.insert( vPtInnerStart, EgtSP( vOuterShell[i]))
end
if #vPtInnerStart == 0 then vPtInnerStart = vPtStart end
-- pareti interne complete
for nInd = 1, LayerParams.nShellsNbr - 1 - nMaxShellNbrDiff do
-- offset della superficie originale
dOffs = dOffs + LayerParams.dStrand * ( 1 - LayerParams.nStrandOverlap / 100)
local bOk, bExists, nSrfId = ComputeSurfOffset( nSrf, nCrvGrpId, - dOffs, LayerParams.vtSlicing)
if not bOk then
EgtOutLog( 'Error on IntOffset (layer '..tostring( nIdx)..') - CalcPaths')
elseif not bExists then
EgtOutLog( 'Warning : IntOffset not possible (layer '..tostring( nIdx)..') - CalcPaths')
else
-- se offset riuscito, estraggo i contorni ( pareti interne)
GetPathsFromSurf( nSrfId, SHELL_CRV..tostring( nInd), TYPE.INNER_SHELL, nGrpId, vPtInnerStart)
end
EgtErase( nSrfId)
end
-- preparo superficie occupata dalle shell da usare per trim
local dSurfTrimOffs = dOffs + LayerParams.dStrand
if nMaxShellNbrDiff > 0 then
-- se hai extra shell tieni conto anche dell'overlap ammesso
dSurfTrimOffs = dOffs + ( 1 - LayerParams.nStrandOverlap / 100) * LayerParams.dStrand - s_dOffsCorr
end
local bOkTrim, bExistsTrim, nSrfTrim = ComputeSurfOffset( nSrf, nCrvGrpId, - dSurfTrimOffs, LayerParams.vtSlicing)
if not bOkTrim then
EgtOutLog( 'Error on IntOffset (layer '..tostring( nIdx)..') - CalcPaths')
elseif bExistsTrim then
EgtSetName( nSrfTrim, TOT_SHELL_TRIM_SURF)
EgtSetStatus( nSrfTrim, GDB_ST.OFF)
end
-- eventuali pareti interne coinvolte dal diverso numero di passate
if nMaxShellNbrDiff > 0 then
CalcExtraShellsPath( nMaxShellNbrDiff, nShellNbrSurfGrp, nCrvGrpId, dOffs, LayerParams, nIdx, vPtInnerStart)
end
-- gestione eventuale floor/ceil
if nIdx <= LayerParams.nFloorNbr then
local nSurfInfill = AdjustSurfForFloorCeil( LayerParams.nFloorNbr - nIdx + 1, nSrfTrim, nShellNbrSurfGrp) or nSrfTrim
if LayerParams.nFloorType == INFILL_TYPE.OFFSET then
ComputeOffsetInfill( nSurfInfill, LayerParams.dStrand, LayerParams.vtSlicing, INFILL_CRV, TYPE.INFILL, vPtStart, nGrpId)
elseif LayerParams.nFloorType == INFILL_TYPE.ZIGZAG then
ComputeZigZagInfill( nSurfInfill, LayerParams.dStrand, LayerParams.vtSlicing, INFILL_CRV, TYPE.INFILL, vPtStart, nGrpId)
end
EgtErase( nSurfInfill)
elseif nIdx > #vLayIds - LayerParams.nCeilNbr then
local nSurfInfill = AdjustSurfForFloorCeil( LayerParams.nCeilNbr - ( #vLayIds - nIdx), nSrfTrim, nShellNbrSurfGrp) or nSrfTrim
if LayerParams.nCeilType == INFILL_TYPE.OFFSET then
ComputeOffsetInfill( nSurfInfill, LayerParams.dStrand, LayerParams.vtSlicing, INFILL_CRV, TYPE.INFILL, vPtStart, nGrpId)
elseif LayerParams.nCeilType == INFILL_TYPE.ZIGZAG then
ComputeZigZagInfill( nSurfInfill, LayerParams.dStrand, LayerParams.vtSlicing, INFILL_CRV, TYPE.INFILL, vPtStart, nGrpId)
end
EgtErase( nSurfInfill)
end
end
-- passo al gruppo di contorni successivo
nCrvGrpId = EgtGetNextName( nCrvGrpId, CONTOUR_GRP.."*") or GDB_ID.NULL
end
if nIdx > LayerParams.nFloorNbr and nIdx <= #vLayIds - LayerParams.nCeilNbr then
-- sistemo eventuali solidi ausiliari
if nAuxSolidsGrp then
CalcAuxSolidsPaths( vLayIds[nIdx], nAuxSolidsGrp, LayerParams, vPtStart)
end
-- sistemo eventuali costolature
if nRibsGrp then
CalcRibsPaths( vLayIds[nIdx], nRibsGrp, LayerParams, nIdx)
end
end
if EgtProcessEvents( EgtIf( PRINT, 200, 0) + nIdx / #vLayIds * 100, 0) == 1 then
EgtDraw()
return
end
end
end
---------------------------------------------------------------------
return CalcPaths