b1d113b63f
- aggiunta lettura thickness dalle info del part.
866 lines
33 KiB
Lua
866 lines
33 KiB
Lua
--24/10/09 ASSEMBLER : File per gestire le operazioni su Part nel VeinMatch3D
|
|
-- creato da D.B.
|
|
|
|
-- Intestazioni
|
|
require( 'EgtBase')
|
|
_ENV = EgtProtectGlobal()
|
|
EgtEnableDebug( false)
|
|
|
|
-- mi preparo a ricevere argomenti
|
|
local arg =...
|
|
|
|
-- variabile globale
|
|
-- setto i valori standard nella tabella di comunicazione col programma
|
|
local ASS = {}
|
|
|
|
-- const da settare al caricamento del file
|
|
ASS.nMaxStory = 100 -- lunghezza massima della storia
|
|
ASS.bActiveHist = false -- flag che indica se attivare il salvataggio delle operazioni ( per poter usare undo e redo)
|
|
|
|
-- input
|
|
ASS.nPartId = GDB_ID.NULL -- part da accoppiare
|
|
ASS.nIdFirstLine = GDB_ID.NULL -- edge del part con cui eseguire l'accoppiamento
|
|
ASS.nIdSecondLine = GDB_ID.NULL -- edge di destinazione dell'accoppiamento
|
|
ASS.nIdAxs = GDB_ID.NULL -- asse con cui eseguire la rotazione( è una CRV_LINE)
|
|
ASS.dAng = 0 -- angolo per la rotazione
|
|
ASS.vtAx = V_NULL() -- asse di rotazione
|
|
ASS.ptAx = ORIG() -- punto per l'asse di rotazione
|
|
ASS.vtMove = V_NULL() -- vettore di traslazione
|
|
ASS.vtFirstNorm = V_NULL() -- normale della superficie del part da accoppiare
|
|
ASS.vtSecondNorm = V_NULL() -- normale di destinazione dell'accoppiamento
|
|
ASS.nVeinCtx = GDB_ID.NULL -- indice del contesto del VeinMatch3D
|
|
ASS.nOption = 0 -- intero che indica l'opzione di pairing scelta
|
|
ASS.nGroup = 0 -- intero che indica il numero del gruppo da aggiornare per il part nPartToPair
|
|
ASS.nPartToPair = GDB_ID.NULL -- id del part di cui si vogliono aggiornare le info di pairing
|
|
ASS.sPairList = "" -- lista di accoppiamento
|
|
ASS.bSaveHist = true -- flag che indica se salvare nella storia l'operazione eseguita
|
|
ASS.bSaveTemp = false -- flag che indica se salvare nella storia temporanea l'operazione eseguita
|
|
ASS.nTempToSave = GDB_ID.NULL -- posizione nel vettore temporaneo della trasformazione da salvare
|
|
ASS.nTypeTrf = GDB_ID.NULL -- tipo della trasformazione da aggiungere alla storia ( 0: traslazione; 1: rotazione; 2: accoppiamento/disaccoppiamento; 3: import)
|
|
|
|
-- output
|
|
ASS.ERR = 0 -- -1 : valori non settati o sbagliati, -2 : operazione impossibile(es: fuori dall'array), -3 : manca qualcosa nel database (info, pezzi, layer..)
|
|
ASS.nTransf = 0 -- numero di operazioni eseguite / numero di operazione nella tabella della storia, aggiornato dopo un Undo o un Redo
|
|
ASS.sFunc = "" -- funzione in cui è stato eseguito il return a seguito di un errore
|
|
ASS.bRedoPossible = false
|
|
|
|
|
|
-- variabili locali
|
|
local vPaired = {}
|
|
local ptPair = ORIG()
|
|
local GroupCounter = 1 -- ogni volta che viene usato va incrementato di 1
|
|
local nTernaId = GDB_ID.NULL
|
|
local ptOrigId = ORIG()
|
|
|
|
-- gestione della storia
|
|
-- tbEvent = { Id, vtDir, ptAx, dAngOrId, bWPaired, lPair} -- solo move e rotate possono essere effettuati su pezzi singoli, anche se accoppiati
|
|
local Time = 0
|
|
local tbStory = {}
|
|
-- gestione della storia temporanea
|
|
local TempTime = 0
|
|
local tbTempStory = {}
|
|
|
|
-- leggo gli argomenti passati dalla chiamata del file
|
|
local bAutoRun = false
|
|
if arg then
|
|
ASS.nVeinCtx = arg.nVeinCtx
|
|
bAutoRun = arg.AutoRun
|
|
end
|
|
|
|
-- rendo la variabile globale
|
|
_G.ASS = ASS
|
|
|
|
function ResetASS()
|
|
-- input
|
|
ASS.nPartId = GDB_ID.NULL
|
|
ASS.nIdFirstLine = GDB_ID.NULL
|
|
ASS.nIdSecondLine = GDB_ID.NULL
|
|
ASS.nIdAxs = GDB_ID.NULL
|
|
ASS.dAng = 0
|
|
ASS.vtAx = V_NULL()
|
|
ASS.ptAx = ORIG()
|
|
ASS.vtMove = V_NULL()
|
|
ASS.vtFirstNorm = V_NULL()
|
|
ASS.vtSecondNorm = V_NULL()
|
|
ASS.nVeinCtx = GDB_ID.NULL
|
|
ASS.nOption = 0
|
|
ASS.nGroup = 0
|
|
ASS.nPartToPair = GDB_ID.NULL
|
|
ASS.sPairList = ""
|
|
ASS.nTempToSave = GDB_ID.NULL
|
|
ASS.nTypeTrf = GDB_ID.NULL
|
|
-- output
|
|
ASS.ERR = GDB_ID.NULL
|
|
ASS.nTransf = 0
|
|
end
|
|
|
|
local function FromStringToINTVECTOR( sIntVectorString)
|
|
local vInt = {}
|
|
local vsInt = EgtSplitString(sIntVectorString,",")
|
|
for sInt in vsInt do
|
|
table.insert( vInt, EgtEvalNumExpr(sInt))
|
|
end
|
|
return vInt
|
|
end
|
|
|
|
local function AddEvent( tbEvent)
|
|
if not tbEvent.Id then do return end end
|
|
-- se ho già raggiunto il massimo della storia salvabile allora elimino il primo elemento
|
|
if Time == ASS.nMaxStory then table.remove(tbStory,1) end
|
|
-- se ero avevo già fatto degli undo allora devo cancellare la storia che sto per sovrascrivere
|
|
if Time < #tbStory then
|
|
local nLastEvent = #tbStory
|
|
for nItTime = Time, nLastEvent, 1 do
|
|
table.remove(tbStory, Time + 1)
|
|
end
|
|
end
|
|
if Time < ASS.nMaxStory then Time = Time + 1 end
|
|
table.insert( tbStory, tbEvent)
|
|
return true
|
|
end
|
|
|
|
local function AddTempEvent( tbEvent)
|
|
-- se ho già raggiunto il massimo della storia salvabile allora elimino il primo elemento
|
|
if TempTime == ASS.nMaxStory then table.remove(tbTempStory,1) end
|
|
-- se ero avevo già fatto degli undo allora devo cancellare la storia che sto per sovrascrivere
|
|
if TempTime < #tbTempStory then
|
|
local nLastEvent = #tbTempStory
|
|
for nItTime = TempTime, nLastEvent, 1 do
|
|
table.remove(tbTempStory, TempTime + 1)
|
|
end
|
|
end
|
|
if TempTime < ASS.nMaxStory then TempTime = TempTime + 1 end
|
|
table.insert( tbTempStory, tbEvent)
|
|
end
|
|
|
|
function ASS.AddEvent()
|
|
ASS.sFunc = "ASS.AddEvent"
|
|
local tbEvent = {}
|
|
local a = tbEvent.nId
|
|
if ASS.nTypeTrf == 0 then -- traslazione
|
|
if ASS.nPartId == GDB_ID.NULL or AreSameVectorApprox(ASS.vtMove, V_NULL()) then
|
|
ASS.ERR = -1
|
|
return false
|
|
end
|
|
tbEvent = {Id = ASS.nPartId, vtDir = ASS.vtMove, ptAx = ORIG(), dAngOrId = 0, bWPaired = true, lPair = {}}
|
|
elseif ASS.nTypeTrf == 1 then -- rotazione
|
|
if ASS.nPartId == GDB_ID.NULL or AreSameVectorApprox(ASS.vtAx, V_NULL()) or ASS.dAng == nil then
|
|
ASS.ERR = -1
|
|
return false
|
|
end
|
|
tbEvent = {Id = ASS.nPartId, vtDir = ASS.vtAx, ptAx = ASS.ptAx, dAngOrId = ASS.dAng, bWPaired = true, lPair = {}}
|
|
elseif ASS.nTypeTrf == 2 then -- accoppiamento
|
|
if ASS.nPartId == GDB_ID.NULL or ASS.nPartToPair == GDB_ID.NULL then
|
|
ASS.ERR = -1
|
|
return false
|
|
end
|
|
tbEvent = {Id = ASS.nPartId, vtDir = V_NULL(), ptAx = ORIG(), dAngOrId = ASS.nPartToPair, bWPaired = true, lPair = FromStringToINTVECTOR(ASS.sPairList)}
|
|
elseif ASS.nTypeTrf == 3 then -- importazione oggetto
|
|
if ASS.nPartId == GDB_ID.NULL then
|
|
ASS.ERR = -1
|
|
return false
|
|
end
|
|
tbEvent = {Id = ASS.nPartId, vtDir = V_NULL(), ptAx = ORIG(), dAngOrId = 0, bWPaired = true, lPair = {}}
|
|
else
|
|
do return false end
|
|
end
|
|
local bOk = false
|
|
if AddEvent( tbEvent) then bOk = true end
|
|
ASS.nTransf = Time
|
|
return bOk
|
|
end
|
|
|
|
function ASS.AddEventFromTemp()
|
|
ASS.sFunc = "AddEventFromTemp"
|
|
if abs(ASS.nTempToSave) > #tbTempStory then
|
|
ASS.ERR = -2
|
|
return false
|
|
end
|
|
if ASS.nTempToSave < 0 then ASS.nTempToSave = #tbTempStory + 1 + ASS.nTempToSave end
|
|
AddEvent( tbTempStory[ASS.nTempToSave])
|
|
return true
|
|
end
|
|
|
|
function ASS.ResetStory()
|
|
tbStory = {}
|
|
Time = 0
|
|
return true
|
|
end
|
|
|
|
function ASS.ResetTempStory()
|
|
tbTempStory = {}
|
|
TempTime = 0
|
|
return true
|
|
end
|
|
|
|
local function ApplyTransf( tbEvent, bForward, bSave, bTemp)
|
|
-- tbEvent = { nId, vtDir, ptAx, dAngOrId, bWPaired, lPair}
|
|
if tbEvent == nil or bForward == nil or bSave == nil or bTemp == nil or
|
|
tbEvent.Id == GDB_ID.NULL or tbEvent.Id == nil or tbEvent.vtDir == nil or
|
|
tbEvent.ptAx == nil or tbEvent.dAngOrId == nil then
|
|
ASS.ERR = -1
|
|
return false
|
|
end
|
|
|
|
ASS.bSaveHist = bSave
|
|
-- se ho una traslazione o una rotazione applico la trasformazione a tutto l'accoppiato
|
|
if not AreSameVectorExact(V_NULL(), tbEvent.vtDir) then
|
|
-- se è un undo allora inverto il vettore
|
|
if not bForward then tbEvent.vtDir = Vector3d(tbEvent.vtDir) * (-1) end
|
|
if tbEvent.dAngOrId == 0 then
|
|
ASS.nTypeTrf = 0 -- setto il tipo di trasformazione che sto facendo (in caso serva al chiamante)
|
|
ASS.nPartId = tbEvent.Id
|
|
ASS.vtMove = tbEvent.vtDir
|
|
ASS.bSaveHist = bSave
|
|
ASS.bSaveTemp = bTemp
|
|
if tbEvent.bWPaired then
|
|
ASS.Move()
|
|
else
|
|
ASS.MoveSingle()
|
|
end
|
|
elseif not AreSameVectorExact(V_NULL(), tbEvent.vtDir) then
|
|
ASS.nTypeTrf = 1 -- setto il tipo di trasformazione che sto facendo (in caso serva al chiamante)
|
|
ASS.nPartId = tbEvent.Id
|
|
ASS.vtAx = tbEvent.vtDir
|
|
ASS.ptAx = tbEvent.ptAx
|
|
ASS.dAng = tbEvent.dAngOrId
|
|
ASS.bSaveHist = bSave
|
|
ASS.bSaveTemp = bTemp
|
|
if tbEvent.bWPaired then
|
|
ASS.Rotate()
|
|
else
|
|
ASS.RotateSingle()
|
|
end
|
|
end
|
|
elseif tbEvent.dAngOrId == 0 then
|
|
ASS.nTypeTrf = 3 -- setto il tipo di trasformazione che sto facendo (in caso serva al chiamante)
|
|
-- se non sono definiti né l'asse né l'angolo/id di accoppiamento allora è un import
|
|
if not bForward then
|
|
-- se sto facendo un undo allora elimino il part e il SOLID importati
|
|
local nChild = EgtGetInfo(tbEvent.Id, "Child", "i")
|
|
EgtErase(nChild)
|
|
EgtErase(tbEvent.Id)
|
|
end
|
|
-- se sto facendo un redo, non faccio nulla
|
|
elseif bForward then
|
|
ASS.nTypeTrf = 2 -- setto il tipo di trasformazione che sto facendo (in caso serva al chiamante)
|
|
-- sto applicando un accoppiamento
|
|
-- aggiorno le info dei due part e di tutti i loro associati
|
|
ASS.nPartId = tbEvent.Id
|
|
ASS.nPartToPair = tbEvent.dAngOrId
|
|
if not ASS.UpdatePairInfo() then return false end
|
|
else
|
|
ASS.nTypeTrf = 2 -- setto il tipo di trasformazione che sto facendo (in caso serva al chiamante)
|
|
-- sto applicando un disaccoppiamento
|
|
if #tbEvent.lPair == 1 then
|
|
ASS.nPartId = tbEvent.dAngOrId
|
|
if not ASS.Unpair() then ASS.ERR = -2 return false end
|
|
else
|
|
-- alla lista dei paired del part selezionato per essere accoppiato tolgo tutti i part che ho aggiunto( part destinatario e suoi eventuali accoppiati)
|
|
for n, nIdToUnpair in pairs(tbEvent.lPair) do
|
|
-- rimuovo anche le info
|
|
ASS.nPartId = tbEvent.Id
|
|
ASS.nPartToPair = nIdToUnpair
|
|
if not ASS.RemovePairInfo() then return false end
|
|
end
|
|
local sPairedNew1 = EgtGetInfo( tbEvent.Id, "Paired", "s")
|
|
local lPairNew1 = EgtGetInfo(tbEvent.Id, "Paired", "vi")
|
|
if lPairNew1 == nil or sPairedNew1 == nil then ASS.ERR = -3 return false end
|
|
-- copio la nuova lista dei paired in tutti gli altri paired
|
|
for n, nIdPaired in pairs(lPairNew1) do
|
|
ASS.nPartId = nIdPaired
|
|
ASS.sPairList = sPairedNew1
|
|
ASS.nGroup = -1
|
|
ASS.UpdatePairInfoSingle()
|
|
end
|
|
-- se il part corrente era già accoppiato con altri pezzi allora lascio a quell'accoppiato il numero del gruppo che sto spezzando
|
|
-- e darò un nuovo numero al destinatario e al suo accoppiato
|
|
local bCurrWasSingle = false
|
|
if #lPairNew1 == 1 then
|
|
bCurrWasSingle = true
|
|
ASS.sPairList = sPairedNew1
|
|
ASS.nGroup = 0
|
|
ASS.UpdatePairInfoSingle()
|
|
end
|
|
-- alla lista del part destinatario dell'accoppiamento tolgo tutti i part che gli ho aggiunto
|
|
for n, nIdPaired in pairs(lPairNew1) do
|
|
ASS.nPartId = tbEvent.dAngOrId
|
|
ASS.nPartToPair = nIdPaired
|
|
if not ASS.RemovePairInfo() then return false end
|
|
end
|
|
-- assegno un nuovo numero di gruppo al gruppo che ho creato
|
|
local sPairedNew2 = EgtGetInfo( tbEvent.dAngOrId, "Paired", "s")
|
|
local lPairNew2 = EgtGetInfo( tbEvent.dAngOrId, "Paired", "vi")
|
|
local nGroupCode = -1
|
|
-- se il curr era single allora mantengo il numero di gruppo per l'assemblato del destinatario
|
|
if not bCurrWasSingle then
|
|
-- il curr non era single, quindi a lui resta il numero di gruppo
|
|
if #lPairNew2 > 1 then
|
|
-- anche il destinatario non era single, quindi serve un nuovo numero di gruppo
|
|
nGroupCode = GroupCounter
|
|
GroupCounter = GroupCounter + 1
|
|
else
|
|
-- il destinatario era single, quindi rimetto semplicemente a 0 il numero di gruppo
|
|
nGroupCode = 0
|
|
end
|
|
end
|
|
-- aggiorno la lista dei part che erano già paired con il part selezionato
|
|
for n, nIdPaired in pairs(lPairNew2) do
|
|
ASS.nPartId = nIdPaired
|
|
ASS.sPairList = sPairedNew2
|
|
ASS.nGroup = nGroupCode
|
|
ASS.UpdatePairInfoSingle()
|
|
end
|
|
end
|
|
end
|
|
return true
|
|
end
|
|
|
|
function ASS.Undo()
|
|
ASS.sFunc = "ASS.Undo"
|
|
if Time == 0 then do return end end
|
|
if Time > #tbStory then Time = #tbStory end
|
|
ApplyTransf(tbStory[Time], false, false, false)
|
|
Time = Time - 1
|
|
ASS.nTransf = Time
|
|
ASS.bRedoPossible = true
|
|
return true
|
|
end
|
|
|
|
function ASS.Redo()
|
|
ASS.sFunc = "ASS.Redo"
|
|
if Time >= #tbStory then ASS.bRedoPossible = false return false end
|
|
if Time == ASS.nMaxStory then ASS.bRedoPossible = false return false end
|
|
ApplyTransf(tbStory[Time + 1], true, false, false)
|
|
Time = Time + 1
|
|
ASS.nTransf = Time
|
|
if Time >= #tbStory then ASS.bRedoPossible = false end
|
|
if Time == ASS.nMaxStory then ASS.bRedoPossible = false end
|
|
return true
|
|
end
|
|
|
|
function ASS.UndoTemp()
|
|
ASS.sFunc = "ASS.UndoTemp"
|
|
if TempTime == 0 then do return end end
|
|
if TempTime > ASS.nMaxStory then TempTime = ASS.nMaxStory end
|
|
ApplyTransf(tbTempStory[TempTime], false, false, false)
|
|
TempTime = TempTime - 1
|
|
end
|
|
|
|
function ASS.RedoTemp()
|
|
ASS.sFunc = "ASS.RedoTemp"
|
|
if TempTime >= #tbTempStory then do return end end
|
|
if TempTime == ASS.nMaxStory then do return end end
|
|
ApplyTransf(tbTempStory[TempTime + 1], true, false, false)
|
|
TempTime = TempTime + 1
|
|
end
|
|
|
|
local function RetrieveSurfNorm( nPartId)
|
|
-- recupero la normale della faccia principale del Part a partire dall'id del Part
|
|
local nLayR = EgtGetFirstNameInGroup( nPartId, "Region")
|
|
local nId = EgtGetFirstInGroup(nLayR)
|
|
local nSurfId = GDB_ID.NULL
|
|
while nId ~= GDB_ID.NULL do
|
|
if EgtGetType( nId) == GDB_TY.SRF_FRGN then
|
|
nSurfId = nId
|
|
break
|
|
end
|
|
nId = EgtGetNext(nId)
|
|
end
|
|
local vtNorm = EgtSurfFrNormVersor(nSurfId, GDB_RT.GLOB)
|
|
return vtNorm
|
|
end
|
|
|
|
local function RetrieveParent( nId)
|
|
-- recupero il parent dell'oggetto nId
|
|
-- se è un oggetto all'interno contenuto in un Part che si chiama SOLID allora recupero il Part
|
|
nId = EgtGetParent(EgtGetParent(nId))
|
|
local sName = ""
|
|
sName = EgtGetName(nId, "s")
|
|
if sName == "SOLID" then
|
|
nId = EgtGetInfo(nId, "Parent","i")
|
|
end
|
|
return nId
|
|
end
|
|
|
|
local function RetrievePart( nId)
|
|
local sName = EgtGetName(nId)
|
|
local nParent = nId
|
|
if sName == "SOLID" then
|
|
nParent = EgtGetInfo(nId, "Parent","i")
|
|
end
|
|
return nParent
|
|
end
|
|
|
|
local function RetrievePaired()
|
|
vPaired = EgtGetInfo( RetrievePart(ASS.nPartId), "Paired", "vi")
|
|
if vPaired == nil then ASS.ERR = -3 return false end
|
|
return true
|
|
end
|
|
|
|
local function RetrieveLocAxis()
|
|
-- recupero l'id della terna, se esiste
|
|
nTernaId = GDB_ID.NULL
|
|
nTernaId = EgtGetInfo( ASS.nPartId, "Terna", "i")
|
|
if not nTernaId then
|
|
return false
|
|
else
|
|
return true
|
|
end
|
|
end
|
|
|
|
local function RetrieveLocOrig()
|
|
-- recupero l'origine della terna
|
|
if nTernaId == GDB_ID.NULL then do return end end
|
|
local LayOrig = EgtGetFirstNameInGroup(nTernaId, "ORIG")
|
|
ptOrigId = EgtGetFirstNameInGroup(LayOrig, "ORIG")
|
|
end
|
|
|
|
function ASS.Move()
|
|
ASS.sFunc = "ASS.Move"
|
|
if AreSameVectorApprox(ASS.vtMove, V_NULL()) then return true end
|
|
if ASS.nPartId == nil or ASS.nPartId == GDB_ID.NULL or ASS.vtMove == nil then ASS.ERR = -1 return false end
|
|
-- recupero la lista degli accoppiati
|
|
if not RetrievePaired() then return false end
|
|
if RetrieveLocAxis() then
|
|
EgtMove(nTernaId, ASS.vtMove, GDB_RT.GLOB)
|
|
end
|
|
-- muovo il pezzo e tutti i suoi accoppiati
|
|
for n, nId in pairs(vPaired) do
|
|
EgtMove( nId, ASS.vtMove, GDB_RT.GLOB)
|
|
local nChild = EgtGetInfo( nId, "Child", "i")
|
|
EgtMove( nChild, ASS.vtMove, GDB_RT.GLOB)
|
|
end
|
|
-- se richiesto salvo la storia
|
|
if ASS.bActiveHist then
|
|
local tbEv = {Id = ASS.nPartId, vtDir = ASS.vtMove, ptAx = ORIG(), dAngOrId = 0, bWPaired = true, lPair = {}}
|
|
if ASS.bSaveHist then AddEvent( tbEv) end
|
|
if ASS.bSaveTemp then AddTempEvent( tbEv) end
|
|
end
|
|
return true
|
|
end
|
|
|
|
function ASS.MoveSingle()
|
|
ASS.sFunc = "ASS.MoveSingle"
|
|
if AreSameVectorApprox(ASS.vtMove, V_NULL()) then return true end
|
|
if ASS.nPartId == nil or ASS.nPartId == GDB_ID.NULL or ASS.vtMove == nil then ASS.ERR = -1 return false end
|
|
-- muovo il pezzo MA NON i suoi accoppiati
|
|
EgtMove( ASS.nPartId, ASS.vtMove, GDB_RT.GLOB)
|
|
local nChild = EgtGetInfo( ASS.nPartId, "Child", "i")
|
|
EgtMove( nChild, ASS.vtMove, GDB_RT.GLOB)
|
|
if RetrieveLocAxis() then
|
|
EgtMove(nTernaId, ASS.vtMove, GDB_RT.GLOB)
|
|
end
|
|
-- se richiesto salvo la storia
|
|
if ASS.bActiveHist then
|
|
local tbEv = {Id = ASS.nPartId, vtDir = ASS.vtMove, ptAx = ORIG(), dAngOrId = 0, bWPaired = false, lPair = {}}
|
|
if ASS.bSaveHist then AddEvent( tbEv) end
|
|
if ASS.bSaveTemp then AddTempEvent( tbEv) end
|
|
end
|
|
return true
|
|
end
|
|
|
|
function ASS.Rotate()
|
|
ASS.sFunc = "ASS.Rotate"
|
|
if ASS.dAng == 0 then return true end
|
|
if ASS.nPartId == nil or ASS.nPartId == GDB_ID.NULL or ASS.ptAx == nil or
|
|
AreSameVectorApprox( ASS.vtAx, V_NULL()) then ASS.ERR = -1 return false end
|
|
-- recupero la lista degli accoppiati
|
|
if not RetrievePaired() then return false end
|
|
if RetrieveLocAxis() then
|
|
RetrieveLocOrig()
|
|
-- muovo la terna
|
|
local ptBefore = EgtSP(ptOrigId, GDB_RT.GLOB)
|
|
local ptAfterId = EgtCopyGlob(ptOrigId, nTernaId)
|
|
EgtRotate( ptAfterId, ASS.ptAx, ASS.vtAx, ASS.dAng, GDB_RT.GLOB, GDB_RT.GLOB)
|
|
local vtMove = Point3d(EgtSP( ptAfterId, GDB_RT.GLOB)) - Point3d(ptBefore)
|
|
EgtMove( nTernaId, vtMove, GDB_RT.GLOB)
|
|
EgtErase(ptAfterId)
|
|
end
|
|
-- ruoto il pezzo e tutti i suoi accoppiati
|
|
for n, nId in pairs(vPaired) do
|
|
EgtRotate( nId, ASS.ptAx, ASS.vtAx, ASS.dAng, GDB_RT.GLOB)
|
|
local nChild = EgtGetInfo( nId, "Child","i")
|
|
EgtRotate( nChild, ASS.ptAx, ASS.vtAx, ASS.dAng, GDB_RT.GLOB)
|
|
end
|
|
-- se richiesto salvo la storia
|
|
if ASS.bActiveHist then
|
|
local tbEv = {Id = ASS.nPartId, vtDir = ASS.vtAx, ptAx = ASS.ptAx, dAngOrId = ASS.dAng, bWPaired = true, lPair = {}}
|
|
if ASS.bSaveHist then AddEvent( tbEv) end
|
|
if ASS.bSaveTemp then AddTempEvent( tbEv) end
|
|
end
|
|
return true
|
|
end
|
|
|
|
function ASS.RotateSingle()
|
|
ASS.sFunc = "ASS.RotateSingle"
|
|
if ASS.dAng == 0 then return true end
|
|
if RetrieveLocAxis() then
|
|
RetrieveLocOrig()
|
|
-- muovo la terna
|
|
local ptBefore = EgtSP(ptOrigId, GDB_RT.GLOB)
|
|
local ptAfterId = EgtCopy(ptOrigId, nTernaId)
|
|
EgtRotate( ptAfterId, ASS.ptAx, ASS.vtAx, ASS.dAng, GDB_RT.GLOB)
|
|
local vtMove = Point3d(EgtSP( ptAfterId, GDB_RT.GLOB)) - Point3d(ptBefore)
|
|
EgtMove( nTernaId, vtMove, GDB_RT.GLOB)
|
|
EgtErase(ptAfterId)
|
|
end
|
|
-- ruoto il pezzo MA NON i suoi accoppiati
|
|
EgtRotate( ASS.nPartId, ASS.ptAx, ASS.vtAx, ASS.dAng, GDB_RT.GLOB)
|
|
local nChild = EgtGetInfo( ASS.nPartId, "Child","i")
|
|
EgtRotate( nChild, ASS.ptAx, ASS.vtAx, ASS.dAng, GDB_RT.GLOB)
|
|
-- se richiesto salvo la storia
|
|
if ASS.bActiveHist then
|
|
local tbEv = {Id = ASS.nPartId, vtDir = ASS.vtMove, ptAx = ASS.ptAx, dAngOrId = ASS.dAng, bWPaired = false, lPair = {}}
|
|
if ASS.bSaveHist then AddEvent( tbEv) end
|
|
if ASS.bSaveTemp then AddTempEvent( tbEv) end
|
|
end
|
|
return true
|
|
end
|
|
|
|
function ASS.FlipParallel()
|
|
ASS.sFunc = "ASS.FlipParallel"
|
|
local vtNorm = V_NULL()
|
|
-- recupero la normale della superficie originale
|
|
vtNorm = RetrieveSurfNorm( RetrievePart(ASS.nPartId))
|
|
if vtNorm == nil or AreSameVectorApprox(vtNorm, V_NULL()) then ASS.ERR = -3 return false end
|
|
ASS.ptAx = ptPair
|
|
ASS.vtAx = vtNorm
|
|
ASS.dAng = 180
|
|
if not ASS.Rotate() or not ASS.EdgePair() then return false end
|
|
return true
|
|
end
|
|
|
|
function ASS.FlipPerpendicular()
|
|
ASS.sFunc = "ASS.FlipPerpendicular"
|
|
-- recupero la normale della faccia principale del part del secondo part
|
|
local vtNorm = V_NULL()
|
|
vtNorm = RetrieveSurfNorm( RetrieveParent(ASS.nIdSecondLine))
|
|
if vtNorm == nil or AreSameVectorApprox(vtNorm, V_NULL()) then ASS.ERR = -3 return false end
|
|
local vtStartDir = EgtSV(ASS.nIdSecondLine, GDB_RT.GLOB)
|
|
local vtAx = vtNorm ^ vtStartDir
|
|
if vtAx == nil or AreSameVectorApprox(vtAx, V_NULL()) then ASS.ERR = -2 return false end
|
|
-- recupero il punto usato per l'accoppiamento
|
|
if ptPair == nil then ASS.ERR = -2 return false end
|
|
ASS.ptAx = ptPair
|
|
ASS.vtAx = vtAx
|
|
ASS.dAng = 180
|
|
if not ASS.Rotate() or not ASS.EdgePair() then return false end
|
|
return true
|
|
end
|
|
|
|
function ASS.FacePair()
|
|
ASS.sFunc = "ASS.FacePair"
|
|
-- setto e controllo
|
|
EgtSetContext(ASS.nVeinCtx)
|
|
if ASS.nPartId == GDB_ID.NULL then ASS.ERR = -1 return false end
|
|
if ASS.nIdSecondLine == GDB_ID.NULL then ASS.ERR = -1 return false end
|
|
-- recupero gli id dei Part
|
|
local nIdToPair = RetrieveParent(ASS.nIdSecondLine)
|
|
ASS.nPartId = RetrievePart(ASS.nPartId)
|
|
local ptAx = EgtSP(ASS.nIdSecondLine, GDB_RT.GLOB)
|
|
local vtAx = Vector3d(EgtSV(ASS.nIdSecondLine, GDB_RT.GLOB))
|
|
local vtNorm1 = Vector3d(ASS.vtFirstNorm):isZero() and Vector3d(RetrieveSurfNorm(ASS.nPartId)) or Vector3d(ASS.vtFirstNorm)
|
|
local vtNorm2 = Vector3d(ASS.vtSecondNorm):isZero() and Vector3d(RetrieveSurfNorm( nIdToPair)) or Vector3d(ASS.vtSecondNorm)
|
|
local dAng = GetAngle( vtNorm1, vtNorm2)
|
|
local vtCopy = Vector3d(vtNorm1)
|
|
vtCopy:rotate(vtAx, 180 - dAng)
|
|
vtCopy = vtCopy * (GDB_ID.NULL)
|
|
ASS.ptAx = ptAx
|
|
ASS.vtAx = vtAx
|
|
if AreSameVectorApprox(vtNorm2, vtCopy) then
|
|
ASS.dAng = 180 - dAng
|
|
if not ASS.Rotate() then return false end
|
|
else
|
|
ASS.dAng = -(180 - dAng)
|
|
if not ASS.Rotate() then return false end
|
|
end
|
|
return true
|
|
end
|
|
|
|
function ASS.EdgePair()
|
|
ASS.sFunc = "ASS.EdgePair"
|
|
-- setto e faccio i controlli
|
|
-- resetto il conto di operazioni fatto
|
|
ASS.nTransf = 1
|
|
EgtSetContext(ASS.nVeinCtx)
|
|
if ASS.nPartId == GDB_ID.NULL then ASS.ERR = -1 return false end
|
|
if ASS.nIdFirstLine == GDB_ID.NULL then ASS.ERR = -1 return false end
|
|
if ASS.nIdSecondLine == GDB_ID.NULL then ASS.ERR = -1 return false end
|
|
-- controllo che i due part non siano già accoppiati
|
|
-- recupero l'id del secondo part
|
|
local nIdToPair = RetrieveParent(ASS.nIdSecondLine)
|
|
if nIdToPair == GDB_ID.NULL then ASS.ERR = -1 return false end
|
|
ASS.nPartId = RetrievePart(ASS.nPartId)
|
|
if ASS.nPartId == GDB_ID.NULL then ASS.ERR = -1 return false end
|
|
-- verifico che i due part non siano già accoppiati
|
|
local nGroup1 = 0
|
|
local nGroup2 = 0
|
|
nGroup1 = EgtGetInfo( ASS.nPartId, "GroupCode","i") or 0
|
|
nGroup2 = EgtGetInfo( nIdToPair, "GroupCode","i") or 0
|
|
if nGroup1 == nGroup2 and nGroup1 ~= 0 then return true end
|
|
-- se i due part non erano già associati allora procedo con l'accoppiamento
|
|
-- first line
|
|
local ptStartF, ptEndF, ptMidF, vtDirF
|
|
ptStartF = EgtSP(ASS.nIdFirstLine, GDB_RT.GLOB)
|
|
ptEndF = EgtEP(ASS.nIdFirstLine, GDB_RT.GLOB)
|
|
ptMidF = EgtMP(ASS.nIdFirstLine, GDB_RT.GLOB)
|
|
vtDirF = EgtSV(ASS.nIdFirstLine, GDB_RT.GLOB)
|
|
-- second line
|
|
local ptStartS, ptEndS, ptMidS, vtDirS
|
|
ptStartS = EgtSP(ASS.nIdSecondLine, GDB_RT.GLOB)
|
|
ptEndS = EgtEP(ASS.nIdSecondLine, GDB_RT.GLOB)
|
|
ptMidS = EgtMP(ASS.nIdSecondLine, GDB_RT.GLOB)
|
|
vtDirS = EgtSV(ASS.nIdSecondLine, GDB_RT.GLOB)
|
|
local ptIni, ptFin
|
|
if ASS.nOption == 0 then
|
|
-- Start-Start
|
|
ptIni = ptStartF
|
|
ptFin = ptStartS
|
|
elseif ASS.nOption == 1 then
|
|
-- Start-End
|
|
ptIni = ptStartF
|
|
ptFin = ptEndS
|
|
elseif ASS.nOption == 2 then
|
|
-- End-Start
|
|
ptIni = ptEndF
|
|
ptFin = ptStartS
|
|
elseif ASS.nOption == 3 then
|
|
-- End-End
|
|
ptIni = ptEndF
|
|
ptFin = ptEndS
|
|
elseif ASS.nOption == 4 then
|
|
-- Mid-Mid
|
|
ptIni = ptMidF
|
|
ptFin = ptMidS
|
|
end
|
|
ptPair = ptFin
|
|
-- calcolo il vettore movimento e sposto solid e part
|
|
ASS.vtMove = ptFin - ptIni
|
|
local dAng = GetAngle(vtDirF, vtDirS)
|
|
if not ASS.Move() then return false end
|
|
local dTol = 0.001
|
|
if dAng < dTol or abs(dAng - 180) < dTol or abs(dAng - 360) < dTol then
|
|
--EgtDraw()
|
|
return true
|
|
end
|
|
ASS.nTransf = 2
|
|
-- ruoto il solid che sto spostando
|
|
local vtAx = Vector3d( vtDirF ^ vtDirS)
|
|
ASS.dAng = dAng
|
|
ASS.ptAx = ptFin
|
|
ASS.vtAx = vtAx
|
|
if not ASS.Rotate() then return false end
|
|
--EgtDraw()
|
|
return true
|
|
end
|
|
|
|
function ASS.Unpair()
|
|
ASS.sFunc = "ASS.Unpair"
|
|
if ASS.nPartId == nil or ASS.nPartId == GDB_ID.NULL then ASS.ERR = -1 return false end
|
|
-- rimuovo le info dal PartCurr e da tutti i suoi Pair
|
|
ASS.nPartToPair = ASS.nPartId
|
|
if not ASS.RemovePairInfo() then return false end
|
|
local nPartCurr = ASS.nPartId
|
|
if not RetrievePaired() then return false end
|
|
local sPaired = EgtGetInfo(ASS.nPartId, "Paired")
|
|
if sPaired == nil then ASS.ERR = -3 return false end
|
|
for n, nId in pairs(vPaired) do
|
|
ASS.nPartId = nId
|
|
ASS.sPairList = sPaired
|
|
ASS.nGroup = #vPaired > 1 and GDB_ID.NULL or 0
|
|
if not ASS.UpdatePairInfoSingle() then return false end
|
|
end
|
|
-- resetto le info di pairing del part corrente
|
|
ASS.nPartId = nPartCurr
|
|
ASS.sPairList = EgtNumToString(nPartCurr)
|
|
ASS.nGroup = 0
|
|
if not ASS.UpdatePairInfoSingle() then return false end
|
|
return true
|
|
end
|
|
|
|
function ASS.RemovePairInfo() --nId As Integer, nIdToUnpair As Integer
|
|
-- al part nId tolgo l'accoppiamento con nIdToUnpair
|
|
ASS.sFunc = "ASS.RemovePairInfo"
|
|
--aggiorno le info
|
|
local sPair = EgtGetInfo(ASS.nPartId, "Paired", sPair)
|
|
local vsPaired = EgtSplitString(sPair, ",")
|
|
local sIdToUnpair = EgtNumToString(ASS.nPartToPair)
|
|
if sIdToUnpair == nil or sIdToUnpair == "" or vsPaired == nil or sPair == nil then ASS.ERR = -3 return false end
|
|
-- ricostruisco l'informazione paired senza l'Id che ho disaccoppiato
|
|
local sNewPaired = ""
|
|
for s, sIdPaired in pairs(vsPaired) do
|
|
if sIdPaired ~= sIdToUnpair then
|
|
if sNewPaired ~= "" then
|
|
sNewPaired = sNewPaired .. "," .. sIdPaired
|
|
else
|
|
sNewPaired = sIdPaired
|
|
end
|
|
end
|
|
end
|
|
-- aggiorno le info
|
|
local nGroup = #vsPaired > 2 and GDB_ID.NULL or 0
|
|
ASS.sPairList = sNewPaired
|
|
ASS.nGroup = nGroup
|
|
if not ASS.UpdatePairInfoSingle() then return false end
|
|
return true
|
|
end
|
|
|
|
function ASS.UpdatePairInfoSingle()
|
|
ASS.sFunc = "ASS.UpdatePairInfoSingle"
|
|
if ASS.sPairList == nil or ASS.sPairList == "" or ASS.nGroup == nil then ASS.ERR = -1 return false end
|
|
EgtSetInfo(ASS.nPartId, "Paired", ASS.sPairList)
|
|
if ASS.nGroup ~= GDB_ID.NULL then
|
|
EgtSetInfo(ASS.nPartId, "GroupCode", ASS.nGroup)
|
|
end
|
|
return true
|
|
end
|
|
|
|
function ASS.UpdatePairInfo()
|
|
ASS.sFunc = "ASS.UpdatePairInfo"
|
|
local nId1 = RetrievePart(ASS.nPartId)
|
|
if nId1 == nil or nId1 == GDB_ID.NULL then ASS.ERR = -1 return false end
|
|
ASS.nPartId = nId1
|
|
-- il secondo id lo recupero dal parent del secondo edge, se presente, altrimenti da nPartToPair
|
|
local nId2 = GDB_ID.NULL
|
|
if ASS.nIdSecondLine ~= GDB_ID.NULL then
|
|
nId2 = RetrieveParent(ASS.nIdSecondLine)
|
|
else
|
|
nId2 = RetrievePart(ASS.nPartToPair)
|
|
end
|
|
if nId1 == nil or nId1 == GDB_ID.NULL then ASS.ERR = -1 return false end
|
|
ASS.nPartToPair = nId2
|
|
-- salvo la lista degli attuali accoppiati del part destinatario dell'accoppiamento
|
|
local lPairList = EgtGetInfo( ASS.nPartToPair,"Paired", "vi")
|
|
if lPairList == nil then ASS.ERR = -3 return false end
|
|
-- verifico se uno o entrambi dei due part sono già in un gruppo
|
|
local sPaired1 = ""
|
|
sPaired1 = EgtGetInfo(nId1, "Paired")
|
|
if sPaired1 == nil then ASS.ERR = -3 return false end
|
|
local sPaired2 = ""
|
|
sPaired2 = EgtGetInfo(nId2, "Paired")
|
|
if sPaired2 == nil then ASS.ERR = -3 return false end
|
|
local nGroup = 0
|
|
-- se nessuno dei due era in un gruppo creo un nuovo gruppo con questi due part
|
|
if sPaired1 == EgtNumToString(nId1) and sPaired2 == EgtNumToString(nId2) then
|
|
sPaired1 = sPaired1 .. "," .. sPaired2
|
|
nGroup = EgtGetInfo(nId1, "GroupCode","i")
|
|
-- se solo il secondo era in un gruppo, al secondo copio gli id del gruppo
|
|
elseif sPaired1 == EgtNumToString(nId1) and sPaired2 ~= EgtNumToString(nId2) then
|
|
sPaired2 = sPaired2 .. "," .. EgtNumToString(nId1)
|
|
sPaired1 = sPaired2
|
|
nGroup = EgtGetInfo(nId2, "GroupCode","i")
|
|
-- se solo il primo era in un gruppo, al secondo copio gli id del gruppo
|
|
elseif sPaired1 ~= EgtNumToString(nId1) and sPaired2 == EgtNumToString(nId2) then
|
|
sPaired1 = sPaired1 .. "," .. EgtNumToString(nId2)
|
|
nGroup = EgtGetInfo(nId1, "GroupCode","i")
|
|
-- se entrambi erano in un gruppo faccio il merge
|
|
elseif sPaired1 ~= EgtNumToString(nId1) and sPaired2 ~= EgtNumToString(nId2) then
|
|
sPaired1 = sPaired1 .. "," .. sPaired2
|
|
local nGroup1 = EgtGetInfo(nId1, "GroupCode","i")
|
|
local nGroup2 = EgtGetInfo(nId2, "GroupCode","i")
|
|
nGroup = nGroup1 < nGroup2 and nGroup1 or nGroup2
|
|
end
|
|
if nGroup == 0 or nGroup == nil then
|
|
nGroup = GroupCounter
|
|
GroupCounter = GroupCounter + 1
|
|
end
|
|
-- scorro tutti i part associati e aggiorno le loro info
|
|
local vPaired_s = EgtSplitString(sPaired1) -- qua devo fare uno split sulle virgole
|
|
ASS.sPairList = sPaired1
|
|
ASS.nGroup = nGroup
|
|
local nPartCurr = ASS.nPartId
|
|
for n, sId in pairs(vPaired_s) do
|
|
local nId = EgtEvalNumExpr(sId)
|
|
ASS.nPartId = nId
|
|
if not ASS.UpdatePairInfoSingle() then return false end
|
|
end
|
|
if ASS.bActiveHist then
|
|
ASS.nPartId = nPartCurr
|
|
local tbEv = {Id = ASS.nPartId, vtDir = V_NULL(), ptAx = ORIG(), dAngOrId = ASS.nPartToPair, bWPaired = true, lPair = lPairList}
|
|
if ASS.bSaveHist then AddEvent( tbEv) end
|
|
if ASS.bSaveTemp then AddTempEvent( tbEv) end
|
|
end
|
|
return true
|
|
end
|
|
|
|
function ASS.PairAll()
|
|
ASS.sFunc = "ASS.PairAll"
|
|
local nTrasfTot = 0
|
|
EgtSetContext(ASS.nVeinCtx)
|
|
local nPart = EgtGetFirstPart()
|
|
if nPart == nil or nPart == GDB_ID.NULL then ASS.ERR = -3 return false end
|
|
while nPart do
|
|
local sLineToPair = EgtGetInfo(nPart, "PairToRef")
|
|
local sMyLineToPairName = EgtGetInfo( nPart, "PairMyRef")
|
|
if sLineToPair then
|
|
-- recupero l'id del lato da accoppiare
|
|
local sLayName = "Ref"
|
|
local nLayRef = EgtGetFirstNameInGroup(nPart, sLayName)
|
|
local nMyLineToPair = EgtGetFirstNameInGroup(nLayRef, sMyLineToPairName)
|
|
if nMyLineToPair == nil or nMyLineToPair == GDB_ID.NULL then ASS.ERR = -3 return false end
|
|
-- spezzo l'informazione per risalire al lato di destionazione dell'accoppiamento
|
|
local vToInfo = EgtSplitString(sLineToPair, "_")
|
|
local sLineToPairName = vToInfo[3]
|
|
local sPartName = vToInfo[1].."_"..vToInfo[2]
|
|
local nPartToPair = EgtGetFirstNameInGroup(GDB_ID.ROOT, sPartName)
|
|
local nLay = EgtGetFirstNameInGroup(nPartToPair, sLayName)
|
|
local nLineToPair = EgtGetFirstNameInGroup(nLay, sLineToPairName)
|
|
if nLineToPair == nil or nLineToPair == GDB_ID.NULL then ASS.ERR = -3 return false end
|
|
|
|
local nSpin = EgtGetInfo(nPart, "PairSpin", "i")
|
|
ASS.nPartId = nPart
|
|
ASS.nIdFirstLine = nMyLineToPair
|
|
ASS.nIdSecondLine = nLineToPair
|
|
|
|
-- controllo se è settata la modalità di accoppiamento sennò lascio il default middle-middle
|
|
local nOption = EgtGetInfo(nPart, "PairMode", "i")
|
|
ASS.nOption = nOption and nOption or 4
|
|
if not ASS.EdgePair() then return false end
|
|
nTrasfTot = ASS.nTransf
|
|
|
|
-- verifico che lo spin sia rispettato
|
|
local vtEdge1 = EgtSV( ASS.nIdFirstLine, GDB_RT.GLOB)
|
|
local vtEdge2 = EgtSV( ASS.nIdSecondLine, GDB_RT.GLOB)
|
|
if AreSameVectorApprox( vtEdge1, vtEdge2) and nSpin == -1 then
|
|
if not ASS.FlipParallel() then return false end
|
|
end
|
|
-- recupero l'angolo che deve esserci tra le due facce dei part alla fine dell'accoppiamento
|
|
local nAngGoal = EgtGetInfo(nPart, "PairAng", "i")
|
|
-- calcolo l'angolo attuale tra le due normali e quindi la rotazione che devo applicare per differenza
|
|
local vtSurf1 = RetrieveSurfNorm(nPart)
|
|
local vtSurf2 = RetrieveSurfNorm(RetrieveParent(ASS.nIdSecondLine))
|
|
if vtSurf1 == nil or AreSameVectorApprox( vtSurf1, V_NULL()) or vtSurf2 == nil or AreSameVectorApprox( vtSurf2, V_NULL()) then ASS.ERR = -3 return false end
|
|
ASS.vtAx = EgtSV(ASS.nIdSecondLine, GDB_RT.GLOB)
|
|
if ASS.vtAx == nil or AreSameVectorApprox(ASS.vtAx, V_NULL()) then ASS.ERR = -1 return false end
|
|
local dAngCurr = GetRotation(vtSurf1, vtSurf2, ASS.vtAx)
|
|
ASS.dAng = dAngCurr - nAngGoal
|
|
ASS.ptAx = EgtSP(ASS.nIdSecondLine, GDB_RT.GLOB)
|
|
if not ASS.Rotate() then return false end
|
|
nTrasfTot = nTrasfTot + 1
|
|
-- aggiorno le info di accoppiamento
|
|
ASS.nPartToPair = nPartToPair
|
|
if not ASS.UpdatePairInfo() then return false end
|
|
nTrasfTot = nTrasfTot + 1
|
|
end
|
|
nPart = EgtGetNext(nPart)
|
|
end
|
|
ASS.nTransf = nTrasfTot
|
|
return true
|
|
end
|
|
|
|
------ per funzionare con il require
|
|
--return ASS
|
|
------ per funzionare con il require
|
|
|
|
------ per funzionare nel CAM5
|
|
-- ASS.nVeinCtx = 1
|
|
-- ASS.PairAll()
|
|
-- EgtDraw()
|
|
------ per funzionare nel CAM5
|
|
---
|
|
|
|
if bAutoRun then
|
|
ASS.PairAll()
|
|
end
|