다음 예제는 베지어 곡선을 그리는 예로 1차 곡선입니다.
즉 시작하는 점은 2개의 점이며 이를 잊는 직선으로 되있을 경우에 베지어 곡선을 그리는 결과를 나타냅니다.

초기 화면은 다음과 같습니다. 두점과 그를 잊는 직선으로 이루어진 경로가 있을 경우의 베지어 곡선입니다.


시작 버튼을 누르게 되면 베지어 곡선을 그리게 되며, 시작 버튼을 누리기 전에 점을 클릭해서 드래그 하면
점의 위치를 변경할수 있읍니다.

다음은 소스 입니다.
Option Explicit ' 모든 변수는 선언된 뒤에 사용 할 수 있다.
Option Base 1

Private Const XPoint = 1
Private Const YPoint = 2

Private HarfDot As Long ' 점의 반지름
Private Pointer() As Long ' 현재 점의 위치
Private Dimension() As Long ' 각 차수 시작 첨자
Private SelectDot As Long ' 현재 마우스로 선택된 점의 인덱스 번호

Private Sub CreatePoint(ByVal index As Long) ' 점을 생성한다.
    Pointer(XPoint, index) = Rnd(1) * picClient.Width
    Pointer(YPoint, index) = Rnd(1) * picClient.Height
End Sub

Private Function GetDimension(ByVal index As Long) As Long ' 점의 어떤 차원의 점인지를 얻는다
    For GetDimension = UBound(Dimension) To 1 Step -1
        If index >= Dimension(GetDimension) Then Exit For
    Next GetDimension
End Function

Private Sub DisplayPoint(ByVal index As Long) ' 점을 표시한다.
    Dim LoadConffirm As Boolean
   
    On Error Resume Next
    LoadConffirm = shpPoint(index).Visible
    If Err.Number > 0 Then Load shpPoint(index)
    On Error GoTo 0
    With shpPoint(index)
        .BackColor = QBColor(GetDimension(index))
        .Left = Pointer(XPoint, index) - HarfDot
        .Top = Pointer(YPoint, index) - HarfDot
        .Visible = True
    End With
End Sub

Private Sub DrawLine(ByVal index As Long, ByVal Befor As Boolean, ByVal Clear As Boolean) ' 점과 점을 잊는 선을 그린다.
    Dim x2 As Long ' 연결할 점의 좌표
    Dim y2 As Long
    Dim C As Long ' 연결할 선의 색
   
    x2 = Pointer(XPoint, index + IIf(Befor, -1, 1)) ' 연결할 점의 좌표를 얻는다.
    y2 = Pointer(YPoint, index + IIf(Befor, -1, 1))
    picClient.Line (Pointer(XPoint, index), Pointer(YPoint, index))-(x2, y2), IIf(Clear, picClient.BackColor, QBColor(GetDimension(index)))
End Sub

Private Function CursorInDot(ByVal x As Long, ByVal y As Long) As Long ' 커서가
    For CursorInDot = UBound(Pointer, 1) To 1 Step -1
        If Pointer(XPoint, CursorInDot) - HarfDot <= x And Pointer(XPoint, CursorInDot) + HarfDot >= x And _
            Pointer(YPoint, CursorInDot) - HarfDot <= y And Pointer(YPoint, CursorInDot) + HarfDot >= y Then
            Exit For
        End If
    Next CursorInDot
End Function

Private Function GetDotNumber() As Long ' 점 수
    GetDotNumber = UBound(Pointer, 2)
End Function

Private Sub cmdStart_Click() ' 시작
    timProcess = True
    cmdStart.Enabled = False
End Sub

Private Sub Form_Load()
    Randomize ' 난수 발생기를 초기화 한다
   
    HarfDot = shpPoint(0).Width / 2 ' 점의 반지름
    ReDim Dimension(1) ' 1차원
    ReDim Pointer(YPoint, 2) ' 포인터가 저장될 배열의 초기화, 초기 점 2개에 좌표(x,y)
    Dimension(1) = 1 ' 1차원 포인터의 시작 첨자
    picClient.AutoRedraw = True
    CreatePoint 1 ' 점을 생성한다.
    CreatePoint 2
    DisplayPoint 1 ' 점을 표시한다.
    DisplayPoint 2
    DrawLine 2, True, False
End Sub

