-
Jul 17th, 2013, 10:46 AM
#1
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.
-
Jul 17th, 2013, 05:54 PM
#2
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?
-
Jul 18th, 2013, 03:09 AM
#3
Re: BSpline-based "Bezier-Art"
Originally Posted by dilettante
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.
-
May 20th, 2017, 05:53 PM
#4
Lively Member
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.
-
May 21st, 2017, 04:37 AM
#5
Re: BSpline-based "Bezier-Art"
Originally Posted by CreativeDreamer
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
-
May 22nd, 2017, 04:37 AM
#6
Re: BSpline-based "Bezier-Art"
Originally Posted by Schmidt
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
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|