-- WallExec.lua by Egaltech s.r.l. 2024/02/20 -- Libreria esecuzione lavorazioni per Pareti -- 2023/05/25 Aggiunto ordinamento in base a priorità da btl. -- 2023/06/07 Nel caso di outline con priorità aggiunta la rimozione degli sfridi nella lavorazione successiva. -- 2023/06/27 Aggiunte origini TN e BN. -- 2023/07/04 Se c'è funzione di macchina WD.GetOrigCorner si lascia scegliere posizione default a questa impostando 0 se non c'è 'REFPOS'. -- 2023/10/16 Aggiunta gestione Aree vietate (LockOut) per chiodature. -- 2023/11/14 Modifiche sostanziali per l'aggiunta delle lavorazioni in doppio. -- In Collect aggiunto il recupero preliminare di varie informazioni sulla feature. -- 2023/12/11 In ClassifyTopology si passa ora anche l'Id del grezzo (allineamento Topology con Beam). -- 2024/02/20 Aggiunta gestione DeltaX/Y/Z del pannello dall'origine da BTL. -- 2024/08/30 Aggiunta nota altezza sottopezzo, per pareti a layer -- Tabella per definizione modulo local WallExec = {} -- Include require( 'EgtBase') -- Carico i dati globali e libero tutti gli altri _G.package.loaded.WallData = nil _G.package.loaded.CutData = nil _G.package.loaded.MillingData = nil _G.package.loaded.PocketingData = nil _G.package.loaded.DrillData = nil _G.package.loaded.SawingData = nil local WD = require( 'WallData') if WALL and WALL.NESTINGCORNERBL then WD.NESTING_CORNER = 'BL' end -- Carico le librerie _G.package.loaded.WMachiningLib = nil _G.package.loaded.WallLib = nil _G.package.loaded.WFeatureTopology = nil _G.package.loaded.WProcessCut = nil _G.package.loaded.WProcessDoubleCut = nil _G.package.loaded.WProcessSawCut = nil _G.package.loaded.WProcessLapJoint = nil _G.package.loaded.WProcessDrill = nil _G.package.loaded.WProcessMortise = nil _G.package.loaded.WProcessDtMortise = nil _G.package.loaded.WProcessMark = nil _G.package.loaded.WProcessText = nil _G.package.loaded.WProcessFreeContour = nil _G.package.loaded.WProcessVariant = nil local WM = require( 'WMachiningLib') local WL = require( 'WallLib') local Topology = require( 'WFeatureTopology') local Squaring = require( 'Squaring') local Cut = require( 'WProcessCut') local DoubleCut = require( 'WProcessDoubleCut') local SawCut = require( 'WProcessSawCut') local LapJoint = require( 'WProcessLapJoint') local Drill = require( 'WProcessDrill') local Mortise = require( 'WProcessMortise') local DtMortise = require( 'WProcessDtMortise') local Mark = require( 'WProcessMark') local Text = require( 'WProcessText') local FreeContour = require( 'WProcessFreeContour') local Variant = require( 'WProcessVariant') ------------------------------------------------------------------------------------------------------------- -- *** Inserimento delle pareti nel pannello *** ------------------------------------------------------------------------------------------------------------- local function GetRawOrigAndDeltas() -- Area tavola local b3Tab = EgtGetTableArea() -- Calcolo posizione estremo di riferimento della tavola rispetto a sua origine in BL local sOrigCorner = WD.ORIG_CORNER or 'BR' local BtlInfoId = EgtGetFirstNameInGroup( GDB_ID.ROOT, 'BtlInfo') or GDB_ID.NULL if WD.GetOrigCorner then sOrigCorner = WD.GetOrigCorner( EgtGetInfo( BtlInfoId, 'REFPOS', 'i') or 0) end -- offset da interfaccia local dDeltaXFromBtl = EgtGetInfo( BtlInfoId, 'PANELDELTAY', 'd') or 0 local dDeltaYFromBtl = EgtGetInfo( BtlInfoId, 'PANELDELTAX', 'd') or 0 local dDeltaZFromBtl = EgtGetInfo( BtlInfoId, 'PANELDELTAZ', 'd') or 0 -- se da interfaccia arriva un valore > 0 si usa quello, altrimenti si legge da WallData (default 0) local DeltaX = EgtIf( dDeltaXFromBtl > 0, dDeltaXFromBtl, WD.DELTA_X or 0) local DeltaY = EgtIf( dDeltaYFromBtl > 0, dDeltaYFromBtl, WD.DELTA_Y or 0) local DeltaZ = EgtIf( dDeltaZFromBtl > 0, dDeltaZFromBtl, WD.DELTA_Z or 0) local nCorner local OrigOnTab if sOrigCorner == 'TL' then nCorner = MCH_CR.TL OrigOnTab = Point3d( 0 + abs( DeltaX), b3Tab:getDimY() - abs( DeltaY), DeltaZ) elseif sOrigCorner == 'BL' then nCorner = MCH_CR.BL OrigOnTab = Point3d( 0 + abs( DeltaX), abs( DeltaY), DeltaZ) elseif sOrigCorner == 'TR' then nCorner = MCH_CR.TR OrigOnTab = Point3d( b3Tab:getDimX() - abs( DeltaX), b3Tab:getDimY() - abs( DeltaY), DeltaZ) elseif sOrigCorner == 'BR' then nCorner = MCH_CR.BR OrigOnTab = Point3d( b3Tab:getDimX() - abs( DeltaX), abs( DeltaY), DeltaZ) elseif sOrigCorner == 'TM' then nCorner = MCH_CR.TR OrigOnTab = Point3d( WD.MID_REF - abs( DeltaX), b3Tab:getDimY() - abs( DeltaY), DeltaZ) elseif sOrigCorner == 'BM' then nCorner = MCH_CR.BR OrigOnTab = Point3d( WD.MID_REF - abs( DeltaX), abs( DeltaY), DeltaZ) elseif sOrigCorner == 'TN' then nCorner = MCH_CR.TL OrigOnTab = Point3d( WD.NEW_REF + abs( DeltaX), b3Tab:getDimY() - abs( DeltaY), DeltaZ) elseif sOrigCorner == 'BN' then nCorner = MCH_CR.BL OrigOnTab = Point3d( WD.NEW_REF + abs( DeltaX), abs( DeltaY), DeltaZ) end return sOrigCorner, nCorner, OrigOnTab end ------------------------------------------------------------------------------------------------------------- function WallExec.ProcessWalls( dRawL, dRawW, dRawH, vWall, bMachGroupOk, bNewProcess, nRawOutlineId) -- Creazione nuovo gruppo di lavoro if not bMachGroupOk then local sMgName = EgtGetMachGroupNewName( 'Mach') local NewMgId = EgtAddMachGroup( sMgName) if not NewMgId then local sOut = 'Errore nella creazione del gruppo di lavoro ' .. sMgName return false, sOut end end -- Impostazione della tavola EgtSetTable( 'Tab') -- Recupero dati posizionamento grezzo local sOrigCorner, nCorner, OrigOnTab = GetRawOrigAndDeltas() -- Impostazione dell'attrezzaggio di default EgtImportSetup() -- Impostazione eventuale allargamento area disponibile per grezzo EgtSetTableAreaOffset( WD.TAB_EXTRA_XP or 0, WD.TAB_EXTRA_YP or 0, WD.TAB_EXTRA_XM or 0, WD.TAB_EXTRA_YM or 0) -- Creazione del grezzo e suo posizionamento in macchina local nRaw = GDB_ID.NULL if nRawOutlineId and nRawOutlineId ~= GDB_ID.NULL then nRaw = EgtAddRawPartWithPart( 0, nRawOutlineId, 0, WD.RAWCOL) else nRaw = EgtAddRawPart( Point3d( 0, 0, 0), dRawL, dRawW, dRawH, WD.RAWCOL) end EgtMoveToCornerRawPart( nRaw, OrigOnTab, nCorner) EgtSetInfo( nRaw, 'ORIGCORNER', sOrigCorner) EgtSetInfo( nRaw, 'ORD', 1) -- Inserimento dei pezzi nel grezzo for i = 1, #vWall do -- assegno identificativo pezzo local Pz = vWall[i].Id -- dati del pezzo local b3Part = EgtGetBBoxGlob( Pz or GDB_ID.NULL, GDB_BB.EXACT) local b3Solid = vWall[i].Box if b3Part:isEmpty() or b3Solid:isEmpty() then break end local PartLen = b3Solid:getDimX() local PartWidth = b3Solid:getDimY() local PartHeight = b3Solid:getDimZ() local vtOffs = b3Part:getMin() - b3Solid:getMin() -- creo o pulisco gruppo geometrie aggiuntive if not WL.CreateOrEmptyAddGroup( Pz) then local sOut = 'Error creating Additional Group in Part ' .. tostring( Pz) return false, sOut end -- inserisco il pezzo nel grezzo EgtDeselectPartObjs( Pz) local ptPos if bNewProcess then local sNestingRef = ( WALL.NESTING_REF or WD.NESTING_CORNER) if sNestingRef == 'TL' then ptPos = Point3d( vWall[i].PosX, dRawW - PartWidth - vWall[i].PosZ, ( dRawH - PartHeight) / 2) + vtOffs elseif sNestingRef == 'TR' then ptPos = Point3d( dRawL - PartLen - vWall[i].PosX, dRawW - PartWidth - vWall[i].PosZ, ( dRawH - PartHeight) / 2) + vtOffs elseif sNestingRef == 'BR' then ptPos = Point3d( dRawL - PartLen - vWall[i].PosX, vWall[i].PosZ, ( dRawH - PartHeight) / 2) + vtOffs else -- 'BL' ptPos = Point3d( vWall[i].PosX, vWall[i].PosZ, ( dRawH - PartHeight) / 2) + vtOffs end else local dPosH = EgtIf( vWall[i].PosY < 0.1, ( dRawH - PartHeight) / 2, vWall[i].PosY) EgtSetInfo( nRaw, 'SUBPIECE', dPosH) ptPos = Point3d( dRawL - vWall[i].PosX - PartLen, vWall[i].PosZ, dPosH) + vtOffs end EgtAddPartToRawPart( Pz, ptPos, nRaw) end return true end ------------------------------------------------------------------------------------------------------------- function WallExec.MoveRaw() -- Recupero dati posizionamento grezzo local sOrigCorner, nCorner, OrigOnTab = GetRawOrigAndDeltas() -- Recupero identificativo del grezzo local nRaw = EgtGetFirstRawPart() or GDB_ID.NULL -- Posizione iniziale del centro grezzo local ptOriCen = EgtGetRawPartCenter( nRaw) -- Sposto il grezzo EgtMoveToCornerRawPart( nRaw, OrigOnTab, nCorner) EgtSetInfo( nRaw, 'ORIGCORNER', sOrigCorner) -- Posizione finale del centro grezzo local ptNewCen = EgtGetRawPartCenter( nRaw) -- Restituisco flag di movimento return not AreSamePointApprox( ptOriCen, ptNewCen) end ------------------------------------------------------------------------------------------------------------- -- *** Inserimento delle lavorazioni nelle pareti *** ------------------------------------------------------------------------------------------------------------- function WallExec.CollectFeatures( PartId, b3Raw, b3Squaring) -- recupero le feature local vProc = {} local LayerId = {} LayerId[1] = EgtGetFirstNameInGroup( PartId or GDB_ID.NULL, 'Outline') LayerId[2] = EgtGetFirstNameInGroup( PartId or GDB_ID.NULL, 'Processings') for nInd = 1, #LayerId do local ProcId = EgtGetFirstInGroup( LayerId[nInd] or GDB_ID.NULL) while ProcId do local nEntType = EgtGetType( ProcId) if nEntType == GDB_TY.SRF_MESH or nEntType == GDB_TY.EXT_TEXT or nEntType == GDB_TY.CRV_LINE or nEntType == GDB_TY.CRV_ARC or nEntType == GDB_TY.CRV_BEZ or nEntType == GDB_TY.CRV_COMPO then local nGrp = EgtGetInfo( ProcId, 'GRP', 'i') local nPrc = EgtGetInfo( ProcId, 'PRC', 'i') local nDo = EgtGetInfo( ProcId, 'DO', 'i') or 1 local nCutId = EgtGetInfo( EgtGetParent( EgtGetParent( ProcId)), 'CUTID', 'i') or 0 local nTaskId = EgtGetInfo( ProcId, 'TASKID', 'i') or 0 if nGrp and nPrc and nDo == 1 then local Proc = {} Proc.PartId = PartId Proc.Id = ProcId Proc.Grp = nGrp Proc.Prc = nPrc Proc.Flg = 1 Proc.Fct = EgtSurfTmFacetCount( ProcId) or 0 Proc.Diam = 0 Proc.Fcs = 0 Proc.Fce = 0 Proc.CutId = nCutId Proc.TaskId = nTaskId Proc.Box = EgtGetBBoxGlob( ProcId, GDB_BB.STANDARD) Proc.IsOutline = ( Proc.Prc == 251 or Proc.Prc == 252) if b3Raw then -- recupero l'elenco delle facce della parte interessate dalla feature Proc.AffectedFaces = WL.GetProcessAffectedFaces( Proc) -- recupero le distanze tra la feature e le altre parti più vicine Proc.DistanceToNearestParts = WL.GetProcessDistanceToNearestParts( Proc) -- recupero le distanze tra la feature e il grezzo Proc.DistanceToRawPart = WL.GetProcessDistanceToRawPart( Proc, b3Raw) -- recupero informazioni sulle facce della feature Proc.Face = {} if Proc.Fct < 50 then for i = 1, Proc.Fct do Proc.Face[i] = { Id = i - 1, VtN = EgtSurfTmFacetNormVersor( Proc.Id, i - 1, GDB_ID.ROOT ), Elevation = WL.GetFaceElevation( Proc.Id, i - 1, PartId)} end end end if Proc.Box and not Proc.Box:isEmpty() then table.insert( vProc, Proc) -- se squadratura sui pezzi, si annullano le lavorazioni esterne al box di squadratura if b3Squaring then local b3SquaringReduced = BBox3d( b3Squaring) b3SquaringReduced:expand( -0.1) if not OverlapsXY( Proc.Box, b3SquaringReduced) then Proc.Flag = 0 end end -- se foro if Drill.Identify( Proc) then -- assegno diametro e facce di ingresso e uscita (dati tabelle sempre per riferimento) Proc.Diam, Proc.Fcs, Proc.Fce = Drill.GetData( Proc, b3Raw) -- verifico se necessaria seconda lavorazione da parte opposta per foro più lungo della punta if Drill.Split( Proc, b3Raw) then -- aggiorno flags prima parte foro (dati tabelle sempre per riferimento) Proc.Flg = 2 -- definisco dati seconda parte local Proc2 = {} Proc2.PartId = PartId Proc2.Id = ProcId Proc2.Grp = nGrp Proc2.Prc = nPrc Proc2.Flg = -2 Proc2.Box = BBox3d( Proc.Box) Proc2.Fct = Proc.Fct Proc2.Diam = Proc.Diam Proc2.Fcs = Proc.Fce Proc2.Fce = Proc.Fcs Proc2.CutId = Proc.CutId Proc2.TaskId = Proc.TaskId table.insert( vProc, Proc2) end -- se free contour elseif FreeContour.Identify( Proc) then -- recupero il tipo e il dato della lavorazione local nCntType = EgtGetInfo( Proc.Id, 'CNT_TYPE', 'i') or 0 local nCntData = EgtGetInfo( Proc.Id, 'CNT_DATA', 'i') or 0 -- imposto se area vietata if nCntType == 200 then Proc.LockOut = EgtIf( ( nCntData == 0 or ( nCntData & 1) ~= 0), 1, -1) end if Proc.LockOut then Proc.Flg = 0 end end else EgtOutLog( ' Feature ' .. tostring( Proc.Id) .. ' is empty (no geometry)') end end end ProcId = EgtGetNext( ProcId) end end return vProc end ------------------------------------------------------------------------------------------------------------- local function ClassifyFeatures( vProc, b3Raw) for i = 1, #vProc do local Proc = vProc[i] -- se taglio if Cut.Identify( Proc) then local bOk = Cut.Classify( Proc, b3Raw) if not bOk then Proc.Flg = 0 end -- se taglio doppio elseif DoubleCut.Identify( Proc) then local bOk = DoubleCut.Classify( Proc, b3Raw) if not bOk then Proc.Flg = 0 end -- se taglio con lama elseif SawCut.Identify( Proc) then local bOk = SawCut.Classify( Proc, b3Raw) if not bOk then Proc.Flg = 0 end -- se tasca elseif LapJoint.Identify( Proc) then local bOk = LapJoint.Classify( Proc, b3Raw) if not bOk then Proc.Flg = 0 end -- se foratura elseif Drill.Identify( Proc) then local bUseMultiDrill = WD.USE_MULTI_DRILL or false local bOk = Drill.Classify( Proc, b3Raw, bUseMultiDrill) if not bOk then Proc.Flg = 0 end -- se mortasatura elseif Mortise.Identify( Proc) then local bOk = Mortise.Classify( Proc, b3Raw) if not bOk then Proc.Flg = 0 end -- se mortasatura a coda di rondine elseif DtMortise.Identify( Proc) then local bOk = DtMortise.Classify( Proc, b3Raw) if not bOk then Proc.Flg = 0 end -- se marcatura elseif Mark.Identify( Proc) then local bOk = Mark.Classify( Proc, b3Raw) if not bOk then Proc.Flg = 0 end -- se testo elseif Text.Identify( Proc) then local bOk = Text.Classify( Proc, b3Raw) if not bOk then Proc.Flg = 0 end -- se contorno libero, outile o aperture elseif FreeContour.Identify( Proc) then local bOk = FreeContour.Classify( Proc, b3Raw) if not bOk then Proc.Flg = 0 end -- se feature custom (Variant) elseif Variant.Identify( Proc) then local bOk = Variant.Classify( Proc, b3Raw) if not bOk then Proc.Flg = 0 end end end end ------------------------------------------------------------------------------------------------------------- local function ClassifyTopology( vProc, nRawId) local b3Raw = EgtGetRawPartBBox( nRawId) local nRecognized = 0 for i = 1, #vProc do local Proc = vProc[i] if Topology.Classify( Proc, b3Raw) then nRecognized = nRecognized + 1 end end return nRecognized end ------------------------------------------------------------------------------------------------------------- local function PrintFeatures( vProc) EgtOutLog( ' *** Feature List ***') for i = 1, #vProc do local Proc = vProc[i] local sOut = string.format( 'Part=%3d Proc=%3d Grp=%1d Prc=%3d TC=%2d/%d Flg=%2d Lo=%d Fcse=%1d,%1d Diam=%.2f Fct=%2d Dbl=%2d Dlt=%.1f Box=%s TopoName=%s', Proc.PartId, Proc.Id, Proc.Grp, Proc.Prc, Proc.TaskId, Proc.CutId, Proc.Flg, EgtIf( Proc.LockOut, 1, 0), Proc.Fcs, Proc.Fce, Proc.Diam, Proc.Fct, Proc.Double or 0, Proc.Delta or 0, tostring( Proc.Box), Proc.TopologyLongName or '') EgtOutLog( sOut) end end ------------------------------------------------------------------------------------------------------------- local function AddFeatureMachining( Proc, nRawId, b3Raw, vNLO, b3Squaring) local bOk = true local sErr = '' EgtOutLog( ' * Process ' .. tostring( Proc.Id) .. ' *', 1) -- se taglio (1/2-010-X) o taglio longitudinale (0/3/4-010-X) if Cut.Identify( Proc) then -- esecuzione taglio bOk, sErr = Cut.Make( Proc, nRawId, b3Raw) -- se taglio doppio (1/2-011-X) o taglio doppio longitudinale (0-012-X) elseif DoubleCut.Identify( Proc) then -- esecuzione taglio bOk, sErr = DoubleCut.Make( Proc, nRawId, b3Raw) -- se taglio con lama (0/3/4-013-X) elseif SawCut.Identify( Proc) then -- esecuzione taglio bOk, sErr = SawCut.Make( Proc, nRawId, b3Raw) -- se tasca (3/4-030-X) o similari elseif LapJoint.Identify( Proc) then -- esecuzione tasca bOk, sErr = LapJoint.Make( Proc, nRawId, b3Raw) -- se foratura ( 3/4-040-X) elseif Drill.Identify( Proc) then -- esecuzione foratura local bUseMultiDrill = WD.USE_MULTI_DRILL or false bOk, sErr = Drill.Make( Proc, nRawId, b3Raw, bUseMultiDrill) -- se mortasatura (3/4-050-X) o similari elseif Mortise.Identify( Proc) then -- esecuzione mortasatura bOk, sErr = Mortise.Make( Proc, nRawId, b3Raw) -- se mortasatura a coda di rondine (3/4-055-X) elseif DtMortise.Identify( Proc) then -- esecuzione mortasatura a coda di rondine bOk, sErr = DtMortise.Make( Proc, nRawId, b3Raw) -- se marcatura (3/4-060-X) elseif Mark.Identify( Proc) then -- esecuzione marcatura bOk, sErr = Mark.Make( Proc, nRawId, b3Raw) -- se testo (4-061-X) elseif Text.Identify( Proc) then -- esecuzione incisione testo bOk, sErr = Text.Make( Proc, nRawId, b3Raw) -- se contorno libero, outline o apertura ( 0/3/4-250/251/252-X) elseif FreeContour.Identify( Proc) then -- esecuzione contorno libero bOk, sErr = FreeContour.Make( Proc, nRawId, b3Raw, vNLO, b3Squaring) -- se feature custom (Variant) elseif Variant.Identify( Proc) then -- esecuzione bOk, sErr = Variant.Make( Proc, nRawId, b3Raw) -- altrimenti feature non riconosciuta else bOk = false sErr = 'Feature type non recognized for machining' end return bOk, sErr end ------------------------------------------------------------------------------------------------------------- local function MoveMachiningsAtEnd( nPhase, nType, sStartName, sProperty) local nOperId = EgtGetPhaseDisposition( nPhase) local nLastId = EgtGetLastOperation() local nInsertId = nLastId while nOperId do local nNextOperId = EgtGetNextOperation( nOperId) if EgtGetOperationPhase( nOperId) == nPhase and EgtGetOperationType( nOperId) == nType and ( ( EgtGetInfo( nOperId, 'MOVE_AFTER', 'i') == 1 ) or ( not sStartName or string.sub( EgtGetName( nOperId), 1, #sStartName) == sStartName)) then EgtRelocateGlob( nOperId, nInsertId, GDB_IN.AFTER) nInsertId = nOperId end if nOperId == nLastId then break end nOperId = nNextOperId end end ------ Ordinamento dei tagli, delle fresature e delle forature ------- local function SpSorting( TabCut, PrevMch, nType, bOneWay) -- ordino le lavorazioni (in gruppi di max 1000 entità se 32bit 10000 se 64bit) --EgtOutLog('Dati per ShortestPath :') local SP_MAX_ENT = EgtIf( EgtIs64bit(), 10000, 1000) local nBase = 0 while nBase < #TabCut do -- calcolo ordinamento EgtSpInit() for i = 1, min( #TabCut - nBase, SP_MAX_ENT) do local ptS = TabCut[nBase+i].Start local ptE = TabCut[nBase+i].End EgtSpAddPoint( ptS:getX(), ptS:getY(), ptS:getZ(), 0, 0, ptE:getX(), ptE:getY(), ptE:getZ(), 0, 0) end EgtSpSetAngularParams( 1000, 40, 2000, 60) EgtSpSetOpenBound( true, SHP_OB.NEAR_PNT, 50000, 0, 0, 0, 0) if WD.BEAM_MACHINE and (nType & MCH_OY.SAWING) == MCH_OY.SAWING then EgtSpSetOpenBound( false, SHP_OB.NEAR_PNT, -50000, 0, 0, 0, 0) end EgtSpSetZzOwStep( 10) local nType = EgtIf( bOneWay, SHP_TY.ONEWAY_YM, SHP_TY.OPEN) local vOrd = EgtSpCalculate( nType) EgtSpTerminate() -- applico ordinamento calcolato if vOrd then for i = 1, #vOrd do EgtRelocateGlob( TabCut[nBase+vOrd[i]].Mch, PrevMch, GDB_IN.AFTER) PrevMch = TabCut[nBase+vOrd[i]].Mch end end -- incremento la base nBase = nBase + SP_MAX_ENT end return PrevMch end local function ContainsStartName( nOperId, StartNames) local bFound = false for i = 1, #StartNames do local sStartName = StartNames[i] if string.sub( EgtGetName( nOperId), 1, #sStartName) == sStartName then bFound = true end end return bFound end ------ Ordinamento dei tagli, delle fresature e delle forature ------- local function SortMach( nPhase, PrevMch, nPartId, nType, StartNames, bExistName, sInfo, bExistInfo, bOneWay, bByTool, bByToolAngle, nPriority) -- dichiarazione tabella local TabCut = {} -- Recupero gli identificativi delle lavorazioni e annullo eventuali allungamenti e Id di altre lavorazioni rappresentate local nOperId = EgtGetNextOperation( PrevMch) while nOperId do local nOperType = EgtGetOperationType( nOperId) -- Se appartiene alla fase corrente e taglio con lama non da sopra (sempre su 1 sola entità) if EgtGetOperationPhase( nOperId) == nPhase and ( nType & nOperType) == nOperType and ( not nPartId or EgtGetInfo( nOperId, 'Part', 'i') == nPartId) and ( not nPriority or EgtGetInfo( nOperId, 'PRIORITY', 'i') == nPriority ) and ( not StartNames or ( bExistName and ContainsStartName( nOperId, StartNames)) or ( not bExistName and not ContainsStartName( nOperId, StartNames))) and ( not sInfo or ( bExistInfo and EgtGetInfo( nOperId, sInfo, 'i') == 1) or ( not bExistInfo and EgtGetInfo( nOperId, sInfo, 'i') ~= 1)) then -- non si deve cambiare lo stato di attivazione della lavorazione (se disabilitata errata) EgtSetCurrMachining( nOperId) if not EgtIsMachiningEmpty() then -- punto iniziale e finale e direzione della lavorazione local ptStart = EgtGetMachiningStartPoint() local ptEnd = EgtGetMachiningEndPoint() local sTUUID = '' local nToolType = 0 local nToolDiam = 0 local nToolDir = 0 if bByTool then sTUUID = EgtGetMachiningParam( MCH_MP.TUUID) local sToolName = EgtTdbGetToolFromUUID( sTUUID) if EgtTdbSetCurrTool( sToolName) then nToolType = EgtTdbGetCurrToolParam( MCH_TP.TYPE) nToolDiam = EgtTdbGetCurrToolParam( MCH_TP.TOTDIAM) else sTUUID = '' end end if bByToolAngle then local nClId = EgtGetFirstNameInGroup( nOperId, 'CL') local nPathId = EgtGetFirstInGroup( nClId or GDB_ID.NULL) local vtTool = EgtGetInfo( nPathId, 'EXTR', 'v') nToolDir = EgtIf( vtTool:getZ() > 0.999999, 1, 0) end table.insert( TabCut, {Mch=nOperId, Ent=nEntId, Start=ptStart, End=ptEnd, Tool=sTUUID, ToolType=nToolType, ToolDiam=nToolDiam, ToolDir=nToolDir}) end end -- Passo alla operazione successiva nOperId = EgtGetNextOperation( nOperId) end if bByTool then local function ToolCompare(a,b) if a.ToolType < b.ToolType then return true elseif a.ToolType == b.ToolType then if a.ToolDiam > b.ToolDiam then return true elseif a.ToolDiam == b.ToolDiam then if a.Tool < b.Tool then return true elseif a.Tool == b.Tool then if bByToolAngle then if a.ToolDir > b.ToolDir then return true elseif a.ToolDir == b.ToolDir then return a.Mch < b.Mch end else return a.Mch < b.Mch end end end end return false end -- test della funzione di ordinamento if EgtGetDebugLevel() >= 3 then EgtOutLog( ' CompareFeatures Test ') local bCompTest = true for i = 1, #TabCut do for j = i + 1, #TabCut do local bComp1 = ToolCompare( TabCut[i], TabCut[j]) local bComp2 = ToolCompare( TabCut[j], TabCut[i]) if bComp1 == bComp2 then bCompTest = false EgtOutLog( string.format( ' ProcId : %d vs %d --> ERROR', TabCut[i].Mch, TabCut[j].Mch)) end end end if bCompTest then EgtOutLog( ' ALL OK') end end table.sort( TabCut, ToolCompare) -- table.sort(TabCut, function(a,b) return a.ToolType < b.ToolType and a.ToolDiam > b.ToolDiam and a.Tool < b.Tool end) local SupportTabCut = {} local nPrevTUUID = 0 local nPrevTDirZ = 1 for i = 1, #TabCut do -- se tuuid uguale al precedente, lo aggiungo alla lista if nPrevTUUID == TabCut[i].Tool and ( not bByToolAngle or nPrevTDirZ == TabCut[i].ToolDir) then table.insert( SupportTabCut, TabCut[i]) -- se tuuid diverso, else -- faccio calcolare la lista PrevMch = SpSorting( SupportTabCut, PrevMch, nType, bOneWay) -- cancello la lista e aggiorno tuuid corrente SupportTabCut = {} nPrevTUUID = TabCut[i].Tool if bByToolAngle then nPrevTDirZ = TabCut[i].ToolDir end table.insert( SupportTabCut, TabCut[i]) end end -- calcolo ultima lista if #SupportTabCut > 0 then PrevMch = SpSorting( SupportTabCut, PrevMch, nType, bOneWay) end else PrevMch = SpSorting( TabCut, PrevMch, nType, bOneWay) end return PrevMch end ------------------------------------------------------------------------------------------------------------- local function SortMachinings( nPhase, PrevMch, nPartId, nPriority) -- Chiodature PrevMch = SortMach( nPhase, PrevMch, nPartId, MCH_OY.MILLING, { 'Nail_'}, true, nil, nil, nil, true, nil, nPriority) -- Tagli con sega a catena che sono rifiniture di spigoli PrevMch = SortMach( nPhase, PrevMch, nPartId, MCH_OY.MORTISING, { 'Csaw_'}, false, nil, nil, nil, nil, nil, nPriority) -- Forature orizzontali con punte lunghe PrevMch = SortMach( nPhase, PrevMch, nPartId, MCH_OY.DRILLING, { 'LhDrill_'}, true, 'MOVE_AFTER', false, true, nil, nil, nPriority) -- Preforature per fori inclinati PrevMch = SortMach( nPhase, PrevMch, nPartId, MCH_OY.POCKETING, { 'PreDrill_'}, true, nil, nil, nil, nil, nil, nPriority) -- Forature e Svuotature PrevMch = SortMach( nPhase, PrevMch, nPartId, MCH_OY.DRILLING + MCH_OY.POCKETING + MCH_OY.MILLING, { 'SideMill_', 'Clean_'}, false, 'MOVE_AFTER', false, false, true, nil, nPriority) -- Forature *** PrevMch = SortMach( nPhase, PrevMch, nPartId, MCH_OY.DRILLING, nil, nil, nil, false, nil, true, nil, nil) -- -- Svuotature *** -- PrevMch = SortMach( nPhase, PrevMch, nPartId, MCH_OY.POCKETING, nil, nil, 'MOVE_AFTER', false) -- -- Fresature che sono rifiniture di spigoli -- PrevMch = SortMach( nPhase, PrevMch, nPartId, MCH_OY.MILLING, { 'Clean_'}, false, 'MOVE_AFTER', false, false, true) -- Lavorazioni di sgrossatura superficie PrevMch = SortMach( nPhase, PrevMch, nPartId, MCH_MY.SURFROUGHING, nil, nil, 'MOVE_AFTER', false, nil, nil, nil, nPriority) -- Lavorazioni di finitura superficie PrevMch = SortMach( nPhase, PrevMch, nPartId, MCH_MY.SURFFINISHING, nil, nil, 'MOVE_AFTER', false, nil, nil, nil, nPriority) -- Fresature per gole PrevMch = SortMach( nPhase, PrevMch, nPartId, MCH_OY.MILLING, { 'Gorge_'}, true, 'MOVE_AFTER', false, nil, nil, nil, nPriority) -- Fresature da fare prima delle SideMill PrevMch = SortMach( nPhase, PrevMch, nPartId, MCH_OY.MILLING, { 'PreSideMill_'}, true, 'MOVE_AFTER', false, false, true, true, nPriority) -- Fresature che sono rifiniture di spigoli PrevMch = SortMach( nPhase, PrevMch, nPartId, MCH_OY.MILLING, { 'SideMill_'}, true, 'MOVE_AFTER', false, false, true, true, nPriority) -- Fresature che sono puliture di spigoli PrevMch = SortMach( nPhase, PrevMch, nPartId, MCH_OY.MILLING, { 'Clean_'}, true, 'MOVE_AFTER', false, false, true, nil, nPriority) -- Tagli per gole PrevMch = SortMach( nPhase, PrevMch, nPartId, MCH_OY.SAWING, { 'GorgeCut_'}, true, nil, nil, nil, nil, nil, nPriority) -- Tagli con lama PrevMch = SortMach( nPhase, PrevMch, nPartId, MCH_OY.SAWING, nil, nil, nil, nil, nil, nil, nil, nPriority) -- Qui rimozione sfridi (se ci sono lavorazioni successive) if not nPriority then -- Fresature da fare prima delle SideMill PrevMch = SortMach( nPhase, PrevMch, nPartId, MCH_OY.MILLING, { 'PreSideMill_'}, true, 'MOVE_AFTER', true, false, true, true) -- Fresature dei lapjoint che necessitano di gorge PrevMch = SortMach( nPhase, PrevMch, nPartId, MCH_OY.MILLING, { 'SideMill_'}, true, 'MOVE_AFTER', true, false, true, true) -- Tagli con sega a catena che vanno fatti dopo i tagli con lama PrevMch = SortMach( nPhase, PrevMch, nPartId, MCH_OY.MORTISING, { 'Csaw_'}, true) -- Fresature (puliture di spigoli) che vanno fatte dopo i tagli con lama PrevMch = SortMach( nPhase, PrevMch, nPartId, MCH_OY.MILLING, nil, nil, 'MOVE_AFTER', true) -- Forature che vanno fatte dopo i tagli con lama PrevMch = SortMach( nPhase, PrevMch, nPartId, MCH_OY.DRILLING, nil, nil, 'MOVE_AFTER', true) -- Svuotature che vanno fatte dopo i tagli con lama PrevMch = SortMach( nPhase, PrevMch, nPartId, MCH_OY.POCKETING, nil, nil, 'MOVE_AFTER', true) -- Lavorazioni di sgrossatura superficie che vanno fatte dopo i tagli con lama PrevMch = SortMach( nPhase, PrevMch, nPartId, MCH_MY.SURFROUGHING, nil, nil, 'MOVE_AFTER', true) -- Lavorazioni di finitura superficie che vanno fatte dopo i tagli con lama PrevMch = SortMach( nPhase, PrevMch, nPartId, MCH_MY.SURFFINISHING, nil, nil, 'MOVE_AFTER', true) end return PrevMch end ------------------------------------------------------------------------------------------------------------- -- setto la rimozione sfridi dopo le lavorazioni di outline local function InsertScrapRemoval( nPhase) local nCurrentOperationId = EgtGetNextOperation( EgtGetPhaseDisposition( nPhase)) local nActiveMachiningId = EgtGetCurrMachining() while nCurrentOperationId do local bIsCurrentOperationOutline = ( EgtGetInfo( nCurrentOperationId or GDB_ID.NULL, 'ISOUTLINE', 'b' ) == true) local bIsCurrentOperationWithPriority = ( ( EgtGetInfo( nCurrentOperationId or GDB_ID.NULL, 'PRIORITY', 'i' ) or 0) > 0) local nNextOperationId = EgtGetNextOperation (nCurrentOperationId) local bIsNextOperationOutline = ( EgtGetInfo( nNextOperationId or GDB_ID.NULL, 'ISOUTLINE', 'b' ) == true) if bIsCurrentOperationOutline and bIsCurrentOperationWithPriority and nNextOperationId and not bIsNextOperationOutline then EgtSetCurrMachining( nNextOperationId) local sMachiningNotes = EgtGetMachiningParam( MCH_MP.USERNOTES) sMachiningNotes = sMachiningNotes .. 'ScrapRemove=1;' EgtSetMachiningParam( MCH_MP.USERNOTES, sMachiningNotes) end nCurrentOperationId = EgtGetNextOperation( nCurrentOperationId) end EgtSetCurrMachining( nActiveMachiningId or GDB_ID.NULL) end ------------------------------------------------------------------------------------------------------------- -- funzione per l'ordinamento delle features in doppio da accoppiare -- ordinate prima in base alla X e poi alla Y local function SortFeaturesForMirror( Proc1, Proc2) -- tolleranza di ricerca local TOL = EgtIf( Proc1.TopologyLongName == 'DRILLING', WD.DOUBLE_HEAD_DRILLING_TOLERANCE or 0.1 , WD.DOUBLE_HEAD_POCKET_TOLERANCE or 0.5) -- recupero i centri dei box lungo X e Y local Proc1X = Proc1.Box:getCenter():getX() local Proc1Y = Proc1.Box:getCenter():getY() local Proc2X = Proc2.Box:getCenter():getX() local Proc2Y = Proc2.Box:getCenter():getY() -- confronto per ordinamento if Proc1X < Proc2X - TOL then return true elseif abs( Proc1X - Proc2X) < TOL then if Proc1Y < Proc2Y - TOL then return true end end end ------------------------------------------------------------------------------------------------------------- -- funzione per l'ordinamento delle operazioni in doppio da accoppiare -- ordinate prima in base alla X e poi alla Y local function SortOperationsForMirror( nOper1, nOper2) -- tolleranza di ricerca local TOL = 0.1 -- recupero il box della prima operazione local nClId1 = EgtGetFirstNameInGroup( nOper1, 'CL') local ptMin1 = EgtGetInfo( nClId1, 'MMIN', 'p') local ptMax1 = EgtGetInfo( nClId1, 'MMAX', 'p') local b3Oper1 = BBox3d( ptMin1, ptMax1) -- recupero il box delle seconda operazione local nClId2 = EgtGetFirstNameInGroup( nOper2, 'CL') local ptMin2 = EgtGetInfo( nClId2, 'MMIN', 'p') local ptMax2 = EgtGetInfo( nClId2, 'MMAX', 'p') local b3Oper2 = BBox3d( ptMin2, ptMax2) -- recupero i centri dei box lungo X e Y local dOper1X = b3Oper1:getCenter():getX() local dOper1Y = b3Oper1:getCenter():getY() local dOper2X = b3Oper2:getCenter():getX() local dOper2Y = b3Oper2:getCenter():getY() -- confronto per ordinamento if dOper1X < dOper2X - TOL then return true elseif abs( dOper1X - dOper2X) < TOL then if dOper1Y < dOper2Y - TOL then return true end end end ------------------------------------------------------------------------------------------------------------- -- Controlla in vProc la presenza di feature da lavorare in doppio e, se trovate, ne setta i parametri local function SetMirroredFeatures( vProc, b3Raw) -- interasse minimo local dMinimumDistanceMirroredFeatures = 780 -- inizializzazione array tasche e forature local vPockets = {} local vDrillings = {} -- raccolgo le feature compatibili con doppio for i = 1, #vProc do local Proc = vProc[i] if Proc.Flg ~= 0 then -- raccolgo le tasche compatibili if WD.DOUBLE_HEAD_POCKET and ( ( Proc.TopologyLongName == 'Rabbet-Through-RightAngles-Parallel-2' and Proc.AffectedFaces.Left and Proc.AffectedFaces.Right) or ( Proc.TopologyLongName == 'Groove-Through-RightAngles-Parallel-3' and ( not Proc.AffectedFaces.Bottom and Proc.AffectedFaces.Left and Proc.AffectedFaces.Right)) or ( Proc.TopologyLongName == 'Groove-Blind-RightAngles-Parallel-3') or ( Proc.TopologyLongName == 'Groove-Blind-RightAngles-Parallel-4') or ( Proc.TopologyLongName == 'Pocket-Blind-RightAngles-Parallel-5' and not Proc.AffectedFaces.Bottom) ) then table.insert( vPockets, Proc) -- raccolgo i fori verticali e aperti verso Z+ elseif WD.DOUBLE_HEAD_DRILLING and Proc.TopologyLongName == 'DRILLING' then -- recupero e verifico la geometria del foro local AuxId = EgtGetInfo( Proc.Id, 'AUXID', 'i') or 0 if AuxId then AuxId = AuxId + Proc.Id end if not AuxId or EgtGetType( AuxId) ~= GDB_TY.CRV_ARC then return false end local vtExtr = EgtCurveExtrusion( AuxId, GDB_RT.GLOB) if Proc.AffectedFaces.Top and AreSameOrOppositeVectorApprox( vtExtr, Z_AX()) then table.insert( vDrillings, Proc) end end end end -- ordinamento delle feature raccolte secondo X e poi Y crescente table.sort( vPockets, SortFeaturesForMirror) table.sort( vDrillings, SortFeaturesForMirror) -- accoppio le tasche local nCurrentPocket = 1 while nCurrentPocket <= #vPockets do local Proc = vPockets[nCurrentPocket] if Proc.Flg ~= 0 then local b3Proc = EgtGetBBoxGlob( Proc.Id, GDB_BB.STANDARD) -- cerco evenutale specchiata local nCurrentMirrorPocket = nCurrentPocket + 1 while nCurrentMirrorPocket <= #vPockets do local ProcMirror = vPockets[nCurrentMirrorPocket] local b3ProcMirror = EgtGetBBoxGlob( ProcMirror.Id, GDB_BB.STANDARD) -- feature non disattivata e diversa da nCurrentPocket local bIsMirrorIdOk = ( Proc.Id ~= ProcMirror.Id and ProcMirror.Flg ~= 0) -- feature mirror della stessa classe topologica local bIsMirrorTopologyOk = ( Proc.TopologyLongName == ProcMirror.TopologyLongName) -- determino se di fianco o in mezzo al singolo pannello local bLapVsTop = Proc.AffectedFaces.Front and ( Proc.TopologyLongName == 'Rabbet-Through-RightAngles-Parallel-2' or Proc.TopologyLongName == 'Groove-Through-RightAngles-Parallel-3' or Proc.TopologyLongName == 'Groove-Blind-RightAngles-Parallel-3' or Proc.TopologyLongName == 'Groove-Blind-RightAngles-Parallel-4' or Proc.TopologyLongName == 'Pocket-Blind-RightAngles-Parallel-5' ) -- se di fianco, determino se è l'ultima parte prima della fine del grezzo local bIsFeatureOnEdge, bIsMirrorFeatureOnEdge = false, false if bLapVsTop then bIsFeatureOnEdge = Proc.DistanceToNearestParts.Front > b3Raw:getDimY() bIsMirrorFeatureOnEdge = ProcMirror.DistanceToNearestParts.Back > b3Raw:getDimY() end -- se di fianco, si sceglie se le feature sono compatibili con il doppio e nel caso che tipo di lavorazione fare -- -1: no doppio, 0: nessuna preferenza, 1: pocket, 2: side (scambio faccia principale) local nDoubleType = 0 local bAllowSideOnMirror = ( ProcMirror.DistanceToRawPart.Back - Proc.DistanceToRawPart.Front < 1 + 10 * GEO.EPS_SMALL) or ( not WD.SIDEMILL_BEFORE and ( not Proc.AffectedFaces.Top or not ProcMirror.AffectedFaces.Top)) if bLapVsTop and ( Proc.AffectedFaces.Top or Proc.AffectedFaces.Bottom) then -- side if bIsFeatureOnEdge and bIsMirrorFeatureOnEdge then if not ( Proc.AffectedFaces.Top and ProcMirror.AffectedFaces.Top) then nDoubleType = 2 end -- no doppio elseif Proc.AffectedFaces.Bottom or ProcMirror.AffectedFaces.Bottom then nDoubleType = -1 -- tasca else nDoubleType = 1 end end -- corrispondenza nella posizione delle feature. Se di fianco il lato master è sempre quello verso l'operatore, se sopra nessun vincolo local bIsMirrorSideOk = ( bLapVsTop and ProcMirror.AffectedFaces.Back and bIsFeatureOnEdge and bIsMirrorFeatureOnEdge and bAllowSideOnMirror) or Proc.TopologyLongName == 'Groove-Through-RightAngles-Parallel-3' and Proc.AffectedFaces.Top and ProcMirror.AffectedFaces.Top or Proc.TopologyLongName == 'Groove-Blind-RightAngles-Parallel-4' and Proc.AffectedFaces.Top and Proc.AffectedFaces.Left and ProcMirror.AffectedFaces.Top and ProcMirror.AffectedFaces.Left or Proc.TopologyLongName == 'Groove-Blind-RightAngles-Parallel-4' and Proc.AffectedFaces.Top and Proc.AffectedFaces.Right and ProcMirror.AffectedFaces.Top and ProcMirror.AffectedFaces.Right or Proc.TopologyLongName == 'Pocket-Blind-RightAngles-Parallel-5' and Proc.AffectedFaces.Top and ProcMirror.AffectedFaces.Top -- box delle stesse dimensioni local bIsMirrorFeatureSameDimension = abs( b3Proc:getDimX() - b3ProcMirror:getDimX()) < ( WD.DOUBLE_HEAD_POCKET_TOLERANCE or 0.5) and abs( b3Proc:getDimY() - b3ProcMirror:getDimY()) < ( WD.DOUBLE_HEAD_POCKET_TOLERANCE or 0.5) and abs( b3Proc:getDimZ() - b3ProcMirror:getDimZ()) < ( WD.DOUBLE_HEAD_POCKET_TOLERANCE or 0.5) -- box allineati in X local bIsMirrorBoxXAligned = abs( Proc.Box:getCenter():getX() - ProcMirror.Box:getCenter():getX()) < ( WD.DOUBLE_HEAD_POCKET_TOLERANCE or 0.5) -- box che non si intersecano local bIsNotMirrorBoxOverlapping = not OverlapsXY( b3Proc, b3ProcMirror) -- distanza minima tra le feature local dYMinDistance = max( b3Proc:getMin():getY(), b3ProcMirror:getMin():getY()) - min( b3Proc:getMax():getY(), b3ProcMirror:getMax():getY()) local bIsMirrorFeatureDistanceOk = dYMinDistance > dMinimumDistanceMirroredFeatures + 10 * GEO.EPS_SMALL -- se tutte vere le condizioni, calcolo i parametri da passare alle lavorazioni if nDoubleType > -1 and bIsMirrorIdOk and bIsMirrorTopologyOk and bIsMirrorSideOk and bIsMirrorFeatureSameDimension and bIsMirrorBoxXAligned and bIsNotMirrorBoxOverlapping and bIsMirrorFeatureDistanceOk then local dYMirrorAx local b3Tab = EgtGetTableArea() local ptOnMirrorAx = ( Proc.Box:getCenter() + ProcMirror.Box:getCenter()) / 2 dYMirrorAx = ptOnMirrorAx:getY() - b3Tab:getMin():getY() local dDeltaZ = ProcMirror.Box:getMax():getZ() - Proc.Box:getMax():getZ() -- forzo side o pocket, se necessario if nDoubleType == 1 then EgtSetInfo( Proc.Id, 'PCKT', 1) EgtSetInfo( ProcMirror.Id, 'PCKT', 1) elseif nDoubleType == 2 then Proc.Stype = 2 ProcMirror.Stype = 2 end -- scrivo i parametri nella lavorazione -- 2: specchiatura in Y Proc.Double = 2 Proc.Mirror = ProcMirror -- posizione Y dell'asse di specchiatura Proc.MirrorAx = dYMirrorAx -- Offset Z tra le feature Proc.MirrorDeltaZ = dDeltaZ -- rimuovo dalla lista le pocket già assegnate local ProcMirrorOldId = ProcMirror.Id table.remove( vPockets, nCurrentPocket) -- avendo rimosso un elemento dall'array, potrebbe essere cambiato l'elemento nCurrentMirrorPocket if nCurrentMirrorPocket > #vPockets or ( vPockets[nCurrentMirrorPocket].Id ~= ProcMirrorOldId) then nCurrentMirrorPocket = nCurrentMirrorPocket - 1 end table.remove( vPockets, nCurrentMirrorPocket) nCurrentPocket = 0 break end nCurrentMirrorPocket = nCurrentMirrorPocket + 1 end end nCurrentPocket = nCurrentPocket + 1 end -- accoppio le forature local nCurrentDrilling = 1 while nCurrentDrilling <= #vDrillings do local Proc = vDrillings[nCurrentDrilling] if Proc.Flg ~= 0 then local b3Proc = EgtGetBBoxGlob( Proc.Id, GDB_BB.STANDARD) -- cerco evenutale specchiata local nCurrentMirrorDrilling = nCurrentDrilling + 1 while nCurrentMirrorDrilling <= #vDrillings do local ProcMirror = vDrillings[nCurrentMirrorDrilling] local b3ProcMirror = EgtGetBBoxGlob( ProcMirror.Id, GDB_BB.STANDARD) -- feature non disattivata e diversa da nCurrentDrilling local bIsMirrorIdOk = ( Proc.Id ~= ProcMirror.Id and ProcMirror.Flg ~= 0) -- box delle stesse dimensioni local bIsMirrorFeatureSameDimension = abs( b3Proc:getDimX() - b3ProcMirror:getDimX()) < ( WD.DOUBLE_HEAD_DRILLING_TOLERANCE or 0.1) and abs( b3Proc:getDimY() - b3ProcMirror:getDimY()) < ( WD.DOUBLE_HEAD_DRILLING_TOLERANCE or 0.1) and abs( b3Proc:getDimZ() - b3ProcMirror:getDimZ()) < ( WD.DOUBLE_HEAD_DRILLING_TOLERANCE or 0.1) -- box allineati in X local bIsMirrorBoxXAligned = abs( Proc.Box:getCenter():getX() - ProcMirror.Box:getCenter():getX()) < ( WD.DOUBLE_HEAD_DRILLING_TOLERANCE or 0.1) -- box che non si intersecano local bIsNotMirrorBoxOverlapping = not OverlapsXY( b3Proc, b3ProcMirror) -- distanza minima tra le feature local dYMinDistance = max( b3Proc:getMin():getY(), b3ProcMirror:getMin():getY()) - min( b3Proc:getMax():getY(), b3ProcMirror:getMax():getY()) local bIsMirrorFeatureDistanceOk = dYMinDistance > dMinimumDistanceMirroredFeatures + 10 * GEO.EPS_SMALL -- se tutte vere le condizioni, calcolo i parametri da passare alle lavorazioni if bIsMirrorIdOk and bIsMirrorFeatureSameDimension and bIsMirrorBoxXAligned and bIsNotMirrorBoxOverlapping and bIsMirrorFeatureDistanceOk then local dYMirrorAx local b3Tab = EgtGetTableArea() local ptOnMirrorAx = ( Proc.Box:getCenter() + ProcMirror.Box:getCenter()) / 2 dYMirrorAx = ptOnMirrorAx:getY() - b3Tab:getMin():getY() -- scrivo i parametri nella lavorazione -- 2: specchiatura in Y Proc.Double = 2 Proc.Mirror = ProcMirror -- posizione Y dell'asse di specchiatura Proc.MirrorAx = dYMirrorAx -- rimuovo dalla lista le forature già assegnate local ProcMirrorOldId = ProcMirror.Id table.remove( vDrillings, nCurrentDrilling) -- avendo rimosso un elemento dall'array, potrebbe essere cambiato l'elemento nCurrentMirrorDrilling if nCurrentMirrorDrilling > #vDrillings or ( vDrillings[nCurrentMirrorDrilling].Id ~= ProcMirrorOldId) then nCurrentMirrorDrilling = nCurrentMirrorDrilling - 1 end table.remove( vDrillings, nCurrentMirrorDrilling) nCurrentDrilling = 0 break end nCurrentMirrorDrilling = nCurrentMirrorDrilling + 1 end end nCurrentDrilling = nCurrentDrilling + 1 end end ------------------------------------------------------------------------------------------------------------- -- verifico e imposto le fresature da specchiare local function SetMirroredOperations() -- interasse minimo local dMinimumDistanceMirroredOperations = 780 -- inzializzazione array local vMillings = {} -- raccolgo le fresature non già fatte in doppio if WD.DOUBLE_HEAD_MILLCORNER then local nOperId = EgtGetNextOperation( EgtGetPhaseDisposition( 1)) while nOperId do EgtSetCurrMachining( nOperId) local sUserNotes = EgtGetMachiningParam( MCH_MP.USERNOTES) local bIsDouble = ( EgtGetValInNotes( sUserNotes, 'DOUBLE', 'i') or 0) > 0 if EgtGetOperationMode( nOperId) and not EgtIsMachiningEmpty( nOperId) and not bIsDouble and EgtGetOperationType( nOperId) == MCH_OY.MILLING then table.insert( vMillings, nOperId) end nOperId = EgtGetNextOperation( nOperId) end end -- ordinamento delle operazioni raccolte secondo X e poi Y crescente table.sort( vMillings, SortOperationsForMirror) -- accoppio le fresature local nCurrentMilling = 1 while nCurrentMilling <= #vMillings do local nOperIdMaster = vMillings[nCurrentMilling] EgtSetCurrMachining( nOperIdMaster) local sMachining = EgtGetMachiningParam( MCH_MP.NAME, 's') local nClId = EgtGetFirstNameInGroup( nOperIdMaster, 'CL') local nPathId = EgtGetFirstInGroup( nClId or GDB_ID.NULL) -- vettore direzione utensile e somma normali facce per lavorazione master local vtTool = EgtGetInfo( nPathId, 'EXTR', 'v') local vtNormSum = EgtGetInfo( nOperIdMaster, 'NORM_SUM', 'v') local ptMin = EgtGetInfo( nClId, 'MMIN', 'p') local ptMax = EgtGetInfo( nClId, 'MMAX', 'p') -- box percorso lavorazione master local b3Operation = BBox3d( ptMin, ptMax) -- lavorazione master adatta alla specchiatura local bIsMachiningOk = WM.IsMachiningOkForDouble( sMachining) if bIsMachiningOk then -- recupero la distanza tra centro di rotazione e punta dell'utensile per aumentare o ridurre l'interasse minimo local dTipToPivot, dTipToPivotDouble = 999, 999 local dToolMasterTotLength, dToolMasterTotLengthDouble = 999, 999 local sToolMasterName = '' if EgtMdbSetCurrMachining( sMachining) then -- recupero l'utensile della lavorazione e il suo doppio sToolMasterName = EgtMdbGetCurrMachiningParam( MCH_MP.TOOL) if EgtTdbSetCurrTool( sToolMasterName or '') then dToolMasterTotLength = EgtTdbGetCurrToolParam( MCH_TP.TOTLEN) or dToolMasterTotLength local sToolDoubleName = EgtTdbGetCurrToolValInNotes( MCH_TP.USERNOTES, 'DOUBLE', 's') if sToolDoubleName and EgtTdbSetCurrTool( sToolDoubleName) then dToolMasterTotLengthDouble = EgtTdbGetCurrToolParam( MCH_TP.TOTLEN) or dToolMasterTotLengthDouble end end end if WD.HEAD_PIVOT_MAIN and WD.HEAD_PIVOT_SECONDARY then dTipToPivot = dToolMasterTotLength + WD.HEAD_PIVOT_MAIN dTipToPivotDouble = dToolMasterTotLengthDouble + WD.HEAD_PIVOT_SECONDARY else local sOut = 'Error : HEAD_PIVOT_MAIN or HEAD_PIVOT_SECONDARY missing in WallData' return false, sOut end -- cerco eventuale specchiata local nCurrentMirrorMilling = nCurrentMilling + 1 while nCurrentMirrorMilling <= #vMillings do local nOperIdMirror = vMillings[nCurrentMirrorMilling] EgtSetCurrMachining( nOperIdMirror) local nClIdMirror = EgtGetFirstNameInGroup( nOperIdMirror, 'CL') local nPathIdMirror = EgtGetFirstInGroup( nClIdMirror or GDB_ID.NULL) -- vettore direzione utensile e somma normali facce per lavorazione mirror local vtToolMirror = EgtGetInfo( nPathIdMirror, 'EXTR', 'v') local vtNormSumMirror = EgtGetInfo( nOperIdMirror, 'NORM_SUM', 'v') local ptMinMirror = EgtGetInfo( nClIdMirror, 'MMIN', 'p') local ptMaxMirror = EgtGetInfo( nClIdMirror, 'MMAX', 'p') -- box percorso lavorazione mirror local b3OperationMirror = BBox3d( ptMinMirror, ptMaxMirror) -- utensile originale lavorazione specchiata local sOriginalMirrorToolName = EgtGetMachiningParam( MCH_MP.TOOL) local bIsOriginalMirrorToolSameSize = WM.IsToolDoubleOk( sToolMasterName, sOriginalMirrorToolName) -- lavorazione mirror adatta alla specchiatura local bIsMirrorMachiningOk = nOperIdMaster ~= nOperIdMirror -- lavorazione master più a sinistra local bIsMirrorSideOk = ( b3OperationMirror:getCenter():getY() - b3Operation:getCenter():getY()) > ( WD.DOUBLE_HEAD_POCKET_TOLERANCE or 0.5) -- box delle stesse dimensioni local bIsMirrorOperationSameDimension = abs( b3Operation:getDimX() - b3OperationMirror:getDimX()) < ( WD.DOUBLE_HEAD_POCKET_TOLERANCE or 0.5) and abs( b3Operation:getDimY() - b3OperationMirror:getDimY()) < ( WD.DOUBLE_HEAD_POCKET_TOLERANCE or 0.5) and abs( b3Operation:getDimZ() - b3OperationMirror:getDimZ()) < ( WD.DOUBLE_HEAD_POCKET_TOLERANCE or 0.5) -- box allineati in X local bIsMirrorBoxXAligned = abs( b3Operation:getCenter():getX() - b3OperationMirror:getCenter():getX()) < ( WD.DOUBLE_HEAD_POCKET_TOLERANCE or 0.5) and abs( b3Operation:getCenter():getX() - b3OperationMirror:getCenter():getX()) < ( WD.DOUBLE_HEAD_POCKET_TOLERANCE or 0.5) -- box che non si intersecano local bIsNotMirrorBoxOverlapping = not OverlapsXY( b3Operation, b3OperationMirror) -- distanza minima tra le feature local dTipToPivotProjectionOnY = dTipToPivot * vtTool:getY() local dTipToPivotProjectionOnYDouble = dTipToPivotDouble * vtToolMirror:getY() local dYMinDistance = max( b3Operation:getMin():getY(), b3OperationMirror:getMin():getY()) - min( b3Operation:getMax():getY(), b3OperationMirror:getMax():getY()) local bIsMirrorOperationDistanceOk = dYMinDistance > dMinimumDistanceMirroredOperations + dTipToPivotProjectionOnY - dTipToPivotProjectionOnYDouble + 10 * GEO.EPS_SMALL -- vettori utensile e somma normali facce specchiati local vtToolMirrored = Vector3d( vtTool) vtToolMirrored:mirror( Y_AX()) local bIsMirrorVectorOk = false if AreSameVectorApprox( vtToolMirrored, vtToolMirror) then if AreSameVectorApprox(vtTool, vtToolMirror) then if vtNormSum and vtNormSumMirror then local vtNormSumMirrored = Vector3d( vtNormSum) vtNormSumMirrored:mirror( Y_AX()) bIsMirrorVectorOk = AreSameVectorApprox( vtNormSumMirrored, vtNormSumMirror) end else bIsMirrorVectorOk = true end end -- se condizioni corrette, scrivo le note e cancello la specchiata if bIsOriginalMirrorToolSameSize and bIsMirrorMachiningOk and bIsMirrorSideOk and bIsMirrorOperationSameDimension and bIsMirrorBoxXAligned and bIsNotMirrorBoxOverlapping and bIsMirrorOperationDistanceOk and bIsMirrorVectorOk then -- calcolo asse di specchiatura local dYMirrorAx local b3Tab = EgtGetTableArea() local ptOnMirrorAx = ( b3Operation:getCenter() + b3OperationMirror:getCenter()) / 2 dYMirrorAx = ptOnMirrorAx:getY() - b3Tab:getMin():getY() EgtSetCurrMachining( nOperIdMaster) -- leggo note esistenti local sUserNotes = EgtGetMachiningParam( MCH_MP.USERNOTES) -- aggiungo note per doppio sUserNotes = EgtSetValInNotes( sUserNotes, 'DOUBLE', 2) sUserNotes = EgtSetValInNotes( sUserNotes, 'MirrorAx', dYMirrorAx) -- scrivo le note della lavorazione EgtSetMachiningParam( MCH_MP.USERNOTES, sUserNotes) -- cancello l'operazione specchiata EgtRemoveOperation( nOperIdMirror) -- rimuovo dalla lista le fresature già assegnate local nCurrentMirrorMillingOldId = nCurrentMirrorMilling table.remove( vMillings, nCurrentMilling) -- avendo rimosso un elemento dall'array, potrebbe essere cambiato l'elemento nCurrentMirrorPocket if nCurrentMirrorMilling > #vMillings or ( vMillings[nCurrentMirrorMilling] ~= nCurrentMirrorMillingOldId) then nCurrentMirrorMilling = nCurrentMirrorMilling - 1 end table.remove( vMillings, nCurrentMirrorMilling) nCurrentMilling = 0 break end nCurrentMirrorMilling = nCurrentMirrorMilling + 1 end end nCurrentMilling = nCurrentMilling + 1 end end ------------------------------------------------------------------------------------------------------------- local function GetFeatureInfoAndDependency( vProc) -- ciclo tutte le feature for i = 1, #vProc do local Proc = vProc[i] -- controllo la feature con tutte le altre per recuperare le dipendenze for j = 1, #vProc do local ProcB = vProc[j] -- se non è la stessa feature if Proc.Id ~= ProcB.Id then -- raggruppamento fori per eventuale Multidrill if WD.USE_MULTI_DRILL and Drill.Identify( Proc) and Proc.Flg ~= 0 and Drill.Identify( ProcB) and ProcB.Flg ~= 0 then if not Proc.OtherGeometries then Proc.OtherGeometries = {} end table.insert( Proc.OtherGeometries, ProcB) ProcB.Flg = 0 ProcB.bGrouped = true end end end end end ------------------------------------------------------------------------------------------------------------- local function CalculateSquaring( sSquaringTool, RawPart, vPart) local dRawPartHeight = RawPart.b3:getDimZ() local bOk local sMsg = '' local SquaringTools = {} local SquaringParameters = {} local b3Squaring SquaringTools = Squaring.GetTools() bOk = Squaring.AreToolsOk( sSquaringTool, SquaringTools, dRawPartHeight) if not bOk then sMsg = 'Squaring failed: cannot find matching tools' return false, {}, nil, sMsg end SquaringParameters, b3Squaring = Squaring.CalculateParameters( sSquaringTool, SquaringTools, RawPart, vPart) if not SquaringParameters or next( SquaringParameters) == nil then sMsg = 'Squaring failed: cannot calculate parameters' return false, {}, nil, sMsg end return true, SquaringParameters, b3Squaring, sMsg end ------------------------------------------------------------------------------------------------------------- local function AddSquaring( SquaringParameters, b3Squaring) local nFirstOperationId = EgtGetNextOperation( EgtGetPhaseDisposition( 1)) local bOk local sMsg = '' local OperationsId = {} bOk, sMsg, OperationsId = Squaring.AddMachinings( SquaringParameters, b3Squaring, nFirstOperationId) if not bOk then for i = 1, #OperationsId do EgtRemoveOperation( i) end sMsg = 'Squaring failed: cannot apply machinings' return false, sMsg end -- se presenti altre lavorazioni, prima di queste va eseguita la pulizia sfridi if nFirstOperationId then Squaring.AddScrapRemoval( nFirstOperationId) end return true, sMsg end ------------------------------------------------------------------------------------------------------------- local function AddFeatureStats( Stats, bOk, sMsg, nCutId, nTaskId) if not bOk then table.insert( Stats, {Err=1, Msg=sMsg, Rot=0, CutId = nCutId, TaskId = nTaskId}) elseif sMsg and #sMsg > 0 then table.insert( Stats, {Err=-1, Msg=sMsg, Rot=0, CutId = nCutId, TaskId = nTaskId}) else table.insert( Stats, {Err=0, Msg='', Rot=0, CutId = nCutId, TaskId = nTaskId}) end return Stats end ------------------------------------------------------------------------------------------------------------- function WallExec.ProcessFeatures() -- errori e stato local nTotErr = 0 local Stats = {} -- recupero il grezzo e il suo box local nRawId = EgtGetFirstRawPart() local b3Raw = EgtGetRawPartBBox( nRawId) -- raccolgo l'elenco dei pezzi local vPart = {} local nPartId = EgtGetFirstPartInRawPart( nRawId) while nPartId do local Ls = EgtGetFirstNameInGroup( nPartId, 'Box') local b3Solid = EgtGetBBoxGlob( Ls or GDB_ID.NULL, GDB_BB.STANDARD) table.insert( vPart, {Id=nPartId, Box=b3Solid}) nPartId = EgtGetNextPartInRawPart( nPartId) end -- calcolo i parametri della squadratura, se richiesta local SquaringParameters = {} local b3Squaring if WD.SQUARING_TYPE and WD.SQUARING_TYPE > 0 then local RawPart = { nId = nRawId, b3 = b3Raw} local bOk, sMsg if type( WD.SQUARING_TOOL) ~= "number" then WD.SQUARING_TOOL = 0 end if WD.SQUARING_TOOL == 0 or WD.SQUARING_TOOL == 1 then bOk, SquaringParameters, b3Squaring, sMsg = CalculateSquaring( 'DoubleDiskmill', RawPart, vPart) end if not bOk and ( WD.SQUARING_TOOL == 0 or WD.SQUARING_TOOL == 2) then -- attualmente non gestito, va modificata la configurazione macchina e non si sa se sia gestito in macchina (PLC) bOk = false sMsg = 'Squaring not possible : double blade + diskmill not supported' --SquaringParameters, b3Squaring, sMsg = CalculateSquaring( 'DoubleDiskmillAndBlade', RawPart) end if not bOk and ( WD.SQUARING_TOOL == 0 or WD.SQUARING_TOOL == 3) then bOk, SquaringParameters, b3Squaring, sMsg = CalculateSquaring( 'DoubleBlade', RawPart, vPart) end if not bOk and ( WD.SQUARING_TOOL == 0 or WD.SQUARING_TOOL == 4) then bOk, SquaringParameters, b3Squaring, sMsg = CalculateSquaring( 'Diskmill', RawPart, vPart) end if not bOk and ( WD.SQUARING_TOOL == 0 or WD.SQUARING_TOOL == 5) then bOk, SquaringParameters, b3Squaring, sMsg = CalculateSquaring( 'Blade', RawPart, vPart) end if not bOk and ( WD.SQUARING_TOOL == 0 or WD.SQUARING_TOOL == 6) then bOk, SquaringParameters, b3Squaring, sMsg = CalculateSquaring( 'DoubleMill', RawPart, vPart) end if not bOk and ( WD.SQUARING_TOOL == 0 or WD.SQUARING_TOOL == 7) then bOk, SquaringParameters, b3Squaring, sMsg = CalculateSquaring( 'Mill', RawPart, vPart) end -- TODO sostituire con funzione if not bOk then nTotErr = nTotErr + 1 table.insert( Stats, {Err=1, Msg=sMsg, Rot=0, CutId=0, TaskId=0}) elseif sMsg and #sMsg > 0 then table.insert( Stats, {Err=-1, Msg=sMsg, Rot=0, CutId=0, TaskId=0}) else table.insert( Stats, {Err=0, Msg='', Rot=0, CutId=0, TaskId=0}) end end -- raccolgo l'elenco delle feature da lavorare, ciclando sui pezzi local vProc = {} for i = 1, #vPart do -- recupero le feature di lavorazione della parete local vPartProc = WallExec.CollectFeatures( vPart[i].Id, b3Raw, b3Squaring) vProc = EgtJoinTables( vProc, vPartProc) end -- recupero informazioni ausiliarie feature e dipendenze tra feature stesse GetFeatureInfoAndDependency( vProc) -- classifico topologicamente le feature ClassifyTopology( vProc, nRawId) -- classifico le feature ClassifyFeatures( vProc, b3Raw) -- recupero l'elenco delle aree vietate alle chiodature local vNLO = WL.GetNailLockOutAreas( vProc) -- Se non ci sono aree vietate alle chiodature, eventuale determinazione delle feature lavorabili in parallelo (implementata nella configurazione macchina) -- si impostano i flag Double (nil/0=no, 1=su X, 2=su Y) e Delta (offset tra T14 e T12 positivo o negativo) if #vNLO == 0 and WD.FindFeaturesInDouble then WD.FindFeaturesInDouble( vProc, b3Raw) end SetMirroredFeatures( vProc, b3Raw) -- debug if EgtGetDebugLevel() >= 1 then PrintFeatures( vProc) end EgtOutLog( ' *** AddMachinings ***', 1) -- inserisco le lavorazioni for i = 1, #vProc do -- creo la lavorazione local Proc = vProc[i] if Proc.Flg ~= 0 then local bOk, sMsg = AddFeatureMachining( Proc, nRawId, b3Raw, vNLO, b3Squaring) if not bOk then nTotErr = nTotErr + 1 end -- output statistiche feature Stats = AddFeatureStats( Stats, bOk, sMsg, Proc.CutId, Proc.TaskId) -- output statistiche in caso di più feature lavorate nella stessa Proc if Proc.OtherGeometries and #Proc.OtherGeometries > 0 then for j = 1, #Proc.OtherGeometries do Stats = AddFeatureStats( Stats, Proc.OtherGeometries[j].bOk, Proc.OtherGeometries[j].sMsg, Proc.OtherGeometries[j].CutId, Proc.OtherGeometries[j].TaskId) if not Proc.OtherGeometries[j].bOk then nTotErr = nTotErr + 1 end end end elseif not Proc.Double and not Proc.LockOut and not Proc.bGrouped then local sMsg = 'Feature not machinable by orientation' table.insert( Stats, {Err=1, Msg=sMsg, Rot=0, CutId=Proc.CutId, TaskId=Proc.TaskId}) end end EgtOutLog( ' *** End AddMachinings ***', 1) -- setto quali sono le lavorazioni da disattivare perchè specchiate di lavorazioni in doppio local vProcToDisable = {} for i = 1, #vProc do local Proc = vProc[i] if Proc.Double and Proc.Double > 0 then for j = 1, #vProc do local ProcMirror = vProc[j] if Proc.Mirror and ( Proc.Mirror.Id == ProcMirror.Id) then -- per i fori l'operazione si basa sulla geometria ausiliaria if Proc.TopologyLongName == 'DRILLING' then local AuxId = EgtGetInfo( ProcMirror.Id, 'AUXID', 'i') or 0 if AuxId then AuxId = AuxId + ProcMirror.Id end table.insert( vProcToDisable, AuxId) -- per tutte le altre lavorazioni si usa la geometria della feature else table.insert( vProcToDisable, ProcMirror.Id) end end end end end -- cancello le operazioni legate a lavorazioni specchiate local nOperId = EgtGetNextOperation( EgtGetPhaseDisposition( 1)) while nOperId do EgtSetCurrMachining( nOperId) local nOperationProcIds = EgtGetMachiningGeometry() local nCurrentOperId = nOperId if #nOperationProcIds > 0 then local nOperationProcId = nOperationProcIds[1][1] for i = 1, #vProcToDisable do local ProcId = vProcToDisable[i] if nOperationProcId == ProcId then nOperId = EgtGetNextOperation( nOperId) EgtRemoveOperation( nCurrentOperId) break end end end if nCurrentOperId == nOperId then nOperId = EgtGetNextOperation( nOperId) end end SetMirroredOperations() -- se macchina pareti if not WD.BEAM_MACHINE then -- riordino le lavorazioni tra tutti i pezzi local nPhase = 1 local PrevMch = EgtGetPhaseDisposition( nPhase) -- abilitazione ordinamento con priorità da btl: 0 = no, 1 = ordine crescente, 2 = ordine decrescente -- le lavorazioni con priorità 0 o senza priorità saranno lasciate per ultime local nGetPriorityFromBtl = WD.BTL_PRIORITY or 0 if nGetPriorityFromBtl > 0 then local vPriority = {} nOperId = EgtGetNextOperation( PrevMch) local nCurrentPriorityId = 1 while nOperId do local nPriority = EgtGetInfo( nOperId or GDB_ID.NULL, 'PRIORITY', 'i') if nPriority and nPriority ~= 0 then vPriority[nCurrentPriorityId] = nPriority nCurrentPriorityId = nCurrentPriorityId + 1 end nOperId = EgtGetNextOperation( nOperId) end -- sorting delle priorità -- ordine crescente if nGetPriorityFromBtl == 1 then table.sort( vPriority) -- ordine decrescente else table.sort( vPriority, function( a, b) return a > b end) end -- riordino le lavorazioni per priorità for i = 1, #vPriority do if i == 1 or ( vPriority[i] ~= vPriority[i - 1]) then PrevMch = SortMachinings( nPhase, PrevMch, nil, vPriority[i]) end end end -- ordinamento standard SortMachinings( nPhase, PrevMch) -- squadratura, se richiesta if SquaringParameters and next( SquaringParameters) ~= nil then local bOk, sMsg = AddSquaring( SquaringParameters, b3Squaring) -- TODO sostituire con funzione if not bOk then nTotErr = nTotErr + 1 table.insert( Stats, {Err=1, Msg=sMsg, Rot=0, CutId=0, TaskId=0}) elseif sMsg and #sMsg > 0 then table.insert( Stats, {Err=-1, Msg=sMsg, Rot=0, CutId=0, TaskId=0}) else table.insert( Stats, {Err=0, Msg='', Rot=0, CutId=0, TaskId=0}) end end -- Aggiornamento finale di tutto if nGetPriorityFromBtl > 0 then InsertScrapRemoval( nPhase) end EgtSetCurrPhase( 1) EgtApplyAllMachinings() -- altrimenti macchina travi else -- dichiaro lavorazione pareti EgtSetInfo( EgtGetCurrMachGroup() or GDB_ID.NULL, 'Wall', '1') -- ordino i pezzi secondo le X decrescenti local function CompareParts( P1, P2) return P1.Box:getCenter():getX() > P2.Box:getCenter():getX() end table.sort( vPart, CompareParts) -- riordino le lavorazioni sui singoli pezzi local nPhase = 1 local PrevMch = EgtGetPhaseDisposition( nPhase) for i = 1, #vPart do PrevMch = SortMachinings( nPhase, PrevMch, vPart[i].Id) end -- aggiungo dati su prima disposizione local nDispId = EgtGetPhaseDisposition( 1) EgtSetInfo( nDispId, 'TYPE', 'START') EgtSetInfo( nDispId, 'ORD', 1) -- aggiungo flag su ultima lavorazione local nLastMchId = EgtGetLastActiveOperation() EgtSetCurrMachining( nLastMchId) EgtSetMachiningParam( MCH_MP.USERNOTES, 'Cut;') -- aggiungo disposizione per lo scarico EgtAddPhase() local nRawId = EgtGetFirstRawPart() EgtKeepRawPart( nRawId, 1) local nDisp2Id = EgtGetPhaseDisposition( 2) EgtSetInfo( nDisp2Id, 'TYPE', 'END') EgtSetInfo( nDisp2Id, 'ORD', 1) -- Aggiornamento finale di tutto EgtSetCurrPhase( 1) local bApplOk, sApplErrors, sApplWarns = EgtApplyAllMachinings() if not bApplOk then nTotErr = nTotErr + 1 table.insert( Stats, {Err = 1, Msg=sApplErrors, Rot=0, CutId=0, TaskId=0}) elseif sApplWarns and #sApplWarns > 0 then -- non interessano perchè riguardano lo scarico delle travi end end -- restituzione risultati return ( nTotErr == 0), Stats end ------------------------------------------------------------------------------------------------------------- return WallExec