Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b882f23d3e | |||
| 8c39c6a94f | |||
| e126e3f389 | |||
| 3bce7b5fd6 | |||
| 99e0bd27d9 | |||
| 456d8e903a | |||
| 14f81da3df | |||
| eb4a5e521f | |||
| 233a928dcd | |||
| db88c7bb8d | |||
| 992a115f93 | |||
| 50753dda52 | |||
| cff250ca37 | |||
| 7309ebb6a3 | |||
| c649870518 | |||
| 3d8ec03c47 | |||
| 42329d7688 |
@@ -44,8 +44,8 @@ local function GetStrategies_Egalware( Proc)
|
||||
Strategies = { { sStrategyId = 'HEADCUT'}}
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Cut
|
||||
elseif ID.IsSplitCut( Proc) then
|
||||
Strategies = { { sStrategyId = 'SPLITCUT'}}
|
||||
elseif ID.IsTailCut( Proc) then
|
||||
Strategies = { { sStrategyId = 'TAILCUT'}}
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Cut
|
||||
elseif ID.IsCut( Proc) then
|
||||
@@ -302,8 +302,8 @@ local function GetStrategies_Essetre( Proc)
|
||||
Strategies = { { sStrategyId = 'HEADCUT'}}
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Cut
|
||||
elseif ID.IsSplitCut( Proc) then
|
||||
Strategies = { { sStrategyId = 'SPLITCUT'}}
|
||||
elseif ID.IsTailCut( Proc) then
|
||||
Strategies = { { sStrategyId = 'TAILCUT'}}
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Cut
|
||||
elseif ID.IsCut( Proc) then
|
||||
|
||||
+56
-14
@@ -146,11 +146,13 @@ function BeamExec.GetToolsFromDB()
|
||||
Tool.dStep = EgtGetValInNotes( Tool.sUserNotes, 'STEP', 'd') or ( Tool.dMaxMaterial / 3) -- se non settato nell'utensile, considero metà del tagliente
|
||||
Tool.dSideStep = EgtGetValInNotes( Tool.sUserNotes, 'SIDESTEP', 'd') or floor( Tool.dDiameter / 3) -- se non settato nell'utensile, considero metà del diametro
|
||||
Tool.bIsPen = abs( Tool.dSpeed) < 5
|
||||
Tool.dPerformanceIndex = ( Tool.dDiameter * Tool.dMaxMaterial) / Tool.dLength
|
||||
-- recupero parametri propri delle lame
|
||||
elseif sToolFamily == 'SAWBLADE' then
|
||||
Tool.bIsUsedForLongCut = EgtGetValInNotes( Tool.sUserNotes, 'LONGCUT') == 1 or false -- false come valore di default
|
||||
Tool.dStep = EgtGetValInNotes( Tool.sUserNotes, 'STEP', 'd') or Tool.dThickness -- se non settato nell'utensile, considero lo spessore lama
|
||||
Tool.dSideStep = EgtGetValInNotes( Tool.sUserNotes, 'SIDESTEP', 'd') or Tool.dMaxMaterial -- se non settato nell'utensile, considero un quarto del diametro
|
||||
Tool.dPerformanceIndex = 1 / ( Tool.dDiameter * Tool.dLength)
|
||||
-- recupero parametri propri delle motoseghe
|
||||
elseif sToolFamily == 'MORTISE' then
|
||||
Tool.dDistance = EgtTdbGetCurrToolParam( MCH_TP.DIST) or 90 -- 90mm dimensione standard aggregato catena
|
||||
@@ -160,7 +162,11 @@ function BeamExec.GetToolsFromDB()
|
||||
Tool.dSideStep = EgtGetValInNotes( Tool.sUserNotes, 'SIDESTEP', 'd') or ( Tool.dThickness - 1) -- se non settato nell'utensile, considero spessore catena meno 1mm di sicurezza
|
||||
Tool.dCornerRadius = EgtTdbGetCurrToolParam( MCH_TP.CORNRAD)
|
||||
Tool.dWidth = Tool.dDiameter
|
||||
Tool.dPerformanceIndex = 1 / Tool.dLength
|
||||
end
|
||||
-- drillbit
|
||||
else
|
||||
Tool.dPerformanceIndex = Tool.dDiameter / Tool.dLength
|
||||
end
|
||||
|
||||
-- se tutti i dati necessari sono disponibili, inserisco utensile nella lista globale degli utensili disponibili
|
||||
@@ -375,13 +381,13 @@ function BeamExec.ProcessBeams( dRawW, dRawH, dRawL, dOvmHead, dOvmMid, PARTS)
|
||||
local dDeltaE = BeamData.OVM_MID
|
||||
for i = 1, #PARTS do
|
||||
-- dati del pezzo
|
||||
local b3Part = EgtGetBBoxGlob( PARTS[i].id or GDB_ID.NULL, GDB_BB.EXACT)
|
||||
if b3Part:isEmpty() or PARTS[i].b3Box:isEmpty() then break end
|
||||
EgtOutLog( 'PartSez=' .. EgtNumToString( b3Part:getDimY(), 1) .. 'x' .. EgtNumToString( b3Part:getDimZ(), 1), 3)
|
||||
local b3BoxExact = EgtGetBBoxGlob( PARTS[i].id or GDB_ID.NULL, GDB_BB.EXACT)
|
||||
if b3BoxExact:isEmpty() or PARTS[i].b3PartOriginal:isEmpty() then break end
|
||||
EgtOutLog( 'PartSez=' .. EgtNumToString( b3BoxExact:getDimY(), 1) .. 'x' .. EgtNumToString( b3BoxExact:getDimZ(), 1), 3)
|
||||
-- se sezione compatibile e lunghezza disponibile sufficiente
|
||||
local dPartLen = PARTS[i].b3Box:getDimX()
|
||||
local dPartWidth = PARTS[i].b3Box:getDimY()
|
||||
local dPartHeight = PARTS[i].b3Box:getDimZ()
|
||||
local dPartLen = PARTS[i].b3PartOriginal:getDimX()
|
||||
local dPartWidth = PARTS[i].b3PartOriginal:getDimY()
|
||||
local dPartHeight = PARTS[i].b3PartOriginal:getDimZ()
|
||||
local dNextLen = dLen - EgtIf( i == 1, dDeltaS, 0) - dPartLen - dDeltaE
|
||||
if (( abs( dPartWidth - dRawW) < 100 * GEO.EPS_SMALL and abs( dPartHeight - dRawH) < 100 * GEO.EPS_SMALL) or
|
||||
( abs( dPartHeight - dRawW) < 100 * GEO.EPS_SMALL and abs( dPartWidth - dRawH) < 100 * GEO.EPS_SMALL)) and
|
||||
@@ -411,7 +417,7 @@ function BeamExec.ProcessBeams( dRawW, dRawH, dRawL, dOvmHead, dOvmMid, PARTS)
|
||||
return false, sOut
|
||||
end
|
||||
-- aggiungo faccia per taglio iniziale al pezzo
|
||||
BeamLib.AddPartStartFace( PARTS[i].id, PARTS[i].b3Box)
|
||||
BeamLib.AddPartStartFace( PARTS[i].id, PARTS[i].b3PartOriginal)
|
||||
-- se sovramateriale di testa, lo notifico
|
||||
if dDeltaS > 0.09 then
|
||||
EgtSetInfo( PARTS[i].idRaw, 'HOVM', dDeltaS)
|
||||
@@ -423,16 +429,16 @@ function BeamExec.ProcessBeams( dRawW, dRawH, dRawL, dOvmHead, dOvmMid, PARTS)
|
||||
EgtSetInfo( PARTS[i].idRaw, 'TOVM', dDeltaE)
|
||||
end
|
||||
-- aggiungo faccia per taglio finale al pezzo
|
||||
BeamLib.AddPartEndFace( PARTS[i].id, PARTS[i].b3Box)
|
||||
BeamLib.AddPartEndFace( PARTS[i].id, PARTS[i].b3PartOriginal)
|
||||
-- inserisco il pezzo nel grezzo
|
||||
EgtDeselectPartObjs( PARTS[i].id)
|
||||
local ptPos = b3Part:getMin() - PARTS[i].b3Box:getMin() + Vector3d( dDelta, ( dRawW - dPartWidth) / 2, ( dRawH - dPartHeight) / 2)
|
||||
local ptPos = b3BoxExact:getMin() - PARTS[i].b3PartOriginal:getMin() + Vector3d( dDelta, ( dRawW - dPartWidth) / 2, ( dRawH - dPartHeight) / 2)
|
||||
EgtAddPartToRawPart( PARTS[i].id, ptPos, PARTS[i].idRaw)
|
||||
if abs( dPartWidth - dRawW) > 100 * GEO.EPS_SMALL then
|
||||
-- rotazione attorno a centro geometria complessiva del pezzo
|
||||
EgtRotatePartInRawPart( PARTS[i].id, X_AX(), 90)
|
||||
-- correggo per eccentricità solido rispetto a geometria complessiva del pezzo
|
||||
local vtEccOri = PARTS[i].b3Box:getCenter() - b3Part:getCenter()
|
||||
local vtEccOri = PARTS[i].b3PartOriginal:getCenter() - b3BoxExact:getCenter()
|
||||
local vtEccRot = Vector3d( vtEccOri)
|
||||
vtEccRot:rotate( X_AX(), 90)
|
||||
EgtMovePartInRawPart( PARTS[i].id, ( vtEccOri - vtEccRot))
|
||||
@@ -450,9 +456,10 @@ function BeamExec.ProcessBeams( dRawW, dRawH, dRawL, dOvmHead, dOvmMid, PARTS)
|
||||
PARTS[i].dWidth = PARTS[i].b3Raw:getDimY()
|
||||
PARTS[i].dHeight = PARTS[i].b3Raw:getDimZ()
|
||||
PARTS[i].bSquareSection = abs( PARTS[i].dWidth - PARTS[i].dHeight) < 100 * GEO.EPS_SMALL
|
||||
PARTS[i].b3Solid = EgtGetBBoxGlob( EgtGetFirstNameInGroup( PARTS[i].id, 'Box') or GDB_ID.NULL, GDB_BB.STANDARD)
|
||||
PARTS[i].b3Part = EgtGetBBoxGlob( EgtGetFirstNameInGroup( PARTS[i].id, 'Box') or GDB_ID.NULL, GDB_BB.STANDARD)
|
||||
PARTS[i].nIndexInParts = i
|
||||
PARTS[i].CombinationList = GetAvailableCombinations( PARTS[i])
|
||||
PARTS[i].SplittingPoints = BeamLib.GetPartSplittingPoints( PARTS[i])
|
||||
else
|
||||
local sOut = 'Error: part L(' .. EgtNumToString( dPartLen, 1) .. ') too big for raw part L(' .. EgtNumToString( dLen - 0.1, 1) .. ')'
|
||||
return false, sOut
|
||||
@@ -981,6 +988,7 @@ local function CalculateMachinings( vProc, Part)
|
||||
bAreAllApplyOk, _ = StrategyScript.Make( true, Proc, Part, Proc.ChosenStrategy.Parameters)
|
||||
end
|
||||
end
|
||||
|
||||
return MACHININGS
|
||||
end
|
||||
|
||||
@@ -1326,11 +1334,45 @@ function BeamExec.ProcessMachinings( PROCESSINGS, PARTS)
|
||||
|
||||
-- esegue le strategie migliori che ha precedentemente scelto e salva le lavorazioni nella lista globale
|
||||
MACHININGS = CalculateMachinings( vProc, PARTS[nPart])
|
||||
MACHININGS = MachiningLib.PrepareMachiningsForSorting( PARTS[nPart])
|
||||
|
||||
-- TODO riordinare lavorazioni ottimizzando cambio utensile/spezzone ecc..., mantenendo dipendenze definite prima
|
||||
-- ordino le lavorazioni
|
||||
-- MACHININGS = OrderMachining( MACHININGS, PARTS[nPart])
|
||||
--TODO - rimuovere o mettere in Log, serve solo per test
|
||||
-- TEST
|
||||
local MachiningPropertiesBeforeSorting = {}
|
||||
for i =1, #MACHININGS do
|
||||
MachiningPropertiesBeforeSorting[i] = {}
|
||||
MachiningPropertiesBeforeSorting[i] = {
|
||||
ptCenter = MACHININGS[i].Machining.ptCenter,
|
||||
nStage = MACHININGS[i].Machining.nStage,
|
||||
nPartSegment = MACHININGS[i].Machining.nPartSegment,
|
||||
sToolFamily = TOOLS[ MACHININGS[i].Machining.nToolIndex].sFamily,
|
||||
dToolPerformanceIndex = TOOLS[ MACHININGS[i].Machining.nToolIndex].dPerformanceIndex,
|
||||
sToolName = TOOLS[ MACHININGS[i].Machining.nToolIndex].sName,
|
||||
vtToolDirection = MACHININGS[i].Machining.vtToolDirection
|
||||
}
|
||||
end
|
||||
-- fine TEST
|
||||
|
||||
-- TODO completare ordinamento. Mancano le dipendenze.
|
||||
MACHININGS = BeamLib.StableSort( MACHININGS, MachiningLib.CompareMachinings)
|
||||
|
||||
--TODO - rimuovere o mettere in Log, serve solo per test
|
||||
-- TEST
|
||||
local MachiningPropertiesAfterSorting = {}
|
||||
for i =1, #MACHININGS do
|
||||
MachiningPropertiesAfterSorting[i] = {}
|
||||
MachiningPropertiesAfterSorting[i] = {
|
||||
ptCenter = MACHININGS[i].Machining.ptCenter,
|
||||
nStage = MACHININGS[i].Machining.nStage,
|
||||
nPartSegment = MACHININGS[i].Machining.nPartSegment,
|
||||
sToolFamily = TOOLS[ MACHININGS[i].Machining.nToolIndex].sFamily,
|
||||
dToolPerformanceIndex = TOOLS[ MACHININGS[i].Machining.nToolIndex].dPerformanceIndex,
|
||||
sToolName = TOOLS[ MACHININGS[i].Machining.nToolIndex].sName,
|
||||
vtToolDirection = MACHININGS[i].Machining.vtToolDirection
|
||||
}
|
||||
end
|
||||
-- fine TEST
|
||||
|
||||
-- aggiungo la fase, se non è la prima
|
||||
if nOrd == 1 then
|
||||
EgtSetCurrPhase( 1)
|
||||
|
||||
+159
-6
@@ -90,6 +90,48 @@ function BeamLib.AddPartEndFace( PartId, b3Solid)
|
||||
return true
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
function BeamLib.GetPartSplittingPoints( Part, OptionalParameters)
|
||||
local PartSplittingPoints = {}
|
||||
local dPartLength = Part.b3Part:getDimX()
|
||||
|
||||
-- parametri opzionali
|
||||
if not OptionalParameters then
|
||||
OptionalParameters = {}
|
||||
end
|
||||
local dMaxSegmentLength = OptionalParameters.dMaxSegmentLength or BeamData.LONGCUT_MAXLEN
|
||||
local dMaxSegmentLengthOnEdges = OptionalParameters.dMaxSegmentLengthOnEdges or BeamData.LONGCUT_ENDLEN
|
||||
|
||||
if dPartLength < dMaxSegmentLength + 10 * GEO.EPS_SMALL then
|
||||
return {}
|
||||
elseif dPartLength >= dMaxSegmentLength + 10 * GEO.EPS_SMALL
|
||||
and dPartLength < 3 * dMaxSegmentLengthOnEdges + 10 * GEO.EPS_SMALL then
|
||||
local dXPartCentralPoint = ( Part.b3Part:getMax():getX() - Part.b3Part:getMin():getX()) / 2
|
||||
table.insert( PartSplittingPoints, Point3d( dXPartCentralPoint, 0, 0))
|
||||
else
|
||||
-- punto estremo destro
|
||||
local dSplitXRight = Part.b3Part:getMax():getX() - dMaxSegmentLengthOnEdges
|
||||
table.insert( PartSplittingPoints, Point3d( dSplitXRight, 0, 0))
|
||||
|
||||
-- punti centrali
|
||||
local dPartCentralLength = dPartLength - 2 * dMaxSegmentLengthOnEdges
|
||||
local nSplitParts = max( ceil( dPartCentralLength / dMaxSegmentLength + 10 * GEO.EPS_SMALL), 1)
|
||||
local dSplitPartsLen = dPartCentralLength / nSplitParts
|
||||
for i = 1, ( nSplitParts - 1) do
|
||||
local ptOn
|
||||
local dCurrentPointX = dSplitXRight - i * dSplitPartsLen
|
||||
ptOn = Point3d( dCurrentPointX, 0, 0)
|
||||
table.insert( PartSplittingPoints, ptOn)
|
||||
end
|
||||
|
||||
-- punto estremo sinistro
|
||||
local dSplitXLeft = Part.b3Part:getMin():getX() + dMaxSegmentLengthOnEdges
|
||||
table.insert( PartSplittingPoints, Point3d( dSplitXLeft, 0, 0))
|
||||
end
|
||||
|
||||
return PartSplittingPoints
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
function BeamLib.AddPhaseWithRawParts( nRawId, OriXR, PosXR, dDeltaSucc)
|
||||
EgtAddPhase()
|
||||
@@ -193,22 +235,22 @@ end
|
||||
function BeamLib.GetAffectedFaces( Proc, Part)
|
||||
local vtFacesAffected = { bTop = false, bBottom = false, bFront = false, bBack = false, bLeft = false, bRight = false}
|
||||
if Proc.b3Box and not Proc.b3Box:isEmpty() then
|
||||
if Proc.b3Box:getMax():getZ() > Part.b3Solid:getMax():getZ() - 500 * GEO.EPS_SMALL then
|
||||
if Proc.b3Box:getMax():getZ() > Part.b3Part:getMax():getZ() - 500 * GEO.EPS_SMALL then
|
||||
vtFacesAffected.bTop = true
|
||||
end
|
||||
if Proc.b3Box:getMin():getZ() < Part.b3Solid:getMin():getZ() + 500 * GEO.EPS_SMALL then
|
||||
if Proc.b3Box:getMin():getZ() < Part.b3Part:getMin():getZ() + 500 * GEO.EPS_SMALL then
|
||||
vtFacesAffected.bBottom = true
|
||||
end
|
||||
if Proc.b3Box:getMin():getY() < Part.b3Solid:getMin():getY() + 500 * GEO.EPS_SMALL then
|
||||
if Proc.b3Box:getMin():getY() < Part.b3Part:getMin():getY() + 500 * GEO.EPS_SMALL then
|
||||
vtFacesAffected.bFront = true
|
||||
end
|
||||
if Proc.b3Box:getMax():getY() > Part.b3Solid:getMax():getY() - 500 * GEO.EPS_SMALL then
|
||||
if Proc.b3Box:getMax():getY() > Part.b3Part:getMax():getY() - 500 * GEO.EPS_SMALL then
|
||||
vtFacesAffected.bBack = true
|
||||
end
|
||||
if Proc.b3Box:getMin():getX() < Part.b3Solid:getMin():getX() + 500 * GEO.EPS_SMALL then
|
||||
if Proc.b3Box:getMin():getX() < Part.b3Part:getMin():getX() + 500 * GEO.EPS_SMALL then
|
||||
vtFacesAffected.bLeft = true
|
||||
end
|
||||
if Proc.b3Box:getMax():getX() > Part.b3Solid:getMax():getX() - 500 * GEO.EPS_SMALL then
|
||||
if Proc.b3Box:getMax():getX() > Part.b3Part:getMax():getX() - 500 * GEO.EPS_SMALL then
|
||||
vtFacesAffected.bRight = true
|
||||
end
|
||||
end
|
||||
@@ -319,6 +361,66 @@ function BeamLib.Is3EdgesApprox( Proc, idFace, nAddGrpId)
|
||||
return bResult
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
function BeamLib.GetNzLimDownUp( b3Raw, vtN, vtOrtho)
|
||||
if BeamData.GetNzLimDownUp then
|
||||
return BeamData.GetNzLimDownUp( b3Raw, vtN, vtOrtho)
|
||||
elseif BeamData.C_SIMM then
|
||||
return -0.484
|
||||
elseif BeamData.TURN then
|
||||
return -2
|
||||
else
|
||||
if vtOrtho and vtOrtho:getZ() > 0.35 then
|
||||
-- N_HorAng < 15° or N_HorAng > 55°
|
||||
if vtN and ( abs( vtN:getY()) < 0.259 or abs( vtN:getY()) > 0.819) then
|
||||
return -0.708
|
||||
-- N_HorAng > 50°
|
||||
elseif vtN and abs( vtN:getY()) > 0.766 then
|
||||
return -0.383
|
||||
else
|
||||
return EgtIf( b3Raw:getDimZ() < BeamData.MIN_DIM_HBEAM, -0.609, -0.383)
|
||||
end
|
||||
else
|
||||
-- N_HorAng > 60°
|
||||
if vtN and ( abs( vtN:getY()) > 0.866) then
|
||||
return -0.708
|
||||
else
|
||||
if b3Raw:getDimZ() < 120 then
|
||||
return -0.708
|
||||
elseif b3Raw:getDimZ() < 200 then
|
||||
-- N_HorAng < 15° or N_HorAng > 55°
|
||||
if vtN and ( abs( vtN:getY()) < 0.259 or abs( vtN:getY()) > 0.819) then
|
||||
return -0.5
|
||||
else
|
||||
return -0.383
|
||||
end
|
||||
elseif b3Raw:getDimZ() < 300 then
|
||||
-- N_HorAng < 10°
|
||||
if vtN and ( abs( vtN:getY()) < 0.174) then
|
||||
return -0.5
|
||||
else
|
||||
return -0.259
|
||||
end
|
||||
elseif b3Raw:getDimZ() < BeamData.MIN_DIM_HBEAM then
|
||||
-- N_HorAng < 10°
|
||||
if vtN and ( abs( vtN:getY()) < 0.174) then
|
||||
return -0.342
|
||||
else
|
||||
return -0.259
|
||||
end
|
||||
else
|
||||
-- N_HorAng < 10°
|
||||
if vtN and ( abs( vtN:getY()) < 0.174) then
|
||||
return -0.383
|
||||
else
|
||||
return -0.174
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
-- sovrascrivo i parametri personalizzati salvati su Proc a quelli di default dalla strategia
|
||||
-- N.B. : I parametri personalizzati non più presenti tra i default della strategia, verranno ignorati. Quelli extra avranno valore di default
|
||||
@@ -473,5 +575,56 @@ function BeamLib.TableCopyDeep( OriginalTable)
|
||||
return CopiedTable
|
||||
end
|
||||
|
||||
---------------------------------------------------------------------
|
||||
-- Merge sorting - algoritmo di sorting stabile, ossia che mantiene l'ordine relativo se gli elementi sono equivalenti
|
||||
-- TODO vedere come riordinare (tutto in tabella MergeSort??)
|
||||
-- TODO libreria Sorting??
|
||||
do
|
||||
-- unisce due liste ordinate
|
||||
local function MergeHalves(Left, Right, Compare)
|
||||
local result = {}
|
||||
local i, j = 1, 1
|
||||
|
||||
while i <= #Left and j <= #Right do
|
||||
if Compare( Left[i], Right[j]) then
|
||||
table.insert( result, Left[i])
|
||||
i = i + 1
|
||||
else
|
||||
table.insert( result, Right[j])
|
||||
j = j + 1
|
||||
end
|
||||
end
|
||||
|
||||
-- Append degli elementi rimanenti a sinistra o destra
|
||||
while i <= #Left do
|
||||
table.insert( result, Left[i])
|
||||
i = i + 1
|
||||
end
|
||||
while j <= #Right do
|
||||
table.insert( result, Right[j])
|
||||
j = j + 1
|
||||
end
|
||||
|
||||
return result
|
||||
end
|
||||
|
||||
-- Merge sort
|
||||
local function MergeSort( List, Compare)
|
||||
if #List <= 1 then
|
||||
return List
|
||||
end
|
||||
|
||||
local mid = floor( #List / 2)
|
||||
local Left = MergeSort( { table.unpack( List, 1, mid)}, Compare)
|
||||
local Right = MergeSort( { table.unpack( List, mid + 1)}, Compare)
|
||||
|
||||
return MergeHalves( Left, Right, Compare)
|
||||
end
|
||||
|
||||
-- chiamata accessibile dall'esterno
|
||||
function BeamLib.StableSort( List, Compare)
|
||||
return MergeSort( List, Compare)
|
||||
end
|
||||
end
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
return BeamLib
|
||||
|
||||
@@ -0,0 +1,676 @@
|
||||
-- DiceCut.lua by Egaltech 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( 'BeamData')
|
||||
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- creo i piani paralleli
|
||||
-- GetParallelPlanes: restituisce un vettore con gli indici delle superfici
|
||||
-- nAddGrpId: il layer
|
||||
-- b3BoxToDicing: 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( nAddGrpId, b3BoxToDicing, 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( nAddGrpId, ptC + ( i * dOffset) * vtN, vtN, b3BoxToDicing, 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:
|
||||
-- nAddGrpId: 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( nAddGrpId, 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, nAddGrpId)
|
||||
local Copy2Id = EgtCopySurfTmFacet( TabParallelPlanes[IndexTmP], 0, nAddGrpId)
|
||||
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 = BeamData.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
|
||||
-- b3BoxToDicing: 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, b3BoxToDicing, 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()
|
||||
local dMaxElev = EgtSurfTmFacetElevationInBBox( CutOId, 0, b3BoxToDicing, 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 <= OffsetP + 1.0 and vtN1:getZ() > dNzLimDwnUp then
|
||||
local nAddGrpId = EgtGetParent( Cut1Id)
|
||||
local SurfId = EgtSurfTmBySewing( nAddGrpId, { 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( b3BoxToDicing)
|
||||
local ptMin = b3BoxToDicing:getMin()
|
||||
local ptMax = b3BoxToDicing: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( nAddGrpId, ptC1, vtN1, ptC2, vtN2, b3BoxToDicing, 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( nAddGrpId)
|
||||
local IdSurf2 = EgtSurfTmPlaneInBBox( IdAux, ptC2, vtN2, b3BoxToDicing, 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 '.vtNormal'
|
||||
-- Face2 : table. Contiene tutti i dati della faccia secondaria. Se non esiste, la table è vuota ({}). Se esiste, obbligatori i campi '.ptCenter' e '.vtNormal'
|
||||
-- OptionaParameters : eventuali parametri opzionali
|
||||
---------------------------------------------------------------------------------------------------------------
|
||||
function DiceCut.GetDice( Part, Face1, Face2, OptionalParameters)
|
||||
|
||||
local dMaxDimDice = BeamData.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
|
||||
|
||||
-- recupero gruppo per geometria addizionale
|
||||
local nAddGrpId = BeamLib.GetAddGroup( Part.id)
|
||||
-- se il box non è passato tra i parametri opzionali, faccio i calcoli sul SOLID del Part
|
||||
local b3BoxToDicing = OptionalParameters.b3BoxToDicing or Part.b3Part
|
||||
-- copio dati passati su variabili locali
|
||||
local ptCMainFace, vtNMainFace, ptCSubordinateFace, vtNSubordinateFace, bGetOrtoPlanes
|
||||
if Face1.ptCenter and Face1.vtNormal then
|
||||
ptCMainFace = Face1.ptCenter
|
||||
vtNMainFace = Face1.vtNormal
|
||||
end
|
||||
-- se esiste faccia secondaria non esiste, forzo calcolo piani ortogonali
|
||||
if Face2.ptCenter and Face2.vtNormal then
|
||||
ptCSubordinateFace = Face2.ptCenter
|
||||
vtNSubordinateFace = Face2.vtNormal
|
||||
bGetOrtoPlanes = false
|
||||
else
|
||||
bGetOrtoPlanes = true
|
||||
end
|
||||
-- ricavo dimensione massima cubetti
|
||||
if OptionalParameters.dCustMaxDimDice and OptionalParameters.dCustMaxDimDice < BeamData.MAX_DIM_DICE then
|
||||
dMaxDimDice = abs( OptionalParameters.dCustMaxDimDice)
|
||||
end
|
||||
|
||||
--Ricavo le altezze dei BoundingBox contenente feature e estremi del grezzo
|
||||
local TBoxPoint = CalcolaPuntiEstremiBox( b3BoxToDicing)
|
||||
TBoxPoint = VerificaEstremiGrezzo( ptCMainFace, vtNMainFace, TBoxPoint)
|
||||
if ptCSubordinateFace and vtNSubordinateFace then
|
||||
TBoxPoint = VerificaEstremiGrezzo( ptCSubordinateFace, vtNSubordinateFace, TBoxPoint)
|
||||
end
|
||||
local dElevP = DistanzaMassima( nAddGrpId, ptCMainFace, vtNMainFace, ptCSubordinateFace, vtNSubordinateFace, b3BoxToDicing, TBoxPoint)
|
||||
local dElevO
|
||||
if ptCSubordinateFace and vtNSubordinateFace and not AreOppositeVectorApprox( vtNSubordinateFace, vtNMainFace) then
|
||||
dElevO = DistanzaMassima( nAddGrpId, ptCSubordinateFace, vtNSubordinateFace, ptCMainFace, vtNMainFace, b3BoxToDicing, TBoxPoint)
|
||||
end
|
||||
|
||||
-- inclinazione limite per taglio da sotto
|
||||
local dNzLimDwnUp = BeamLib.GetNzLimDownUp( b3BoxToDicing)
|
||||
|
||||
-- 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 BeamData.DOWN_HEAD and abs( vtNMainFace:getY()) < 0.1 and vtNMainFace:getZ() < 0.7071 and ( not vtNSubordinateFace or abs( vtNSubordinateFace:getY()) < 0.1) and b3BoxToDicing:getDimZ() < BeamData.MIN_DIM_HBEAM then
|
||||
OffsetO = OptionalParameters.dOrthoMaxDim or BeamData.MAX_DIM_HTCUT
|
||||
end
|
||||
|
||||
-- aggiungo piccolo extra agli offset
|
||||
OffsetP = OffsetP + 10 * GEO.EPS_SMALL
|
||||
OffsetO = OffsetO + 10 * GEO.EPS_SMALL
|
||||
|
||||
-- se piani non ortogonali, diminuisco la distanza di offset opportunamente
|
||||
local originalOffsetP = OffsetP
|
||||
if not bGetOrtoPlanes then
|
||||
local dCoeff = ( vtNMainFace ^ vtNSubordinateFace):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( nAddGrpId, b3BoxToDicing, ptCMainFace, vtNMainFace, 0, OffsetP, StepP, 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( nAddGrpId, b3BoxToDicing, ptCSubordinateFace, vtNSubordinateFace, 0, OffsetO, StepO, Color3d( GREEN(), 60), dTolerance, false, ptCMainFace, vtNMainFace)
|
||||
for i = #TabFromIn, 1, -1 do
|
||||
table.insert( TabellaTmSurfOrto, TabFromIn[i])
|
||||
end
|
||||
local TabellaOrderParallelCut = GetOrderedCutTable( nAddGrpId, TabellaTmSurfP, TabellaTmSurfOrto) -- Ottiene la tabella dei tagli paralleli ordinati
|
||||
local TabellaOrderOrtoCut = GetOrderedCutTable( nAddGrpId, 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 b3BoxToDicing: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 OptionalParameters.bHeadFromBottom 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( nAddGrpId, b3BoxToDicing, ptCStart, vtO, CopyPlane, -OffsetRel, StepO, Color3d( GREEN(), 60),
|
||||
dTolerance, false, ptCInner, vtNInner, ptCOuter, vtNOuter)
|
||||
if CopyPlane == 0 then
|
||||
CopyPlane = 1
|
||||
end
|
||||
local TabLeft = GetParallelPlanes( nAddGrpId, b3BoxToDicing, 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( nAddGrpId, {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, b3BoxToDicing, 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 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 b3BoxToDicing = EgtGetBBoxGlob( nRawPart, GDB_BB.STANDARD )
|
||||
local b3BoxToDicing = 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, b3BoxToDicing, ptC1, vtN1, true)
|
||||
elseif nFacet == 2 then
|
||||
CutTable = DiceCut.GetDice( nAddGrpId, b3BoxToDicing, ptC1, vtN1, false, TabPlanesFeatures[2].ptC, TabPlanesFeatures[2].vtN)
|
||||
end
|
||||
|
||||
if EgtGetDebugLevel() >= 3 then
|
||||
DiceCut.PrintOrderCut( CutTable)
|
||||
end
|
||||
|
||||
EgtDeselectAll()
|
||||
|
||||
EgtDraw()
|
||||
end
|
||||
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
--DiceCutTest()
|
||||
|
||||
return DiceCut
|
||||
@@ -120,7 +120,7 @@ function FaceData.GetFacesInfo( Proc, Part)
|
||||
-- frame OCS faccia
|
||||
Faces[i].vtFrameHV = Frame3d( Faces[i].ptCenter, Faces[i].vtN)
|
||||
-- elevazione calcolata rispetto al box della parte
|
||||
Faces[i].dElevation = EgtSurfTmFacetElevationInBBox( Proc.id, i - 1, Part.b3Solid, true, GDB_ID.ROOT)
|
||||
Faces[i].dElevation = EgtSurfTmFacetElevationInBBox( Proc.id, i - 1, Part.b3Part, true, GDB_ID.ROOT)
|
||||
-- TODO qui sarebbe meglio l'area vera e non quella del rettangolo minimo
|
||||
local _, dLongEdgeDimension, dShortEdgeDimension = EgtSurfTmFacetMinAreaRectangle( Proc.id, i - 1, GDB_ID.ROOT)
|
||||
Faces[i].dArea = dShortEdgeDimension * dLongEdgeDimension
|
||||
@@ -180,7 +180,7 @@ local function GetTunnelFaces( Proc, Part)
|
||||
end
|
||||
|
||||
-- faccia centrale
|
||||
local nMiddleTmId = EgtSurfTmPlaneInBBox( nAddGrpId, ptTunnelCenter, vtTunnelDirection, Part.b3Solid, GDB_ID.ROOT)
|
||||
local nMiddleTmId = EgtSurfTmPlaneInBBox( nAddGrpId, ptTunnelCenter, vtTunnelDirection, Part.b3Part, GDB_ID.ROOT)
|
||||
-- TODO se non si riesce a costruire la faccia bisogna dare errore o semplicemente non ritornarla??
|
||||
for i = 1, Proc.nFct do
|
||||
EgtCutSurfTmPlane( nMiddleTmId, Proc.Faces[i].ptCenter, -Proc.Faces[i].vtN, false, GDB_ID.ROOT)
|
||||
@@ -265,7 +265,7 @@ local function GetBottomFaces( Proc)
|
||||
CurrentEdge.idAdjacentFace = BottomFaces[1].Edges[i].Adj
|
||||
CurrentEdge.vtToolDirection = Vector3d( BottomFaces[1].Edges[i].Norm)
|
||||
CurrentEdge.dLength = BottomFaces[1].Edges[i].Len
|
||||
CurrentEdge.dLengthOnX = CurrentEdge.dLength * CurrentEdge.vtToolDirection:getY()
|
||||
CurrentEdge.dLengthOnX = abs( CurrentEdge.dLength * CurrentEdge.vtToolDirection:getY())
|
||||
CurrentEdge.dElevation = BottomFaces[1].Edges[i].Elev
|
||||
CurrentEdge.bIsOpen = BottomFaces[1].Edges[i].Open
|
||||
CurrentEdge.bIsStartOpen = BottomFaces[1].Edges[nPreviousEdgeIndex].Open
|
||||
@@ -351,7 +351,7 @@ local function GetLongFaces( Proc, MainFaces)
|
||||
CurrentEdge.idAdjacentFace = LongFaces[i].Edges[j].Adj
|
||||
CurrentEdge.vtToolDirection = Vector3d( LongFaces[i].Edges[j].Norm)
|
||||
CurrentEdge.dLength = LongFaces[i].Edges[j].Len
|
||||
CurrentEdge.dLengthOnX = CurrentEdge.dLength * CurrentEdge.vtToolDirection:getY()
|
||||
CurrentEdge.dLengthOnX = abs( CurrentEdge.dLength * CurrentEdge.vtToolDirection:getY())
|
||||
CurrentEdge.dElevation = LongFaces[i].Edges[j].Elev
|
||||
CurrentEdge.bIsOpen = LongFaces[i].Edges[j].Open
|
||||
CurrentEdge.bIsStartOpen = LongFaces[i].Edges[nPreviousEdgeIndex].Open
|
||||
@@ -438,7 +438,7 @@ local function GetSideFaces( Proc, MainFaces)
|
||||
CurrentEdge.idAdjacentFace = SideFaces[i].Edges[j].Adj
|
||||
CurrentEdge.vtToolDirection = Vector3d( SideFaces[i].Edges[j].Norm)
|
||||
CurrentEdge.dLength = SideFaces[i].Edges[j].Len
|
||||
CurrentEdge.dLengthOnX = CurrentEdge.dLength * CurrentEdge.vtToolDirection:getY()
|
||||
CurrentEdge.dLengthOnX = abs( CurrentEdge.dLength * CurrentEdge.vtToolDirection:getY())
|
||||
CurrentEdge.dElevation = SideFaces[i].Edges[j].Elev
|
||||
CurrentEdge.bIsOpen = SideFaces[i].Edges[j].Open
|
||||
CurrentEdge.bIsStartOpen = SideFaces[i].Edges[nPreviousEdgeIndex].Open
|
||||
|
||||
+19
-21
@@ -22,7 +22,7 @@ function FeatureLib.NeedTopologyFeature( Proc)
|
||||
return true
|
||||
elseif ID.IsHeadCut( Proc) then
|
||||
return true
|
||||
elseif ID.IsSplitCut( Proc) then
|
||||
elseif ID.IsTailCut( Proc) then
|
||||
return true
|
||||
elseif ID.IsDoubleCut( Proc) then
|
||||
return true
|
||||
@@ -98,14 +98,12 @@ end
|
||||
|
||||
---------------------------------------------------------------------
|
||||
-- restituisce true se almeno una delle dimensioni della feature è maggiore o uguale ad una delle dimensioni principali del pezzo (tolleranza 1 mm)
|
||||
local function IsAnyDimensionLongAsPart( Proc)
|
||||
local function IsAnyDimensionLongAsPart( Proc, Part)
|
||||
local bResult = false
|
||||
local nBoxSolidId = EgtGetFirstNameInGroup( Proc.idPart or GDB_ID.NULL, 'Box')
|
||||
local b3Solid = EgtGetBBoxGlob( nBoxSolidId, GDB_BB.STANDARD)
|
||||
|
||||
if Proc.b3Box:getDimX() > b3Solid:getDimX() - 1000 * GEO.EPS_SMALL or
|
||||
Proc.b3Box:getDimY() > b3Solid:getDimY() - 1000 * GEO.EPS_SMALL or
|
||||
Proc.b3Box:getDimZ() > b3Solid:getDimZ() - 1000 * GEO.EPS_SMALL then
|
||||
if Proc.b3Box:getDimX() > Part.b3Part:getDimX() - 1000 * GEO.EPS_SMALL or
|
||||
Proc.b3Box:getDimY() > Part.b3Part:getDimY() - 1000 * GEO.EPS_SMALL or
|
||||
Proc.b3Box:getDimZ() > Part.b3Part:getDimZ() - 1000 * GEO.EPS_SMALL then
|
||||
bResult = true
|
||||
end
|
||||
|
||||
@@ -141,7 +139,7 @@ function FeatureLib.ClassifyTopology( Proc, Part)
|
||||
|
||||
local bIsFeatureCuttingEntireSection = IsFeatureCuttingEntireSection( Proc.b3Box, Part)
|
||||
local bIsFeatureCuttingEntireLength = IsFeatureCuttingEntireLength( Proc.b3Box, Part)
|
||||
local bIsAnyDimensionLongAsPart = IsAnyDimensionLongAsPart( Proc)
|
||||
local bIsAnyDimensionLongAsPart = IsAnyDimensionLongAsPart( Proc, Part)
|
||||
local vAdj = Proc.AdjacencyMatrix
|
||||
local bAllAnglesConcave, bAllRightAngles = AreAllAnglesConcaveOrRight( vAdj)
|
||||
local vTriangularFaces = FaceData.GetTriangularFaces( Proc)
|
||||
@@ -305,13 +303,13 @@ function FeatureLib.MachiningNeedsSplitting( dMachiningLengthOnX, Part, Optional
|
||||
local dMaxSegmentLength = OptionalParameters.dMaxSegmentLength or BeamData.LONGCUT_MAXLEN
|
||||
|
||||
bMachiningNeedsSplitting = ( dMachiningLengthOnX > dMaxSegmentLength + 10 * GEO.EPS_SMALL)
|
||||
or ( dMachiningLengthOnX > 0.7 * Part.b3Solid:getDimX() + 10 * GEO.EPS_SMALL)
|
||||
or ( dMachiningLengthOnX > 0.7 * Part.b3Part:getDimX() + 10 * GEO.EPS_SMALL)
|
||||
|
||||
return bMachiningNeedsSplitting
|
||||
end
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
function FeatureLib.GetFeatureSplittingPoints( Proc, Part, OptionalParameters)
|
||||
local vFeatureSplittingPoints = {}
|
||||
local FeatureSplittingPoints = {}
|
||||
local bFeatureStartsOnEdgeLeft = false
|
||||
local bFeatureStartsOnEdgeRight = false
|
||||
local dSplitXLeft = Proc.b3Box:getMin():getX()
|
||||
@@ -333,10 +331,10 @@ function FeatureLib.GetFeatureSplittingPoints( Proc, Part, OptionalParameters)
|
||||
end
|
||||
|
||||
-- verifica se necessari spezzoni differenti sugli estremi
|
||||
if Proc.b3Box:getMin():getX() < Part.b3Solid:getMin():getX() + dMaxSegmentLengthOnEdges - 10 * GEO.EPS_SMALL then
|
||||
if Proc.b3Box:getMin():getX() < Part.b3Part:getMin():getX() + dMaxSegmentLengthOnEdges - 10 * GEO.EPS_SMALL then
|
||||
bFeatureStartsOnEdgeLeft = true
|
||||
end
|
||||
if Proc.b3Box:getMax():getX() > Part.b3Solid:getMax():getX() - dMaxSegmentLengthOnEdges + 10 * GEO.EPS_SMALL then
|
||||
if Proc.b3Box:getMax():getX() > Part.b3Part:getMax():getX() - dMaxSegmentLengthOnEdges + 10 * GEO.EPS_SMALL then
|
||||
bFeatureStartsOnEdgeRight = true
|
||||
end
|
||||
|
||||
@@ -345,13 +343,13 @@ function FeatureLib.GetFeatureSplittingPoints( Proc, Part, OptionalParameters)
|
||||
if bFeatureStartsOnEdgeLeft then
|
||||
-- decido punto spezzatura verso la coda
|
||||
if Proc.b3Box:getDimX() > dMaxSegmentLengthOnEdges * 2 then
|
||||
dSplitXLeft = max( Part.b3Solid:getMin():getX() + dMaxSegmentLengthOnEdges, Proc.b3Box:getMin():getX() + dMinSegmentLength)
|
||||
dSplitXLeft = max( Part.b3Part:getMin():getX() + dMaxSegmentLengthOnEdges, Proc.b3Box:getMin():getX() + dMinSegmentLength)
|
||||
else
|
||||
-- se pezzo abbastanza piccolo, spezzo in mezzo al 'pezzo + grezzo restante'
|
||||
if Part.dRestLength + Part.b3Solid:getDimX() < BeamData.dMinRaw * 1.5 then
|
||||
dSplitXLeft = Part.b3Solid:getMax():getX() - ( ( Part.dRestLength + Part.b3Solid:getDimX()) / 2)
|
||||
if Part.dRestLength + Part.b3Part:getDimX() < BeamData.dMinRaw * 1.5 then
|
||||
dSplitXLeft = Part.b3Part:getMax():getX() - ( ( Part.dRestLength + Part.b3Part:getDimX()) / 2)
|
||||
else
|
||||
dSplitXLeft = max( Proc.b3Box:getMin():getX() + ( BeamData.dMinRaw)/2 + 150, Part.b3Solid:getMax():getX() - dMaxSegmentLengthOnEdges)
|
||||
dSplitXLeft = max( Proc.b3Box:getMin():getX() + ( BeamData.dMinRaw)/2 + 150, Part.b3Part:getMax():getX() - dMaxSegmentLengthOnEdges)
|
||||
end
|
||||
end
|
||||
dFeatureCentralLength = abs( dSplitXRight - dSplitXLeft)
|
||||
@@ -361,7 +359,7 @@ function FeatureLib.GetFeatureSplittingPoints( Proc, Part, OptionalParameters)
|
||||
-- calcolo punto estremo destro
|
||||
local ptSplitXRight
|
||||
if bFeatureStartsOnEdgeRight then
|
||||
dSplitXRight = min( ( Proc.b3Box:getMax():getX() - dMinSegmentLength), Part.b3Solid:getMax():getX() - dMaxSegmentLengthOnEdges)
|
||||
dSplitXRight = min( ( Proc.b3Box:getMax():getX() - dMinSegmentLength), Part.b3Part:getMax():getX() - dMaxSegmentLengthOnEdges)
|
||||
if dSplitXRight - dSplitXLeft < 500 * GEO.EPS_SMALL then
|
||||
dSplitXRight = dSplitXLeft - dToolOverlapBetweenSegments
|
||||
dFeatureCentralLength = 0
|
||||
@@ -373,7 +371,7 @@ function FeatureLib.GetFeatureSplittingPoints( Proc, Part, OptionalParameters)
|
||||
|
||||
-- aggiungo eventuale punto estremo destro
|
||||
if bFeatureStartsOnEdgeRight then
|
||||
table.insert( vFeatureSplittingPoints, ptSplitXRight)
|
||||
table.insert( FeatureSplittingPoints, ptSplitXRight)
|
||||
end
|
||||
|
||||
-- aggiungo punti centrali della feature
|
||||
@@ -384,16 +382,16 @@ function FeatureLib.GetFeatureSplittingPoints( Proc, Part, OptionalParameters)
|
||||
local ptOn
|
||||
local dCurrentPointX = dSplitXRight - i * dSplitPartsLen
|
||||
ptOn = Point3d( dCurrentPointX, 0, 0)
|
||||
table.insert( vFeatureSplittingPoints, ptOn)
|
||||
table.insert( FeatureSplittingPoints, ptOn)
|
||||
end
|
||||
end
|
||||
|
||||
-- aggiungo eventuale punto estemo sinistro
|
||||
if bFeatureStartsOnEdgeLeft then
|
||||
table.insert( vFeatureSplittingPoints, ptSplitXLeft)
|
||||
table.insert( FeatureSplittingPoints, ptSplitXLeft)
|
||||
end
|
||||
|
||||
return vFeatureSplittingPoints
|
||||
return FeatureSplittingPoints
|
||||
end
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -13,8 +13,8 @@ function Identity.IsHeadCut( Proc)
|
||||
return ( Proc.nGrp == 1 and Proc.nPrc == 340)
|
||||
end
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Split Cut
|
||||
function Identity.IsSplitCut( Proc)
|
||||
-- Feature : Tail Cut
|
||||
function Identity.IsTailCut( Proc)
|
||||
return ( Proc.nGrp == 2 and Proc.nPrc == 350)
|
||||
end
|
||||
|
||||
|
||||
+239
-19
@@ -105,9 +105,9 @@ function MachiningLib.GetMachiningSteps( dMachiningDepth, dStep)
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
function MachiningLib.GetSplitMachinings( Machinings, vSplittingPoints, Part )
|
||||
function MachiningLib.GetSplitMachinings( Machinings, SplittingPoints, Part )
|
||||
for i = #Machinings, 1, -1 do
|
||||
local nParts = #vSplittingPoints + 1
|
||||
local nParts = #SplittingPoints + 1
|
||||
local dEdgeMaxX = Machinings[i].ptEdge1:getX()
|
||||
local dEdgeMinX = Machinings[i].ptEdge2:getX()
|
||||
if Machinings[i].ptEdge1:getX() < Machinings[i].ptEdge2:getX() - 10 * GEO.EPS_SMALL then
|
||||
@@ -122,10 +122,10 @@ function MachiningLib.GetSplitMachinings( Machinings, vSplittingPoints, Part )
|
||||
for j = 1, nParts do
|
||||
-- check ultimo segmento della lavorazione (NON della feature)
|
||||
local bIsLastSegment = ( nParts == 1)
|
||||
or ( ( ( j ~= 1) and vSplittingPoints[j - 1]:getX() > dEdgeMinX + 10 * GEO.EPS_SMALL)
|
||||
and ( j == nParts or vSplittingPoints[j]:getX() < dEdgeMinX + 10 * GEO.EPS_SMALL))
|
||||
or ( ( ( j ~= 1) and SplittingPoints[j - 1]:getX() > dEdgeMinX + 10 * GEO.EPS_SMALL)
|
||||
and ( j == nParts or SplittingPoints[j]:getX() < dEdgeMinX + 10 * GEO.EPS_SMALL))
|
||||
-- se non è l'ultimo segmento della lavorazione, il punto di spezzatura deve essere all'interno del lato che si sta lavorando
|
||||
if ( j ~= nParts and ( vSplittingPoints[j]:getX() > dEdgeMinX + 10 * GEO.EPS_SMALL and vSplittingPoints[j]:getX() < dEdgeMaxX - 10 * GEO.EPS_SMALL))
|
||||
if ( j ~= nParts and ( SplittingPoints[j]:getX() > dEdgeMinX + 10 * GEO.EPS_SMALL and SplittingPoints[j]:getX() < dEdgeMaxX - 10 * GEO.EPS_SMALL))
|
||||
or bIsLastSegment then
|
||||
if j > 1 then
|
||||
nCurrentMachiningIndex = nCurrentMachiningIndex + 1
|
||||
@@ -137,12 +137,15 @@ function MachiningLib.GetSplitMachinings( Machinings, vSplittingPoints, Part )
|
||||
dStartAddLength, dEndAddLength = dEndAddLength, dStartAddLength
|
||||
end
|
||||
if j == 1 then
|
||||
dEndAddLength = - ( vSplittingPoints[j]:getX() - dEdgeMinX) + BeamData.MILL_OVERLAP
|
||||
dEndAddLength = - ( SplittingPoints[j]:getX() - dEdgeMinX) + BeamData.MILL_OVERLAP
|
||||
Machinings[nCurrentMachiningIndex].ptCenter = Point3d( SplittingPoints[j]:getX() + ( dEdgeMaxX - SplittingPoints[j]:getX()) / 2, 0, 0)
|
||||
elseif j == nParts then
|
||||
dStartAddLength = - ( dEdgeMaxX - vSplittingPoints[j - 1]:getX()) + BeamData.MILL_OVERLAP
|
||||
dStartAddLength = - ( dEdgeMaxX - SplittingPoints[j - 1]:getX()) + BeamData.MILL_OVERLAP
|
||||
Machinings[nCurrentMachiningIndex].ptCenter = Point3d( dEdgeMinX + ( SplittingPoints[j - 1]:getX() - dEdgeMinX) / 2, 0, 0)
|
||||
else
|
||||
dStartAddLength = - ( dEdgeMaxX - vSplittingPoints[j - 1]:getX()) + BeamData.MILL_OVERLAP
|
||||
dEndAddLength = - ( vSplittingPoints[j]:getX() - dEdgeMinX) + BeamData.MILL_OVERLAP
|
||||
dStartAddLength = - ( dEdgeMaxX - SplittingPoints[j - 1]:getX()) + BeamData.MILL_OVERLAP
|
||||
dEndAddLength = - ( SplittingPoints[j]:getX() - dEdgeMinX) + BeamData.MILL_OVERLAP
|
||||
Machinings[nCurrentMachiningIndex].ptCenter = Point3d( SplittingPoints[j]:getX() + ( SplittingPoints[j - 1]:getX() - SplittingPoints[j]:getX()) / 2, 0, 0)
|
||||
end
|
||||
if MachiningLib.StartsLeftSide( Machinings[nCurrentMachiningIndex]) then
|
||||
dStartAddLength, dEndAddLength = dEndAddLength, dStartAddLength
|
||||
@@ -152,9 +155,9 @@ function MachiningLib.GetSplitMachinings( Machinings, vSplittingPoints, Part )
|
||||
Machinings[nCurrentMachiningIndex].LeadOut.dEndAddLength = dEndAddLength
|
||||
end
|
||||
if not bIsLastSegment then
|
||||
Machinings[nCurrentMachiningIndex].bMoveAfterSplitcut = false
|
||||
Machinings[nCurrentMachiningIndex].sStage = ''
|
||||
end
|
||||
Machinings[nCurrentMachiningIndex].nSegment = j
|
||||
Machinings[nCurrentMachiningIndex].nFeatureSegment = j
|
||||
end
|
||||
-- anche le lavorazioni non splittate necessitano del segmento assegnato
|
||||
else
|
||||
@@ -167,12 +170,14 @@ function MachiningLib.GetSplitMachinings( Machinings, vSplittingPoints, Part )
|
||||
local dNextSplitX = dEdgeMinX
|
||||
local dPreviousSplitX = dEdgeMaxX
|
||||
if j ~= 1 then
|
||||
dPreviousSplitX = vSplittingPoints[j - 1]:getX()
|
||||
elseif j ~= nParts then
|
||||
dNextSplitX = vSplittingPoints[j]:getX()
|
||||
dPreviousSplitX = SplittingPoints[j - 1]:getX()
|
||||
end
|
||||
if ( dEdgeMinX - dLeftAddLength) > dNextSplitX - 10 * GEO.EPS_SMALL and ( dEdgeMaxX + dRightAddLength) < dPreviousSplitX + 10 * GEO.EPS_SMALL then
|
||||
Machinings[i].nSegment = j
|
||||
if j ~= nParts then
|
||||
dNextSplitX = SplittingPoints[j]:getX()
|
||||
end
|
||||
if ( dEdgeMinX - dLeftAddLength) > dNextSplitX - 10 * GEO.EPS_SMALL and ( dEdgeMinX - dLeftAddLength) < dPreviousSplitX + 10 * GEO.EPS_SMALL then
|
||||
Machinings[i].nFeatureSegment = j
|
||||
Machinings[i].ptCenter = Point3d( dNextSplitX + ( dPreviousSplitX - dNextSplitX) / 2, 0, 0)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -254,7 +259,7 @@ function MachiningLib.FindMill( Proc, ToolSearchParameters)
|
||||
-- se hanno stesso montaggio
|
||||
elseif TOOLS[i].SetupInfo.bToolOnAggregate == TOOLS[nBestToolIndex].SetupInfo.bToolOnAggregate then
|
||||
-- scelgo utensile con indice di bontà utensile calcolato come: lunghezza / massimo materiale / diametro
|
||||
if ( TOOLS[i].dLength / TOOLS[i].dMaxMaterial) / TOOLS[i].dDiameter < ( TOOLS[nBestToolIndex].dLength / TOOLS[nBestToolIndex].dMaxMaterial) / TOOLS[nBestToolIndex].dDiameter then
|
||||
if TOOLS[i].dPerformanceIndex > TOOLS[nBestToolIndex].dPerformanceIndex then
|
||||
nBestToolIndex = i
|
||||
dBestToolResidualDepth = dCurrentResidualDepth
|
||||
end
|
||||
@@ -391,7 +396,7 @@ function MachiningLib.FindChainSaw( Proc, ToolSearchParameters)
|
||||
-- se entrambi completi
|
||||
if dBestToolResidualDepth <= 0 and dCurrentResidualDepth <= 0 then
|
||||
-- scelgo utensile con rapporto lunghezza / diametro minore
|
||||
if ( TOOLS[i].dLength / pow( TOOLS[i].dDiameter, 1.5)) < ( TOOLS[nBestToolIndex].dLength / pow( TOOLS[nBestToolIndex].dDiameter, 1.5)) then
|
||||
if TOOLS[i].dPerformanceIndex > TOOLS[nBestToolIndex].dPerformanceIndex then
|
||||
nBestToolIndex = i
|
||||
dBestToolResidualDepth = dCurrentResidualDepth
|
||||
end
|
||||
@@ -642,7 +647,7 @@ function MachiningLib.AddOperations( vProc, Part, sRotation)
|
||||
|
||||
-- TODO è giusto inserire queste info alla fine della lavorazione? oppure conviene creare un record in MACHININGS apposito per la disposizione?
|
||||
-- se era taglio di separazione, aggiungo nuova fase
|
||||
if MACHININGS[i].AuxiliaryData.bAddNewPhase then
|
||||
if MACHININGS[i].AuxiliaryData.bIsSplitOrCut then
|
||||
bSplitExecuted = true
|
||||
BeamLib.AddPhaseWithRawParts( MACHININGS[i].Proc.idRaw, BeamData.ptOriXR, BeamData.dPosXR, BeamData.RAW_OFFSET)
|
||||
-- se grezzo successivo senza pezzi e finale, va tolto
|
||||
@@ -711,5 +716,220 @@ function MachiningLib.GetToolMRR( Parameters)
|
||||
return dMRR / pow( 10, 6)
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
function MachiningLib.PrepareMachiningsForSorting( Part)
|
||||
local nFeatureInternalIndex = 1
|
||||
for i = 1, #MACHININGS do
|
||||
local MachiningCurrent = MACHININGS[i].Machining
|
||||
local ProcCurrent = MACHININGS[i].Proc
|
||||
if not MachiningCurrent.ptCenter then
|
||||
MachiningCurrent.ptCenter = Point3d( ProcCurrent.b3Box:getCenter():getX(), 0, 0)
|
||||
end
|
||||
|
||||
-- conversione campo sStage in nStage, numerico e ordinabile
|
||||
if not MachiningCurrent.sStage or MachiningCurrent.sStage == '' then
|
||||
MachiningCurrent.sStage = 'Middle'
|
||||
end
|
||||
if MachiningCurrent.sStage == 'Head' then
|
||||
MachiningCurrent.nStage = 1
|
||||
elseif MachiningCurrent.sStage == 'Tail' then
|
||||
MachiningCurrent.nStage = 3
|
||||
elseif MachiningCurrent.sStage == 'AfterTail' then
|
||||
MachiningCurrent.nStage = 4
|
||||
else
|
||||
MachiningCurrent.nStage = 2
|
||||
end
|
||||
|
||||
if i > 1 then
|
||||
local MachiningPrevious = MACHININGS[i - 1].Machining
|
||||
local ProcPrevious = MACHININGS[i - 1].Proc
|
||||
if ProcCurrent.id == ProcPrevious.id then
|
||||
-- nStage devono essere sempre uguali o crescenti nella stessa feature
|
||||
if MachiningCurrent.nStage < MachiningPrevious.nStage then
|
||||
MachiningCurrent.nStage = MachiningPrevious.nStage
|
||||
end
|
||||
-- assegnazione indice interno alla feature
|
||||
nFeatureInternalIndex = nFeatureInternalIndex + 1
|
||||
else
|
||||
nFeatureInternalIndex = 1
|
||||
end
|
||||
end
|
||||
MachiningCurrent.nFeatureInternalIndex = nFeatureInternalIndex
|
||||
|
||||
-- se fase di lavoro standard, assegnazione dello spezzone
|
||||
if MachiningCurrent.nStage == 2 then
|
||||
local nParts = #Part.SplittingPoints + 1
|
||||
local dPartMinX = Part.b3Part:getMin():getX()
|
||||
local dPartMaxX = Part.b3Part:getMax():getX()
|
||||
for j = 1, nParts do
|
||||
local dNextSplitX = dPartMinX
|
||||
local dPreviousSplitX = dPartMaxX
|
||||
if j ~= 1 then
|
||||
dPreviousSplitX = Part.SplittingPoints[j - 1]:getX()
|
||||
elseif j ~= nParts then
|
||||
dNextSplitX = Part.SplittingPoints[j]:getX()
|
||||
end
|
||||
if MachiningCurrent.ptCenter:getX() > dNextSplitX - 10 * GEO.EPS_SMALL and MachiningCurrent.ptCenter:getX() < dPreviousSplitX + 10 * GEO.EPS_SMALL then
|
||||
MachiningCurrent.nPartSegment = j
|
||||
end
|
||||
end
|
||||
else
|
||||
MachiningCurrent.nPartSegment = -1
|
||||
end
|
||||
end
|
||||
|
||||
return MACHININGS
|
||||
end
|
||||
|
||||
-- TODO convertire in tabella in cui si chiamano direttamente i nomi delle funzioni, in modo da poter cambiare l'ordine facilmente
|
||||
-- TODO libreria Sorting??
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
local SortingComparisonRules = {
|
||||
-- ordine interno alla feature
|
||||
function( MachiningA, MachiningB)
|
||||
if MachiningA.Proc.id == MachiningB.Proc.id then
|
||||
if MachiningA.Machining.nFeatureInternalIndex < MachiningB.Machining.nFeatureInternalIndex then
|
||||
return 1
|
||||
elseif MachiningA.Machining.nFeatureInternalIndex > MachiningB.Machining.nFeatureInternalIndex then
|
||||
return -1
|
||||
end
|
||||
end
|
||||
|
||||
return 0
|
||||
end,
|
||||
|
||||
-- dipendenze solo spostamento stage 2->4
|
||||
-- TODO da fare
|
||||
|
||||
-- stage
|
||||
function( MachiningA, MachiningB)
|
||||
if MachiningA.Machining.nStage < MachiningB.Machining.nStage then
|
||||
return 1
|
||||
elseif MachiningA.Machining.nStage > MachiningB.Machining.nStage then
|
||||
return -1
|
||||
else
|
||||
return 0
|
||||
end
|
||||
end,
|
||||
|
||||
-- dipendenze
|
||||
-- TODO da fare
|
||||
|
||||
-- segment
|
||||
function ( MachiningA, MachiningB)
|
||||
if MachiningA.Machining.nPartSegment < MachiningB.Machining.nPartSegment then
|
||||
return 1
|
||||
elseif MachiningA.Machining.nPartSegment > MachiningB.Machining.nPartSegment then
|
||||
return -1
|
||||
else
|
||||
return 0
|
||||
end
|
||||
end,
|
||||
|
||||
-- testa
|
||||
-- TODO da fare
|
||||
|
||||
-- famiglia utensile
|
||||
function ( MachiningA, MachiningB)
|
||||
-- TODO tirare fuori da qua??
|
||||
local ToolFamilyOrder = {
|
||||
SAWBLADE = 1,
|
||||
DRILLBIT = 2,
|
||||
MILL = 3,
|
||||
MORTISE = 4
|
||||
}
|
||||
local nToolFamilyOrderA = ToolFamilyOrder[ TOOLS[ MachiningA.Machining.nToolIndex].sFamily]
|
||||
local nToolFamilyOrderB = ToolFamilyOrder[ TOOLS[ MachiningB.Machining.nToolIndex].sFamily]
|
||||
|
||||
if nToolFamilyOrderA < nToolFamilyOrderB then
|
||||
return 1
|
||||
elseif nToolFamilyOrderA > nToolFamilyOrderB then
|
||||
return -1
|
||||
else
|
||||
return 0
|
||||
end
|
||||
end,
|
||||
|
||||
-- performance utensile
|
||||
function( MachiningA, MachiningB)
|
||||
local dToolPerformanceIndexA = TOOLS[MachiningA.Machining.nToolIndex].dPerformanceIndex
|
||||
local dToolPerformanceIndexB = TOOLS[MachiningB.Machining.nToolIndex].dPerformanceIndex
|
||||
|
||||
if dToolPerformanceIndexA > dToolPerformanceIndexB then
|
||||
return 1
|
||||
elseif dToolPerformanceIndexA < dToolPerformanceIndexB then
|
||||
return -1
|
||||
else
|
||||
return 0
|
||||
end
|
||||
end,
|
||||
|
||||
-- probabilmente arrivati qui significa che gli utensili A e B sono gli stessi
|
||||
-- se così non fosse e tutte le caratteristiche sopra sono uguali, ordine alfabetico
|
||||
function( MachiningA, MachiningB)
|
||||
local sToolNameA = TOOLS[MachiningA.Machining.nToolIndex].sName
|
||||
local sToolNameB = TOOLS[MachiningB.Machining.nToolIndex].sName
|
||||
|
||||
if sToolNameA < sToolNameB then
|
||||
return 1
|
||||
elseif sToolNameA > sToolNameB then
|
||||
return -1
|
||||
else
|
||||
return 0
|
||||
end
|
||||
end,
|
||||
|
||||
-- lato di lavoro
|
||||
-- TODO questo, insieme all'ordinamento X, andrà sostituito dallo shortest path pesato sulla quantità di rotazione della testa
|
||||
function( MachiningA, MachiningB)
|
||||
if MachiningA.Machining.vtToolDirection:getY() < 10 * GEO.EPS_SMALL and MachiningB.Machining.vtToolDirection:getY() >= 10 * GEO.EPS_SMALL then
|
||||
return 1
|
||||
elseif MachiningA.Machining.vtToolDirection:getY() >= 10 * GEO.EPS_SMALL and MachiningB.Machining.vtToolDirection:getY() < 10 * GEO.EPS_SMALL then
|
||||
return -1
|
||||
else
|
||||
return 0
|
||||
end
|
||||
end,
|
||||
|
||||
-- ordinamento X
|
||||
-- TODO questo andrà sostituito dallo shortest path pesato sulla quantità di rotazione della testa
|
||||
function( MachiningA, MachiningB)
|
||||
local bIsMachiningOnFront = MachiningA.Machining.vtToolDirection:getY() < 10 * GEO.EPS_SMALL
|
||||
local nResult = 0
|
||||
|
||||
-- se lavorazione davanti ordine testa->coda
|
||||
if bIsMachiningOnFront then
|
||||
if MachiningA.Machining.ptCenter:getX() > MachiningB.Machining.ptCenter:getX() + 10 * GEO.EPS_SMALL then
|
||||
nResult = 1
|
||||
elseif MachiningA.Machining.ptCenter:getX() < MachiningB.Machining.ptCenter:getX() - 10 * GEO.EPS_SMALL then
|
||||
nResult = -1
|
||||
end
|
||||
-- se lavorazione dietro ordine coda->testa
|
||||
else
|
||||
if MachiningA.Machining.ptCenter:getX() < MachiningB.Machining.ptCenter:getX() - 10 * GEO.EPS_SMALL then
|
||||
nResult = 1
|
||||
elseif MachiningA.Machining.ptCenter:getX() > MachiningB.Machining.ptCenter:getX() + 10 * GEO.EPS_SMALL then
|
||||
nResult = -1
|
||||
end
|
||||
end
|
||||
|
||||
return nResult
|
||||
end
|
||||
}
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
function MachiningLib.CompareMachinings( MachiningA, MachiningB)
|
||||
-- itera le SortingComparisonRules una per volta. Se non vi è alcuna scelta va avanti (result = 0), altrimenti ritorna true/false in base al risultato
|
||||
for i = 1, #SortingComparisonRules do
|
||||
local CompareFunction = SortingComparisonRules[i]
|
||||
local result = CompareFunction( MachiningA, MachiningB)
|
||||
if result ~= 0 then
|
||||
return result > 0
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
return MachiningLib
|
||||
|
||||
@@ -0,0 +1,368 @@
|
||||
-- StrategyLib.lua by Egalware s.r.l. 2024/04/02
|
||||
-- Libreria di supporto a strategie con funzioni comune a strategie diverse.
|
||||
|
||||
-- Tabella per definizione modulo
|
||||
local StrategyLib = {}
|
||||
|
||||
-- Include
|
||||
require( 'EgtBase')
|
||||
|
||||
-- Carico i dati globali
|
||||
local BeamData = require( 'BeamData')
|
||||
local FeatureLib = require( 'FeatureLib')
|
||||
local MachiningLib = require( 'MachiningLib')
|
||||
-- strategie di base
|
||||
local FaceByBlade = require('FACEBYBLADE')
|
||||
|
||||
EgtOutLog( ' StrategyLib started', 1)
|
||||
|
||||
-----------------------------------------------------------------------------------
|
||||
---------------------- FUNZIONI DI SPLIT ------------------------------------------
|
||||
-----------------------------------------------------------------------------------
|
||||
|
||||
StrategyLib.SplitStrategy = {}
|
||||
function StrategyLib.SplitStrategy.Get( Proc, Part, OptionalParameters)
|
||||
local Machining = {}
|
||||
local Result = {}
|
||||
-- sTypeMachining = BladeSideSingle\ BladeSideDouble\ BladeHorizontalSingle\ BladeHorizontalDouble\ ChainSawHorizontal\ ChainSawSideSingle\ ChainSawSideDouble\ ChainSawPlusBlade\ Mill\ None
|
||||
Machining.sTypeMachining = 'None'
|
||||
local Splitting = {}
|
||||
-- imposto parametri di ricerca utensile in base a topologia
|
||||
local ToolSearchParameters = {}
|
||||
ToolSearchParameters.vtToolDirection = Proc.Faces[1].vtN
|
||||
|
||||
-- ===== RICERCA UTENSILE =====
|
||||
-- cerco lama sopra
|
||||
Splitting.bIsApplicable = false
|
||||
ToolSearchParameters.bAllowTopHead = true
|
||||
ToolSearchParameters.bAllowBottomHead = false
|
||||
Splitting.ToolInfo = {}
|
||||
Splitting.ToolInfo = MachiningLib.FindBlade( Proc, ToolSearchParameters)
|
||||
if Splitting.ToolInfo.nToolIndex then
|
||||
Splitting.bIsApplicable = true
|
||||
local ParametersMRR = {}
|
||||
ParametersMRR.nToolIndex = Splitting.ToolInfo.nToolIndex
|
||||
Splitting.dMRR = MachiningLib.GetToolMRR( ParametersMRR)
|
||||
end
|
||||
table.insert( Machining, Splitting)
|
||||
|
||||
-- cerco lama sotto
|
||||
Splitting = {}
|
||||
Splitting.bIsApplicable = false
|
||||
ToolSearchParameters.bAllowTopHead = false
|
||||
ToolSearchParameters.bAllowBottomHead = true
|
||||
Splitting.ToolInfo = {}
|
||||
Splitting.ToolInfo = MachiningLib.FindBlade( Proc, ToolSearchParameters)
|
||||
if Splitting.ToolInfo.nToolIndex then
|
||||
Splitting.bIsApplicable = true
|
||||
local ParametersMRR = {}
|
||||
ParametersMRR.nToolIndex = Splitting.ToolInfo.nToolIndex
|
||||
Splitting.dMRR = MachiningLib.GetToolMRR( ParametersMRR)
|
||||
end
|
||||
table.insert( Machining, Splitting)
|
||||
|
||||
-- cerco motosega
|
||||
Splitting = {}
|
||||
Splitting.bIsApplicable = false
|
||||
table.insert( Machining, Splitting)
|
||||
|
||||
-- cerco fresa
|
||||
Splitting = {}
|
||||
Splitting.bIsApplicable = false
|
||||
table.insert( Machining, Splitting)
|
||||
|
||||
-- ===== SCELTA LAVORAZIONI =====
|
||||
-- forzature da parametri
|
||||
if OptionalParameters.bForceChainSaw then
|
||||
Machining[1].bIsApplicable = false
|
||||
Machining[2].bIsApplicable = false
|
||||
end
|
||||
|
||||
-- setto valori di default. Impossibile che taglio di separazione sia incompleto
|
||||
Result.sStatus = 'Completed'
|
||||
Result.nCompletionIndex = FeatureLib.GetFeatureCompletionIndex( 100)
|
||||
Result.dMRR = 1
|
||||
|
||||
-- correzioni sul massimo materiale lama, considerando ingombri vari
|
||||
local dMaxMatBladeSideSingle
|
||||
local dMaxMatBladeSideDouble
|
||||
local dMaxMatBladeHorizontalSingle
|
||||
local dMaxMatBladeHorizontalDouble
|
||||
if Machining[1].bIsApplicable then
|
||||
local dMaxMat = TOOLS[Machining[1].ToolInfo.nToolIndex].dMaxMaterial
|
||||
local dRadius = TOOLS[Machining[1].ToolInfo.nToolIndex].dDiameter / 2
|
||||
local sHead = TOOLS[Machining[1].ToolInfo.nToolIndex].sHead
|
||||
-- se taglio di fianco disponibile, si controlla il massimo materiale reale. Per pezzi alti, bisogna controllare anche l'ingombro asse Z nelle 4 direzioni.
|
||||
if Part.dHeight < BeamData.MIN_DIM_HBEAM then
|
||||
dMaxMat = min( dMaxMat, BeamData.MAX_DIM_HTCUT)
|
||||
dMaxMatBladeSideSingle = dMaxMat
|
||||
dMaxMatBladeSideDouble = dMaxMat * 2
|
||||
else
|
||||
if BeamData.GetMaxMatReductionBladeCut then
|
||||
dMaxMatBladeSideSingle = min( max( dRadius - BeamData.GetMaxMatReductionBladeCut( sHead, Y_AX()), dRadius - BeamData.GetMaxMatReductionBladeCut( sHead, -Y_AX())),
|
||||
TOOLS[Machining[1].ToolInfo.nToolIndex].dMaxMaterial)
|
||||
dMaxMatBladeSideDouble = dRadius - BeamData.GetMaxMatReductionBladeCut( sHead, Y_AX()) + dRadius - BeamData.GetMaxMatReductionBladeCut( sHead, -Y_AX())
|
||||
else
|
||||
dMaxMatBladeSideSingle = abs( BeamData.MAX_DIM_HTCUT_HBEAM)
|
||||
dMaxMatBladeSideDouble = abs( BeamData.MAX_DIM_HTCUT_HBEAM) * 2
|
||||
end
|
||||
end
|
||||
-- se taglio orizzontale
|
||||
if BeamData.GetMaxMatReductionBladeCut then
|
||||
dMaxMatBladeHorizontalSingle = min( TOOLS[Machining[1].ToolInfo.nToolIndex].dMaxMaterial, dRadius - BeamData.GetMaxMatReductionBladeCut( TOOLS[Machining[1].ToolInfo.nToolIndex].sHead, -Z_AX()))
|
||||
else
|
||||
dMaxMatBladeHorizontalSingle = TOOLS[Machining[1].ToolInfo.nToolIndex].dMaxMaterial
|
||||
end
|
||||
end
|
||||
if Machining[2].bIsApplicable then
|
||||
if BeamData.GetMaxMatReductionBladeCut then
|
||||
local dRadius = TOOLS[Machining[2].ToolInfo.nToolIndex].dDiameter / 2
|
||||
dMaxMatBladeHorizontalDouble = min( TOOLS[Machining[2].ToolInfo.nToolIndex].dMaxMaterial, dRadius - BeamData.GetMaxMatReductionBladeCut( TOOLS[Machining[2].ToolInfo.nToolIndex].sHead, Z_AX()))
|
||||
else
|
||||
dMaxMatBladeHorizontalDouble = TOOLS[Machining[2].ToolInfo.nToolIndex].dMaxMaterial
|
||||
end
|
||||
end
|
||||
|
||||
-- TODO considerare di tagliare con il massimo materiale possibile per non salire troppo in Z (macchine tipo PF), oppure non scendere troppo (tipo Kairos)
|
||||
-- BladeSideSingle (taglio di lama singolo di fianco)
|
||||
if Machining[1].bIsApplicable and ( dMaxMatBladeSideSingle - BeamData.CUT_EXTRA) > Part.dWidth + 10 * GEO.EPS_SMALL then
|
||||
Result.nQuality = FeatureLib.GetFeatureQuality( 'Blade')
|
||||
Machining.sTypeMachining = 'BladeSideSingle'
|
||||
Machining[2].bIsApplicable = false
|
||||
Machining[3].bIsApplicable = false
|
||||
Machining[4].bIsApplicable = false
|
||||
return Machining, Result
|
||||
-- TODO considerare di tagliare con il massimo materiale possibile per non salire troppo in Z (macchine tipo PF), oppure non scendere troppo (tipo Kairos)
|
||||
-- BladeSideDouble (taglio di lama doppio di fianco)
|
||||
elseif Machining[1].bIsApplicable and ( dMaxMatBladeSideDouble - BeamData.CUT_EXTRA) > Part.dWidth + 10 * GEO.EPS_SMALL then
|
||||
Result.nQuality = FeatureLib.GetFeatureQuality( 'Blade')
|
||||
Result.dMRR = Result.dMRR/2
|
||||
Machining.sTypeMachining = 'BladeSideDouble'
|
||||
Machining[2].bIsApplicable = false
|
||||
Machining[3].bIsApplicable = false
|
||||
Machining[4].bIsApplicable = false
|
||||
return Machining, Result
|
||||
-- BladeHorizontalSingle (taglio di lama singolo orizzontale)
|
||||
elseif Machining[1].bIsApplicable and ( dMaxMatBladeHorizontalSingle - BeamData.CUT_EXTRA) > Part.dHeight + 10 * GEO.EPS_SMALL then
|
||||
Result.nQuality = FeatureLib.GetFeatureQuality( 'Blade')
|
||||
Machining.sTypeMachining = 'BladeHorizontalSingle'
|
||||
Machining[2].bIsApplicable = false
|
||||
Machining[3].bIsApplicable = false
|
||||
Machining[4].bIsApplicable = false
|
||||
return Machining, Result
|
||||
-- BladeHorizontalDouble (taglio di lama doppio orizzontale)
|
||||
elseif Machining[1].bIsApplicable and Machining[2].bIsApplicable and
|
||||
( dMaxMatBladeHorizontalSingle + dMaxMatBladeHorizontalDouble - BeamData.CUT_EXTRA) > Part.dHeight + 10 * GEO.EPS_SMALL then
|
||||
Result.nQuality = FeatureLib.GetFeatureQuality( 'Blade')
|
||||
Result.dMRR = Result.dMRR/2
|
||||
Machining.sTypeMachining = 'BladeHorizontalDouble'
|
||||
Machining[1].ToolInfo.dMaxMatBladeFromTop = dMaxMatBladeHorizontalSingle
|
||||
Machining[2].ToolInfo.dMaxMatBladeFromDown = dMaxMatBladeHorizontalDouble
|
||||
Machining[3].bIsApplicable = false
|
||||
Machining[4].bIsApplicable = false
|
||||
return Machining, Result
|
||||
|
||||
-- TODO : casi con motosega da completare
|
||||
-- ChainSawHorizontal (motosega)
|
||||
-- ChainSawSideSingle (motosega)
|
||||
-- ChainSawSideDouble (motosega)
|
||||
-- ChainSawPlusBlade (motosega più lama orizzontale)
|
||||
-- Mill (svuotatura)
|
||||
end
|
||||
|
||||
-- se non ho trovato neanche una lavorazione completa, non posso separare
|
||||
if Machining.sTypeMachining == 'None' then
|
||||
Result.sStatus = 'Not-Applicable'
|
||||
Result.nCompletionIndex = 0
|
||||
Result.dMRR = 0
|
||||
Result.nQuality = 0
|
||||
Result.sInfo = 'Split not possible'
|
||||
end
|
||||
|
||||
return Machining, Result
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
function StrategyLib.SplitStrategy.GetEdgeToMachine( Proc, vtEdge)
|
||||
local Edge
|
||||
for i = 1, #Proc.Faces[1].Edges do
|
||||
if AreSameVectorApprox( Proc.Faces[1].Edges[i].Norm, vtEdge) then
|
||||
Edge = Proc.Faces[1].Edges[i]
|
||||
end
|
||||
end
|
||||
return Edge
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
function StrategyLib.SplitStrategy.CalculateLeadInOut( EdgeToMachine)
|
||||
|
||||
local LeadIn = {}
|
||||
local LeadOut = {}
|
||||
LeadIn.dStartAddLength = 0
|
||||
LeadOut.dEndAddLength = 0
|
||||
LeadIn.nType = MCH_MILL_LI.LINEAR
|
||||
LeadOut.nType = MCH_MILL_LI.LINEAR
|
||||
LeadIn.dTangentDistance = 0
|
||||
LeadOut.dTangentDistance = 0
|
||||
-- elevazione sempre in negativo
|
||||
if EdgeToMachine.Elev < 10 * GEO.EPS_SMALL then
|
||||
LeadIn.dPerpDistance = BeamData.CUT_SIC - EdgeToMachine.Elev
|
||||
LeadOut.dPerpDistance = BeamData.CUT_SIC - EdgeToMachine.Elev
|
||||
else
|
||||
LeadIn.dPerpDistance = BeamData.CUT_SIC
|
||||
LeadOut.dPerpDistance = BeamData.CUT_SIC
|
||||
end
|
||||
LeadIn.dElevation = 0
|
||||
LeadOut.dElevation = 0
|
||||
LeadIn.dCompLength = 0
|
||||
LeadOut.dCompLength = 0
|
||||
LeadIn.dStartAddLength = BeamData.CUT_EXTRA
|
||||
LeadOut.dEndAddLength = BeamData.CUT_EXTRA
|
||||
|
||||
return LeadIn, LeadOut
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------
|
||||
function StrategyLib.SplitStrategy.Execute( Proc, Part, Strategy)
|
||||
local Machinings = {}
|
||||
|
||||
-- applico le lavorazioni
|
||||
--------------------------------------------------------------------------------
|
||||
if Strategy.SplitStrategy.sTypeMachining == 'BladeSideSingle' then
|
||||
local Machining = {}
|
||||
Machining.Splitting = {}
|
||||
Machining.AuxiliaryData = {}
|
||||
local OptionalParameters = {}
|
||||
OptionalParameters.nToolIndex = Strategy.SplitStrategy[1].ToolInfo.nToolIndex
|
||||
OptionalParameters.nFaceuse = MCH_MILL_FU.ORTHO_BACK
|
||||
OptionalParameters.sDepth = 0
|
||||
OptionalParameters.dLongitudinalOffset = Strategy.dOffset or 0
|
||||
OptionalParameters.sUserNotes = EgtIf( Strategy.bSplit, 'Split;', 'Cut;')
|
||||
|
||||
Machining.AuxiliaryData.bIsSplitOrCut = true
|
||||
|
||||
local EdgeToMachine = StrategyLib.SplitStrategy.GetEdgeToMachine( Proc, -Y_AX())
|
||||
-- approccio e retrazione
|
||||
OptionalParameters.LeadIn, OptionalParameters.LeadOut = StrategyLib.SplitStrategy.CalculateLeadInOut( EdgeToMachine)
|
||||
Machining.Splitting = FaceByBlade.Make( Proc, Part, Proc.Faces[1].id, EdgeToMachine, OptionalParameters)
|
||||
table.insert( Machinings, Machining)
|
||||
|
||||
----------------------------------------------------------------------------------
|
||||
elseif Strategy.SplitStrategy.sTypeMachining == 'BladeSideDouble' then
|
||||
local Machining = {}
|
||||
Machining.Splitting = {}
|
||||
Machining.AuxiliaryData = {}
|
||||
local OptionalParameters = {}
|
||||
OptionalParameters.nToolIndex = Strategy.SplitStrategy[1].ToolInfo.nToolIndex
|
||||
-- Taglio lato frontale
|
||||
OptionalParameters.nFaceuse = MCH_MILL_FU.ORTHO_BACK
|
||||
OptionalParameters.sDepth = 0
|
||||
OptionalParameters.dLongitudinalOffset = Strategy.dOffset or 0
|
||||
OptionalParameters.dRadialOffset = ( Part.dWidth - BeamData.CUT_EXTRA) / 2
|
||||
OptionalParameters.sUserNotes = EgtIf( Strategy.bSplit, 'Presplit;', 'Precut;')
|
||||
|
||||
local EdgeToMachine = StrategyLib.SplitStrategy.GetEdgeToMachine( Proc, -Y_AX())
|
||||
-- approccio e retrazione
|
||||
OptionalParameters.LeadIn, OptionalParameters.LeadOut = StrategyLib.SplitStrategy.CalculateLeadInOut( EdgeToMachine)
|
||||
Machining.Splitting = FaceByBlade.Make( Proc, Part, Proc.Faces[1].id, EdgeToMachine, OptionalParameters)
|
||||
table.insert( Machinings, Machining)
|
||||
|
||||
-- Taglio lato dietro
|
||||
Machining = {}
|
||||
Machining.Splitting = {}
|
||||
Machining.AuxiliaryData = {}
|
||||
OptionalParameters = {}
|
||||
OptionalParameters.nToolIndex = Strategy.SplitStrategy[1].ToolInfo.nToolIndex
|
||||
OptionalParameters.nFaceuse = MCH_MILL_FU.ORTHO_FRONT
|
||||
OptionalParameters.sDepth = 0
|
||||
OptionalParameters.dLongitudinalOffset = Strategy.dOffset or 0
|
||||
OptionalParameters.dRadialOffset = ( Part.dWidth - BeamData.CUT_EXTRA) / 2
|
||||
OptionalParameters.sUserNotes = EgtIf( Strategy.bSplit, 'Split;', 'Cut;')
|
||||
|
||||
Machining.AuxiliaryData.bIsSplitOrCut = true
|
||||
|
||||
EdgeToMachine = StrategyLib.SplitStrategy.GetEdgeToMachine( Proc, Y_AX())
|
||||
-- approccio e retrazione
|
||||
OptionalParameters.LeadIn, OptionalParameters.LeadOut = StrategyLib.SplitStrategy.CalculateLeadInOut( EdgeToMachine)
|
||||
Machining.Splitting = FaceByBlade.Make( Proc, Part, Proc.Faces[1].id, EdgeToMachine, OptionalParameters)
|
||||
table.insert( Machinings, Machining)
|
||||
----------------------------------------------------------------------------------
|
||||
elseif Strategy.SplitStrategy.sTypeMachining == 'BladeHorizontalSingle' then
|
||||
local Machining = {}
|
||||
Machining.Splitting = {}
|
||||
Machining.AuxiliaryData = {}
|
||||
local OptionalParameters = {}
|
||||
OptionalParameters.nToolIndex = Strategy.SplitStrategy[1].ToolInfo.nToolIndex
|
||||
OptionalParameters.nFaceuse = MCH_MILL_FU.ORTHO_DOWN
|
||||
OptionalParameters.sDepth = 0
|
||||
OptionalParameters.dLongitudinalOffset = Strategy.dOffset or 0
|
||||
OptionalParameters.dRadialOffset = -BeamData.CUT_EXTRA
|
||||
OptionalParameters.sUserNotes = EgtIf( Strategy.bSplit, 'Split;', 'Cut;')
|
||||
|
||||
Machining.AuxiliaryData.bIsSplitOrCut = true
|
||||
|
||||
local EdgeToMachine = StrategyLib.SplitStrategy.GetEdgeToMachine( Proc, Z_AX())
|
||||
-- approccio e retrazione
|
||||
OptionalParameters.LeadIn, OptionalParameters.LeadOut = StrategyLib.SplitStrategy.CalculateLeadInOut( EdgeToMachine)
|
||||
Machining.Splitting = FaceByBlade.Make( Proc, Part, Proc.Faces[1].id, EdgeToMachine, OptionalParameters)
|
||||
table.insert( Machinings, Machining)
|
||||
----------------------------------------------------------------------------------
|
||||
elseif Strategy.SplitStrategy.sTypeMachining == 'BladeHorizontalDouble' then
|
||||
local Machining = {}
|
||||
Machining.Splitting = {}
|
||||
Machining.AuxiliaryData = {}
|
||||
local OptionalParameters = {}
|
||||
OptionalParameters.nToolIndex = Strategy.SplitStrategy[1].ToolInfo.nToolIndex
|
||||
-- Taglio lato frontale
|
||||
OptionalParameters.nFaceuse = MCH_MILL_FU.ORTHO_DOWN
|
||||
OptionalParameters.sDepth = 0
|
||||
OptionalParameters.dLongitudinalOffset = Strategy.dOffset or 0
|
||||
local dExtraMaxMat = ( Strategy.SplitStrategy[1].ToolInfo.dMaxMatBladeFromTop + Strategy.SplitStrategy[2].ToolInfo.dMaxMatBladeFromDown - Part.dHeight - BeamData.CUT_EXTRA) / 2
|
||||
OptionalParameters.dRadialOffset = Part.dHeight - Strategy.SplitStrategy[1].ToolInfo.dMaxMatBladeFromTop + dExtraMaxMat
|
||||
OptionalParameters.sUserNotes = EgtIf( Strategy.bSplit, 'Presplit;', 'Precut;')
|
||||
|
||||
|
||||
local EdgeToMachine = StrategyLib.SplitStrategy.GetEdgeToMachine( Proc, Z_AX())
|
||||
-- approccio e retrazione
|
||||
OptionalParameters.LeadIn, OptionalParameters.LeadOut = StrategyLib.SplitStrategy.CalculateLeadInOut( EdgeToMachine)
|
||||
Machining.Splitting = FaceByBlade.Make( Proc, Part, Proc.Faces[1].id, EdgeToMachine, OptionalParameters)
|
||||
table.insert( Machinings, Machining)
|
||||
|
||||
-- Taglio lato dietro
|
||||
Machining = {}
|
||||
Machining.Splitting = {}
|
||||
Machining.AuxiliaryData = {}
|
||||
OptionalParameters = {}
|
||||
OptionalParameters.nToolIndex = Strategy.SplitStrategy[2].ToolInfo.nToolIndex
|
||||
OptionalParameters.nFaceuse = MCH_MILL_FU.ORTHO_TOP
|
||||
OptionalParameters.sDepth = 0
|
||||
OptionalParameters.dLongitudinalOffset = Strategy.dOffset or 0
|
||||
OptionalParameters.dRadialOffset = Part.dHeight - Strategy.SplitStrategy[2].ToolInfo.dMaxMatBladeFromDown + dExtraMaxMat
|
||||
OptionalParameters.sUserNotes = EgtIf( Strategy.bSplit, 'Split;', 'Cut;')
|
||||
|
||||
Machining.AuxiliaryData.bIsSplitOrCut = true
|
||||
|
||||
EdgeToMachine = StrategyLib.SplitStrategy.GetEdgeToMachine( Proc, -Z_AX())
|
||||
-- approccio e retrazione
|
||||
OptionalParameters.LeadIn, OptionalParameters.LeadOut = StrategyLib.SplitStrategy.CalculateLeadInOut( EdgeToMachine)
|
||||
Machining.Splitting = FaceByBlade.Make( Proc, Part, Proc.Faces[1].id, EdgeToMachine, OptionalParameters)
|
||||
table.insert( Machinings, Machining)
|
||||
----------------------------------------------------------------------------------
|
||||
elseif Strategy.SplitStrategy.sTypeMachining == 'ChainSawHorizontal' then
|
||||
; -- TODO
|
||||
----------------------------------------------------------------------------------
|
||||
elseif Strategy.SplitStrategy.sTypeMachining == 'ChainSawSideSingle' then
|
||||
; -- TODO
|
||||
----------------------------------------------------------------------------------
|
||||
elseif Strategy.SplitStrategy.sTypeMachining == 'ChainSawSideDouble' then
|
||||
; -- TODO
|
||||
----------------------------------------------------------------------------------
|
||||
elseif Strategy.SplitStrategy.sTypeMachining == 'ChainSawPlusBlade' then
|
||||
; -- TODO
|
||||
----------------------------------------------------------------------------------
|
||||
end
|
||||
return Machinings
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
return StrategyLib
|
||||
+13
-11
@@ -42,12 +42,14 @@ _G.package.loaded.BasicCustomerStrategies = nil
|
||||
_G.package.loaded.FeatureLib = nil
|
||||
_G.package.loaded.FaceData = nil
|
||||
_G.package.loaded.MachiningLib = nil
|
||||
_G.package.loaded.DiceCut = nil
|
||||
_G.package.loaded.StrategyLib = nil
|
||||
_G.package.loaded.Logs = nil
|
||||
-- strategie di base sempre presenti
|
||||
_G.package.loaded['SPLITCUT\\SPLITCUT'] = nil
|
||||
_G.package.loaded['SPLITCUT\\SPLITCUTConfig'] = nil
|
||||
_G.package.loaded['HEADCUT\\HEADCUT'] = nil
|
||||
_G.package.loaded['HEADCUT\\HEADCUTConfig'] = nil
|
||||
_G.package.loaded['TAILCUT\\TAILCUT'] = nil
|
||||
_G.package.loaded['TAILCUT\\TAILCUTConfig'] = nil
|
||||
|
||||
-- TODO controllare se c'è un modo migliore per resettare librerie delle strategie caricate precedentemente
|
||||
-- Per ottimizzare potremmo anche ciclare solo fino al numero di strategie raggiunto per il momento.
|
||||
@@ -129,15 +131,15 @@ local function MyProcessInputData()
|
||||
EgtOutBox( 'Box non definito per la trave ' .. PARTS[i].sName, 'Lavora Travi', 'ERROR')
|
||||
return false
|
||||
else
|
||||
PARTS[i].b3Box = b3Solid
|
||||
PARTS[i].b3PartOriginal = b3Solid
|
||||
end
|
||||
end
|
||||
dRawW = PARTS[1].b3Box:getDimY()
|
||||
dRawH = PARTS[1].b3Box:getDimZ()
|
||||
dRawW = PARTS[1].b3PartOriginal:getDimY()
|
||||
dRawH = PARTS[1].b3PartOriginal:getDimZ()
|
||||
local vBeamErr = {}
|
||||
for i = 2, #PARTS do
|
||||
local dDimW = PARTS[i].b3Box:getDimY()
|
||||
local dDimH = PARTS[i].b3Box:getDimZ()
|
||||
local dDimW = PARTS[i].b3PartOriginal:getDimY()
|
||||
local dDimH = PARTS[i].b3PartOriginal:getDimZ()
|
||||
if ( abs( dDimW - dRawW) > 10 * GEO.EPS_SMALL or abs( dDimH - dRawH) > 10 * GEO.EPS_SMALL) and
|
||||
( abs( dDimH - dRawW) > 10 * GEO.EPS_SMALL or abs( dDimW - dRawH) > 10 * GEO.EPS_SMALL) then
|
||||
table.insert( vBeamErr, i)
|
||||
@@ -184,9 +186,9 @@ local function MyProcessBeams()
|
||||
-- Lunghezza totale delle travi
|
||||
local dTotLen = 0
|
||||
for i = 1, #PARTS - 1 do
|
||||
dTotLen = dTotLen + PARTS[i].b3Box:getDimX()
|
||||
dTotLen = dTotLen + PARTS[i].b3PartOriginal:getDimX()
|
||||
end
|
||||
dTotLen = dTotLen + max( PARTS[#PARTS].b3Box:getDimX(), BeamData.dMinRaw)
|
||||
dTotLen = dTotLen + max( PARTS[#PARTS].b3PartOriginal:getDimX(), BeamData.dMinRaw)
|
||||
local dAddLen = BeamData.OVM_HEAD + ( #PARTS - 1) * BeamData.OVM_MID
|
||||
EgtOutLog( 'Ltot : '..EgtNumToString( dTotLen, 1) .. ' Lagg : '..EgtNumToString( dAddLen, 1)..' MinUnloadRaw : '.. EgtNumToString( BeamData.dMinRaw + BeamData.OVM_MID, 1), 1)
|
||||
|
||||
@@ -275,10 +277,10 @@ local function MyProcessBeams()
|
||||
local bOrd = ( vsVal[5] == 'true')
|
||||
if bOrd then
|
||||
table.sort( PARTS, function( B1, B2)
|
||||
if abs( B1.b3Box:getDimX() - B2.b3Box:getDimX()) < 1 then
|
||||
if abs( B1.b3PartOriginal:getDimX() - B2.b3PartOriginal:getDimX()) < 1 then
|
||||
return B1.nInd < B2.nInd
|
||||
else
|
||||
return B1.b3Box:getDimX() < B2.b3Box:getDimX()
|
||||
return B1.b3PartOriginal:getDimX() < B2.b3PartOriginal:getDimX()
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
@@ -70,12 +70,14 @@ function FACEBYBLADE.Make( Proc, Part, FaceToMachine, EdgeToMachine, OptionalPar
|
||||
local vtMachiningDirection = EdgeToMachine.Norm
|
||||
local vtN = Proc.Faces[FaceToMachine+1].vtN
|
||||
Cutting.sDepth = OptionalParameters.sDepth or 0
|
||||
Cutting.dLongitudinalOffset = OptionalParameters.dLongitudinalOffset or 0
|
||||
Cutting.dRadialOffset = OptionalParameters.dRadialOffset or 0
|
||||
|
||||
Cutting.nType = MCH_MY.MILLING
|
||||
Cutting.nToolIndex = OptionalParameters.nToolIndex
|
||||
Cutting.Geometry = {{ Proc.id, FaceToMachine}}
|
||||
Cutting.id = Proc.id
|
||||
Cutting.vtToolDirection = vtMachiningDirection
|
||||
|
||||
|
||||
-- ===== calcolo LeadIn/out =====
|
||||
|
||||
@@ -93,7 +93,7 @@ function SLOTBYBLADE.Make( Proc, Part, FaceToMachine, EdgeToMachine, OptionalPar
|
||||
Cutting.dResidualDepth = abs( EdgeToMachine.dElevation)
|
||||
Cutting.dBladeMarkLength = 0
|
||||
Cutting.sEdgeType = EdgeToMachine.sType
|
||||
Cutting. nSegment = 1
|
||||
Cutting.nFeatureSegment = 1
|
||||
|
||||
-- parametri opzionali
|
||||
if not OptionalParameters then
|
||||
@@ -107,7 +107,12 @@ function SLOTBYBLADE.Make( Proc, Part, FaceToMachine, EdgeToMachine, OptionalPar
|
||||
Cutting.dLengthOnX = abs( EdgeToMachine.dLength * EdgeToMachine.vtToolDirection:getY())
|
||||
Cutting.dEdgeLength = EdgeToMachine.dLength
|
||||
Cutting.ptEdge1, _, Cutting.ptEdge2 = EgtSurfTmFacetOppositeSide( Proc.id, FaceToMachine.id, -EdgeToMachine.vtToolDirection, GDB_ID.ROOT)
|
||||
Cutting.vtEdgeDirection = EdgeToMachine.vtToolDirection ^ FaceToMachine.vtN
|
||||
Cutting.vtToolDirection = EdgeToMachine.vtToolDirection
|
||||
if EdgeToMachine.bIsOpen then
|
||||
Cutting.vtEdgeDirection = -EdgeToMachine.vtToolDirection ^ FaceToMachine.vtN
|
||||
else
|
||||
Cutting.vtEdgeDirection = EdgeToMachine.vtToolDirection ^ FaceToMachine.vtN
|
||||
end
|
||||
|
||||
local dPocketHeight = 0
|
||||
if Proc.Topology.sFamily == 'Tunnel' then
|
||||
@@ -248,7 +253,7 @@ function SLOTBYBLADE.Make( Proc, Part, FaceToMachine, EdgeToMachine, OptionalPar
|
||||
|
||||
-- se lavorazione aperta sulla coda, eventuali aggiustamenti
|
||||
-- TODO valutare se fare funzione a parte
|
||||
if Proc.AffectedFaces.bLeft then
|
||||
if Proc.AffectedFaces.bLeft and ( EdgeToMachine.sType == 'Bottom' or ( EdgeToMachine.vtToolDirection:getX() < 10 * GEO.EPS_SMALL)) then
|
||||
local bStartLeft = MachiningLib.StartsLeftSide( Cutting)
|
||||
local dAddLengthLeftSide = Cutting.LeadOut.dEndAddLength
|
||||
local dAddLengthToReduce = sqrt( Cutting.dDepthToMachine * TOOLS[Cutting.nToolIndex].dDiameter - Cutting.dDepthToMachine * Cutting.dDepthToMachine)
|
||||
@@ -257,13 +262,13 @@ function SLOTBYBLADE.Make( Proc, Part, FaceToMachine, EdgeToMachine, OptionalPar
|
||||
end
|
||||
if not AreSameOrOppositeVectorApprox( EdgeToMachine.vtToolDirection, Y_AX()) then
|
||||
if MachiningLib.CanMoveAfterSplitcut( Cutting.dLengthOnX, Part) then
|
||||
Cutting.bMoveAfterSplitcut = true
|
||||
Cutting.sStage = 'AfterTail'
|
||||
else
|
||||
Cutting.bIsApplicable = false
|
||||
end
|
||||
elseif dAddLengthLeftSide + dAddLengthToReduce > dExtendAfterTail then
|
||||
if MachiningLib.CanMoveAfterSplitcut( Cutting.dLengthOnX, Part) then
|
||||
Cutting.bMoveAfterSplitcut = true
|
||||
Cutting.sStage = 'AfterTail'
|
||||
else
|
||||
if bStartLeft then
|
||||
Cutting.LeadIn.dStartAddLength = - dAddLengthToReduce + dExtendAfterTail
|
||||
|
||||
@@ -56,7 +56,7 @@ function SLOTBYCHAINSAW.Make( Proc, Part, FaceToMachine, EdgeToMachine, Optional
|
||||
Mortising.sMessage = ''
|
||||
Mortising.idProc = Proc.id
|
||||
Mortising.sEdgeType = EdgeToMachine.sType
|
||||
Mortising.nSegment = 1
|
||||
Mortising.nFeatureSegment = 1
|
||||
|
||||
-- parametri opzionali
|
||||
if not OptionalParameters then
|
||||
@@ -74,7 +74,12 @@ function SLOTBYCHAINSAW.Make( Proc, Part, FaceToMachine, EdgeToMachine, Optional
|
||||
Mortising.dLengthOnX = abs( dLengthToMachine * EdgeToMachine.vtToolDirection:getY())
|
||||
Mortising.dEdgeLength = EdgeToMachine.dLength
|
||||
Mortising.ptEdge1, _, Mortising.ptEdge2 = EgtSurfTmFacetOppositeSide( Proc.id, FaceToMachine.id, -EdgeToMachine.vtToolDirection, GDB_ID.ROOT)
|
||||
Mortising.vtEdgeDirection = EdgeToMachine.vtToolDirection ^ FaceToMachine.vtN
|
||||
Mortising.vtToolDirection = EdgeToMachine.vtToolDirection
|
||||
if EdgeToMachine.bIsOpen then
|
||||
Mortising.vtEdgeDirection = -EdgeToMachine.vtToolDirection ^ FaceToMachine.vtN
|
||||
else
|
||||
Mortising.vtEdgeDirection = EdgeToMachine.vtToolDirection ^ FaceToMachine.vtN
|
||||
end
|
||||
|
||||
-- altezza tasca, in base alla topologia
|
||||
local dPocketHeight = 0
|
||||
@@ -185,7 +190,7 @@ function SLOTBYCHAINSAW.Make( Proc, Part, FaceToMachine, EdgeToMachine, Optional
|
||||
-- offset radiale
|
||||
Mortising.dRadialOffset = 0
|
||||
-- distanza di sicurezza
|
||||
Mortising.dStartSafetyLength = max( EdgeToMachine.dElevation, 10)
|
||||
Mortising.dStartSafetyLength = max( EdgeToMachine.dElevation, ( TOOLS[Mortising.nToolIndex].SetupInfo.dZSafeDelta or 60) + EgtMdbGetGeneralParam( MCH_GP.SAFEZ))
|
||||
-- overlap
|
||||
Mortising.dOverlap = 0
|
||||
-- step
|
||||
@@ -224,7 +229,7 @@ function SLOTBYCHAINSAW.Make( Proc, Part, FaceToMachine, EdgeToMachine, Optional
|
||||
|
||||
-- se lavorazione aperta sulla coda, eventuali aggiustamenti
|
||||
-- TODO valutare se fare funzione a parte
|
||||
if Proc.AffectedFaces.bLeft then
|
||||
if Proc.AffectedFaces.bLeft and ( EdgeToMachine.sType == 'Bottom' or ( EdgeToMachine.vtToolDirection:getX() < 10 * GEO.EPS_SMALL)) then
|
||||
local bStartLeft = MachiningLib.StartsLeftSide( Mortising)
|
||||
local dAddLengthLeftSide = Mortising.LeadOut.dEndAddLength
|
||||
if bStartLeft then
|
||||
@@ -232,13 +237,13 @@ function SLOTBYCHAINSAW.Make( Proc, Part, FaceToMachine, EdgeToMachine, Optional
|
||||
end
|
||||
if not AreSameOrOppositeVectorApprox( EdgeToMachine.vtToolDirection, Y_AX()) then
|
||||
if MachiningLib.CanMoveAfterSplitcut( Mortising.dLengthOnX, Part) then
|
||||
Mortising.bMoveAfterSplitcut = true
|
||||
Mortising.sStage = 'AfterTail'
|
||||
else
|
||||
Mortising.bIsApplicable = false
|
||||
end
|
||||
elseif dAddLengthLeftSide + TOOLS[Mortising.nToolIndex].dDiameter / 2 > dExtendAfterTail then
|
||||
if MachiningLib.CanMoveAfterSplitcut( Mortising.dLengthOnX, Part) then
|
||||
Mortising.bMoveAfterSplitcut = true
|
||||
Mortising.sStage = 'AfterTail'
|
||||
else
|
||||
if bStartLeft then
|
||||
Mortising.LeadIn.dStartAddLength = - TOOLS[Mortising.nToolIndex].dDiameter / 2 + dExtendAfterTail
|
||||
|
||||
@@ -279,6 +279,7 @@ function HEADCUT.Make( bAddMachining, Proc, Part, CustomParameters)
|
||||
-- approccio e retrazione
|
||||
OptionalParameters.LeadIn, OptionalParameters.LeadOut = CalculateLeadInOut( Splitting, EdgeToMachine)
|
||||
Splitting = FaceByBlade.Make( Proc, Part, Proc.Faces[1].id, EdgeToMachine, OptionalParameters)
|
||||
Splitting.sStage = 'Head'
|
||||
MachiningLib.AddNewMachining( Proc, Splitting, AuxiliaryData)
|
||||
----------------------------------------------------------------------------------
|
||||
elseif Strategy.sSplitStrategy.sTypeMachining == 'BladeSideDouble' then
|
||||
@@ -295,6 +296,7 @@ function HEADCUT.Make( bAddMachining, Proc, Part, CustomParameters)
|
||||
-- approccio e retrazione
|
||||
OptionalParameters.LeadIn, OptionalParameters.LeadOut = CalculateLeadInOut( Splitting, EdgeToMachine)
|
||||
Splitting = FaceByBlade.Make( Proc, Part, Proc.Faces[1].id, EdgeToMachine, OptionalParameters)
|
||||
Splitting.sStage = 'Head'
|
||||
MachiningLib.AddNewMachining( Proc, Splitting, AuxiliaryData)
|
||||
|
||||
-- Taglio lato dietro
|
||||
@@ -312,6 +314,7 @@ function HEADCUT.Make( bAddMachining, Proc, Part, CustomParameters)
|
||||
-- approccio e retrazione
|
||||
OptionalParameters.LeadIn, OptionalParameters.LeadOut = CalculateLeadInOut( Splitting, EdgeToMachine)
|
||||
Splitting = FaceByBlade.Make( Proc, Part, Proc.Faces[1].id, EdgeToMachine, OptionalParameters)
|
||||
Splitting.sStage = 'Head'
|
||||
MachiningLib.AddNewMachining( Proc, Splitting, AuxiliaryData)
|
||||
----------------------------------------------------------------------------------
|
||||
elseif Strategy.sSplitStrategy.sTypeMachining == 'BladeHorizontalSingle' then
|
||||
@@ -327,6 +330,7 @@ function HEADCUT.Make( bAddMachining, Proc, Part, CustomParameters)
|
||||
-- approccio e retrazione
|
||||
OptionalParameters.LeadIn, OptionalParameters.LeadOut = CalculateLeadInOut( Splitting, EdgeToMachine)
|
||||
Splitting = FaceByBlade.Make( Proc, Part, Proc.Faces[1].id, EdgeToMachine, OptionalParameters)
|
||||
Splitting.sStage = 'Head'
|
||||
MachiningLib.AddNewMachining( Proc, Splitting, AuxiliaryData)
|
||||
----------------------------------------------------------------------------------
|
||||
elseif Strategy.sSplitStrategy.sTypeMachining == 'BladeHorizontalDouble' then
|
||||
@@ -344,6 +348,7 @@ function HEADCUT.Make( bAddMachining, Proc, Part, CustomParameters)
|
||||
-- approccio e retrazione
|
||||
OptionalParameters.LeadIn, OptionalParameters.LeadOut = CalculateLeadInOut( Splitting, EdgeToMachine)
|
||||
Splitting = FaceByBlade.Make( Proc, Part, Proc.Faces[1].id, EdgeToMachine, OptionalParameters)
|
||||
Splitting.sStage = 'Head'
|
||||
MachiningLib.AddNewMachining( Proc, Splitting, AuxiliaryData)
|
||||
|
||||
-- Taglio lato dietro
|
||||
@@ -361,6 +366,7 @@ function HEADCUT.Make( bAddMachining, Proc, Part, CustomParameters)
|
||||
-- approccio e retrazione
|
||||
OptionalParameters.LeadIn, OptionalParameters.LeadOut = CalculateLeadInOut( Splitting, EdgeToMachine)
|
||||
Splitting = FaceByBlade.Make( Proc, Part, Proc.Faces[1].id, EdgeToMachine, OptionalParameters)
|
||||
Splitting.sStage = 'Head'
|
||||
MachiningLib.AddNewMachining( Proc, Splitting, AuxiliaryData)
|
||||
----------------------------------------------------------------------------------
|
||||
elseif Strategy.sSplitStrategy.sTypeMachining == 'ChainSawHorizontal' then
|
||||
|
||||
@@ -1,425 +0,0 @@
|
||||
-- Strategia: SPLITCUT
|
||||
-- Descrizione
|
||||
-- Taglio di separazione
|
||||
-- Feature: SplitCut
|
||||
|
||||
-- carico librerie
|
||||
local BeamLib = require( 'BeamLib')
|
||||
local BeamData = require( 'BeamData')
|
||||
local MachiningLib = require( 'MachiningLib')
|
||||
local FeatureLib = require( 'FeatureLib')
|
||||
-- strategie di base
|
||||
local FaceByBlade = require('FACEBYBLADE')
|
||||
|
||||
-- Tabella per definizione modulo
|
||||
local SPLITCUT = {}
|
||||
local Strategy = {}
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
local function LoadStrategyParameters( CustomParameters)
|
||||
local StrategyLib = {}
|
||||
StrategyLib.Config = require( 'SPLITCUT\\SPLITCUTConfig')
|
||||
Strategy.sName = StrategyLib.Config.sStrategyId
|
||||
CustomParameters = BeamLib.GetUpdateCustomParameters( CustomParameters, StrategyLib.Config.Parameters)
|
||||
Strategy.Parameters = BeamLib.LoadCustomParametersInStrategy( CustomParameters)
|
||||
Strategy.Result = {}
|
||||
Strategy.Machining = {}
|
||||
Strategy.Result.sInfo = ''
|
||||
return Strategy
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
local function CalculateLeadInOut( Machining, EdgeToMachine)
|
||||
|
||||
local LeadIn = {}
|
||||
local LeadOut = {}
|
||||
LeadIn.dStartAddLength = 0
|
||||
LeadOut.dEndAddLength = 0
|
||||
LeadIn.nType = MCH_MILL_LI.LINEAR
|
||||
LeadOut.nType = MCH_MILL_LI.LINEAR
|
||||
LeadIn.dTangentDistance = 0
|
||||
LeadOut.dTangentDistance = 0
|
||||
-- elevazione sempre in negativo
|
||||
if EdgeToMachine.Elev < 10 * GEO.EPS_SMALL then
|
||||
LeadIn.dPerpDistance = BeamData.CUT_SIC - EdgeToMachine.Elev
|
||||
LeadOut.dPerpDistance = BeamData.CUT_SIC - EdgeToMachine.Elev
|
||||
else
|
||||
LeadIn.dPerpDistance = BeamData.CUT_SIC
|
||||
LeadOut.dPerpDistance = BeamData.CUT_SIC
|
||||
end
|
||||
LeadIn.dElevation = 0
|
||||
LeadOut.dElevation = 0
|
||||
LeadIn.dCompLength = 0
|
||||
LeadOut.dCompLength = 0
|
||||
LeadIn.dStartAddLength = BeamData.CUT_EXTRA
|
||||
LeadOut.dEndAddLength = BeamData.CUT_EXTRA
|
||||
|
||||
return LeadIn, LeadOut
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
local function MakeChamfer()
|
||||
-- TODO funzionalità da aggiungere
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
local function GetEdgeToMachine( Proc, vtEdge)
|
||||
local Edge
|
||||
for i = 1, #Proc.Faces[1].Edges do
|
||||
if AreSameVectorApprox( Proc.Faces[1].Edges[i].Norm, vtEdge) then
|
||||
Edge = Proc.Faces[1].Edges[i]
|
||||
end
|
||||
end
|
||||
return Edge
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
local function GetSplitStrategy( Proc, Part)
|
||||
-- se non sono stati caricati i parametri, si ricaricano
|
||||
if not Strategy.Parameters then
|
||||
Strategy = LoadStrategyParameters()
|
||||
end
|
||||
|
||||
-- separazione solo se esiste grezzo successivo con pezzi o scaricabile
|
||||
local nNextRawId = EgtGetNextRawPart( Part.idRaw)
|
||||
Strategy.bSplit = ( nNextRawId and ( EgtGetPartInRawPartCount( nNextRawId) > 0 or EgtGetRawPartBBox( nNextRawId):getDimX() >= BeamData.dMinRaw))
|
||||
|
||||
-- imposto paraemtri di ricerca utensile in base a topologia
|
||||
local Machining = {}
|
||||
-- sTypeMachining = BladeSideSingle\ BladeSideDouble\ BladeHorizontalSingle\ BladeHorizontalDouble\ ChainSawHorizontal\ ChainSawSideSingle\ ChainSawSideDouble\ ChainSawPlusBlade\ Mill\ None
|
||||
Machining.sTypeMachining = 'None'
|
||||
local Splitting = {}
|
||||
local ToolSearchParameters = {}
|
||||
ToolSearchParameters.vtToolDirection = Proc.Faces[1].vtN
|
||||
|
||||
|
||||
-- ===== RICERCA UTENSILE =====
|
||||
-- cerco lama sopra
|
||||
Splitting.bIsApplicable = false
|
||||
ToolSearchParameters.bAllowTopHead = true
|
||||
ToolSearchParameters.bAllowBottomHead = false
|
||||
Splitting.ToolInfo = {}
|
||||
Splitting.ToolInfo = MachiningLib.FindBlade( Proc, ToolSearchParameters)
|
||||
if Splitting.ToolInfo.nToolIndex then
|
||||
Splitting.bIsApplicable = true
|
||||
local ParametersMRR = {}
|
||||
ParametersMRR.nToolIndex = Splitting.ToolInfo.nToolIndex
|
||||
Splitting.dMRR = MachiningLib.GetToolMRR( ParametersMRR)
|
||||
end
|
||||
table.insert( Machining, Splitting)
|
||||
|
||||
-- cerco lama sotto
|
||||
Splitting = {}
|
||||
Splitting.bIsApplicable = false
|
||||
ToolSearchParameters.bAllowTopHead = false
|
||||
ToolSearchParameters.bAllowBottomHead = true
|
||||
Splitting.ToolInfo = {}
|
||||
Splitting.ToolInfo = MachiningLib.FindBlade( Proc, ToolSearchParameters)
|
||||
if Splitting.ToolInfo.nToolIndex then
|
||||
Splitting.bIsApplicable = true
|
||||
local ParametersMRR = {}
|
||||
ParametersMRR.nToolIndex = Splitting.ToolInfo.nToolIndex
|
||||
Splitting.dMRR = MachiningLib.GetToolMRR( ParametersMRR)
|
||||
end
|
||||
table.insert( Machining, Splitting)
|
||||
|
||||
-- cerco motosega
|
||||
Splitting = {}
|
||||
Splitting.bIsApplicable = false
|
||||
table.insert( Machining, Splitting)
|
||||
|
||||
-- cerco fresa
|
||||
Splitting = {}
|
||||
Splitting.bIsApplicable = false
|
||||
table.insert( Machining, Splitting)
|
||||
|
||||
-- ===== SCELTA LAVORAZIONI =====
|
||||
-- forzature da parametri
|
||||
if Strategy.Parameters.bForceChainSaw then
|
||||
Machining[1].bIsApplicable = false
|
||||
Machining[2].bIsApplicable = false
|
||||
end
|
||||
|
||||
-- setto valori di default. Impossibile che taglio di separazione sia incompleto
|
||||
Strategy.Result.sStatus = 'Completed'
|
||||
Strategy.Result.nCompletionIndex = FeatureLib.GetFeatureCompletionIndex( 100)
|
||||
Strategy.Result.dMRR = 1
|
||||
|
||||
-- correzioni sul massimo materiale lama, considerando ingombri vari
|
||||
local dMaxMatBladeSideSingle
|
||||
local dMaxMatBladeSideDouble
|
||||
local dMaxMatBladeHorizontalSingle
|
||||
local dMaxMatBladeHorizontalDouble
|
||||
if Machining[1].bIsApplicable then
|
||||
local dMaxMat = TOOLS[Machining[1].ToolInfo.nToolIndex].dMaxMaterial
|
||||
local dRadius = TOOLS[Machining[1].ToolInfo.nToolIndex].dDiameter / 2
|
||||
local sHead = TOOLS[Machining[1].ToolInfo.nToolIndex].sHead
|
||||
-- se taglio di fianco disponibile, si controlla il massimo materiale reale. Per pezzi alti, bisogna controllare anche l'ingombro asse Z nelle 4 direzioni.
|
||||
if Part.dHeight < BeamData.MIN_DIM_HBEAM then
|
||||
dMaxMat = min( dMaxMat, BeamData.MAX_DIM_HTCUT)
|
||||
dMaxMatBladeSideSingle = dMaxMat
|
||||
dMaxMatBladeSideDouble = dMaxMat * 2
|
||||
else
|
||||
if BeamData.GetMaxMatReductionBladeCut then
|
||||
dMaxMatBladeSideSingle = min( max( dRadius - BeamData.GetMaxMatReductionBladeCut( sHead, Y_AX()), dRadius - BeamData.GetMaxMatReductionBladeCut( sHead, -Y_AX())),
|
||||
TOOLS[Machining[1].ToolInfo.nToolIndex].dMaxMaterial)
|
||||
dMaxMatBladeSideDouble = dRadius - BeamData.GetMaxMatReductionBladeCut( sHead, Y_AX()) + dRadius - BeamData.GetMaxMatReductionBladeCut( sHead, -Y_AX())
|
||||
else
|
||||
dMaxMatBladeSideSingle = abs( BeamData.MAX_DIM_HTCUT_HBEAM)
|
||||
dMaxMatBladeSideDouble = abs( BeamData.MAX_DIM_HTCUT_HBEAM) * 2
|
||||
end
|
||||
end
|
||||
-- se taglio orizzontale
|
||||
if BeamData.GetMaxMatReductionBladeCut then
|
||||
dMaxMatBladeHorizontalSingle = min( TOOLS[Machining[1].ToolInfo.nToolIndex].dMaxMaterial, dRadius - BeamData.GetMaxMatReductionBladeCut( TOOLS[Machining[1].ToolInfo.nToolIndex].sHead, -Z_AX()))
|
||||
else
|
||||
dMaxMatBladeHorizontalSingle = TOOLS[Machining[1].ToolInfo.nToolIndex].dMaxMaterial
|
||||
end
|
||||
end
|
||||
if Machining[2].bIsApplicable then
|
||||
if BeamData.GetMaxMatReductionBladeCut then
|
||||
local dRadius = TOOLS[Machining[2].ToolInfo.nToolIndex].dDiameter / 2
|
||||
dMaxMatBladeHorizontalDouble = min( TOOLS[Machining[2].ToolInfo.nToolIndex].dMaxMaterial, dRadius - BeamData.GetMaxMatReductionBladeCut( TOOLS[Machining[2].ToolInfo.nToolIndex].sHead, Z_AX()))
|
||||
else
|
||||
dMaxMatBladeHorizontalDouble = TOOLS[Machining[2].ToolInfo.nToolIndex].dMaxMaterial
|
||||
end
|
||||
end
|
||||
|
||||
-- TODO considerare di tagliare con il massimo materiale possibile per non salire troppo in Z (macchine tipo PF), oppure non scendere troppo (tipo Kairos)
|
||||
-- BladeSideSingle (taglio di lama singolo di fianco)
|
||||
if Machining[1].bIsApplicable and ( dMaxMatBladeSideSingle - BeamData.CUT_EXTRA) > Part.dWidth + 10 * GEO.EPS_SMALL then
|
||||
Strategy.Result.nQuality = FeatureLib.GetFeatureQuality( 'Blade')
|
||||
Machining.sTypeMachining = 'BladeSideSingle'
|
||||
Machining[2].bIsApplicable = false
|
||||
Machining[3].bIsApplicable = false
|
||||
Machining[4].bIsApplicable = false
|
||||
return Machining
|
||||
-- TODO considerare di tagliare con il massimo materiale possibile per non salire troppo in Z (macchine tipo PF), oppure non scendere troppo (tipo Kairos)
|
||||
-- BladeSideDouble (taglio di lama doppio di fianco)
|
||||
elseif Machining[1].bIsApplicable and ( dMaxMatBladeSideDouble - BeamData.CUT_EXTRA) > Part.dWidth + 10 * GEO.EPS_SMALL then
|
||||
Strategy.Result.nQuality = FeatureLib.GetFeatureQuality( 'Blade')
|
||||
Strategy.Result.dMRR = Strategy.Result.dMRR/2
|
||||
Machining.sTypeMachining = 'BladeSideDouble'
|
||||
Machining[2].bIsApplicable = false
|
||||
Machining[3].bIsApplicable = false
|
||||
Machining[4].bIsApplicable = false
|
||||
return Machining
|
||||
-- BladeHorizontalSingle (taglio di lama singolo orizzontale)
|
||||
elseif Machining[1].bIsApplicable and ( dMaxMatBladeHorizontalSingle - BeamData.CUT_EXTRA) > Part.dHeight + 10 * GEO.EPS_SMALL then
|
||||
Strategy.Result.nQuality = FeatureLib.GetFeatureQuality( 'Blade')
|
||||
Machining.sTypeMachining = 'BladeHorizontalSingle'
|
||||
Machining[2].bIsApplicable = false
|
||||
Machining[3].bIsApplicable = false
|
||||
Machining[4].bIsApplicable = false
|
||||
return Machining
|
||||
-- BladeHorizontalDouble (taglio di lama doppio orizzontale)
|
||||
elseif Machining[1].bIsApplicable and Machining[2].bIsApplicable and
|
||||
( dMaxMatBladeHorizontalSingle + dMaxMatBladeHorizontalDouble - BeamData.CUT_EXTRA) > Part.dHeight + 10 * GEO.EPS_SMALL then
|
||||
Strategy.Result.nQuality = FeatureLib.GetFeatureQuality( 'Blade')
|
||||
Strategy.Result.dMRR = Strategy.Result.dMRR/2
|
||||
Machining.sTypeMachining = 'BladeHorizontalDouble'
|
||||
Machining[1].ToolInfo.dMaxMatBladeFromTop = dMaxMatBladeHorizontalSingle
|
||||
Machining[2].ToolInfo.dMaxMatBladeFromDown = dMaxMatBladeHorizontalDouble
|
||||
Machining[3].bIsApplicable = false
|
||||
Machining[4].bIsApplicable = false
|
||||
return Machining
|
||||
|
||||
-- TODO : casi con motosega da completare
|
||||
-- ChainSawHorizontal (motosega)
|
||||
-- ChainSawSideSingle (motosega)
|
||||
-- ChainSawSideDouble (motosega)
|
||||
-- ChainSawPlusBlade (motosega più lama orizzontale)
|
||||
-- Mill (svuotatura)
|
||||
end
|
||||
|
||||
-- se non ho trovato neanche una lavorazione completa, non posso separare
|
||||
if Machining.sTypeMachining == 'None' then
|
||||
Strategy.Result.sStatus = 'Not-Applicable'
|
||||
Strategy.Result.nCompletionIndex = 0
|
||||
Strategy.Result.dMRR = 0
|
||||
Strategy.Result.nQuality = 0
|
||||
Strategy.Result.sInfo = 'Split not possible'
|
||||
end
|
||||
|
||||
return Machining
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
function SPLITCUT.Make( bAddMachining, Proc, Part, CustomParameters)
|
||||
Strategy = LoadStrategyParameters( CustomParameters)
|
||||
local bAreAllMachiningsAdded = true
|
||||
local Splitting = {}
|
||||
local AuxiliaryData = {}
|
||||
|
||||
Strategy.sSplitStrategy = GetSplitStrategy( Proc, Part)
|
||||
if bAddMachining then
|
||||
-- inserimento smussi su spigoli del taglio
|
||||
if Strategy.Parameters.bMakeChamfer then
|
||||
MakeChamfer()
|
||||
end
|
||||
|
||||
local OptionalParameters = {}
|
||||
-- applico le lavorazioni
|
||||
----------------------------------------------------------------------------------
|
||||
if Strategy.sSplitStrategy.sTypeMachining == 'BladeSideSingle' then
|
||||
OptionalParameters = {}
|
||||
OptionalParameters.nToolIndex = Strategy.sSplitStrategy[1].ToolInfo.nToolIndex
|
||||
OptionalParameters.nFaceuse = MCH_MILL_FU.ORTHO_BACK
|
||||
OptionalParameters.sDepth = 0
|
||||
|
||||
-- TODO gestire lavorazione a cubetti
|
||||
|
||||
if Strategy.bSplit then
|
||||
OptionalParameters.sUserNotes = 'Split;'
|
||||
else
|
||||
OptionalParameters.sUserNotes = 'Cut;'
|
||||
end
|
||||
AuxiliaryData.bAddNewPhase = true
|
||||
|
||||
local EdgeToMachine = GetEdgeToMachine( Proc, -Y_AX())
|
||||
-- approccio e retrazione
|
||||
OptionalParameters.LeadIn, OptionalParameters.LeadOut = CalculateLeadInOut( Splitting, EdgeToMachine)
|
||||
Splitting = FaceByBlade.Make( Proc, Part, Proc.Faces[1].id, EdgeToMachine, OptionalParameters)
|
||||
MachiningLib.AddNewMachining( Proc, Splitting, AuxiliaryData)
|
||||
----------------------------------------------------------------------------------
|
||||
elseif Strategy.sSplitStrategy.sTypeMachining == 'BladeSideDouble' then
|
||||
OptionalParameters = {}
|
||||
OptionalParameters.nToolIndex = Strategy.sSplitStrategy[1].ToolInfo.nToolIndex
|
||||
-- Taglio lato frontale
|
||||
OptionalParameters.nFaceuse = MCH_MILL_FU.ORTHO_BACK
|
||||
OptionalParameters.sDepth = 0
|
||||
OptionalParameters.dRadialOffset = ( Part.dWidth - BeamData.CUT_EXTRA) / 2
|
||||
|
||||
-- TODO gestire lavorazione a cubetti
|
||||
|
||||
if Strategy.bSplit then
|
||||
OptionalParameters.sUserNotes = 'PreSplit;'
|
||||
else
|
||||
OptionalParameters.sUserNotes = 'PreCut;'
|
||||
end
|
||||
|
||||
local EdgeToMachine = GetEdgeToMachine( Proc, -Y_AX())
|
||||
-- approccio e retrazione
|
||||
OptionalParameters.LeadIn, OptionalParameters.LeadOut = CalculateLeadInOut( Splitting, EdgeToMachine)
|
||||
Splitting = FaceByBlade.Make( Proc, Part, Proc.Faces[1].id, EdgeToMachine, OptionalParameters)
|
||||
MachiningLib.AddNewMachining( Proc, Splitting, AuxiliaryData)
|
||||
|
||||
-- Taglio lato dietro
|
||||
OptionalParameters = {}
|
||||
Splitting = {}
|
||||
AuxiliaryData = {}
|
||||
OptionalParameters.nToolIndex = Strategy.sSplitStrategy[1].ToolInfo.nToolIndex
|
||||
OptionalParameters.nFaceuse = MCH_MILL_FU.ORTHO_FRONT
|
||||
OptionalParameters.sDepth = 0
|
||||
OptionalParameters.dRadialOffset = ( Part.dWidth - BeamData.CUT_EXTRA) / 2
|
||||
|
||||
-- TODO gestire lavorazione a cubetti
|
||||
|
||||
if Strategy.bSplit then
|
||||
OptionalParameters.sUserNotes = 'Split;'
|
||||
else
|
||||
OptionalParameters.sUserNotes = 'Cut;'
|
||||
end
|
||||
AuxiliaryData.bAddNewPhase = true
|
||||
|
||||
EdgeToMachine = GetEdgeToMachine( Proc, Y_AX())
|
||||
-- approccio e retrazione
|
||||
OptionalParameters.LeadIn, OptionalParameters.LeadOut = CalculateLeadInOut( Splitting, EdgeToMachine)
|
||||
Splitting = FaceByBlade.Make( Proc, Part, Proc.Faces[1].id, EdgeToMachine, OptionalParameters)
|
||||
MachiningLib.AddNewMachining( Proc, Splitting, AuxiliaryData)
|
||||
----------------------------------------------------------------------------------
|
||||
elseif Strategy.sSplitStrategy.sTypeMachining == 'BladeHorizontalSingle' then
|
||||
OptionalParameters = {}
|
||||
OptionalParameters.nToolIndex = Strategy.sSplitStrategy[1].ToolInfo.nToolIndex
|
||||
OptionalParameters.nFaceuse = MCH_MILL_FU.ORTHO_DOWN
|
||||
OptionalParameters.sDepth = 0
|
||||
OptionalParameters.dRadialOffset = -BeamData.CUT_EXTRA
|
||||
|
||||
-- TODO gestire lavorazione a cubetti
|
||||
|
||||
if Strategy.bSplit then
|
||||
OptionalParameters.sUserNotes = 'Split;'
|
||||
else
|
||||
OptionalParameters.sUserNotes = 'Cut;'
|
||||
end
|
||||
AuxiliaryData.bAddNewPhase = true
|
||||
|
||||
local EdgeToMachine = GetEdgeToMachine( Proc, Z_AX())
|
||||
-- approccio e retrazione
|
||||
OptionalParameters.LeadIn, OptionalParameters.LeadOut = CalculateLeadInOut( Splitting, EdgeToMachine)
|
||||
Splitting = FaceByBlade.Make( Proc, Part, Proc.Faces[1].id, EdgeToMachine, OptionalParameters)
|
||||
MachiningLib.AddNewMachining( Proc, Splitting, AuxiliaryData)
|
||||
----------------------------------------------------------------------------------
|
||||
elseif Strategy.sSplitStrategy.sTypeMachining == 'BladeHorizontalDouble' then
|
||||
OptionalParameters = {}
|
||||
OptionalParameters.nToolIndex = Strategy.sSplitStrategy[1].ToolInfo.nToolIndex
|
||||
-- Taglio lato frontale
|
||||
OptionalParameters.nFaceuse = MCH_MILL_FU.ORTHO_DOWN
|
||||
OptionalParameters.sDepth = 0
|
||||
local dExtraMaxMat = ( Strategy.sSplitStrategy[1].ToolInfo.dMaxMatBladeFromTop + Strategy.sSplitStrategy[2].ToolInfo.dMaxMatBladeFromDown - Part.dHeight - BeamData.CUT_EXTRA) / 2
|
||||
OptionalParameters.dRadialOffset = Part.dHeight - Strategy.sSplitStrategy[1].ToolInfo.dMaxMatBladeFromTop + dExtraMaxMat
|
||||
|
||||
-- TODO gestire lavorazione a cubetti
|
||||
|
||||
if Strategy.bSplit then
|
||||
OptionalParameters.sUserNotes = 'PreSplit;'
|
||||
else
|
||||
OptionalParameters.sUserNotes = 'PreCut;'
|
||||
end
|
||||
|
||||
local EdgeToMachine = GetEdgeToMachine( Proc, Z_AX())
|
||||
-- approccio e retrazione
|
||||
OptionalParameters.LeadIn, OptionalParameters.LeadOut = CalculateLeadInOut( Splitting, EdgeToMachine)
|
||||
Splitting = FaceByBlade.Make( Proc, Part, Proc.Faces[1].id, EdgeToMachine, OptionalParameters)
|
||||
MachiningLib.AddNewMachining( Proc, Splitting, AuxiliaryData)
|
||||
|
||||
-- Taglio lato dietro
|
||||
OptionalParameters = {}
|
||||
Splitting = {}
|
||||
AuxiliaryData = {}
|
||||
OptionalParameters.nToolIndex = Strategy.sSplitStrategy[2].ToolInfo.nToolIndex
|
||||
OptionalParameters.nFaceuse = MCH_MILL_FU.ORTHO_TOP
|
||||
OptionalParameters.sDepth = 0
|
||||
OptionalParameters.dRadialOffset = Part.dHeight - Strategy.sSplitStrategy[2].ToolInfo.dMaxMatBladeFromDown + dExtraMaxMat
|
||||
|
||||
-- TODO gestire lavorazione a cubetti
|
||||
|
||||
if Strategy.bSplit then
|
||||
OptionalParameters.sUserNotes = 'Split;'
|
||||
else
|
||||
OptionalParameters.sUserNotes = 'Cut;'
|
||||
end
|
||||
AuxiliaryData.bAddNewPhase = true
|
||||
|
||||
EdgeToMachine = GetEdgeToMachine( Proc, -Z_AX())
|
||||
-- approccio e retrazione
|
||||
OptionalParameters.LeadIn, OptionalParameters.LeadOut = CalculateLeadInOut( Splitting, EdgeToMachine)
|
||||
Splitting = FaceByBlade.Make( Proc, Part, Proc.Faces[1].id, EdgeToMachine, OptionalParameters)
|
||||
MachiningLib.AddNewMachining( Proc, Splitting, AuxiliaryData)
|
||||
----------------------------------------------------------------------------------
|
||||
elseif Strategy.sSplitStrategy.sTypeMachining == 'ChainSawHorizontal' then
|
||||
; -- TODO
|
||||
----------------------------------------------------------------------------------
|
||||
elseif Strategy.sSplitStrategy.sTypeMachining == 'ChainSawSideSingle' then
|
||||
; -- TODO
|
||||
----------------------------------------------------------------------------------
|
||||
elseif Strategy.sSplitStrategy.sTypeMachining == 'ChainSawSideDouble' then
|
||||
; -- TODO
|
||||
----------------------------------------------------------------------------------
|
||||
elseif Strategy.sSplitStrategy.sTypeMachining == 'ChainSawPlusBlade' then
|
||||
; -- TODO
|
||||
----------------------------------------------------------------------------------
|
||||
elseif Strategy.sSplitStrategy.sTypeMachining == 'Mill' then
|
||||
; -- TODO
|
||||
----------------------------------------------------------------------------------
|
||||
end
|
||||
|
||||
return bAreAllMachiningsAdded, Strategy.Result
|
||||
else
|
||||
return nil, Strategy.Result
|
||||
end
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
|
||||
return SPLITCUT
|
||||
@@ -360,29 +360,29 @@ local function GetSplitSurfaces( Proc, Part)
|
||||
end
|
||||
|
||||
-- recupero punti di spezzatura - da destra a sinistra
|
||||
local vFeatureSplittingPoints = FeatureLib.GetFeatureSplittingPoints( Proc, Part)
|
||||
local FeatureSplittingPoints = FeatureLib.GetFeatureSplittingPoints( Proc, Part)
|
||||
|
||||
if #vFeatureSplittingPoints == 0 then
|
||||
if #FeatureSplittingPoints == 0 then
|
||||
local nAddId = EgtCopyGlob( Proc.id, nAddGrpId) or GDB_ID.NULL
|
||||
local nAddIdTunnel = EgtCopyGlob( nOriginalTmIdTunnel, nAddGrpId) or GDB_ID.NULL
|
||||
table.insert( vAddId, nAddId)
|
||||
table.insert( vAddIdTunnel, nAddIdTunnel)
|
||||
else
|
||||
for i = 1, #vFeatureSplittingPoints do
|
||||
for i = 1, #FeatureSplittingPoints do
|
||||
local nAddId = EgtCopyGlob( Proc.id, nAddGrpId) or GDB_ID.NULL
|
||||
local nAddIdTunnel = EgtCopyGlob( nOriginalTmIdTunnel, nAddGrpId) or GDB_ID.NULL
|
||||
if i == 1 then
|
||||
-- prima superficie, va tagliata solo a sinistra
|
||||
local ptSplit = vFeatureSplittingPoints[i] + Vector3d( -BeamData.MILL_OVERLAP / 2, 0, 0)
|
||||
local ptSplit = FeatureSplittingPoints[i] + Vector3d( -BeamData.MILL_OVERLAP / 2, 0, 0)
|
||||
EgtCutSurfTmPlane( nAddId, ptSplit, -X_AX(), true, GDB_RT.GLOB)
|
||||
EgtCutSurfTmPlane( nAddIdTunnel, ptSplit, -X_AX(), true, GDB_RT.GLOB)
|
||||
else
|
||||
-- taglio della superficie corrente - lato sinistro
|
||||
local ptSplit = vFeatureSplittingPoints[i] + Vector3d( -BeamData.MILL_OVERLAP / 2, 0, 0)
|
||||
local ptSplit = FeatureSplittingPoints[i] + Vector3d( -BeamData.MILL_OVERLAP / 2, 0, 0)
|
||||
EgtCutSurfTmPlane( nAddId, ptSplit, -X_AX(), true, GDB_RT.GLOB)
|
||||
EgtCutSurfTmPlane( nAddIdTunnel, ptSplit, -X_AX(), true, GDB_RT.GLOB)
|
||||
-- taglio della superficie corrente - lato destro
|
||||
ptSplit = vFeatureSplittingPoints[i - 1] + Vector3d( BeamData.MILL_OVERLAP / 2, 0, 0)
|
||||
ptSplit = FeatureSplittingPoints[i - 1] + Vector3d( BeamData.MILL_OVERLAP / 2, 0, 0)
|
||||
EgtCutSurfTmPlane( nAddId, ptSplit, X_AX(), true, GDB_RT.GLOB)
|
||||
EgtCutSurfTmPlane( nAddIdTunnel, ptSplit, X_AX(), true, GDB_RT.GLOB)
|
||||
end
|
||||
@@ -392,7 +392,7 @@ local function GetSplitSurfaces( Proc, Part)
|
||||
-- taglio ultima superficie, va tagliata solo a destra
|
||||
local nAddId = EgtCopyGlob( Proc.id, nAddGrpId) or GDB_ID.NULL
|
||||
local nAddIdTunnel = EgtCopyGlob( nOriginalTmIdTunnel, nAddGrpId) or GDB_ID.NULL
|
||||
local ptSplit = vFeatureSplittingPoints[#vFeatureSplittingPoints] + Vector3d( BeamData.MILL_OVERLAP / 2, 0, 0)
|
||||
local ptSplit = FeatureSplittingPoints[#FeatureSplittingPoints] + Vector3d( BeamData.MILL_OVERLAP / 2, 0, 0)
|
||||
EgtCutSurfTmPlane( nAddId, ptSplit, X_AX(), true, GDB_RT.GLOB)
|
||||
EgtCutSurfTmPlane( nAddIdTunnel, ptSplit, X_AX(), true, GDB_RT.GLOB)
|
||||
table.insert( vAddId, nAddId)
|
||||
@@ -438,6 +438,7 @@ function STR0002.Make( bAddMachining, Proc, Part, CustomParameters)
|
||||
vAddId, vAddIdTunnel = GetSplitSurfaces( Proc, Part)
|
||||
|
||||
-- si applicano le lavorazioni
|
||||
-- TODO manca la gestione delle lavorazioni dopo separazione
|
||||
for i = 1, #vAddId do
|
||||
for j = 1, #Strategy.Machining do
|
||||
if Strategy.Machining[j].bIsApplicable then
|
||||
@@ -460,13 +461,15 @@ function STR0002.Make( bAddMachining, Proc, Part, CustomParameters)
|
||||
-- se ho una sola trimesh, sto lavorando la Proc direttamente e non ho spezzato. Applico direttamente alla geometria calcolata prima
|
||||
if #vAddId == 1 then
|
||||
Pocketing.Geometry = {{ Strategy.Machining[j].idProc, Strategy.Machining[j].idFaceToMachine}}
|
||||
Pocketing.vtToolDirection = Proc.Faces[ Strategy.Machining[j].idFaceToMachine + 1].vtN
|
||||
bAreAllMachiningsAdded = MachiningLib.AddNewMachining( Proc, Pocketing)
|
||||
else
|
||||
-- TODO settare parametro per indicare qual è lo spezzone che deve essere fatto dopo il taglio di separazione
|
||||
for k = 1, Proc.nFct do
|
||||
local vtNSplitFace
|
||||
local nIdTm = EgtIf( Strategy.Machining[j].bMachAppliedToTunnelFace, vAddIdTunnel[i], vAddId[i])
|
||||
vtNSplitFace = EgtSurfTmFacetNormVersor( nIdTm, k - 1, GDB_ID.ROOT)
|
||||
Pocketing.ptCenter, vtNSplitFace = EgtSurfTmFacetCenter( nIdTm, k - 1, GDB_ID.ROOT)
|
||||
Pocketing.vtToolDirection = vtNSplitFace
|
||||
if vtNSplitFace and AreSameVectorApprox( vtNSplitFace * EgtIf( Pocketing.bToolInvert, -1, 1), Strategy.Machining[j].vtFaceNormal) then
|
||||
Pocketing.Geometry = {{ nIdTm, k - 1}}
|
||||
bAreAllMachiningsAdded = bAreAllMachiningsAdded and MachiningLib.AddNewMachining( Proc, Pocketing)
|
||||
|
||||
@@ -62,9 +62,9 @@ end
|
||||
|
||||
-- TODO si può unificare con eguale funzione in STR0004
|
||||
local function SortMachiningsBySegment( MachiningA, MachiningB)
|
||||
if MachiningA.nSegment > MachiningB.nSegment then
|
||||
if MachiningA.nFeatureSegment > MachiningB.nFeatureSegment then
|
||||
return false
|
||||
elseif MachiningB.nSegment > MachiningA.nSegment then
|
||||
elseif MachiningB.nFeatureSegment > MachiningA.nFeatureSegment then
|
||||
return true
|
||||
else
|
||||
if TOOLS[ MachiningA.nToolIndex].sFamily == 'SAWBLADE' and TOOLS[ MachiningB.nToolIndex].sFamily == 'MORTISE' then
|
||||
@@ -88,9 +88,9 @@ local function SortMachiningsByTool( MachiningA, MachiningB)
|
||||
elseif TOOLS[ MachiningA.nToolIndex].sFamily == 'MORTISE' and TOOLS[ MachiningB.nToolIndex].sFamily == 'SAWBLADE' then
|
||||
return false
|
||||
else
|
||||
if MachiningA.nSegment > MachiningB.nSegment then
|
||||
if MachiningA.nFeatureSegment > MachiningB.nFeatureSegment then
|
||||
return false
|
||||
elseif MachiningB.nSegment > MachiningA.nSegment then
|
||||
elseif MachiningB.nFeatureSegment > MachiningA.nFeatureSegment then
|
||||
return true
|
||||
else
|
||||
if MachiningA.sEdgeType == 'Side' and MachiningB.sEdgeType ~= 'Side' then
|
||||
@@ -303,9 +303,9 @@ function STR0003.Make( bAddMachining, Proc, Part, CustomParameters)
|
||||
-- lama - lavorazioni raggruppate in unica lista
|
||||
Blade.Result.Sorted = MergeResults( Blade.Result)
|
||||
-- lama - aggiunta eventuali lavorazioni splittate
|
||||
local vFeatureSplittingPoints = FeatureLib.GetFeatureSplittingPoints( Proc, Part)
|
||||
if #vFeatureSplittingPoints > 0 then
|
||||
Blade.Result.Sorted = MachiningLib.GetSplitMachinings( Blade.Result.Sorted, vFeatureSplittingPoints, Part)
|
||||
local FeatureSplittingPoints = FeatureLib.GetFeatureSplittingPoints( Proc, Part)
|
||||
if #FeatureSplittingPoints > 0 then
|
||||
Blade.Result.Sorted = MachiningLib.GetSplitMachinings( Blade.Result.Sorted, FeatureSplittingPoints, Part)
|
||||
end
|
||||
-- lama - nessuna lavorazione successiva - aggiunta lavorazioni e calcolo risultati
|
||||
if not Strategy.Parameters.bFinishWithChainSaw then
|
||||
@@ -500,8 +500,8 @@ function STR0003.Make( bAddMachining, Proc, Part, CustomParameters)
|
||||
-- sega a catena - lavorazioni raggruppate in unica lista
|
||||
Chainsaw.Result.Sorted = MergeResults( Chainsaw.Result)
|
||||
-- sega a catena - aggiunta eventuali lavorazioni splittate
|
||||
if #vFeatureSplittingPoints > 0 then
|
||||
Chainsaw.Result.Sorted = MachiningLib.GetSplitMachinings( Chainsaw.Result.Sorted, vFeatureSplittingPoints, Part)
|
||||
if #FeatureSplittingPoints > 0 then
|
||||
Chainsaw.Result.Sorted = MachiningLib.GetSplitMachinings( Chainsaw.Result.Sorted, FeatureSplittingPoints, Part)
|
||||
end
|
||||
|
||||
-- tutte le lavorazioni di tutti gli utensili in unica lista
|
||||
|
||||
@@ -57,10 +57,11 @@ local function GetCompletionPercentage( Proc, Result)
|
||||
end
|
||||
|
||||
|
||||
-- TODO si può unificare con Sorting generale
|
||||
local function SortMachiningsBySegment( MachiningA, MachiningB)
|
||||
if MachiningA.nSegment > MachiningB.nSegment then
|
||||
if MachiningA.nFeatureSegment > MachiningB.nFeatureSegment then
|
||||
return false
|
||||
elseif MachiningB.nSegment > MachiningA.nSegment then
|
||||
elseif MachiningB.nFeatureSegment > MachiningA.nFeatureSegment then
|
||||
return true
|
||||
else
|
||||
if MachiningA.sEdgeType == 'Side' and MachiningB.sEdgeType ~= 'Side' then
|
||||
@@ -156,7 +157,7 @@ function STR0004.Make( bAddMachining, Proc, Part, CustomParameters)
|
||||
|
||||
-- calcolo lavorazioni
|
||||
local Mortising = {}
|
||||
OptionalParameters = { dExtendAfterTail = dExtendAfterTail}
|
||||
local OptionalParameters = { dExtendAfterTail = dExtendAfterTail}
|
||||
if Proc.Topology.sName == 'Groove-4-Blind' or Proc.Topology.sName == 'Pocket-5-Blind' then
|
||||
-- si lavora tutto il fondo
|
||||
local OptionalParameters = { dExtendAfterTail = dExtendAfterTail}
|
||||
@@ -234,9 +235,9 @@ function STR0004.Make( bAddMachining, Proc, Part, CustomParameters)
|
||||
end
|
||||
|
||||
-- aggiunta eventuali lavorazioni splittate
|
||||
local vFeatureSplittingPoints = FeatureLib.GetFeatureSplittingPoints( Proc, Part)
|
||||
if #vFeatureSplittingPoints > 0 then
|
||||
Chainsaw.Result.Sorted = MachiningLib.GetSplitMachinings( Chainsaw.Result.Sorted, vFeatureSplittingPoints, Part)
|
||||
local FeatureSplittingPoints = FeatureLib.GetFeatureSplittingPoints( Proc, Part)
|
||||
if #FeatureSplittingPoints > 0 then
|
||||
Chainsaw.Result.Sorted = MachiningLib.GetSplitMachinings( Chainsaw.Result.Sorted, FeatureSplittingPoints, Part)
|
||||
end
|
||||
|
||||
-- ordinamento
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
-- Strategia: TAILCUT
|
||||
-- Descrizione
|
||||
-- Taglio di separazione
|
||||
-- Feature: TailCut
|
||||
|
||||
-- carico librerie
|
||||
local BeamLib = require( 'BeamLib')
|
||||
local BeamData = require( 'BeamData')
|
||||
local MachiningLib = require( 'MachiningLib')
|
||||
local StrategyLib = require( 'StrategyLib')
|
||||
local DiceCut = require( 'DiceCut')
|
||||
|
||||
-- Tabella per definizione modulo
|
||||
local TAILCUT = {}
|
||||
local Strategy = {}
|
||||
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
local function MakeChamfer()
|
||||
-- TODO funzionalità da aggiungere
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
function TAILCUT.Make( bAddMachining, Proc, Part, CustomParameters)
|
||||
local StrategyDefaultParam = {}
|
||||
StrategyDefaultParam.Config = require( 'TAILCUT\\TAILCUTConfig')
|
||||
Strategy.sName = StrategyDefaultParam.Config.sStrategyId
|
||||
CustomParameters = BeamLib.GetUpdateCustomParameters( CustomParameters, StrategyDefaultParam.Config.Parameters)
|
||||
Strategy.Parameters = BeamLib.LoadCustomParametersInStrategy( CustomParameters)
|
||||
Strategy.SplitStrategy = {}
|
||||
Strategy.Result = {}
|
||||
Strategy.Machining = {}
|
||||
Strategy.Result.sInfo = ''
|
||||
local bAreAllMachiningsAdded = true
|
||||
|
||||
-- separazione solo se esiste grezzo successivo con pezzi o scaricabile
|
||||
Strategy.bSplit = not( Part.bIsLastPart) or Part.dRestLength >= BeamData.dMinRaw
|
||||
|
||||
-- se devo fare split perchè c'è un grezzo da scaricare o un altro pezzo
|
||||
if Strategy.bSplit then
|
||||
Strategy.SplitStrategy, Strategy.Result = StrategyLib.SplitStrategy.Get( Proc, Part, Strategy.Parameters)
|
||||
|
||||
-- se devo rimuovere tutto il restante
|
||||
else
|
||||
-- se abilitato, faccio tagli di PRECUT a zero (come SPLIT)
|
||||
if Strategy.Parameters.bExecutePreCut then
|
||||
Strategy.SplitStrategy, Strategy.Result = StrategyLib.SplitStrategy.Get( Proc, Part, Strategy.Parameters)
|
||||
-- se non faccio tagli PRECUT, imposto tabella Result direttamente. Non serve verificare che riesca a rimuovere il materiale extra
|
||||
else
|
||||
Strategy.Result.sStatus = 'Completed'
|
||||
Strategy.Result.nCompletionIndex = 5
|
||||
Strategy.Result.dMRR = 1
|
||||
Strategy.Result.nQuality = 5
|
||||
Strategy.Result.sInfo = 'Split not possible'
|
||||
end
|
||||
end
|
||||
|
||||
-- se devo applicare le lavorazioni
|
||||
if bAddMachining then
|
||||
|
||||
-- inserimento smussi su spigoli del taglio
|
||||
if Strategy.Parameters.bMakeChamfer then
|
||||
MakeChamfer()
|
||||
end
|
||||
|
||||
local MachiningsToAdd = {}
|
||||
-- se devo fare split perchè c'è un grezzo da scaricare o un altro pezzo
|
||||
if Strategy.bSplit then
|
||||
Strategy.dOffset = 0
|
||||
MachiningsToAdd = StrategyLib.SplitStrategy.Execute( Proc, Part, Strategy)
|
||||
-- se devo rimuovere tutto il restante
|
||||
else
|
||||
-- se abilitato, faccio tagli di PRECUT a zero (come SPLIT)
|
||||
if Strategy.Parameters.bExecutePreCut then
|
||||
Strategy.dOffset = Part.dRestLength
|
||||
MachiningsToAdd = StrategyLib.SplitStrategy.Execute( Proc, Part, Strategy)
|
||||
end
|
||||
-- rimuovo tutto il restante
|
||||
-- table.insert( MachiningsToAdd, StrategyLib.BladeToWasteOneFace( Proc, Part))
|
||||
local Faces = {}
|
||||
local Face1 = {}
|
||||
local Face2 = {}
|
||||
local OptionalParameters = {}
|
||||
Face1.ptCenter = Proc.Faces[1].ptCenter
|
||||
Face1.vtNormal = Proc.Faces[1].vtN
|
||||
OptionalParameters.b3BoxToDicing = Part.b3Raw
|
||||
Faces = DiceCut.GetDice( Part, Face1, Face2, OptionalParameters)
|
||||
end
|
||||
|
||||
-- aggiungo lavorazioni trovate alla lista generale
|
||||
for i = 1, #MachiningsToAdd do
|
||||
MachiningsToAdd[i].Splitting.sStage = 'Tail'
|
||||
MachiningLib.AddNewMachining( Proc, MachiningsToAdd[i].Splitting, MachiningsToAdd[i].AuxiliaryData)
|
||||
end
|
||||
|
||||
return bAreAllMachiningsAdded, Strategy.Result
|
||||
else
|
||||
return nil, Strategy.Result
|
||||
end
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
|
||||
return TAILCUT
|
||||
+5
-4
@@ -1,12 +1,13 @@
|
||||
-- Parametri configurabili da cliente per strategia: SPLITCUT
|
||||
-- Parametri configurabili da cliente per strategia: TAILCUT
|
||||
|
||||
local SPLITCUTData = {
|
||||
sStrategyId = 'SPLITCUT',
|
||||
local TAILCUTData = {
|
||||
sStrategyId = 'TAILCUT',
|
||||
Parameters = {
|
||||
{ sName = 'bMakeChamfer', sValue = 'false', sDescriptionShort = 'Execute Chamfer', sDescriptionLong = 'Use the V-Mill to execute chamfers on cut-edges', sType = 'b', sMessageId = '', sMinUserLevel = '1'},
|
||||
{ sName = 'bForceChainSaw', sValue = 'false', sDescriptionShort = 'Force to use chain saw', sDescriptionLong = 'Force to use chain saw', sType = 'b', sMessageId = '', sMinUserLevel = '1'},
|
||||
{ sName = 'bExecutePreCut', sValue = 'true', sDescriptionShort = 'Force to add PreCuts', sDescriptionLong = "Autocam will apply a machining on the theoric zero, to avoid collision if the theoric piece length doesn't correspond to the real length", sType = 'b', sMessageId = '', sMinUserLevel = '1'},
|
||||
{ sName = 'bFinishWithMill', sValue = 'true', sDescriptionShort = 'Finish with mill', sDescriptionLong = 'Use a mill to finish the surface if split with chain saw', sType = 'b', sMessageId = '', sMinUserLevel = '1'}
|
||||
}
|
||||
}
|
||||
|
||||
return SPLITCUTData
|
||||
return TAILCUTData
|
||||
@@ -139,8 +139,8 @@ STR0003 = Topologia tipo LapJoint. Lama + motosega
|
||||
252,0,Feature,
|
||||
; Feature : HEADCUT
|
||||
340,0,Feature,HEADCUT
|
||||
; Feature : SPLITCUT
|
||||
350,0,Feature,SPLITCUT
|
||||
; Feature : TAILCUT
|
||||
350,0,Feature,TAILCUT
|
||||
; Feature : Variant
|
||||
900,0,Feature,
|
||||
; Feature Decor
|
||||
|
||||
Reference in New Issue
Block a user