Files
StoneSolidGen/OperationOnSolid.lua
Daniele Bariletti b1d113b63f - corretto bug nella creazione del solido di un pezzo con un foro.
- aggiunta lettura thickness dalle info del part.
2024-12-02 09:42:41 +01:00

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