Imports EgtUILib Module SideAngle Private m_MainWindow As MainWindow = DirectCast(Application.Current.MainWindow, MainWindow) Friend Sub WriteSideAngleForNest(nCtx As Integer) ' Imposto contesto corrente EgtSetCurrentContext(nCtx) Dim PartId As Integer = EgtGetFirstPart() While PartId <> GDB_ID.NULL ' Se richiesti lati paralleli con misura sul top come in TRF e non già misure sul top, verifico e aggiusto If GetPrivateProfileInt( S_SIDES, K_PARSIDE_AS_TRF, 0, m_MainWindow.GetIniFile()) <> 0 AndAlso GetPrivateProfileInt( S_SIDES, K_SIZEALWAYSONTOP, 0, m_MainWindow.GetIniFile()) = 0 Then AdjustAsTrfParSides( PartId) End If ' Elimino eventuale precedente layer per testi EgtErase(EgtGetFirstNameInGroup(PartId, SIDE_ANGLE_LAYER)) ' Creo layer per testi nesting Dim TextLayId As Integer = EgtCreateGroup(PartId) EgtSetName(TextLayId, SIDE_ANGLE_LAYER) EgtSetColor(TextLayId, New Color3d(0, 0, 128)) ' Opero su geometria esterna pezzo WriteSideAngleOnLoop(EgtGetFirstNameInGroup(PartId, NAME_OUTLOOP), TextLayId) ' Ciclo su geometria interna pezzo Dim LoopId As Integer = EgtGetFirstNameInGroup(PartId, NAME_INLOOP) While LoopId <> GDB_ID.NULL WriteSideAngleOnLoop(LoopId, TextLayId) LoopId = EgtGetNextName(LoopId, NAME_INLOOP) End While PartId = EgtGetNextPart(PartId) End While End Sub ' Funzione che verifica se la linea corrente è inclinabile in base al tipo della precedente e successiva Friend Function VerifySideAnglePossible(LastLine As Integer, CurrLine As Integer, NextLine As Integer, bOutLoop As Boolean) As Boolean ' Se WaterJet si tolgono i limiti Dim bSideFree As Boolean = m_MainWindow.m_CurrentMachine.bWaterJetting ' Analisi del tipo Select EgtGetType(CurrLine) Case GDB_TY.CRV_LINE ' Le linee vanno bene di per sè Case GDB_TY.CRV_ARC If Not bSideFree Then ' Gli archi devono essere lavorati sul lato esterno Dim dAngCen As Double : EgtArcAngCenter( CurrLine, dAngCen) If ( bOutLoop And dAngCen < 0) Or ( Not bOutLoop And dAngCen > 0) Then Return False End If Case GDB_TY.CRV_COMPO If Not bSideFree Then ' Gli archi componenti devono essere lavorati sul lato esterno Dim nCopyId As Integer = EgtCopy( CurrLine, CurrLine, GDB_POS.AFTER) If nCopyId = GDB_ID.NULL Then Return False Dim bOk As Boolean = True Dim nCount As Integer = 0 Dim nNewId As Integer = EgtExplodeCurveCompo( nCopyId, nCount) For nI As Integer = 0 To nCount - 1 Dim nEntId As Integer = nNewId + nI If EgtGetType( nEntId) = GDB_TY.CRV_ARC Then Dim dAngCen As Double : EgtArcAngCenter( nEntId, dAngCen) If ( bOutLoop And dAngCen < 0) Or ( Not bOutLoop And dAngCen > 0) Then bOk = False End If EgtErase( nEntId) Next If Not bOk Then Return False End If Case Else Return False End Select ' Se curva chiusa va bene solo se loop esterno if Not bSideFree AndAlso EgtCurveIsClosed( CurrLine) Then Return bOutLoop ' Delta angolare limite per tangenza Const DELTA_ANG_TG_DEF As Double = 5.0 Dim dDeltaAngTg As Double = GetPrivateProfileDouble(S_SIDES, K_DELTA_ANG_TG, DELTA_ANG_TG_DEF, m_MainWindow.GetIniFile()) if bSideFree Then dDeltaAngTg = 0 ' Verifico se curva precedente mi permette di inclinare Dim bLastOk As Boolean = False Select EgtGetType(LastLine) Case GDB_TY.CRV_LINE, GDB_TY.CRV_ARC, GDB_TY.CRV_COMPO ' Ricavo direzione finale curva precedente Dim vtLastEnd As Vector3d EgtEndVector(LastLine, vtLastEnd) ' Ricavo direzione iniziale curva corrente Dim vtCurrStart As Vector3d EgtStartVector(CurrLine, vtCurrStart) ' Confronto direzioni per vedere se sono tangenti Dim dAngDeg As Double = GetAngle( vtLastEnd, vtCurrStart) ' verifico se l'angolo è significativo bLastOk = ( dDeltaAngTg < EPS_ANG_SMALL Or dAngDeg > dDeltaAngTg) Case Else EgtOutLog("Error in Compo Outloop: found an entity that is not a line or a arc") End Select ' Verifico se curva successiva mi permette di inclinare Dim bNextOk As Boolean = False Select EgtGetType(NextLine) Case GDB_TY.CRV_LINE, GDB_TY.CRV_ARC, GDB_TY.CRV_COMPO ' Ricavo direzione finale curva corrente Dim vtCurrEnd As Vector3d EgtEndVector(CurrLine, vtCurrEnd) ' Ricavo direzione iniziale curva successiva Dim vtNextStart As Vector3d EgtStartVector(NextLine, vtNextStart) ' Confronto direzioni per vedere se sono tangenti Dim dAngDeg As Double = GetAngle( vtCurrEnd, vtNextStart) ' verifico se l'angolo è significativo bNextOk = ( dDeltaAngTg < EPS_ANG_SMALL Or dAngDeg > dDeltaAngTg) Case Else EgtOutLog("Error in Compo Outloop: found an entity that is not a line or a arc") End Select ' Se entrambe me lo permettono restituisco vero Return ( bLastOk And bNextOk) End Function Private Function AdjustAsTrfParSides( PartId As Integer) As Boolean ' Recupero il loop esterno Dim LoopId As Integer = EgtGetFirstNameInGroup(PartId, NAME_OUTLOOP) If LoopId = GDB_ID.NULL Then Return False ' Scansiono i lati Dim LineId As Integer = EgtGetFirstInGroup(LoopId) While LineId <> GDB_ID.NULL ' Se non è linea con singolo angolo, vado oltre If Not EgtExistsInfo(LineId, INFO_SIDE_ANGLE) OrElse EgtExistsInfo(LineId, INFO_SIDE_ANGLE2) OrElse EgtExistsInfo(LineId, INFO_HEEL) Then LineId = EgtGetNext(LineId) Continue While End If ' Recupero angolo di fianco e direzione Dim dSideAng As Double = 0 : EgtGetInfo( LineId, INFO_SIDE_ANGLE, dSideAng) Dim vtDir As new Vector3d : EgtStartVector( LineId, GDB_ID.ROOT, vtDir) ' Confronto con le linee successive Dim OthLId As Integer = EgtGetNext(LineId) While OthLId <> GDB_ID.NULL ' Se non è linea con singolo angolo, vado oltre If Not EgtExistsInfo(OthLId, INFO_SIDE_ANGLE) OrElse EgtExistsInfo(OthLId, INFO_SIDE_ANGLE2) OrElse EgtExistsInfo(OthLId, INFO_HEEL) Then OthLId = EgtGetNext(OthLId) Continue While End If ' Recupero angolo di fianco e direzione Dim dOthSAng As Double = 0 : EgtGetInfo( OthLId, INFO_SIDE_ANGLE, dOthSAng) Dim vtOthDir As new Vector3d : EgtStartVector( OthLId, GDB_ID.ROOT, vtOthDir) ' Se gli angoli sono opposti e le due linee sono controverse If Math.Abs( dSideAng + dOthSAng) < 10 * EPS_ANG_SMALL AndAlso (vtDir + vtOthDir).IsSmall() Then EgtSetInfo( LineId, INFO_SIDE_FIXED, 1) EgtSetInfo( OthLId, INFO_SIDE_FIXED, 1) Exit While End If OthLId = EgtGetNext(OthLId) End While LineId = EgtGetNext(LineId) End While Return True End Function Private Function WriteSideAngleOnLoop(LoopId As Integer, TextLayId As Integer) As Boolean ' Verifiche If LoopId = GDB_ID.NULL Or TextLayId = GDB_ID.NULL Then Return False ' Calcolo dimensione ingombro Loop Dim ptMin, ptMax As Point3d EgtGetBBoxGlob(LoopId, GDB_BB.STANDARD, ptMin, ptMax) Dim dBBoxRad As Double = 0.5 * Point3d.DistXY(ptMin, ptMax) ' Ciclo sulle curve di contorno, se hanno info con inclinazione aggiungo testo con angolo Dim LineId As Integer = EgtGetFirstInGroup(LoopId) While LineId <> GDB_ID.NULL Dim dSideAngle As Double = 0 Dim bSA As Boolean = EgtGetInfo(LineId, INFO_SIDE_ANGLE, dSideAngle) Dim dSideAngle2 As Double = 0 Dim bSA2 As Boolean = EgtGetInfo(LineId, INFO_SIDE_ANGLE2, dSideAngle2) Dim dSideHeel As Double = 0 Dim bSH As Boolean = EgtGetInfo(LineId, INFO_HEEL, dSideHeel) If Math.Abs(dSideAngle) > EPS_ANG_SMALL Or ( bSA2 And Not bSH) Then ' Creo testo con angolo di inclinazione Dim sText As String = DoubleToString(dSideAngle, 2) & "°" ' Se presente tallone, lo indico If bSH then If dSideHeel > 10 * EPS_SMALL Then If dSideAngle > 0 Then sText = sText & "; " & LenToString(dSideHeel, 2) Else sText = LenToString(dSideHeel, 2) & "; " & sText End If End If ' se altrimenti presente secondo angolo, lo indico ElseIf bSA2 then sText = DoubleToString(dSideAngle2, 2) & "°" & "; " & sText End If AddTextToLine(sText, TextLayId, LineId, 15, dBBoxRad, False, True) End If LineId = EgtGetNext(LineId) End While Return True End Function Friend Sub ColorToSideAngle(nCtx As Integer) ' Leggo dati corrispondenza colore-angolo Dim CurrCSA As New ColorSideAngs CurrCSA.Read( m_MainWindow.GetIniFile) ' Imposto contesto corrente EgtSetCurrentContext(nCtx) ' Ciclo sui pezzi Dim PartId As Integer = EgtGetFirstPart() While PartId <> GDB_ID.NULL ' Ciclo sui layer di contorno Dim bOutLoop As Boolean = True Dim LoopId As Integer = EgtGetFirstNameInGroup(PartId, NAME_OUTLOOP) While LoopId <> GDB_ID.NULL ' Ciclo sulle curve Dim PrevId As Integer = EgtGetLastInGroup( LoopId) Dim EntId As Integer = EgtGetFirstInGroup( LoopId) While EntId <> GDB_ID.NULL Dim NextId As Integer = EgtGetNext( EntId) If NextId = GDB_ID.NULL Then NextId = EgtGetFirstInGroup( LoopId) If VerifySideAnglePossible( PrevId, EntId, NextId, bOutLoop) Then Dim colEnt As Color3d If EgtGetColor( EntId, colEnt) Then Dim dAng As Double Dim dHeel As Double If CurrCSA.GetSideAngHeel( colEnt, dAng, dHeel) Then EgtSetInfo( EntId, INFO_SIDE_ANGLE, dAng) EgtSetInfo( EntId, INFO_ORIG_SIDE_ANGLE, dAng) EgtSetInfo( EntId, INFO_HEEL, dHeel) End If End If End If PrevId = EntId EntId = EgtGetNext( EntId) End While If bOutLoop then bOutLoop = False LoopId = EgtGetFirstNameInGroup(PartId, NAME_INLOOP) Else LoopId = EgtGetNextName(LoopId, NAME_INLOOP) End If End While PartId = EgtGetNextPart(PartId) End While ' Aggiorno scritte per angoli sui lati WriteSideAngleForNest(nCtx) End Sub ' Funzione che dato un segmento e una distanza, scrive il testo centrato alla sua sinistra (destra se bTextExt) Friend Function AddTextToLine(sText As String, TextLayer As Integer, CurrLine As Integer, dDistance As Double, dBBoxRad As Double, bTextExt As Boolean, Optional bRot As Boolean = False) As Integer ' Calcolo altezza testo Dim dH As Double = 0.05 * dBBoxRad ' Creo testo Dim nText As Integer = EgtCreateTextAdv(TextLayer, Point3d.ORIG(), 0, sText, "", 500, False, dH, 1, 0, INS_POS.MC) ' Calcolo posizionamento ' BBox del testo e suo centro Dim ptMinBBox As Point3d Dim ptMaxBBox As Point3d EgtGetBBox(nText, GDB_BB.STANDARD, ptMinBBox, ptMaxBBox) Dim ptMidBBox As Point3d ptMidBBox = Point3d.Media(ptMinBBox, ptMaxBBox) ' Punto medio della curva Dim ptMid As Point3d EgtMidPoint( CurrLine, nText, ptMid) ' Versore sul punto medio della curva Dim vtMid As Vector3d EgtMidVector( CurrLine, nText, vtMid) ' versore perpendicolare alla CurrLine che punta verso il testo Dim vtOrto As New Vector3d( vtMid) If bTextExt Then vtOrto.Rotate( Vector3d.Z_AX(), -90) Else vtOrto.Rotate( Vector3d.Z_AX(), 90) End If ' eventuale rotazione del testo Dim dRotAng As Double = 0 If bRot Then dRotAng = Math.Atan2( vtMid.y, vtMid.x) * 180 / Math.PI Dim dSpecRotAng = dRotAng If dSpecRotAng > 91 Then dSpecRotAng -= 180 ElseIf dSpecRotAng < -89 Then dSpecRotAng += 180 End If EgtRotate(nText, Point3d.ORIG(), Vector3d.Z_AX(), dSpecRotAng) End If ' vettore dal centro del BBox all'estremo più vicino Dim vtptExtptMC As Vector3d If bRot Then vtptExtptMC = New Vector3d(0, ptMidBBox.y - ptMinBBox.y, 0) vtptExtptMC.Rotate(Vector3d.Z_AX(), dRotAng) Else If bTextExt Then If vtMid.x > 0 Then If vtMid.y > 0 Then vtptExtptMC = ptMidBBox - New Point3d(ptMinBBox.x, ptMaxBBox.y, 0) Else vtptExtptMC = ptMidBBox - ptMaxBBox End If Else If vtMid.y > 0 Then vtptExtptMC = ptMidBBox - ptMinBBox Else vtptExtptMC = ptMidBBox - New Point3d(ptMaxBBox.x, ptMinBBox.y, 0) End If End If Else If vtMid.x > 0 Then If vtMid.y > 0 Then vtptExtptMC = ptMidBBox - New Point3d(ptMaxBBox.x, ptMinBBox.y, 0) Else vtptExtptMC = ptMidBBox - ptMinBBox End If Else If vtMid.y > 0 Then vtptExtptMC = ptMidBBox - ptMaxBBox Else vtptExtptMC = ptMidBBox - New Point3d(ptMinBBox.x, ptMaxBBox.y, 0) End If End If End If End If ' Calcolo il centro del testo Dim ptTextMC As Point3d = ptMid + vtOrto * (dDistance + (vtOrto * vtptExtptMC)) EgtMove(nText, (ptTextMC - Point3d.ORIG())) Return nText End Function '-------------------------------------------------------------------------------------------------- Friend Class ColorSideAngs Class CTSA Friend m_bOk As Boolean Friend m_R As Integer Friend m_G As Integer Friend m_B As Integer Friend m_dAng As Double Friend m_dHeel As Double End Class Private m_ListCtsa As New List(Of CTSA) Private m_nTol As Integer = 10 Friend Function Read( sIniFile As String) As Boolean ' Lettura parametri di conversione Dim nIndex As Integer = 1 Dim OneCtsa As CTSA = GetPrivateProfileColorSideAng( S_COLORTOSIDEANG, K_CTSA & nIndex, sIniFile) While Not IsNothing(OneCtsa) m_ListCtsa.Add(OneCtsa) nIndex += 1 OneCtsa = GetPrivateProfileColorSideAng( S_COLORTOSIDEANG, K_CTSA & nIndex, sIniFile) End While ' Lettura tolleranza m_nTol = GetPrivateProfileInt( S_COLORTOSIDEANG, K_CTSA_TOLERANCE, 10, sIniFile) Return True End Function Private Function GetPrivateProfileColorSideAng( sSect As String, sKey As String, sIniFile As String) As CTSA Dim OneCtsa As New CTSA Dim sVal As String = String.Empty GetPrivateProfileString(sSect, sKey, "", sVal, sIniFile) Dim sItems() As String = sVal.Split(",".ToCharArray) OneCtsa.m_bOk = If( sItems.Count() = 6, ( sItems(5).Trim() <> "0"), True) If sItems.Count() >= 5 Then StringToInt( sItems(0), OneCtsa.m_R) StringToInt( sItems(1), OneCtsa.m_G) StringToInt( sItems(2), OneCtsa.m_B) StringToDouble( sItems(3), OneCtsa.m_dAng) StringToDouble( sItems(4), OneCtsa.m_dHeel) Return OneCtsa End If Return Nothing End Function Friend Function GetSideAngHeel( cCol As Color3d, ByRef dAng As Double, ByRef dHeel As Double) As Boolean For Each Ctsa As CTSA In m_ListCtsa If Ctsa.m_bOk And Math.Abs( cCol.R - Ctsa.m_R) < m_nTol And Math.Abs( cCol.G - Ctsa.m_G) < m_nTol And Math.Abs( cCol.B - Ctsa.m_B) < m_nTol Then dAng = Ctsa.m_dAng dHeel = Ctsa.m_dHeel Return True End If Next Return False End Function End Class End Module