Imports System.Math
Public Class frmCompGranul
    Private ValS As Decimal = 0 'Récupération de la valeur de NudSable
    Private Sub Pb_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Pb.Paint
        Dim Verif As Boolean = True
        If ChkbAffichage2sables.Checked = True Then
            'Affichage des 2 sables
            Call Affichage_CourbeGranulo(e.Graphics, 1, 4,, Verif)
        Else
            Call Affichage_CourbeGranulo(e.Graphics, 1, 3,, Verif) '    Call Affichage_graphique(e)
        End If
        If Verif = False Then Exit Sub
        'Affichage courbe de mélange
        If ChkbMelange.Checked = True Then Call Affichage_Melange(e.Graphics)
    End Sub
    Private Sub frmCompGranul_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        ChkbMelange.ForeColor = Color.Fuchsia
        ChkbAffichage2sables.ForeColor = Color.Salmon
        Call Affichage()
        ValS = NudSable.Value
    End Sub

    Private Sub Affichage()
        Dim msg As String = String.Empty
        Dim msg1 As String = String.Empty
        Select Case Beton.NbSable
            Case 1
                msg = "d'un sable"
                LblSable1.Visible = False : NudSable1.Visible = False : LblSable1Pourcent.Visible = False
                LblSable2.Visible = False : LblSable2Txt.Visible = False : LblSable2Pourcent.Visible = False
                ChkbAffichage2sables.Visible = False
            Case 2
                msg = "de deux sables"
                LblSable1.Visible = True : NudSable1.Visible = True : LblSable1Pourcent.Visible = True
                NudSable1.Value = Sable.Item(0).S_Vs
                LblSable2.Visible = True : LblSable2Txt.Visible = True : LblSable2Pourcent.Visible = True
                LblSable2Txt.Text = Sable.Item(1).S_Vs.ToString("#0")
                ChkbAffichage2sables.Visible = True
        End Select
        Select Case Beton.NbGravillon
            Case 1
                msg1 = "d'un gravillon." : LblGravillon.Text = Gravillon.Item(0).G_Vg.ToString("#0")
                LblGravillon1.Visible = False : NudGravillon1.Visible = False : LblGravillon1Pourcent.Visible = False
                LblGravillon2.Visible = False : LblGravillon2Txt.Visible = False : LblGravillon2Pourcent.Visible = False
            Case 2
                msg1 = "de deux gravillons." : LblGravillon.Text = (100 - Beton.S_Vs).ToString("#0")
                LblGravillon1.Visible = True : NudGravillon1.Visible = True : LblGravillon1Pourcent.Visible = True
                NudGravillon1.Value = Gravillon.Item(0).G_Vg
                LblGravillon2.Visible = True : LblGravillon2Txt.Visible = True : LblGravillon2Pourcent.Visible = True
                LblGravillon2Txt.Text = Gravillon.Item(1).G_Vg.ToString("#0")
        End Select
        LblMelange.Text = "Proportion du mélange " & msg & " et " & msg1
        NudSable.Value = Beton.S_Vs
    End Sub

    Private Sub BtnReinitialisation_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BtnReinitialisation.Click
        'Demande de Reinitialisation du mélange granulaire
        NudSable.Value = Beton.S_Vs
        LblGravillon.Text = (100 - NudSable.Value).ToString("#0")
        If Beton.NbSable = 2 Then
            NudSable1.Value = Sable.Item(0).S_Vs
            LblSable2Txt.Text = Sable.Item(1).S_Vs.ToString("#0")
        End If
        If Beton.NbGravillon = 2 Then
            NudGravillon1.Value = Gravillon.Item(0).G_Vg
            LblGravillon2Txt.Text = Gravillon.Item(1).G_Vg.ToString("#0")
        End If
    End Sub
    Private Sub ChkbMelange_CheckedChanged(sender As Object, e As EventArgs) Handles ChkbMelange.CheckedChanged
        If ChkbMelange.Checked = True Then NudSable.Enabled = True Else NudSable.Enabled = False
        Pb.Refresh() 'Affichage du nouveau mélange granulaire
    End Sub
    Private Sub Affichage_Melange(ByVal g As Graphics) 'ByVal Support As Integer,
        Dim i, j, k, k1 As Integer
        Dim X, Y, X1 As Single
        Dim myPen As New Pen(Color.Black, 1)
        Dim Ym(32) As Double
        Dim d1, d2, d3 As Integer
        'Affichage des points
        'Passant en %
        j = 0 : k = 0 ': Y = 50 '
        Dim xx(32), yy(32) As Single
        'écran 1070x700
        X1 = 50 : k1 = 19 'ou(gravillon, l) 'analyse commence à 0.063mm
        d1 = 30 : d2 = 650 : d3 = 6

        'Dans un 1ier temps calcul uniquement avec 1 sables et 1 gravillon
        Call Calcul_Melange(Ym)

        For i = 0 To 31 '31 = ligne verticale 80 mm
            If Ym(i) <> -1 Then
                If i = 0 Then X = X1 Else X = X1 + j
                k = k + 1 : xx(k) = X
                Y = CSng(d2 - Ym(i) * d3) : yy(k) = Y
                g.DrawRectangle(Pens.BlueViolet, X - 2, Y - 2, 4, 4)
            Else

            End If
            j += d1
        Next

        i = k
        Dim hi(k - 1), Hn(k, k), Cn(k), Yn(k) As Double
        Dim verif As Boolean = True
        For i = 1 To k
            xx(i - 1) = xx(i) 'démarrage à 0 au lieu de 1
            yy(i - 1) = yy(i)
        Next
        For i = 1 To k
            hi(i - 1) = xx(i) - xx(i - 1)
        Next
        'ligne 1
        i = 1
        Yn(i) = ((yy(i + 1) - yy(i)) / hi(i)) - ((yy(i) - yy(i - 1)) / hi(i - 1))
        Hn(i, i) = (hi(i - 1) + hi(i)) / 3
        Hn(i, i + 1) = hi(i) / 6
        'ligne k-2
        i = k - 2
        Yn(i) = ((yy(i + 1) - yy(i)) / hi(i)) - ((yy(i) - yy(i - 1)) / hi(i - 1))
        Hn(i, i - 1) = hi(i - 1) / 6
        Hn(i, i) = (hi(i - 1) + hi(i)) / 3
        'Autres lignes
        For i = 2 To k - 3 'ligne
            Yn(i) = ((yy(i + 1) - yy(i)) / hi(i)) - ((yy(i) - yy(i - 1)) / hi(i - 1))
            Hn(i, i - 1) = hi(i - 1) / 6
            Hn(i, i) = (hi(i - 1) + hi(i)) / 3
            Hn(i, i + 1) = hi(i) / 6
        Next
        Call Gauss_Pivot_Max(k - 2, Hn, Yn, Cn, verif)
        If verif = False Then Exit Sub
        'affichage de 3 droites par segment
        Dim xs(2, k - 2), ys(2, k - 2), xi As Single
        For i = 0 To k - 2
            xs(1, i) = CSng(xx(i) + hi(i) / 3)
            xs(2, i) = CSng(xx(i) + (2 * hi(i) / 3))
        Next
        Cn(0) = 0 : Cn(k - 1) = 0 : k1 = 1
        For i = 0 To k - 2
            For j = 1 To 2
                xi = xs(j, i)
                ys(j, i) = CSng((Cn(i) / 6) * (((xx(i + 1) - xi) ^ 3 / hi(i)) - hi(i) * (xx(i + 1) - xi)))
                ys(j, i) += CSng((Cn(i + 1) / 6) * (((xi - xx(i)) ^ 3 / hi(i)) - hi(i) * (xi - xx(i))))
                ys(j, i) += CSng((yy(i) * (xx(i + 1) - xi) / hi(i)) + (yy(i + 1) * (xi - xx(i)) / hi(i)))
            Next
        Next
        myPen = New Pen(Color.Fuchsia, 2)
        For i = 0 To k - 2
            g.DrawLine(myPen, xx(i), yy(i), xs(1, i), ys(1, i)) '1ier segment
            g.DrawLine(myPen, xs(1, i), ys(1, i), xs(2, i), ys(2, i)) '2ième segment
            g.DrawLine(myPen, xs(2, i), ys(2, i), xx(i + 1), yy(i + 1)) '3ième segment

        Next
        Erase xs, ys, hi, Hn, Cn, Yn, xx, yy
    End Sub
    Private Sub Calcul_Melange(ByRef Ym() As Double)
        Dim Total_S, Total_G, Total_Ginf, Total_Ssup As Double
        Dim i, i1, i2, Total As Integer 'k1, 
        'dimension 32
        'Répartition mélange
        Total = 1000
        Total_S = NudSable.Value * Total / 100 '
        Total_G = (100 - NudSable.Value) * Total / 100 ' (100 - Beton.S_Vs) * Total / 100
        'sable
        Total_Ssup = 0
        Dim iTa() As Double = {0.063, 0.08, 0.1, 0.125, 0.16, 0.2, 0.25, 0.315, 0.4, 0.5, 0.63, 0.8, 1, 1.25, 1.6, 2, 2.5, 3.15, 4, 5, 6.3, 8, 10}
        For i = 0 To 11 'je m'arrête à 11 = 0.8 voir gravillon pour le reste 'dimension des tamis du sable   k1 = 23
            If Beton.NbSable = 2 AndAlso Sable.Count > 2 Then i1 = 2 Else i1 = 0
            With Sable.Item(i1)
                If .Disponibilite_Tamis.Item(iTa(i)) = True Then  'AndAlso .TamisatCumule_Pourcent.ContainsKey(iiTa(i))
                    Ym(i) = .TamisatCumule_Pourcent(iTa(i)) * Total_S / Total 'Ym(i) reste donc en %
                    If .TamisatCumule_Pourcent(iTa(i)) > 98 Then Total_Ssup = Total_S 'pour indiquer que nous sommes arrivés à 100% de passant
                Else
                    Ym(i) = -1 'ce qui signifie qu'il n'y a pas eu de mesure sur le tamis i correspondant
                End If
            End With
        Next
        '--> Calcul mélange(s) avec courbe(s) Gravillon(s)
        i2 = 0
        If Beton.NbGravillon = 2 AndAlso Gravillon.Count = 2 Then
            'ajout d'un 3ième Gravillon qui sera le Gravillon composé
            Dim GravillonCompose As New clsGravillon
            Dim TotalGravillon As Double
            Dim ValeurprecedenteS1, ValeurPrecedenteS2, totalGrav As Integer
            With Gravillon
                GravillonCompose.Disponibilite_Tamis = .Item(0).Disponibilite_Tamis
                totalGrav = CInt(100 - NudSable.Value)
                For Each kvp As KeyValuePair(Of Double, Boolean) In .Item(1).Disponibilite_Tamis
                    If GravillonCompose.Disponibilite_Tamis.ContainsKey(kvp.Key) AndAlso GravillonCompose.Disponibilite_Tamis(kvp.Key) = False AndAlso .Item(1).Disponibilite_Tamis(kvp.Key) = True Then
                        GravillonCompose.Disponibilite_Tamis(kvp.Key) = True
                    End If
                Next
                GravillonCompose.TamisatCumule_Pourcent.Clear() : ValeurprecedenteS1 = 0 : ValeurPrecedenteS2 = 0
                For Each kvp As KeyValuePair(Of Double, Boolean) In GravillonCompose.Disponibilite_Tamis
                    If .Item(0).TamisatCumule_Pourcent(kvp.Key) = 0 And ValeurprecedenteS1 = 100 Then .Item(0).TamisatCumule_Pourcent(kvp.Key) = 100
                    If .Item(1).TamisatCumule_Pourcent(kvp.Key) = 0 And ValeurPrecedenteS2 = 100 Then .Item(1).TamisatCumule_Pourcent(kvp.Key) = 100
                    TotalGravillon = (NudGravillon1.Value * .Item(0).TamisatCumule_Pourcent(kvp.Key) / (totalGrav)) + ((totalGrav - NudGravillon1.Value) * .Item(1).TamisatCumule_Pourcent(kvp.Key) / (totalGrav))
                    GravillonCompose.TamisatCumule_Pourcent.Add(kvp.Key, TotalGravillon)
                    If .Item(0).TamisatCumule_Pourcent(kvp.Key) = 100 Then ValeurprecedenteS1 = 100
                    If .Item(1).TamisatCumule_Pourcent(kvp.Key) = 100 Then ValeurPrecedenteS2 = 100
                Next
                GravillonCompose.Choix_mesureGranulo = 4 'pour spécifier que pour le Gravillon composé, la mesure est réalisée en tamisat cumulé %
                .Add(GravillonCompose) 'le Gravillon composé sera le 3ième Gravillon soit le Gravillon n°2
            End With
            'Affichage de la courbe granulaire du gravillon composé
            i2 = 2
        End If

        Dim iiTa() As Double = {1, 1.25, 1.6, 2, 2.5, 3.15, 4, 5, 6.3, 8, 10, 12.5, 16, 20, 25, 31.5, 40, 50, 63, 80}
        Total_Ginf = 0
        For i = 0 To iiTa.Length - 1
            With Gravillon.Item(i2)
                If i < 11 Then 'jusqu'au tamis 10
                    If Sable.Item(i1).Disponibilite_Tamis.Item(iTa(12 + i)) = True Then 'Pour le sable, la partie entre 1 et 10
                        If .Disponibilite_Tamis.Item(iiTa(i)) = True Then '
                            Total_Ginf = Total_G '
                            Ym(i + 12) = (Sable.Item(i1).TamisatCumule_Pourcent(iTa(12 + i)) * Total_S + .TamisatCumule_Pourcent(iiTa(i)) * Total_G) / Total 'Ym(i) reste donc en %
                            If Total_Ssup = 0 AndAlso Sable.Item(i1).TamisatCumule_Pourcent(iTa(12 + i)) > 98 Then Total_Ssup = Total_S 'dans le cas ou le test n'a pas été concluant dans la partie ci-dessus.
                        Else
                            If Total_Ginf = 0 Then 'la courbe granulométrique du gravillon n'a pas encore démarré
                                Ym(i + 12) = (Sable.Item(i1).TamisatCumule_Pourcent(iTa(12 + i)) * Total_S) / Total 'Ym(i) reste donc en %
                            Else
                                'ce qui signifie qu'une 1ière mesure précédente a été faite et la ou les suivantes sur le gravillon n'ont pas été faite
                                Ym(i + 12) = -1 'ce qui signifie qu'il n'y a pas eu de mesure sur le tamis i correspondant
                            End If
                        End If
                    Else
                        If Total_Ssup = Total_S Then
                            'Plus de mesure sur le sable car tout le sable est passant
                            If .Disponibilite_Tamis.Item(iiTa(i)) = True Then '
                                Ym(i + 12) = (Total_S * 100 + .TamisatCumule_Pourcent(iiTa(i)) * Total_G) / Total 'Ym(i) reste donc en %
                            Else
                                Ym(i + 12) = -1 'ce qui signifie qu'il n'y a pas eu de mesure sur le tamis i correspondant
                            End If
                        Else
                            Ym(i + 12) = -1 'ce qui signifie qu'il n'y a pas eu de mesure sur le tamis i correspondant
                        End If
                    End If
                Else 'A partir du tamis 12.5
                    'Plus d'interaction avec le sable - Tout le sable passe
                    If .Disponibilite_Tamis.Item(iiTa(i)) = True Then  'AndAlso .TamisatCumule_Pourcent.ContainsKey(iiTa(i))
                        Ym(i + 12) = (Total_S * 100 + .TamisatCumule_Pourcent(iiTa(i)) * Total_G) / Total 'Ym(i) reste donc en %
                    Else
                        Ym(i + 12) = -1 'ce qui signifie qu'il n'y a pas eu de mesure sur le tamis i correspondant
                    End If
                End If
            End With
        Next
        'Suppression du gravillon n°3
        If Gravillon.Count = 3 Then Gravillon.RemoveAt(2)
    End Sub
    Private Sub NudSable_ValueChanged(sender As Object, e As EventArgs) Handles NudSable.ValueChanged
        LblGravillon.Text = (100 - NudSable.Value).ToString("#0")
        If Beton.NbSable = 2 Then
            NudSable1.Value = CInt(Floor(NudSable.Value * Sable.Item(0).Mf_prop))
            LblSable2Txt.Text = (NudSable.Value - NudSable1.Value).ToString("#0")
        End If
        If Beton.NbGravillon = 2 AndAlso ValS <> 0 Then
            Dim i As Decimal
            i = NudSable.Value - ValS
            If i < 0 Then
                'je décrémente
                NudGravillon1.Value = Floor(NudGravillon1.Value * (1 - (i / ValS)))
            Else
                'j'incrémente
                NudGravillon1.Value = Floor(NudGravillon1.Value * (1 + (i / ValS)))
            End If
            LblGravillon2Txt.Text = (100 - NudSable.Value - NudGravillon1.Value).ToString("#0")
            ValS = NudSable.Value
        End If
        Pb.Refresh()
    End Sub

    Private Sub NudSable1_ValueChanged(sender As Object, e As EventArgs) Handles NudSable1.ValueChanged
        If NudSable1.Value > NudSable.Value - 2 Then
            NudSable1.Value = NudSable.Value - 2 : Exit Sub
        Else
            LblSable2Txt.Text = (NudSable.Value - NudSable1.Value).ToString("#0")
        End If

        Pb.Refresh()
    End Sub

    Private Sub NudGravillon1_ValueChanged(sender As Object, e As EventArgs) Handles NudGravillon1.ValueChanged
        If NudGravillon1.Value > (100 - NudSable.Value - 4) Then
            NudGravillon1.Value = 100 - NudSable.Value - 4 : Exit Sub
        Else
            LblGravillon2Txt.Text = (100 - NudSable.Value - NudGravillon1.Value).ToString("#0")
        End If

        Pb.Refresh()
    End Sub

    Private Sub ChkbAffichage2sables_CheckedChanged(sender As Object, e As EventArgs) Handles ChkbAffichage2sables.CheckedChanged
        Pb.Refresh()
    End Sub
End Class