Results 1 to 22 of 22

Thread: RC6 Cairo Path "Double" Stroke

  1. #1

    Thread Starter
    PowerPoster
    Join Date
    Aug 2010
    Location
    Canada
    Posts
    2,715

    RC6 Cairo Path "Double" Stroke

    Any RC6 Cairo users know if there is a way to perform a second stroke around/outside of a first stroke? Something that looks like this:

    Name:  2025-03-05_16-57-58.jpg
Views: 455
Size:  23.6 KB

    I see that it is possible to get the extents of the path including the Stroke using GetStrokeExtents, but using CopyPath doesn't seem to be able to return the Path with the Stroke applied, just the main path points (unless I'm missing something)?

    Code:
    Option Explicit
    
    Private Sub Form_Click()
       Dim x1 As Double, y1 As Double, x2 As Double, y2 As Double
       Dim w As Double, h As Double
    
       With Cairo.CreateSurface(Me.ScaleWidth, Me.ScaleHeight)
          With .CreateContext
             ' Fill entire background of surface
             .SetSourceColor vbWhite
             .Paint
    
             ' Draw a simple but arbitrary polygon path
             .MoveTo 50, 50
             .LineTo 100, 50
             .LineTo 300, 300
             .LineTo 150, 400
             .ClosePath  ' Close the polygon
    
             ' Get the W/H of the polygon path
             .GetPathExtents x1, y1, x2, y2
             w = x2 - x1
             h = y2 - y1
    
             Debug.Print "UNSTROKED PATH W/H: " & w, h
    
             ' Stroke the polygon path
             .SetSourceColor vbRed
             .SetLineWidth 3
             .Stroke True   ' Leave the path open to measure it with the stroke applied
    
             ' Get the W/H of the path including stroke width
             .GetStrokeExtents x1, y1, x2, y2
             w = x2 - x1
             h = y2 - y1
    
             .ClearPath  ' Close the path
    
             Debug.Print "STROKED PATH W/H: " & w, h  ' Should be a bit larger than the unstroked path width
    
    
             ' IS THERE ANY WAY TO A CREATE NEW UNSTROKED PATH FROM A STROKED PATH? OR ADD A SECOND STROKE AROUND THE FIRST STROKE?
          End With
    
          .DrawToDC Me.hDC
       End With
    End Sub

  2. #2
    Frenzied Member
    Join Date
    Aug 2020
    Posts
    1,670

    Re: RC6 Cairo Path "Double" Stroke

    In Olaf's AquaButton example, multiple strokes are achieved by calling DefineButtonPath and CC.Clip/CC.ResetClip multiple times.

    https://www.vbforums.com/showthread....=1#post5663051

  3. #3
    Frenzied Member
    Join Date
    Aug 2020
    Posts
    1,670

    Re: RC6 Cairo Path "Double" Stroke

    A stupid and imprecise approach:

    Version1
    Code:
    Option Explicit
    
    Private Sub Form_Click()
       Dim x1 As Double, y1 As Double, x2 As Double, y2 As Double, x3 As Double, y3 As Double, x4 As Double, y4 As Double
       Dim w As Double, h As Double, Srf As cCairoSurface, CC As cCairoContext, LineWidth As Double
       
        LineWidth = 3
        
       Set Srf = Cairo.CreateSurface(Me.ScaleWidth, Me.ScaleHeight)
       Set CC = Srf.CreateContext
        
       With CC
             ' Fill entire background of surface
             .SetSourceColor vbWhite
             .Paint
            
             ' Draw a simple but arbitrary polygon path
             x1 = 50: y1 = 50
             x2 = 100: y2 = 50
             x3 = 300: y3 = 300
             x4 = 150: y4 = 400
             
             DefinePolygonPath CC, x1, y1, x2, y2, x3, y3, x4, y4 ', vbYellow
             CC.Fill True, Cairo.CreateSolidPatternLng(vbYellow)
                    
            x1 = x1 - 1:        y1 = y1 - 1
            x2 = x2 + 1:        y2 = y2 - 1
            x3 = x3 + 1:        y3 = y3 + 1
            x4 = x4 - 1:        y4 = y4 + 1
            DefinePolygonPath CC, x1, y1, x2, y2, x3, y3, x4, y4, vbRed
            
            x1 = x1 - 1:        y1 = y1 - 1
            x2 = x2 + 1:        y2 = y2 - 1
            x3 = x3 + 1:        y3 = y3 + 1
            x4 = x4 - 1:        y4 = y4 + 1
            DefinePolygonPath CC, x1, y1, x2, y2, x3, y3, x4, y4, vbGreen
            
          End With
    
          Srf.DrawToDC Me.hDC
    
    End Sub
    
    Private Sub DefinePolygonPath(CC As cCairoContext, ByVal x1#, ByVal y1#, ByVal x2#, ByVal y2#, ByVal x3#, ByVal y3#, ByVal x4#, ByVal y4#, _
                                                Optional ByVal StrokeColor& = -1, Optional ByVal Alpha# = 1, Optional ByVal Shade# = 1)
                                                
        CC.MoveTo x1, y1
        CC.LineTo x2, y2
        CC.LineTo x3, y3
        CC.LineTo x4, y4
    
        CC.ClosePath
        
        If StrokeColor <> -1 Then CC.Stroke , Cairo.CreateSolidPatternLng(StrokeColor, Alpha, Shade)
      
    End Sub
    
    Private Sub Form_Resize()
        Me.ScaleMode = vbPixels
    End Sub

  4. #4
    Frenzied Member
    Join Date
    Aug 2020
    Posts
    1,670

    Re: RC6 Cairo Path "Double" Stroke

    Another stupid and imprecise approach:

    Version2
    Code:
    Option Explicit
    
    Private Sub Form_Click()
       Dim x1 As Double, y1 As Double, x2 As Double, y2 As Double, x3 As Double, y3 As Double, x4 As Double, y4 As Double
       Dim w As Double, h As Double, Srf As cCairoSurface, CC As cCairoContext, LineWidth As Double
       Dim LeftOffs#, TopOffs#, RightOffs#, BottomOffs#, x5#, y5#, x6#, y6#
       
        LineWidth = 3
        
       Set Srf = Cairo.CreateSurface(Me.ScaleWidth, Me.ScaleHeight)
       Set CC = Srf.CreateContext
        
       With CC
             ' Fill entire background of surface
             .SetSourceColor vbWhite
             .Paint
            
             ' Draw a simple but arbitrary polygon path
             x1 = 50: y1 = 50
             x2 = 100: y2 = 50
             x3 = 300: y3 = 300
             x4 = 150: y4 = 400
             
             DefinePolygonPath CC, x1, y1, x2, y2, x3, y3, x4, y4 ', vbYellow
             CC.Fill True, Cairo.CreateSolidPatternLng(vbYellow)
            
            .GetStrokeExtents x5, y5, x6, y6
            LeftOffs = 50 - x5
            TopOffs = 50 - y5
            RightOffs = x6 - 300
            BottomOffs = y6 - 400
            
            x1 = x1 - LeftOffs:        y1 = y1 - TopOffs
            x2 = x2 + RightOffs:        y2 = y2 - TopOffs
            x3 = x3 + RightOffs:        y3 = x3         'y3 + BottomOffs
            x4 = x4 - LeftOffs:        y4 = y4 + BottomOffs
            DefinePolygonPath CC, x1, y1, x2, y2, x3, y3, x4, y4, vbRed
            
            x1 = x1 - LeftOffs:        y1 = y1 - TopOffs
            x2 = x2 + RightOffs:        y2 = y2 - TopOffs
            x3 = x3 + RightOffs:        y3 = x3         'y3 + BottomOffs
            x4 = x4 - LeftOffs:        y4 = y4 + BottomOffs
            DefinePolygonPath CC, x1, y1, x2, y2, x3, y3, x4, y4, vbGreen
                    
          End With
    
          Srf.DrawToDC Me.hDC
    
    End Sub
    
    Private Sub DefinePolygonPath(CC As cCairoContext, ByVal x1#, ByVal y1#, ByVal x2#, ByVal y2#, ByVal x3#, ByVal y3#, ByVal x4#, ByVal y4#, _
                                                Optional ByVal StrokeColor& = -1, Optional ByVal Alpha# = 1, Optional ByVal Shade# = 1)
                                                
        CC.MoveTo x1, y1
        CC.LineTo x2, y2
        CC.LineTo x3, y3
        CC.LineTo x4, y4
    
        CC.ClosePath
        
        If StrokeColor <> -1 Then CC.Stroke , Cairo.CreateSolidPatternLng(StrokeColor, Alpha, Shade)
      
    End Sub
    
    Private Sub Form_Resize()
        Me.ScaleMode = vbPixels
    End Sub

  5. #5
    Frenzied Member
    Join Date
    Aug 2020
    Posts
    1,670

    Re: RC6 Cairo Path "Double" Stroke

    The third stupid and accurate way to do this is to calculate Left-Offsets, Top-Offsets, Right-Offsets, Bottom-Offsets.

    When there is no documentation and no help can be obtained through the Object-Browser, we are usually left with a stupid approach.

  6. #6

    Thread Starter
    PowerPoster
    Join Date
    Aug 2010
    Location
    Canada
    Posts
    2,715

    Re: RC6 Cairo Path "Double" Stroke

    Thanks SD - I've also come up with some imprecise methods, but they all look kind of ugly. Thinking about it more, it might be that we need to find the "center" of the path, then loop through each point a change the X/Y values depending on where they are relative to the center:

    • If X is left of the center, subtract the stroke width.
    • If X is at the center, leave it alone.
    • If X is right of center, add the stroke width.
    • If Y is above the center, subtract the stroke width.
    • If Y is at the center, leave it alone.
    • If Y is below the center, add the stroke width.


    In my head that seems like it should work, but the proof will be in the rendering. The tricky bit will be finding the center of any arbitrary polygon - maybe it's enough to find the center of the bounding box? I'll give it a try today and post the results.

  7. #7
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Location
    Sofia, Bulgaria
    Posts
    5,833

    Re: RC6 Cairo Path "Double" Stroke

    If I had to do it in GDI+ I would first fill path with yellow, then clip surface/graphics to path and draw green outline with 8 px wide (centered) pen, then reset clip and draw red outline 2 px wide.

    This way half of the 8 px green outline (which gets outsite clip path) is trimmed, so drawing ends up with 4 px green outline only on the inside of path.

    cheers,
    </wqw>

  8. #8

    Thread Starter
    PowerPoster
    Join Date
    Aug 2010
    Location
    Canada
    Posts
    2,715

    Re: RC6 Cairo Path "Double" Stroke

    Tried a bunch of variations of finding the center and centroid (by converting Emile Cormier's C++ code in this StackOverflow answer) of the polygon to determine whether and where a point should be bumped. It worked a bit better, but there were still problems with the results:

    Name:  2025-03-06_15-24-00.png
Views: 298
Size:  15.5 KB

    Somewhat inspired by wqweto's idea (thank you!!), I tried stroking the path, then applying a Gaussian blur and flattened the blur to a single colour. This worked well enough for my purposes as long as the main shape was filled 100% opaquely:

    Name:  2025-03-06_15-34-11.png
Views: 293
Size:  6.5 KB

    But I also need to allow for inner transparency/translucency and unfortunately this approach won't work unless I get inner clipping figured out:

    Name:  2025-03-06_15-36-36.png
Views: 293
Size:  9.0 KB

    Experimentation continues...

  9. #9

    Thread Starter
    PowerPoster
    Join Date
    Aug 2010
    Location
    Canada
    Posts
    2,715

    Re: RC6 Cairo Path "Double" Stroke

    Bloody hell - vbforums.com died when I posted my message!!

  10. #10

    Thread Starter
    PowerPoster
    Join Date
    Aug 2010
    Location
    Canada
    Posts
    2,715

    Re: RC6 Cairo Path "Double" Stroke

    Okay, I have something that renders reasonably well, though I suspect there must be a better way as it is quite heavy. Here's the rendered result:

    Name:  2025-03-06_17-23-38.jpg
Views: 271
Size:  21.4 KB

    And here's a demo you can play with:

    FakeDoubleStroke.zip

    To use the demo, click on the form to start a polygon, then move the mouse and click wherever you'd like to anchor a new point. When you are done, press Enter and the polygon will be rendered with a fake double stroke.

  11. #11
    Frenzied Member
    Join Date
    Aug 2020
    Posts
    1,670

    Re: RC6 Cairo Path "Double" Stroke

    Excellent !

  12. #12
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,437

    Re: RC6 Cairo Path "Double" Stroke

    As long as only "stroking" is concerned - one can achieve something like an
    inner-stroke + outer-stroke effect (each with half the choosen line-width) this way:
    (using wqwetos clipping-idea)

    Code:
    Private Sub Form_Load()
       ScaleMode = vbPixels
       With Cairo.CreateSurface(ScaleWidth, ScaleHeight).CreateContext
             ' Fill entire background of surface
             .Paint 1, Cairo.CreateCheckerPattern
    
             ' Define a simple but arbitrary polygon path
             .MoveTo 50, 50
             .LineTo 100, 50
             .LineTo 300, 300
             .LineTo 150, 400
             .ClosePath  ' close the polygon-path (in the sense, of connecting the last point to the first one)
             
             .SetLineWidth 10 'set a somewhat thicker linewidth, to make the "half-width-lines" easier to recognize
                      
             .Stroke True, Cairo.CreateSolidPatternLng(vbGreen) 'normal (full LineWidth-)Stroke
             
             .Clip True 'now set a clip on the poly-path (so that only inside this area, drawings can manifest)
             .Stroke True, Cairo.CreateSolidPatternLng(vbRed) 'additional (half-)stroke - only on the inside
     
             .ResetClip
             .ClearPath
     
          Set Picture = .Surface.Picture
       End With
    End Sub
    HTH

    Olaf
    Last edited by Schmidt; Mar 7th, 2025 at 08:12 AM.

  13. #13

    Thread Starter
    PowerPoster
    Join Date
    Aug 2010
    Location
    Canada
    Posts
    2,715

    Re: RC6 Cairo Path "Double" Stroke

    Quote Originally Posted by Schmidt View Post
    As long as only "stroking" is concerned - one can achieve something like an
    inner-stroke + outer-stroke effect (each with half the choosen line-width) this way:
    (using wqwetos clipping-idea)
    Thanks Olaf, that's definitely much cleaner than my attempt, with the downside that the stroke is an inner stroke. Ideally, I'd like to do an outer stroke because my user's will be using drawing tools to call out certain areas of photographs, and they might be drawing fairly tight polygons around areas of interest. Something like this:

    Name:  2025-03-07_9-02-35.jpg
Views: 188
Size:  34.6 KB

    The goal is to have a second stroke outside for when a polygon has been selected (to move it, delete it, etc...) and I'd prefer not to obscure any of the inner portion/area of interest.

    I'm probably being persnickety, but I've tried just stroking with a highlight colour over top the existing stroke when an object is selected. This wasn't too bad, but then I need to do some tests to make sure that the selection stroke is definitely a different colour/style than the unselected polygon stroke to ensure maxium visibility, and this has the downside of the selection strokes potentially looking different for different kinds of selected objects in multi-select scenarios. Another option would be to just stroke the bounding box, but it's not as "cool" looking.

    I was hoping that since Cairo knows the size and shape of the stroked path, that there might be someway to get it to spit out an expanded path ready to re-stroke, but it appears not. I've been doing some more experiments on algos for expanding a path and I'm getting closer by finding the left-most point, and looping around points to determine if there are changes in line direction and adjusting the X/Y coords by an offset, but it's not quite good enough as I'm still miscalculating which way/how far to offset in some cases.

    Another option I just found would be to use a third-party library...the Clipper2 library looks interesting...

  14. #14
    Fanatic Member
    Join Date
    Sep 2010
    Location
    Italy
    Posts
    704

    Re: RC6 Cairo Path "Double" Stroke

    I have these two ideas:
    The simple one is maybe similar to Olaf's. But I doubt it's enough.
    The advanced one applies the offset (positive or negative / external or internal) to the polygon by recalculating the coordinates of the points.
    It basically moves the segments according to their normals and then calculates the points of the new polygon by finding the intersections between them.
    Code:
    Option Explicit
    
    Private Sub Form_Click()
        Dim Srf As cCairoSurface, CC As cCairoContext
    
        Set Srf = Cairo.CreateSurface(Me.ScaleWidth, Me.ScaleHeight)
        Set CC = Srf.CreateContext
    
        Dim PolyCoord() As Single
        Dim PolyCoordOUT() As Single
    
        Dim N         As Long
        N = 4 * 2 - 1
        ReDim PolyCoord(N)
    
        PolyCoord(0) = 50: PolyCoord(1) = 50
        PolyCoord(2) = 100: PolyCoord(3) = 50
        PolyCoord(4) = 300: PolyCoord(5) = 300
        PolyCoord(6) = 150: PolyCoord(7) = 400
    
    
        'SIMPLER MODE
        CC.SetSourceColor vbWhite: CC.Paint
    
        CC.SetSourceColor vbRed: CC.SetLineWidth 12
        CC.PolygonSingle PolyCoord(), True
        CC.Stroke
    
        CC.SetSourceColor vbYellow
        CC.PolygonSingle PolyCoord(), True
        CC.Fill
    
        CC.SetSourceColor vbGreen: CC.SetLineWidth 6
        CC.PolygonSingle PolyCoord(), True
        CC.Stroke
    
        '--------------------------------------------------
        'Advanced mode (using line-line intersection)
        Dim I         As Long
        For I = 0 To N Step 2               ' offset right X coords
            PolyCoord(I) = PolyCoord(I) + 300
        Next
    
        CC.SetSourceColor vbYellow
        CC.PolygonSingle PolyCoord(), True
        CC.Fill
    
        CC.SetSourceColor vbGreen: CC.SetLineWidth 4
        CC.PolygonSingle PolyCoord(), True
        CC.Stroke
    
        OFFSETPOLYGON PolyCoord, PolyCoordOUT, 4
    
        CC.SetSourceColor vbRed: CC.SetLineWidth 4
        CC.PolygonSingle PolyCoordOUT(), True
        CC.Stroke
    
        Srf.DrawToDC Me.hDC
    
    End Sub
    
    
    Private Sub OFFSETPOLYGON(PolyIn() As Single, PolyOut() As Single, Offset As Single)
        Dim U         As Long
        Dim X1 As Long, Y1 As Long
        Dim X2 As Long, Y2 As Long
        Dim X3 As Long, Y3 As Long
        Dim X4 As Long, Y4 As Long
    
        Dim U1        As Long
        Dim PolySideNormal() As Single
        U = UBound(PolyIn)
        ReDim PolySideNormal(U)
        ReDim PolyOut(U)
        Dim Dx!, Dy!
    
        'Compute Segments Normals
        U1 = U + 1
        For X1 = 0 To U Step 2
            Y1 = X1 + 1
            X2 = (X1 + 2) Mod (U1)
            Y2 = (Y1 + 2) Mod (U1)
            Dx = PolyIn(X2) - PolyIn(X1)
            Dy = PolyIn(Y2) - PolyIn(Y1)
            Normalize Dx, Dy
            PolySideNormal(X1) = Dy
            PolySideNormal(Y1) = -Dx
        Next
    
        ' OFFSET SEGMENTS and FIND INTERSECTION
        Dim xx1!, yy1, xx2!, yy2!, xx3!, yy3!, xx4!, yy4!
        Dim RX!, RY!
    
        For X1 = 0 To U Step 2
            Y1 = X1 + 1
            X2 = (X1 + 2) Mod (U1)
            Y2 = (Y1 + 2) Mod (U1)
    
            X3 = X1 - 2: If X3 < 0 Then X3 = U1 + X3
            Y3 = Y1 - 2: If Y3 < 0 Then Y3 = U1 + Y3
    
            xx1 = PolyIn(X3) + PolySideNormal(X3) * Offset
            yy1 = PolyIn(Y3) + PolySideNormal(Y3) * Offset
            xx2 = PolyIn(X1) + PolySideNormal(X3) * Offset
            yy2 = PolyIn(Y1) + PolySideNormal(Y3) * Offset
    
            xx3 = PolyIn(X1) + PolySideNormal(X1) * Offset
            yy3 = PolyIn(Y1) + PolySideNormal(Y1) * Offset
            xx4 = PolyIn(X2) + PolySideNormal(X1) * Offset
            yy4 = PolyIn(Y2) + PolySideNormal(Y1) * Offset
    
            LINELINE xx1, yy1, xx2, yy2, xx3, yy3, xx4, yy4, RX, RY
    
            PolyOut(X1) = RX
            PolyOut(Y1) = RY
    
        Next
    
    End Sub
    
    Private Sub Form_Resize()
        Me.ScaleMode = vbPixels
    End Sub
    
    
    Private Sub Normalize(ByRef Dx!, ByRef Dy!)
        Dim D!
        D = 1! / Sqr(Dx * Dx + Dy * Dy)
        Dx = Dx * D
        Dy = Dy * D
    End Sub
    
    
    Private Sub LINELINE(ByVal Ax!, ByVal Ay!, ByVal Bx!, ByVal By!, _
                         ByVal Cx!, ByVal Cy!, ByVal Dx!, ByVal Dy!, _
                         ByRef RX!, ByRef RY!)
    
        Dim Nu!, De!, S!
        Dim BAx!, BAy!
        Dim DCx!, DCy!
    
        BAx = Bx - Ax
        BAy = By - Ay
        DCx = Dx - Cx
        DCy = Dy - Cy
    
        Nu! = ((BAx * (Ay - Cy)) + ((BAy) * Cx) - ((BAy) * Ax))
        De! = ((BAx) * (DCy)) - ((BAy) * (DCx))
    
        S = Nu / De
    
        RX = Cx + (Dx - Cx) * S
        RY = Cy + (Dy - Cy) * S
    
    End Sub

  15. #15
    Fanatic Member
    Join Date
    Nov 2018
    Posts
    772

    Re: RC6 Cairo Path "Double" Stroke

    GDI+ has a function that converts a path to it's outline points only (GdipWindingModeOutline)

    https://learn.microsoft.com/en-us/wi...cspath-outline
    The above has a code example that draws an outline with a 1px wide pen around a path made with a 10px wide pen.
    One line function call to construct the outline path.

    Perhaps RC6 Cairo has a similar function??
    Last edited by mms_; Mar 7th, 2025 at 01:25 PM.

  16. #16

    Thread Starter
    PowerPoster
    Join Date
    Aug 2010
    Location
    Canada
    Posts
    2,715

    Re: RC6 Cairo Path "Double" Stroke

    Quote Originally Posted by reexre View Post
    I have these two ideas:
    The simple one is maybe similar to Olaf's. But I doubt it's enough.
    The advanced one applies the offset (positive or negative / external or internal) to the polygon by recalculating the coordinates of the points.
    It basically moves the segments according to their normals and then calculates the points of the new polygon by finding the intersections between them.
    The advanced method is *perfect*! I've been trying to do something similar with the idea of pushing the segments out and extending them, but clearly my math wasn't up to snuff, so thank you!

    Here's an example of the output:

    Name:  2025-03-07_14-17-04.jpg
Views: 141
Size:  17.4 KB

    One question - is there a reason you chose to work with Singles instead of Doubles? Just curious because Cairo does a lot of its work at double precision.

    Also - in case anyone passing by uses reexre's code in the future: I had to adjust my point dropping/locking code to avoid double entries in case of user double-click, otherwise there would be a division by zero error in the Normalize sub. If this happens to you, then your points are too close together.

  17. #17
    Fanatic Member
    Join Date
    Sep 2010
    Location
    Italy
    Posts
    704

    Re: RC6 Cairo Path "Double" Stroke

    Thank you jpbro
    Quote Originally Posted by jpbro View Post
    One question - is there a reason you chose to work with Singles instead of Doubles? Just curious because Cairo does a lot of its work at double precision.
    ah, no, there is no reason, I just temporarily forgot about CC.Polygon (I don't know why but I remembered there was only CC.PolygonSingle)
    Replace everywhere Single with Double and ! with #

    PS
    about line line intersection I took the formulas from this video https://www.youtube.com/watch?v=CLX3AwSc3Zc

  18. #18

    Thread Starter
    PowerPoster
    Join Date
    Aug 2010
    Location
    Canada
    Posts
    2,715

    Re: RC6 Cairo Path "Double" Stroke

    Quote Originally Posted by reexre View Post
    ah, no, there is no reason, I just temporarily forgot about CC.Polygon (I don't know why but I remembered there was only CC.PolygonSingle)
    Replace everywhere Single with Double and ! with #
    Got it! Just making sure there wasn't a good reason for Single that I didn't know about

    Quote Originally Posted by reexre View Post
    about line line intersection I took the formulas from this video https://www.youtube.com/watch?v=CLX3AwSc3Zc
    Thanks for the video, I'll check it out.

    To show how well your code works, you can stack strokes for quite a while and it looks great:

    Name:  2025-03-07_15-17-01.jpg
Views: 131
Size:  31.9 KB

    Great job, thank you!

  19. #19
    Fanatic Member
    Join Date
    Sep 2010
    Location
    Italy
    Posts
    704

    Re: RC6 Cairo Path "Double" Stroke

    maybe the code could be improved a bit, for example avoiding redundant operations, but it was written in a hurry
    EG
    Code:
    PolySideNormal(X1) = Dy
    PolySideNormal(Y1) = -Dx
    could be
    Code:
    PolySideNormal(X1) = Dy * Offset
    PolySideNormal(Y1) = -Dx *  Offset
    and all ...
    Code:
    xx1 = PolyIn(X3) + PolySideNormal(X3) * Offset
    to
    Code:
    xx1 = PolyIn(X3) + PolySideNormal(X3)
    .... And something else similar

  20. #20

    Thread Starter
    PowerPoster
    Join Date
    Aug 2010
    Location
    Canada
    Posts
    2,715

    Re: RC6 Cairo Path "Double" Stroke

    Quote Originally Posted by reexre View Post
    maybe the code could be improved a bit, for example avoiding redundant operations, but it was written in a hurry
    EG

    Thanks for the tweaks, but it's plenty good enough for my use case as it is. Right it handles ~200 points in about 0.1ms I wouldn't expect users to be getting close to that many points very often.

    I'm just tweaking it a bit now to get it to take a single RC6.cArrayList of cPoint objects to perform an inplace value swap/expansion, and that way I can skip a step of converting my points to an array of Doubles. I'm using the ArrayList because it makes it easier to insert/remove points at arbitrary positions should the user choose to do so.
    Last edited by jpbro; Mar 7th, 2025 at 07:15 PM.

  21. #21

    Thread Starter
    PowerPoster
    Join Date
    Aug 2010
    Location
    Canada
    Posts
    2,715

    Re: RC6 Cairo Path "Double" Stroke

    I spent some time trying to understand reexre's code and modified it a bit to work with a cArrayList of CPoint classes instead of an array of Doubles. I also changed it so that it would work properly with polygons that were drawn counter-clockwise (the original method would perform an inner stroke in this case), and implemented reexre's suggested improvement.

    Finally, I changed a bunch of variable names along the way while I was improving my understanding of the algorithms involved, and asked ChatGPT to add some comments that were reasonably helpful.

    The final code is fast and does exactly what I needed it to do. Thanks to everyone for your input, and especially reexre for the code contribution, much appreciated!

    SOURCE: MultiStrokePolygonPath.zip


    Check out the timings on base polygon of 180 points, and a 6x expansion/stroke:

    Name:  2025-03-08_15-08-56.jpg
Views: 73
Size:  60.7 KB

    Not too shabby!

  22. #22

    Thread Starter
    PowerPoster
    Join Date
    Aug 2010
    Location
    Canada
    Posts
    2,715

    Re: RC6 Cairo Path "Double" Stroke

    Just completed a demo project that makes use of double-stroking polygons and and whole bunch of other Cairo drawing stuff to allow users to mark-up/annotate images here:

    https://www.vbforums.com/showthread....e-Markup-Tools


    Thanks again to everyone for their help, and especially reexre for the near-perfect polygon expansion code. Much appreciated!

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