Tracer une ligne ou un cercle avec anticrènelage

Description

voici un code permettant de tracer une ligne ou un cercle avec un anticrènelage

il vous suffit de mettre ça dans un module et d'appeller les fonctions DrawLineAA, DrawCircleAA (DrawLine et DrawCircle servent à la même chose sans anticrènelage et SetPixelAA c'est ce qui trace un pixel avec un antialias en fonction de ce qu'il y a après la virgule)

DeviceContext c'est le .hDC de l'objet sur lequel vous voulez tracer (par exemple Form1.hDC ou Picture1.hDC)

le ScaleMode de l'objet sur lequel on trace doit être sur 3 (vbPixel)

les autres paramètres sont assez explicites pour ne pas être commentés.

notez qu'avec SetPixelAA vous pouvez faire un code qui trace par exemple une élipse ou un triangle et au lieu de faire SetPixel vous remplaces par SetPixelAA en mettant des paramètres de type Double donc avec une virgule donc avec un anticrènelage :) et vous obtiendrez un superbe anticrènelage.

Source / Exemple :


' ======================================
' DECLARATIONS D'API
' ======================================

Private Declare Function GetPixel Lib "gdi32" (ByVal hDC As Long, ByVal X As Long, ByVal Y As Long) As Long
Private Declare Function SetPixelV Lib "gdi32" (ByVal hDC As Long, ByVal X As Long, ByVal Y As Long, ByVal crColor As Long) As Long

' ======================================
' AVEC ANTICRENELAGE
' ======================================

' trace un pixel avec un anticrènelage
Public Sub SetPixelAA( _
    ByVal DeviceContext As Long, _
    ByVal XX As Single, _
    ByVal YY As Single, _
    ByVal r As Byte, _
    ByVal g As Byte, _
    ByVal b As Byte)
    
    Dim BackR       As Byte
    Dim BackG       As Byte
    Dim BackB       As Byte
    Dim BackCol     As Long
    
    Dim xi          As Long: xi = CLng(XX)
    Dim yi          As Long: yi = CLng(YY)
    
    Dim xp          As Single
    Dim yp          As Single
    
    Dim pa          As Single
    Dim pb          As Single
    Dim pc          As Single
    Dim pd          As Single
    
    If xi > XX Then xi = xi - 1
    If yi > YY Then yi = yi - 1
    
    If xi <> XX And yi <> YY Then
    
        xp = XX - xi
        yp = YY - yi
    
        pa = (1 - xp) * (1 - yp)
        pb = xp * (1 - yp)
        pc = (1 - xp) * yp
        pd = xp * yp
        
        BackCol = GetPixel(DeviceContext, xi, yi)
        BackR = BackCol And &HFF
        BackG = (BackCol \ &H100) And &HFF
        BackB = (BackCol \ &H10000) And &HFF
        SetPixelV DeviceContext, xi, yi, RGB(r * pa + BackR * (1 - pa), g * pa + BackG * (1 - pa), b * pa + BackB * (1 - pa))
        
        BackCol = GetPixel(DeviceContext, xi + 1, yi)
        BackR = BackCol And &HFF
        BackG = (BackCol \ &H100) And &HFF
        BackB = (BackCol \ &H10000) And &HFF
        SetPixelV DeviceContext, xi + 1, yi, RGB(r * pb + BackR * (1 - pb), g * pb + BackG * (1 - pb), b * pb + BackB * (1 - pb))
    
        BackCol = GetPixel(DeviceContext, xi, yi + 1)
        BackR = BackCol And &HFF
        BackG = (BackCol \ &H100) And &HFF
        BackB = (BackCol \ &H10000) And &HFF
        SetPixelV DeviceContext, xi, yi + 1, RGB(r * pc + BackR * (1 - pc), g * pc + BackG * (1 - pc), b * pc + BackB * (1 - pc))

        BackCol = GetPixel(DeviceContext, xi + 1, yi + 1)
        BackR = BackCol And &HFF
        BackG = (BackCol \ &H100) And &HFF
        BackB = (BackCol \ &H10000) And &HFF
        SetPixelV DeviceContext, xi + 1, yi + 1, RGB(r * pd + BackR * (1 - pd), g * pd + BackG * (1 - pd), b * pd + BackB * (1 - pd))
    
    ElseIf xi <> XX Then

        pc = XX - xi
        pa = 1 - (XX - xi)

        BackCol = GetPixel(DeviceContext, xi, yi)
        BackR = BackCol And &HFF
        BackG = (BackCol \ &H100) And &HFF
        BackB = (BackCol \ &H10000) And &HFF
        SetPixelV DeviceContext, xi, yi, RGB(r * pa + BackR * (1 - pa), g * pa + BackG * (1 - pa), b * pa + BackB * (1 - pa))
        
        BackCol = GetPixel(DeviceContext, xi + 1, yi)
        BackR = BackCol And &HFF
        BackG = (BackCol \ &H100) And &HFF
        BackB = (BackCol \ &H10000) And &HFF
        SetPixelV DeviceContext, xi + 1, yi, RGB(r * pc + BackR * (1 - pc), g * pc + BackG * (1 - pc), b * pc + BackB * (1 - pc))

    ElseIf yi <> YY Then
    
        pb = YY - yi
        pa = 1 - (YY - yi)

        BackCol = GetPixel(DeviceContext, xi, yi)
        BackR = BackCol And &HFF
        BackG = (BackCol \ &H100) And &HFF
        BackB = (BackCol \ &H10000) And &HFF
        SetPixelV DeviceContext, xi, yi, RGB(r * pa + BackR * (1 - pa), g * pa + BackG * (1 - pa), b * pa + BackB * (1 - pa))
        
        BackCol = GetPixel(DeviceContext, xi, yi + 1)
        BackR = BackCol And &HFF
        BackG = (BackCol \ &H100) And &HFF
        BackB = (BackCol \ &H10000) And &HFF
        SetPixelV DeviceContext, xi, yi + 1, RGB(r * pb + BackR * (1 - pb), g * pb + BackG * (1 - pb), b * pb + BackB * (1 - pb))
    
    Else
        
        SetPixelV DeviceContext, XX, YY, RGB(r, g, b)
        
    End If
    
