Attribute VB_Name = "modPlotSpectrum"
Option Explicit

'==========================================
'Plot Spectrum
'==========================================

Public Type COORD   'The co-ordinates in Long
    X As Long
    Y As Long
End Type

Private picBuffer As PictureBox
Private picPlot As PictureBox
Public MaxChanCnt As Single
Public isLog As Boolean
Public isLine As Boolean
Public isSolid As Boolean
Public isLinear As Boolean


''----- Plot Data -----
Public PlotCursor As COORD
Public OldPlotCursor As COORD
Public YPlotBuffer(16384) As Long    'holds y position data for cursor updates
Public YPlotMAX As Long
Public XPlotMAX As Long

Private Const ALTERNATE = 1 ' ALTERNATE and WINDING are
Private Const WINDING = 2 ' constants for FillMode.
Private Declare Function CreatePolygonRgn Lib "gdi32" (lpPoint As Any, ByVal nCount As Long, ByVal nPolyFillMode As Long) As Long
Private Declare Function FillRgn Lib "gdi32" (ByVal hdc As Long, ByVal hRgn As Long, ByVal hBrush As Long) As Long
Private Declare Function DeleteObject Lib "gdi32" (ByVal hObject As Long) As Long
Private Declare Function CreateSolidBrush Lib "gdi32" (ByVal crColor As Long) As Long

Public Function DrawFilledPolygon(Pic As PictureBox, ByRef Pnt() As COORD, _
                                    Optional ByVal NUMPOINTS As Double = 4) As Boolean
    Dim PolyPoint As Integer
    Dim hBrush As Long
    Dim hRgn As Long    'Defining color filling Variables

    On Error GoTo DrawFilledPolygonErr
    If Val(NUMPOINTS) < 3 Then
        DrawFilledPolygon = False
        Exit Function   'Exiting none valid Sidecount
    End If
    Dim Vtx() As COORD 'Defining  new verticies in Pixel Mode
    ReDim Vtx(1 To NUMPOINTS)
    For PolyPoint = 1 To NUMPOINTS
        Vtx(PolyPoint).X = (Pnt(PolyPoint).X / Screen.TwipsPerPixelX)
        Vtx(PolyPoint).Y = (Pnt(PolyPoint).Y / Screen.TwipsPerPixelY)
    Next PolyPoint
    hBrush = CreateSolidBrush(Pic.FillColor)
    hRgn = CreatePolygonRgn(Vtx(1), NUMPOINTS, ALTERNATE)   'Getting the polygon region from the Vertices
    If hRgn Then FillRgn Pic.hdc, hRgn, hBrush  'Filling the determined area
    DeleteObject hRgn
    DeleteObject hBrush
    DrawFilledPolygon = True
    Exit Function
DrawFilledPolygonErr:
    MsgBox "DrawFilledPolygon: Unexpected error occured." & vbCrLf & "Err." & Err.Number & " : " & Err.Description, vbCritical, "Error"
    DrawFilledPolygon = False
End Function
'-------------------------------------------------------------------------

