-- 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 = 20 * GEO.EPS_SMALL local s_vErr = {} local s_nCurrIdx local s_vtSlicing local s_dOffsTol = 50 * 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.dInnerStrand = EgtGetInfo( s_nPartId, KEY_INNER_STRAND, 'd') or LayerParams.dStrand if LayerParams.dInnerStrand < GEO.EPS_SMALL then LayerParams.dInnerStrand = LayerParams.dStrand end LayerParams.dLayHeight = EgtGetInfo( s_nPartId, KEY_SLICE_STEP, 'd') LayerParams.dStrandOverlap = EgtGetInfo( s_nPartId, KEY_STRAND_OVERLAP, 'd') or 0 LayerParams.dOffs = EgtGetInfo( s_nPartId, KEY_OFFSET_SLICE, 'd') s_vtSlicing = EgtGetInfo( s_nPartId, KEY_SLICE_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') or false LayerParams.bInvertRibsMergedShellLink = EgtGetInfo( s_nPartId, KEY_INVERT_RIBS_MERGED_SHELL_LINK, 'b') or false -- 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') -- parametri solid fill LayerParams.nFloorNbr = EgtGetInfo( s_nPartId, KEY_FLOOR_NBR, 'i') or 0 LayerParams.nFloorType = EgtGetInfo( s_nPartId, KEY_FLOOR_TYPE, 'i') or FILL_TYPE.OFFSET LayerParams.nCeilNbr = EgtGetInfo( s_nPartId, KEY_CEIL_NBR, 'i') or 0 LayerParams.nCeilType = EgtGetInfo( s_nPartId, KEY_CEIL_TYPE, 'i') or FILL_TYPE.OFFSET -- parametri infill LayerParams.dInfillStrand = EgtGetInfo( s_nPartId, KEY_INFILL_STRAND, 'd') or LayerParams.dStrand if LayerParams.dInfillStrand < GEO.EPS_SMALL then LayerParams.dInfillStrand = LayerParams.dStrand end LayerParams.bInfillLink = EgtGetInfo( s_nPartId, KEY_INFILL_LINK, 'b') or false LayerParams.dInfillOverlap = EgtGetInfo( s_nPartId, KEY_INFILL_OVERLAP, 'd') or 0 LayerParams.nInfillType = EgtGetInfo( s_nPartId, KEY_INFILL_TYPE, 'i') or FILL_TYPE.NONE -- eventuale modifica dei parametri per gestire correttamente il caso spiral vase if LayerParams.bSpiralVase then 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 SwapInfo( nId1, nId2, sInfo, sType, sDefVal) local info1 = EgtGetInfo( nId1, sInfo, sType) or sDefVal local info2 = EgtGetInfo( nId2, sInfo, sType) or sDefVal EgtSetInfo( nId1, sInfo, info2) EgtSetInfo( nId2, sInfo, info1) 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) -- restituisce id della superficie offsettata in caso di successo, nil in caso di errore, GDB_ID.NULL se la superficie offsettata scompare local nOffsSrf = EgtSurfFrOffsetAdv( nSrf, dOffs) if not nOffsSrf then -- ritento modificando leggermente l'offset nOffsSrf = EgtSurfFrOffsetAdv( nSrf, dOffs + 0.05) end -- sposto nel gruppo desiderato EgtRelocateGlob( nOffsSrf or GDB_ID.NULL, nGrpId) return nOffsSrf end -------------------------------------------------------------------- local function ComputeTrimSurf( nSrf, nGrpId, dStrand, dOverlap) local nTrimSurf = ComputeSurfOffset( nSrf, nGrpId, - dStrand * ( 0.5 - dOverlap / 100) + 2 * s_dOffsCorr) local bNoOverlap = false if not nTrimSurf and dOverlap > GEO.EPS_SMALL then -- tento senza overlap nTrimSurf = ComputeSurfOffset( nSrf, nGrpId, - dStrand * 0.5) if not nTrimSurf then return end bNoOverlap = true end return nTrimSurf, bNoOverlap end --------------------------------------------------------------------- local function GetLayerStartPoint( nLayId) -- gruppo temporaneo dove salvo i risultati local nGrpTmp = EgtGroup( nLayId) local vPtStart = {} local nMachStartGrp = EgtGetFirstNameInGroup( s_nPartId, LAY_MACH_START) local ptOn = EgtGetInfo( nLayId, KEY_SLICE_POS, 'p') 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, s_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) EgtModifyCurveExtrusion( nCrvId + nInd, s_vtSlicing, GDB_ID.ROOT) -- se è loop interno lo inverto per averlo orientato in senso antiorario if nInd > 0 then EgtInvertCurve( nCrvId + nInd) EgtSetInfo( nCrvId + nInd, KEY_INTERNAL_SRF_LOOP, true) 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) else table.insert( vIds, nCrvId + nInd) ModifyStartPoint( nCrvId + nInd, vPtStart) end end end return vIds or {} end ---------------------------------------------------------------------- local function VerifyPath( nCrvId, dStrand, nGrp) local _, _, dArea = EgtCurveArea( nCrvId) -- verifico se esiste l'offset ( permetto una piccola sovrapposizione) -- TODO migliorare il controllo per verificare se sovrapposizione local dAllowedOverlap = 1 local nRes, nCnt = EgtOffsetCurveAdv( nCrvId, - dStrand / 2 + dAllowedOverlap, GDB_OT.FILLET, s_dOffsTol) -- se errore ritento con valore leggermente modificato if not nRes then nRes, nCnt = EgtOffsetCurveAdv( nCrvId, - dStrand / 2 + 0.05, GDB_OT.FILLET, s_dOffsTol) 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(), s_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 -- verifico se devo eliminarlo dalle info della curva precedente local nPrev = EgtGetInfo( nCrvId, KEY_PREV_CRV, 'i') if nPrev then local vNext = EgtGetInfo( nPrev, KEY_NEXT_CRVS, 'vi') if vNext then for k = 1, #vNext do if vNext[k] == nCrvId then table.remove( vNext, k) break end end EgtSetInfo( nPrev, KEY_NEXT_CRVS, vNext) end end -- cancello EgtErase( nCrvId) return false end end return true end --------------------------------------------------------------------- local function AdjustTrimSurfExtraAngleChunks( nTrimSurf, dOffs, dStrand) if EgtSurfFrChunkCount( nTrimSurf) == 0 then return end -- calcolo la superficie occupata dalle shell se non ci fossero shell particolari ( extra shells o ribs-merged shells) local nLaySurf = EgtGetFirstNameInGroup( EgtGetParent( nTrimSurf), LAYER_SRF) dOffs = dOffs + dStrand * 0.5 + 50 * GEO.EPS_SMALL local nBaseSurf = ComputeSurfOffset( nLaySurf, EgtGetParent( nTrimSurf), - dOffs) if not nBaseSurf then EgtOutLog( 'Warning : AdjustTrimSurfExtraAngleChunks base surf computation failed. TrimSurf may be inaccurate (layer '.. EgtNumToString( s_nCurrIdx) ..') - CalcPaths') return elseif nBaseSurf == GDB_ID.NULL then EgtOutLog( 'Warning : AdjustTrimSurfExtraAngleChunks base surf does not exist. TrimSurf may be inaccurate (layer '.. EgtNumToString( s_nCurrIdx) ..') - CalcPaths') return end local nChunks = EgtSurfFrChunkCount( nBaseSurf) -- individuo i chunk della TrimSurf da conservare local vValidChunks = {} local nFirstId, nCnt = EgtExplodeSurf( nTrimSurf) for nId = nFirstId, nFirstId + nCnt - 1 do -- verifico se è esterno a tutti i chunks di nBaseSurf ( quindi è porzione non riempita tra le shell da eliminare) local bIsOut = true for i = 0, nChunks - 1 do local nRes = EgtSurfFrChunkSimpleClassify( nId, 0, nBaseSurf, i) if nRes ~= GDB_RC.OUT then bIsOut = false break end end if bIsOut then EgtErase( nId) else -- se compreso nella superficie base va conservato table.insert( vValidChunks, nId) end end -- unisco tutti i chunk validi in un'unica superficie for i = 2, #vValidChunks do EgtSurfFrAdd( vValidChunks[1], vValidChunks[i]) EgtErase( vValidChunks[i]) end EgtErase( nBaseSurf) end -------------------------------------------------------------------- ------------------------- INFILL ----------------------------------- -------------------------------------------------------------------- local function CalcInfillPaths( nLayId, nInfillGrp, LayerParams) if not nInfillGrp then return end -- recupero le curve di infill local vIds = EgtGetAllInGroup( nInfillGrp) if not vIds or #vIds == 0 then return end -- scorro i gruppi di curve local vCrvGrps = EgtGetNameInGroup( nLayId, CONTOUR_GRP .. '*') for i = 1, #vCrvGrps do -- creo il gruppo per infill local nInfillPathGrp = EgtGroup( vCrvGrps[i]) EgtSetName( nInfillPathGrp, INFILL_GRP) EgtSetStatus( nInfillPathGrp, GDB_ST.OFF) EgtSetInfo( nInfillPathGrp, KEY_FILL_TYPE, LayerParams.nInfillType) -- recupero la superficie occupata dalle shell local nSrfBase = EgtGetFirstNameInGroup( vCrvGrps[i], TOT_SHELL_TRIM_SURF) if not nSrfBase then -- se non esiste non c'è spazio per infill EgtOutLog( 'Warning : Infill not possibile (layer '.. EgtNumToString( s_nCurrIdx) ..') - CalcPaths') else -- calcolo la superficie per trim local nTrimSrf, bNoOverlap = ComputeTrimSurf( nSrfBase, nInfillPathGrp, LayerParams.dInfillStrand, LayerParams.dInfillOverlap) if not nTrimSrf then -- errore EgtOutLog( 'Error : creation of Infill region failed (layer '.. EgtNumToString( s_nCurrIdx) ..') - CalcPaths') table.insert( s_vErr, ' - layer ' .. EgtNumToString( s_nCurrIdx) .. ' : creation of Infill region failed') elseif nTrimSrf == GDB_ID.NULL then EgtOutLog( 'Warning : Infill not possibile (layer '.. EgtNumToString( s_nCurrIdx) ..') - CalcPaths') else if bNoOverlap then EgtOutLog( 'Warning : Infill without correct overlap (layer '.. EgtNumToString( s_nCurrIdx) ..') - CalcPaths') end for i = 1, #vIds do local nNewId = EgtCopyGlob( vIds[i], nInfillPathGrp) -- eventuale inversione della curva per link if LayerParams.bInfillLink and i % 2 == 0 then EgtInvertCurve( nNewId) UpdateInvertInfo( nNewId) end -- faccio trim con la superficie local nRes, nCnt = EgtTrimCurveWithRegion( nNewId, nTrimSrf, true, true) for nId = nRes, nRes + nCnt - 1 do -- verifico se lunghezza minima local dLen = EgtCurveLength( nId) if dLen < MIN_INFILL_LEN then EgtErase( nId) else EgtSetName( nId, INFILL_CRV) EgtSetInfo( nId, KEY_TYPE, TYPE.INFILL) EgtSetInfo( nId, KEY_ASSOCIATED_SURF, nTrimSrf) EgtModifyCurveExtrusion( nId, s_vtSlicing, GDB_RT.GLOB) end end end -- avendo riempito la regione con gli infill, la TotShellTrimSurf non deve esistere EgtErase( nSrfBase) end end -- se gruppo vuoto lo cancello if not EgtGetFirstNameInGroup( nInfillPathGrp, INFILL_CRV .. '*') then EgtErase( nInfillPathGrp) end end return true end -------------------------------------------------------------------- ------------------------ SOLID FILL -------------------------------- -------------------------------------------------------------------- local function AssignChildrenCurves( vParentIds, vChildrenIds, vOrdered) if not vParentIds or not vChildrenIds then return end if #vParentIds == 1 then vOrdered[vParentIds[1]] = vChildrenIds else -- recupero i centroidi di tutte le curve padre local vPtCParent = {} for i = 1, #vParentIds do table.insert( vPtCParent, EgtGP( vParentIds[i])) end -- associo ad ogni elemento di vParentIds gli elementi di vChildrenIds che ha generato for i = 1, #vChildrenIds do -- individuo la curva di vParentIds con il centroiode più vicino local ptC = EgtGP( vChildrenIds[i]) local dDistMin = GEO.INFINITO local nParentId = -1 for j = 1, #vPtCParent do local dCurrDist = dist( ptC, vPtCParent[j]) if dCurrDist < dDistMin - GEO.EPS_SMALL then dDistMin = dCurrDist nParentId = vParentIds[j] end end -- la aggiungo tra i figli della curva di vParentIds trovata if not vOrdered[nParentId] then vOrdered[nParentId] = {vChildrenIds[i]} else table.insert( vOrdered[nParentId], vChildrenIds[i]) end end end end --------------------------------------------------------------------------- local function ReorderPath( vOldIds, vNewIds) if not vNewIds or #vNewIds == 0 then return end if not vOldIds or #vOldIds == 0 then return end -- suddivido in base alla tipologia di loop ( esterno o interno) local tOldIds = {{}, {}} for i = 1, #vOldIds do local bIntLoop = EgtGetInfo( vOldIds[i], KEY_INTERNAL_SRF_LOOP, 'b') or false local nTabInd = EgtIf( bIntLoop, 2, 1) table.insert( tOldIds[nTabInd], vOldIds[i]) end local tNewIds = {{}, {}} for i = 1, #vNewIds do local bIntLoop = EgtGetInfo( vNewIds[i], KEY_INTERNAL_SRF_LOOP, 'b') or false local nTabInd = EgtIf( bIntLoop, 2, 1) table.insert( tNewIds[nTabInd], vNewIds[i]) end -- assegno ad ogni curva di vOldIds le curve di vNewIds che ha generato local vOrdered = {} AssignChildrenCurves( tOldIds[1], tNewIds[1], vOrdered) -- loop esterni AssignChildrenCurves( tOldIds[2], tNewIds[2], vOrdered) -- loop interni -- assegno le info e riordino local vNewOrder = {} local nGrp = EgtGetParent( vNewIds[1]) for i = 1, #vOldIds do local vChildrenIds = vOrdered[vOldIds[i]] or {} EgtSetInfo( vOldIds[i], KEY_NEXT_CRVS, vChildrenIds) for j = 1, #vChildrenIds do EgtRelocateGlob( vChildrenIds[j], nGrp, GDB_IN.LAST_SON) table.insert( vNewOrder, vChildrenIds[j]) EgtSetInfo( vChildrenIds[j], KEY_PREV_CRV, vOldIds[i]) end end return vNewOrder end --------------------------------------------------------------------------- local function ComputeOffsetShells( nSrf, dStrand, sName, nType, nGrp, vPtStart, vOldIds, nMaxShells) if nSrf == GDB_ID.NULL then return true end if not nMaxShells then nMaxShells = GEO.INFINITO end if nMaxShells == 0 then return true end -- nSrf è già la prima superficie da cui estrarre i bordi, quindi il primo offset non va fatto local dOffs = 0 local nSrfOffs = EgtCopyGlob( nSrf, nGrp) for i = 1, nMaxShells do -- estraggo i contorni local vNewIds = GetPathsFromSurf( nSrfOffs, sName, nType, nGrp, vPtStart) if vNewIds then -- riordino local vNewOrder = ReorderPath( vOldIds, vNewIds) or vNewIds vOldIds = vNewOrder else return false end EgtErase( nSrfOffs) -- se sei già all'ultima shell richiesta non è necessario calcolare offset successivo if i == nMaxShells then return true end -- offset successivo dOffs = dOffs - dStrand nSrfOffs = ComputeSurfOffset( nSrf, nGrp, dOffs) if not nSrfOffs then -- errore nel calcolo della superficie return false elseif nSrfOffs == GDB_ID.NULL then -- spazio esaurito, termino la funzione return true end end return true end ------------------------------------------------------------------ local function FindOptimalZigZagDirection( nSrfId, nBorderSurf, dStrand, nGrp, frLoc) -- come direzione ottimale scelgo quella del lato più vicino al bordo oppure quella del -- lato più lungo nel caso in cui i lati fossero tutti sufficientemente lontani ( distanza > dStrand) dal bordo local nGrpTmp = EgtGroup( nGrp, frLoc, GDB_RT.GLOB) -- gruppo temporaneo per i conti local dTol = 1 + GEO.EPS_SMALL -- recupero tutti i lati della superficie da riempire local vCrvIds = GetPathsFromSurf( nSrfId, 'Tmp', 0, nGrpTmp) local nId, nCnt = EgtExplodeCurveCompo( vCrvIds[1]) local vAllIds = {} for i = nId, nId + nCnt - 1 do table.insert( vAllIds, i) end local vCheckIds = {} -- se ho superficie che contiene nSrfId ( caso AuxSolid) cerco il lato di lunghezza massima tra quelli a distanza minima dal bordo if nBorderSurf then -- recupero i contorni della curva di bordo local vBorderIds = GetPathsFromSurf( nBorderSurf, 'TmpBorder', 0, nGrpTmp) local dMinDist = GEO.INFINITO for i = nId, nId + nCnt - 1 do -- trovo la distanza minima dalle curve di bordo local dDist if #vBorderIds == 1 then dDist = EgtPointCurveDist( EgtMP( i), vBorderIds[1]) else dDist = GEO.INFINITO for j = 1, #vBorderIds do local dCurrDist = EgtPointCurveDist( EgtMP( i), vBorderIds[j]) if dCurrDist < dDist then dDist = dCurrDist end end end -- se tratto sufficientemente vicino al bordo verifico se a distanza minima ( entro tolleranza dTol) if dDist < dStrand + GEO.EPS_SMALL then if abs( dDist - dMinDist) < dTol then table.insert( vCheckIds, i) elseif dDist < dMinDist - dTol then dMinDist = dDist vCheckIds = {i} end end end end -- se non ho id specifici da controllare considero tutti i lati if #vCheckIds == 0 then vCheckIds = vAllIds end -- cerco il lato più lungo tra quelli selezionati local vtDir if #vCheckIds == 1 then vtDir = EgtSV( vCheckIds[1]) else local dLen = - GEO.INFINITO for k = 1, #vCheckIds do local dCurrLen = EgtCurveLength( vCheckIds[k]) if dCurrLen > dLen + GEO.EPS_SMALL then dLen = dCurrLen vtDir = EgtSV( vCheckIds[k]) end end end EgtErase( nGrpTmp) return vtDir end -------------------------------------------------------------------- local function ComputeZigZagSolidFill( nSrf, dStrand, sName, nType, nGrp, nBorderSurf) if nSrf == GDB_ID.NULL then return end local nCopySrf = EgtCopyGlob( nSrf, nGrp) local frLoc = Frame3d( ORIG(), s_vtSlicing) -- analizzo tutti i chunk della superficie da riempire local nFirst, nSrfCnt = EgtExplodeSurf( nCopySrf) local vIds = {} for nSrfId = nFirst, nFirst + nSrfCnt - 1 do -- trovo la direzione ottimale per la svuotatura in frLoc local vtDir = FindOptimalZigZagDirection( nSrfId, nBorderSurf, dStrand, nGrp, frLoc) local _, _, dAng = SphericalFromVector( vtDir) vtDir:toGlob( frLoc) local nInd, nCnt = EgtGetSurfFrZigZagInfill( nSrfId, nGrp, dStrand, dAng, false, false) if nInd then 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, true) EgtModifyCurveExtrusion( j, s_vtSlicing, GDB_RT.GLOB) table.insert( vIds, j) end end EgtErase( nSrfId) end end ------------------------------------------------------------------ local function CalcSolidFillPath( nLayId, LayerParams, vPtStart, nFillType) -- scorro i gruppi di curve local vCrvGrps = EgtGetNameInGroup( nLayId, CONTOUR_GRP .. '*') for i = 1, #vCrvGrps do -- creo il gruppo per infill local nInfillPathGrp = EgtGroup( vCrvGrps[i]) EgtSetName( nInfillPathGrp, INFILL_GRP) EgtSetStatus( nInfillPathGrp, GDB_ST.OFF) EgtSetInfo( nInfillPathGrp, KEY_FILL_TYPE, nFillType) -- recupero la superficie occupata dalle shell local nSrfBase = EgtGetFirstNameInGroup( vCrvGrps[i], TOT_SHELL_TRIM_SURF) if not nSrfBase then -- se non esiste non c'è spazio per solid fill EgtOutLog( 'Warning : SolidFill not possibile (layer '.. EgtNumToString( s_nCurrIdx) ..') - CalcPaths') else -- calcolo la superficie da riempire local nSrfToFill, bNoOverlap = ComputeTrimSurf( nSrfBase, nInfillPathGrp, LayerParams.dInfillStrand, LayerParams.dInfillOverlap) if not nSrfToFill then -- errore EgtOutLog( 'Error : creation of SolidFill region failed (layer '.. EgtNumToString( s_nCurrIdx) ..') - CalcPaths') table.insert( s_vErr, ' - layer ' .. EgtNumToString( s_nCurrIdx) .. ' : creation of SolidFill region failed') elseif nSrfToFill == GDB_ID.NULL then EgtOutLog( 'Warning : SolidFill not possibile (layer '.. EgtNumToString( s_nCurrIdx) ..') - CalcPaths') else if bNoOverlap then EgtOutLog( 'Warning : SolidFill without correct overlap (layer '.. EgtNumToString( s_nCurrIdx) ..') - CalcPaths') end -- distanza tra passate tenendo conto dell'overlap indicato local dDist = ( 1 - LayerParams.dStrandOverlap / 100) * LayerParams.dInfillStrand -- inserisco il riempimento if nFillType == FILL_TYPE.OFFSET then -- recupero le shell precedenti dal PathGrp local nPathGrp = EgtGetFirstNameInGroup( vCrvGrps[i], PATH_GRP) local nLast = EgtGetLastNameInGroup( nPathGrp, SHELL_CRV .. '*') or EgtGetLastNameInGroup( nPathGrp, EXTRA_SHELL_CRV .. '*') local vOldIds = EgtGetNameInGroup( nPathGrp, EgtGetName( nLast)) if not ComputeOffsetShells( nSrfToFill, dDist, INFILL_CRV, TYPE.INFILL, nInfillPathGrp, vPtStart, vOldIds) then EgtOutLog( 'Error : creation of SolidFill failed (layer '.. EgtNumToString( s_nCurrIdx) ..') - CalcPaths') table.insert( s_vErr, ' - layer ' .. EgtNumToString( s_nCurrIdx) .. ' : creation of SolidFill failed') end elseif nFillType == FILL_TYPE.ZIGZAG then ComputeZigZagSolidFill( nSrfToFill, dDist, INFILL_CRV, TYPE.INFILL, nInfillPathGrp) end -- avendo riempito la regione, la TotShellTrimSurf non deve esistere EgtErase( nSrfBase) end end -- se gruppo vuoto lo cancello if not EgtGetFirstInGroup( nInfillPathGrp) then EgtErase( nInfillPathGrp) end end end -------------------------------------------------------------------- --------------------------- RIBS ----------------------------------- -------------------------------------------------------------------- local function VerifyRibsHoles( vIds) -- raggruppo i setti per nome local tabRibs = { { vIds[1]}} local sPrevName = EgtGetName( vIds[1]) for i = 2, #vIds do if sPrevName == EgtGetName( vIds[i]) then table.insert( tabRibs[#tabRibs], vIds[i]) else sPrevName = EgtGetName( vIds[i]) table.insert( tabRibs, { vIds[i]}) end end -- verifico se posso concatenare le curve con lo stesso nome usando come tolleranza lo strand del setto ( se le passate si toccano non ha senso tenerle separate) local nGrp = EgtGetParent( vIds[1]) for i = 1, #tabRibs do if #tabRibs[i] > 1 then local dStrand = EgtGetInfo( tabRibs[i][1], KEY_RIBS_STRAND, 'd') -- gruppo temporaneo per il concatenamento local nGrpTmp = EgtGroup( nGrp) for j = 1, #tabRibs[i] do EgtRelocateGlob( tabRibs[i][j], nGrpTmp) end EgtReorderCurvesInGroup( nGrpTmp, EgtSP( tabRibs[i][1], GDB_ID.ROOT), GDB_RT.GLOB, dStrand) -- recupero le curve e le concateno se possibile local vNewIds = EgtGetAllInGroup( nGrpTmp) local nCurrId = vNewIds[1] EgtRelocateGlob( nCurrId, nGrp) for j = 2, #vNewIds do if dist( EgtEP( nCurrId, GDB_ID.ROOT), EgtSP( vNewIds[j], GDB_ID.ROOT)) < dStrand + GEO.EPS_SMALL then EgtAddCurveCompoLine( nCurrId, EgtSP( vNewIds[j], GDB_ID.ROOT), GDB_RT.GLOB) EgtAddCurveCompoCurve( nCurrId, vNewIds[j]) else nCurrId = vNewIds[j] EgtRelocateGlob( nCurrId, nGrp) end end EgtErase( nGrpTmp) end end -- aggiorno gli id return EgtGetAllInGroup( nGrp) end -------------------------------------------------------------------- local function FindRibsUserLinkDirection( nCrv1, nCrv2) -- stabilisco l'orientamento del link local bCCW = false -- costruisco la superficie "definita" dal setto di partenza con i primi due setti che lo definiscono local nGrpTmp = EgtGroup( EgtGetParent( nCrv1)) local nSrfLoop = EgtCurveCompoFromPoints( nGrpTmp, {EgtEP( nCrv1), EgtSP( nCrv2)}) if not nSrfLoop then return false end EgtAddCurveCompoLine( nSrfLoop, EgtSP( nCrv2) + 100 * EgtSV( nCrv2)) EgtAddCurveCompoLine( nSrfLoop, EgtEP( nCrv1) - 100 * EgtEV( nCrv1)) 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, s_vtSlicing) then bCCW = true end EgtErase( nGrpTmp) return bCCW end ----------------------------------------------------------------------- local function FindAssociatedUserLinkParts( nStartRib, vRibs, vUsed, nGrpTmp, nType, nSrfTest) local tabUserLink = {} for i = 1, #vRibs do local nTypeCurr = EgtGetInfo( vRibs[i], KEY_RIBS_TYPE, 'i') -- verifico che il setto non sia già stato utilizzato in un altro UserLink e sia di tipologia compatibile if not vUsed[vRibs[i]] and nTypeCurr == nType then -- recupero setto di partenza non trimmato local nStartId = EgtGetInfo( vRibs[i], KEY_START_RIB, 'i') -- verifico se interseca nStartRib con un estremo local dParS = EgtCurveParamAtPoint( nStartRib, EgtSP( nStartId), 100 * GEO.EPS_SMALL) local dParE = EgtCurveParamAtPoint( nStartRib, EgtEP( nStartId), 100 * GEO.EPS_SMALL) if dParS and dParE then -- se entrambi gli estremi non ha senso aggiungerlo a UserLink elseif dParS or dParE then -- se solo un estremo verifico se si unisce a UserLink in tratto sensato local dPar = dParS or dParE local ptTest = EgtPoint( nGrpTmp, EgtUP( nStartRib, dPar)) local bExtJoint = EgtSurfFrTestExternal( nSrfTest, ptTest) if ( nType == RIB_TYPE.EXTERNAL and not bExtJoint) or ( nType ~= RIB_TYPE.EXTERNAL and bExtJoint) then -- lo aggiungo alla tabella di UserLink local tRib = { nId = vRibs[i], bStart = EgtIf( dParS, true, false), bOn = false, dPar = dPar} table.insert( tabUserLink, tRib) -- indico che il setto è stato utilizzato vUsed[vRibs[i]] = 1 end end end end return tabUserLink end ----------------------------------------------------------------------- local function AssignUserLinkInfo( tabUserLink, bCCW, bLoopRib, bSameSide, sName) -- ordino per paramentro crescente table.sort( tabUserLink, function(a,b) return a.dPar < b.dPar end) -- aggiorno le info dei tratti di UserLink per tenere conto delle aggiunte local bUseOppositeCondition = EgtIf( bSameSide, false, true) for i = 1, #tabUserLink do local nId = tabUserLink[i].nId EgtSetName( nId, sName) EgtSetInfo( nId, KEY_RIBS_USER_LINK, 1) EgtSetInfo( nId, KEY_RIBS_USER_LINK_CCW, bCCW) EgtSetInfo( nId, KEY_LOOP_RIB, bLoopRib) EgtSetInfo( nId, KEY_RIBS_USER_LINK_SAME_SIDE, bSameSide) EgtSetInfo( nId, KEY_RIBS_USER_LINK_TOT, #tabUserLink) -- riposiziono if i > 1 then EgtRelocateGlob( nId, tabUserLink[i-1].nId, GDB_IN.AFTER) end -- ordine local nPrevOrd = EgtGetInfo( nId, KEY_RIBS_USER_LINK_ORDER, 'i') local nCurrOrd = i - 1 EgtSetInfo( nId, KEY_RIBS_USER_LINK_ORDER, nCurrOrd) -- orientamento if tabUserLink[i].bOn then -- se il tratto apparteneva già a UserLink va invertito se order passa da pari a dispari o viceversa local bInvert = ( nPrevOrd and nPrevOrd % 2 ~= nCurrOrd % 2) or ( not nPrevOrd and i ~= 1 and i % 2 ~= 0) if bInvert then EgtInvertCurve( nId) UpdateInvertInfo( nId) end if not bSameSide then bUseOppositeCondition = not bUseOppositeCondition end else -- se tratto aggiunto dipende con quale estremo interseca il setto local bCondition = ( nCurrOrd % 2 == 0 and tabUserLink[i].bStart) or ( nCurrOrd % 2 ~= 0 and not tabUserLink[i].bStart) if bUseOppositeCondition ~= bCondition then EgtInvertCurve( nId) UpdateInvertInfo( nId) end end end end ------------------------------------------------------------------------ local function AdjustUserLinkRibs( tUserLink, vRibs, nSrfInt, nSrfExt, nGrp) local nGrpTmp = EgtGroup( nGrp) -- gruppo temporaneo per conti local vUsed = {} -- setti di vRibs utilizzati per UserLink -- verifico se posso aggiungere tratti extra agli UserLink già individuati for nStartRib, vAssociatedRibs in pairs( tUserLink) do -- verifico se ho tratti singoli da aggiungere a UserLink definito da nStartRib local nType = EgtGetInfo( nStartRib, KEY_RIBS_TYPE, 'i') local nSrfTest = EgtIf( nType == RIB_TYPE.EXTERNAL, nSrfExt, nSrfInt) local tabUserLink = FindAssociatedUserLinkParts( nStartRib, vRibs, vUsed, nGrpTmp, nType, nSrfTest) -- se ho tratti da aggiungere if #tabUserLink > 0 then -- recupero i tratti già individuati su UserLink for i = 1, #vAssociatedRibs do local dPar = EgtCurveParamAtPoint( nStartRib, EgtSP( vAssociatedRibs[i]), 100 * GEO.EPS_SMALL) local tRib = { nId = vAssociatedRibs[i], bStart = true, bOn = true, dPar = dPar} table.insert( tabUserLink, tRib) end -- recupero alcune info utili relative a UserLink local bCCW = EgtGetInfo( vAssociatedRibs[1], KEY_RIBS_USER_LINK_CCW, 'b') or false local bLoopRib = EgtGetInfo( vAssociatedRibs[1], KEY_LOOP_RIB, 'b') or false local bSameSide = EgtGetInfo( vAssociatedRibs[1], KEY_RIBS_USER_LINK_SAME_SIDE, 'b') or false local sName = EgtGetName( vAssociatedRibs[1]) -- assegno le proprietà AssignUserLinkInfo( tabUserLink, bCCW, bLoopRib, bSameSide, sName) end end -- verifico se tra i setti singoli rimasti posso trovare nuovi UserLink for i = 1, #vRibs do if not vUsed[vRibs[i]] then -- indico il corrente come utilizzato per non ricontrollarlo in FindAssociatedUserLinkParts vUsed[vRibs[i]] = 1 -- verifico se trovo setti associati ( e quindi definisce UserLink) local nStartRib = EgtGetInfo( vRibs[i], KEY_START_RIB, 'i') local nType = EgtGetInfo( vRibs[i], KEY_RIBS_TYPE, 'i') local nSrfTest = EgtIf( nType == RIB_TYPE.EXTERNAL, nSrfExt, nSrfInt) local tabUserLink = FindAssociatedUserLinkParts( nStartRib, vRibs, vUsed, nGrpTmp, nType, nSrfTest) if #tabUserLink > 0 then -- se definisce UserLink aggiungo setto di partenza alla tabella local dPar = EgtCurveParamAtPoint( nStartRib, EgtSP( vRibs[i]), 100 * GEO.EPS_SMALL) local tRib = { nId = vRibs[i], bStart = true, bOn = true, dPar = dPar} table.insert( tabUserLink, tRib) -- assegno le info local bCCW = false -- non posso conoscere a priori il verso del collegamento local bLoopRib = false local bSameSide = true local sName = EgtGetName( vRibs[i]) AssignUserLinkInfo( tabUserLink, bCCW, bLoopRib, bSameSide, sName) -- correggo orientamento del link bCCW = FindRibsUserLinkDirection( tabUserLink[1].nId, tabUserLink[2].nId) for i = 1, #tabUserLink do local nId = tabUserLink[i].nId EgtSetInfo( nId, KEY_RIBS_USER_LINK_CCW, bCCW) end else -- se non è UserLink lo rimuovo dalla tabella dei tratti utilizzati per controllarlo nelle iterazioni successive vUsed[vRibs[i]] = nil end end end EgtErase( nGrpTmp) end ------------------------------------------------------------------- local function FindAssociatedHoledRib( vRibs, nCrv) -- trovo setto di vRibs che poggia su nCrv if not nCrv then return end if not vRibs or #vRibs == 0 then return end for i = 1, #vRibs do -- verifico se ha un estremo sulla curva local ptS = EgtSP( vRibs[i], GDB_ID.ROOT) local dParS = EgtCurveParamAtPoint( nCrv, ptS, 100 * GEO.EPS_SMALL, GDB_RT.GLOB) if dParS then return i, true else local ptE = EgtEP( vRibs[i], GDB_ID.ROOT) local dParE = EgtCurveParamAtPoint( nCrv, ptE, 100 * GEO.EPS_SMALL, GDB_RT.GLOB) if dParE then return i, false end end end return end ------------------------------------------------------------------- local function FindHoleCurve( pt, vLoopIds) -- trovo indice della curva di vLoopIds a cui appartiene pt ( in globale) if not vLoopIds or #vLoopIds == 0 then return end for i = 1, #vLoopIds do local dPar = EgtCurveParamAtPoint( vLoopIds[i], pt, 100 * GEO.EPS_SMALL, GDB_RT.GLOB) if dPar then return i end end return end ------------------------------------------------------------------- local function ReorderHoledRibs( vRibs, tHoles, bInvertOrder) local vUserLink = {} -- vettore con gli id dei tratti di UserLink local tUserLink = {} -- chiave = setto, valore = true/false se userlink oppure no for i = 1, #vRibs do local bUserLink = EgtGetInfo( vRibs[i], KEY_RIBS_USER_LINK, 'b') or false tUserLink[vRibs[i]] = bUserLink if bUserLink then table.insert( vUserLink, vRibs[i]) end end local nRelocatePosFirst = EgtIf( bInvertOrder, GDB_IN.AFTER, GDB_IN.BEFORE) local nRelocatePos = EgtIf( bInvertOrder, GDB_IN.BEFORE, GDB_IN.AFTER) local nIdx = 1 while nIdx <= #vUserLink do local nTot = EgtGetInfo( vUserLink[nIdx], KEY_RIBS_USER_LINK_TOT, 'i') local nFirst = vUserLink[nIdx] local nLast = vUserLink[nIdx + nTot - 1] if bInvertOrder then -- i tratti di UserLink saranno ordinati in senso opposto nFirst, nLast = nLast, nFirst end -- primo tratto di UserLink local vAssRibs = tHoles[nFirst] or {} for j = #vAssRibs, 1, -1 do if not tUserLink[vAssRibs[j]] then EgtRelocateGlob( vAssRibs[j], nFirst, nRelocatePosFirst) end end -- altri tratti di UserLink for k = 1, nTot - 1 do local nCurrIdx = EgtIf( bInvertOrder, nIdx + nTot - 1 - k, nIdx + k) local vAssRibs = tHoles[vUserLink[nCurrIdx]] or {} for j = #vAssRibs, 1, -1 do if not tUserLink[vAssRibs[j]] then EgtRelocateGlob( vAssRibs[j], nLast, nRelocatePos) end end end -- passo al gruppo di UserLink successivo nIdx = nIdx + nTot end end ------------------------------------------------------------------- local function AdjustHoledRibs( nTrimmedRibsGrp, nSrfInt, nSrfExt) local vRibs = EgtGetAllInGroup( nTrimmedRibsGrp) if not vRibs then return end -- recupero i loop della superficie del setto local nLoopGrp = EgtGetFirstNameInGroup( s_nPartId, RIBS_LOOP_GRP) -- estraggo eventuali loop interni dalle superfici di trim local vLoopInt = {} local vLoopExt = {} local vSurfs = { nSrfInt, nSrfExt} for i = 1, 2 do if vSurfs[i] then local nChunk = EgtSurfFrChunkCount( vSurfs[i]) for nC = 0, nChunk - 1 do local nRes, nCnt = EgtExtractSurfFrChunkLoops( vSurfs[i], nC, nTrimmedRibsGrp) if nCnt > 1 then EgtTableAdd( EgtIf( i == 1, vLoopInt, vLoopExt), nRes + 1, nCnt - 1) end EgtErase( nRes) end end end -- individuo catena di setti che è stata interrotta dagli holes partendo dai setti con user link local bHoles = false local tHoles = {} while #vRibs > 0 do -- cerco il primo setto di tipo UserLink local nRefRib for i = 1, #vRibs do local bUserLink = EgtGetInfo( vRibs[i], KEY_RIBS_USER_LINK, 'b') or false if bUserLink then nRefRib = vRibs[i] table.remove( vRibs, i) break end end if not nRefRib then break end local sName = EgtGetName( nRefRib) -- recupero eventuali loop interessati dal setto local nOrigSrfId = EgtGetInfo( nRefRib, KEY_ORIGINAL_SURF, 'i') local nType = EgtGetInfo( nRefRib, KEY_RIBS_TYPE, 'i') local vLoopIds = EgtGetNameInGroup( nLoopGrp, SURF_LOOP .. tostring( nOrigSrfId)) if nType == RIB_TYPE.INTERNAL then EgtJoinTables( vLoopIds, vLoopInt) elseif nType == RIB_TYPE.EXTERNAL then EgtJoinTables( vLoopIds, vLoopExt) end -- verifico se è limitato da un hole local ptS = EgtSP( nRefRib, GDB_ID.ROOT) local ptE = EgtEP( nRefRib, GDB_ID.ROOT) local nIdx = FindHoleCurve( ptS, vLoopIds) local bStartOrig = true if not nIdx then nIdx = FindHoleCurve( ptE, vLoopIds) bStartOrig = false end if nIdx then tHoles[nRefRib] = {} -- trovo tutti i setti associati local nAssIdx, bStart = FindAssociatedHoledRib( vRibs, vLoopIds[nIdx]) while nAssIdx do bHoles = true local nCurrRib = vRibs[nAssIdx] local ptRef = EgtIf( bStart, EgtEP( nCurrRib, GDB_ID.ROOT), EgtSP( nCurrRib, GDB_ID.ROOT)) local bUserLink = EgtGetInfo( nCurrRib, KEY_RIBS_USER_LINK, 'b') or false if not bUserLink then -- se non è coinvolto in altro user link assegno lo stesso orientamento e lo stesso nome if bStartOrig == bStart then EgtInvertCurve( nCurrRib) UpdateInvertInfo( nCurrRib) end EgtSetName( nCurrRib, sName) end table.insert( tHoles[nRefRib], nCurrRib) table.remove( vRibs, nAssIdx) -- verifico se con l'altro estermo poggia su hole e trovo setto associato local nIdx = FindHoleCurve( ptRef, vLoopIds) nAssIdx, bStart = FindAssociatedHoledRib( vRibs, vLoopIds[nIdx]) end end end -- se no holes esco if not bHoles then return end -- riordino vRibs = EgtGetAllInGroup( nTrimmedRibsGrp) local bInvertOrder = EgtGetInfo( vRibs[1], KEY_RIBS_INVERT_STRAND_ORDER, 'b') or false ReorderHoledRibs( vRibs, tHoles, bInvertOrder) -- gestione per eventuale InvertDirection local bInvertDir = EgtGetInfo( vRibs[1], KEY_RIBS_INVERT_DIR, 'b') or false if bInvertDir then for nRib1, vAssRibs in pairs( tHoles) do local nRib2 = vAssRibs[#vAssRibs] if nRib2 then -- se entrambi coinvolti in UserLink scambio le direzioni local bUserLink1 = EgtGetInfo( nRib1, KEY_RIBS_USER_LINK, 'b') or false local bUserLink2 = EgtGetInfo( nRib2, KEY_RIBS_USER_LINK, 'b') or false if bUserLink1 and bUserLink2 then local bInvert1 = EgtGetInfo( nRib1, KEY_INVERTED_CRV, 'b') or false local bInvert2 = EgtGetInfo( nRib2, KEY_INVERTED_CRV, 'b') or false if bInvert1 ~= bInvert2 then EgtInvertCurve( nRib1) UpdateInvertInfo( nRib1) EgtInvertCurve( nRib2) UpdateInvertInfo( nRib2) end end -- scambio le info SwapInfo( nRib1, nRib2, KEY_RIBS_USER_LINK, 'b', false) SwapInfo( nRib1, nRib2, KEY_RIBS_USER_LINK_ORDER, 'i', 0) SwapInfo( nRib1, nRib2, KEY_RIBS_USER_LINK_TOT, 'i', 0) SwapInfo( nRib1, nRib2, KEY_RIBS_USER_LINK_CCW, 'b', false) -- scambio la posizione local nCopy = EgtCopyGlob( nRib2, nRib2, GDB_IN.AFTER) EgtRelocateGlob( nRib2, nRib1, GDB_IN.AFTER) EgtRelocateGlob( nRib1, nCopy, GDB_IN.AFTER) EgtErase( nCopy) end end end -- elimino loop dello slice utilizzati for i = 1, #vLoopInt do EgtErase( vLoopInt[i]) end for i = 1, #vLoopExt do EgtErase( vLoopExt[i]) end end ------------------------------------------------------------------- local function TrimRibs( vRibs, nRibsGrp, nSrfTrimInt, nSrfTrimExt) -- trim dei setti local nTrimmedRibsGrp = EgtGroup( nRibsGrp) local tUserLink = {} -- tratti appartenenti a UserLink local vSingleRibs = {} -- tratti singoli for i = 1, #vRibs do -- trim dei setti local nType = EgtGetInfo( vRibs[i], KEY_RIBS_TYPE, 'i') local nCopyRib = EgtCopyGlob( vRibs[i], nTrimmedRibsGrp) local nCrv, nCnt -- setto interno if nType == RIB_TYPE.INTERNAL or nType == RIB_TYPE.SUPPORT then if nSrfTrimInt == GDB_ID.NULL then -- se la superficie non esiste, il setto deve essere cancellato perchè non c'è spazio nCrv = nCopyRib nCnt = 0 elseif nSrfTrimInt then nCrv, nCnt = EgtTrimCurveWithRegion( nCopyRib, nSrfTrimInt, true, true) end -- setto esterno elseif nType == RIB_TYPE.EXTERNAL then if nSrfTrimExt ~= GDB_ID.NULL then nCrv, nCnt = EgtTrimCurveWithRegion( nCopyRib, nSrfTrimExt, false, true) end end -- se nCrv non definito ( per errore nel trim o perchè il setto va conservato) riprendo il setto originario if not nCrv then nCrv = nCopyRib nCnt = 1 end if nCnt == 0 then -- il setto va eliminato EgtErase( nCrv) elseif nCnt == 1 then -- tratto singolo EgtSetInfo( nCrv, KEY_START_RIB, vRibs[i]) table.insert( vSingleRibs, nCrv) EgtSetInfo( vRibs[i], KEY_ASSOCIATED_CRVS, {nCrv}) else -- UserLink tUserLink[vRibs[i]] = {} local bCCW = FindRibsUserLinkDirection( nCrv, nCrv + 1) -- sistemo le info for j = 0, nCnt - 1 do EgtSetInfo( nCrv + j, KEY_START_RIB, vRibs[i]) EgtSetInfo( nCrv + j, KEY_RIBS_USER_LINK, 1) EgtSetInfo( nCrv + j, KEY_RIBS_USER_LINK_ORDER, j) EgtSetInfo( nCrv + j, KEY_RIBS_USER_LINK_TOT, nCnt) EgtSetInfo( nCrv + j, KEY_RIBS_USER_LINK_CCW, bCCW) -- se setto di partenza è chiuso è LoopRib if EgtCurveIsClosed( vRibs[i]) then EgtSetInfo( nCrv + j, KEY_LOOP_RIB, 1) end -- se ho solo due tratti allora il link è realizzato da un solo lato if nCnt == 2 then EgtSetInfo( nCrv + j, KEY_RIBS_USER_LINK_SAME_SIDE, 1) end table.insert( tUserLink[vRibs[i]], nCrv + j) end EgtSetInfo( vRibs[i], KEY_ASSOCIATED_CRVS, tUserLink[vRibs[i]]) end end -- verifico e sistemo UserLink AdjustUserLinkRibs( tUserLink, vSingleRibs, nSrfTrimInt, nSrfTrimExt, nRibsGrp) -- verifico se necessari aggiustamenti per holes AdjustHoledRibs( nTrimmedRibsGrp, nSrfTrimInt, nSrfTrimExt) return nTrimmedRibsGrp end -------------------------------------------------------------------- local function ComputeRibsOrientedOffset( nRibsGrp) 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') -- 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 local dStrand = EgtGetInfo( vIds[i], KEY_RIBS_STRAND, 'd') local dStrandOverlap = EgtGetInfo( vIds[i], KEY_RIBS_STRAND_OVERLAP, 'd') or 0 local dOffs = ( nShellsNbr - 1) * ( 1 - dStrandOverlap / 100) * dStrand / 2 -- 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 local vOffsRib = {} for k = 0, nShellsNbr - 1 do local dOffsCurr = dOffs - k * ( 1 - dStrandOverlap / 100) * dStrand local nNewId if abs( dOffsCurr) < GEO.EPS_SMALL then nNewId = EgtCopyGlob( vIds[i], nOffsGrp) else nNewId = EgtOffsetCurveAdv( vIds[i], EgtIf( bPlusToMinus, dOffsCurr, - dOffsCurr), GDB_OT.FILLET, s_dOffsTol) 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) table.insert( vOffsRib, nNewId) end end EgtSetInfo( vIds[i], KEY_ASSOCIATED_CRVS, vOffsRib) 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 nLinkTot % 2 ~= 0)) 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 FindRibWithSameTrimSurf( tOffs, dOffs, nType) for nId, dCurrOffs in pairs( tOffs) do local nCurrType = EgtGetInfo( nId, KEY_RIBS_TYPE, 'i') if nCurrType == nType and abs( dOffs - dCurrOffs) < GEO.EPS_SMALL then return nId end end return end -------------------------------------------------------------------- local function ComputeTrimSurfWithOverlapsForRibs( vIds, nGrp, nSrfInt, nSrfExt, nLoopGrp) -- ad ogni setto ottenuto dallo slicing associo la superficie con cui fare trim : nSurfId se setto da trimmare, nil se setto da cancellare, GDB_ID.NULL se setto da non trimmare local tOffs = {} local tSurfOffs = {} for i = 1, #vIds do local dStrand = EgtGetInfo( vIds[i], KEY_RIBS_STRAND, 'd') local dOverlap = EgtGetInfo( vIds[i], KEY_RIBS_OVERLAP, 'd') local nType = EgtGetInfo( vIds[i], KEY_RIBS_TYPE, 'i') local dOffs = dStrand * ( 0.5 - dOverlap / 100) -- verifico se la superficie è già stata calcolata local nRefId = FindRibWithSameTrimSurf( tOffs, dOffs, nType) if nRefId then tSurfOffs[vIds[i]] = tSurfOffs[nRefId] else if nType == RIB_TYPE.INTERNAL or nType == RIB_TYPE.SUPPORT then if nSrfInt == GDB_ID.NULL then -- se la superficie non esiste non c'è spazio per il setto che va cancellato EgtOutLog( 'Warning : rib not possibile (layer '.. EgtNumToString( s_nCurrIdx) ..') - CalcPaths') else local nTrimSurf, bNoOverlap = ComputeTrimSurf( nSrfInt, nGrp, dStrand, dOverlap) if not nTrimSurf then EgtOutLog( 'Error : creation of trim region for internal rib failed (layer '.. EgtNumToString( s_nCurrIdx) ..') - CalcPaths') table.insert( s_vErr, ' - layer ' .. EgtNumToString( s_nCurrIdx) .. ' : creation of trim region for rib failed') elseif nTrimSurf == GDB_ID.NULL then EgtOutLog( 'Warning : rib not possibile (layer '.. EgtNumToString( s_nCurrIdx) ..') - CalcPaths') else if bNoOverlap then EgtOutLog( 'Warning : internal rib without correct overlap (layer '.. EgtNumToString( s_nCurrIdx) ..') - CalcPaths') end EgtSetName( nTrimSurf, TOT_SHELL_TRIM_SURF) tSurfOffs[vIds[i]] = nTrimSurf end end elseif nType == RIB_TYPE.EXTERNAL then if not nSrfExt then -- sono in un CrvGrp intermedio, il setto va cancellato elseif nSrfExt == GDB_ID.NULL then -- se la superficie non esiste il setto va conservato tSurfOffs[vIds[i]] = GDB_ID.NULL else local nTrimSurf, bNoOverlap = ComputeTrimSurf( nSrfExt, nGrp, - dStrand, dOverlap) if not nTrimSurf then EgtOutLog( 'Error : creation of trim region for external rib failed (layer '.. EgtNumToString( s_nCurrIdx) ..') - CalcPaths') table.insert( s_vErr, ' - layer ' .. EgtNumToString( s_nCurrIdx) .. ' : creation of trim region for external rib failed') else if bNoOverlap then EgtOutLog( 'Warning : external rib without correct overlap (layer '.. EgtNumToString( s_nCurrIdx) ..') - CalcPaths') end EgtSetName( nTrimSurf, TOT_SHELL_TRIM_SURF) tSurfOffs[vIds[i]] = nTrimSurf end end else -- il setto unbounded deve comparire solo nell'ultimo CrvGrp senza alcun trim. Se nSrfExt non è definita sono in un CrvGrp intermedio e il setto va cancellato -- se nSrfExt è definita allora il setto non va trimmato if nSrfExt then tSurfOffs[vIds[i]] = GDB_ID.NULL end end tOffs[vIds[i]] = dOffs end end -- estraggo i contorni local vSurfIds = EgtGetNameInGroup( nGrp, TOT_SHELL_TRIM_SURF) or {} for i = 1, #vSurfIds do local nChunksNbr = EgtSurfFrChunkCount( vSurfIds[i]) for j = 0, nChunksNbr - 1 do local nRes, nCnt = EgtExtractSurfFrChunkLoops( vSurfIds[i], j, nLoopGrp) for k = nRes, nRes + nCnt - 1 do EgtSetName( k, TRIM_SURF_LOOP) end end end return tSurfOffs end -------------------------------------------------------------------- local function VerifyRibsIntersectionValidity( nIntersId, nSrfInt, nSrfExt, nType1, nType2) if nType1 == RIB_TYPE.UNBOUNDED and nType2 == RIB_TYPE.UNBOUNDED then -- l'intersezione è sempre valida return true elseif nType1 == RIB_TYPE.EXTERNAL or nType2 == RIB_TYPE.EXTERNAL then if not nSrfExt or nSrfExt == GDB_ID.NULL then -- se la surf non esiste l'intersezione è sicuramente esterna return true else -- l'intersezione deve essere esterna return EgtSurfFrTestExternal( nSrfExt, nIntersId) end else if nSrfInt == GDB_ID.NULL then -- se la superficie non esiste, l'intersezione è sicuramente esterna return false else -- l'intersezione deve essere interna return not EgtSurfFrTestExternal( nSrfInt, nIntersId) end end return false end -------------------------------------------------------------------- local function VerifyRibsIntersection( nRib1, nRib2, nType1, nType2, nSrfInt, nSrfExt, nGrp, nOffsGrp) -- restituisce se intersezione ( bInters) e se taglio va forzato sulla curva1 ( bForceCrv1Cut) -- 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, false end -- se hanno lo stesso nome derivano dalla stessa costolatura quindi non ha senso controllare intersezione -- ( non vengono gestiti setti che si autointersecano) if EgtGetName( nRib1) == EgtGetName( nRib2) then return false, false end -- 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 in modo valido local bForceCrv1Cut = false local nOrigInt, nPntCnt, nCrvCnt = EgtCurveCurveInters( nCrv1, nCrv2, nGrp) if nOrigInt then local bInters = false -- scorro tutti i punti di intersezione trovati for nPtId = nOrigInt, nOrigInt + nPntCnt - 1 do -- verifico se forza il taglio sulla curva 1 ( indipendentemente dalla validità) if not bForceCrv1Cut 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 end if VerifyRibsIntersectionValidity( nPtId, nSrfInt, nSrfExt, nType1, nType2) then bInters = true if bForceCrv1Cut then return true, true -- intersezione, forza taglio sulla crv1 end end end if bInters then return true, false -- intersezione, non forza taglio su crv1 end end -- se le curve non si intersecano in modo valido, verifico se lo fanno i loro offset local vOffs1 = EgtGetNameInGroup( nOffsGrp, EgtGetName( nCrv1)) or {} local vOffs2 = EgtGetNameInGroup( nOffsGrp, EgtGetName( nCrv2)) or {} local nOffs1Inters = 0 -- numero di offset di nCrv1 coinvolti nelle intersezioni for i = 1, #vOffs1 do local nOffs1 = EgtCopyGlob( vOffs1[i], nGrp) local bInters = false for j = 1, #vOffs2 do if bInters then break end -- se già trovato intersezione non ho bisogno di analizzare gli altri offset local nOffs2 = EgtCopyGlob( vOffs2[j], nGrp) local nId, nPntCnt, nCrvCnt = EgtCurveCurveInters( nOffs1, nOffs2, nGrp) if nId then for nPtId = nId, nId + nPntCnt - 1 do if VerifyRibsIntersectionValidity( nPtId, nSrfInt, nSrfExt, nType1, nType2) then -- intersezione valida bInters = true nOffs1Inters = nOffs1Inters + 1 break end end end end end if nOffs1Inters > 0 then if nOrigInt then -- se i setti originiari si intersecavano il forzare il taglio sulla curva1 dipende dalla loro intersezione anche se non valida return true, bForceCrv1Cut else return true, nOffs1Inters == #vOffs1 end end -- se le curve di offset non si intersecano verifico se lo fanno le loro SurfFatCurve local dStrand1 = EgtGetInfo( nCrv1, KEY_RIBS_STRAND, 'd') local dStrand2 = EgtGetInfo( nCrv2, KEY_RIBS_STRAND, 'd') local dOverlap2 = EgtGetInfo( nCrv2, KEY_RIBS_OVERLAP, 'd') for i = 1, #vOffs1 do for j = 1, #vOffs2 do local nSrfOffs = EgtSurfFrFatCurve( nGrp, vOffs1[i], 0.5 * dStrand1 + dStrand2 * ( 0.5 - dOverlap2 / 100), false, false, s_dOffsTol) if nSrfOffs then local nRes = EgtCurveWithRegionClassify( vOffs2[j], nSrfOffs) if nRes ~= GDB_CRC.OUT then return true, false end end end end return false, false end --------------------------------------------------------------------------------- -- Funzione che sistema le intersezioni fra costolature nel caso generico local function AdjustRibsOffsetForIntersection( nCrv1, nCrv2, nOffsGrp, nLoopGrp, nSrfTrim, nType2) -- recupero gli offset della curva secondaria ( nCrv2) local vOffs2 = EgtGetNameInGroup( nOffsGrp, EgtGetName( nCrv2)) or {} local nShells = EgtGetInfo( nCrv1, KEY_RIBS_SHELLS_NBR, 'i') local dStrand1 = EgtGetInfo( nCrv1, KEY_RIBS_STRAND, 'd') local dStrandOverlap1 = EgtGetInfo( nCrv1, KEY_RIBS_STRAND_OVERLAP, 'd') or 0 local dOverlap = EgtGetInfo( nCrv2, KEY_RIBS_OVERLAP, 'i') local dStrand2 = EgtGetInfo( nCrv2, KEY_RIBS_STRAND, 'd') if dOverlap / 100 * dStrand2 > ( nShells - 1) * ( 1 - dStrandOverlap1 / 100) * dStrand1 * 0.5 + dStrand1 * 0.5 - GEO.EPS_SMALL then -- non ha senso spezzare la curva, aggiorno solo split order dei suoi offset for i = 1, #vOffs2 do CopyInfo( nCrv2, vOffs2[i], KEY_SPLIT_ORDER, 'i') end return end -- calcolo la superficie della curva principale ( nCrv1) da usare per trim local dOffs = ( nShells - 1) * ( 1 - dStrandOverlap1 / 100) * dStrand1 * 0.5 + dStrand1 * 0.5 + dStrand2 * ( 0.5 - dOverlap / 100) local nSrf = EgtSurfFrFatCurve( nOffsGrp, nCrv1, dOffs, false, false, s_dOffsTol) if not nSrf then EgtOutLog( 'Error : ribs intersection failed (layer '.. EgtNumToString( s_nCurrIdx) ..') - CalcPaths') table.insert( s_vErr, ' - layer ' .. EgtNumToString( s_nCurrIdx) .. ' : error in computing ribs intersection') return end 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 -- salvo i loop da usare nel toolpath per ingressi e uscite local nSrfRef -- recupero la superficie di bordo con lo stesso overlap if nSrfTrim and nSrfTrim ~= GDB_ID.NULL then nSrfRef = EgtCopyGlob( nSrfTrim, nLoopGrp) if nType2 == RIB_TYPE.INTERNAL or nType2 == RIB_TYPE.SUPPORT then EgtSurfFrSubtract( nSrfRef, nSrf) elseif nType2 == RIB_TYPE.EXTERNAL then EgtSurfFrAdd( nSrfRef, nSrf) end EgtErase( nSrf) else EgtInvertSurf( nSrf) nSrfRef = nSrf end -- estraggo i loop local nChunks = EgtSurfFrChunkCount( nSrfRef) for i = 0, nChunks - 1 do local nRes, nCnt = EgtExtractSurfFrChunkLoops( nSrfRef, i, nLoopGrp) for j = nRes, nRes + nCnt - 1 do EgtSetName( j, SURF_LOOP) end end EgtErase( nSrfRef) end -------------------------------------------------------------------- -- Funzione che sistema le intersezioni fra costolature nel caso di 2 passate local function AdjustRibsOffsetForIntersection2Shells( nCrv1, nCrv2, nOffsGrp) -- costruisco le superfici da usare per trim local dStrand1 = EgtGetInfo( nCrv1, KEY_RIBS_STRAND, 'd') local dStrandOverlap1 = EgtGetInfo( nCrv1, KEY_RIBS_STRAND_OVERLAP, 'd') or 0 local nSrf1 = EgtSurfFrFatCurve( nOffsGrp, nCrv1, ( 1 - dStrandOverlap1 / 100) * dStrand1 * 0.5, false, false, s_dOffsTol) local dStrand2 = EgtGetInfo( nCrv2, KEY_RIBS_STRAND, 'd') local dStrandOverlap2 = EgtGetInfo( nCrv2, KEY_RIBS_STRAND_OVERLAP, 'd') or 0 local nSrf2 = EgtSurfFrFatCurve( nOffsGrp, nCrv2, ( 1 - dStrandOverlap2 / 100) * dStrand2 * 0.5, false, false, s_dOffsTol) -- trim degli offset di nCrv1 local vOffs1 = EgtGetNameInGroup( nOffsGrp, EgtGetName( nCrv1)) or {} 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)) or {} 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, nOffsGrp, nRibsPathGrp, nSrfInt, nSrfExt, bAllTwoStrands, vTypeSequence, nLoopGrp, tSurfOffs) local bSpecialCase = false local vAllRibsIds = EgtGetNameInGroup( nRibsGrp, RIBS_CRV .. '*') -- setti originali local vRibsIds = {} -- ignoro setti che non hanno passate corrispondenti for i = 1, #vAllRibsIds do local vOffs = EgtGetNameInGroup( nRibsPathGrp, EgtGetName( vAllRibsIds[i])) if vOffs and #vOffs > 0 then table.insert( vRibsIds, vAllRibsIds[i]) end end -- creo un gruppo con frame locale per calcolare le intersezioni ( è il piano XY locale dove calcolare intersezioni) local frLoc = Frame3d( ORIG(), s_vtSlicing) local nGrpTmp = EgtGroup( nRibsGrp, frLoc, GDB_RT.GLOB) local bInters = false 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, nSrfInt, nSrfExt, 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 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, nRibsPathGrp) bSpecialCase = true else AdjustRibsOffsetForIntersection( nCrv1, nCrv2, nRibsPathGrp, nLoopGrp, tSurfOffs[nCrv2], nType2) end end end end EgtErase( nGrpTmp) return bInters, bSpecialCase end --------------------------------------------------------------------- local function VerifySplitAssociation( nRib1, nRib2, dStrand) local dDist1 = EgtPointCurveDist( EgtMP( nRib1), nRib2) local dDist2 = EgtPointCurveDist( EgtMP( nRib2), nRib1) -- verifico siano sufficientemente vicini 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( nRib2, KEY_RIBS_USER_LINK, 'b') or false local bSplitAfterTrim1 = EgtGetInfo( nRib1, KEY_SPLIT_AFTER_TRIM, 'b') or false local bSplitAfterTrim2 = EgtGetInfo( nRib2, KEY_SPLIT_AFTER_TRIM, 'b') or false if bSplitAfterTrim1 ~= bSplitAfterTrim2 then if not bSplitAfterTrim2 and bSplitAfterTrim1 then local nOrd = EgtGetInfo( nRib2, KEY_SPLIT_AFTER_TRIM_ORDER, 'i') if nOrd == 0 then return true end end if bSplitAfterTrim1 then local nOrd = EgtGetInfo( nRib1, KEY_SPLIT_AFTER_TRIM_ORDER, 'i') local nTot = EgtGetInfo( nRib1, KEY_SPLIT_AFTER_TRIM_TOT, 'i') if nOrd == nTot - 1 then return true end end else return true end end return false end --------------------------------------------------------------------- local function FindAssociatedSplitRibs( vRibs, dStrand) local vAssociatedRibs = {} -- vettore di flag per indicare se corrispondente elemento di vRibs è già stato associato ad un gruppo local vUsed = {} for i = 1, #vRibs do vUsed[i] = false end local nCurrId = vRibs[1] vUsed[1] = true while nCurrId do -- definisco un nuovo gruppo di setti associati local vCurrGrp = { nCurrId} local bFound = true while bFound do -- appena aggiungo un nuovo elemento al gruppo riparto a controllare tutti i setti non ancora associati per vedere quale posso aggiungere bFound = false for i = 2, #vRibs do if bFound then break end if not vUsed[i] then for j = 1, #vCurrGrp do if VerifySplitAssociation( vCurrGrp[j], vRibs[i], dStrand) then bFound = true table.insert( vCurrGrp, vRibs[i]) vUsed[i] = true break end end end end end -- quando non ho più setti da aggiungere al gruppo corrente -- riordino il gruppo appena individuato if #vCurrGrp == 2 then -- lascio l'ordinamento 1,2 EgtRelocateGlob( vCurrGrp[2], vCurrGrp[1], GDB_IN.AFTER) elseif #vCurrGrp > 2 then -- calcolo ordinamento ottimale con shorest path EgtSpInit() for i = 1, #vCurrGrp do local ptS = EgtSP( vCurrGrp[i], GDB_ID.ROOT) local ptE = EgtEP( vCurrGrp[i], GDB_ID.ROOT) EgtSpAddPoint( ptS:getX(), ptS:getY(), ptS:getZ(), 0, 0, ptE:getX(), ptE:getY(), ptE:getZ(), 0, 0) end local vOrd = EgtSpCalculate( SHP_TY.OPEN) EgtSpTerminate() local vNewOrd = {} for i = 1, #vOrd do table.insert( vNewOrd, vCurrGrp[vOrd[i]]) end -- riposiziono il primo elemento ( solo se è cambiato) if vOrd[1] ~= 1 then EgtRelocateGlob( vNewOrd[1], vCurrGrp[1], GDB_IN.AFTER) end -- riposiziono gli altri elementi for i = 2, #vNewOrd do EgtRelocateGlob( vNewOrd[i], vNewOrd[i-1], GDB_IN.AFTER) end vCurrGrp = vNewOrd end -- inserisco nella tabella il gruppo trovato table.insert( vAssociatedRibs, vCurrGrp) -- cerco il prossimo setto per un nuovo gruppo nCurrId = nil for i = 1, #vRibs do if not vUsed[i] then nCurrId = vRibs[i] vUsed[i] = true break end end end return vAssociatedRibs end --------------------------------------------------------------------- local function ReorderSplitRibs( vIds, 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 local tUserLinkSameSide = {} 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') local dStrand = EgtGetInfo( tabVal[1], KEY_RIBS_STRAND, 'd') 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 = FindAssociatedSplitRibs( tabVal, dStrand) -- 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 bSameSide = EgtGetInfo( tAssociatedRibs[1][1], KEY_RIBS_USER_LINK_SAME_SIDE, 'b') or false 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 if bSameSide and nTotParts > 2 then -- salvo gli id che andaranno collegati nella tabella tUserLinkSameSide local sName = EgtGetName( tAssociatedRibs[1][1]) -- eventuale creazione della voce nella tabella if not tUserLinkSameSide[sName] then tUserLinkSameSide[sName] = {} end for i = 1, #tAssociatedRibs[1] do table.insert( tUserLinkSameSide[sName], tAssociatedRibs[1][i]) end else -- ordinamento if ( bInvertOrder and nLinkOrder % 2 ~= 0 ) or ( not bInvertOrder 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 nLinkOrder > 0) then local vLastGrp = tAssociatedRibs[#tAssociatedRibs] for j = 1, #vLastGrp do EgtInvertCurve( vLastGrp[j]) UpdateInvertInfo( vLastGrp[j]) end end end end end end end for k, vRibs in pairs( tUserLinkSameSide) do table.sort( vRibs) for i = 2, #vRibs do EgtRelocateGlob( vRibs[i], vRibs[i-1], GDB_IN.AFTER) 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} elseif #tabRibs == 2 then -- se due gruppi fisso l'ordinamento per evitare inversioni tra i layers vOrd = { 1, 2} 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) local vIds = EgtGetNameInGroup( nGrp, RIBS_CRV .. '*') if not vIds or #vIds == 0 then return end -- riordino setti splittati ReorderSplitRibs( vIds, 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_STRAND, 'd') 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, 'd') CopyInfo( vOrig[i], nId, KEY_RIBS_STRAND_OVERLAP, 'd') CopyInfo( vOrig[i], nId, KEY_RIBS_TYPE, 'i') CopyInfo( vOrig[i], nId, KEY_RIBS_LINK, 'b') CopyInfo( vOrig[i], nId, KEY_RIBS_LINK_FILLET, 'd') CopyInfo( vOrig[i], nId, KEY_RIBS_LEAD_FILLET, 'd') 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, 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 local dStrand = EgtGetInfo( vCopy[1], KEY_RIBS_STRAND, 'd') -- 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 local 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, vPtStart, bIgnoreMergedRibs) -- recupero i setti local vAllRibs = EgtGetNameInGroup( nRibsGrp, RIBS_CRV .. '*') local vOrigRibs = {} if bIgnoreMergedRibs then -- escludo i setti che sono stati già uniti nel percorso delle shell for i = 1, #vAllRibs do local nType = EgtGetInfo( vAllRibs[i], KEY_RIBS_TYPE, 'i') local bMergeWithShells = EgtGetInfo( vAllRibs[i], KEY_RIBS_MERGE_WITH_SHELLS, 'b') or false if not ( nType == RIB_TYPE.INTERNAL and bMergeWithShells) then table.insert( vOrigRibs, vAllRibs[i]) end end else vOrigRibs = vAllRibs end if #vOrigRibs == 0 then return end -- 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 -- verifico se tutte le costolature vengono fatte con 2 passate e con lo stesso strand local bAllTwoStrands = true local dStrandRef = EgtGetInfo( vOrigRibs[1], KEY_RIBS_STRAND, 'd') for i = 1, #vOrigRibs do local nShells = EgtGetInfo( vOrigRibs[i], KEY_RIBS_SHELLS_NBR, 'i') local dStrand = EgtGetInfo( vOrigRibs[i], KEY_RIBS_STRAND, 'd') if nShells ~= 2 or abs( dStrand - dStrandRef) > GEO.EPS_SMALL then bAllTwoStrands = false break end end -- verifico se posso ignorare eventuali buchi nei setti vOrigRibs = VerifyRibsHoles( vOrigRibs) local nTotSrfInt = GDB_ID.NULL local nTotSrfExt = GDB_ID.NULL -- scorro i gruppi di curve local vCrvGrps = EgtGetNameInGroup( nSliceGrp, CONTOUR_GRP .. '*') for i = 1, #vCrvGrps do -- creo o svuoto il gruppo local nRibsPathGrp = EgtGetFirstNameInGroup( vCrvGrps[i], RIBS_GRP) if not nRibsPathGrp then nRibsPathGrp = EgtGroup( vCrvGrps[i]) EgtSetName( nRibsPathGrp, RIBS_GRP) EgtSetStatus( nRibsPathGrp, GDB_ST.OFF) else EgtEmptyGroup( nRibsPathGrp) end -- calcolo le superfici occupate dalle shell nel gruppo di curve corrente e aggiorno le superfici totali -- a) superficie più interna local nSrfInt = EgtGetFirstNameInGroup( vCrvGrps[i], TOT_SHELL_TRIM_SURF) or GDB_ID.NULL if nTotSrfInt == GDB_ID.NULL and nSrfInt ~= GDB_ID.NULL then nTotSrfInt = EgtCopyGlob( nSrfInt, nRibsGrp) elseif nTotSrfInt ~= GDB_ID.NULL and nSrfInt ~= GDB_ID.NULL then if not EgtSurfFrAdd( nTotSrfInt, nSrfInt) then EgtOutLog( 'Error : EgtSurfFrAdd for external ribs failed. Errors may occur with user-linked ribs (layer '.. EgtNumToString( s_nCurrIdx) ..') - CalcPaths') end end -- b) superficie più esterna local nSrfExt = GDB_ID.NULL local nSrfLay = EgtGetFirstNameInGroup( vCrvGrps[i], LAYER_SRF) if nSrfLay then nSrfExt = ComputeSurfOffset( nSrfLay, vCrvGrps[i], LayerParams.dOffs) if not nSrfExt then EgtOutLog( 'Error : creation of trim region for external ribs failed. Errors may occur also with internal user-linked ribs (layer '.. EgtNumToString( s_nCurrIdx) ..') - CalcPaths') table.insert( s_vErr, ' - layer ' .. EgtNumToString( s_nCurrIdx) .. ' : error in computing trim region for external ribs') nTotSrfExt = nil else if nTotSrfExt == GDB_ID.NULL then nTotSrfExt = EgtCopyGlob( nSrfExt, nRibsGrp) elseif nTotSrfExt then if not EgtSurfFrAdd( nTotSrfExt, nSrfExt) then nTotSrfExt = nil EgtOutLog( 'Error : creation of trim region for external ribs failed (layer '.. EgtNumToString( s_nCurrIdx) ..') - CalcPaths') table.insert( s_vErr, ' - layer ' .. EgtNumToString( s_nCurrIdx) .. ' : error in computing trim region for external ribs') end end end end -- trim grossolano dei setti local nTrimGrp = TrimRibs( vOrigRibs, nRibsGrp, nSrfExt, EgtIf( i == #vCrvGrps, nTotSrfInt, GDB_ID.NULL)) -- calcolo offset orientati local nOffsGrp = ComputeRibsOrientedOffset( nTrimGrp) -- preparo il gruppo con i contorni delle superfici di offset ( necessario per CalcToolPath) local nLoopGrp = EgtGroup( nRibsPathGrp) -- creo le superfici con cui fare i trim corretti e ne estraggo contorni local tSurfOffs = ComputeTrimSurfWithOverlapsForRibs( vOrigRibs, nRibsPathGrp, nSrfInt, EgtIf( i == #vCrvGrps, nTotSrfExt, nil), nLoopGrp) -- copio gli offset delle costolature nel PathGrp local vOffsRib = EgtGetAllInGroup( nOffsGrp) for i = 1, #vOffsRib do EgtCopyGlob( vOffsRib[i], nRibsPathGrp) end -- 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 nType = EgtGetInfo( nCrvId, KEY_RIBS_TYPE, 'i') local nStartRib = EgtGetInfo( nCrvId, KEY_START_RIB, 'i') if not tSurfOffs[nStartRib] then -- la costolatura non è fattibile EgtErase( nCrvId) else local nCrv, nCnt if tSurfOffs[nStartRib] == GDB_ID.NULL then -- il setto non va trimmato ( caso di rib unbounded o rib esterno senza solido) nCrv = nCrvId nCnt = 1 else nCrv, nCnt = EgtTrimCurveWithRegion( nCrvId, tSurfOffs[nStartRib], EgtIf( nType == RIB_TYPE.INTERNAL or nType == RIB_TYPE.SUPPORT, true, false), false) end for nInd = 0, nCnt - 1 do -- verifico vincolo 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[nStartRib]) -- 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 -- gestisco eventuali intersezioni fra costolature local bInters, bSpecialCase = HandleRibsIntersections( nRibsGrp, nOffsGrp, nRibsPathGrp, nSrfInt, EgtIf( i == #vCrvGrps, nTotSrfExt, nil), bAllTwoStrands, vTypeSequence, nLoopGrp, tSurfOffs) EgtSetInfo( nRibsPathGrp or GDB_ID.NULL, KEY_RIBS_INTERS, bInters) EgtSetInfo( nRibsPathGrp or GDB_ID.NULL, KEY_RIBS_SPECIAL_CASE, bSpecialCase) -- riordino le costolature if bSpecialCase then -- gestione caso speciale di intersezione e 2 passate ReorderRibsInters2Shells( nRibsPathGrp, LayerParams.bRibsInvertOrder) else ReorderRibs( nRibsPathGrp, LayerParams.bRibsInvertOrder) end -- sistemo le quote dei loop per CalcToolPath local vLoopIds = EgtGetAllInGroup( nLoopGrp) or {} for i = 1, #vLoopIds do EgtMove( vLoopIds[i], LayerParams.dLayHeight * s_vtSlicing, GDB_RT.GLOB) end -- elimino superficie per check EgtErase( nSrfExt) if not EgtGetFirstNameInGroup( nRibsPathGrp, RIBS_CRV .. '*') then EgtErase( nRibsPathGrp) end end end -------------------------------------------------------------------- --------------------- RIBS-MERGED SHELLS --------------------------- -------------------------------------------------------------------- local function CalcFillet( nCrv1, nCrv2, dFillet, nGrpId, nGrpTmp) if dFillet < GEO.EPS_SMALL then return end -- creo il fillet local dParRef1 = EgtCurveParamAtLength( nCrv1, EgtCurveLength( nCrv1) - 100 * GEO.EPS_SMALL) local dParRef2 = EgtCurveParamAtLength( nCrv2, 100 * GEO.EPS_SMALL) local nFillet = EgtCurveFillet( nGrpTmp, nCrv1, EgtUP( nCrv1, dParRef1, nGrpTmp), nCrv2, EgtUP( nCrv2, dParRef2, nGrpTmp), dFillet, true, GDB_RT.LOC) if not nFillet then -- ritento con valore di fillet leggermente inferiore nFillet = EgtCurveFillet( nGrpTmp, nCrv1, EgtUP( nCrv1, dParRef1, nGrpTmp), nCrv2, EgtUP( nCrv2, dParRef2, nGrpTmp), dFillet - 50 * GEO.EPS_SMALL, true, GDB_RT.LOC) end -- spezzo a metà il fillet per assegnarlo alle due curve if nFillet then local nNewFillet = EgtSplitCurve( nFillet, 2) -- aggiungo a nCrv1 if EgtExistsObj( nCrv1) then EgtAddCurveCompoArcTg( nCrv1, EgtEP( nNewFillet, GDB_ID.ROOT), true, GDB_RT.GLOB) EgtErase( nNewFillet) else -- nCrv1 viene sostituita completamente dal fillet local nNewCrv = EgtCurveCompo( nGrpId, {nNewFillet}) EgtChangeId( nNewCrv, nCrv1) end -- aggiungo a nCrv2 if EgtExistsObj( nCrv2) then EgtAddCurveCompoArcTg( nCrv2, EgtSP( nNewFillet + 1, GDB_ID.ROOT), false, GDB_RT.GLOB) EgtErase( nNewFillet + 1) else -- nCrv2 viene sostituita completamente dal fillet local nNewCrv = EgtCurveCompo( nGrpId, {nNewFillet + 1}) EgtChangeId( nNewCrv, nCrv2) end else EgtOutLog( 'Warning : ribs-merged shells fillet not possible (layer '..tostring( s_nCurrIdx)..') - CalcPath') end EgtRelocateGlob( nFillet or GDB_ID.NULL, nGrpId) end -------------------------------------------------------------------- local function AddFillet( nRib1, vLinks, nRib2, nGrpId) local dFillet1 = EgtGetInfo( nRib1, KEY_RIBS_LINK_FILLET, 'd') local dFillet2 = EgtGetInfo( nRib2, KEY_RIBS_LINK_FILLET, 'd') -- verifico se necessaria correzione per passate dello stesso setto local nOrig1 = EgtGetInfo( nRib1, KEY_ORIGINAL_RIB, 'i') local nOrig2 = EgtGetInfo( nRib2, KEY_ORIGINAL_RIB, 'i') local nSplit1 = EgtGetInfo( nRib1, KEY_SPLIT_ID, 'i') or 0 local nSplit2 = EgtGetInfo( nRib2, KEY_SPLIT_ID, 'i') or 0 if nOrig1 == nOrig2 and nSplit1 == nSplit2 then local dStrand = EgtGetInfo( nRib1, KEY_RIBS_STRAND, 'd') local dStrandOverlap = EgtGetInfo( nRib1, KEY_RIBS_STRAND_OVERLAP, 'd') dFillet1 = min( dFillet1, 0.5 * ( 1 - dStrandOverlap / 100) * dStrand) dFillet2 = dFillet1 end -- creo un gruppo con riferimento locale allo slicing per i conti del fillet local nGrpTmp = EgtGroup( nGrpId, Frame3d( ORIG(), s_vtSlicing), GDB_RT.GLOB) -- calcolo il primo fillet local ptRib1 = EgtEP( nRib1, GDB_ID.ROOT) for i = 1, #vLinks do if AreSamePointApprox( ptRib1, EgtSP( vLinks[i], GDB_ID.ROOT)) then CalcFillet( nRib1, vLinks[i], dFillet1, nGrpId, nGrpTmp) break end end -- calcolo il secondo fillet local ptRib2 = EgtSP( nRib2, GDB_ID.ROOT) for i = 1, #vLinks do if AreSamePointApprox( EgtEP( vLinks[i], GDB_ID.ROOT), ptRib2) then CalcFillet( vLinks[i], nRib2, dFillet2, nGrpId, nGrpTmp) break end end EgtErase( nGrpTmp) end -------------------------------------------------------------------- local function ComputeShortestLinkOnCurve( nCrv, dParS, dParE, nGrp) -- costruisco percorso dParS->dParE local nCrv1 = EgtCopyGlob( nCrv, nGrp) EgtTrimCurveStartEndAtParam( nCrv1, dParS, dParE) -- costruisco percorso dParE->dParS local nCrv2 = EgtCopyGlob( nCrv, nGrp) EgtTrimCurveStartEndAtParam( nCrv2, dParE, dParS) EgtInvertCurve( nCrv2) -- restituisco il tratto più corto local dLen1 = EgtCurveLength( nCrv1) local dLen2 = EgtCurveLength( nCrv2) if dLen1 < dLen2 + GEO.EPS_SMALL then EgtErase( nCrv2) return nCrv1 else EgtErase( nCrv1) return nCrv2 end end -------------------------------------------------------------------- local function TrimCurveExtremity( nCrv, nTrimSrf, bStartOrEnd, nGrp) local nCopyCrv = EgtCopyGlob( nCrv, nGrp) local nRes, nCnt = EgtTrimCurveWithRegion( nCopyCrv, nTrimSrf, true, false) if nRes then -- recupero estremi di interesse local nRefCrv = EgtIf( bStartOrEnd, nRes, nRes + nCnt - 1) local ptRefRes = EgtIf( bStartOrEnd, EgtSP( nRefCrv, GDB_ID.ROOT), EgtEP( nRefCrv, GDB_ID.ROOT)) local ptRefCrv = EgtIf( bStartOrEnd, EgtSP( nCrv, GDB_ID.ROOT), EgtEP( nCrv, GDB_ID.ROOT)) -- se estremi coincidenti significa che il trim non è necessario if not AreSamePointApprox( ptRefRes, ptRefCrv) then -- trim della curva local dPar = EgtCurveParamAtPoint( nCrv, ptRefRes, 100 * GEO.EPS_SMALL, GDB_RT.GLOB) if not dPar then return false end if bStartOrEnd then EgtTrimCurveStartAtParam( nCrv, dPar) else EgtTrimCurveEndAtParam( nCrv, dPar) end end end -- cancello tutte le curve ausiliarie create EgtErase( nCopyCrv) for nId = nRes, nRes + nCnt - 1 do EgtErase( nId) end end -------------------------------------------------------------------- local function PrepareShellsForRibsMerge( vOrigShells, bExtraShell) if #vOrigShells == 0 then return vOrigShells end local vIds = vOrigShells -- se sono extra shells calcolo le curve chiuse da cui si sono generate if bExtraShell then local nGrp = EgtGetParent( vOrigShells[1]) local dOffs = EgtGetInfo( vOrigShells[1], KEY_CRV_OFFSET, 'd') local nLaySrf = EgtGetFirstNameInGroup( EgtGetParent( nGrp), LAYER_SRF) local nSrf = ComputeSurfOffset( nLaySrf, EgtGetParent( vOrigShells[1]), - dOffs) if not nSrf or nSrf == GDB_ID.NULL then EgtOutLog( 'Error : error in computing complete shell for shell-merged ribs (layer '.. EgtNumToString( s_nCurrIdx) ..') - CalcPaths') table.insert( s_vErr, ' - layer ' .. EgtNumToString( s_nCurrIdx) .. ' : error in ribs-merged shells') return end -- estraggo i loop vIds = GetPathsFromSurf( nSrf, '', TYPE.EXTRA_SHELL, EgtGetParent( vOrigShells[1])) EgtErase( nSrf) end -- associo loop esterni ai loop interni local tShells = {} if #vIds == 1 then tShells = {{vIds[1]}} else -- individuo i loop esterni e i loop interni local vExt = {} local vInt = {} for i = 1, #vIds do local bInternalLoop = EgtGetInfo( vIds[i], KEY_INTERNAL_SRF_LOOP, 'b') or false table.insert( EgtIf( bInternalLoop, vInt, vExt), vIds[i]) end if #vInt == 0 then -- se solo loop esterni for i = 1, #vExt do table.insert( tShells, {vExt[i]}) end elseif #vExt == 1 then -- se un solo loop esterno, tutti i loop interni sono riferiti ad esso local vCrvs = { vExt[1]} for i = 1, #vInt do table.insert( vCrvs, vInt[i]) end tShells = { vCrvs} else -- associo ad ogni loop esterno, gli interni corrispondenti local vUsed = {} -- per tenere traccia se il loop è già stato associato ad un esterno for i = 1, #vInt do vUsed[i] = false end for i = 1, #vExt do local vCrvs = { vExt[i]} local nSrfTmp = EgtSurfFlatRegion( EgtGetParent( vOrigShells[1]), vExt[i]) for j = 1, #vInt do if not vUsed[j] then local nRes = EgtCurveWithRegionClassify( vInt[j], nSrfTmp) if nRes == GDB_CRC.IN then table.insert( vCrvs, vInt[j]) vUsed[j] = true end end end table.insert( tShells, vCrvs) EgtErase( nSrfTmp) end end end return tShells end -------------------------------------------------------------------- local function PrepareAuxSurfsForRibsMerge( nGrp, vShells, dStrand, LayerParams) -- superficie definita dalla shell local nSrfShell = EgtSurfFlatRegion( nGrp, vShells) if not nSrfShell then EgtOutLog( 'Error : error in computing shell region for shell-merged ribs (layer '.. EgtNumToString( s_nCurrIdx) ..') - CalcPaths') table.insert( s_vErr, ' - layer ' .. EgtNumToString( s_nCurrIdx) .. ' : error in computing ribs-merged shells') return false end EgtSetName( nSrfShell, SHELL_SURF) -- superficie per trim grossolano dei setti local nCrvGrp = EgtGetParent( EgtGetParent( nGrp)) local nSrfCoarseTrim = GDB_ID.NULL local nSrfLay = EgtGetFirstNameInGroup( nCrvGrp, LAYER_SRF) if nSrfLay then nSrfCoarseTrim = ComputeSurfOffset( nSrfLay, nGrp, LayerParams.dOffs) if not nSrfCoarseTrim then EgtOutLog( 'Error : error in computing coarse trim region for shell-merged ribs (layer '.. EgtNumToString( s_nCurrIdx) ..') - CalcPaths') table.insert( s_vErr, ' - layer ' .. EgtNumToString( s_nCurrIdx) .. ' : error in computing ribs-merged shells') return false end EgtSetName( nSrfCoarseTrim, COARSE_TRIM_SURF) else return false end -- superficie per trim corretto dei setti local nTotShellTrimSurf = EgtGetFirstNameInGroup( nCrvGrp, TOT_SHELL_TRIM_SURF) if not nTotShellTrimSurf then EgtOutLog( 'Warning : not enough space for merging ribs with shells (layer '.. EgtNumToString( s_nCurrIdx) ..') - CalcPaths') return false end local nTrimSurf = ComputeSurfOffset( nTotShellTrimSurf, nGrp, - ( 0.5 - LayerParams.dStrandOverlap / 100) * dStrand) if not nTrimSurf then -- errore nel calcolo EgtOutLog( 'Error : error in computing trim region for shell-merged ribs (layer '.. EgtNumToString( s_nCurrIdx) ..') - CalcPaths') table.insert( s_vErr, ' - layer ' .. EgtNumToString( s_nCurrIdx) .. ' : error in computing ribs-merged shells') return false elseif nTrimSurf == GDB_ID.NULL then -- non c'è spazio per creare ribs-merged shell, realizzo solo la shell EgtOutLog( 'Warning : not enough space for merging ribs with shells (layer '.. EgtNumToString( s_nCurrIdx) ..') - CalcPaths') return false end -- creo il gruppo con i loop delle superfici local nLoopGrp = EgtGroup( nGrp) EgtSetName( nLoopGrp, LOOP_GRP) for i = 1, #vShells do local nSrfLoop = EgtCopyGlob( vShells[i], nLoopGrp) EgtSetName( nSrfLoop, SURF_LOOP) end GetPathsFromSurf( nTrimSurf, TRIM_SURF_LOOP, nil, nLoopGrp) return true end -------------------------------------------------------------------- local function HandleRibsIntersectionForRibsMergedShells( vOrigRibs, nRibsGrp, nOffsGrp, nLoopGrp, dStrand, dOverlap) local vRibsIds = {} -- ignoro setti che non hanno passate corrispondenti for i = 1, #vOrigRibs do local vOffs = EgtGetNameInGroup( nRibsGrp, EgtGetName( vOrigRibs[i])) if vOffs and #vOffs > 0 then table.insert( vRibsIds, vOrigRibs[i]) end end -- creo un gruppo con frame locale per calcolare le intersezioni ( è il piano XY locale dove calcolare intersezioni) local frLoc = Frame3d( ORIG(), s_vtSlicing) local nGrpTmp = EgtGroup( nRibsGrp, frLoc, GDB_RT.GLOB) local nShellSrf = EgtGetFirstNameInGroup( EgtGetParent( nRibsGrp), SHELL_SURF) local nTrimSrf = EgtGetFirstNameInGroup( EgtGetParent( nRibsGrp), TOT_SHELL_TRIM_SURF) local nShellSrfInters = EgtCopyGlob( nShellSrf, nLoopGrp) local nTrimSrfInters = EgtCopyGlob( nTrimSrf, nLoopGrp) local bIntersection = false for i = 1, #vRibsIds do -- verifico se interseca uno dei setti successivi for j = i + 1, #vRibsIds do local bInters, bForceCutOnCrv1 = VerifyRibsIntersection( vRibsIds[i], vRibsIds[j], RIB_TYPE.INTERNAL, RIB_TYPE.INTERNAL, nShellSrf, nil, nGrpTmp, nOffsGrp) if bInters then bIntersection = true local nCrv1 = vRibsIds[i] -- curva principale che non viene tagliata local nCrv2 = vRibsIds[j] -- curve secondaria da modificare if bForceCutOnCrv1 then nCrv1, nCrv2 = nCrv2, nCrv1 end -- verifico che la curva secondaria abbia una sola passata local nShells2 = EgtGetInfo( nCrv2, KEY_RIBS_SHELLS_NBR, 'i') if nShells2 > 1 then EgtOutLog( 'Error : shell-merged ribs intersect in a non valid way (layer '.. EgtNumToString( s_nCurrIdx) ..') - CalcPaths') table.insert( s_vErr, ' - layer ' .. EgtNumToString( s_nCurrIdx) .. ' : error in ribs-merged shells intersection') return false end -- calcolo la superficie della curva principale ( nCrv1) da usare per trim local nShells = EgtGetInfo( nCrv1, KEY_RIBS_SHELLS_NBR, 'i') local dStrandOverlap = EgtGetInfo( nCrv1, KEY_RIBS_STRAND_OVERLAP, 'd') local dOffs = (( nShells - 1) * ( 1 - dStrandOverlap / 100) * 0.5 + 1 - dOverlap / 100) * dStrand local nSrf = EgtSurfFrFatCurve( nGrpTmp, nCrv1, dOffs, false, false, s_dOffsTol) if not nSrf then EgtOutLog( 'Error : EgtSurfFrFatCurve for shell-merged ribs intersection failed (layer '.. EgtNumToString( s_nCurrIdx) ..') - CalcPaths') table.insert( s_vErr, ' - layer ' .. EgtNumToString( s_nCurrIdx) .. ' : error in ribs-merged shells intersection') return false end -- estraggo il loop local nLoop, nCnt = EgtExtractSurfFrChunkLoops( nSrf, 0, nGrpTmp) -- taglio il setto secondario ( nCrv2) local vOffs2 = EgtGetNameInGroup( nRibsGrp, EgtGetName( nCrv2)) or {} for i = 1, #vOffs2 do local nId, nCnt = EgtTrimCurveWithRegion( vOffs2[i], nSrf, false, true) if nCnt == 0 then -- il setto scompare EgtErase( nId) elseif nCnt > 1 then -- verifico se posso ricollegare i tratti ottenuti per formare un setto unico for nCrv = nId, nId + nCnt - 2 do local dParS = EgtCurveParamAtPoint( nLoop, EgtEP( nCrv, GDB_ID.ROOT), 100 * GEO.EPS_SMALL, GDB_RT.GLOB) local dParE = EgtCurveParamAtPoint( nLoop, EgtSP( nCrv + 1, GDB_ID.ROOT), 100 * GEO.EPS_SMALL, GDB_RT.GLOB) local nLinkId = ComputeShortestLinkOnCurve( nLoop, dParS, dParE, nRibsGrp) if nLinkId then local nRes = EgtCurveWithRegionClassify( nLinkId, nShellSrf) if nRes == GDB_CRC.IN then -- fillet AddFillet( nCrv, {nLinkId}, nCrv + 1, nRibsGrp) EgtAddCurveCompoCurve( nCrv + 1, nLinkId, true, false) EgtAddCurveCompoCurve( nCrv + 1, nCrv, true, false) else -- tipo di intersezione non permessa EgtOutLog( 'Error : shell-merged ribs intersect in a non valid way (layer '.. EgtNumToString( s_nCurrIdx) ..') - CalcPaths') table.insert( s_vErr, ' - layer ' .. EgtNumToString( s_nCurrIdx) .. ' : error in ribs-merged shells intersection') return false end end end end end -- aggiorno le superfici da utilizzare per creare collegamenti if not EgtSurfFrSubtract( nShellSrfInters, nSrf) or not EgtSurfFrSubtract( nTrimSrfInters, nSrf) then EgtOutLog( 'Error : EgtSurfFrSubtract with shell-merged ribs intersection failed (layer '.. EgtNumToString( s_nCurrIdx) ..') - CalcPaths') table.insert( s_vErr, ' - layer ' .. EgtNumToString( s_nCurrIdx) .. ' : error in ribs-merged shells intersection') return false end EgtErase( nSrf) end end end -- se ho trovato intersezioni estraggo i loop delle superfici ausiliarie if bIntersection then GetPathsFromSurf( nShellSrfInters, SURF_LOOP, nil, nLoopGrp) GetPathsFromSurf( nTrimSrfInters, TRIM_SURF_LOOP, nil, nLoopGrp) end EgtErase( nShellSrfInters) EgtErase( nTrimSrfInters) EgtErase( nGrpTmp) return true end -------------------------------------------------------------------- local function PrepareRibsForMergeWithShells( vOrigRibs, nGrp, dStrand, dOverlap, bInvertRibsOrder) -- verifico se sono presenti buchi che possono essere chiusi vOrigRibs = VerifyRibsHoles( vOrigRibs) -- trim grossolano dei setti local nSrfCoarseTrim = EgtGetFirstNameInGroup( nGrp, COARSE_TRIM_SURF) local nTrimGrp = TrimRibs( vOrigRibs, nGrp, nSrfCoarseTrim, GDB_ID.NULL) -- calcolo offset orientati local nOffsGrp = ComputeRibsOrientedOffset( nTrimGrp) -- trim con la regione della shell local nRibsGrp = EgtGroup( nGrp) local nSrfShell = EgtGetFirstNameInGroup( nGrp, SHELL_SURF) local nSrfTrim = EgtGetFirstNameInGroup( nGrp, TOT_SHELL_TRIM_SURF) local vRibs = EgtGetAllInGroup( nOffsGrp) for i = 1, #vRibs do -- copio i setti nel gruppo dei conti local nCopy = EgtCopyGlob( vRibs[i], nRibsGrp) -- trim local nRes, nCnt = EgtTrimCurveWithRegion( nCopy, nSrfShell, true, true) if nCnt == 0 then EgtErase( nRes) end for nId = nRes, nRes + nCnt - 1 do -- verifico se si trova nella regione di trim local nClassif = EgtCurveWithRegionClassify( nId, nSrfTrim) if nClassif == GDB_CRC.OUT then EgtErase( nId) end end end local vIds = EgtGetAllInGroup( nRibsGrp) or {} if #vIds == 0 then return end -- gestione delle intersezioni local nLoopGrp = EgtGetFirstNameInGroup( nGrp, LOOP_GRP) if not HandleRibsIntersectionForRibsMergedShells( vOrigRibs, nRibsGrp, nOffsGrp, nLoopGrp, dStrand, dOverlap) then return end -- ordinamento vIds = EgtGetAllInGroup( nRibsGrp) ShortestPathForRibs( vIds, nRibsGrp, bInvertRibsOrder) -- elimino elementi superflui per passaggi successivi EgtErase( nTrimGrp) EgtErase( nOffsGrp) EgtErase( nSrfCoarseTrim) EgtErase( nSrfShell) return nRibsGrp end -------------------------------------------------------------------- local function CreateRibsMergedShellLastLink( vShells, vRibs, nGrp, bInvert) for i = 1, #vShells do local dParS = EgtCurveParamAtPoint( vShells[i], EgtSP( vRibs[1], GDB_ID.ROOT), 100 * GEO.EPS_SMALL, GDB_RT.GLOB) local dParE = EgtCurveParamAtPoint( vShells[i], EgtEP( vRibs[#vRibs], GDB_ID.ROOT), 100 * GEO.EPS_SMALL, GDB_RT.GLOB) if dParS and dParE then local nLink = EgtCopyGlob( vShells[i], nGrp) if bInvert then -- conservo tratto dParS->dParE EgtTrimCurveStartEndAtParam( nLink, dParS, dParE) EgtInvertCurve( nLink) else -- conservo tratto dParE->dParS EgtTrimCurveStartEndAtParam( nLink, dParE, dParS) end -- sistemo i setti che hanno tratti nella regione occupata dal last link local dStrand = EgtGetInfo( vRibs[1], KEY_RIBS_STRAND, 'd') local nLinkSrf = EgtSurfFrFatCurve( nGrp, nLink, dStrand, false, false, s_dOffsTol) if not nLinkSrf then return nLink end local nLoopGrp = EgtGetFirstNameInGroup( nGrp, LOOP_GRP) local vLoops = EgtGetNameInGroup( nLoopGrp, TRIM_SURF_LOOP) local nTrimSurf = EgtGetFirstNameInGroup( nGrp, TOT_SHELL_TRIM_SURF) for i = 1, #vRibs do -- individuo i tratti del setto esterni alla superficie di trim local nCopyCrv = EgtCopyGlob( vRibs[i], nGrp) local nCrv, nCnt = EgtTrimCurveWithRegion( nCopyCrv, nTrimSurf, false, false) if nCrv then for nId = nCrv, nCrv + nCnt - 1 do -- ignoro i tratti esterni che corrispondono allo start e all'end della curva if not AreSamePointApprox( EgtSP( nId), EgtSP( vRibs[i])) and not AreSamePointApprox( EgtEP( nId), EgtEP( vRibs[i])) then -- verifico se giace nella regione occupata dal last link local nRes = EgtCurveWithRegionClassify( nId, nLinkSrf) if nRes ~= GDB_CRC.OUT then local nOtherPart = EgtCopyGlob( vRibs[i], nGrp) local ptS = EgtSP( nId, GDB_ID.ROOT) local ptE = EgtEP( nId, GDB_ID.ROOT) local dPar1 = EgtCurveParamAtPoint( vRibs[i], ptS, 100 * GEO.EPS_SMALL, GDB_RT.GLOB) local dPar2 = EgtCurveParamAtPoint( vRibs[i], ptE, 100 * GEO.EPS_SMALL, GDB_RT.GLOB) EgtTrimCurveEndAtParam( vRibs[i], dPar1) EgtTrimCurveStartAtParam( nOtherPart, dPar2) -- creo il collegamento local nPartLink for i = 1, #vLoops do local dParS = EgtCurveParamAtPoint( vLoops[i], ptS, 100 * GEO.EPS_SMALL, GDB_RT.GLOB) local dParE = EgtCurveParamAtPoint( vLoops[i], ptE, 100 * GEO.EPS_SMALL, GDB_RT.GLOB) if dParS and dParE then nPartLink = ComputeShortestLinkOnCurve( vLoops[i], dParS, dParE, nGrp) end end if nPartLink then -- fillet AddFillet( vRibs[i], {nPartLink}, nOtherPart, nGrp) EgtAddCurveCompoCurve( vRibs[i], nPartLink) EgtAddCurveCompoCurve( vRibs[i], nOtherPart) end end end EgtErase( nId) end end end EgtErase( nLinkSrf) return nLink end end -- se non ho trovato curva per il link segnalo errore EgtOutLog( 'Error : creation of ribs-merged shells main link failed. Ribs not ending on same shell (layer '.. EgtNumToString( s_nCurrIdx) ..') - CalcPaths') table.insert( s_vErr, ' - layer ' .. EgtNumToString( s_nCurrIdx) .. ' : error in computing ribs-merged shells (ribs link not possible)') end -------------------------------------------------------------------- local function CreateRibsMergedShellLink( nCurr, nNext, nGrp, vLoops, nCheckGrp) for i = 1, #vLoops do local dParS = EgtCurveParamAtPoint( vLoops[i], EgtEP( nCurr, GDB_ID.ROOT), 100 * GEO.EPS_SMALL, GDB_RT.GLOB) local dParE = EgtCurveParamAtPoint( vLoops[i], EgtSP( nNext, GDB_ID.ROOT), 100 * GEO.EPS_SMALL, GDB_RT.GLOB) if dParS and dParE then -- cerco il più corto fra i percorsi dParS->dParE e dParE->dParS local nLinkId = ComputeShortestLinkOnCurve( vLoops[i], dParS, dParE, nGrp) -- verifico sia sensato : local nCurrCheck = EgtGetInfo( nCurr, KEY_ASSOCIATED_CRVS, 'i') local nNextCheck = EgtGetInfo( nNext, KEY_ASSOCIATED_CRVS, 'i') local frLoc = Frame3d( ORIG(), s_vtSlicing) local nGrpLoc = EgtGroup( nGrp, frLoc, GDB_RT.GLOB) -- a) verifico direzione -- verifico se interseca uno dei due setti in un altro punto oltre all'estremo interessato dal collegamento local _, nPntCnt1 = EgtCurveCurveInters( nCurrCheck, nLinkId, nGrpLoc) local _, nPntCnt2 = EgtCurveCurveInters( nNextCheck, nLinkId, nGrpLoc) if nPntCnt1 > 1 or nPntCnt2 > 1 then EgtOutLog( 'Error : creation of ribs-merged shells failed for inconsistent ribs directions (layer '.. EgtNumToString( s_nCurrIdx) ..') - CalcPaths') table.insert( s_vErr, ' - layer ' .. EgtNumToString( s_nCurrIdx) .. ' : error in ribs-merged shells (inconsistent ribs direction)') EgtErase( nLinkId) EgtErase( nGrpLoc) return end -- b) verifico ordinamento -- verifico se interseca uno degli altri setti local vCheckIds = EgtGetAllInGroup( nCheckGrp) or {} for i = 1, #vCheckIds do if vCheckIds[i] ~= nCurrCheck and vCheckIds[i] ~= nNextCheck then local _, nPntCnt, nCrvCnt = EgtCurveCurveInters( vCheckIds[i], nLinkId, nGrpLoc) if nPntCnt > 0 or nCrvCnt > 0 then EgtOutLog( 'Error : creation of ribs-merged shells failed for inconsistent ribs order (layer '.. EgtNumToString( s_nCurrIdx) ..') - CalcPaths') table.insert( s_vErr, ' - layer ' .. EgtNumToString( s_nCurrIdx) .. ' : error in ribs-merged shells (inconsistent ribs order)') EgtErase( nLinkId) EgtErase( nGrpLoc) return end end end EgtErase( nGrpLoc) return nLinkId end end -- se sono passate relative allo stesso setto possono essere collegate con tratto lineare anche se non poggiano sulle curve di bordo -- ( caso di setto che non arriva fino al bordo) local nOrig1 = EgtGetInfo( nCurr, KEY_ORIGINAL_RIB, 'i') local nOrig2 = EgtGetInfo( nNext, KEY_ORIGINAL_RIB, 'i') local nSplit1 = EgtGetInfo( nCurr, KEY_SPLIT_ID, 'i') or 0 local nSplit2 = EgtGetInfo( nNext, KEY_SPLIT_ID, 'i') or 0 if nOrig1 == nOrig2 and nSplit1 == nSplit2 then local nLinkId = EgtCurveCompoFromPoints( nGrp, {EgtEP( nCurr, GDB_ID.ROOT), EgtSP( nNext, GDB_ID.ROOT)}, GDB_RT.GLOB) return nLinkId end -- se il link non è stato creato errore EgtOutLog( 'Error : creation of ribs-merged shells link failed (layer '.. EgtNumToString( s_nCurrIdx) ..') - CalcPaths') table.insert( s_vErr, ' - layer ' .. EgtNumToString( s_nCurrIdx) .. ' : error in ribs-merged shells (ribs link not possible)') return end -------------------------------------------------------------------- local function AdjustRibsMergedExtraShellLink( nLinkId, vExtraShells, nGrp) local vLinks = {} -- devo conservare solo i tratti comuni fra link ed extra shell for i = 1, #vExtraShells do local dParS = EgtCurveParamAtPoint( nLinkId, EgtSP( vExtraShells[i]), 100 * GEO.EPS_SMALL) local dParE = EgtCurveParamAtPoint( nLinkId, EgtEP( vExtraShells[i]), 100 * GEO.EPS_SMALL) if dParS or dParE then local nCrv = EgtCopyGlob( nLinkId, nGrp) if dParS and dParE then EgtTrimCurveStartEndAtParam( nCrv, dParS, dParE) elseif dParS then EgtTrimCurveStartAtParam( nCrv, dParS) elseif dParE then EgtTrimCurveEndAtParam( nCrv, dParE) end EgtModifyCurveExtrusion( nCrv, s_vtSlicing, GDB_ID.ROOT) table.insert( vLinks, nCrv) else -- verifico se il link originale è già corretto local dPar1 = EgtCurveParamAtPoint( vExtraShells[i], EgtSP( nLinkId), 100 * GEO.EPS_SMALL) local dPar2 = EgtCurveParamAtPoint( vExtraShells[i], EgtEP( nLinkId), 100 * GEO.EPS_SMALL) if dPar1 and dPar2 then return { nLinkId} end end end -- cancello il link originale EgtErase( nLinkId) return vLinks end -------------------------------------------------------------------- local function CreateRibsMergedShellCurve( nGrp, nRibsGrp, vShells, vOrigShells, dStrand, LayerParams, bExtraShell) local vOrigRibs = EgtGetAllInGroup( nRibsGrp) local vRibs = {} for i = 1, #vOrigRibs do local nCopy = EgtCopyGlob( vOrigRibs[i], nGrp) EgtSetInfo( nCopy, KEY_ASSOCIATED_CRVS, vOrigRibs[i]) table.insert( vRibs, nCopy) end local nLoopGrp = EgtGetFirstNameInGroup( nGrp, LOOP_GRP) local vLoopsTrim = EgtGetNameInGroup( nLoopGrp, TRIM_SURF_LOOP) local vLoopsShell = EgtGetNameInGroup( nLoopGrp, SURF_LOOP) local nTrimSurf = EgtGetFirstNameInGroup( nGrp, TOT_SHELL_TRIM_SURF) -- creo ultimo link local nLastLink = CreateRibsMergedShellLastLink( vShells, vRibs, nGrp, LayerParams.bInvertRibsMergedShellLink) if not nLastLink then return false end -- creo collegamenti interni for i = 1, #vRibs - 1 do local nCurr = vRibs[i] local nNext = vRibs[i+1] -- verifico se posso collegare sulla shell local bLinkOnShell = true local dPar1 = EgtCurveParamAtPoint( nLastLink, EgtEP( nCurr, GDB_ID.ROOT), 100 * GEO.EPS_SMALL, GDB_RT.GLOB) local dPar2 = EgtCurveParamAtPoint( nLastLink, EgtSP( nNext, GDB_ID.ROOT), 100 * GEO.EPS_SMALL, GDB_RT.GLOB) if dPar1 or dPar2 then -- il collegamento sulla shell non è fattibile, quindi trimmo opportunamente i setti in modo che finiscano sulla curva di trim TrimCurveExtremity( nCurr, nTrimSurf, false, nGrp) TrimCurveExtremity( nNext, nTrimSurf, true, nGrp) bLinkOnShell = false end -- creo il link local nLinkId = CreateRibsMergedShellLink( nCurr, nNext, nGrp, EgtIf( bLinkOnShell, vLoopsShell, vLoopsTrim), nRibsGrp) if not nLinkId then return false end -- se link fatto sulla shell verifico non si sovrapponga al last link -- ( il caso di setti che terminano su intersezione con altro setto non è rilevato dal controllo iniziale) if bLinkOnShell then local frLoc = Frame3d( ORIG(), s_vtSlicing) local nGrpLoc = EgtGroup( nGrp, frLoc, GDB_RT.GLOB) local nRes = EgtCurveCurveInters( nLinkId, nLastLink, nGrpLoc) -- se sovrapposizione, tento con il link sul trim if nRes then bLinkOnShell = false EgtErase( nLinkId) nLinkId = CreateRibsMergedShellLink( nCurr, nNext, nGrp, vLoopsTrim, nRibsGrp) if not nLinkId then return false end end EgtErase( nGrpLoc) end -- verifico se necessari aggiustamenti per extra shell local vLinks if bExtraShell and bLinkOnShell then vLinks = AdjustRibsMergedExtraShellLink( nLinkId, vOrigShells, nGrp) end -- fillet AddFillet( nCurr, vLinks or {nLinkId}, nNext, nGrp) end -- eventuali aggiustamenti del last link per extra shell local vLastLinks if bExtraShell then vLastLinks = AdjustRibsMergedExtraShellLink( nLastLink, vOrigShells, nGrp) end -- fillet sul last link AddFillet( vRibs[#vRibs], vLastLinks or {nLastLink}, vRibs[1], nGrp) -- elimino le curve inutili e le superfici EgtErase( nRibsGrp) EgtErase( nTrimSurf) EgtErase( nLoopGrp) return true end -------------------------------------------------------------------- local function AssignRibsMergedExtraShellsLeadOutInfo( nCrv, vShells, LayerParams, dStrand) local vCoastLen = { LayerParams.dShellNbrCoasting, LayerParams.dShellNbrCoasting} local vWipeLen = { LayerParams.dShellNbrWipe, LayerParams.dShellNbrWipe} local vWipeDir = { LayerParams.dShellNbrWipeDir, LayerParams.dShellNbrWipeDir} local bFoundS = false local bFoundE = false local ptS = EgtSP( nCrv, GDB_ID.ROOT) local ptE = EgtEP( nCrv, GDB_ID.ROOT) for i = 1, #vShells do -- recupero le info della shell attuale local vShellCoastLen = EgtGetInfo( vShells[i], KEY_EXTRA_SHELL_COASTING, 'vd') local vShellWipeLen = EgtGetInfo( vShells[i], KEY_EXTRA_SHELL_WIPE, 'vd') local vShellWipeDir = EgtGetInfo( vShells[i], KEY_EXTRA_SHELL_WIPE_DIR, 'vd') -- verifico se posso usarle per settare info per lo start point if not bFoundS then if AreSamePointEpsilon( ptS, EgtSP( vShells[i], GDB_ID.ROOT), dStrand) then bFoundS = true vCoastLen[1] = vShellCoastLen[1] vWipeLen[1] = vShellWipeLen[1] vWipeDir[1] = vShellWipeDir[1] elseif AreSamePointEpsilon( ptS, EgtEP( vShells[i], GDB_ID.ROOT), dStrand) then bFoundS = true vCoastLen[1] = vShellCoastLen[2] vWipeLen[1] = vShellWipeLen[2] vWipeDir[1] = vShellWipeDir[2] end end -- verifico se posso usarle per settare info per l'end point if not bFoundE then if AreSamePointEpsilon( ptE, EgtSP( vShells[i], GDB_ID.ROOT), dStrand) then bFoundE = true vCoastLen[2] = vShellCoastLen[1] vWipeLen[2] = vShellWipeLen[1] vWipeDir[2] = vShellWipeDir[1] elseif AreSamePointEpsilon( ptE, EgtEP( vShells[i], GDB_ID.ROOT), dStrand) then bFoundE = true vCoastLen[2] = vShellCoastLen[2] vWipeLen[2] = vShellWipeLen[2] vWipeDir[2] = vShellWipeDir[2] end end -- se ho trovato sia start sia end termino la ricerca if bFoundS and bFoundE then break end end -- setto le info alla nuova shell EgtSetInfo( nCrv, KEY_EXTRA_SHELL_COASTING, vCoastLen) EgtSetInfo( nCrv, KEY_EXTRA_SHELL_WIPE, vWipeLen) EgtSetInfo( nCrv, KEY_EXTRA_SHELL_WIPE_DIR, vWipeDir) end -------------------------------------------------------------------- local function UpdateTrimSurfWithRibsMergedShell( nPathGrp, sName, LayerParams) local nCrvGrp = EgtGetParent( nPathGrp) local nOldTrimSurf = EgtGetFirstNameInGroup( nCrvGrp, TOT_SHELL_TRIM_SURF) -- calcolo la nuova superficie di trim a partire dalla regione occupata dall'ultima shell completa che conservo local nFirstShell = EgtGetFirstNameInGroup( nPathGrp, sName) local nPrevShell = EgtGetPrev( nFirstShell) local dOffs if nPrevShell then dOffs = EgtGetInfo( nPrevShell, KEY_CRV_OFFSET, 'd') local nType = EgtGetInfo( nPrevShell, KEY_TYPE, 'i') local dPrevStrand = EgtIf( nType == TYPE.OUTER_SHELL, LayerParams.dStrand, LayerParams.dInnerStrand) dOffs = dOffs + 0.5 * dPrevStrand else dOffs = - LayerParams.dOffs end local nLaySurf = EgtGetFirstNameInGroup( nCrvGrp, LAYER_SRF) local nNewTrimSurf = ComputeSurfOffset( nLaySurf, nCrvGrp, - dOffs) if not nNewTrimSurf then EgtOutLog( 'Error : ComputeSurfOffset with ribs-merged shell for TotTrimSurfRegion failed (layer '.. EgtNumToString( s_nCurrIdx) ..') - CalcPaths') table.insert( s_vErr, ' - layer ' .. EgtNumToString( s_nCurrIdx) .. ' : error in computing region for internal elements') return false end EgtSetName( nNewTrimSurf, TOT_SHELL_TRIM_SURF) -- aggiorno con le nuove shell appena modificate local vNewShells = EgtGetNameInGroup( nPathGrp, sName) or {} local bOk = true local dStrand for i = 1, #vNewShells do -- calcolo la regione occupata dalla nuova shell local nType = EgtGetInfo( vNewShells[i], KEY_TYPE, 'i') dStrand = EgtIf( nType == TYPE.OUTER_SHELL or nType == TYPE.EXTRA_OUTER_SHELL, LayerParams.dStrand, LayerParams.dInnerStrand) local nSrfShell = EgtSurfFrFatCurve( nCrvGrp, vNewShells[i], dStrand * 0.5 + s_dOffsCorr, false, false, s_dOffsTol) if nSrfShell then if not EgtSurfFrSubtract( nNewTrimSurf, nSrfShell) then EgtOutLog( 'Error : EgtSurfFrSubtract with ribs-merged shell for TotTrimSurfRegion failed (layer '.. EgtNumToString( s_nCurrIdx) ..') - CalcPaths') bOk = false end EgtErase( nSrfShell) else EgtOutLog( 'Error : EgtSurfFrFatCurve with ribs-merged shell for TotTrimSurfRegion failed (layer '.. EgtNumToString( s_nCurrIdx) ..') - CalcPaths') bOk = false end end if not bOk then table.insert( s_vErr, ' - layer ' .. EgtNumToString( s_nCurrIdx) .. ' : error in computing region for internal elements') end -- aggiorno la trim surf eliminando piccole zone non riempite tra le shell local dCurrOffs = EgtGetInfo( vNewShells[#vNewShells], KEY_CRV_OFFSET, 'd') AdjustTrimSurfExtraAngleChunks( nNewTrimSurf, dCurrOffs, dStrand) -- elimino la vecchia superficie di trim EgtErase( nOldTrimSurf) end -------------------------------------------------------------------- local function CalcRibsMergedShells( nSlicedRibsGrp, nPathGrp, LayerParams, vPtStart) if not nSlicedRibsGrp then return true end -- recupero i setti interni/supporto da collegare alla shell local vAllRibs = EgtGetAllInGroup( nSlicedRibsGrp) local vOrigRibs = {} for i = 1, #vAllRibs do local nType = EgtGetInfo( vAllRibs[i], KEY_RIBS_TYPE, 'i') local bMergeWithShell = EgtGetInfo( vAllRibs[i], KEY_RIBS_MERGE_WITH_SHELLS, 'b') or false if ( nType == RIB_TYPE.INTERNAL or nType == RIB_TYPE.SUPPORT) and bMergeWithShell then table.insert( vOrigRibs, vAllRibs[i]) end end if #vOrigRibs == 0 then return true end -- recupero le shell da unire ai setti local nLast = EgtGetLastInGroup( nPathGrp) or GDB_ID.NULL local nShellType = EgtGetInfo( nLast, KEY_TYPE, 'i') local bExtraShell = ( nShellType == TYPE.EXTRA_OUTER_SHELL or nShellType == TYPE.EXTRA_SHELL) local sLastName = EgtGetName( nLast) local vOrigShells = EgtGetNameInGroup( nPathGrp, sLastName) or {} local tShells = PrepareShellsForRibsMerge( vOrigShells, bExtraShell) if not tShells then return false end if #tShells == 0 then return false end -- sistemo gli strand dei setti per adattarli alla shell local dStrand = EgtIf( nShellType == TYPE.OUTER_SHELL or nShellType == TYPE.EXTRA_OUTER_SHELL, LayerParams.dStrand, LayerParams.dInnerStrand) for i = 1, #vOrigRibs do EgtSetInfo( vOrigRibs[i], KEY_RIBS_STRAND, dStrand) end local dShellOffs = EgtGetInfo( vOrigShells[1], KEY_CRV_OFFSET, 'd') -- per ogni gruppo di shell preparo il nuovo percorso local bOk = true for i = 1, #tShells do -- gruppo per conti local nGrp = EgtGroup( nPathGrp) local bShellOk = false -- preparo le superfici ausiliarie per la creazione delle shell if PrepareAuxSurfsForRibsMerge( nGrp, tShells[i], dStrand, LayerParams) then -- preparazione dei setti local nRibsGrp = PrepareRibsForMergeWithShells( vOrigRibs, nGrp, dStrand, LayerParams.dStrandOverlap, LayerParams.bRibsInvertOrder) if nRibsGrp then -- combino i setti con le shell per creare il nuovo percorso if CreateRibsMergedShellCurve( nGrp, nRibsGrp, tShells[i], vOrigShells, dStrand, LayerParams, bExtraShell) then -- creo le nuove curve di shell local nCrv, nCnt = EgtCurveCompoByChain( nGrp, EgtGetAllInGroup( nGrp), ORIG()) if nCrv and nCnt > 0 then for nId = nCrv, nCrv + nCnt - 1 do EgtRelocateGlob( nId, nPathGrp) -- assegno info EgtSetName( nId, sLastName) EgtSetInfo( nId, KEY_TYPE, nShellType) EgtSetInfo( nId, KEY_CRV_OFFSET, dShellOffs) ModifyStartPoint( nId, vPtStart) EgtModifyCurveExtrusion( nId, s_vtSlicing, GDB_RT.GLOB) -- ripristino orientamento originale if EgtCurveIsClosed( nId) then local vtCrv = EgtCurveArea( nId) if AreOppositeVectorApprox( vtCrv, s_vtSlicing) then EgtInvertCurve( nId) end end -- riassegno le info di lead out se extra shell if bExtraShell then AssignRibsMergedExtraShellsLeadOutInfo( nId, vOrigShells, LayerParams, dStrand) end end -- cancello le shell e le shell originarie associati for j = 1, #vOrigShells do local ptRef = EgtMP( vOrigShells[j], GDB_ID.ROOT) if ptRef then for k = 1, #tShells[i] do if EgtCurveParamAtPoint( tShells[i][k], ptRef, 100 * GEO.EPS_SMALL, GDB_RT.GLOB) then EgtErase( vOrigShells[j]) vOrigShells[j] = GDB_ID.NULL break end end end end for j = 1, #tShells[i] do EgtErase( tShells[i][j]) end bShellOk = true end end end end if not bShellOk then bOk = false end EgtErase( nGrp) end -- riordino rispetto alle shell precedenti if not bExtraShell then local nFirstShell = EgtGetFirstNameInGroup( nPathGrp, sLastName) local nPrevShell = EgtGetPrev( nFirstShell) if nPrevShell then local vOldIds = EgtGetNameInGroup( nPathGrp, EgtGetName( nPrevShell)) local vNewIds = EgtGetNameInGroup( nPathGrp, sLastName) ReorderPath( vOldIds, vNewIds) end end -- aggiorno la superficie di trim con le nuove shell UpdateTrimSurfWithRibsMergedShell( nPathGrp, EgtIf( bExtraShell, EXTRA_SHELL_CRV .. '*', sLastName), LayerParams) -- se ho fallito in qualche merge i setti saranno considerati anche per la realizzazione standard return bOk 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 -- verifico se area significativa local _, _, dArea = EgtCurveArea( nCrvId) if dArea and dArea > GEO.EPS_SMALL 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 else EgtOutLog( 'Warning : ReducedShellNumber is too small (layer '.. EgtNumToString( s_nCurrIdx) ..') - CalcPaths') end else EgtOutLog( 'Error : ReducedShellNumber is not closed (layer '.. EgtNumToString( s_nCurrIdx) ..') - CalcPaths') table.insert( s_vErr, ' - layer ' .. EgtNumToString( s_nCurrIdx) .. ' : ReducedShellNumber is not closed') 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 for i = 1, #vCrvIds do local nSrfTmp = EgtSurfFlatRegion( nSrfGrp, vCrvIds[i]) local bOk = false if nSrfTmp then if not nSrfId then -- se è la prima curva è quella che definisce la superficie nSrfId = nSrfTmp bOk = true else bOk = EgtSurfFrAdd( nSrfId, nSrfTmp) EgtErase( nSrfTmp) end end if not bOk then EgtOutLog( 'Error : ReducedShellNumber is not considered (layer '.. EgtNumToString( s_nCurrIdx) ..') - CalcPaths') table.insert( s_vErr, ' - layer ' .. EgtNumToString( s_nCurrIdx) .. ' : ReducedShellNumber is not considered') end end if nSrfId then EgtSetName( nSrfId, SHELL_NBR_SURF .. EgtNumToString( nDiff)) -- salvo come info gli id delle curve che la definiscono EgtSetInfo( nSrfId, KEY_ASSOCIATED_CRVS, vCrvIds) end end return nSrfGrp 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 for nId = nCrv, nCrv + nCnt - 1 do -- assegno estrusione EgtModifyCurveExtrusion( nCrv, s_vtSlicing, GDB_RT.GLOB) -- assegno le info per leadout 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 UpdateTrimSurfWithExtraShell( nSrf, nCrv, dStrand, nGrpId) local nSrfExtraShell = EgtSurfFrFatCurve( nGrpId, nCrv, dStrand * 0.5 + s_dOffsCorr, true, false, s_dOffsTol) if nSrfExtraShell then if not EgtSurfFrSubtract( nSrf, nSrfExtraShell) then EgtOutLog( 'Error : EgtSurfFrSubtract with ExtraShell for TotTrimSurfRegion failed (layer '.. EgtNumToString( s_nCurrIdx) ..') - CalcPaths') table.insert( s_vErr, ' - layer ' .. EgtNumToString( s_nCurrIdx) .. ' : error in computing region for internal elements') end EgtErase( nSrfExtraShell) else EgtOutLog( 'Error : creation of ExtraShell region for TotTrimSurfRegion failed (layer '.. EgtNumToString( s_nCurrIdx) ..') - CalcPaths') table.insert( s_vErr, ' - layer ' .. EgtNumToString( s_nCurrIdx) .. ' : error in computing region for internal elements') end end --------------------------------------------------------------------- local function UpdateExtraShellRetractionParamsAfterMerge( nCrv1, nCrv2, nCase) -- recupero le info delle due curve da combinare local vCoast1 = EgtGetInfo( nCrv1, KEY_EXTRA_SHELL_COASTING, 'vi') local vCoast2 = EgtGetInfo( nCrv2, KEY_EXTRA_SHELL_COASTING, 'vi') local vWipe1 = EgtGetInfo( nCrv1, KEY_EXTRA_SHELL_WIPE, 'vi') local vWipe2 = EgtGetInfo( nCrv2, KEY_EXTRA_SHELL_WIPE, 'vi') local vWipeDir1 = EgtGetInfo( nCrv1, KEY_EXTRA_SHELL_WIPE_DIR, 'vi') local vWipeDir2 = EgtGetInfo( nCrv2, KEY_EXTRA_SHELL_WIPE_DIR, 'vi') local vCoast, vWipe, vWipeDir if nCase == 1 then -- ep di nCrv1 e sp di nCrv2 vCoast = { vCoast1[1], vCoast2[2]} vWipe = { vWipe1[1], vWipe2[2]} vWipeDir = { vWipeDir1[1], vWipeDir2[2]} elseif nCase == 2 then -- sp di nCrv1 ed ep di nCrv2 vCoast = { vCoast2[1], vCoast1[2]} vWipe = { vWipe2[1], vWipe1[2]} vWipeDir = { vWipeDir2[1], vWipeDir1[2]} elseif nCase == 3 then -- ep di nCrv1 e ep di nCrv2 vCoast = { vCoast1[1], vCoast2[1]} vWipe = { vWipe1[1], vWipe2[1]} vWipeDir = { vWipeDir1[1], vWipeDir2[1]} elseif nCase == 4 then -- sp di nCrv1 e sp di nCrv2 vCoast = { vCoast2[2], vCoast1[2]} vWipe = { vWipe2[2], vWipe1[2]} vWipeDir = { vWipeDir2[2], vWipeDir1[2]} end EgtErase( nCrv2) EgtSetInfo( nCrv1, KEY_EXTRA_SHELL_COASTING, vCoast) EgtSetInfo( nCrv1, KEY_EXTRA_SHELL_WIPE, vWipe) EgtSetInfo( nCrv1, KEY_EXTRA_SHELL_WIPE_DIR, vWipeDir) end --------------------------------------------------------------------- local function ReorderExtraShells( nPathGrp, vPtStart, LayerParams) local dAlpha = 1.2 -- verifico se posso unire due tratti consecutivi della stessa shell aggiornando opportunamente le info per il lead out local nFirst = EgtGetFirstNameInGroup( nPathGrp, EXTRA_SHELL_CRV .. '*') if not nFirst then return end while nFirst do -- recupero tratti appartenenti alla stessa shell local sName = EgtGetName( nFirst) local vShells = EgtGetNameInGroup( nPathGrp, sName) -- inserisco la prima shell anche in fondo alla tabella per garantire anche il confronto fra l'ultima e la prima table.insert( vShells, vShells[1]) local nType = EgtGetInfo( nFirst, KEY_TYPE, 'i') local dStrand = EgtIf( nType == TYPE.EXTRA_OUTER_SHELL, LayerParams.dStrand, LayerParams.dInnerStrand) local nCurr = vShells[1] for i = 2, #vShells do if nCurr == vShells[i] then -- nell'ultimo confronto ( ultima e prima extra shell) potresti confrontare una curva con se stessa break end if dist( EgtSP( nCurr), EgtSP( vShells[i])) < dAlpha * dStrand + GEO.EPS_SMALL then -- start- start EgtAddCurveCompoLine( nCurr, EgtSP( vShells[i]), false) EgtInvertCurve( vShells[i]) EgtAddCurveCompoCurve( nCurr, vShells[i], false, false) UpdateExtraShellRetractionParamsAfterMerge( nCurr, vShells[i], 4) elseif dist( EgtSP( nCurr), EgtEP( vShells[i])) < dAlpha * dStrand + GEO.EPS_SMALL then -- start - end EgtAddCurveCompoLine( nCurr, EgtEP( vShells[i]), false) EgtAddCurveCompoCurve( nCurr, vShells[i], false, false) UpdateExtraShellRetractionParamsAfterMerge( nCurr, vShells[i], 2) elseif dist( EgtEP( nCurr), EgtSP( vShells[i])) < dAlpha * dStrand + GEO.EPS_SMALL then -- end - start EgtAddCurveCompoLine( nCurr, EgtSP( vShells[i])) EgtAddCurveCompoCurve( nCurr, vShells[i], false) UpdateExtraShellRetractionParamsAfterMerge( nCurr, vShells[i], 1) elseif dist( EgtEP( nCurr), EgtEP( vShells[i])) < dAlpha * dStrand + GEO.EPS_SMALL then -- end - end EgtAddCurveCompoLine( nCurr, EgtEP( vShells[i])) EgtInvertCurve( vShells[i]) EgtAddCurveCompoCurve( nCurr, vShells[i], false) UpdateExtraShellRetractionParamsAfterMerge( nCurr, vShells[i], 3) else nCurr = vShells[i] end end -- verifico se le curve si possono chiudere vShells = EgtGetNameInGroup( nPathGrp, sName) for i = 1, #vShells do if not EgtCurveIsClosed( vShells[i]) then if dist( EgtSP( vShells[i]), EgtEP( vShells[i])) < dAlpha * dStrand + GEO.EPS_SMALL then EgtCloseCurveCompo( vShells[i]) -- ripristino orientamento originale local vtCrv = EgtCurveArea( vShells[i]) if AreOppositeVectorApprox( vtCrv, s_vtSlicing) then EgtInvertCurve( vShells[i]) UpdateInvertInfo( vShells[i]) end end end end -- passo al gruppo di extra shell successivo nFirst = EgtGetNextName( vShells[#vShells], EXTRA_SHELL_CRV .. '*') end local vIds = EgtGetNameInGroup( nPathGrp, EXTRA_SHELL_CRV .. '*') if not vIds or #vIds == 0 then return end -- eventuale inversione di tutte le curve if LayerParams.bPrintInvert then for i = 1, #vIds do EgtInvertCurve( vIds[i]) UpdateInvertInfo( vIds[i]) end end -- cerco di creare percorsi local k = 1 -- indice da utilizzare per i nomi local vUsed = {} -- flag per indicare se corrispondente elemento di vIds è già stato considerato for i = 1, #vIds do vUsed[i] = false end local nCurr = vIds[1] vUsed[1] = true EgtSetName( nCurr, EXTRA_SHELL_CRV .. tostring(k)) while nCurr do local bEndChain = false local nCnt = 0 local vLinkedShells = { nCurr} local dCurrStrand local bSameStrand = true if EgtCurveIsClosed( nCurr) then ModifyStartPoint( nCurr, vPtStart) -- se è chiusa costituisce già una catena bEndChain = true end local ptSCurr = EgtSP( nCurr) local ptECurr = EgtEP( nCurr) while not bEndChain do local nCurrType = EgtGetInfo( nCurr, KEY_TYPE, 'i') dCurrStrand = EgtIf( nCurrType == TYPE.EXTRA_OUTER_SHELL, LayerParams.dStrand, LayerParams.dInnerStrand) local bFound = false for j = 1, #vIds do if not vUsed[j] and not EgtCurveIsClosed( vIds[j]) then local ptS = EgtSP( vIds[j]) local ptE = EgtEP( vIds[j]) local nTypeJ = EgtGetInfo( vIds[j], KEY_TYPE, 'i') local dStrandJ = EgtIf( nTypeJ == TYPE.EXTRA_OUTER_SHELL, LayerParams.dStrand, LayerParams.dInnerStrand) local dVal = dAlpha * max( dCurrStrand, dStrandJ) local bLink = false local bAddFirst = false if dist( ptECurr, ptE) < dVal then -- congiungo end-end EgtInvertCurve( vIds[j]) UpdateInvertInfo( vIds[j]) ptECurr = ptS bLink = true elseif dist( ptECurr, ptS) < dVal then -- congiungo end-start bLink = true ptECurr = ptE elseif dist( ptSCurr, ptE) < dVal then -- congiungo start-end -- il tratto va posizionato in testa bLink = true bAddFirst = true ptSCurr = ptS elseif dist( ptSCurr, ptS) < dVal then -- congiungo start-start bLink = true local vNewLinkedShells = {} for k = 1, #vLinkedShells do EgtInvertCurve( vLinkedShells[k]) UpdateInvertInfo( vLinkedShells[k]) EgtRelocateGlob( vLinkedShells[k], vLinkedShells[#vLinkedShells], GDB_IN.AFTER) table.insert( vNewLinkedShells, 1, vLinkedShells[k]) end vLinkedShells = vNewLinkedShells ptSCurr = EgtSP( vLinkedShells[1]) ptECurr = ptE end if bLink then EgtRelocateGlob( vIds[j], EgtIf( bAddFirst, vLinkedShells[1], vLinkedShells[#vLinkedShells]), EgtIf( bAddFirst, GDB_IN.BEFORE, GDB_IN.AFTER)) EgtSetName( vIds[j], EXTRA_SHELL_CRV .. tostring( k)) table.insert( vLinkedShells, EgtIf( bAddFirst, 1, #vLinkedShells + 1), vIds[j]) if abs( dStrandJ - dCurrStrand) > GEO.EPS_SMALL then bSameStrand = false end vUsed[j] = true -- aggiorno per collegamento successivo if not bAddFirst then bFound = true nCurr = vIds[j] break end end end end -- se non ho trovato setti da collegare la catena è finita, altrimenti posso cercare successivo bEndChain = not bFound end -- verifico se posso unire tutti i tratti appena trovati in curva chiusa if #vLinkedShells > 1 and bSameStrand and EgtGetInfo( vLinkedShells[1], KEY_TYPE, 'i') == TYPE.EXTRA_OUTER_SHELL and dist( EgtSP( vLinkedShells[1]), EgtEP( vLinkedShells[#vLinkedShells])) < dAlpha * dCurrStrand + GEO.EPS_SMALL then -- unisco le curve for i = 2, #vLinkedShells do EgtAddCurveCompoLine( vLinkedShells[1], EgtSP( vLinkedShells[i])) EgtAddCurveCompoCurve( vLinkedShells[1], vLinkedShells[i]) end EgtCloseCurveCompo( vLinkedShells[1]) ModifyStartPoint( vLinkedShells[1], vPtStart) EgtSetInfo( vLinkedShells[1], KEY_CLOSED_CRV, true) -- ripristino orientamento desiderato local vtCrv = EgtCurveArea( vLinkedShells[1]) if ( not LayerParams.bPrintInvert and AreOppositeVectorApprox( vtCrv, s_vtSlicing)) or ( LayerParams.bPrintInvert and AreSameVectorApprox( vtCrv, s_vtSlicing)) then EgtInvertCurve( vLinkedShells[1]) UpdateInvertInfo( vLinkedShells[1]) end end -- cerco il prossimo da cui partire nCurr = nil for i = 1, #vIds do if not vUsed[i] then nCurr = vIds[i] vUsed[i] = true k = k + 1 EgtSetName( nCurr, EXTRA_SHELL_CRV .. tostring(k)) break end end end end -------------------------------------------------------------------- local function CalcExtraShellsPath( nMaxShellNbrDiff, nShellNbrGrp, nCrvGrpId, dOffs, LayerParams, vPtStart, nRibsGrp) local nGrpId = EgtGetFirstNameInGroup( nCrvGrpId, PATH_GRP) local nGrpTmp = EgtGroup( nGrpId) -- gruppo temporaneo per conti -- recupero la superficie occupata dalle shell local nTotShellTrim = EgtGetFirstNameInGroup( nCrvGrpId, TOT_SHELL_TRIM_SURF) if not nTotShellTrim then EgtOutLog( 'Warning : ExtraInnerShells not possible (layer '..tostring( s_nCurrIdx)..') - CalcPaths') return end local dCurrStrand = 0 for nInd = nMaxShellNbrDiff, 1, -1 do if nInd == LayerParams.nShellsNbr then -- devo realizzare la shell esterna dOffs = dOffs + 0.5 * LayerParams.dStrand elseif nInd == LayerParams.nShellsNbr - 1 then -- devo realizzare la prima shell interna dOffs = dOffs + 0.5 * LayerParams.dStrand + LayerParams.dInnerStrand * ( 0.5 - LayerParams.dStrandOverlap / 100) else -- devo realizzare shell interne dOffs = dOffs + LayerParams.dInnerStrand * ( 1 - LayerParams.dStrandOverlap / 100) end dCurrStrand = EgtIf( nInd == LayerParams.nShellsNbr, LayerParams.dStrand, LayerParams.dInnerStrand) local nSrfDiff = EgtGetFirstNameInGroup( nShellNbrGrp, SHELL_NBR_SURF .. tostring( nInd)) local bOk = true local nOuterCrv = EgtGetFirstNameInGroup( nCrvGrpId, OUTER_CRV) while nOuterCrv do if not bOk then break end -- trim della outer curve con la superficie local nTrimCrv, nTrimCnt = TrimOuterCurveForExtraShellCalc( nOuterCrv, nSrfDiff, nGrpTmp, vPtStart, LayerParams) for nCrvT = nTrimCrv, nTrimCrv + nTrimCnt - 1 do if not bOk then break end -- calcolo offset della curva ( è il percorso della shell) local nOffs, nOffsCnt = EgtOffsetCurveAdv( nCrvT, - dOffs, GDB_OT.FILLET, s_dOffsTol) for nCrvOffs = nOffs, nOffs + nOffsCnt - 1 do -- calcolo la regione con cui fare trim ( con correzione extra per evitare tratti on) local nTrimSurf, bNoOverlap = ComputeTrimSurf( nTotShellTrim, nGrpTmp, dCurrStrand - 10 * s_dOffsCorr, LayerParams.dStrandOverlap) if not nTrimSurf then -- errore nel calcolo della superficie di trim EgtOutLog( 'Error : creation of ExtraShell failed (layer '.. EgtNumToString( s_nCurrIdx) ..') - CalcPaths') table.insert( s_vErr, ' - layer ' .. EgtNumToString( s_nCurrIdx) .. ' : error in computing extra shell') bOk = false break elseif nTrimSurf == GDB_ID.NULL then -- non c'è più spazio per realizzare le extra shell EgtOutLog( 'Warning : ExtraInnerShells not possible (layer '..tostring( s_nCurrIdx)..') - CalcPaths') bOk = false break else if bNoOverlap then EgtOutLog( 'Warning : ExtraShell without correct overlap (layer '.. EgtNumToString( s_nCurrIdx) ..') - CalcPaths') end local nCrv, nCnt = EgtTrimCurveWithRegion( nCrvOffs, nTrimSurf, true, true) if nCrv and nCnt ~= 0 then -- verifico se posso unire primo e ultimo tratto if nCrv and 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 for nId = nCrv, nCrv + nCnt - 1 do local dLen = EgtCurveLength( nId) local bValid = true if EgtCurveIsClosed( nId) then bValid = VerifyPath( nId, LayerParams.dStrand, nGrpId) end -- verifico se soddisfa vincolo sulla lunghezza if dLen > MIN_LEN and bValid then -- sposto nel path EgtRelocateGlob( nId, nGrpId) EgtSetStatus( nId, GDB_ST.ON) EgtModifyCurveExtrusion( nId, s_vtSlicing, GDB_RT.GLOB) EgtSetName( nId, EXTRA_SHELL_CRV .. tostring( nMaxShellNbrDiff - nInd + 1)) EgtSetInfo( nId, KEY_CRV_OFFSET, dOffs) if nInd == LayerParams.nShellsNbr then EgtSetInfo( nId, KEY_TYPE, TYPE.EXTRA_OUTER_SHELL) else EgtSetInfo( nId, KEY_TYPE, TYPE.EXTRA_SHELL) end -- verifico se può essere chiusa if not EgtCurveIsClosed( nId) then if dLen > dCurrStrand and dist( EgtSP( nId), EgtEP( nId)) < dCurrStrand + GEO.EPS_SMALL then EgtCloseCurveCompo( nId) end end -- aggiorno la superficie occupata dalle shell con quella appena calcolata UpdateTrimSurfWithExtraShell( nTotShellTrim, nId, dCurrStrand, nGrpId) else EgtErase( nId) end end end end end end nOuterCrv = EgtGetNextName( nOuterCrv, OUTER_CRV) end end -- ultimi aggiustamenti alla superfice di trim AdjustTrimSurfExtraAngleChunks( nTotShellTrim, dOffs, dCurrStrand, nGrpTmp) EgtErase( nGrpTmp) end -------------------------------------------------------------------- ------------------ AUX SOLIDS ------------------------------------- -------------------------------------------------------------------- local function UpdateTrimSurfWithAuxSolidsOffset( nSrfSolid, nSrfBase, dStrand, nCrvGrp) -- offset della superfice del solido local nSrfOffs = ComputeSurfOffset( nSrfSolid, nCrvGrp, dStrand * 0.5) if not nSrfOffs then EgtOutLog( 'Error : creation of AuxSolid region for TotTrimSurfRegion failed (layer '.. EgtNumToString( s_nCurrIdx) ..') - CalcPaths') table.insert( s_vErr, ' - layer ' .. EgtNumToString( s_nCurrIdx) .. ' : error in computing region for internal elements') else if not EgtSurfFrSubtract( nSrfBase, nSrfOffs) then EgtOutLog( 'Error : EgtSurfFrSubtract with AuxSolid for TotTrimSurfRegion failed (layer '.. EgtNumToString( s_nCurrIdx) ..') - CalcPaths') table.insert( s_vErr, ' - layer ' .. EgtNumToString( s_nCurrIdx) .. ' : error in computing region for internal elements') end 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 nSrfFatCrv = EgtSurfFrFatCurve( nGrpTmp, vCrvs[i], dStrand * 0.5 + 10 * GEO.EPS_SMALL, false, false, s_dOffsTol) local nOffsP = EgtExtractSurfFrChunkLoops( nSrfFatCrv, 0, nGrpTmp) 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 ortogonale alla direzione della svuotatura la approssimo if nType == GDB_TY.CRV_LINE and abs( vtDir * vtCurrDir) < 0.1 then -- cerco ultima curva con lo stesso orientamento local nLastValidId = nInd local nInd2 = nInd + 1 while nInd2 < nFirst + nCnt do local nType2 = EgtGetType( nInd2) if nType2 == GDB_TY.CRV_LINE and not AreSameOrOppositeVectorApprox( EgtSV( nInd2), vtDir) 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 not nSrfZigZag then -- uso la superficie occupata dall'aux solid, anche se potrebbe non corrispondere perfettamente con quella effettiva del percorso a zigzag EgtOutLog( 'Warning : approximation of the region filled by AuxSolid (layer '.. EgtNumToString( s_nCurrIdx) ..') - CalcPaths') nSrfZigZag = nSrf end -- aggiorno la TotShellSurfForTrim if not EgtSurfFrSubtract( nSrfBase, nSrfZigZag) then EgtOutLog( 'Error : EgtSurfFrSubtract with AuxSolid for TotTrimSurfRegion failed (layer '.. EgtNumToString( s_nCurrIdx) ..') - CalcPaths') table.insert( s_vErr, ' - layer ' .. EgtNumToString( s_nCurrIdx) .. ' : error in computing region for internal elements') end end EgtErase( nGrpTmp) end ------------------------------------------------------------------- local function AddExtraZigZag( nSrf, sName, dStrand, nGrp, nSrfTrim) local vIds = EgtGetNameInGroup( nGrp, sName) if not vIds or #vIds == 0 then return end local vtDir = EgtSV( vIds[1], GDB_ID.ROOT) local vtYLoc = s_vtSlicing ^ vtDir local nOuterLoop, nCnt = 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 < 0.5 * dStrand - 100 * GEO.EPS_SMALL 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 for nId = nOuterLoop, nOuterLoop + nCnt - 1 do EgtErase( nId) end end ------------------------------------------------------------------- local function ComputeAuxSolidsGenericInfill( nSrf, dStrand, sName, nPathGrp, vPtStart, nOrigSurf, dOverlap, nAuxSolidsGrp, bLink) if nSrf == GDB_ID.NULL then return end -- recupero gli infill associati local sNameInfill = AUX_SOLIDS_INFILL_CRV .. tostring( nOrigSurf) local vInfillIds = EgtGetNameInGroup( nAuxSolidsGrp, sNameInfill .. '*') or {} -- eseguo trim con la superficie for i = 1, #vInfillIds do local nCrv = EgtCopyGlob( vInfillIds[i], nPathGrp) -- eventuale inversione della curva per link if bLink and i % 2 == 0 then EgtInvertCurve( nCrv) UpdateInvertInfo( nCrv) end local nRes, nCnt = EgtTrimCurveWithRegion( nCrv, nSrf, true, true) for nId = nRes, nRes + nCnt - 1 do -- verifico se lunghezza minima local dLen = EgtCurveLength( nId) if dLen < MIN_INFILL_LEN then EgtErase( nId) else EgtSetName( nId, sName) EgtSetInfo( nId, KEY_TYPE, TYPE.INFILL) EgtSetInfo( nId, KEY_ASSOCIATED_SURF, nSrf) EgtModifyCurveExtrusion( nId, s_vtSlicing, GDB_RT.GLOB) end end end end -------------------------------------------------------------------- local function CalcAuxSolidsPaths( nSliceGrp, nSolidGrp, LayerParams, vPtStart) -- recupero i solidi ausiliari dividendoli per nome local vSolidIds = {} local nFirst = EgtGetFirstNameInGroup( nSolidGrp, AUX_SOLIDS_CRV .. '*') while nFirst do local sName = EgtGetName( nFirst) local vIds = EgtGetNameInGroup( nSolidGrp, sName) table.insert( vSolidIds, vIds) nFirst = EgtGetNextName( vIds[#vIds], AUX_SOLIDS_CRV .. '*') end -- 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 '.. EgtNumToString( s_nCurrIdx) ..') - CalcPaths') else for i = 1, #vSolidIds do -- creo la flat region corrispondente al solido ausiliario local sName = EgtGetName( vSolidIds[i][1]) local dStrand = EgtGetInfo( vSolidIds[i][1], KEY_AUX_SOLIDS_STRAND, 'd') local dOverlap = EgtGetInfo( vSolidIds[i][1], KEY_AUX_SOLIDS_OVERLAP, 'd') local nOrigSurf = EgtGetInfo( vSolidIds[i][1], KEY_ORIGINAL_SURF, 'i') local nInfillType = EgtGetInfo( vSolidIds[i][1], KEY_AUX_SOLIDS_INFILL, 'i') local bInfillLink = EgtGetInfo( vSolidIds[i][1], KEY_AUX_SOLIDS_INFILL_LINK, 'b') local nShells = EgtGetInfo( vSolidIds[i][1], KEY_AUX_SOLIDS_SHELLS_NBR, 'i') if nInfillType == FILL_TYPE.OFFSET then -- realizzo le shells insieme al riempimento nShells = 0 end local nSrfId = EgtSurfFlatRegion( nSolidPathGrp, vSolidIds[i]) if nSrfId then EgtSetName( nSrfId, AUX_SOLIDS_SRF) -- calcolo superficie con cui fare trim local nTrimSurf, bNoOverlap = ComputeTrimSurf( nSrfBase, nSolidPathGrp, dStrand, dOverlap) if not nTrimSurf then EgtOutLog( 'Error : creation of AuxSolid region failed (layer '.. EgtNumToString( s_nCurrIdx) ..') - CalcPaths') table.insert( s_vErr, ' - layer ' .. EgtNumToString( s_nCurrIdx) .. ' : creation of AuxSolid region failed') elseif nTrimSurf == GDB_ID.NULL then EgtOutLog( 'Warning : AuxSolids not possible (layer '.. EgtNumToString( s_nCurrIdx) ..') - CalcPaths') else if bNoOverlap then EgtOutLog( 'Warning : AuxSolids without correct overlap (layer '.. EgtNumToString( s_nCurrIdx) ..') - CalcPaths') end -- trim con la superficie di offset EgtSurfFrIntersect( nSrfId, nTrimSurf) local nFirst, nCnt = EgtExplodeSurf( nSrfId) for j = 0, nCnt - 1 do local sNewName = sName .. EgtIf( j == 0, '', '_' .. tostring( j)) -- calcolo shells if not ComputeOffsetShells( nFirst + j, dStrand, sNewName, TYPE.AUX_SOLID, nSolidPathGrp, vPtStart, nil, nShells) then EgtOutLog( 'Error : creation of AuxSolid shells failed (layer '.. EgtNumToString( s_nCurrIdx) ..') - CalcPaths') table.insert( s_vErr, ' - layer ' .. EgtNumToString( s_nCurrIdx) .. ' : creation of AuxSolid shells failed') end -- calcolo la superficie per il riempimento local nSrfFill if nShells > 0 then local dOffs = ( nShells - dOverlap / 100) * dStrand nSrfFill = ComputeSurfOffset( nFirst + j, nSolidPathGrp, - dOffs) if not nSrfFill then EgtOutLog( 'Error : creation of AuxSolid infill region failed (layer '.. EgtNumToString( s_nCurrIdx) ..') - CalcPaths') table.insert( s_vErr, ' - layer ' .. EgtNumToString( s_nCurrIdx) .. ' : creation of AuxSolid infill region failed') elseif nSrfFill == GDB_ID.NULL then EgtOutLog( 'Warning : AuxSolids infill not possible (layer '.. EgtNumToString( s_nCurrIdx) ..') - CalcPaths') end else -- la superficie per il riempimento è la surf del solido nSrfFill = nFirst + j end -- riempimento if nInfillType == FILL_TYPE.OFFSET then -- recupero le shells if not ComputeOffsetShells( nSrfFill, dStrand, sNewName, TYPE.AUX_SOLID, nSolidPathGrp, vPtStart) then EgtOutLog( 'Error : creation of AuxSolid offset infill failed (layer '.. EgtNumToString( s_nCurrIdx) ..') - CalcPaths') table.insert( s_vErr, ' - layer ' .. EgtNumToString( s_nCurrIdx) .. ' : creation of AuxSolid offset infill failed') end elseif nInfillType == FILL_TYPE.ZIGZAG then ComputeZigZagSolidFill( nSrfFill, dStrand, sNewName, TYPE.AUX_SOLID, nSolidPathGrp, EgtIf( nShells == 0, nTrimSurf, nil)) if nShells == 0 then -- aggiungo eventuale passata extra AddExtraZigZag( nSrfFill, sNewName, dStrand, nSolidPathGrp, nTrimSurf) end elseif nInfillType ~= FILL_TYPE.NONE then ComputeAuxSolidsGenericInfill( nSrfFill, dStrand, sNewName, nSolidPathGrp, vPtStart, nOrigSurf, dOverlap, nSolidGrp, bInfillLink) end -- aggiorno la superficie di trim con il solido ausiliario if nShells == 0 and nInfillType == FILL_TYPE.ZIGZAG then -- gestione speciale perchè non è detto che le passate corrispondano esattamente al solido UpdateTrimSurfWithAuxSolidsZigZag( nSolidPathGrp, sNewName, nSrfBase, dStrand, nFirst + j) else UpdateTrimSurfWithAuxSolidsOffset( nFirst + j, nSrfBase, dStrand, nSolidPathGrp) end end end else EgtOutLog( 'Error : creation of AuxSolid region failed (layer '.. EgtNumToString( s_nCurrIdx) ..') - CalcPaths') table.insert( s_vErr, ' - layer ' .. EgtNumToString( s_nCurrIdx) .. ' : creation of AuxSolid region failed') end 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) EgtStartCounter() s_nPartId = nPartId local vLayIds = EgtGetNameInGroup( s_nPartId, SLICE_LAYER.."*") if not vLayIds or #vLayIds == 0 then EgtOutBox( 'Error no slice', 'PathCalc') return true end -- recupero i parametri per calcolo dei path local LayerParams = GetLayerParamsForPathCalc() local nFirstSolidLay = EgtGetInfo( s_nPartId, KEY_FIRST_SOLID_LAY, 'i') or -1 local nLastSolidLay = EgtGetInfo( s_nPartId, KEY_LAST_SOLID_LAY, 'i') or -1 local nSlicingType = EgtGetInfo( s_nPartId, KEY_SLICING_TYPE, 'i') -- scorro tutti i suoi layer for nIdx = 1, #vLayIds do s_nCurrIdx = nIdx if nSlicingType == SLICING_TYPE.MULTIPLANAR or nSlicingType == SLICING_TYPE.MULTIPLANAR_DEG45 or nSlicingType == SLICING_TYPE.MULTIPLANAR_HOR then s_vtSlicing = EgtGetInfo( vLayIds[nIdx], KEY_SLICE_DIR, 'v') end local nRibsGrp = EgtGetFirstNameInGroup( vLayIds[nIdx], RIBS_GRP) local bIgnoreMergedRibs = true local nAuxSolidsGrp = EgtGetFirstNameInGroup( vLayIds[nIdx], AUX_SOLIDS_GRP) local nInfillGrp = EgtGetFirstNameInGroup( vLayIds[nIdx], INFILL_GRP) -- regioni con diverso numero di passate local nShellNbrGrp = EgtGetFirstNameInGroup( vLayIds[nIdx], SHELL_NBR_GRP) local nShellNbrSurfGrp = CreateShellNbrSurfaces( nShellNbrGrp, LayerParams.nShellsNbr) -- recupero gli start point per il layer local vPtStart = GetLayerStartPoint( vLayIds[nIdx]) -- 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 vOldIds local bPrevExists = true local dLastStrand = 0 local dOffs = - LayerParams.dOffs if nMaxShellNbrDiff < LayerParams.nShellsNbr then dOffs = dOffs + 0.5 * LayerParams.dStrand dLastStrand = LayerParams.dStrand local nSrfId = ComputeSurfOffset( nSrf, nCrvGrpId, - dOffs) if not nSrfId then EgtOutLog( 'Error : ExtOffset failed (layer '.. EgtNumToString( s_nCurrIdx) ..') - CalcPaths') table.insert( s_vErr, ' - layer ' .. EgtNumToString( s_nCurrIdx) .. ' : creation of OuterShell failed') elseif nSrfId == GDB_ID.NULL then EgtOutLog( 'Warning : ExtOffset not possible (layer '.. EgtNumToString( s_nCurrIdx) ..') - CalcPaths') else -- se offset riuscito, estraggo i contorni (pareti esterne) vOldIds = GetPathsFromSurf( nSrfId, SHELL_CRV ..'0', TYPE.OUTER_SHELL, nGrpId, vPtStart) for i = 1, #vOldIds do EgtSetInfo( vOldIds[i], KEY_CRV_OFFSET, dOffs) end end bPrevExists = ( nSrfId ~= GDB_ID.NULL) EgtErase( nSrfId) end -- pareti interne complete for nInd = 1, LayerParams.nShellsNbr - 1 - nMaxShellNbrDiff do dLastStrand = LayerParams.dInnerStrand -- offset della superficie originale if nInd == 1 then dOffs = dOffs + 0.5 * LayerParams.dStrand + LayerParams.dInnerStrand * ( 0.5 - LayerParams.dStrandOverlap / 100) else dOffs = dOffs + LayerParams.dInnerStrand * ( 1 - LayerParams.dStrandOverlap / 100) end local nSrfId = ComputeSurfOffset( nSrf, nCrvGrpId, - dOffs) if not nSrfId then EgtOutLog( 'Error : IntOffset failed (layer '.. EgtNumToString( s_nCurrIdx) ..') - CalcPaths') table.insert( s_vErr, ' - layer ' .. EgtNumToString( s_nCurrIdx) .. ' : creation of InnerShell failed') elseif nSrfId == GDB_ID.NULL then EgtOutLog( 'Warning : IntOffset ' .. EgtNumToString( nInd) .. ' not possible (layer '.. EgtNumToString( s_nCurrIdx) ..') - CalcPaths') else -- se offset riuscito, estraggo i contorni ( pareti interne) local vNewIds = GetPathsFromSurf( nSrfId, SHELL_CRV..tostring( nInd), TYPE.INNER_SHELL, nGrpId, vPtStart) ReorderPath( vOldIds, vNewIds) for i = 1, #vNewIds do EgtSetInfo( vNewIds[i], KEY_CRV_OFFSET, dOffs) end vOldIds = vNewIds -- se questo offset esiste ma il precedente no, allora il precedente è un errore da segnalare if not bPrevExists then local sElement = EgtIf( nInd > 1, 'IntOffset ' .. EgtNumToString( nInd - 1), 'ExtOffset') EgtOutLog( 'Error :' .. sElement .. ' failed (layer '.. EgtNumToString( s_nCurrIdx) ..') - CalcPaths') table.insert( s_vErr, ' - layer ' .. EgtNumToString( s_nCurrIdx) .. ' : creation of ' .. EgtIf( nInd > 1, 'InnerShell', 'OuterShell') .. ' failed') end end bPrevExists = ( nSrfId ~= GDB_ID.NULL) EgtErase( nSrfId) end -- preparo superficie occupata dalle shell da usare per trim local dSurfTrimOffs = dOffs + 0.5 * dLastStrand local nSrfTrim = ComputeSurfOffset( nSrf, nCrvGrpId, - dSurfTrimOffs) if not nSrfTrim then EgtOutLog( 'Error : offset for TotTrimSurfRegion failed (layer '.. EgtNumToString( s_nCurrIdx) ..') - CalcPaths') table.insert( s_vErr, ' - layer ' .. EgtNumToString( s_nCurrIdx) .. ' : error in computing region for internal elements') elseif nSrfTrim ~= GDB_ID.NULL then EgtSetName( nSrfTrim, TOT_SHELL_TRIM_SURF) EgtSetStatus( nSrfTrim, GDB_ST.OFF) -- se questo offset esiste ma il precedente no, allora il precedente è un errore da segnalare if not bPrevExists then EgtOutLog( 'Error : IntOffset' .. EgtNumToString( LayerParams.nShellsNbr - 1 - nMaxShellNbrDiff) .. ' failed (layer '.. EgtNumToString( s_nCurrIdx) ..') - CalcPaths') table.insert( s_vErr, ' - layer ' .. EgtNumToString( s_nCurrIdx) .. ' : creation of InnerShell failed') end end -- pareti coinvolte dal diverso numero di passate if nMaxShellNbrDiff > 0 then CalcExtraShellsPath( nMaxShellNbrDiff, nShellNbrSurfGrp, nCrvGrpId, dOffs, LayerParams, vPtStart, nRibsGrp) end -- ribs-merged shells bIgnoreMergedRibs = CalcRibsMergedShells( nRibsGrp, nGrpId, LayerParams, vPtStart) -- riordino extra shells ReorderExtraShells( nGrpId, vPtStart, LayerParams) end -- passo al gruppo di contorni successivo nCrvGrpId = EgtGetNextName( nCrvGrpId, CONTOUR_GRP.."*") or GDB_ID.NULL end -- gestione solidi ausiliari ( se no floor o ceil) if nAuxSolidsGrp and ( nFirstSolidLay + LayerParams.nFloorNbr <= nIdx and nIdx <= nLastSolidLay - LayerParams.nCeilNbr or LayerParams.nShellsNbr == 0) then CalcAuxSolidsPaths( vLayIds[nIdx], nAuxSolidsGrp, LayerParams, vPtStart) end -- gestione riempimenti if LayerParams.nShellsNbr > 0 then -- infill if nFirstSolidLay + LayerParams.nFloorNbr <= nIdx and nIdx <= nLastSolidLay - LayerParams.nCeilNbr then CalcInfillPaths( vLayIds[nIdx], nInfillGrp, LayerParams) -- floor elseif nFirstSolidLay <= nIdx and nIdx < nFirstSolidLay + LayerParams.nFloorNbr then CalcSolidFillPath( vLayIds[nIdx], LayerParams, vPtStart, LayerParams.nFloorType) -- ceil elseif nLastSolidLay - LayerParams.nCeilNbr < nIdx and nIdx <= nLastSolidLay then CalcSolidFillPath( vLayIds[nIdx], LayerParams, vPtStart, LayerParams.nCeilType) end end -- gestione costolature if nRibsGrp then CalcRibsPaths( vLayIds[nIdx], nRibsGrp, LayerParams, vPtStart, bIgnoreMergedRibs) end if EgtProcessEvents( EgtIf( PRINT, 200, 0) + nIdx / #vLayIds * 100, 0) == 1 then EgtDraw() return false end end -- report tempo di calcolo in log EgtOutLog( string.format( ' CalcPathTime = %.2f ms', EgtStopCounter())) if #s_vErr > 0 then EgtOutBox( 'CalcPath Error on :\n' .. table.concat( s_vErr, '\n'), 'Calculating Paths') end return true end --------------------------------------------------------------------- return CalcPaths