Project S Curves

Just starting out? Need help? Post your questions and find answers here.
nicksteel
User
User
Posts: 43
Joined: Sat Apr 24, 2004 5:20 pm
Location: Houston

Project S Curves

Post by nicksteel »

Need sample code for producing a Project S Curve, similar to those produced by Excel. Any advice would be most appreciated.
Slow, but trying.
lule
User
User
Posts: 31
Joined: Fri Sep 17, 2010 8:22 pm

Re: Project S Curves

Post by lule »

With GDI+ (windows only), sample by danilo :

Code: Select all

EnableExplicit

;>----- START INCLUDE ---------------------------------------
;
;-[ antialiased PB compatible drawing functions using GDI+ ]-
;
; by Danilo, July 2011
;
Prototype DebugEventProc(level, *message.Ascii)
Prototype NotificationHookProc(*token.Long)
Prototype NotificationUnhookProc(token.l)

Structure GdiplusStartupInput
    GdiPlusVersion.l
    *DebugEventCallback.DebugEventProc
    SuppressBackgroundThread.l
    SuppressExternalCodecs.l
EndStructure

Structure GdiplusStartupOutput
    *NotificationHook.NotificationHookProc
    *NotificationUnhook.NotificationUnhookProc
EndStructure

Enumeration ; CompositingMode
    #CompositingModeSourceOver = 0 ;   // 0
    #CompositingModeSourceCopy = 1 ;   // 1
EndEnumeration

Enumeration ; QualityMode
    #QualityModeInvalid   = -1
    #QualityModeDefault   =  0
    #QualityModeLow       =  1  ; Best performance
    #QualityModeHigh      =  2  ; Best rendering quality
EndEnumeration

Enumeration ; CompositingQuality
    #CompositingQualityInvalid          = #QualityModeInvalid
    #CompositingQualityDefault          = #QualityModeDefault
    #CompositingQualityHighSpeed        = #QualityModeLow
    #CompositingQualityHighQuality      = #QualityModeHigh
    #CompositingQualityGammaCorrected
    #CompositingQualityAssumeLinear
EndEnumeration

Enumeration ; SmoothingMode
    #SmoothingModeInvalid     = #QualityModeInvalid
    #SmoothingModeDefault     = #QualityModeDefault
    #SmoothingModeHighSpeed   = #QualityModeLow
    #SmoothingModeHighQuality = #QualityModeHigh
    #SmoothingModeNone
    #SmoothingModeAntiAlias
;#if (GDIPVER >= 0x0110)
    #SmoothingModeAntiAlias8x4 = #SmoothingModeAntiAlias
    #SmoothingModeAntiAlias8x8
;#endif //(GDIPVER >= 0x0110)
EndEnumeration

Enumeration ; InterpolationMode
    #InterpolationModeInvalid          = #QualityModeInvalid
    #InterpolationModeDefault          = #QualityModeDefault
    #InterpolationModeLowQuality       = #QualityModeLow
    #InterpolationModeHighQuality      = #QualityModeHigh
    #InterpolationModeBilinear
    #InterpolationModeBicubic
    #InterpolationModeNearestNeighbor
    #InterpolationModeHighQualityBilinear
    #InterpolationModeHighQualityBicubic
EndEnumeration

Enumeration ; PixelOffsetMode
    #PixelOffsetModeInvalid     = #QualityModeInvalid
    #PixelOffsetModeDefault     = #QualityModeDefault
    #PixelOffsetModeHighSpeed   = #QualityModeLow
    #PixelOffsetModeHighQuality = #QualityModeHigh
    #PixelOffsetModeNone     ; No pixel offset
    #PixelOffsetModeHalf     ; Offset by -0.5, -0.5 For fast anti-alias perf
EndEnumeration

Enumeration ; LineCap
    #LineCapFlat             = 0
    #LineCapSquare           = 1
    #LineCapRound            = 2
    #LineCapTriangle         = 3

    #LineCapNoAnchor         = $10 ; corresponds To flat cap
    #LineCapSquareAnchor     = $11 ; corresponds To square cap
    #LineCapRoundAnchor      = $12 ; corresponds To round cap
    #LineCapDiamondAnchor    = $13 ; corresponds To triangle cap
    #LineCapArrowAnchor      = $14 ; no correspondence

    #LineCapCustom           = $ff ; custom cap

    #LineCapAnchorMask       = $f0 ; mask To check For anchor Or Not.
EndEnumeration

Prototype.l GdiplusStartup(*token.Long, *input.GdiplusStartupInput, *output.GdiplusStartupOutput)
Prototype.l GdiplusShutdown(token.l)