Public Function GetPathWOFilename(strPath As String)
    Dim i As Integer
    
    GetPathWOFilename = strPath
    If (Len(strPath) = 0) Then Exit Function
    If (Right(strPath, 1) = "\") Then Exit Function
    For i = Len(strPath) To 1 Step -1
        If Mid(strPath, i, 1) = "\" Then
            GetPathWOFilename = Left(strPath, i)
            Exit For
        End If
    Next
End Function

'draws a filled polygon
Private Sub DrawFilledPoly(i As Double, y1 As Double, y2 As Double, xScale As Double, yScale As Double)
    Dim Pnt(1 To 4) As COORD   'Getting the  vaiables for vertex of polygon
    Pnt(1).X = CLng(i * (picBuffer.Width / xScale))
    Pnt(1).Y = CLng(picBuffer.Height - 0)
    Pnt(2).X = CLng(i * (picBuffer.Width / xScale))
    Pnt(2).Y = CLng((picBuffer.Height - 0) - (y1 * (picBuffer.Height / yScale)))
    Pnt(3).X = CLng((i + 1#) * (picBuffer.Width / xScale))
    Pnt(3).Y = CLng((picBuffer.Height - 0) - (y2 * (picBuffer.Height / yScale)))
    Pnt(4).X = CLng((i + 1#) * (picBuffer.Width / xScale))
    Pnt(4).Y = CLng(picBuffer.Height - 0)
    DrawFilledPolygon picBuffer, Pnt, 4
End Sub

'calculates and plots a spectrum display from given data
Public Sub PlotData(DataBuffer() As Double, NumChan As Integer)
    Dim i As Integer
    Dim j As Integer
    Dim YMAX As Double
    Dim logTemp As Double
    Dim y1 As Double
    Dim y2 As Double
    Dim YPlotScale As Double
    
    isLine = Not isSolid
    isLog = Not isLinear
   
    XPlotMAX = NumChan - 1
    If (NumChan > 0) Then 'plot data
        
        YMAX = 0
        For i = 0 To (NumChan - 1) 'get the largest value to be displayed
            If (isLinear) Then
                If (DataBuffer(i) > YMAX) Then YMAX = DataBuffer(i)
            Else
                If (Log(0.1 + DataBuffer(i)) > YMAX) Then YMAX = Log(0.1 + DataBuffer(i))
            End If
        Next
        If (YMAX < 1) Then Exit Sub         'if no y scale exit sub
        If (isLog) Then     'adjust plot to include entire high peak
            YPlotScale = (YMAX * 10#)
            YMAX = (YMAX * 10#) + 10
        Else
            YPlotScale = YMAX
            If (YMAX < 20) Then
                YMAX = YMAX + 2
            Else
                YMAX = YMAX + 10
            End If
        End If
        MaxChanCnt = YMAX
        picBuffer.Scale (0, YMAX)-(NumChan, 0)
        picPlot.Scale (0, YMAX)-(NumChan, 0)
        picBuffer.Line (0, 0)-(NumChan, YMAX), picBuffer.BackColor, BF
        For i = 0 To (NumChan - 2) 'get the largest value to be displayed
            'If ((i + 1) >= NumChan) Then Exit For
            If (isLinear) Then
                y1 = DataBuffer(i): y2 = DataBuffer(i + 1)
            Else
                y1 = Log(0.1 + DataBuffer(i)) * 10#: y2 = Log(0.1 + DataBuffer(i + 1)) * 10#
            End If
            YPlotBuffer(i) = y1
            Select Case True
                Case isSolid
                    If (NumChan < 1024) Then
                        Call DrawFilledPoly(CDbl(i), CDbl(y1), CDbl(y2), CDbl(NumChan + 1.5), CDbl(YMAX))
                    Else
                        picBuffer.Line (i, 0)-(i, y1), picBuffer.ForeColor, BF
                        picBuffer.Line (i + 1, 0)-(i + 1, y2), picBuffer.ForeColor, BF
                        picBuffer.Line (i, y1)-(i + 1, y2), picBuffer.ForeColor, BF
                    End If
                Case isLine
                    picBuffer.Line (i, y1)-(i + 1, y2)
            End Select
            DoEvents
        Next
        YPlotMAX = YMAX
        picBuffer.Line (PlotCursor.X, 0)-(PlotCursor.X, YMAX), QBColor(8)
        picPlot.Picture = picBuffer.Image
    End If
End Sub

'initialize the plot drawing buffer, the buffer reduces plot update flicker
'plots are first drawn to picBuffer then displayed on picPlot
Public Sub Init_Pic(picBufferIn As PictureBox, picPlotIn As PictureBox)
    Set picBuffer = picBufferIn
    Set picPlot = picPlotIn

    picBuffer.Left = picPlot.Left
    picBuffer.Top = picPlot.Top
    picBuffer.Width = picPlot.Width
    picBuffer.Height = picPlot.Height
    picBuffer.BackColor = picPlot.BackColor
    picBuffer.ForeColor = picPlot.ForeColor
    picBuffer.FillColor = picPlot.FillColor
End Sub

''draws the plot cursor at the current position
'Public Function PlotCursorAtPos() As Long
'    Dim sngXScale As Single
'    Dim CurorChannel As Long
'    picPlot.Line (OldPlotCursor.X, 0)-(OldPlotCursor.X, YPlotMAX), picBuffer.BackColor                  'QBColor(15)
'    Select Case True
'        Case isSolid
'            picPlot.Line (OldPlotCursor.X, YPlotBuffer(OldPlotCursor.X))-(OldPlotCursor.X + 1, YPlotBuffer(OldPlotCursor.X + 1)) ', QBColor(4)
'            picPlot.Line (OldPlotCursor.X, 0)-(OldPlotCursor.X, YPlotBuffer(OldPlotCursor.X)), picBuffer.ForeColor, BF ', QBColor(4), BF
'        Case isLine
'            picPlot.Line (OldPlotCursor.X, YPlotBuffer(OldPlotCursor.X))-(OldPlotCursor.X + 1, YPlotBuffer(OldPlotCursor.X + 1)) ', QBColor(4)
'    End Select
'    picPlot.Line (PlotCursor.X, 0)-(PlotCursor.X, YPlotMAX), QBColor(8)
'    sngXScale = picPlot.ScaleWidth / CSng(XPlotMAX + 1)
'    CurorChannel = (CLng(CSng(PlotCursor.X) * sngXScale) + 1)
'    PlotCursorAtPos = CurorChannel
'End Function

Public Function GetOption(opts As Object) As Integer
    On Error GoTo GetOptionErr
    Dim opt As OptionButton
    For Each opt In opts
        If opt.value Then
            GetOption = opt.Index
            Exit Function
        End If
    Next
GetOptionErr:
    GetOption = -1
End Function


'Private Const OFFSET_4 = 4294967296#
Function LongToUnsigned(value As Long) As Double
    If value < 0 Then
        'LongToUnsigned = value + OFFSET_4
        LongToUnsigned = value + 4294967296#
    Else
        LongToUnsigned = value
    End If
End Function
