046431a2a9
- corretta la gestione delle uscite per setti chiusi con link disegnato dall'utente.
2288 lines
90 KiB
Lua
2288 lines
90 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.dLayHeight = EgtGetInfo( s_nPartId, KEY_SLICE_STEP, '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)
|
|
LayerParams.vPrintOrder = EgtGetInfo( s_nPartId, KEY_PRINT_ORDER, 'vi') or { 1, 2, 3, 4, 5, 6, 7, 8}
|
|
-- parametri costolature
|
|
LayerParams.bRibsInvertOrder = EgtGetInfo( s_nPartId, KEY_RIBS_INVERT_ORDER, 'b')
|
|
-- 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 UpdateInvertInfo( nId)
|
|
local bInvert = EgtGetInfo( nId, KEY_INVERTED_CRV, 'b') or false
|
|
EgtSetInfo( nId, KEY_INVERTED_CRV, not bInvert)
|
|
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 VerifyRibsHoles( vIds, dStrand)
|
|
|
|
local sPrevName = EgtGetName( vIds[1])
|
|
local i = 2
|
|
while i <= #vIds do
|
|
|
|
local bAdd = false
|
|
local sCurrName = EgtGetName( vIds[i])
|
|
-- se derivano dallo stesso setto verifico se possono essere uniti
|
|
if sCurrName == sPrevName then
|
|
if dist( EgtEP( vIds[i-1]), EgtSP( vIds[i])) < dStrand + 10 * GEO.EPS_SMALL then
|
|
bAdd = true
|
|
-- unisco il secondo tratto al primo
|
|
EgtAddCurveCompoLine( vIds[i-1], EgtSP( vIds[i]))
|
|
EgtAddCurveCompoCurve( vIds[i-1], vIds[i])
|
|
table.remove( vIds, i) -- rimuovo il setto dalla tabella
|
|
elseif dist( EgtSP( vIds[i-1]), EgtEP( vIds[i])) < dStrand + 10 * GEO.EPS_SMALL then
|
|
bAdd = true
|
|
-- unisco il primo tratto al secondo
|
|
EgtAddCurveCompoLine( vIds[i], EgtSP( vIds[i-1]))
|
|
EgtAddCurveCompoCurve( vIds[i], vIds[i-1])
|
|
table.remove( vIds, i-1) -- rimuovo il setto dalla tabella
|
|
end
|
|
end
|
|
-- aggiorno per iterazione successiva
|
|
sPrevName = sCurrName
|
|
if not bAdd then
|
|
i = i + 1
|
|
end
|
|
end
|
|
end
|
|
|
|
--------------------------------------------------------------------
|
|
local function CheckRibUserLink( nCrv, nCnt, vtSlicing)
|
|
|
|
-- se dal trim non ho ottenuto almeno due tratti, non si tratta di UserLink
|
|
if nCnt < 2 then return end
|
|
|
|
-- stabilisco l'orientamento del link
|
|
local bCCW = false
|
|
-- costruisco la superficie "definita" dal setto
|
|
local nGrpTmp = EgtGroup( EgtGetParent( nCrv))
|
|
local nSrfLoop = EgtCurveCompoFromPoints( nGrpTmp, {EgtEP( nCrv), EgtSP( nCrv + 1)})
|
|
EgtAddCurveCompoLine( nSrfLoop, EgtSP( nCrv + 1) + 100 * EgtSV( nCrv + 1))
|
|
EgtAddCurveCompoLine( nSrfLoop, EgtEP( nCrv) - 100 * EgtEV( nCrv))
|
|
EgtCloseCurveCompo( nSrfLoop)
|
|
|
|
local nSurf = EgtSurfFlatRegion( nGrpTmp, {nSrfLoop})
|
|
if not nSurf then
|
|
EgtErase( nGrpTmp)
|
|
return
|
|
end
|
|
-- verifico direzione della normale
|
|
local vtN = EgtSurfFrNormVersor( nSurf, GDB_ID.ROOT)
|
|
if AreSameVectorApprox( vtN, vtSlicing) then
|
|
bCCW = true
|
|
end
|
|
|
|
-- setto le info
|
|
for i = 0, nCnt - 1 do
|
|
EgtSetInfo( nCrv + i, KEY_RIBS_USER_LINK, 1)
|
|
EgtSetInfo( nCrv + i, KEY_RIBS_USER_LINK_CCW, bCCW)
|
|
EgtSetInfo( nCrv + i, KEY_RIBS_USER_LINK_ORDER, i)
|
|
EgtSetInfo( nCrv + i, KEY_RIBS_USER_LINK_TOT, nCnt)
|
|
end
|
|
|
|
EgtErase( nGrpTmp)
|
|
|
|
end
|
|
|
|
-------------------------------------------------------------------
|
|
local function TrimRibs( vRibs, nRibsGrp, nSrf, dSrfOffs, vtSlicing)
|
|
|
|
-- costruisco le superfici con cui fare il trim grossolano dei setti
|
|
local nSrfInt = EgtCopyGlob( nSrf, nRibsGrp) or GDB_ID.NULL
|
|
local nSrfExt = EgtCopyGlob( nSrf, nRibsGrp) or GDB_ID.NULL
|
|
EgtSurfFrOffset( nSrfInt, dSrfOffs)
|
|
EgtSurfFrOffset( nSrfExt, - dSrfOffs)
|
|
|
|
-- trim dei setti
|
|
local nTrimmedRibsGrp = EgtGroup( nRibsGrp)
|
|
for i = 1, #vRibs do
|
|
local nCopyRib = EgtCopyGlob( vRibs[i], nTrimmedRibsGrp)
|
|
local nType = EgtGetInfo( vRibs[i], KEY_RIBS_TYPE, 'i')
|
|
|
|
local nCrv, nCnt
|
|
if nType == RIB_TYPE.INTERNAL or nType == RIB_TYPE.SUPPORT then
|
|
if EgtSurfFrChunkCount( nSrfInt) == 0 then
|
|
-- se la superficie non esiste, il setto deve essere cancellato
|
|
EgtErase( nCopyRib)
|
|
nCrv = GDB_ID.NULL
|
|
nCnt = 0
|
|
else
|
|
nCrv, nCnt = EgtTrimCurveWithRegion( nCopyRib, nSrfInt, true, true)
|
|
end
|
|
elseif nType == RIB_TYPE.EXTERNAL then
|
|
if EgtSurfFrChunkCount( nSrfExt) == 0 then
|
|
-- se la superficie non esiste il setto è valido
|
|
nCrv = nCopyRib
|
|
nCnt = 1
|
|
else
|
|
nCrv, nCnt = EgtTrimCurveWithRegion( nCopyRib, nSrfExt, false, true)
|
|
end
|
|
else
|
|
-- setto unbounded non va tagliato
|
|
nCrv = nCopyRib
|
|
nCnt = 1
|
|
end
|
|
|
|
-- se errore nel calcolare trim ( nCrv = nil) riprendo il setto originario
|
|
if not nCrv then
|
|
nCrv = nCopyRib
|
|
nCnt = 1
|
|
end
|
|
|
|
for nId = nCrv, nCrv + nCnt - 1 do
|
|
EgtSetInfo( nId, KEY_START_RIB, vRibs[i])
|
|
-- se originale era chiusa ma è stata spezzata dopo il trim è il caso di LoopRib
|
|
if EgtCurveIsClosed( vRibs[i]) and nCnt > 1 then
|
|
EgtSetInfo( nId, KEY_LOOP_RIB, 1)
|
|
end
|
|
end
|
|
-- verifico se link definito dall'utente e ne analizzo le proprietà
|
|
CheckRibUserLink( nCrv, nCnt, vtSlicing)
|
|
|
|
end
|
|
|
|
return nTrimmedRibsGrp
|
|
end
|
|
|
|
--------------------------------------------------------------------
|
|
local function ComputeRibsOrientedOffset( nRibsGrp, dStrand)
|
|
|
|
local nOffsGrp = EgtGroup( EgtGetParent( nRibsGrp))
|
|
|
|
local nCurrRib = EgtGetFirstNameInGroup( nRibsGrp, RIBS_CRV .. '*')
|
|
while nCurrRib do
|
|
|
|
-- recupero tutti i tratti appartenenti a quel setto (hanno lo stesso nome)
|
|
local sName = EgtGetName( nCurrRib)
|
|
local vIds = EgtGetNameInGroup( nRibsGrp, sName)
|
|
|
|
-- recupero i parametri del setto
|
|
local bInvert = EgtGetInfo( nCurrRib, KEY_RIBS_INVERT_DIR, 'b') or false
|
|
local bInvertOrder = EgtGetInfo( nCurrRib, KEY_RIBS_INVERT_STRAND_ORDER, 'b') or false
|
|
|
|
local nShellsNbr = EgtGetInfo( nCurrRib, KEY_RIBS_SHELLS_NBR, 'i')
|
|
local dOffs = ( nShellsNbr - 1) * dStrand / 2
|
|
|
|
-- offset di ogni tratto del setto
|
|
local vOffs = {}
|
|
local bPlusToMinus = false
|
|
for i = 1, #vIds do
|
|
|
|
local bUserLinked = EgtGetInfo( vIds[i], KEY_RIBS_USER_LINK, 'b') or false
|
|
local bCCW = EgtGetInfo( vIds[i], KEY_RIBS_USER_LINK_CCW, 'b') or false
|
|
local nLinkOrder = EgtGetInfo( vIds[i], KEY_RIBS_USER_LINK_ORDER, 'i') or 0
|
|
|
|
-- ordine di realizzazione degli offset
|
|
if not bUserLinked then
|
|
bPlusToMinus = false
|
|
else
|
|
if nLinkOrder == 0 then
|
|
-- determinato dal verso del collegamento
|
|
bPlusToMinus = EgtIf( bCCW, true, false)
|
|
else
|
|
bPlusToMinus = not bPlusToMinus
|
|
end
|
|
end
|
|
|
|
for k = 0, nShellsNbr - 1 do
|
|
local dOffsCurr = dOffs - k * dStrand
|
|
local nNewId
|
|
if abs( dOffsCurr) < GEO.EPS_SMALL then
|
|
nNewId = EgtCopyGlob( vIds[i], nOffsGrp)
|
|
else
|
|
nNewId = EgtOffsetCurveAdv( vIds[i], EgtIf( bPlusToMinus, dOffsCurr, - dOffsCurr))
|
|
end
|
|
|
|
if nNewId then
|
|
EgtSetName( nNewId, sName)
|
|
EgtSetInfo( nNewId, KEY_TYPE, TYPE.RIB)
|
|
EgtSetInfo( nNewId, KEY_ORIGINAL_RIB, vIds[i])
|
|
EgtRelocateGlob( nNewId, nOffsGrp)
|
|
table.insert( vOffs, nNewId)
|
|
end
|
|
end
|
|
end
|
|
|
|
-- ordinamento
|
|
if bInvertOrder then
|
|
for i = 1, #vOffs - 1 do
|
|
EgtRelocateGlob( vOffs[i], vOffs[#vOffs], GDB_IN.AFTER)
|
|
end
|
|
-- aggiorno il vettore con gli indici per rispettare nuovo ordinamento
|
|
vOffs = EgtGetNameInGroup( nOffsGrp, sName)
|
|
end
|
|
|
|
-- orientamento
|
|
local bInvertCrv = bInvert
|
|
for j = 1, #vOffs, nShellsNbr do
|
|
|
|
-- stabilisco orientamento del primo tratto del gruppo
|
|
local bUserLinked = EgtGetInfo( vOffs[j], KEY_RIBS_USER_LINK, 'b') or false
|
|
local nLinkOrder = EgtGetInfo( vOffs[j], KEY_RIBS_USER_LINK_ORDER, 'i') or 0
|
|
local nLinkTot = EgtGetInfo( vOffs[j], KEY_RIBS_USER_LINK_TOT, 'i') or 0
|
|
if not bUserLinked then
|
|
bInvertCrv = bInvert
|
|
else
|
|
if ( not bInvertOrder and nLinkOrder == 0) or ( bInvertOrder and nLinkOrder == nLinkTot - 1) then
|
|
bInvertCrv = bInvert
|
|
if ( nShellsNbr % 2 == 0 and not bInvertOrder) or ( nShellsNbr % 2 ~= 0 and bInvertOrder) then
|
|
bInvertCrv = not bInvert
|
|
end
|
|
else
|
|
if nShellsNbr % 2 == 0 then
|
|
bInvertCrv = not bInvertCrv
|
|
end
|
|
end
|
|
end
|
|
|
|
-- inversione
|
|
for k = 0, nShellsNbr - 1 do
|
|
if ( bInvertCrv and k % 2 == 0) or ( not bInvertCrv and k % 2 ~= 0) then
|
|
EgtInvertCurve( vOffs[j + k])
|
|
UpdateInvertInfo( vOffs[j + k])
|
|
end
|
|
end
|
|
end
|
|
|
|
-- passo al setto successivo
|
|
nCurrRib = EgtGetNextName( vIds[#vIds], RIBS_CRV .. '*')
|
|
end
|
|
|
|
return nOffsGrp
|
|
end
|
|
|
|
--------------------------------------------------------------------
|
|
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 or nType == RIB_TYPE.SUPPORT then
|
|
if nSrfBase ~= GDB_ID.NULL then
|
|
local dNewOffs = nOverlap / 100 * dStrand
|
|
local bOk, bExists, nSrfOffs = ComputeSurfOffset( nSrfBase, nGrp, dNewOffs, vtSlicing)
|
|
if bOk then
|
|
tSurfOffs[RIB_TYPE.INTERNAL][nOverlap] = nSrfOffs
|
|
tSurfOffs[RIB_TYPE.SUPPORT][nOverlap] = nSrfOffs
|
|
end
|
|
end
|
|
elseif nType == RIB_TYPE.EXTERNAL then
|
|
if nSrfExt ~= GDB_ID.NULL 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
|
|
else
|
|
-- se la superficie non esiste, il setto è sicuramente esterno (è analogo ad unbounded)
|
|
tSurfOffs[nType][nOverlap] = GDB_ID.NULL
|
|
end
|
|
else
|
|
tSurfOffs[nType][nOverlap] = GDB_ID.NULL
|
|
end
|
|
end
|
|
end
|
|
return tSurfOffs
|
|
end
|
|
|
|
--------------------------------------------------------------------
|
|
local function VerifyRibsIntersection( nRib1, nRib2, nType1, nType2, nSrf1, nSrf2, dStrand, nGrp, nOffsGrp)
|
|
|
|
-- setti interni/supporto ed esterni non si possono intersecare per definizione
|
|
if ( ( nType1 == RIB_TYPE.INTERNAL or nType1 == RIB_TYPE.SUPPORT) and nType2 == RIB_TYPE.EXTERNAL) or
|
|
( nType1 == RIB_TYPE.EXTERNAL and ( nType2 == RIB_TYPE.INTERNAL or nType2 == RIB_TYPE.SUPPORT)) 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 bForceCrv1Cut = false
|
|
|
|
-- porto le curve nel gruppo locale
|
|
local nCrv1 = EgtCopyGlob( nRib1, nGrp)
|
|
local nCrv2 = EgtCopyGlob( nRib2, nGrp)
|
|
-- verifico se si intersecano nel piano XY definito dal gruppo locale
|
|
local nId, nPntCnt, nCrvCnt = EgtCurveCurveInters( nCrv1, nCrv2, nGrp)
|
|
|
|
-- se si intersecano verifico se ho intersezioni valide
|
|
if nId then
|
|
-- scorro tutti i punti di intersezione trovati
|
|
for i = 0, nPntCnt - 1 do
|
|
local nPtId = nId + i
|
|
-- verifico se valida
|
|
if nType1 == RIB_TYPE.UNBOUNDED and nType2 == RIB_TYPE.UNBOUNDED then
|
|
-- nel caso unbounded l'intersezione può essere ovunque
|
|
bInters = true
|
|
elseif nType1 == RIB_TYPE.EXTERNAL or nType2 == RIB_TYPE.EXTERNAL then
|
|
if nSrf2 then
|
|
-- l'intersezione deve essere esterna
|
|
if EgtSurfFrTestExternal( nSrf2, nPtId) then bInters = true end
|
|
else
|
|
-- se la surf non esiste l'intersezione è sicuramente esterna
|
|
bInters = true
|
|
end
|
|
else
|
|
-- se uno dei due è interno o supporto l'intersezione deve essere interna
|
|
if nSrf1 and not EgtSurfFrTestExternal( nSrf1, nPtId) then bInters = true end
|
|
end
|
|
|
|
-- se valida verifico se forza il taglio sulla curva 1
|
|
if bInters then
|
|
local ptInt = EgtSP( nPtId, GDB_ID.ROOT)
|
|
local dPar1 = EgtCurveParamAtPoint( nCrv1, ptInt, GEO.EPS_SMALL, GDB_RT.GLOB)
|
|
local dPar2 = EgtCurveParamAtPoint( nCrv2, ptInt, GEO.EPS_SMALL, GDB_RT.GLOB)
|
|
local _, dParE1 = EgtCurveDomain( nCrv1)
|
|
local _, dParE2 = EgtCurveDomain( nCrv2)
|
|
|
|
local bCrv1OnExtr = ( dPar1 < 10 * GEO.EPS_SMALL or abs( dPar1 - dParE1) < 10 * GEO.EPS_SMALL)
|
|
local bCrv2OnExtr = ( dPar2 < 10 * GEO.EPS_SMALL or abs( dPar2 - dParE2) < 10 * GEO.EPS_SMALL)
|
|
bForceCrv1Cut = ( bCrv1OnExtr and not bCrv2OnExtr)
|
|
|
|
if bForceCrv1Cut then
|
|
return bInters, bForceCrv1Cut -- true, true
|
|
end
|
|
end
|
|
end
|
|
|
|
return bInters, bForceCrv1Cut -- true/false, false
|
|
|
|
else
|
|
-- se non si intersecano, verifico se si intersecano i loro offset
|
|
local vOffs1 = EgtGetNameInGroup( nOffsGrp, EgtGetName( nCrv1)) or {}
|
|
local vOffs2 = EgtGetNameInGroup( nOffsGrp, EgtGetName( nCrv2)) or {}
|
|
for i = 1, #vOffs1 do
|
|
local nSrfOffs1 = EgtSurfFrFatCurve( nGrp, vOffs1[i], 0.5 * dStrand, false)
|
|
if nSrfOffs1 then
|
|
for j = 1, #vOffs2 do
|
|
-- verifico se intersezione
|
|
local nRes = EgtCurveWithRegionClassify( vOffs2[j], nSrfOffs1)
|
|
if nRes == GDB_CRC.IN or nRes == GDB_CRC.INTERS then
|
|
bInters = true
|
|
break
|
|
end
|
|
end
|
|
if bInters then break end
|
|
end
|
|
end
|
|
|
|
return bInters, bForceCrv1Cut -- true, false
|
|
end
|
|
|
|
end
|
|
|
|
---------------------------------------------------------------------------------
|
|
-- Funzione che sistema le intersezioni fra costolature nel caso generico
|
|
local function AdjustRibsOffsetForIntersection( nCrv1, nCrv2, LayerParams, nOffsGrp, bSaveSurf, nLoopGrp)
|
|
|
|
-- calcolo la superficie della curva principale ( nCrv1) da usare per trim
|
|
local nShells = EgtGetInfo( nCrv1, KEY_RIBS_SHELLS_NBR, 'i')
|
|
local nOverlap = EgtGetInfo( nCrv2, KEY_RIBS_OVERLAP, 'i')
|
|
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)
|
|
|
|
-- se setto chiuso verifico se primo e ultimo tratto possono essere uniti
|
|
if EgtCurveIsClosed( nCrv2) then
|
|
if nCnt > 1 and AreSamePointApprox( EgtEP( nId + nCnt - 1), EgtSP( nId)) then
|
|
EgtRelocateGlob( nId + nCnt - 1, nId, GDB_IN.AFTER)
|
|
EgtAddCurveCompoCurve( nId + nCnt - 1, nId)
|
|
EgtChangeId( nId + nCnt - 1, nId)
|
|
nCnt = nCnt - 1
|
|
end
|
|
end
|
|
|
|
-- aggiorno ordine di split copiandolo da nCrv2
|
|
for j = nId, nId + nCnt - 1 do
|
|
CopyInfo( nCrv2, j, KEY_SPLIT_ORDER, 'i')
|
|
end
|
|
end
|
|
|
|
-- se necessario salvo i loop da usare per ingressi e uscite
|
|
if bSaveSurf then
|
|
-- verifico orientamento della superficie per compatibilità ingressi ribs splittati
|
|
local vtN = EgtSurfFrNormVersor( nSrf)
|
|
if AreSameVectorApprox( vtN, LayerParams.vtSlicing) then
|
|
EgtInvertSurf( nSrf)
|
|
end
|
|
local nChunks = EgtSurfFrChunkCount( nSrf)
|
|
for i = 0, nChunks - 1 do
|
|
local nRes, nCnt = EgtExtractSurfFrChunkLoops( nSrf, i, nLoopGrp)
|
|
for j = nRes, nRes + nCnt - 1 do
|
|
EgtSetName( j, SURF_LOOP)
|
|
end
|
|
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, nLoopGrp, bAllTwoStrands, vTypeSequence)
|
|
|
|
local bSpecialCase = false
|
|
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 ( è il piano XY locale dove calcolare 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) or GDB_ID.NULL
|
|
if nSrf1 ~= GDB_ID.NULL 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) or GDB_ID.NULL
|
|
if nSrf2 ~= GDB_ID.NULL 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, bForceCrv1Cut = VerifyRibsIntersection( vRibsIds[i], vRibsIds[j], nType1, nType2, nSrfOffs1, nSrfOffs2, LayerParams.dStrand, nGrpTmp, nOffsGrp)
|
|
if bRibInters then
|
|
bInters = true
|
|
|
|
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
|
|
|
|
if bForceCrv1Cut then
|
|
nCrv1, nCrv2 = nCrv2, nCrv1
|
|
nSplitOrder1, nSplitOrder2 = nSplitOrder2, nSplitOrder1
|
|
else
|
|
-- se stessa tipologia taglio il setto già splittato più volte, altrimenti taglio il setto che viene realizzato successivamente
|
|
if ( nType1 == nType2 and nSplitOrder1 > nSplitOrder2) or
|
|
( nType1 ~= nType2 and vTypeSequence[nType1] > vTypeSequence[nType2]) then
|
|
nCrv1, nCrv2 = nCrv2, nCrv1
|
|
nSplitOrder1, nSplitOrder2 = nSplitOrder2, nSplitOrder1
|
|
end
|
|
end
|
|
|
|
-- aggiorno tabella delle intersezioni
|
|
local bSaveSurf = false
|
|
if tInters[nCrv1] then
|
|
table.insert( tInters[nCrv1], nCrv2)
|
|
else
|
|
tInters[nCrv1] = {nCrv2}
|
|
-- è la prima volta che nCrv1 viene usata per un trim quindi devo salvare la superficie utilizzata
|
|
bSaveSurf = true
|
|
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)
|
|
bSpecialCase = true
|
|
else
|
|
AdjustRibsOffsetForIntersection( nCrv1, nCrv2, LayerParams, nRibsPathGrp, bSaveSurf, nLoopGrp)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
EgtErase( nSrfOffs1)
|
|
EgtErase( nSrfOffs2)
|
|
EgtErase( nGrpTmp)
|
|
|
|
return bInters, bSpecialCase
|
|
end
|
|
|
|
---------------------------------------------------------------------
|
|
local function ReorderSplitRibs( vIds, dStrand, bParamInvertOrder)
|
|
|
|
-- individuo i setti che derivano da uno stesso pezzo di costolatura
|
|
local tabRibs = {}
|
|
for i = 1, #vIds do
|
|
local nOrigId = EgtGetInfo( vIds[i], KEY_ORIGINAL_RIB, 'i')
|
|
if tabRibs[nOrigId] then
|
|
table.insert( tabRibs[nOrigId], vIds[i])
|
|
else
|
|
tabRibs[nOrigId] = { vIds[i]}
|
|
end
|
|
end
|
|
|
|
for k, tabVal in pairs( tabRibs) do
|
|
|
|
-- verifico se split dopo intersezione con altro setto
|
|
local nSplitOrder = EgtGetInfo( tabVal[1], KEY_SPLIT_ORDER, 'i') or 0
|
|
|
|
-- verifico se split dopo aver fatto il trim con la superficie
|
|
local nStartRib = EgtGetInfo( tabVal[1], KEY_START_RIB, 'i')
|
|
local bSplitAfterTrim = EgtGetInfo( nStartRib, KEY_SPLIT_AFTER_TRIM, 'b') or false
|
|
|
|
if nSplitOrder > 0 or bSplitAfterTrim then
|
|
-- caso di setti splittati
|
|
local nShells = EgtGetInfo( tabVal[1], KEY_RIBS_SHELLS_NBR, 'i')
|
|
if nShells == 1 then
|
|
-- non è necessario il riordino, associo splitId diversi ad ogni tratto per gestire correttamente il link nel CalcToolPath
|
|
for i = 1, #tabVal do
|
|
EgtSetInfo( tabVal[i], KEY_SPLIT_ID, i)
|
|
end
|
|
|
|
else
|
|
-- associo le curve dello split
|
|
local tAssociatedRibs = {}
|
|
while #tabVal > 0 do
|
|
local nCurrId = tabVal[1]
|
|
table.remove( tabVal, 1)
|
|
table.insert( tAssociatedRibs, { nCurrId})
|
|
local bCurrSplitAfterTrim = EgtGetInfo( nCurrId, KEY_SPLIT_AFTER_TRIM, 'b') or false
|
|
while nCurrId do
|
|
local ptCurr = EgtMP( nCurrId)
|
|
bFound = false
|
|
for j = 1, #tabVal do
|
|
local dDist1 = EgtPointCurveDist( ptCurr, tabVal[j])
|
|
local dDist2 = EgtPointCurveDist( EgtMP( tabVal[j]), nCurrId)
|
|
if dDist1 < dStrand + 10 * GEO.EPS_SMALL or dDist2 < dStrand + 10 * GEO.EPS_SMALL then
|
|
|
|
-- verifico nel caso di setti splittati dopo il trim che siano compatibili
|
|
local bUserLink = EgtGetInfo( tabVal[j], KEY_RIBS_USER_LINK, 'b') or false
|
|
local bSplitAfterTrim = EgtGetInfo( tabVal[j], KEY_SPLIT_AFTER_TRIM, 'b') or false
|
|
if bSplitAfterTrim ~= bCurrSplitAfterTrim then
|
|
if not bCurrSplitAfterTrim and bSplitAfterTrim then
|
|
local nOrd = EgtGetInfo( tabVal[j], KEY_SPLIT_AFTER_TRIM_ORDER, 'i')
|
|
if nOrd == 0 then
|
|
bFound = true
|
|
end
|
|
end
|
|
if bCurrSplitAfterTrim then
|
|
local nOrd = EgtGetInfo( nCurrId, KEY_SPLIT_AFTER_TRIM_ORDER, 'i')
|
|
local nTot = EgtGetInfo( nCurrId, KEY_SPLIT_AFTER_TRIM_TOT, 'i')
|
|
if nOrd == nTot - 1 then
|
|
bFound = true
|
|
end
|
|
end
|
|
else
|
|
bFound = true
|
|
end
|
|
|
|
if bFound then
|
|
EgtRelocateGlob( tabVal[j], nCurrId, GDB_IN.AFTER)
|
|
nCurrId = tabVal[j]
|
|
bCurrSplitAfterTrim = bSplitAfterTrim
|
|
table.remove( tabVal, j)
|
|
table.insert( tAssociatedRibs[#tAssociatedRibs], nCurrId)
|
|
break
|
|
end
|
|
end
|
|
end
|
|
|
|
if not bFound then
|
|
nCurrId = nil
|
|
end
|
|
end
|
|
end
|
|
|
|
-- assegno splitid per gestire correttamente il link nel CalcToolPath
|
|
for i = 1, #tAssociatedRibs do
|
|
for j = 1, #tAssociatedRibs[i] do
|
|
EgtSetInfo( tAssociatedRibs[i][j], KEY_SPLIT_ID, i)
|
|
end
|
|
end
|
|
|
|
-- modifiche per preservare i link definiti dall'utente
|
|
local bUserLink = EgtGetInfo( tAssociatedRibs[1][1], KEY_RIBS_USER_LINK, 'b') or false
|
|
if bUserLink and nShells % 2 == 0 then
|
|
|
|
local nLinkOrder = EgtGetInfo( tAssociatedRibs[1][1], KEY_RIBS_USER_LINK_ORDER, 'i') or 0
|
|
local nTotParts = EgtGetInfo( tAssociatedRibs[1][1], KEY_RIBS_USER_LINK_TOT, 'i') or 1
|
|
local bInvertOrder = EgtGetInfo( tAssociatedRibs[1][1], KEY_RIBS_INVERT_STRAND_ORDER, 'b') or false
|
|
|
|
-- ordinamento
|
|
if ( nTotParts % 2 == 0 and bInvertOrder and nLinkOrder % 2 ~= 0 ) or
|
|
( nTotParts % 2 == 0 and not bInvertOrder and nLinkOrder % 2 == 0) or
|
|
( nTotParts % 2 ~= 0 and nLinkOrder % 2 == 0) then
|
|
local vLastGrp = tAssociatedRibs[#tAssociatedRibs]
|
|
local nPrevId = vLastGrp[#vLastGrp]
|
|
for i = #tAssociatedRibs - 1, 1, -1 do
|
|
for j = 1, #tAssociatedRibs[i] do
|
|
local nCurrId = tAssociatedRibs[i][j]
|
|
EgtRelocateGlob( nCurrId, nPrevId, GDB_IN.AFTER)
|
|
nPrevId = nCurrId
|
|
end
|
|
end
|
|
end
|
|
|
|
-- direzione
|
|
if ( nTotParts % 2 == 0 and nLinkOrder > 0 and nLinkOrder < nTotParts - 1) or
|
|
( nTotParts % 2 ~= 0 and not bInvertOrder and nLinkOrder > 0) or
|
|
( nTotParts % 2 ~= 0 and bInvertOrder and nLinkOrder < nTotParts - 1) then
|
|
local vLastGrp = tAssociatedRibs[#tAssociatedRibs]
|
|
for j = 1, #vLastGrp do
|
|
EgtInvertCurve( vLastGrp[j])
|
|
UpdateInvertInfo( vLastGrp[j])
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
end
|
|
|
|
--------------------------------------------------------------------
|
|
local function ShortestPathForRibs( vRibs, nGrp, bInvertOrder)
|
|
|
|
if not vRibs or #vRibs == 0 then return end
|
|
|
|
-- divido per gruppi di setti ( i gruppi sono identificati dallo stesso nome)
|
|
local tabRibs = {}
|
|
local sPrevName = ""
|
|
for i = 1, #vRibs do
|
|
local sName = EgtGetName( vRibs[i])
|
|
if sName == sPrevName then
|
|
table.insert( tabRibs[#tabRibs], vRibs[i])
|
|
else
|
|
table.insert( tabRibs, {vRibs[i]})
|
|
end
|
|
sPrevName = sName
|
|
end
|
|
|
|
-- stabilisco l'ordine di realizzazione dei gruppi di setti
|
|
local vOrd
|
|
if #tabRibs == 1 then
|
|
-- se un solo gruppo ordinamento banale
|
|
vOrd = {1}
|
|
else
|
|
-- se più gruppi ordinamento con shortest path
|
|
EgtSpInit()
|
|
for i = 1, #tabRibs do
|
|
local ptS = EgtSP( tabRibs[i][1], GDB_ID.ROOT)
|
|
local ptE = EgtEP( tabRibs[i][#tabRibs[i]], GDB_ID.ROOT)
|
|
EgtSpAddPoint( ptS:getX(), ptS:getY(), ptS:getZ(), 0, 0, ptE:getX(), ptE:getY(), ptE:getZ(), 0, 0)
|
|
end
|
|
vOrd = EgtSpCalculate( SHP_TY.OPEN)
|
|
EgtSpTerminate()
|
|
end
|
|
|
|
-- creo il vettore con i setti ordinati
|
|
local vIds = {}
|
|
local nStart = EgtIf( bInvertOrder, #vOrd, 1)
|
|
local nEnd = EgtIf( bInvertOrder, 1, #vOrd)
|
|
local nStep = EgtIf( bInvertOrder, -1, 1)
|
|
for i = nStart, nEnd, nStep do
|
|
local vCurrRibs = tabRibs[vOrd[i]]
|
|
for j = 1, #vCurrRibs do
|
|
table.insert( vIds, vCurrRibs[j])
|
|
end
|
|
end
|
|
|
|
EgtRelocateGlob( vIds[1], nGrp, GDB_IN.LAST_SON)
|
|
for i = 2, #vIds do
|
|
EgtRelocateGlob( vIds[i], vIds[i-1], GDB_IN.AFTER)
|
|
end
|
|
|
|
end
|
|
|
|
--------------------------------------------------------------------
|
|
local function ReorderRibs( nGrp, bInvertOrder, dStrand)
|
|
|
|
local vIds = EgtGetNameInGroup( nGrp, RIBS_CRV .. '*')
|
|
if not vIds or #vIds == 0 then return end
|
|
|
|
-- riordino setti splittati
|
|
ReorderSplitRibs( vIds, dStrand, bInvertOrder)
|
|
|
|
-- aggiorno gli id con il nuovo ordinamento
|
|
vIds = EgtGetNameInGroup( nGrp, RIBS_CRV .. '*')
|
|
|
|
-- 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
|
|
for j = 1, 4 do
|
|
local vIds = tRibs[j]
|
|
|
|
-- raggruppo in base allo split order
|
|
local tSplitOrder = {}
|
|
local nMaxSplitOrder = 0
|
|
for i = 1, #vIds do
|
|
local nSplitOrder = EgtGetInfo( vIds[i], KEY_SPLIT_ORDER, 'i') or 0
|
|
-- eventuale aggiornamento del max split order
|
|
if nSplitOrder > nMaxSplitOrder then nMaxSplitOrder = nSplitOrder end
|
|
-- inserisco nella tabella
|
|
if not tSplitOrder[nSplitOrder] then
|
|
tSplitOrder[nSplitOrder]= {vIds[i]}
|
|
else
|
|
table.insert( tSplitOrder[nSplitOrder], vIds[i])
|
|
end
|
|
end
|
|
|
|
-- riordino ogni ordine di split con shortest path
|
|
for k = 0, nMaxSplitOrder do
|
|
ShortestPathForRibs( tSplitOrder[k], nGrp, bInvertOrder)
|
|
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)
|
|
if EgtCurveIsClosed( nId) then
|
|
EgtSetInfo( nId, KEY_CLOSED_CRV, 1)
|
|
end
|
|
|
|
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, bInvertOrder)
|
|
|
|
local vOffs = {}
|
|
local vClosed = {}
|
|
local nId = EgtGetFirstNameInGroup( nOffsGrp, RIBS_CRV .. '*')
|
|
while nId do
|
|
if EgtCurveIsClosed( nId) then
|
|
table.insert( vClosed, nId)
|
|
else
|
|
table.insert( vOffs, nId)
|
|
end
|
|
nId = EgtGetNextName( nId, RIBS_CRV .. '*')
|
|
end
|
|
|
|
local k = 0 -- indice da utilizzare per i nomi
|
|
|
|
-- gestione delle curve chiuse
|
|
if #vClosed > 0 then
|
|
k = k + 1
|
|
local sPrevName = EgtGetName( vClosed[1])
|
|
EgtSetName( vClosed[1], RIBS_CRV .. tostring( k))
|
|
for i = 2, #vClosed do
|
|
local sCurrName = EgtGetName( vClosed[i])
|
|
-- se setto diverso aggiorno il nome
|
|
if sCurrName ~= sPrevName then
|
|
k = k + 1
|
|
end
|
|
EgtSetName( vClosed[i], RIBS_CRV .. tostring( k))
|
|
sPrevName = sCurrName
|
|
end
|
|
end
|
|
|
|
-- gestione delle curve aperte
|
|
-- 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)
|
|
|
|
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
|
|
|
|
-- eventuale inversione ordinamento
|
|
if bInvertOrder then
|
|
local vRibs = EgtGetNameInGroup( nOffsGrp, RIBS_CRV .. '*')
|
|
for j = #vRibs, 1, -1 do
|
|
-- inverto direzione curve per mantenere concatenamento
|
|
EgtInvertCurve( vRibs[j])
|
|
EgtRelocateGlob( vRibs[j], nOffsGrp, GDB_IN.LAST_SON)
|
|
end
|
|
end
|
|
|
|
end
|
|
|
|
-------------------------------------------------------------------
|
|
local function CalcRibsPaths( nSliceGrp, nRibsGrp, LayerParams, nIdx, vPtStart)
|
|
|
|
-- stabilisco ordine di realizzazione delle varie tipologie
|
|
local vTypeSequence = {}
|
|
for i = 1, #LayerParams.vPrintOrder do
|
|
if LayerParams.vPrintOrder[i] == PRINT_ELEMENT.RIB_UNBOUNDED then
|
|
vTypeSequence[RIB_TYPE.UNBOUNDED] = i
|
|
elseif LayerParams.vPrintOrder[i] == PRINT_ELEMENT.RIB_INTERNAL then
|
|
vTypeSequence[RIB_TYPE.INTERNAL] = i
|
|
elseif LayerParams.vPrintOrder[i] == PRINT_ELEMENT.RIB_EXTERNAL then
|
|
vTypeSequence[RIB_TYPE.EXTERNAL] = i
|
|
elseif LayerParams.vPrintOrder[i] == PRINT_ELEMENT.RIB_SUPPORT then
|
|
vTypeSequence[RIB_TYPE.SUPPORT] = i
|
|
end
|
|
end
|
|
|
|
local vOrigRibs = EgtGetNameInGroup( nRibsGrp, RIBS_CRV .. '*')
|
|
-- verifico se tutte le costolature vengono fatte con 2 passate
|
|
local bAllTwoStrands = true
|
|
for i = 1, #vOrigRibs do
|
|
local nStrand = EgtGetInfo( vOrigRibs[i], KEY_RIBS_SHELLS_NBR, 'i')
|
|
if nStrand ~= 2 then
|
|
bAllTwoStrands = false
|
|
break
|
|
end
|
|
end
|
|
|
|
-- verifico se posso ignorare eventuali buchi nei setti
|
|
VerifyRibsHoles( vOrigRibs, LayerParams.dStrand)
|
|
|
|
-- scorro i gruppi di curve
|
|
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
|
|
|
|
-- recupero le superfici
|
|
local nSrfBase = EgtGetFirstNameInGroup( nCrvGrp, TOT_SHELL_TRIM_SURF) or GDB_ID.NULL
|
|
local nSrfExt = EgtGetFirstNameInGroup( nCrvGrp, LAYER_SRF) or GDB_ID.NULL
|
|
|
|
-- trim grossolano dei setti
|
|
local nTrimGrp = TrimRibs( vOrigRibs, nRibsGrp, nSrfExt, LayerParams.dOffs - LayerParams.dStrand / 2, LayerParams.vtSlicing)
|
|
|
|
-- calcolo offset orientati
|
|
local nOffsGrp = ComputeRibsOrientedOffset( nTrimGrp, LayerParams.dStrand)
|
|
|
|
-- creo le superfici con cui fare i trim corretti
|
|
local tSurfOffs = ComputeTrimSurfWithOverlapsForRibs( vOrigRibs, nSrfBase, nSrfExt, LayerParams.dOffs, LayerParams.dStrand, nRibsPathGrp, LayerParams.vtSlicing)
|
|
|
|
-- preparo il gruppo con i contorni delle superfici di offset ( necessario per CalcToolPath)
|
|
local nLoopGrp = EgtGroup( nRibsPathGrp)
|
|
local nSrfId = EgtGetFirstNameInGroup( nRibsPathGrp, TOT_SHELL_TRIM_SURF)
|
|
while nSrfId do
|
|
local nChunksNbr = EgtSurfFrChunkCount( nSrfId)
|
|
for i = 0, nChunksNbr - 1 do
|
|
local nRes, nCnt = EgtExtractSurfFrChunkLoops( nSrfId, i, nLoopGrp)
|
|
for j = nRes, nRes + nCnt - 1 do
|
|
EgtSetName( j, TRIM_SURF_LOOP)
|
|
end
|
|
end
|
|
nSrfId = EgtGetNextName( nSrfId, TOT_SHELL_TRIM_SURF)
|
|
end
|
|
|
|
-- gestisco eventuali intersezioni fra costolature
|
|
local bInters, bSpecialCase = HandleRibsIntersections( nRibsGrp, LayerParams, nOffsGrp, nRibsPathGrp, nLoopGrp, bAllTwoStrands, vTypeSequence)
|
|
EgtSetInfo( nRibsPathGrp or GDB_ID.NULL, KEY_RIBS_INTERS, bInters)
|
|
EgtSetInfo( nRibsPathGrp or GDB_ID.NULL, KEY_RIBS_SPECIAL_CASE, bSpecialCase)
|
|
|
|
-- trim dei setti con le regioni offsettate secondo opportuno overlap
|
|
local vRibs = EgtGetNameInGroup( nRibsPathGrp, RIBS_CRV ..'*') or {}
|
|
for i = 1, #vRibs do
|
|
local nCrvId = vRibs[i]
|
|
-- trim con superficie opportuna
|
|
local nOverlap = EgtGetInfo( nCrvId, KEY_RIBS_OVERLAP, 'i')
|
|
local nType = EgtGetInfo( nCrvId, KEY_RIBS_TYPE, 'i')
|
|
if not tSurfOffs[nType][nOverlap] then
|
|
-- la costolatura non è fattibile
|
|
EgtOutLog( 'Warning: Ribs not possibile (layer '..tostring( nIdx)..') - CalcPaths')
|
|
EgtErase( vRibs[i])
|
|
else
|
|
local nCrv, nCnt
|
|
if tSurfOffs[nType][nOverlap] == GDB_ID.NULL then
|
|
-- caso unbounded o esterno in assenza di solido
|
|
nCrv = nCrvId
|
|
nCnt = 1
|
|
else
|
|
nCrv, nCnt = EgtTrimCurveWithRegion( nCrvId, tSurfOffs[nType][nOverlap], EgtIf( nType == RIB_TYPE.INTERNAL or nType == RIB_TYPE.SUPPORT, true, false), false)
|
|
end
|
|
|
|
for nInd = 0, nCnt - 1 do
|
|
-- verifico vicolo sulla lunghezza
|
|
local dLen = EgtCurveLength( nCrv + nInd)
|
|
if dLen < MIN_RIBS_LEN then
|
|
EgtErase( nCrv + nInd)
|
|
else
|
|
|
|
-- salvo info della superficie di trim associata
|
|
EgtSetInfo( nCrv + nInd, KEY_ASSOCIATED_SURF, tSurfOffs[nType][nOverlap])
|
|
|
|
-- setti chiusi
|
|
if EgtCurveIsClosed( nCrv + nInd) then
|
|
EgtSetInfo( nCrv + nInd, KEY_CLOSED_CRV, 1)
|
|
|
|
-- ripristino orientamento originale
|
|
local bInvertInfo = EgtGetInfo( nCrv + nInd, KEY_RIBS_INVERT_DIR, 'b') or false
|
|
local bInverted = EgtGetInfo( nCrv + nInd, KEY_INVERTED_CRV, 'b') or false
|
|
if bInvertInfo ~= bInverted then
|
|
EgtInvertCurve( nCrv + nInd)
|
|
UpdateInvertInfo( nCrv + nInd)
|
|
end
|
|
|
|
ModifyStartPoint( nCrv + nInd, vPtStart)
|
|
EgtSetInfo( nCrv + nInd, KEY_RIBS_LINK, 0)
|
|
end
|
|
|
|
-- se dopo trim ho avuto split in più tratti, salvo alcune info
|
|
if nCnt > 1 then
|
|
local nStartRib = EgtGetInfo( nCrv + nInd, KEY_START_RIB, 'i')
|
|
EgtSetInfo( nStartRib, KEY_SPLIT_AFTER_TRIM, 1)
|
|
EgtSetInfo( nCrv + nInd, KEY_SPLIT_AFTER_TRIM, 1)
|
|
EgtSetInfo( nCrv + nInd, KEY_SPLIT_AFTER_TRIM_ORDER, nInd)
|
|
EgtSetInfo( nCrv + nInd, KEY_SPLIT_AFTER_TRIM_TOT, nCnt)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
-- riordino le costolature
|
|
if bSpecialCase then
|
|
-- gestione caso speciale di intersezione e 2 passate
|
|
ReorderRibsInters2Shells( nRibsPathGrp, LayerParams.dStrand, LayerParams.bRibsInvertOrder)
|
|
else
|
|
ReorderRibs( nRibsPathGrp, LayerParams.bRibsInvertOrder, LayerParams.dStrand)
|
|
end
|
|
|
|
if not EgtGetFirstNameInGroup( nRibsPathGrp, RIBS_CRV .. '*') then
|
|
EgtErase( nRibsPathGrp)
|
|
end
|
|
|
|
-- sistemo le quote delle superfici e dei loop per CalcToolPath
|
|
local vLoopIds = EgtGetAllInGroup( nLoopGrp) or {}
|
|
for i = 1, #vLoopIds do
|
|
EgtMove( vLoopIds[i], LayerParams.dLayHeight * LayerParams.vtSlicing, GDB_RT.GLOB)
|
|
end
|
|
local vSrfIds = EgtGetNameInGroup( nRibsPathGrp, TOT_SHELL_TRIM_SURF) or {}
|
|
for i = 1, #vSrfIds do
|
|
EgtMove( vSrfIds[i], LayerParams.dLayHeight * LayerParams.vtSlicing, GDB_RT.GLOB)
|
|
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
|
|
EgtRelocateGlob( nCrv + nCnt - 1, nCrv, GDB_IN.AFTER)
|
|
EgtAddCurveCompoCurve( nCrv + nCnt - 1, nCrv)
|
|
EgtChangeId( nCrv + nCnt - 1, 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])
|
|
UpdateInvertInfo( vIds[i])
|
|
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
|
|
EgtSetStatus( nId, GDB_ST.ON)
|
|
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 true
|
|
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
|
|
EgtSetInfo( nCrvGrpId, KEY_START_POINT, vPtInnerStart[1])
|
|
|
|
-- 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, vPtStart)
|
|
end
|
|
end
|
|
|
|
if EgtProcessEvents( EgtIf( PRINT, 200, 0) + nIdx / #vLayIds * 100, 0) == 1 then
|
|
EgtDraw()
|
|
return false
|
|
end
|
|
end
|
|
|
|
return true
|
|
end
|
|
|
|
---------------------------------------------------------------------
|
|
return CalcPaths
|