Files
Nicola Pievani 98b6563e57 OmagVIEWPlus 2.2k1:
-> verificate coordinate di prelievo e deposito (Tab1 e Tab2)
-> scatta foto
-> gestione di preparazione pallet (nesting 1d)
-> gestione mancato vuoto su tavola 1
-> gestione di mancato vuoto tavola 2.
2020-11-20 19:48:51 +00:00

923 lines
40 KiB
VB.net

Imports EgtUILib
Module VacuumCups
' Tipo manipolatore con ventosa (0=assente, 1=dietro, 2=laterale)
Private m_nVacType As Integer = 0
' Dati del manipolatore
Private m_nTempId As Integer = GDB_ID.NULL
Private m_nVacId As Integer = GDB_ID.NULL
Private m_nRefId As Integer = GDB_ID.NULL
' utilizzati per gestire il posizionamento delle ventose
Private m_dPreferredRot As Double = 0
Private m_dDripRefAng As Double = 0
' Nome del gruppo temporaneo per le ventose
Private Const VACTMP_GRP As String = "VacTmp"
Friend Function GetVacuumType() As Integer
Return m_nVacType
End Function
Friend Function GetVacuumId() As Integer
Return m_nVacId
End Function
Friend Function LoadVacuumCups(ByVal Optional sNameHead As String = VACUUM_HEAD) As Boolean
' Leggo tipo manipolatore con ventosa
m_nVacType = 0
EgtGetInfo(EgtGetHeadId(sNameHead), KEY_VAC_TYPE, m_nVacType)
' Cancello eventuali vecchie ventose
RemoveVacuumCups()
' Identificativo ventose nella macchina
Dim nLayId As Integer = EgtGetFirstNameInGroup(EgtGetHeadId(sNameHead), VACUUM_HEAD_LAYOUT)
If nLayId = GDB_ID.NULL Then Return False
' Identificativo riferimento della testa nella macchina
Dim nT1Id As Integer = EgtGetFirstNameInGroup(EgtGetHeadId(sNameHead), HEAD_FIRST_EXIT)
If nT1Id = GDB_ID.NULL Then Return False
' Creo gruppo temporaneo in cui copiarli
m_nTempId = EgtCreateGroup(GDB_ID.ROOT)
If m_nTempId = GDB_ID.NULL Then Return False
EgtSetName(m_nTempId, VACTMP_GRP)
EgtSetLevel(m_nTempId, GDB_LV.TEMP)
' Eseguo copia in globale
m_nVacId = EgtCopyGlob(nLayId, m_nTempId)
If m_nVacId = GDB_ID.NULL Then Return False
' Angolo di rotazione preferito
EgtGetInfo(m_nVacId, KEY_VACLAY_PREFROT, m_dPreferredRot)
' Direzione di riferimento per tagli Drip
'EgtGetInfo( m_nVacId, KEY_VACLAY_DRIPREFDIR, m_dDripRefAng)
' Nascondo il gruppo ma rendo visibili le curve di contorno delle ventose
EgtSetStatus(m_nVacId, GDB_ST.OFF)
Dim nId As Integer = EgtGetFirstInGroup(m_nVacId)
While nId <> GDB_ID.NULL
Select Case EgtGetType(nId)
Case GDB_TY.CRV_LINE, GDB_TY.CRV_ARC, GDB_TY.CRV_BEZ, GDB_TY.CRV_COMPO
EgtSetStatus(nId, GDB_ST.ON_)
Case Else
EgtSetStatus(nId, GDB_ST.OFF)
End Select
nId = EgtGetNext(nId)
End While
m_nRefId = EgtCopyGlob(nT1Id, m_nVacId)
If m_nRefId = GDB_ID.NULL Then Return False
EgtSetStatus(m_nRefId, GDB_ST.ON_)
Return True
End Function
Friend Function RemoveVacuumCups() As Boolean
' Cancello eventuali gruppi per ventose usati appena prima
EgtErase(m_nTempId)
m_nTempId = GDB_ID.NULL
m_nVacId = GDB_ID.NULL
m_nRefId = GDB_ID.NULL
' Cancello eventuali vecchi gruppi per ventose
Dim nId As Integer = EgtGetFirstNameInGroup(GDB_ID.ROOT, VACTMP_GRP)
While nId <> GDB_ID.NULL
Dim nNextId As Integer = EgtGetNextName(nId, VACTMP_GRP)
EgtErase(nId)
nId = nNextId
End While
Return True
End Function
Friend Function ResetVacuumCups(Optional ByVal sNameHead As String = VACUUM_HEAD) As Boolean
' Ripristino posizione e rotazione originali
Dim frOriRef As New Frame3d
EgtFrame(EgtGetFirstNameInGroup(EgtGetHeadId(sNameHead), HEAD_FIRST_EXIT), GDB_ID.ROOT, frOriRef)
Dim frCurrRef As New Frame3d
EgtFrame(m_nRefId, GDB_ID.ROOT, frCurrRef)
EgtMove(m_nVacId, frOriRef.Orig() - frCurrRef.Orig(), GDB_RT.GLOB)
frCurrRef.ToLoc(frOriRef)
Dim dLen, dAngVertDeg, dAngOrizzDeg As Double
frCurrRef.VersX().ToSpherical(dLen, dAngVertDeg, dAngOrizzDeg)
EgtRotate(m_nVacId, frOriRef.Orig(), frOriRef.VersZ(), -dAngOrizzDeg, GDB_RT.GLOB)
' Ripristino visualizzazione originale
Dim nId As Integer = EgtGetFirstInGroup(m_nVacId)
While nId <> GDB_ID.NULL
Select Case EgtGetType(nId)
Case GDB_TY.CRV_LINE, GDB_TY.CRV_ARC, GDB_TY.CRV_BEZ, GDB_TY.CRV_COMPO
EgtSetStatus(nId, GDB_ST.ON_)
Case Else
EgtSetStatus(nId, GDB_ST.OFF)
End Select
nId = EgtGetNext(nId)
End While
EgtSetStatus(m_nRefId, GDB_ST.ON_)
Return True
End Function
Friend Function PutVacuumCupsOnRaw(nRawId As Integer, ByRef rmData As RawMoveData) As Boolean
' Ripristino posizione originale ventose
ResetVacuumCups()
' Box e baricentro del grezzo (riportato sopra al grezzo)
Dim b3Raw As New BBox3d
EgtGetRawPartBBox(nRawId, b3Raw)
Dim ptRawCen As Point3d
EgtGetRawPartCenter(nRawId, ptRawCen)
ptRawCen.z += b3Raw.DimZ() / 2
' Se non esiste, creo la regione del kerf del grezzo
Dim nKerfId As Integer = EgtGetFirstNameInGroup(nRawId, NAME_KERF)
Dim nRKerfId = EgtGetFirstNameInGroup(nRawId, NAME_KERF_REGION)
If nRKerfId = GDB_ID.NULL Then
nRKerfId = EgtCreateSurfFlatRegion(nRawId, nKerfId)
' se non sono riuscito a crearla, allora è nulla e posso uscire
If nRKerfId = GDB_ID.NULL Then Return False
EgtSetName(nRKerfId, NAME_KERF_REGION)
EgtSetMode(nRKerfId, GDB_MD.HIDDEN)
End If
' Box e baricentro della regione di kerf
Dim b3Kerf As New BBox3d
EgtGetBBoxGlob(nRKerfId, GDB_BB.STANDARD, b3Kerf)
Dim ptKerfCen As Point3d
EgtCentroid(nRKerfId, GDB_ID.ROOT, ptKerfCen)
' Eseguo ricerca
If FindVacuumCupsOnRaw(nRawId, ptRawCen, b3Kerf, ptKerfCen, nKerfId, nRKerfId, rmData) Then
Return True
End If
' In caso di fallimento, provo riducendo con offset la regione di kerf
' (così si simula la proiezione del centro sul MAT - medial axis transform)
Dim bOkFind As Boolean = False
Dim vOffset() As Double = {-450, -350, -250, -150}
For i As Integer = 0 To vOffset.Length() - 1
Dim nRKerfOffsId = EgtCopy(nRKerfId, nRKerfId, GDB_POS.AFTER)
If EgtSurfFrOffset(nRKerfOffsId, vOffset(i), OFF_TYPE.FILLET) AndAlso
EgtCentroid(nRKerfOffsId, GDB_ID.ROOT, ptKerfCen) Then
Dim nOutOffsId As Integer = GetRegionOutLoop(nRKerfOffsId, nRawId)
bOkFind = FindVacuumCupsOnRaw(nRawId, ptRawCen, b3Kerf, ptKerfCen, nOutOffsId, nRKerfId, rmData)
EgtErase(nOutOffsId)
End If
EgtErase(nRKerfOffsId)
If bOkFind Then Return True
Next
Return False
End Function
Friend Function PutVacuumCupsOnPart(nPartId As Integer,
ByRef rmData As RawMoveData, ByRef b3Part As BBox3d) As Boolean
' Ripristino posizione originale ventose
ResetVacuumCups()
' Verifico sia veramente un pezzo
If EgtGetRawPartFromPart(nPartId) = GDB_ID.NULL Then Return False
' Cerco la direzione del primo taglio attivo da sotto
Dim nDripLayId As Integer = EgtGetFirstNameInGroup( nPartId, NAME_DRIPCUT)
Dim nDripLineId As Integer = EgtGetFirstInGroup( nDripLayId)
While nDripLineId <> GDB_ID.NULL
Dim nMchId As Integer = EgtGetOperationId( "DripSaw" & nDripLineId.ToString())
Dim nMode As Integer
If EgtGetMode( nMchId, nMode) AndAlso nMode = GDB_MD.STD Then Exit While
nDripLineId = EgtGetNext( nDripLineId)
End While
Dim vtDir As New Vector3d
if EgtStartVector( nDripLineId, GDB_ID.ROOT, vtDir) Then
Dim dLen, dAngV, dAngH As Double
vtDir.ToSpherical( dLen, dAngV, dAngH)
Dim dOffsAng = dAngH - m_dDripRefAng
While dOffsAng - m_dPreferredRot >= 90
dOffsAng -= 180
End While
While dOffsAng - m_dPreferredRot <= -90
dOffsAng += 180
End While
m_dPreferredRot = dOffsAng
End If
' Recupero la regione del pezzo
Dim nGrpRegId As Integer = EgtGetFirstNameInGroup(nPartId, ConstMach.NAME_REGION)
Dim nRegId As Integer = EgtGetFirstInGroup(nGrpRegId)
While nRegId <> GDB_ID.NULL
If EgtGetType(nRegId) = GDB_TY.SRF_FRGN Then Exit While
nRegId = EgtGetNext(nRegId)
End While
If nRegId = GDB_ID.NULL Then Return False
' Box e baricentro del pezzo (sempre sopra)
EgtGetBBoxGlob(nRegId, GDB_BB.STANDARD, b3Part)
Dim ptPartCen As Point3d
EgtCentroid(nRegId, GDB_ID.ROOT, ptPartCen)
' Calcolo il contorno esterno del pezzo
Dim nOutId As Integer = GetRegionOutLoop(nRegId, nGrpRegId)
If nOutId = GDB_ID.NULL Then Return False
' Eseguo ricerca
If FindVacuumCupsOnRaw(nPartId, ptPartCen, b3Part, ptPartCen, nOutId, nRegId, rmData) Then
EgtErase(nOutId)
Return True
Else
EgtErase(nOutId)
End If
' In caso di fallimento, provo riducendo con offset la regione di kerf
' (così si simula la proiezione del centro sul MAT - medial axis transform)
Dim bOkFind As Boolean = False
Dim vOffset() As Double = {-450, -350, -250, -150}
For i As Integer = 0 To vOffset.Length() - 1
Dim nRegOffsId As Integer = EgtCopy(nRegId, nRegId, GDB_POS.AFTER)
Dim ptRegOffsCen As Point3d
If EgtSurfFrOffset(nRegOffsId, vOffset(i), OFF_TYPE.FILLET) AndAlso
EgtCentroid(nRegOffsId, GDB_ID.ROOT, ptRegOffsCen) Then
Dim nOutOffsId As Integer = GetRegionOutLoop(nRegOffsId, nGrpRegId)
bOkFind = FindVacuumCupsOnRaw(nPartId, ptRegOffsCen, b3Part, ptPartCen, nOutOffsId, nRegId, rmData)
EgtErase(nOutOffsId)
End If
EgtErase(nRegOffsId)
If bOkFind Then Return True
Next
Return False
End Function
Friend Function MyPutVacuumCupsOnPart(nPartId As Integer,
ByRef rmData As RawMoveData, ByRef b3Part As BBox3d, ByVal sNameHead As String) As Boolean
LoadVacuumCups(sNameHead)
' Ripristino posizione originale ventose
ResetVacuumCups(sNameHead)
' Verifico sia veramente un pezzo
If EgtGetRawPartFromPart(nPartId) = GDB_ID.NULL Then Return False
' Recupero la regione del pezzo
Dim nGrpRegId As Integer = EgtGetFirstNameInGroup(nPartId, ConstMach.NAME_REGION)
Dim nRegId As Integer = EgtGetFirstInGroup(nGrpRegId)
While nRegId <> GDB_ID.NULL
If EgtGetType(nRegId) = GDB_TY.SRF_FRGN Then Exit While
nRegId = EgtGetNext(nRegId)
End While
If nRegId = GDB_ID.NULL Then Return False
Dim nCount As Integer = 0
' recupero il contorno del pezzo
Dim nIdCurve As Integer = GetRegionOutLoop(nRegId, nGrpRegId)
If nIdCurve = GDB_ID.NULL OrElse nCount > 1 Then Return False
' recuper il versore
Dim frFrame As New Frame3d
' recupero le dimensioni del minimo rettangolo
Dim dLengthX As Double = 0
Dim dLengthY As Double = 0
EgtCurveMinAreaRectangleXY(nIdCurve, GDB_ID.ROOT, frFrame, dLengthX, dLengthY)
rmData.m_vtRect.x = dLengthX / 2
rmData.m_vtRect.y = dLengthY / 2
' recupero il centro del rettangolo (nel piano XY)
Dim ptCetMinRect As Point3d = frFrame.Orig()
rmData.m_ptCenMinRect = ptCetMinRect
' recupero la direzione ortogaonale al versore X
Dim vtOrtoDir As Vector3d = frFrame.VersY()
Dim vtDir As Vector3d = frFrame.VersX()
rmData.m_vtOrtoDirX = vtOrtoDir
Dim dMyLen, dMyAngV, dMyAngH As Double
vtDir.ToSpherical(dMyLen, dMyAngV, dMyAngH)
' mi riconduco sempre agli angoli
If dMyAngH > 180 Then
dMyAngH = dMyAngH - 180
End If
' se sono sul manipolatore due definisco l'angolo di presa
If sNameHead = VACUUM_HEAD_PALLET Then
dMyAngH = 180
End If
m_dPreferredRot = dMyAngH
'' recupero l'Id del lato più lungo
'Dim MaxSideId As Integer = GetMaxSideId(nPartId)
'EgtRotate(MaxSideId, ptCetMinRect, Vector3d.Z_AX, dMyAngH)
'' recupero la direzione del lato più lungo
'EgtMidVector(MaxSideId, vtDir)
'rmData.m_vtDirX = vtDir
'' fisso l'angolo di prelievo del pezzo
'm_dPreferredRot = dMyAngH
'' controruoto il segmento
'EgtRotate(MaxSideId, ptCetMinRect, Vector3d.Z_AX, -dMyAngH)
' ottengo l'angolo orizzotale del vettore direzione (dAngH)
'Dim dLen, dAngV, dAngH As Double
'vtDir.ToSpherical(dLen, dAngV, dAngH)
' misuro il delta tra l'angolo calcolato e quello provilegiato per il taglio da sotto (sempre nullo)
'Dim dOffsAng = dMyAngH - m_dDripRefAng
'While dOffsAng - m_dPreferredRot >= 90
' dOffsAng -= 180
'End While
'While dOffsAng - m_dPreferredRot <= -90
' dOffsAng += 180
'End While
'm_dPreferredRot = dOffsAng
' Box e baricentro del pezzo (sempre sopra)
EgtGetBBoxGlob(nRegId, GDB_BB.STANDARD, b3Part)
Dim ptPartCen As Point3d
EgtCentroid(nRegId, GDB_ID.ROOT, ptPartCen)
' Calcolo il contorno esterno del pezzo
Dim nOutId As Integer = GetRegionOutLoop(nRegId, nGrpRegId)
If nOutId = GDB_ID.NULL Then Return False
' Eseguo ricerca
If FindVacuumCupsOnRaw(nPartId, ptPartCen, b3Part, ptPartCen, nOutId, nRegId, rmData, sNameHead) Then
EgtErase(nOutId)
Return True
Else
EgtErase(nOutId)
End If
' In caso di fallimento, provo riducendo con offset la regione di kerf
' (così si simula la proiezione del centro sul MAT - medial axis transform)
Dim bOkFind As Boolean = False
Dim vOffset() As Double = {-450, -350, -250, -150}
For i As Integer = 0 To vOffset.Length() - 1
Dim nRegOffsId As Integer = EgtCopy(nRegId, nRegId, GDB_POS.AFTER)
Dim ptRegOffsCen As Point3d
If EgtSurfFrOffset(nRegOffsId, vOffset(i), OFF_TYPE.FILLET) AndAlso
EgtCentroid(nRegOffsId, GDB_ID.ROOT, ptRegOffsCen) Then
Dim nOutOffsId As Integer = GetRegionOutLoop(nRegOffsId, nGrpRegId)
bOkFind = FindVacuumCupsOnRaw(nPartId, ptRegOffsCen, b3Part, ptPartCen, nOutOffsId, nRegId, rmData)
EgtErase(nOutOffsId)
End If
EgtErase(nRegOffsId)
If bOkFind Then Return True
Next
Return False
End Function
Private Function FindVacuumCupsOnRaw(nRawId As Integer, ptRawCen As Point3d,
b3Kerf As BBox3d, ptKerfCen As Point3d, nOutlineId As Integer, nRKerfId As Integer,
ByRef rmData As RawMoveData, Optional sNameHead As String = VACUUM_HEAD) As Boolean
' Cerco migliore configurazione di ventose per prendere il grezzo
Const MAX_SEL As Integer = 24
For nI As Integer = 1 To MAX_SEL
' Recupero la configurazione di ventose nI-esima
Dim sCups() As String = Nothing
Dim sCups2() As String = Nothing
If Not GetVacuumCupSelection(nI, sCups, sCups2) Then Return False
' Determino validità soluzioni della configurazione
Dim vtMove As New Vector3d
Dim ptRotCen As New Point3d
Dim dRotAngDeg As Double = 0
Dim vtMove2 As New Vector3d
Dim ptRotCen2 As New Point3d
Dim dRotAngDeg2 As Double = 90
' verifico con il primo elenco di ventose
Dim dDist As Double = INFINITO
If sNameHead = VACUUM_HEAD Then
' se tavola 1
Dim bFirstSelection As Boolean = MyVacuumTest(sCups, b3Kerf, ptKerfCen, nOutlineId, nRKerfId, vtMove, ptRotCen, dRotAngDeg, sNameHead)
Dim bSecondSelection As Boolean = False
If Not bFirstSelection Then
' se la prima selezione fallisce allora provo con un'altra complementare
bSecondSelection = MyVacuumTest(sCups2, b3Kerf, ptKerfCen, nOutlineId, nRKerfId, vtMove2, ptRotCen2, dRotAngDeg2, sNameHead)
End If
If bSecondSelection Then
' se la nuova selezione funziona allora salvo
sCups = sCups2
vtMove = vtMove2
ptRotCen = ptRotCen2
dRotAngDeg = dRotAngDeg2
rmData.m_bCupsSecondSel = True
End If
' se nessuna delle due proposte soluzioni ha funzionato allora provo con un'altra
If Not bFirstSelection And Not bSecondSelection Then Continue For
Else
' se tavola 2 allora pallettizzatore imposto come angolo privilegiato C180
m_dPreferredRot = 180
' correggo l'uso delle ventose
If rmData.m_vtRect.x * 2 >= Map.refUnloadingAreaVM.MaxLength And Not IsNothing(sCups) Then
If sCups.Count = 1 Then
If Trim(sCups(0)) = "V4" Then Continue For
End If
ElseIf rmData.m_vtRect.x * 2 < Map.refUnloadingAreaVM.MaxLength And Not IsNothing(sCups) Then
' se pezzo da depositare sui pallet
If sCups.Count = 2 Then
If ((sCups(0).Contains("V3") And sCups(1).Contains("V1")) Or (sCups(0).Contains("V1") And sCups(1).Contains("V3"))) Then Continue For
End If
End If
dDist = TestVacuumCupSelection(sCups, b3Kerf, ptKerfCen, nOutlineId, nRKerfId, vtMove, ptRotCen, dRotAngDeg)
If dDist > INFINITO - 1 Then Continue For
End If
'If dDist > INFINITO - 1 And dDist2 > INFINITO - 1 Then Continue For
'If dDist2 < dDist Then
' sCups = sCups2
' vtMove = vtMove2
' ptRotCen = ptRotCen2
' dRotAngDeg = dRotAngDeg2
'End If
' Eseguo il movimento della ventosa
'' rappresento graficamente l'afferraggio dei pezzi
'EgtSetMachineLook(MCH_LOOK.TAB_HEAD)
'EgtSetAxisPos("X1", ptRawCen.x + 25)
'EgtSetAxisPos("Y", ptRawCen.y - 729)
'EgtSetAxisPos("W1", dRotAngDeg)
'EgtDraw()
EgtMove(m_nVacId, vtMove, GDB_RT.GLOB)
' allineo la ventosa
EgtRotate(m_nVacId, ptRotCen, Vector3d.Z_AX(), dRotAngDeg, GDB_RT.GLOB)
' Visualizzo le ventose
For nJ As Integer = 0 To sCups.Length() - 1
Dim nCupId = EgtGetFirstNameInGroup(m_nVacId, sCups(nJ))
EgtSetStatus(nCupId, GDB_ST.ON_)
Next
' Calcolo delta posizione (rispetto all'origine delle ventose)
Dim frCurrRef As New Frame3d
EgtFrame(m_nRefId, GDB_ID.ROOT, frCurrRef)
Dim vtDelta As Vector3d = frCurrRef.Orig() - ptRawCen
' correggo le coordinate (x,y) considerando il centro del minimo rettangolo
Dim vtOffsetCenter As Vector3d = ptRawCen - rmData.m_ptCenMinRect
' la quota zeta in realtà è ignorata
Dim zDelta As Double = vtDelta.z
vtDelta = vtDelta + vtOffsetCenter
' reimposto il valore della z
vtDelta.z = zDelta
' Assegno dati noti al movimento del grezzo
rmData.m_nId = nRawId
rmData.m_vtRawMove = Vector3d.NULL()
rmData.m_vtDelta = vtDelta
rmData.m_dAngRotDeg = dRotAngDeg
Dim sVal As String = String.Empty
For Each sCup As String In sCups
If String.IsNullOrEmpty(sVal) Then
sVal &= sCup
Else
sVal &= "," & sCup
End If
Next
rmData.m_sCups = sVal
' riposiziono la ventosa nel punto di partenza
EgtMove(m_nVacId, -vtMove, GDB_RT.GLOB)
' controruoto la ventosa per tornare alla posizione di partenza
EgtRotate(m_nVacId, ptRotCen, Vector3d.Z_AX(), -dRotAngDeg, GDB_RT.GLOB)
frCurrRef.Rotate(ptRotCen, Vector3d.Z_AX(), -dRotAngDeg)
Return True
Next
Return False
End Function
Private Function MyVacuumTest(sCups() As String, b3Raw As BBox3d, ptRawCen As Point3d, nOutlineId As Integer, nRawRegId As Integer,
ByRef vtMove As Vector3d, ByRef ptRotCen As Point3d, ByRef dRotAngDeg As Double, sNameHead As String) As Boolean
Dim dDist = TestVacuumCupSelection(sCups, b3Raw, ptRawCen, nOutlineId, nRawRegId, vtMove, ptRotCen, dRotAngDeg)
If dDist < INFINITO - 1 Then
' costruisco una copia del riferimento
Dim frCurrRefTemp As New Frame3d
EgtFrame(m_nRefId, GDB_ID.ROOT, frCurrRefTemp)
EgtMove(m_nVacId, vtMove, GDB_RT.GLOB)
frCurrRefTemp.Move(vtMove)
' calcolo l'offset dal centro del pezzo
Dim vtDeltaTest As Vector3d = frCurrRefTemp.Orig() - ptRawCen
' dimensioni tavola
Dim MinX, MaxY, MaxX, MinY As Double
EgtGetInfo(EgtGetTableId(MAIN_TAB), "MaxTabY", MaxY)
EgtGetInfo(EgtGetTableId(MAIN_TAB), "MinTabX", MinX)
EgtGetInfo(EgtGetTableId(MAIN_TAB), "MinTabY", MinY)
EgtGetInfo(EgtGetTableId(MAIN_TAB), "MaxTabX", MaxX)
' allineo il riferimeno della ventosa
frCurrRefTemp.Rotate(ptRawCen, Vector3d.Z_AX, dRotAngDeg)
vtDeltaTest.Rotate(Vector3d.Z_AX, dRotAngDeg)
EgtRotate(m_nVacId, ptRawCen, Vector3d.Z_AX, dRotAngDeg, GDB_RT.GLOB)
' calcolo la posizione di prelievo del pezzo
Dim ptUnload As New Point3d
ptUnload.x = ptRawCen.x + vtDeltaTest.x
ptUnload.y = ptRawCen.y + vtDeltaTest.y
' verifico che il punto sia all'interno delle corse
EgtSetCalcTool("", sNameHead, 1)
Dim nStat As Integer = 0
Dim bVerifyStroke As Boolean = EgtVerifyOutstroke(ptUnload.x, ptUnload.y, ptRawCen.z, 0, dRotAngDeg, nStat)
If nStat <> 0 Then bVerifyStroke = False
' verifico di no sbattere contro la macchina
If bVerifyStroke Then
Dim b3BoxVacuum As New BBox3d
EgtGetBBoxGlob(m_nVacId, GDB_BB.STANDARD, b3BoxVacuum)
If b3BoxVacuum.Min.x < MinX Or b3BoxVacuum.Max.x > MaxX Then
bVerifyStroke = False
End If
If b3BoxVacuum.Max.y > MaxY Or b3BoxVacuum.Min.y < MinY Then
bVerifyStroke = False
End If
End If
If Not bVerifyStroke Then
' mi riporto in posizione di partenza
frCurrRefTemp.Rotate(ptRawCen, Vector3d.Z_AX, -dRotAngDeg)
vtDeltaTest.Rotate(Vector3d.Z_AX, -dRotAngDeg)
EgtRotate(m_nVacId, ptRawCen, Vector3d.Z_AX, -dRotAngDeg, GDB_RT.GLOB)
' provo a ruotare di 180
If dRotAngDeg >= 90 Then
dRotAngDeg = dRotAngDeg - 180
Else
dRotAngDeg = dRotAngDeg + 180
End If
' mi allineo
vtDeltaTest.Rotate(Vector3d.Z_AX, dRotAngDeg)
frCurrRefTemp.Rotate(ptRawCen, Vector3d.Z_AX, dRotAngDeg)
EgtRotate(m_nVacId, ptRawCen, Vector3d.Z_AX, dRotAngDeg)
ptUnload.x = ptRawCen.x + vtDeltaTest.x
ptUnload.y = ptRawCen.y + vtDeltaTest.y
bVerifyStroke = EgtVerifyOutstroke(ptUnload.x, ptUnload.y, ptRawCen.z, 0, dRotAngDeg, nStat)
If nStat <> 0 Then bVerifyStroke = False
' verifico di no sbattere contro la macchina
Dim b3BoxVacuum As New BBox3d
EgtGetBBoxGlob(m_nVacId, GDB_BB.STANDARD, b3BoxVacuum)
If b3BoxVacuum.Min.x < MinX Or b3BoxVacuum.Max.x > MaxX Then
bVerifyStroke = False
End If
If b3BoxVacuum.Max.y > MaxY Or b3BoxVacuum.Min.y < MinY Then
bVerifyStroke = False
End If
EgtRotate(m_nVacId, ptRawCen, Vector3d.Z_AX, -dRotAngDeg, GDB_RT.GLOB)
frCurrRefTemp.Rotate(ptRawCen, Vector3d.Z_AX, -dRotAngDeg)
EgtMove(m_nVacId, -vtMove, GDB_RT.GLOB)
frCurrRefTemp.Move(-vtMove)
Return bVerifyStroke
End If
frCurrRefTemp.Rotate(ptRawCen, Vector3d.Z_AX, -dRotAngDeg)
EgtRotate(m_nVacId, ptRawCen, Vector3d.Z_AX, -dRotAngDeg, GDB_RT.GLOB)
EgtMove(m_nVacId, -vtMove, GDB_RT.GLOB)
frCurrRefTemp.Move(-vtMove)
Return bVerifyStroke
End If
Return False
End Function
Private Function GetVacuumCupSelection(nInd As Integer, ByRef sCups() As String, ByRef sCups2() As String) As Boolean
' Recupero elenco ventose nella soluzione
Dim sSel As String = KEY_VACLAY_SEL & nInd.ToString()
Dim sVal As String = String.Empty
' recupero la selezione "nInd"
If Not EgtGetInfo(m_nVacId, sSel, sVal) Then Return False
' verifico se esiste più di una configurazione: V1,V2/V5,V6
If sVal.IndexOf("/") >= 0 Then
Dim sSplit() As String = sVal.Split("/".ToCharArray)
If sSplit.Length() >= 2 Then
' slavo la prima selezione: V1,V2
sCups = sSplit(0).Split(",".ToCharArray)
' salvo la seconda selezione: V5,V6
sCups2 = sSplit(1).Split(",".ToCharArray)
ElseIf sSplit.Length() >= 1 Then
sCups = sSplit(0).Split(",".ToCharArray)
sCups2 = Nothing
Else
' nessuna definizione assciata: /
sCups = Nothing
sCups2 = Nothing
End If
Else
' definizione di una sola selezione: V7,V8
sCups = sVal.Split(",".ToCharArray)
sCups2 = Nothing
End If
Return True
End Function
Private Function GetVacRotAxisSteps(ByRef vAngRot As List(Of Double), ByRef Optional sNameHead As String = VACUUM_HEAD) As Boolean
' Recupero l'asse rotante della testa ventosa
Dim nRotAxId As Integer = EgtGetParent(EgtGetHeadId(sNameHead))
' Verifico se contiene info con STEPS
Dim sSteps As String = ""
If Not EgtGetInfo(nRotAxId, KEY_ROTVAC_STEPS, sSteps) Then Return False
' Leggo gli step previsti
Dim vStep() As String = sSteps.Split(",".ToCharArray)
For Each sStep As String In vStep
Dim dStep As Double = 0
If StringToDouble(sStep, dStep) Then
vAngRot.Add(dStep)
End If
Next
Return True
End Function
Private Function TestVacuumCupSelection(sCups() As String, b3Raw As BBox3d, ptRawCen As Point3d, nOutlineId As Integer, nRawRegId As Integer,
ByRef vtMove As Vector3d, ByRef ptRotCen As Point3d, ByRef dRotAngDeg As Double) As Double
' Se definizione mancante, scarto soluzione
If IsNothing(sCups) Then Return INFINITO
' Ne calcolo il box
Dim b3Vac As New BBox3d
For nJ As Integer = 0 To sCups.Length() - 1
' recupero l'Id della camera (V_nJ)
Dim nCupId = EgtGetFirstNameInGroup(m_nVacId, sCups(nJ))
Dim b3Cup As New BBox3d
' se la costruzione del Box va a buon fine allora lo aggiungo all'inisieme (per generare il Box complessivo)
If EgtGetBBoxGlob(nCupId, GDB_BB.STANDARD, b3Cup) Then b3Vac.Add(b3Cup)
Next
' se non ho generato un Box esco
If b3Vac.IsEmpty() Then Return INFINITO
' Se box maggiore di quello del pezzo, scarto soluzione
If b3Vac.Radius() > b3Raw.Radius() Then Return INFINITO
' Determino il movimento per portare il set di camere sopra al pezzo
vtMove = ptRawCen - b3Vac.Center()
b3Vac.Move(vtMove)
' Determino la rotazione, allineando il lato lungo delle ventose con quello del grezzo
ptRotCen = b3Vac.Center()
' angolo preferenziale di afferraggio
dRotAngDeg = m_dPreferredRot + dRotAngDeg
'Dim frMinRect As New Frame3d
'If EgtCurveMinAreaRectangleXY(nOutlineId, GDB_ID.ROOT, frMinRect) Then
' Dim dLen, dAngVertDeg, dAngOrizzDeg As Double
' frMinRect.VersX().ToSpherical(dLen, dAngVertDeg, dAngOrizzDeg)
' dRotAngDeg = dAngOrizzDeg
' If b3Vac.DimY() > b3Vac.DimX() + EPS_SMALL Then dRotAngDeg -= 90
' Dim dAngDelta As Double = If(Math.Abs(b3Vac.DimY() - b3Vac.DimX()) < 10 * EPS_SMALL, 90, 180)
' While dRotAngDeg - m_dPreferredRot >= dAngDelta / 2
' dRotAngDeg -= dAngDelta
' End While
' While dRotAngDeg - m_dPreferredRot <= -dAngDelta / 2
' dRotAngDeg += dAngDelta
' End While
'Else
' dRotAngDeg = 0
' If (b3Vac.DimX() >= b3Vac.DimY() And b3Raw.DimX() < b3Raw.DimY()) Or
' (b3Vac.DimX() < b3Vac.DimY() And b3Raw.DimX() >= b3Raw.DimY()) Then
' dRotAngDeg = m_dPreferredRot
' End If
'End If
' cosrtuisco un array con gli Identificativi delle ventose
Dim nCups(sCups.Length() - 1) As Integer
For nJ As Integer = 0 To sCups.Length() - 1
nCups(nJ) = EgtGetFirstNameInGroup(m_nVacId, sCups(nJ))
Next
' Angoli di prova
Dim vAngRot As New List(Of Double)
'' Se asse rotante ventosa a step
'If GetVacRotAxisSteps(vAngRot) Then
' ' Ordino secondo distanza angolare crescente da direzione di allineamento (modulo 180 deg)
' Dim dRotRefDeg As Double = dRotAngDeg
' vAngRot.Sort(Function(P, Q)
' Dim dDiffP = Math.Abs(P - dRotRefDeg)
' If Math.Abs(dDiffP - 180) < 10 * EPS_ANG_SMALL Then dDiffP = 1
' Dim dDiffQ = Math.Abs(Q - dRotRefDeg)
' If Math.Abs(dDiffQ - 180) < 10 * EPS_ANG_SMALL Then dDiffQ = 1
' Return CInt(dDiffP - dDiffQ)
' End Function)
' ' Annullo la rotazione di allineamento
' dRotAngDeg = 0
' ' altrimenti in continuo
'Else
' ' Assegno più valori di ricerca e conservo angolo di allineamento
' vAngRot.AddRange({0, +5, -5, +12.5, -12.5, +25, -25, +45, -45})
'End If
' Assegno più valori di ricerca e conservo angolo di allineamento
vAngRot.AddRange({0, +5, -5, +12.5, -12.5, +25, -25, +45, -45})
' Eseguo verifica delle ventose rispetto al grezzo
Dim bVacOk As Boolean = False
For i As Integer = 0 To vAngRot.Count() - 1
If TestVacuumCups(nCups, nRawRegId, vtMove, ptRotCen, dRotAngDeg + vAngRot(i)) Then
dRotAngDeg += vAngRot(i)
bVacOk = True
Exit For
End If
Next
If Not bVacOk Then Return INFINITO
' Recupero riferimento della testa ventose
Dim frCurrRef As New Frame3d
EgtFrame(m_nRefId, GDB_ID.ROOT, frCurrRef)
Dim ptRef As Point3d = frCurrRef.Orig()
' Applico movimento e rotazione al punto
ptRef.Move(vtMove)
ptRef.Rotate(ptRotCen, Vector3d.Z_AX(), dRotAngDeg)
' Ne calcolo la distanza dal centro della tavola
Dim b3Tab As New BBox3d
EgtGetTableArea(1, b3Tab)
Dim dDist As Double = Point3d.DistXY(ptRef, b3Tab.Center())
Return dDist
End Function
Private Function TestVacuumCups(nCups() As Integer, nRawRegId As Integer,
vtMove As Vector3d, ptRotCen As Point3d, dRotAngDeg As Double) As Boolean
' Eseguo verifica delle ventose rispetto al grezzo
Dim bVacOk As Boolean = True
For nJ As Integer = 0 To nCups.Length() - 1
' recupero l'id della ventosa corrente
Dim nCupId = nCups(nJ)
' Eseguo rototraslazione delle ventose per verificare se sono contenute nel grezzo
EgtMove(nCupId, vtMove, GDB_RT.GLOB)
EgtRotate(nCupId, ptRotCen, Vector3d.Z_AX(), dRotAngDeg, GDB_RT.GLOB)
' Confronto le regioni
If EgtSurfFrChunkSimpleClassify(nRawRegId, 0, nCupId, 0) <> REGC.IN2 Then bVacOk = False
' Annullo rototraslazione
EgtRotate(nCupId, ptRotCen, Vector3d.Z_AX(), -dRotAngDeg, GDB_RT.GLOB)
EgtMove(nCupId, -vtMove, GDB_RT.GLOB)
' Se verifica fallita, esco dal ciclo
If Not bVacOk Then Exit For
Next
Return bVacOk
End Function
Friend Function SaveOneMoveInfo(nId As Integer, rmData As RawMoveData) As Boolean
' Assegno le informazioni
EgtSetInfo(nId, "Id", rmData.m_nId)
EgtSetInfo(nId, "Mv", rmData.m_vtRawMove)
EgtSetInfo(nId, "Rr", rmData.m_dRawAngRotDeg)
EgtSetInfo(nId, "Dt", rmData.m_vtDelta)
EgtSetInfo(nId, "Ad", rmData.m_dAngRotDeg)
EgtSetInfo(nId, "Vc", rmData.m_sCups)
EgtSetInfo(nId, "Vt", GetVacuumType())
Return True
End Function
Friend Function RemoveOneMoveInfo(nId As Integer) As Boolean
' Rimuovo le informazioni
EgtRemoveInfo(nId, "Id")
EgtRemoveInfo(nId, "Mv")
EgtRemoveInfo(nId, "Rr")
EgtRemoveInfo(nId, "Dt")
EgtRemoveInfo(nId, "Ad")
EgtRemoveInfo(nId, "Vc")
EgtRemoveInfo(nId, "Vt")
Return True
End Function
Friend Function SaveOneMoveInfoInDisposition(nDispId As Integer, rmData As RawMoveData) As Boolean
' Se movimento e rotazione trascurabili, inutile salvare
If rmData.m_vtRawMove.IsSmall() AndAlso Math.Abs(rmData.m_dRawAngRotDeg) < EPS_ANG_SMALL Then Return True
' Creo il gruppo
Dim nRpmId As Integer = EgtCreateGroup(nDispId)
If nRpmId = GDB_ID.NULL Then Return False
EgtSetName(nRpmId, "Rpm" & rmData.m_nId.ToString())
' Assegno le informazioni
SaveOneMoveInfo(nRpmId, rmData)
Return True
End Function
Friend Function SaveMoveInfoInDisposition(nDispId As Integer, rmList As List(Of RawMoveData)) As Boolean
' Verifico DispId
If EgtGetOperationType(nDispId) <> MCH_OY.DISP Then Return False
' aggiungo al gruppo disposizione dei sottogruppi con i dati di movimento dei grezzi spostati
For Each rmData As RawMoveData In rmList
If Not SaveOneMoveInfoInDisposition(nDispId, rmData) Then Return False
Next
Return True
End Function
Friend Function GetMoveInfoInDisposition(nDispId As Integer, ByRef rmList As List(Of RawMoveData)) As Boolean
' Verifico DispId
If EgtGetOperationType(nDispId) <> MCH_OY.DISP Then Return False
' Recupero i gruppi con i dati
Dim nRpmId As Integer = EgtGetFirstNameInGroup(nDispId, "Rpm*")
While nRpmId <> GDB_ID.NULL
' Recupero le informazioni
Dim rmData As New RawMoveData
EgtGetInfo(nRpmId, "Id", rmData.m_nId)
EgtGetInfo(nRpmId, "Mv", rmData.m_vtRawMove)
EgtGetInfo(nRpmId, "Rr", rmData.m_dRawAngRotDeg)
EgtGetInfo(nRpmId, "Dt", rmData.m_vtDelta)
EgtGetInfo(nRpmId, "Ad", rmData.m_dAngRotDeg)
EgtGetInfo(nRpmId, "Vc", rmData.m_sCups)
EgtGetInfo(nRpmId, "Vt", GetVacuumType())
' se non già presenti, le inserisco nella lista
If FindRawMoveData(rmData.m_nId, rmList) = -1 Then
rmList.Add(rmData)
End If
' Cerco un altro gruppo
nRpmId = EgtGetNextName(nRpmId, "Rpm*")
End While
Return True
End Function
Friend Function FindRawMoveData(nRawId As Integer, ByRef rmList As List(Of RawMoveData)) As Integer
' Cerco in lista record con dati del grezzo indicato
Dim nInd As Integer = -1
For i As Integer = 0 To rmList.Count() - 1
If rmList(i).m_nId = nRawId Then
nInd = i
Exit For
End If
Next
Return nInd
End Function
Private Function AddRawMoveData(nRawId As Integer, ByRef rmList As List(Of RawMoveData)) As Integer
' Cerco in lista record con dati del grezzo indicato
Dim nInd As Integer = -1
For i As Integer = 0 To rmList.Count() - 1
If rmList(i).m_nId = nRawId Then
nInd = i
Exit For
End If
Next
' Se trovato
If nInd <> -1 Then
' Se con movimenti trascurabili e non alla fine, lo sposto alla fine
If rmList(nInd).m_vtRawMove.IsSmall() AndAlso Math.Abs(rmList(nInd).m_dRawAngRotDeg) < EPS_ANG_SMALL AndAlso nInd <> rmList.Count() - 1 Then
rmList.Add(rmList(nInd))
rmList.RemoveAt(nInd)
nInd = rmList.Count() - 1
End If
' Se non trovato, lo accodo
Else
rmList.Add(New RawMoveData(nRawId))
nInd = rmList.Count() - 1
End If
Return nInd
End Function
Friend Function AddRawMoveData(nRawId As Integer, vtMove As Vector3d, ByRef rmList As List(Of RawMoveData)) As Integer
' Recupero o creo record con dati del grezzo indicato
Dim nInd As Integer = AddRawMoveData(nRawId, rmList)
If nInd = -1 Then Return -1
' Aggiorno i valori
rmList(nInd).m_vtRawMove += vtMove
Return nInd
End Function
Friend Function AddRawMoveData(nRawId As Integer, dRawAngRotDeg As Double, ByRef rmList As List(Of RawMoveData)) As Integer
' Recupero o creo record con dati del grezzo indicato
Dim nInd As Integer = AddRawMoveData(nRawId, rmList)
If nInd = -1 Then Return -1
' Aggiorno i valori
rmList(nInd).m_dRawAngRotDeg += dRawAngRotDeg
Return nInd
End Function
Friend Function AddRawMoveData(rmData As RawMoveData, ByRef rmList As List(Of RawMoveData)) As Integer
' Recupero o creo record con dati del grezzo indicato
Dim nInd As Integer = AddRawMoveData(rmData.m_nId, rmList)
If nInd = -1 Then Return -1
' Aggiorno i valori (tengo conto di quanto già ruotato il pezzo)
Dim vtDeltaRot As New Vector3d(rmData.m_vtDelta)
vtDeltaRot.Rotate(Vector3d.Z_AX(), -rmList(nInd).m_dRawAngRotDeg)
rmList(nInd).m_vtDelta = vtDeltaRot
rmList(nInd).m_dAngRotDeg = rmData.m_dAngRotDeg - rmList(nInd).m_dRawAngRotDeg
rmList(nInd).m_sCups = rmData.m_sCups
Return nInd
End Function
Friend Sub RemoveRawMoveData(nRawId As Integer, ByRef rmList As List(Of RawMoveData))
' Cerco in lista record con dati del grezzo indicato
Dim nInd As Integer = -1
For i As Integer = 0 To rmList.Count() - 1
If rmList(i).m_nId = nRawId Then
nInd = i
Exit For
End If
Next
' Se trovato, lo elimino
If nInd >= 0 Then
rmList.RemoveAt(nInd)
End If
End Sub
Friend Function SaveRemoveByHandInDisposition(nDispId As Integer, bRemoveByHand As Boolean) As Boolean
' Verifico DispId
If EgtGetOperationType(nDispId) <> MCH_OY.DISP Then Return False
' Imposto flag
EgtSetInfo(nDispId, "Rbh", bRemoveByHand)
Return True
End Function
Friend Function GetRemoveByHandInDisposition(nDispId As Integer) As Boolean
' Verifico DispId
If EgtGetOperationType(nDispId) <> MCH_OY.DISP Then Return False
' Leggo flag
Dim bRemoveByHand As Boolean = False
EgtGetInfo(nDispId, "Rbh", bRemoveByHand)
Return bRemoveByHand
End Function
Friend Function SaveMovePartsOnAuxTable(nDispId As Integer, bMovePartsOnAuxTab As Boolean) As Boolean
' Verifico DispId
If EgtGetOperationType(nDispId) <> MCH_OY.DISP Then Return False
' Imposto flag
EgtSetInfo(nDispId, "Pat", bMovePartsOnAuxTab)
Return True
End Function
End Module
' in precedenza era di tipo friend ed interno al modulo sopra, portato fuori per poter salvare in ogni pezzo queste info
Public Class RawMoveData
Public m_nId As Integer
Public m_vtRawMove As Vector3d
Public m_dRawAngRotDeg As Double
Public m_vtDelta As Vector3d
Public m_dAngRotDeg As Double
Public m_sCups As String
' vettore centro-vertice on alto a sinistra MinimoRettangolo
Public m_vtRect As New Vector3d
' versore del lato più lungo nel sistema assoluto
Public m_vtDirX As New Vector3d
Public m_vtOrtoDirX As New Vector3d
' centro del rettangolo minimo
Public m_ptCenMinRect As New Point3d
' posizione ventose perpendicolari
Public m_bCupsSecondSel As Boolean = False
Sub New()
m_nId = GDB_ID.NULL
m_vtRawMove = Vector3d.NULL()
m_dRawAngRotDeg = 0
m_vtDelta = Vector3d.NULL()
m_dAngRotDeg = 0
m_sCups = String.Empty
End Sub
Sub New(nId As Integer)
m_nId = nId
m_vtRawMove = Vector3d.NULL()
m_dRawAngRotDeg = 0
m_vtDelta = Vector3d.NULL()
m_dAngRotDeg = 0
m_sCups = String.Empty
End Sub
End Class