The Demo shows, how to create Path-Objects via simple helper-functions (of return-type cCairoPath) -
and how to "Append" and then "Stroke" these Paths via similar named methods on a cCairoContext.
I guess, this is also a topic for "Makers" (Laser-Cutting, 3D-Printing)...
Simple Path-construction-functions as e.g.:
- a path for a single tooth of a gear (or its horizontal expansion via loop)
- or a single path for a curve, or a circle
are relatively easy to "code by hand".
But what if e.g. a "horizontal line of teeth" (as used on a "rack") needs to follow a curved- or circular track?
Such "combined complex paths" are difficult to "define by hand" -
and that's where the second part of the Demo comes into play:
showing how one can project one path in a way, so that it "follows" another Path.
E.g. if you look at the 1st ScreenShot here, which shows the Demo after it was just starting up:
(showing the "yet un-projected two Paths" which we've generated, a "horizontal line of teeths" and "a circle"):
![Name: PathProjection1.png
Views: 29
Size: 43.3 KB]()
Ok, now - with a single Method-call (ProjectPathData) on the cairo-context, we can combine the two paths
(producing a combined path for a "42-teeth-gear"):
![Name: PathProjection2.png
Views: 26
Size: 39.1 KB]()
Third and last image is just showing, that any (horizontally designed) Path-Renderings -
can be projected onto any other (arbitrary) path or curve.
![Name: PathProjection3.jpg
Views: 26
Size: 42.7 KB]()
Here is the code for a single (empty) Form-Project (which needs a reference to RC6):
Have fun,
Olaf
and how to "Append" and then "Stroke" these Paths via similar named methods on a cCairoContext.
I guess, this is also a topic for "Makers" (Laser-Cutting, 3D-Printing)...
Simple Path-construction-functions as e.g.:
- a path for a single tooth of a gear (or its horizontal expansion via loop)
- or a single path for a curve, or a circle
are relatively easy to "code by hand".
But what if e.g. a "horizontal line of teeth" (as used on a "rack") needs to follow a curved- or circular track?
Such "combined complex paths" are difficult to "define by hand" -
and that's where the second part of the Demo comes into play:
showing how one can project one path in a way, so that it "follows" another Path.
E.g. if you look at the 1st ScreenShot here, which shows the Demo after it was just starting up:
(showing the "yet un-projected two Paths" which we've generated, a "horizontal line of teeths" and "a circle"):
Ok, now - with a single Method-call (ProjectPathData) on the cairo-context, we can combine the two paths
(producing a combined path for a "42-teeth-gear"):
Third and last image is just showing, that any (horizontally designed) Path-Renderings -
can be projected onto any other (arbitrary) path or curve.
Here is the code for a single (empty) Form-Project (which needs a reference to RC6):
Code:
Option Explicit
Const TeethCount = 42, TeethHeight = 5, SinglePeriodDistance = 12
Private CC As cCairoContext, WithEvents Btn As VB.CommandButton
Private Sub Form_Load()
Set Btn = Controls.Add("VB.CommandButton", "Btn") 'add a checkbox dynamically
Btn.Caption = "Project teeth to circular Path": Btn.Visible = 1
Move Left, Top, ScaleX(590, vbPixels, vbTwips), ScaleY(320, vbPixels, vbTwips)
End Sub
Private Sub Form_Resize() 'the usual lines, to keep CC as a "Form-covering-context
ScaleMode = vbPixels: Set CC = Cairo.CreateSurface(ScaleWidth, ScaleHeight).CreateContext
RefreshDrawings False
End Sub
Private Sub Btn_Click()
RefreshDrawings
Btn.Caption = "Project teeth to " & IIf(InStr(Btn.Caption, "curved"), "circular Path", "curved Path")
End Sub
Private Sub RefreshDrawings(Optional ByVal UseProjection As Boolean = True)
CC.Paint 1, Cairo.CreateCheckerPattern
Dim PPath As cCairoPath: Set PPath = CreateProjectionPath()
Dim TPath As cCairoPath: Set TPath = CreateTeethPath()
If UseProjection Then TPath.ProjectPathData_Using PPath '<- here's where the magic happens (TPath will now "follow along" PPath)
CC.Save '<- isolates the render-output of our two paths...
CC.TranslateDrawings 55, 55 '...because we use a transform (here only, to provide some shifting)
RenderStrokedPath PPath, 1, vbBlue
RenderStrokedPath TPath, 2, vbRed
CC.Restore
Set Picture = CC.Surface.Picture
End Sub
Sub RenderStrokedPath(Path As cCairoPath, Optional ByVal LineWidth& = 1, Optional ByVal Color&)
CC.AppendPath Path 'add the Projection-Path to the context
CC.SetLineWidth LineWidth
CC.Stroke , Cairo.CreateSolidPatternLng(Color)
End Sub
Function CreateProjectionPath() As cCairoPath
Dim PC As cCairoContext
Set PC = Cairo.CreateSurface(1, 1).CreateContext 'ensure a "Projection-Context"
If InStr(Btn.Caption, "curved") Then
PC.CurveTo 0, 0, 90, 0, 190, 120
PC.RelCurveTo 120, 150, 90, 0, 190, -66
Else
PC.Arc 80, 100, (TeethCount * SinglePeriodDistance) / (2 * Cairo.PI)
End If
Set CreateProjectionPath = PC.CopyPath(True) 'return the resulting path
End Function
Function CreateTeethPath(Optional ByVal StepsPerToothPeriod& = 32) As cCairoPath
Dim PC As cCairoContext, i As Long, j As Long, x As Double, y As Double
Set PC = Cairo.CreateSurface(1, 1).CreateContext 'ensure a "Projection-Context"
PC.MoveTo 0, 0 'ensure a valid starting-point for the (horizontal to the right) teeth-renderings
For i = 1 To TeethCount 'repeat the whole thing, according to our TeethCount-constant
AddSingleToothTo PC, x, y, StepsPerToothPeriod
Next
Set CreateTeethPath = PC.CopyPath(True) 'return the resulting path
End Function
Sub AddSingleToothTo(PC As cCairoContext, x, y, StepsPerToothPeriod)
Dim i As Long
For i = 1 To StepsPerToothPeriod 'this loop is a generator for a simpe, single "SinusTooth"
x = x + SinglePeriodDistance / StepsPerToothPeriod
y = Sin(i / StepsPerToothPeriod * 2 * Cairo.PI) * TeethHeight
PC.LineTo x, -y
Next
End Sub
Olaf