End Sub

' trace une ligne avec anticrènelage
Public Sub DrawLineAA( _
    ByVal DeviceContext As Long, _
    ByVal x1 As Single, _
    ByVal y1 As Single, _
    ByVal x2 As Single, _
    ByVal y2 As Single, _
    ByVal Color As Long)
    
    Dim m       As Single
    Dim b       As Single
    Dim XX      As Single
    Dim YY      As Single
    
    Dim rr       As Byte: rr = Color And &HFF
    Dim gg       As Byte: gg = (Color \ &H100) And &HFF
    Dim bb       As Byte: bb = (Color \ &H10000) And &HFF
    
    If x2 = x1 Then
        m = (y2 - y1) / 1
    Else
        m = (y2 - y1) / (x2 - x1)
    End If
    
    b = y1 - (m * x1)
    
    If Abs(m) <= 1 Then
        If x1 <= x2 Then
            For XX = x1 To x2 - 1
                YY = m * XX + b
                SetPixelAA DeviceContext, XX, YY, rr, gg, bb
            Next XX
        Else
            For XX = x2 + 1 To x1
                YY = m * XX + b
                SetPixelAA DeviceContext, XX, YY, rr, gg, bb
            Next XX
        End If
    Else
        If y1 <= y2 Then
            For YY = y1 To y2 - 1
                XX = (YY - b) / m
                SetPixelAA DeviceContext, XX, YY, rr, gg, bb
            Next YY
        Else
            For YY = y2 + 1 To y1
                XX = (YY - b) / m
                SetPixelAA DeviceContext, XX, YY, rr, gg, bb
            Next YY
        End If
    End If
    
End Sub

' trace un cercle avec anticrènelage
Public Sub DrawCircleAA( _
    ByVal DeviceContext As Long, _
    ByVal X As Single, _
    ByVal Y As Single, _
    ByVal Rayon As Single, _
    ByVal Color As Long)

    Dim XX      As Single
    Dim YY      As Single

    Dim rr       As Byte: rr = Color And &HFF
    Dim gg       As Byte: gg = (Color \ &H100) And &HFF
    Dim bb       As Byte: bb = (Color \ &H10000) And &HFF
    
    If Rayon = 0 Then Exit Sub
    
    SetPixelAA DeviceContext, X + Rayon, Y, rr, gg, bb
    SetPixelAA DeviceContext, X, Y + Rayon, rr, gg, bb
    SetPixelAA DeviceContext, X, Y - Rayon, rr, gg, bb
    SetPixelAA DeviceContext, X - Rayon, Y, rr, gg, bb
    
    For XX = 1 To Rayon * 0.71 ' = 1 / Sqr(2)
        
        YY = Sqr(Rayon * Rayon - XX * XX)
        
        SetPixelAA DeviceContext, XX + X, YY + Y, rr, gg, bb
        SetPixelAA DeviceContext, -XX + X, YY + Y, rr, gg, bb
        SetPixelAA DeviceContext, XX + X, -YY + Y, rr, gg, bb
        SetPixelAA DeviceContext, -XX + X, -YY + Y, rr, gg, bb

        SetPixelAA DeviceContext, YY + X, XX + Y, rr, gg, bb
        SetPixelAA DeviceContext, -YY + X, XX + Y, rr, gg, bb
        SetPixelAA DeviceContext, YY + X, -XX + Y, rr, gg, bb
        SetPixelAA DeviceContext, -YY + X, -XX + Y, rr, gg, bb
        
    Next XX
    
