-- DiceCut.lua by Egaltech s.r.l. 2023/06/29 -- Gestione dei piano paralleli nei tagli lunghi: equidistanziamento dei piani paralleli -- Tabella per definizione modulo local DiceCut = {} -- Include require( 'EgtBase') local BL = require( 'BeamLib') EgtOutLog( ' DiceCut started', 1) -- Dati local BD = require( 'BeamData') ---------------------------------------------------------------------------------------------------------------------------------------------------- -- creo i piani paralleli -- GetParallelPlanes: restituisce un vettore con gli indici delle superfici -- nParent: il layer -- BBoxRawPart: il grezzo della barra -- ptC: il punto centrale del piano della feature -- vtN: il versore normale del piano della feature -- nCopyPlane: 0 => genera una copia del piano passato, 1=> non genera una copia del piano passato -- dOffset: offset dei piani paralleli -- nStep: numero massimo di step -- Color: colre del fascio di piani -- dTolerance*: distanza tra i piani paralleli e i piani di taglio (se non esistono altre superfici può essere omesso) -- bNoTolOnFirstCut*: elimina la tolleranza per il primo piano del fascio (se non esistono altre superfici può essere omesso) -- ptCCut*: il punto centrale della superfice limitante (se non esistono altre superfici può essere omesso) -- vtNCut*: il punto centrale della superfice limitante (se non esistono altre superfici può essere omesso) -- ptCCut1*: il punto centrale della superfice limitante (se non esistono altre superfici può essere omesso) -- vtNCut1*: il punto centrale della superfice limitante (se non esistono altre superfici può essere omesso) local function GetParallelPlanes( nParent, BBoxRawPart, ptC, vtN, nCopyPlane, dOffset, nStep, Color, dTolerance, bNoTolOnFirstCut, ptCCut, vtNCut, ptCCut1, vtNCut1 ) local ptMyCCut local AreaMin = 5*5 if ptCCut and vtNCut then if dTolerance then ptMyCCut = Point3d( ptCCut + dTolerance * vtNCut) end ptMyCCut = Point3d( ptCCut) end local ptMyCCut1 if ptCCut1 and vtNCut1 then ptMyCCut1 = Point3d( ptCCut1 + 0 * vtNCut1) end local TabellaTmSurfParallel = {} local i = nCopyPlane while i < nStep do local SurfId = EgtSurfTmPlaneInBBox( nParent, ptC + ( i * dOffset) * vtN, vtN, BBoxRawPart, GDB_RT.GLOB) local nFacet = EgtSurfTmFacetCount( SurfId or GDB_ID.NULL) if nFacet == 0 then -- se sono al primo taglio do una possibilità in più di girare if i > nCopyPlane then break end end if nFacet > 0 and vtNCut and ptMyCCut and EgtSurfArea(SurfId) > AreaMin then if i == nCopyPlane and bNoTolOnFirstCut then EgtCutSurfTmPlane( SurfId, ptCCut, -vtNCut, false, GDB_RT.GLOB) else EgtCutSurfTmPlane( SurfId, ptMyCCut, -vtNCut, false, GDB_RT.GLOB) end nFacet = EgtSurfTmFacetCount( SurfId) end if nFacet > 0 and vtNCut1 and ptMyCCut1 and EgtSurfArea(SurfId) > AreaMin then if i == nCopyPlane and bNoTolOnFirstCut then EgtCutSurfTmPlane( SurfId, ptCCut1, -vtNCut1, false, GDB_RT.GLOB) else EgtCutSurfTmPlane( SurfId, ptMyCCut1, -vtNCut1, false, GDB_RT.GLOB) end nFacet = EgtSurfTmFacetCount( SurfId) end if nFacet > 0 and EgtSurfArea(SurfId) > AreaMin then table.insert( TabellaTmSurfParallel, SurfId) EgtSetColor( SurfId, Color) else EgtErase( SurfId) end if dOffset == 0 then break end i = i + 1 end return TabellaTmSurfParallel end ---------------------------------------------------------------------------------------------------------------------------------------------------- -- GetOrderedCutTable: -- nParent: il layer -- TabParallelPlanes: tabella delle superfici dei piani paralleli -- TabOrtoPlanes: tabella delle superfici dei piani ortogonali -- stampo l'ordine dei piani di taglio (prima tagli ortogonali piu' esterni poi taglio parallelo collettivo) local function GetOrderedCutTable( nParent, TabParallelPlanes, TabOrtoPlanes) local StepParallel = #TabParallelPlanes local StepOrto = #TabOrtoPlanes local TabellaOrderParallelCut1 = {} for IndexTmP=1, StepParallel do TabellaOrderParallelCut1[IndexTmP] = {} for IndexOrto=1, StepOrto do local ptOrtoN, vtNOrtoN = EgtSurfTmFacetCenter( TabOrtoPlanes[IndexOrto ], 0, GDB_ID.ROOT) local Copy1Id = EgtCopySurfTmFacet( TabParallelPlanes[IndexTmP], 0, nParent) local Copy2Id = EgtCopySurfTmFacet( TabParallelPlanes[IndexTmP], 0, nParent) if Copy1Id and ptOrtoN then EgtCutSurfTmPlane( Copy1Id, ptOrtoN, -vtNOrtoN, false, GDB_RT.GLOB) EgtCutSurfTmPlane( Copy2Id, ptOrtoN, vtNOrtoN, false, GDB_RT.GLOB) local nFacet1 = EgtSurfTmFacetCount( Copy1Id) local nFacet2 = EgtSurfTmFacetCount( Copy2Id) if nFacet1 < 1 then EgtErase( Copy1Id) EgtErase( Copy2Id) EgtCutSurfTmPlane( TabParallelPlanes[IndexTmP], ptOrtoN, vtNOrtoN, false, GDB_RT.GLOB) elseif nFacet2 < 1 then EgtErase( Copy1Id) EgtErase( Copy2Id) break else table.insert( TabellaOrderParallelCut1[IndexTmP], Copy1Id) EgtErase( Copy2Id) EgtCutSurfTmPlane( TabParallelPlanes[IndexTmP], ptOrtoN, vtNOrtoN, false, GDB_RT.GLOB) end end end table.insert(TabellaOrderParallelCut1[IndexTmP], TabParallelPlanes[IndexTmP]) end return TabellaOrderParallelCut1 end ---------------------------------------------------------------------------------------------------------------------------------------------------- -- GetOrtoCutCenter: -- idFacet: l'id della faccia -- ptC: il punto centrale della faccia -- vtN: il versore normale della faccia -- vtO: il versore dei piani ortogonali -- dOffsetEff: offset della distanza dal punto centrale -- Verifica se l'asse X del box costruito sopra la superficie è più grande di un certo offset local function GetOrtoCutCenter( FacetId, ptC, vtN, vtO, dOffsetEff, dNzLimDwnUp) local FrameLocal = Frame3d( EgtSurfTmFacetCenter( FacetId, 0, GDB_ID.ROOT)) EgtSetGridFrame(FrameLocal) local IdAuxLocal = EgtGroup(EgtGetParent( FacetId), FrameLocal) EgtSetName( IdAuxLocal, "AuxLocal") local BoxLocal = EgtGetBBoxRef( FacetId, GDB_BB.STANDARD, FrameLocal) local ptS = EgtGP( EgtSurfTmBBox( IdAuxLocal, BoxLocal, GDB_RT.GRID), GDB_ID.ROOT) EgtErase( IdAuxLocal) EgtSetGridFrame(Frame3d()) -- riferimento intrinseco local asseX = Vector3d( vtO) local asseY = vtN ^ asseX local Frame = Frame3d( ptC, ptC + asseX, ptC + asseY) -- ingombro della faccia secondo questo riferimento local Box = EgtGetBBoxRef( FacetId, GDB_BB.STANDARD, Frame) local dLen = Box:getDimX() local dWidth = Box:getDimY() -- se faccia non troppo lunga, con un lato piccolo e non diretta troppo verso il basso, non servono dice local dMaxLen = BD.MAX_LEN_DICE or 600 if dLen < dMaxLen and dWidth < dMaxLen and ( dLen < dOffsetEff + 1.0 or dWidth < dOffsetEff + 1.0) and vtN:getZ() > dNzLimDwnUp then return nil, nil, nil end local N = ceil( dLen / dOffsetEff) local dOffsetRel = ( dLen / N) + 10 * GEO.EPS_SMALL local dCopyPlane local dCenOffs = ( Box:getMax():getX() + Box:getMin():getX()) / 2 if dLen <= dOffsetRel then dCopyPlane = 1 elseif dLen <= 2 * dOffsetRel then dOffsetRel = dOffsetEff dCopyPlane = 0 else if N % 2 == 0 then dCopyPlane = 0 elseif N % 2 == 1 then dCopyPlane = 0.5 end end return dOffsetRel, dCopyPlane, dCenOffs, ptS end ---------------------------------------------------------------------------------------------------------------------------------------------------- -- TableMesh: -- TableOrto: tabella delle superfici dei piani ortogonali -- TableParallel: tabella delle superfici dei piani paralleli -- Forma una tabella unica delle superfici di taglio inserendo strati di tagli ortogonali alternati da strati di taglio parallelo local function TableMesh( TableOrto, TableParallel) local TableUnited = {} for i=1, #TableOrto do table.insert( TableUnited, TableOrto[i]) table.insert( TableUnited, TableParallel[i]) end return TableUnited end ---------------------------------------------------------------------------------------------------------------------------------------------------- -- FindValue: -- tab: tabella da scansionare -- val: valore da cercare -- Verifica se tab contiene val, a supporto della funzione SortOrtoCutsByNormalMethod local function FindValue( tab, val) for index, value in ipairs( tab) do if value == val then return true end end return false end ---------------------------------------------------------------------------------------------------------------------------------------------------- -- SortOrtoCutsByNormalMethod: -- TabParallelPlanes: tabella delle superfici dei piani paralleli -- TabOrtoPlanes: tabella delle superfici dei piani ortogonali -- stampo l'ordine dei piani di taglio sfruttando il prodotto dei versori normali (prima tagli ortogonali piu' esterni poi taglio parallelo collettivo) local function SortOrtoCutsByNormalMethod( TabParallelPlanes, TabOrtoPlanes) -- tabella dei tagli ordinati local TabOrderOrtoCut = {} -- tabella ausiliaria dei dati inseriti nell'ordine local TabAux = {} -- ciclo di ordinamento local StepParallel = #TabParallelPlanes local StepOrto = #TabOrtoPlanes for IndexTmP=1, StepParallel do TabOrderOrtoCut[IndexTmP] = {} local ptParalN, vtNParalN = EgtSurfTmFacetCenter( TabParallelPlanes[IndexTmP][1], 0, GDB_ID.ROOT) for IndexOrto=1, StepOrto do for i=1, #TabOrtoPlanes[IndexOrto] do -- identificativo del taglio local OrtoPlaneId = TabOrtoPlanes[IndexOrto][i] -- controlla che l'elemento da valutare non sia gia' stato inserito nella tabella if not FindValue( TabAux, OrtoPlaneId) then local ptOrtoN, vtNOrtoN = EgtSurfTmFacetCenter( OrtoPlaneId, 0, GDB_ID.ROOT) local scalarProduct = ( ptOrtoN - ptParalN) * vtNParalN if scalarProduct > 0 then table.insert( TabOrderOrtoCut[IndexTmP], OrtoPlaneId) table.insert( TabAux, OrtoPlaneId) end end end end end -- cancello dal DB geometrico i tagli non inseriti for IndexOrto=1, StepOrto do for i=1, #TabOrtoPlanes[IndexOrto] do -- identificativo del taglio local OrtoPlaneId = TabOrtoPlanes[IndexOrto][i] -- ricerco il taglio tra gli inseriti if not FindValue( TabAux, OrtoPlaneId) then EgtErase( OrtoPlaneId) end end end return TabOrderOrtoCut end ---------------------------------------------------------------------------------------------------------------------------------------------------- -- VerifyFirstOrthoCut : -- CutTable: tabella dei tagli -- OffsetP: offset della distanza dal punto centrale -- BBoxRawPart: il grezzo della barra -- Verifica se l'asse X del box costruito sopra le 2 facce è più piccolo di un certo offset e quindi la faccia O è superflua local function VerifyFirstOrthoCut( CutTable, OffsetP, BBoxRawPart, dNzLimDwnUp) if not CutTable[1] or not CutTable[2] then return end local CutOId = CutTable[1][1] local Cut1Id = CutTable[2][1] local Cut2Id = CutTable[2][2] if CutOId and Cut1Id and Cut2Id then -- centri e normali delle due semifacce local ptC1, vtN1 = EgtSurfTmFacetCenter( Cut1Id, 0, GDB_ID.ROOT) local ptC2, vtN2 = EgtSurfTmFacetCenter( Cut2Id, 0, GDB_ID.ROOT) -- normale alla faccia ortogonale local _, vtO = EgtSurfTmFacetCenter( CutOId, 0, GDB_ID.ROOT) vtO = vtO - vtO * vtN1 * vtN1 ; vtO:normalize() -- calcolo lunghezza prima semi-faccia local asseX1 = vtO local asseY1 = vtN1 ^ asseX1 local Frame1 = Frame3d( ptC1, ptC1+asseX1, ptC1+asseY1) local Box1 = EgtGetBBoxRef( Cut1Id, GDB_BB.STANDARD, Frame1) local x1 = Box1:getDimX() -- calcolo lunghezza seconda semi-faccia local asseX2 = vtO local asseY2 = vtN2 ^ asseX2 local Frame2 = Frame3d( ptC2, ptC2+asseX2, ptC2+asseY2) local Box2 = EgtGetBBoxRef( Cut2Id, GDB_BB.STANDARD, Frame2) local x2 = Box2:getDimX() -- lunghezza totale faccia local dLongSize = x1 + x2 -- se faccia piccola e non orientata verso il basso, elimino ortogonale e unisco le due parti if dLongSize <= OffsetP + 1.0 and vtN1:getZ() > dNzLimDwnUp then local nParent = EgtGetParent( Cut1Id) local SurfId = EgtSurfTmBySewing( nParent, { Cut1Id, Cut2Id}) EgtSetColor( SurfId, Color3d( FUCHSIA(), 60)) EgtErase( CutOId) table.remove( CutTable[1], 1) table.remove( CutTable[2], 1) table.remove( CutTable[2], 1) table.insert( CutTable[2], 1, SurfId) end end end ---------------------------------------------------------------------------------------------------------------------------------------------------- -- ricavo i vertici del box local function CalcolaPuntiEstremiBox( BBoxRawPart) local ptMin = BBoxRawPart:getMin() local ptMax = BBoxRawPart:getMax() local TBoxPoint = {} table.insert( TBoxPoint, { P = Point3d( ptMin:getX(), ptMin:getY(), ptMin:getZ()), On = true}) table.insert( TBoxPoint, { P = Point3d( ptMax:getX(), ptMin:getY(), ptMin:getZ()), On = true}) table.insert( TBoxPoint, { P = Point3d( ptMin:getX(), ptMax:getY(), ptMin:getZ()), On = true}) table.insert( TBoxPoint, { P = Point3d( ptMax:getX(), ptMax:getY(), ptMin:getZ()), On = true}) table.insert( TBoxPoint, { P = Point3d( ptMin:getX(), ptMin:getY(), ptMax:getZ()), On = true}) table.insert( TBoxPoint, { P = Point3d( ptMax:getX(), ptMin:getY(), ptMax:getZ()), On = true}) table.insert( TBoxPoint, { P = Point3d( ptMin:getX(), ptMax:getY(), ptMax:getZ()), On = true}) table.insert( TBoxPoint, { P = Point3d( ptMax:getX(), ptMax:getY(), ptMax:getZ()), On = true}) return TBoxPoint end ---------------------------------------------------------------------------------------------------------------------------------------------------- -- restituisce i punti che devono essere presi in considerazione per la costruzione del BoundingBox local function VerificaEstremiGrezzo( ptC, vtN, TPoint) for i = 1, #TPoint do if ( TPoint[i].P - ptC) * vtN < 0 then TPoint[i].On = false end end return TPoint end ---------------------------------------------------------------------------------------------------------------------------------------------------- -- ricavo l'altezza del BoundingBox assegnati gli estremi del grezzo e la feature -- le funzioni commentate permettono di vedere la creazione di BoundingBox local function DistanzaMassima( nParent, ptC1, vtN1, ptC2, vtN2, BBoxRawPart, TPoint) -- calcolo il riferimento nel piano 1 local Frame1 = Frame3d( ptC1, vtN1) -- determino l'ingombro in questo riferimento della parte di trave compresa nel o nei piani local BB1 = BBox3d() -- punti di vertice della trave compresi for i = 1, #TPoint do if TPoint[i].On then local ptP = Point3d( TPoint[i].P) ptP:toLoc( Frame1) BB1:Add( ptP) end end -- eventuale altra faccia if ptC2 and vtN2 then local IdAux = EgtGroup( nParent) local IdSurf2 = EgtSurfTmPlaneInBBox( IdAux, ptC2, vtN2, BBoxRawPart, GDB_RT.GLOB) EgtCutSurfTmPlane( IdSurf2, ptC1, -vtN1, false, GDB_RT.GLOB) if IdSurf2 then local BB2 = EgtGetBBoxRef( IdSurf2, GDB_BB.STANDARD, Frame1) BB1:Add( BB2) end EgtErase( IdAux) end if not BB1:isEmpty() then return ( BB1:getMax():getZ() + 0.1) end return 0 end ---------------------------------------------------------------------------------------------------------------------------------------------------- -- DiceCut.GetDice : -- nParent: il layer -- BBoxRawPart: il grezzo della barra -- ptCPlanes: il punto centrale del piano della feature -- vtNPlanes: il versore normale del piano della feature -- bGetOrtoPlanes*: se voglio calcolare i piani ortogonali al piano passato (se non esistono altre superfici può essere omesso) -- ptCBond*: il punto centrale della superfice limitante (se non esistono altre superfici può essere omesso) -- vtNBond*: il versore normale della superfice limitante (se non esistono altre superfici può essere omesso) -- dOrthoMaxDim : massima profondità taglio se faccia singola perpendicolare facce laterali trave -- dCustMaxDimDice: dimensione massima customizzata, sostituisce il parametro BD.MAX_DIM_DICE (se negativa qualunque, se positiva deve stare nel MAX) -- bDownHead : taglio con testa da sotto ---------------------------------------------------------------------------------------------------------------------------------------------------- function DiceCut.GetDice( nParent, BBoxRawPart, ptCPlanes, vtNPlanes, bGetOrtoPlanes, ptCBond, vtNBond, dOrthoMaxDim, dCustMaxDimDice, bDownHead) local dMaxDimDice = BD.MAX_DIM_DICE if dCustMaxDimDice and dCustMaxDimDice < BD.MAX_DIM_DICE then dMaxDimDice = abs( dCustMaxDimDice) end local dTolerance = 0 -- distanza di sicurezza per i tagli ortogonali local OffsetP = dMaxDimDice -- distanza tra i piani paralleli local StepP = 100 -- numero massimo di piani paralleli da generare local OffsetO = dMaxDimDice -- distanza tra i piani ortogonali local StepO = 100 -- numero massimo di piani ortogonali da generare --Ricavo le altezze dei BoundingBox contenente feature e estremi del grezzo local TBoxPoint = CalcolaPuntiEstremiBox( BBoxRawPart) TBoxPoint = VerificaEstremiGrezzo( ptCPlanes, vtNPlanes, TBoxPoint) if ptCBond and vtNBond then TBoxPoint = VerificaEstremiGrezzo( ptCBond, vtNBond, TBoxPoint) end local dElevP = DistanzaMassima( nParent, ptCPlanes, vtNPlanes, ptCBond, vtNBond, BBoxRawPart, TBoxPoint) local dElevO if ptCBond and vtNBond then dElevO = DistanzaMassima( nParent, ptCBond, vtNBond, ptCPlanes, vtNPlanes, BBoxRawPart, TBoxPoint) end -- inclinazione limite per taglio da sotto local dNzLimDwnUp = BL.GetNzLimDownUp( BBoxRawPart) -- se non c'è testa da sotto e normali senza componenti in Y con faccia quasi verticale e trave non alta, uso per offset i limiti dei tagli di testa e coda if not BD.DOWN_HEAD and abs( vtNPlanes:getY()) < 0.1 and vtNPlanes:getZ() < 0.7071 and ( not vtNBond or abs( vtNBond:getY()) < 0.1) and BBoxRawPart:getDimZ() < BD.MIN_DIM_HBEAM then OffsetO = dOrthoMaxDim or BD.MAX_DIM_HTCUT end -- aggiungo piccolo extra agli offset OffsetP = OffsetP + 10 * GEO.EPS_SMALL OffsetO = OffsetO + 10 * GEO.EPS_SMALL -- se seconda faccia non definita, forzo calcolo piani ortogonali if not ptCBond or not vtNBond then bGetOrtoPlanes = true end -- se piani non ortogonali, diminuisco la distanza di offset opportunamente local originalOffsetP = OffsetP if not bGetOrtoPlanes then local dCoeff = ( vtNPlanes ^ vtNBond):len() OffsetP = OffsetP * dCoeff OffsetO = OffsetO * dCoeff end local n = ceil( dElevP / OffsetP) OffsetP = dElevP / n if dElevO then local m = ceil( dElevO / OffsetO) OffsetO = dElevO / m end -- elenco di tutte le superfici generate dai tagli local TabFUCHSIA = {} local TabGREEN = {} -- PIANI PARALLELI alla faccia di taglio local TabellaTmSurfP = {} local TabFromIn = GetParallelPlanes( nParent, BBoxRawPart, ptCPlanes, vtNPlanes, 0, OffsetP, StepP, Color3d( FUCHSIA(), 60), dTolerance, true, ptCBond, vtNBond) for i = #TabFromIn, 1, -1 do table.insert( TabellaTmSurfP, TabFromIn[i]) end -- PIANI ORTOGONALI alla faccia di taglio -- orientamento definito da seconda faccia if not bGetOrtoPlanes then local TabellaTmSurfOrto = {} local TabFromIn = GetParallelPlanes( nParent, BBoxRawPart, ptCBond, vtNBond, 0, OffsetO, StepO, Color3d( GREEN(), 60), dTolerance, false, ptCPlanes, vtNPlanes) for i = #TabFromIn, 1, -1 do table.insert( TabellaTmSurfOrto, TabFromIn[i]) end local TabellaOrderParallelCut = GetOrderedCutTable( nParent, TabellaTmSurfP, TabellaTmSurfOrto) -- Ottiene la tabella dei tagli paralleli ordinati local TabellaOrderOrtoCut = GetOrderedCutTable( nParent, TabellaTmSurfOrto, TabellaTmSurfP) -- Ottiene la tabella dei tagli ortogonali da riordinare per strato TabGREEN = SortOrtoCutsByNormalMethod( TabellaOrderParallelCut, TabellaOrderOrtoCut) -- I tagli ortogonali vengono ordinati per strato TabFUCHSIA = TabellaOrderParallelCut -- I tagli paralleli sono già ordinati -- orientamento da definire else for PlnInd = 1, #TabellaTmSurfP do -- piano interno local ptCInner, vtNInner = EgtSurfTmFacetCenter( TabellaTmSurfP[PlnInd], 0, GDB_ID.ROOT) -- eventuale piano esterno local ptCOuter, vtNOuter = nil, nil if PlnInd > 1 then ptCOuter, vtNOuter = EgtSurfTmFacetCenter( TabellaTmSurfP[PlnInd-1], 0, GDB_ID.ROOT) vtNOuter = -vtNOuter end -- calcolo la direzione dei piani ortogonali local vtO = VectorFromUprightOrtho( vtNInner) if vtNInner:getZ() > -0.0175 or vtNInner:getZ() < dNzLimDwnUp or abs( vtNInner:getY()) > 0.8 then vtO:rotate( vtNInner, 90) -- se diretto troppo ortogonalmente all'asse trave e taglio non da sotto, lo ruoto ulteriormente if ( abs( vtO:getY()) > 4 * abs( vtO:getX()) or BBoxRawPart:getDimZ() > 620) and vtNInner:getZ() > dNzLimDwnUp then vtO:rotate( vtNInner, 90) -- se faccia principale verso il basso (almeno -3deg), lo inverto per iniziare da sopra if vtNInner:getZ() < -0.05 then vtO = -vtO end else if vtNInner:getX() > -0.017 then if vtO:getX() < -0.001 then vtO = -vtO end else if vtO:getX() > 0.001 then vtO = -vtO end end end end -- se quasi verticale (fino a 20 gradi di distanza) su faccia inclinata in Y, ruoto di 90 gradi if vtO:getZ() > 0.939 and abs( vtNInner:getY()) > 0.5 then vtO:rotate( vtNInner, 90) end -- se taglio con testa da sotto if bDownHead and vtO:getZ() > 0.05 then vtO = -vtO end -- per macchina TURN if BD.TURN then if vtO:getY() > 0.707 then vtO = -vtO end end -- calcolo le dimensioni dell'offset e dove posizionare la prima faccia: -- CopyPlane: 0 => crea la prima faccia direttamente sul punto passato -- CopyPlane: 1 => crea la prima faccia e tutte le altre con l'offset passato -- CopyPlane: 0.5 => crea la prima faccia a metà offset e tutte le altre con l'offest intero local OffsetRel, CopyPlane, dCenOffs, ptCStart = GetOrtoCutCenter( TabellaTmSurfP[PlnInd], ptCInner, vtNInner, vtO, OffsetO, dNzLimDwnUp) if OffsetRel and CopyPlane and dCenOffs then ptCInner = ptCInner + dCenOffs * vtO local TabRight = GetParallelPlanes( nParent, BBoxRawPart, ptCStart, vtO, CopyPlane, -OffsetRel, StepO, Color3d( GREEN(), 60), dTolerance, false, ptCInner, vtNInner, ptCOuter, vtNOuter) if CopyPlane == 0 then CopyPlane = 1 end local TabLeft = GetParallelPlanes( nParent, BBoxRawPart, ptCStart, vtO, CopyPlane, OffsetRel, StepO, Color3d( GREEN(), 60), dTolerance, false, ptCInner, vtNInner, ptCOuter, vtNOuter) -- carico la tabella con gli indici riordinati local TempOrtoTab = {} for i = #TabLeft, 1, -1 do table.insert( TempOrtoTab, TabLeft[i]) end for i = 1, #TabRight do table.insert( TempOrtoTab, TabRight[i]) end -- creo una tabella per ogni piano per generare i tagli sulla Inner local TempParTab = GetOrderedCutTable( nParent, {TabellaTmSurfP[PlnInd]}, TempOrtoTab) for i = 1, #TempParTab do table.insert( TabFUCHSIA, TempParTab[i]) end table.insert( TabGREEN, TempOrtoTab) else table.insert( TabFUCHSIA, {TabellaTmSurfP[PlnInd]}) table.insert( TabGREEN, {}) end end end -- Se sono state costruite non più di una faccia parallela e una faccia perpendicolare, allora non servono e tengo le originali if #TabGREEN == 1 and #TabGREEN[1] <= 1 and #TabFUCHSIA == 1 and #TabFUCHSIA[1] <= 1 then if #TabGREEN[1] == 1 then EgtErase( TabGREEN[1][1]) end TabGREEN = {} if #TabFUCHSIA[1] == 1 then EgtErase( TabFUCHSIA[1][1]) end TabFUCHSIA = {} end -- Si uniscono le tabelle dei tagli ortogonali e paralleli in una sola tabella local UltimateTable = TableMesh( TabGREEN, TabFUCHSIA) -- Se esiste la superficie limitante (nFacet == 2) verifica se il taglio più esterno è superfluo e quindi viene eliminato if not bGetOrtoPlanes then VerifyFirstOrthoCut( UltimateTable, originalOffsetP, BBoxRawPart, dNzLimDwnUp) -- se rimangono due sole facce, devono coincidere con le originali e quindi sono superflue if #UltimateTable == 2 and #UltimateTable[1] == 1 and #UltimateTable[2] == 1 then EgtErase( UltimateTable[1][1]) EgtErase( UltimateTable[2][1]) UltimateTable = {} end end return UltimateTable end ---------------------------------------------------------------------------------------------------------------------------------------------------- -- PrintOrderCut: -- TabellaOrderCut: tabella delle superfici di taglio -- stampo l'ordine dei piani di taglio ricevendo una tabella con gli strati parallelo/ortogonali già ordinati function DiceCut.PrintOrderCut( TabellaOrderCut) local Step = #TabellaOrderCut if Step > 0 then EgtOutLog( " L'ordine delle superfici da tagliare è il seguente:") else EgtOutLog( ' Non sono necessarie superfici aggiuntive di taglio.') end for i = 1, Step do if i % 2 == 1 then EgtOutLog( ' *** Strato di taglio ' .. EgtNumToString( ( i + 1) / 2, 0)) if #TabellaOrderCut[i] > 0 then EgtOutLog( ' Tagli ortogonali: ') else EgtOutLog( ' Tagli ortogonali assenti') end else if #TabellaOrderCut[i] > 0 then EgtOutLog( ' Tagli paralleli: ') else EgtOutLog( ' Tagli paralleli assenti') end end for j=1, #TabellaOrderCut[i] do EgtOutLog( ' Indice faccia ' .. (TabellaOrderCut[i][j] or 0)) end end end ---------------------------------------------------------------------------------------------------------------------------------------------------- local function DiceCutTest() -- salvo l'indice del layer Trimesh selezionato local SelectedIndex = EgtGetFirstSelectedObj() -- verifico che sia selezionato un elemento if not SelectedIndex then return end -- salvo l'indice del layer Processing local nParent = EgtGetParent( SelectedIndex) -- salvo l'indice del layer Part local nRawPart = EgtGetParent( nParent) local nBox = EgtGetFirstNameInGroup( nRawPart, 'Box') -- carico il bounding box della trave -- local BBoxRawPart = EgtGetBBoxGlob( nRawPart, GDB_BB.STANDARD ) local BBoxRawPart = EgtGetBBoxGlob( nBox, GDB_BB.STANDARD ) -- seleziono il Part e il Layer di destinazione EgtSetCurrPartLayer( nRawPart, nParent) -- conto il numero di facce da processare local nFacet = EgtSurfTmFacetCount( SelectedIndex) EgtOutLog( ' Numero facce ' .. nFacet, 1) -- salvo local TabPlanesFeatures = {} for i = 1, nFacet do local ptC, vtN = EgtSurfTmFacetCenter( SelectedIndex, i - 1, GDB_ID.ROOT) table.insert( TabPlanesFeatures, { ptC = ptC, vtN = vtN}) end local ptC1 = Point3d( TabPlanesFeatures[1].ptC) local vtN1 = Vector3d( TabPlanesFeatures[1].vtN) local CutTable = {} if nFacet == 1 then CutTable = DiceCut.GetDice( nParent, BBoxRawPart, ptC1, vtN1, true) elseif nFacet == 2 then CutTable = DiceCut.GetDice( nParent, BBoxRawPart, ptC1, vtN1, false, TabPlanesFeatures[2].ptC, TabPlanesFeatures[2].vtN) end if EgtGetDebugLevel() >= 3 then DiceCut.PrintOrderCut( CutTable) end EgtDeselectAll() EgtDraw() end ---------------------------------------------------------------------------------------------------------------------------------------------------- --DiceCutTest() return DiceCut