Prototype.l GdipCreateFromHDC(*hDC, *graphics)
Prototype.l GdipDeleteGraphics(*graphics)

Prototype.l GdipGraphicsClear(*graphics, color.l)

Prototype.l GdipSetSmoothingMode        (*graphics, smoothingMode.l)
Prototype.l GdipSetCompositingMode      (*graphics, compositingMode.l)
Prototype.l GdipSetCompositingQuality   (*graphics, compositingQuality.l)
Prototype.l GdipSetInterpolationMode    (*graphics, interpolationMode.l)
Prototype.l GdipSetPixelOffsetMode      (*graphics, pixelOffsetMode.l)


Prototype.l GdipCreatePen1    (color.l, Width.f, unit.l, *pen)
Prototype.l GdipDeletePen     (*pen)
Prototype.l GdipSetPenStartCap(*pen, startCap.l)
Prototype.l GdipSetPenEndCap  (*pen, endCap.l)

Prototype.l GdipCreateSolidFill(color.l, *brush)
Prototype.l GdipDeleteBrush(*brush)


Prototype.l GdipDrawRectangleI(*graphics, *pen  , x.l , y.l , width.l, height.l)
Prototype.l GdipFillRectangleI(*graphics, *brush, x.l , y.l , width.l, height.l)
Prototype.l GdipDrawLineI     (*graphics, *pen  , x1.l, y1.l, x2.l   , y2.l    )
Prototype.l GdipDrawPieI      (*graphics, *pen  , x.l , y.l , width.l, height.l, startAngle.f, sweepAngle.f)
Prototype.l GdipFillPieI      (*graphics, *brush, x.l , y.l , width.l, height.l, startAngle.f, sweepAngle.f)
Prototype.l GdipDrawArcI      (*graphics, *pen  , x.l , y.l , width.l, height.l, startAngle.f, sweepAngle.f)
Prototype.l GdipDrawEllipseI  (*graphics, *pen  , x.l , y.l , width.l, height.l)
Prototype.l GdipFillEllipseI  (*graphics, *pen  , x.l , y.l , width.l, height.l)
Prototype.l GdipDrawBezierI   (*graphics, *pen  , x1.l, y1.l, x2.l   , y2.l    , x3.l, y3.l, x4.l, y4.l)
Prototype.l GdipDrawPolygonI  (*graphics, *pen  , *points.POINT, count.l)
Prototype.l GdipFillPolygon2I (*graphics, *brush, *points.POINT, count.l)

Macro DoubleQuote
    "
EndMacro

Macro setFunc(_name_)
    Global _name_#_._name_
    _name_#_ = GetFunction(__dll,DoubleQuote#_name_#DoubleQuote)
EndMacro

Macro toARGB(color)
    ( (color & $FF00FF00) | ( (color & $FF) << 16 ) | ((color >> 16) & $FF) )
EndMacro

Global __dll,__gdiplusToken.l,__drawingMode.l,__graphics,__lineCapStart,__lineCapEnd

