Files
DataBeam/LuaLibs/DiceCut.lua
T
DarioS fdd959cf85 DataBeam :
- piccole correzioni varie.
2022-02-21 07:03:00 +01:00

642 lines
29 KiB
Lua

-- DiceCut.lua by Egaltech s.r.l. 2022/02/18
-- 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 = vtO
local asseY = asseX ^ vtN
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
local dCopyPlane
local dCenOffs = ( Box:getMax():getX() + Box:getMin():getX()) / 2
if dLen <= dOffsetRel then
--dOffsetRel = 0
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
-- bDownHead : taglio con testa da sotto
----------------------------------------------------------------------------------------------------------------------------------------------------
function DiceCut.GetDice( nParent, BBoxRawPart, ptCPlanes, vtNPlanes, bGetOrtoPlanes, ptCBond, vtNBond, dOrthoMaxDim, dCustMaxDimDice, bDownHead)
local dMaxDimDice = EgtIf( dCustMaxDimDice and dCustMaxDimDice < BD.MAX_DIM_DICE, dCustMaxDimDice, BD.MAX_DIM_DICE)
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()) > 3 * 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 then vtO = - vtO end
else
if vtO:getX() > 0 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
-- 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)
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