--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