Procedure gInit()
    __dll = OpenLibrary(#PB_Any, "gdiplus.dll")
    If Not __dll : ProcedureReturn 0 : EndIf
   
    setFunc(GdiplusStartup)
    setFunc(GdiplusShutdown)
    setFunc(GdipCreateFromHDC)
    setFunc(GdipDeleteGraphics)
    setFunc(GdipGraphicsClear)
    setFunc(GdipSetSmoothingMode)
    setFunc(GdipSetCompositingMode)
    setFunc(GdipSetCompositingQuality)
    setFunc(GdipSetInterpolationMode)
    setFunc(GdipSetPixelOffsetMode)
    setFunc(GdipCreatePen1)
    setFunc(GdipDeletePen)
    setFunc(GdipSetPenStartCap)
    setFunc(GdipSetPenEndCap)
    setFunc(GdipCreateSolidFill)
    setFunc(GdipDeleteBrush)
    setFunc(GdipDrawRectangleI)
    setFunc(GdipFillRectangleI)
    setFunc(GdipDrawLineI)
    setFunc(GdipDrawPieI)
    SetFunc(GdipFillPieI)
    setFunc(GdipDrawArcI)
    setFunc(GdipDrawEllipseI)
    SetFunc(GdipFillEllipseI)
    SetFunc(GdipDrawBezierI)
    SetFunc(GdipDrawPolygonI)
    SetFunc(GdipFillPolygon2I)

    ; Initialize GDI+.
    Protected gdiplusStartupInput.GdiplusStartupInput
   
    gdiplusStartupInput\GdiplusVersion              = 1
    gdiplusStartupInput\DebugEventCallback          = #Null
    gdiplusStartupInput\SuppressBackgroundThread    = #False
    gdiplusStartupInput\SuppressExternalCodecs      = #False
   
    If Not GdiplusStartup_(@__gdiplusToken, @gdiplusStartupInput, #Null)
        ProcedureReturn #True
    EndIf
EndProcedure

Procedure gEnd()
    GdiplusShutdown_(__gdiplusToken)
    If __dll
        CloseLibrary(__dll)
    EndIf
EndProcedure

Procedure gStartDrawing( out )
    Protected hDC

    hDC = StartDrawing(out)
    If Not hDC : ProcedureReturn 0 : EndIf
   
    GdipCreateFromHDC_(hDC ,@__graphics)
    If Not __graphics
        StopDrawing()
        ProcedureReturn 0
    EndIf
   
    __drawingMode  = #PB_2DDrawing_Default
    __lineCapStart = #LineCapFlat
    __lineCapEnd   = #LineCapFlat
    GdipSetSmoothingMode_     (__graphics,#SmoothingModeAntiAlias8x8)
    GdipSetCompositingMode_   (__graphics,#CompositingModeSourceOver)
    GdipSetCompositingQuality_(__graphics,#CompositingQualityGammaCorrected)
    GdipSetInterpolationMode_ (__graphics,#InterpolationModeHighQualityBicubic)
    GdipSetPixelOffsetMode_   (__graphics,#PixelOffsetModeHighQuality)
    ProcedureReturn hDC
EndProcedure

Procedure gStopDrawing()
    If __graphics
        GdipDeleteGraphics_( __graphics )
        __graphics = 0
    EndIf
    StopDrawing()
EndProcedure

Procedure gDrawingMode( newMode.l )
    __drawingMode = newMode
EndProcedure

Procedure gCapMode( lineCapStart.l, lineCapEnd.l )
    __lineCapStart = lineCapStart
    __lineCapEnd   = lineCapEnd
EndProcedure


Procedure gAntiAliasMode( newMode.l )
    If __graphics
        GdipSetSmoothingMode_(__graphics,newMode)
    EndIf
EndProcedure


Procedure gClear(color.l)
    If __graphics
        GdipGraphicsClear_(__graphics, toARGB(color))   
    EndIf
EndProcedure

Procedure gBox(x.l, y.l, width.l, height.l, color.l, penwidth.l=1)
    If __graphics
        If __drawingMode & #PB_2DDrawing_Outlined
            Protected *pen
            GdipCreatePen1_(toARGB(color),penwidth,2,@*pen)
            GdipDrawRectangleI_(__graphics,*pen,x,y,width,height)
            GdipDeletePen_(*pen)
        Else
            Protected *brush
            GdipCreateSolidFill_(toARGB(color),@*brush)
            GdipFillRectangleI_(__graphics,*brush,x,y,width,height)
            GdipDeleteBrush_(*brush)
        EndIf
    EndIf
EndProcedure


Procedure gLineXY(x1.l, y1.l, x2.l, y2.l, color.l, penwidth.l=1)
    If __graphics
        Protected *pen
        GdipCreatePen1_(toARGB(color),penwidth,2,@*pen)
        GdipSetPenStartCap_(*pen, __lineCapStart)
        GdipSetPenEndCap_  (*pen, __lineCapEnd  )
        GdipDrawLineI_(__graphics,*pen,x1,y1,x2,y2)
        GdipDeletePen_(*pen)
    EndIf
EndProcedure

Procedure gLine(x.l, y.l, width.l, height.l, color.l, penwidth.l=1)
    gLineXY(x,y,x+width,y+height,color,penwidth)
EndProcedure

Procedure gPie(x.l, y.l, radiusX.l, radiusY.l, startAngle.f, sweepAngle.f, color.l, penwidth.l=1)
    If __graphics
        If __drawingMode & #PB_2DDrawing_Outlined
            Protected *pen
            GdipCreatePen1_(toARGB(color),penwidth,2,@*pen)
            GdipDrawPieI_(__graphics,*pen,x-radiusX,y-radiusY,radiusX*2,radiusY*2,startAngle,sweepAngle)
            GdipDeletePen_(*pen)
        Else
            Protected *brush
            GdipCreateSolidFill_(toARGB(color),@*brush)
            GdipFillPieI_(__graphics,*brush,x-radiusX,y-radiusY,radiusX*2,radiusY*2,startAngle,sweepAngle)
            GdipDeleteBrush_(*brush)
        EndIf
    EndIf
EndProcedure

Procedure gArc(x.l, y.l, radiusX.l, radiusY.l, startAngle.f, sweepAngle.f, color.l, penwidth.l=1)
    If __graphics
        Protected *pen
        GdipCreatePen1_(toARGB(color),penwidth,2,@*pen)
        GdipSetPenStartCap_(*pen, __lineCapStart)
        GdipSetPenEndCap_  (*pen, __lineCapEnd  )
        GdipDrawArcI_(__graphics,*pen,x-radiusX,y-radiusY,radiusX*2,radiusY*2,startAngle,sweepAngle)
        GdipDeletePen_(*pen)
    EndIf
EndProcedure

Procedure gEllipse(x.l, y.l, radiusX.l, radiusY.l, color.l, penwidth.l=1)
    If __graphics
        If __drawingMode & #PB_2DDrawing_Outlined
            Protected *pen
            GdipCreatePen1_(toARGB(color),penwidth,2,@*pen)
            GdipDrawEllipseI_(__graphics,*pen,x-radiusX,y-radiusY,radiusX*2,radiusY*2)
            GdipDeletePen_(*pen)
        Else
            Protected *brush
            GdipCreateSolidFill_(toARGB(color),@*brush)
            GdipFillEllipseI_(__graphics,*brush,x-radiusX,y-radiusY,radiusX*2,radiusY*2)
            GdipDeleteBrush_(*brush)
        EndIf
    EndIf
EndProcedure

Procedure gCircle(x.l, y.l, radius.l, color.l, penwidth.l=1)
    gEllipse(x,y,radius,radius,color,penwidth)
EndProcedure

Procedure gBezier(x1.l, y1.l, x2.l, y2.l, x3.l, y3.l, x4.l, y4.l, color.l, penwidth.l=1)
    If __graphics
        Protected *pen
        GdipCreatePen1_(toARGB(color),penwidth,2,@*pen)
        GdipSetPenStartCap_(*pen, __lineCapStart)
        GdipSetPenEndCap_  (*pen, __lineCapEnd  )
        GdipDrawBezierI_(__graphics,*pen,x1,y1,x2,y2,x3,y3,x4,y4)
        GdipDeletePen_(*pen)
    EndIf
EndProcedure

Procedure gPoly(x1.l, y1.l, x2.l, y2.l, x3.l, y3.l, color.l, penwidth.l=1)
    If __graphics
        Dim points.POINT(3)
        points(0)\x = x1
        points(0)\y = y1
        points(1)\x = x2
        points(1)\y = y2
        points(2)\x = x3
        points(2)\y = y3
        If __drawingMode & #PB_2DDrawing_Outlined
            Protected *pen
            GdipCreatePen1_(toARGB(color),penwidth,2,@*pen)
            GdipDrawPolygonI_(__graphics,*pen,@points(),3)
            GdipDeletePen_(*pen)
        Else
            Protected *brush
            GdipCreateSolidFill_(toARGB(color),@*brush)
            GdipFillPolygon2I_(__graphics,*brush,@points(),3)
            GdipDeleteBrush_(*brush)
        EndIf
    EndIf
EndProcedure

;>----- END INCLUDE -----------------------------------------

;- Program

Global img, currentColor, drawMode
Global startPos.POINT
Global endPos.POINT
Global mainWin, imgWin, modeWin
Define i.l, mouseDown.l, copy
Global currentColor = RGBA($00,$00,$FF,$80)
Global currentPenSize = 15

Procedure redraw(image)
    If gStartDrawing( ImageOutput(image) )
        If image <> img
            DrawImage(ImageID(img),0,0)
        EndIf
        gCapMode(#LineCapRound,#LineCapRound)
        gDrawingMode(#PB_2DDrawing_Outlined)
        Select drawMode
            Case 0 : gLineXY(startPos\x,startPos\y,endPos\x,endPos\y,currentColor,currentPenSize)
            Case 1 : gBox(startPos\x,startPos\y,endPos\x-startPos\x,endPos\y-startPos\y,currentColor,currentPenSize)
            Case 2 : gEllipse(startPos\x,startPos\y,endPos\x-startPos\x,endPos\y-startPos\y,currentColor,currentPenSize)
            Case 3 : gCircle(startPos\x,startPos\y,endPos\x-startPos\x,currentColor,currentPenSize)
        EndSelect
        gStopDrawing()
        If IsGadget(imgWin)
            SetGadgetState(imgWin,ImageID(image))
        EndIf
    EndIf
EndProcedure


If gInit()
    img = CreateImage(#PB_Any,850,600,24)
    If gStartDrawing( ImageOutput(img) )
        gClear( RGBA($80,$80,$80,$FF) )
        gDrawingMode(#PB_2DDrawing_Outlined)
        gBox(50,50,100,100,RGBA($40,$40,$40,$FF),5)
        gLineXY(160,50,260,150,RGBA($00,$00,$FF,$FF),5)
        gDrawingMode(#PB_2DDrawing_Default)
        gPie(320,100,49,49,-90,110,RGBA($FF,$FF,$00,$FF))
        gPie(320,100,49,49, 20, 50,RGBA($00,$FF,$FF,$FF))
        gPie(320,100,49,49, 70, 60,RGBA($00,$00,$FF,$FF))
        gDrawingMode(#PB_2DDrawing_Outlined)
        gPie(320,100,50,50,-90,220,RGBA($00,$00,$00,$FF),3)
        For i = 0 To 260 Step 20
            gArc(430,100,50,50,-90+i,15,RGBA($00,$00,$00,$FF),3)
        Next i
        gDrawingMode(#PB_2DDrawing_Default)
        gEllipse(540,100,50,25,RGBA($FF,$FF,$FF,$FF))
        gCircle(540,100,25,RGBA($00,$FF,$00,$FF))
        gCircle(540,100,10,RGBA($00,$00,$00,$FF))
        gDrawingMode(#PB_2DDrawing_Outlined)
        gEllipse(540,100,50,25,RGBA($00,$00,$00,$FF),2)
        gCircle(540,100,25,RGBA($00,$00,$00,$FF),2)
        gBezier(600,50,800,100,500,100,700,150,RGBA($00,$FF,$FF,$FF),2)
        gPoly(710,50,730,150,780,80,RGBA($FF,$00,$FF,$FF),2)

        gDrawingMode(#PB_2DDrawing_Default)
        gBox(70,100,100,100,RGBA($00,$00,$00,$80))
        gPie(340,150,50,50,-90,220,RGBA($00,$00,$00,$80))
        gEllipse(570,150,50,25,RGBA($00,$00,$00,$80))
        gPoly(730,100,750,200,800,130,RGBA($00,$00,$00,$80))

        gCapMode(#LineCapRound,#LineCapArrowAnchor)
        gLineXY(190,100,290,200,RGBA($00,$00,$00,$80),15)
        For i = 0 To 260 Step 40
            gArc(460,150,50,50,-90+i,30,RGBA($00,$00,$00,$80),7)
        Next i
        gBezier(620,100,820,150,520,150,720,200,RGBA($00,$00,$00,$80),7)


        gStopDrawing()
    EndIf
   
    mainWin = OpenWindow(#PB_Any,0,0,850,620,"Draw!",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
   
    modeWin = ComboBoxGadget(#PB_Any,0,600,100,20)
    AddGadgetItem(modeWin,-1,"Line")
    AddGadgetItem(modeWin,-1,"Box")
    AddGadgetItem(modeWin,-1,"Ellipse")
    AddGadgetItem(modeWin,-1,"Circle")
    SetGadgetState(modeWin,0)
   
    imgWin  = ImageGadget(#PB_Any,0,00,850,600,ImageID(img))
    DisableGadget(imgWin,1)
   
    Repeat
        Select WaitWindowEvent()
            Case #PB_Event_CloseWindow
                Break
            Case #PB_Event_Gadget
                Select EventGadget()
                    Case modeWin    : drawMode = GetGadgetState(modeWin)
                EndSelect
            Case #WM_LBUTTONDOWN
                GetCursorPos_(@startPos)
                ScreenToClient_(GadgetID(imgWin),@startPos)
                If startPos\y < 600
                    SetCapture_(WindowID(mainWin))
                    mouseDown = 1
                    endPos\x = startPos\x+1
                    endPos\y = startPos\y+1
                    If copy : FreeImage(copy) : EndIf
                    copy = CopyImage(img,#PB_Any)
                EndIf
            Case #WM_LBUTTONUP
                If mouseDown
                    ReleaseCapture_()
                    mouseDown = 0
                    redraw(img)
                EndIf
            Case #WM_MOUSEMOVE
                If mouseDown
                    GetCursorPos_(@endPos)
                    ScreenToClient_(GadgetID(imgWin),@endPos)
                    redraw(copy)
                EndIf
        EndSelect
    ForEver

    gEnd()
EndIf
Linux Mint 21.1 Vera base: Ubuntu 22.04 jammy.
PureBasic 6.10 LTS (Linux - x64)
Post Reply