Results 1 to 6 of 6

Thread: BSpline-based "Bezier-Art"

  1. #1

    Thread Starter
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,219

    BSpline-based "Bezier-Art"

    A small Graphics-Demo for VB6, which shows the nice effects one can produce, when Anti-Aliasing in conjunction with Color-Alpha-settings is combined with "curved Line-Output".

    Here's the ~90 lines of code, to put into a single VB-Form:
    Code:
    'needs a reference to the free vbRichClient5-lib, which is located and available on:
    'http://www.vbRichClient.com/#/en/Downloads.htm
    Option Explicit
     
    Private Srf As cCairoSurface, NumPoints As Single
    Private pntX() As Single, pntY() As Single, sgnX() As Single, sgnY() As Single
    Private WithEvents tmrRefresh As cTimer
    
    Private Sub Form_Load()
    Dim i As Long
    '    Rnd -1 'uncomment, if you want to always start from the same "randomness"
    
        Me.ScaleMode = vbPixels
        Me.Caption = "Left-Click for Start/Stop, Right-Click to clear"
        
        NumPoints = 7
        ReDim pntX(1 To NumPoints): ReDim pntY(1 To NumPoints)
        ReDim sgnX(1 To NumPoints): ReDim sgnY(1 To NumPoints)
     
        For i = 1 To NumPoints
          pntX(i) = ScaleWidth * Rnd
          pntY(i) = ScaleHeight * Rnd
          sgnX(i) = IIf(i Mod 2, 1, -1)
          sgnY(i) = IIf(i Mod 2, -1, 1)
        Next i
        
        Set tmrRefresh = New_c.Timer(10, True)
    End Sub
     
    Private Sub Form_DblClick()
      tmrRefresh.Enabled = Not tmrRefresh.Enabled
    End Sub
    Private Sub Form_MouseDown(Button As Integer, Shift As Integer, x As Single, y As Single)
      If Button = 1 Then tmrRefresh.Enabled = Not tmrRefresh.Enabled
      If Button = 2 Then Set Srf = Cairo.CreateSurface(ScaleWidth, ScaleHeight) 'reset the surface
    End Sub
    
    Private Sub Form_Resize()
      Set Srf = Cairo.CreateSurface(ScaleWidth, ScaleHeight)
    End Sub
    
    Private Sub Form_Terminate()
      If Forms.Count = 0 Then New_c.CleanupRichClientDll
    End Sub
    
    Private Sub tmrRefresh_Timer()
    Dim i As Integer, cc As Long
    
      For cc = 1 To 100 'just to perform some more operations within a single timer-event
    
        For i = 1 To NumPoints 'the next two lines influence the erratic point-movement (just play around)
          pntX(i) = pntX(i) + sgnX(i) * 0.0004 * Abs(pntY(i) - pntX(i))
          pntY(i) = pntY(i) + sgnY(i) * 0.1 / Abs((33 - pntY(i)) / (77 + pntX(i)))
          
          If pntX(i) < ScaleLeft Then pntX(i) = ScaleLeft: sgnX(i) = 1
          If pntX(i) > ScaleLeft + ScaleWidth Then pntX(i) = ScaleLeft + ScaleWidth: sgnX(i) = -1
          If pntY(i) < ScaleTop Then pntY(i) = ScaleTop: sgnY(i) = 1
          If pntY(i) > ScaleHeight + ScaleTop Then pntY(i) = ScaleHeight + ScaleTop: sgnY(i) = -1
        Next i
      
        Static j As Long, k As Single
        k = k + 0.34: If k > 255 Then k = 0: j = j + 1: If j > 5 Then j = 0
        Select Case j
          Case 0: draw RGB(k, 255 - k, 255)
          Case 1: draw RGB(255, k, 255 - k)
          Case 2: draw RGB(255 - k, 255, k)
          Case 3: draw RGB(0, 255 - k, k)
          Case 4: draw RGB(0, 0, 255 - k)
          Case 5: draw RGB(255 - k, k, 0)
        End Select
        
        If cc Mod 10 = 0 Then Srf.DrawToDC hDC
     
      Next cc
    End Sub
     
    Private Sub draw(ByVal Color As Long)
    Dim i As Long, PolyArr() As Single
      ReDim PolyArr(0 To (NumPoints + 3) * 2 - 1)
      For i = 0 To NumPoints - 1 'this is just a normal copy-over
        PolyArr(2 * i) = pntX(i + 1) 'the dst-array has x at even indexes...
        PolyArr(2 * i + 1) = pntY(i + 1) 'and the y-coord at the uneven ones
      Next i
      For i = 0 To 2 'now we add 3 additional points, to "close the circle" (so to say)
        PolyArr(2 * (NumPoints + i)) = PolyArr(2 * i) 'those extra-points are copies ...
        PolyArr(2 * (NumPoints + i) + 1) = PolyArr(2 * i + 1) '...of the first 3 points
      Next i
      
      With Srf.CreateContext 'once we have filled our PolyArr, the rest is pretty simple
        .SetSourceColor Color, 0.05
        .SetLineWidth 0.5
          .PolygonSingle PolyArr, False, splNormal '... using the powerful Poly-call
        .Stroke
      End With
    End Sub
    The example starts out producing something like that (all Screenshots were reduced in their Pixel-dimensions for smaller upload/download-size - they look even a bit better when directly rendered):



    Then, as long as not resetted continues adding more and more alpha-curves (still the same "set" as above, just some more rendered lines on it):



    But one can reset the whole thing with the right Mouse and start with a fresh image, ending up with something like this:



    Just play around with it (and maybe manipulate the PolyArray-xy-Coords with your own random move-formulas or parameters) ...
    Have fun... :-)

    Olaf
    Last edited by Schmidt; Jul 17th, 2013 at 06:43 PM.

  2. #2
    PowerPoster
    Join Date
    Feb 2006
    Posts
    24,482

    Re: BSpline-based "Bezier-Art"

    Very nice looking, but you do you have a simple demo showing how we might use this beyond abstract decorative "aurora" screensavers and such?

    Perhaps a simple data charting example supporting 3D bar graphs where the bars have various cross-sections (triangular and square prisms, circular and elliptical tubes, etc.) for each of several data series? Maybe some 3D extruded text labels just to show what can be done?

    Or maybe there are other applications of these techniques I haven't thought of?

  3. #3

    Thread Starter
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,219

    Re: BSpline-based "Bezier-Art"

    Quote Originally Posted by dilettante View Post
    Very nice looking, but you do you have a simple demo showing how we might use this beyond abstract decorative "aurora" screensavers and such?

    Perhaps a simple data charting example supporting 3D bar graphs where the bars have various cross-sections (triangular and square prisms, circular and elliptical tubes, etc.) for each of several data series? Maybe some 3D extruded text labels just to show what can be done?

    Or maybe there are other applications of these techniques I haven't thought of?
    I'm not sure, what "techniques" you are referring to exactly, because the two main-requirements to achieve similar results as the demo above are only:
    - you need Bezier- or BSpline-call support (e.g. already good old GDI supports Bezier-Curves)
    - you need a 2D-lib that supports anti-aliased rendering + the definition of semi-transparent colors for "stroke or fill" (e.g. GDI+ allows that, whilst GDI does not)

    In the concrete example above, the 2D-functionality is provided by cairo (a wellknown OpenSource-lib, which the RichClient-COMlib wraps in comfortable classes) -
    and the Curves in question were generated with the wrappers Polygon-API-method (cairo natively doesn't offer a higher-level API for the rendering of Poly-Points).

    So the wrappers PolygonAPI allows the comfortable passing of VBArrays of type Double or of Type Single - and aside from rendering such a Polygon
    with the usual direct line-connections, it also supports a "rendering in-between those PolyPoints, using BSplines" - and that latter feature is, what the
    demo above is using, to generate "curved paths".

    If you want to see the just mentioned PolygonAPI-support of the RC5-wrapper in a more serious application
    (e.g. here I have those recently encountered questions in mind, where the creation of Polynom-Coefficients was asked,
    based on a few "incoming Sampling-Points", perhaps to be able to interpolate in-between those points - and perhaps
    those interpolated Values were used finally, to "just render something between the original points").

    Well, that usecase is needed often enough when you want to visualize curves from arbitrary incoming measurement-data.

    Here's what's needed for this concrete task with the RC5-lib (it boils down to specifying one single optional parameter):



    Here the appropriate code in Text-format (paste it into a single VB-Form)
    Code:
    'needs a reference to the free vbRichClient5-lib, which is located and available on:
    'http://www.vbRichClient.com/#/en/Downloads.htm
    Option Explicit
    
    Private Type PointDbl
      x As Double
      y As Double
    End Type
    
    Private Srf As cCairoSurface, Pts() As PointDbl
     
    Private Sub Form_Load()
      'Let's assume we have 5 x,y-Points of incoming measurement-data
      'and those points are not even equidistant in x-direction...
      
      ReDim Pts(0 To 4) 'reserve memory for those points, and fill with data
            Pts(0).x = 100: Pts(0).y = 150
            Pts(1).x = 180: Pts(1).y = 100
            Pts(2).x = 330: Pts(2).y = 200
            Pts(3).x = 450: Pts(3).y = 150
            Pts(4).x = 650: Pts(4).y = 300
            
      Move Left, Top, Screen.Width / 2, Screen.Height / 2
    End Sub
     
    Private Sub Form_Resize() 'here we ensure, that the Surface has the same size as the form ...
      ScaleMode = vbPixels 'just take care, to ensure this size in Pixels (not in Twips ;-)
      Set Srf = Cairo.CreateSurface(ScaleWidth, ScaleHeight)
      Draw
    End Sub
    
    Private Sub Draw()
    Dim i As Long
     
      'Ok, onto the drawing:
      With Srf.CreateContext 'we derive a drawing-context from our Surface
        'and since we want to render within a Bottom-Up-Coord-System, ...
         
        'we change from our top-down-default with the usual two lines of code:
        .TranslateDrawings 0, Srf.Height 'the y-coord-point is shifted to the bottom
        .ScaleDrawings 1, -1 'and the y-scale is negated (but otherwise not "stretched")
        
        'now let's draw lines between our Poly-Points as any PolygonAPI-call allows
        .SetSourceColor vbGreen 'define the color for the next operation
          .PolygonPtr VarPtr(Pts(0)), UBound(Pts) + 1 'define the path per drawing-call
        .Stroke 'stroke it with the current color
        
        'now, what if we need to draw between our measure-points more smoothly?
        .SetSourceColor vbRed '...easy as pie, since we use the same call on the same data...
          .PolygonPtr VarPtr(Pts(0)), UBound(Pts) + 1, , splNormal, True '<-just two more params
        .Stroke 'stroke it with the current color
        
        'and just for good measure, we visualize, where the original Points were
        .SetSourceColor vbYellow, 0.5 '<- an Alpha-Color-Def for the points-overlay
        For i = 0 To UBound(Pts)
          .ARC Pts(i).x, Pts(i).y, 7 'a fully closed circle with radius 7
          .Fill 'fill the circular path
        Next i
        
      End With
    
      Set Me.Picture = Srf.Picture 'this is just one of the different output-methods of a cairo-surface
    End Sub
    
    Private Sub Form_Terminate()
      If Forms.Count = 0 Then New_c.CleanupRichClientDll
    End Sub
    If you're after more and deeper examples (not only for the Polygon-API-call above) then (by all means), please download the huge cairo-Drawing-Tutorial...
    Here's a page which links to all the different Tutorials for the RC5-lib.
    http://www.vbrichclient.com/#/en/Demos/GUI/

    And here's a direct link to the Zip-File of the cairo-Tutorial (which contains in 20+ standalone Folders everything a VB-Dev possibly needs, to satisfy "modern 2D-grahics-desires" <g>).
    http://www.vbrichclient.com/Download...roTutorial.zip (about 7MB, because it contains a lot of image-resources)

    Since we talked about BSplines - here's another use-case, e.g. when you want to define the Baseline for "curved TextOutputs" (with draggable control-points):



    Or since you were interested in more "charting-like outputs" - here's dynamically and directly (per cairo-surface) created PDF:
    (the small window to the right side shows only a visualizing of the cairo-created PDF-output, it's just a secondary screen which
    doesn't have much to do with the Demo itself, because the OnScreen-Preview of the PDF is done per cairo-ImageSurface-type -
    and then the same drawing-routines are applied against cairos PDF-surface-type, without changing a single line of drawing-code.



    Olaf
    Last edited by Schmidt; Jul 18th, 2013 at 03:19 AM.

  4. #4
    Lively Member
    Join Date
    Mar 2015
    Posts
    104

    Re: BSpline-based "Bezier-Art"

    In Flash animator, there is a function to smoothen out hand drawn curves. I was wondering could a BSpline be used to do this? Sort of like you draw a squiggle in a vb paint program and the BSpline smoothens it out.

  5. #5

    Thread Starter
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,219

    Re: BSpline-based "Bezier-Art"

    Quote Originally Posted by CreativeDreamer View Post
    In Flash animator, there is a function to smoothen out hand drawn curves. I was wondering could a BSpline be used to do this? Sort of like you draw a squiggle in a vb paint program and the BSpline smoothens it out.
    Exactly that is explained (including working VB6-Formcode) in post #3 above (the red Curve is drawn
    from the very same PolygonPoint-Array as the green-colored "jagged line").

    Olaf

  6. #6
    PowerPoster
    Join Date
    Sep 2012
    Posts
    2,083

    Re: BSpline-based "Bezier-Art"

    Quote Originally Posted by Schmidt View Post
    I'm not sure, what "techniques" you are referring to exactly, because the two main-requirements to achieve similar results as the demo above are only:
    - you need Bezier- or BSpline-call support (e.g. already good old GDI supports Bezier-Curves)
    - you need a 2D-lib that supports anti-aliased rendering + the definition of semi-transparent colors for "stroke or fill" (e.g. GDI+ allows that, whilst GDI does not)

    In the concrete example above, the 2D-functionality is provided by cairo (a wellknown OpenSource-lib, which the RichClient-COMlib wraps in comfortable classes) -
    and the Curves in question were generated with the wrappers Polygon-API-method (cairo natively doesn't offer a higher-level API for the rendering of Poly-Points).

    So the wrappers PolygonAPI allows the comfortable passing of VBArrays of type Double or of Type Single - and aside from rendering such a Polygon
    with the usual direct line-connections, it also supports a "rendering in-between those PolyPoints, using BSplines" - and that latter feature is, what the
    demo above is using, to generate "curved paths".

    If you want to see the just mentioned PolygonAPI-support of the RC5-wrapper in a more serious application
    (e.g. here I have those recently encountered questions in mind, where the creation of Polynom-Coefficients was asked,
    based on a few "incoming Sampling-Points", perhaps to be able to interpolate in-between those points - and perhaps
    those interpolated Values were used finally, to "just render something between the original points").

    Well, that usecase is needed often enough when you want to visualize curves from arbitrary incoming measurement-data.

    Here's what's needed for this concrete task with the RC5-lib (it boils down to specifying one single optional parameter):



    Here the appropriate code in Text-format (paste it into a single VB-Form)
    Code:
    'needs a reference to the free vbRichClient5-lib, which is located and available on:
    'http://www.vbRichClient.com/#/en/Downloads.htm
    Option Explicit
    
    Private Type PointDbl
      x As Double
      y As Double
    End Type
    
    Private Srf As cCairoSurface, Pts() As PointDbl
     
    Private Sub Form_Load()
      'Let's assume we have 5 x,y-Points of incoming measurement-data
      'and those points are not even equidistant in x-direction...
      
      ReDim Pts(0 To 4) 'reserve memory for those points, and fill with data
            Pts(0).x = 100: Pts(0).y = 150
            Pts(1).x = 180: Pts(1).y = 100
            Pts(2).x = 330: Pts(2).y = 200
            Pts(3).x = 450: Pts(3).y = 150
            Pts(4).x = 650: Pts(4).y = 300
            
      Move Left, Top, Screen.Width / 2, Screen.Height / 2
    End Sub
     
    Private Sub Form_Resize() 'here we ensure, that the Surface has the same size as the form ...
      ScaleMode = vbPixels 'just take care, to ensure this size in Pixels (not in Twips ;-)
      Set Srf = Cairo.CreateSurface(ScaleWidth, ScaleHeight)
      Draw
    End Sub
    
    Private Sub Draw()
    Dim i As Long
     
      'Ok, onto the drawing:
      With Srf.CreateContext 'we derive a drawing-context from our Surface
        'and since we want to render within a Bottom-Up-Coord-System, ...
         
        'we change from our top-down-default with the usual two lines of code:
        .TranslateDrawings 0, Srf.Height 'the y-coord-point is shifted to the bottom
        .ScaleDrawings 1, -1 'and the y-scale is negated (but otherwise not "stretched")
        
        'now let's draw lines between our Poly-Points as any PolygonAPI-call allows
        .SetSourceColor vbGreen 'define the color for the next operation
          .PolygonPtr VarPtr(Pts(0)), UBound(Pts) + 1 'define the path per drawing-call
        .Stroke 'stroke it with the current color
        
        'now, what if we need to draw between our measure-points more smoothly?
        .SetSourceColor vbRed '...easy as pie, since we use the same call on the same data...
          .PolygonPtr VarPtr(Pts(0)), UBound(Pts) + 1, , splNormal, True '<-just two more params
        .Stroke 'stroke it with the current color
        
        'and just for good measure, we visualize, where the original Points were
        .SetSourceColor vbYellow, 0.5 '<- an Alpha-Color-Def for the points-overlay
        For i = 0 To UBound(Pts)
          .ARC Pts(i).x, Pts(i).y, 7 'a fully closed circle with radius 7
          .Fill 'fill the circular path
        Next i
        
      End With
    
      Set Me.Picture = Srf.Picture 'this is just one of the different output-methods of a cairo-surface
    End Sub
    
    Private Sub Form_Terminate()
      If Forms.Count = 0 Then New_c.CleanupRichClientDll
    End Sub
    If you're after more and deeper examples (not only for the Polygon-API-call above) then (by all means), please download the huge cairo-Drawing-Tutorial...
    Here's a page which links to all the different Tutorials for the RC5-lib.
    http://www.vbrichclient.com/#/en/Demos/GUI/

    And here's a direct link to the Zip-File of the cairo-Tutorial (which contains in 20+ standalone Folders everything a VB-Dev possibly needs, to satisfy "modern 2D-grahics-desires" <g>).
    http://www.vbrichclient.com/Download...roTutorial.zip (about 7MB, because it contains a lot of image-resources)

    Since we talked about BSplines - here's another use-case, e.g. when you want to define the Baseline for "curved TextOutputs" (with draggable control-points):



    Or since you were interested in more "charting-like outputs" - here's dynamically and directly (per cairo-surface) created PDF:
    (the small window to the right side shows only a visualizing of the cairo-created PDF-output, it's just a secondary screen which
    doesn't have much to do with the Demo itself, because the OnScreen-Preview of the PDF is done per cairo-ImageSurface-type -
    and then the same drawing-routines are applied against cairos PDF-surface-type, without changing a single line of drawing-code.



    Olaf
    FasionCharts for VB6 is the best VB6 chart control I've ever seen, but this control was abandoned by its developer InfoSoft Global a few years ago. I know that the development workload of a similar chart control is very large if we start from scratch. Whether vbRichClient5(Cairo graphics engine) can reduce the development workload of this chart control. Or whether there is a better product that can replace FusionCharts for VB6.

    Now many people are using JavaScript and HTML5 to develop chart control, if VB6 can use these chart controls it would be great. (I mean wrapping a JavaScript or HTML5 chart control into an OCX control for VB6 calls like FusionCharts for VB6.)

    My current work doesn't need to use the chart control, I am only interested in this issue.
    Last edited by dreammanor; May 22nd, 2017 at 09:56 AM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width