Private Sub picClient_MouseDown(Button As Integer, Shift As Integer, x As Single, y As Single)
    If Not Button = vbLeftButton Then Exit Sub ' 왼쪽 버튼일때만 처리
    SelectDot = CursorInDot(x, y) ' 선택된 점 지정
End Sub

Private Sub picClient_MouseMove(Button As Integer, Shift As Integer, x As Single, y As Single)
    If Not Button = vbLeftButton Or SelectDot = 0 Then Exit Sub ' 왼족 버튼과, 점을 선택한경우만 처리
    If Not SelectDot = UBound(Pointer, 1) Then
        DrawLine SelectDot, False, True
    End If
    If Not SelectDot = 1 Then
        DrawLine SelectDot, True, True
    End If
    Pointer(XPoint, SelectDot) = x
    Pointer(YPoint, SelectDot) = y
    DisplayPoint SelectDot
    If Not SelectDot = UBound(Pointer, 1) Then
        DrawLine SelectDot, False, False
    End If
    If Not SelectDot = 1 Then
        DrawLine SelectDot, True, False
    End If
End Sub

Private Sub picClient_MouseUp(Button As Integer, Shift As Integer, x As Single, y As Single)
    SelectDot = 0
End Sub

Private Sub timProcess_Timer()
    Static T As Double ' 비율
    Static Bx As Long ' 이전 베지어 곡선 마지막 좌표
    Static By As Long ' 이전 베지어 곡선 마지막 좌표
    Dim CurrentDimension As Long ' 현재 차운
    Dim ForPointerCounter As Long ' 현재 포인터 인덱스
    Dim LastPointIndex As Long ' 현재 차원의 마지막 점의 인덱스-1
    Dim NextDimensionDotIndex As Long ' 현재 직선에 대한 다음 차원의 점 인덱스 번호
   

    timProcess.Enabled = False
    If T >= 1 Then ' 비율 계산, 및 초기화
        Exit Sub
    Else
        T = T + 0.01
        labRateValue.Caption = Format(T, "0.00")
        CurrentDimension = 1
        ForPointerCounter = 1
    End If


    If UBound(Dimension) = CurrentDimension Then
        LastPointIndex = UBound(Pointer, 1) - 1
    Else
        LastPointIndex = (Dimension(CurrentDimension + 1) - 1) - 1
    End If


    For ForPointerCounter = Dimension(CurrentDimension) To LastPointIndex
        If ForPointerCounter = Dimension(CurrentDimension) And UBound(Dimension) = CurrentDimension Then
            ReDim Preserve Dimension(CurrentDimension + 1)
            Dimension(CurrentDimension + 1) = UBound(Pointer, 1) + 1
        End If
        NextDimensionDotIndex = Dimension(CurrentDimension + 1) + (ForPointerCounter - Dimension(CurrentDimension))
        If UBound(Pointer, 1) < NextDimensionDotIndex Then ReDim Preserve Pointer(YPoint, NextDimensionDotIndex)
        Pointer(XPoint, NextDimensionDotIndex) = Pointer(XPoint, ForPointerCounter) + (Pointer(XPoint, ForPointerCounter) - Pointer(XPoint, ForPointerCounter + 1)) * T * -1
        Pointer(YPoint, NextDimensionDotIndex) = Pointer(YPoint, ForPointerCounter) + (Pointer(YPoint, ForPointerCounter) - Pointer(YPoint, ForPointerCounter + 1)) * T * -1
        DisplayPoint NextDimensionDotIndex
    Next
    CurrentDimension = CurrentDimension + 1 ' 다음 차원
    If GetDotNumber - Dimension(CurrentDimension) = 0 Then ' 이전 이벤트의 마지막 점과, 현재의 마지막 점을 연결하여 베지어 곡선을 그린다
        If Bx = 0 Then
            Bx = Pointer(XPoint, 1)
            By = Pointer(YPoint, 1)
        End If
        picClient.Line (Bx, By)-(Pointer(XPoint, GetDotNumber), Pointer(YPoint, GetDotNumber)), vbRed
        Bx = Pointer(XPoint, GetDotNumber)
        By = Pointer(YPoint, GetDotNumber)
    End If
    timProcess.Enabled = True
End Sub

다음 번에는 시작점이 3개인 즉, 직선이 2개인 경로를 갖는 경우의 베지어 곡선을 그려보겠읍니다.

+ Recent posts