Files
StoneSolidGen/OperationOnSolid.lua
T
Daniele Bariletti a466488114 OpertaionOnSolid :
- gestione output errori.
- evento importazione.
- accoppiamento automatico di default middle-middle.
| CreateSolid:
- estensione a più feature.
- gestione delle info per gli offset dei riferimenti.
2024-11-20 17:27:22 +01:00

831 lines
32 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)
-- 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
-- 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
ASS.sFunc = "" -- funzione in cui è stato eseguito il return a seguito di un errore
-- 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 = {}
-- 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)
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 AreSameVectorApporx(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 AreSameVectorApporx(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 == 2 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
AddEvent( tbEvent)
return true
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.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.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
-- 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(tvEvent.Id, "Child", "i")
EgtErase(nChild)
EgtErase(tvEvent.Id)
end
-- se sto facendo un redo, non faccio nulla
elseif bForward then
-- 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
-- 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 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
EgtSetInfo(nIdPaired, "Paired", sPairedNew1)
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 nGroupCode = GroupCounter
GroupCounter = GroupCounter + 1
local sPairedNew2 = EgtGetInfo( tbEvent.dAngOrId, "Paired", "s")
local lPairNew2 = EgtGetInfo( tbEvent.dAngOrId, "Paired", "vi")
-- aggiorno la lista dei part che erano già paired con il part selezionato
for n, nIdPaired in pairs(lPairNew2) do
EgtSetInfo(nIdPaired, "Paired", sPairedNew2)
EgtSetInfo(nIdPaired, "GroupCode", nGroupCode)
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
end
function ASS.Redo()
ASS.sFunc = "ASS.Redo"
if Time >= #tbStory then do return end end
if Time == ASS.nMaxStory then do return end end
ApplyTransf(tbStory[Time + 1], true, false, false)
Time = Time + 1
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 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)
end
-- muovo il pezzo e tutti i suoi accoppiati
for n, nId in pairs(vPaired) do
EgtMove( nId, ASS.vtMove)
local nChild = EgtGetInfo( nId, "Child", "i")
EgtMove( nChild, ASS.vtMove)
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 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)
local nChild = EgtGetInfo( ASS.nPartId, "Child", "i")
EgtMove( nChild, ASS.vtMove)
if RetrieveLocAxis() then
EgtMove(nTernaId, ASS.vtMove)
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.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)
local vtMove = Point3d(EgtSP( ptAfterId, GDB_RT.GLOB)) - Point3d(ptBefore)
EgtMove( nTernaId, vtMove)
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)
local nChild = EgtGetInfo( nId, "Child","i")
EgtRotate( nChild, ASS.ptAx, ASS.vtAx, ASS.dAng)
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 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)
local vtMove = Point3d(EgtSP( ptAfterId, GDB_RT.GLOB)) - Point3d(ptBefore)
EgtMove( nTernaId, vtMove)
EgtErase(ptAfterId)
end
-- ruoto il pezzo MA NON i suoi accoppiati
EgtRotate( ASS.nPartId, ASS.ptAx, ASS.vtAx, ASS.dAng)
local nChild = EgtGetInfo( ASS.nPartId, "Child","i")
EgtRotate( nChild, ASS.ptAx, ASS.vtAx, ASS.dAng)
-- 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 AreSameVectorApporx(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 AreSameVectorApporx(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
--dofile("D:\\Temp\\marmo\\repeat2.lua")
function ASS.PairAll()
ASS.sFunc = "ASS.PairAll"
--local sTime = os.date( '%y%m%d%H%M%S', os.time())
local nTrasfTot = 0
EgtSetContext(ASS.nVeinCtx)
local nPart = EgtGetFirstPart()
if nPart == nil or nPart == GDB_ID.NULL then ASS.ERR = -3 return false end
--EgtOutLog(tostring(nPart))
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
-- se lo spin è negativo vuol dire che devo accoppiare start del primo con end del secondo
-- sennò start con start
--ASS.nOption = (nSpin == -1 and 1 or 0)
ASS.nOption = 4
if not ASS.EdgePair() then return false end
nTrasfTot = ASS.nTransf
local ptFirst
local ptSecond
if ASS.nOption == 0 then
--Start-Start
ptFirst = EgtEP( ASS.nIdFirstLine, GDB_RT.GLOB)
ptSecond = EgtEP( ASS.nIdSecondLine, GDB_RT.GLOB)
elseif ASS.nOption == 1 then
--Start-End
ptFirst = EgtEP( ASS.nIdFirstLine, GDB_RT.GLOB)
ptSecond = EgtSP( ASS.nIdSecondLine, GDB_RT.GLOB)
elseif ASS.nOption == 2 then
--End-Start
ptFirst = EgtSP( ASS.nIdFirstLine, GDB_RT.GLOB)
ptSecond = EgtEP( ASS.nIdSecondLine, GDB_RT.GLOB)
elseif ASS.nOption == 3 then
--End-End
ptFirst = EgtSP( ASS.nIdFirstLine, GDB_RT.GLOB)
ptSecond = EgtSP( ASS.nIdSecondLine, GDB_RT.GLOB)
elseif ASS.nOption == 4 then
--Mid-Mid
if nSpin == 1 then
ptFirst = EgtSP( ASS.nIdFirstLine, GDB_RT.GLOB)
ptSecond = EgtSP( ASS.nIdSecondLine, GDB_RT.GLOB)
elseif nSpin == -1 then
ptFirst = EgtSP( ASS.nIdFirstLine, GDB_RT.GLOB)
ptSecond = EgtEP( ASS.nIdSecondLine, GDB_RT.GLOB)
end
end
-- 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