676 lines
30 KiB
Lua
676 lines
30 KiB
Lua
-- DiceCut.lua by Egalware s.r.l. 2024/01/23
|
|
-- Gestione dei piano paralleli nei tagli lunghi: equidistanziamento dei piani paralleli
|
|
|
|
-- Tabella per definizione modulo
|
|
local DiceCut = {}
|
|
|
|
-- Include
|
|
require( 'EgtBase')
|
|
local BeamLib = require( 'BeamLib')
|
|
|
|
EgtOutLog( ' DiceCut started', 1)
|
|
|
|
-- Dati
|
|
local BeamData = require( 'BeamDataNew')
|
|
|
|
----------------------------------------------------------------------------------------------------------------------------------------------------
|
|
-- creo i piani paralleli
|
|
-- GetParallelPlanes: restituisce un vettore con gli indici delle superfici
|
|
-- idAddGroup: il layer
|
|
-- b3BoxDicing: 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( idAddGroup, b3BoxDicing, 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( idAddGroup, ptC + ( i * dOffset) * vtN, vtN, b3BoxDicing, 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:
|
|
-- idAddGroup: 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( idAddGroup, 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, idAddGroup)
|
|
local Copy2Id = EgtCopySurfTmFacet( TabParallelPlanes[IndexTmP], 0, idAddGroup)
|
|
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)
|
|
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
|
|
-- TODO si può eliminare questo test dato che vengono verificate già volume e dimensione del cubetto??
|
|
local dMaxLen = BeamData.MAX_LEN_DICE or 600
|
|
if dLen < dMaxLen and dWidth < dMaxLen and
|
|
( dLen < dOffsetEff + 1.0 or dWidth < dOffsetEff + 1.0) 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
|
|
-- dOffsetParallel: offset della distanza dal punto centrale
|
|
-- b3BoxDicing: 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, dOffsetParallel, b3BoxDicing)
|
|
|
|
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()
|
|
local dMaxElev = EgtSurfTmFacetElevationInBBox( CutOId, 0, b3BoxDicing, true, GDB_ID.ROOT)
|
|
-- 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()
|
|
-- prendo il massimo tra la lugnhezza della faccia parallela e l'elevazione della corrispondente ortogonale
|
|
x1 = max( x1, dMaxElev)
|
|
-- 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 <= dOffsetParallel + 1.0 then
|
|
local idAddGroup = EgtGetParent( Cut1Id)
|
|
local SurfId = EgtSurfTmBySewing( idAddGroup, { 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( b3BoxDicing)
|
|
local ptMin = b3BoxDicing:getMin()
|
|
local ptMax = b3BoxDicing: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( idAddGroup, ptC1, vtN1, ptC2, vtN2, b3BoxDicing, 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( idAddGroup)
|
|
local IdSurf2 = EgtSurfTmPlaneInBBox( IdAux, ptC2, vtN2, b3BoxDicing, 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 BeamData.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)
|
|
|
|
|
|
---------------------------------------------------------------------------------------------------------------
|
|
-- DiceCut.GetDice :
|
|
-- Part : pezzo
|
|
-- Face1 : table. Contiene tutti i dati della faccia principale. Obbligatori i campi '.ptCenter' e '.vtN'
|
|
-- Face2 : table. Contiene tutti i dati della faccia secondaria. Se non esiste, la table è vuota ({}). Se esiste, obbligatori i campi '.ptCenter' e '.vtN'
|
|
-- OptionaParameters : eventuali parametri opzionali
|
|
---------------------------------------------------------------------------------------------------------------
|
|
function DiceCut.GetDice( Part, Face1, Face2, OptionalParameters)
|
|
-- gruppo per geometria addizionale
|
|
local idAddGroup
|
|
if OptionalParameters.bSaveAddedGeometries then
|
|
idAddGroup = BeamLib.GetAddGroup( Part.id)
|
|
else
|
|
idAddGroup = Part.idTempGroup
|
|
end
|
|
|
|
-- faccia primaria
|
|
local ptCMainFace
|
|
local vtNMainFace
|
|
if Face1.ptCenter and Face1.vtN then
|
|
ptCMainFace = Point3d( Face1.ptCenter)
|
|
vtNMainFace = Vector3d( Face1.vtN)
|
|
end
|
|
-- faccia secondaria; se non esiste, si forza il calcolo dei piani ortogonali
|
|
local ptCSubordinateFace
|
|
local vtNSubordinateFace
|
|
local bGetOrtoPlanes
|
|
if Face2.ptCenter and Face2.vtN then
|
|
ptCSubordinateFace = Point3d( Face2.ptCenter)
|
|
vtNSubordinateFace = Vector3d( Face2.vtN)
|
|
bGetOrtoPlanes = false
|
|
else
|
|
bGetOrtoPlanes = true
|
|
end
|
|
|
|
-- parametri opzionali e default
|
|
-- box per dicing
|
|
local b3BoxDicing = OptionalParameters.b3BoxDicing or Part.b3Part
|
|
-- distanza tra piani paralleli
|
|
local dOffsetParallel = OptionalParameters.dOffsetParallel or BeamData.MAX_DIM_DICE
|
|
-- distanza tra piani ortogonali
|
|
local dOffsetOrthogonal = OptionalParameters.dOffsetOrthogonal or BeamData.MAX_DIM_DICE
|
|
-- numero massimo piani paralleli
|
|
local nStepParallel = OptionalParameters.nStepParallel or 100
|
|
-- numero massimo piani perpendicolari
|
|
local nStepOrthogonal = OptionalParameters.nStepOrthogonal or 100
|
|
-- distanza tra piani paralleli e piani di taglio (era sempre 0, serve???)
|
|
local dTolerance = OptionalParameters.dTolerance or 0
|
|
|
|
--Ricavo le altezze dei BoundingBox contenente feature e estremi del grezzo
|
|
local TBoxPoint = CalcolaPuntiEstremiBox( b3BoxDicing)
|
|
TBoxPoint = VerificaEstremiGrezzo( ptCMainFace, vtNMainFace, TBoxPoint)
|
|
if ptCSubordinateFace and vtNSubordinateFace then
|
|
TBoxPoint = VerificaEstremiGrezzo( ptCSubordinateFace, vtNSubordinateFace, TBoxPoint)
|
|
end
|
|
local dElevP = DistanzaMassima( idAddGroup, ptCMainFace, vtNMainFace, ptCSubordinateFace, vtNSubordinateFace, b3BoxDicing, TBoxPoint)
|
|
local dElevO
|
|
if ptCSubordinateFace and vtNSubordinateFace and not AreOppositeVectorApprox( vtNSubordinateFace, vtNMainFace) then
|
|
dElevO = DistanzaMassima( idAddGroup, ptCSubordinateFace, vtNSubordinateFace, ptCMainFace, vtNMainFace, b3BoxDicing, TBoxPoint)
|
|
end
|
|
|
|
-- aggiungo piccolo extra agli offset
|
|
dOffsetParallel = dOffsetParallel + 10 * GEO.EPS_SMALL
|
|
dOffsetOrthogonal = dOffsetOrthogonal + 10 * GEO.EPS_SMALL
|
|
|
|
-- se piani non ortogonali, diminuisco la distanza di offset opportunamente
|
|
local dOffsetParallelOriginal = dOffsetParallel
|
|
if not bGetOrtoPlanes then
|
|
local dCoeff = max( ( vtNMainFace ^ vtNSubordinateFace):len(), 0.5)
|
|
dOffsetParallel = dOffsetParallel * dCoeff
|
|
dOffsetOrthogonal = dOffsetOrthogonal * dCoeff
|
|
end
|
|
|
|
local n = ceil( dElevP / dOffsetParallel)
|
|
dOffsetParallel = dElevP / n
|
|
if dElevO then
|
|
local m = ceil( dElevO / dOffsetOrthogonal)
|
|
dOffsetOrthogonal = 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( idAddGroup, b3BoxDicing, ptCMainFace, vtNMainFace, 0, dOffsetParallel, nStepParallel, Color3d( FUCHSIA(), 60), dTolerance, true, ptCSubordinateFace, vtNSubordinateFace)
|
|
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( idAddGroup, b3BoxDicing, ptCSubordinateFace, vtNSubordinateFace, 0, dOffsetOrthogonal, nStepOrthogonal, Color3d( GREEN(), 60), dTolerance, false, ptCMainFace, vtNMainFace)
|
|
for i = #TabFromIn, 1, -1 do
|
|
table.insert( TabellaTmSurfOrto, TabFromIn[i])
|
|
end
|
|
local TabellaOrderParallelCut = GetOrderedCutTable( idAddGroup, TabellaTmSurfP, TabellaTmSurfOrto) -- Ottiene la tabella dei tagli paralleli ordinati
|
|
local TabellaOrderOrtoCut = GetOrderedCutTable( idAddGroup, 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 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 b3BoxDicing:getDimZ() > 620) 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
|
|
-- 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, dOffsetOrthogonal)
|
|
|
|
if OffsetRel and CopyPlane and dCenOffs then
|
|
ptCInner = ptCInner + dCenOffs * vtO
|
|
local TabRight = GetParallelPlanes( idAddGroup, b3BoxDicing, ptCStart, vtO, CopyPlane, -OffsetRel, nStepOrthogonal, Color3d( GREEN(), 60),
|
|
dTolerance, false, ptCInner, vtNInner, ptCOuter, vtNOuter)
|
|
if CopyPlane == 0 then
|
|
CopyPlane = 1
|
|
end
|
|
local TabLeft = GetParallelPlanes( idAddGroup, b3BoxDicing, ptCStart, vtO, CopyPlane, OffsetRel, nStepOrthogonal, 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( idAddGroup, {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, dOffsetParallelOriginal, b3BoxDicing)
|
|
-- 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 nAddGrpId = EgtGetParent( SelectedIndex)
|
|
-- salvo l'indice del layer Part
|
|
local nRawPart = EgtGetParent( nAddGrpId)
|
|
local nBox = EgtGetFirstNameInGroup( nRawPart, 'Box')
|
|
-- carico il bounding box della trave
|
|
-- local b3BoxDicing = EgtGetBBoxGlob( nRawPart, GDB_BB.STANDARD )
|
|
local b3BoxDicing = EgtGetBBoxGlob( nBox, GDB_BB.STANDARD )
|
|
-- seleziono il Part e il Layer di destinazione
|
|
EgtSetCurrPartLayer( nRawPart, nAddGrpId)
|
|
|
|
-- 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( nAddGrpId, b3BoxDicing, ptC1, vtN1, true)
|
|
elseif nFacet == 2 then
|
|
CutTable = DiceCut.GetDice( nAddGrpId, b3BoxDicing, ptC1, vtN1, false, TabPlanesFeatures[2].ptC, TabPlanesFeatures[2].vtN)
|
|
end
|
|
|
|
if EgtGetDebugLevel() >= 3 then
|
|
DiceCut.PrintOrderCut( CutTable)
|
|
end
|
|
|
|
EgtDeselectAll()
|
|
|
|
EgtDraw()
|
|
end
|
|
|
|
----------------------------------------------------------------------------------------------------------------------------------------------------
|
|
--DiceCutTest()
|
|
|
|
return DiceCut
|