End Sub

' ======================================
' SANS ANTICRENELAGE
' ======================================

' trace une ligne
Public Sub DrawLine( _
    ByVal DeviceContext As Long, _
    ByVal x1 As Long, _
    ByVal y1 As Long, _
    ByVal x2 As Single, _
    ByVal y2 As Single, _
    ByVal Color As Long)
    
    Dim m       As Single
    Dim b       As Single
    Dim XX      As Long
    Dim YY      As Long
    
    If x2 = x1 Then
        m = (y2 - y1) / 1
    Else
        m = (y2 - y1) / (x2 - x1)
    End If
    
    b = y1 - (m * x1)
    
    If Abs(m) <= 1 Then
        If x1 <= x2 Then
            For XX = x1 To x2 - 1
                YY = m * XX + b
                SetPixelV DeviceContext, XX, YY, Color
            Next XX
        Else
            For XX = x2 + 1 To x1
                YY = m * XX + b
                SetPixelV DeviceContext, XX, YY, Color
            Next XX
        End If
    Else
        If y1 <= y2 Then
            For YY = y1 To y2 - 1
                XX = (YY - b) / m
                SetPixelV DeviceContext, XX, YY, Color
            Next YY
        Else
            For YY = y2 + 1 To y1
                XX = (YY - b) / m
                SetPixelV DeviceContext, XX, YY, Color
            Next YY
        End If
    End If
    
End Sub

' trace un cercle
Public Sub DrawCircle( _
    ByVal DeviceContext As Long, _
    ByVal X As Long, _
    ByVal Y As Long, _
    ByVal Rayon As Long, _
    ByVal Color As Long)

    Dim XX      As Long
    Dim YY      As Long

    Dim rr       As Byte: rr = Color And &HFF
    Dim gg       As Byte: gg = (Color \ &H100) And &HFF
    Dim bb       As Byte: bb = (Color \ &H10000) And &HFF
    
    If Rayon = 0 Then Exit Sub
    
    SetPixelV DeviceContext, X + Rayon, Y, Color
    SetPixelV DeviceContext, X, Y + Rayon, Color
    SetPixelV DeviceContext, X, Y - Rayon, Color
    SetPixelV DeviceContext, X - Rayon, Y, Color
    
    For XX = 1 To Rayon * 0.71 ' = 1 / Sqr(2)
        
        YY = Sqr(Rayon * Rayon - XX * XX)
        
        SetPixelV DeviceContext, XX + X, YY + Y, Color
        SetPixelV DeviceContext, -XX + X, YY + Y, Color
        SetPixelV DeviceContext, XX + X, -YY + Y, Color
        SetPixelV DeviceContext, -XX + X, -YY + Y, Color

        SetPixelV DeviceContext, YY + X, XX + Y, Color
        SetPixelV DeviceContext, -YY + X, XX + Y, Color
        SetPixelV DeviceContext, YY + X, -XX + Y, Color
        SetPixelV DeviceContext, -YY + X, -XX + Y, Color
        
    Next XX
    
End Sub

Conclusion :


14/09/2004 :
- j'ai corrigé la faute à "anticrènelage" selon l'académie française.

24/06/2004 :
- j'ai remplacé SetPixel par SetPixelV
- j'ai viré les Double que j'ai remplacé par des Long là ou il n'y avait pas lieu d'utiliser des Double.
- J'ai remplacé tous les Double par des Single qui sont plus rapides que les Doubles car moins précis (mais nous n'avons pas besoin de Double ici)

Merci à vlad2 ;)

22/06/2004
- J'ai modifié un peu le code dans SetPixelAA, en effet il y avait une erreur, maintenant c'est nickel !

Codes Sources

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.