Results 1 to 25 of 25

Thread: [RESOLVED] Filling a Polygon on a Picturebox

  1. #1

    Thread Starter
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    9,853

    Resolved [RESOLVED] Filling a Polygon on a Picturebox

    Okay, I'm drawing a very complex polygon (enclosed) on a PictureBox, and I want to fill it when I'm done.

    What's the best way to do this? I see two options: 1) I could look into the ExtFloodFill API in the GDI32, or 2) I could look into the Polygon API in the GDI32.

    This polygon is the first thing I'm drawing on an otherwise blank PictureBox, so nothing else will be interfering. And I'm just using straightforward pic.Line... commands to draw the polygon. Any thoughts on whether the ExtFloodFill or Polygon API is best, or maybe some other approach?

    Thanks,
    Elroy

    EDIT: I'll just be filling it with a solid color, preferably the same color I used to draw the polygon.
    Last edited by Elroy; Aug 11th, 2018 at 09:35 AM.
    Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.

  2. #2
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: Filling a Polygon on a Picturebox

    If doing this via VB line methods, recommend flood fill API as it's the easiest IMO.

    If using APIs to create a polygon, you could create a region via CreatePolygonRgn (or possibly a path) from the poly points and call FillRgn or FillPath APIs
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  3. #3

    Thread Starter
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    9,853

    Re: Filling a Polygon on a Picturebox

    Quote Originally Posted by LaVolpe View Post
    If doing this via VB line methods, recommend flood fill API as it's the easiest IMO.
    I'm definitely using the pic.Line method, as that's all done. Just to be clear, when you say "flood fill", you're talking about ExtFloodFill, correct?

    Code:
    
    Private Declare Function ExtFloodFill Lib "gdi32" (ByVal hdc As Long, ByVal x As Long, ByVal y As Long, ByVal crColor As Long, ByVal wFillType As Long) As Long
    

    I found this old thread that talks about it. That's probably the example I'll follow unless you have something more recent.

    Thank You,
    Elroy
    Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.

  4. #4
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: Filling a Polygon on a Picturebox

    Quote Originally Posted by Elroy View Post
    I'm definitely using the pic.Line method, as that's all done. Just to be clear, when you say "flood fill", you're talking about ExtFloodFill, correct?
    Yes. I think I've only used that API one time in my entire life, so I won't comment on examples or offer sample code.
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  5. #5

    Thread Starter
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    9,853

    Re: Filling a Polygon on a Picturebox

    Well that was a bit more work than I thought it was going to be. Just to give people an idea of what I was after, I was trying to draw those "gray bands" on something like the following plot:

    Name:  Image1.jpg
Views: 1499
Size:  25.2 KB


    I ran into several problems:
    1. I'm not using vbPixel as ScaleMode.
    2. I'm using a negative ScaleHeight.
    3. Only pieces of the gray band may be on the screen.
    4. The ExtFloodFill doesn't seem to do anything when its X,Y are out of bounds.

    I started out writing a generic procedure with ExtFloodFill in it. However, to get this done, I abandoned that and wrote a procedure rather specific to my needs. It's posted below, but I'm not sure how much help it's going to be to anyone else. The API declaration is provided above. Here's the procedure I wound up using:

    Code:
    
    Private Sub PicAreaFill(pic As PictureBox, ByVal X As Single, ByVal Y As Single)
        ' Fill a region using the current color or brush (via .FillColor).
        ' X & Y are given in the ScaleMode coordinates.
        ' It is assumed that pic.ScaleHeight is negative (to act more like a coordinate system).
        ' It fills until a different color border is hit.
        '
        Dim y2 As Long
        '
        y2 = CLng(pic.ScaleY(-pic.ScaleTop + Y, pic.ScaleMode, vbPixels))                               ' Re-arrange our Y coordinate.
        If y2 < 0& Or y2 > CLng(pic.ScaleY(pic.ScaleHeight, pic.ScaleMode, vbPixels)) Then Exit Sub     ' Make sure we're on the pic, or don't bother.
        If pic.Point(X, Y) <> vbWhite Then Exit Sub                                                     ' If area is already filled, don't bother.
        '
        ExtFloodFill pic.hdc, CLng(pic.ScaleX(X, pic.ScaleMode, vbPixels)), y2, pic.Point(X, Y), 1      ' 1=FLOODFILLSURFACE.
    End Sub
    

    Now, I'll also provide the code where I call it, but not in its complete form. This is just a specific block of code in a much larger procedure. I've left it black, with the loop that calls PicAreaFill in red.

    Code:
                    If bFound Then
                        pic.FillColor = iLineColorVal
                        pic.FillStyle = vbFSSolid
                        pic.DrawWidth = 1
                        '
                        pic.Line (0, GcdMeans(1) - GcdSDs(1))-(0, GcdMeans(1) + GcdSDs(1)), iLineColorVal                                                       ' The starting vertical line to polygon.
                        For iRow = 1 To GcdFrameCount                           ' Seed the cubic-spline.
                            xData(iRow) = iRow - 1                              ' 0 to 50.
                            yData(iRow) = CDbl(GcdMeans(iRow) + GcdSDs(iRow))
                        Next iRow
                        CSpline_SetData xData, yData
                        '
                        dValuePrev = CSpline_Value(0)
                        For dRow = dStep To GcdFrameCount Step dStep            ' Use cubic-spline to plot.
                            dValueNext = CSpline_Value(dRow)
                            pic.Line (dRow - dStep, dValuePrev)-(dRow, dValueNext), iLineColorVal
                            dValuePrev = dValueNext
                        Next dRow
                        CSpline_ClearData
                        '
                        pic.Line (50, GcdMeans(GcdFrameCount) + GcdSDs(GcdFrameCount))-(50, GcdMeans(GcdFrameCount) - GcdSDs(GcdFrameCount)), iLineColorVal     ' The ending vertical line to polygon.
                        For iRow = 1 To GcdFrameCount                           ' Seed the cubic-spline.
                            xData(iRow) = iRow - 1                              ' 0 to 50.
                            yData(iRow) = CDbl(GcdMeans(iRow) - GcdSDs(iRow))
                        Next iRow
                        CSpline_SetData xData, yData
                        '
                        dValuePrev = CSpline_Value(GcdFrameCount)
                        For dRow = GcdFrameCount - dStep To 0 Step -dStep      ' Use cubic-spline to plot.
                            dValueNext = CSpline_Value(dRow)
                            pic.Line (dRow, dValuePrev)-(dRow - dStep, dValueNext), iLineColorVal
                            dValuePrev = dValueNext
                        Next dRow
                        CSpline_ClearData
                        '
                        ' And now we fill the area.
                        For iRow = 4 To GcdFrameCount Step 5
                            PicAreaFill pic, iRow - 1, GcdMeans(iRow)
                            PicAreaFill pic, iRow - 1, GcdMeans(iRow) + GcdSDs(1) * 0.75!
                            PicAreaFill pic, iRow - 1, GcdMeans(iRow) - GcdSDs(1) * 0.75!
                        Next
                    End If

    There are still situations that can make it fail, such as when the gray band just barely dips onto the picturebox, but the polygon is still there, suggesting to the user that they should re-scale things. Those little spinners on the left (in the image) are for rescaling.

    I'm calling this one resolved.

    @LaVolpe: Thanks.

    Elroy
    Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.

  6. #6
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,219

    Re: [RESOLVED] Filling a Polygon on a Picturebox

    As I see it, you basically want to fill the interior between two "Poly-Curves":
    - one "Upper-Border-Curve"
    - and one "Lower-Border-Curve"

    And that'd be quite easy to accomplish, when you'd use either:
    - the GDI Polygon-API (which supports filling a PolyGon)
    - or the GDI PolyLine-API in GDI-Path-Mode (where you can choose later, whether to Stroke or Fill the rendered Poly-Path)

    Those who want to see a demonstration for a Path-based approach, could play around with the following
    (based on the RC5-Cairo-Wrapper, which supports PolyPath-Rendering in "non-splined" as well as "splined" modes).

    Put a reference to vbRichClient5 into your Project and the following into an empty Form:
    Code:
    Option Explicit
    
    Private Const MinX = 0, MaxX = 7, MinY = -1, MaxY = 1 'roughly covers the range for a single Sinus-Period
    
    Private Poly1 As cArrayList, Poly2 As cArrayList
     
    Private Sub Form_Load() 'ensure filling the RawData-PolyArrays with Double-Points (x at even Arr-Indexes, y at odd Indexes)
      Set Poly1 = New_c.ArrayList(vbDouble)
      Set Poly2 = New_c.ArrayList(vbDouble)
      
      Dim x As Double
      For x = MinX To MaxX 'this will add 8-Points (at x-Values 0,1,2,3,4,5,6,7) to each PolyGon-Array
        Poly1.Add x: Poly1.Add 0.7 * Sin(x)              'add an x/y-Pair to Poly1
        Poly2.Add x: Poly2.Add 0.7 * Sin(x - 0.1) - 0.2  'add an x/y-Pair to Poly2 (with slightly "lowered" Sinus-Output)
      Next
    End Sub
    
    Private Sub Form_Resize() 'this triggers the Redrawing-Routine
      ScaleMode = vbPixels
      Redraw Cairo.CreateSurface(ScaleWidth, ScaleHeight).CreateContext, splNone '<- changeable to e.g. splNormal
    End Sub
    
    Private Sub Redraw(CC As cCairoContext, SplineMode As SplineInterpolationEnm)
      CC.Paint 1, Cairo.CreateSolidPatternLng(vbWhite) 'ensure white BackGround
      CC.SetLineWidth 2 'ensure a default-LineWidth
      
      DrawPolyPath CC, Poly1, SplineMode
                   CC.Stroke , Cairo.CreateSolidPatternLng(vbRed, 1) 'Stroke with solid red
      
      DrawPolyPath CC, Poly2, SplineMode
                   CC.Stroke , Cairo.CreateSolidPatternLng(vbBlue, 1) 'Stroke with solid blue
      
      Set Me.Picture = CC.Surface.Picture 'Flip the Cairo-Surface-Content to the Forms Picture-Prop
    End Sub
    
    Private Sub DrawPolyPath(CC As cCairoContext, Poly As cArrayList, SplineMode As SplineInterpolationEnm)
      CC.Save
        EnsureMathCoordSystemOn CC
        CC.PolygonPtr Poly.DataPtr, Poly.Count \ 2, False, SplineMode, True, True 'render the Poly-Path in one call (from the Array)
      CC.Restore
    End Sub
    
    Private Sub EnsureMathCoordSystemOn(CC As cCairoContext)
      CC.TranslateDrawings 0, CC.Surface.Height / 2
      CC.ScaleDrawings CC.Surface.Width / (MaxX - MinX), -CC.Surface.Height / (MaxY - MinY)
    End Sub
    The above code will produce two "Sinus-like" Polygon-curves for roughly one Sinus-Period, looking like that:


    Well, the above does not really look like a Sinus yet (since the two Polygon-Arrays only contain 8 points each -> with x-Values at 0,1,2,3,4,5,6,7),
    but with enabled Spline-Interpolation (adaptable in the Form_Resize Handler), the two Curves will come out a bit more "sinus-like":


    Ok, now to the problem, how to fill the interior between the two PolyArray-based curves:
    Quite easy really, when you think about it "Poly-Point-wise" (each point in the PolyArr representing a "Step" whilst a path is defined/plotted by the renderers)...

    Basically, what we need, is a third Polygon-Array, which:
    - contains a copy of all the Points from PolyArr1 (which is represented in the ScreenShots as the red Curve)
    - and then adds all the Points of PolyArr2 (the blue curve) in reverse order, beginning with the last Point of Poly2 - adding it directly behind the last Point of Poly1...

    An appropriate "Connect"-Function (to be included in the above example-code) would be this one:
    Code:
    Private Function ConnectPolies(Poly1 As cArrayList, Poly2 As cArrayList) As cArrayList
      Set ConnectPolies = Poly1.Clone 'make a copy of the Poly1-Points
      Dim i As Long
      For i = Poly2.Count \ 2 - 1 To 0 Step -1 'add all Points of Poly2 in inverse order
        ConnectPolies.Add Poly2(2 * i + 0)
        ConnectPolies.Add Poly2(2 * i + 1)
      Next
    End Function
    Then - what remains, is an additional render-block for that third "Combined" (or connected) PolyArray (which then focuses on Filling, instead of Stroking that "combined Poly").
    I've marked the required addition to the existing Redraw-Routine below, in magenta...
    Code:
    Private Sub Redraw(CC As cCairoContext, SplineMode As SplineInterpolationEnm)
      CC.Paint 1, Cairo.CreateSolidPatternLng(vbWhite) 'ensure white BackGround
      CC.SetLineWidth 2 'ensure a default-LineWidth
    
      DrawPolyPath CC, ConnectPolies(Poly1, Poly2), SplineMode
                   CC.Fill , Cairo.CreateSolidPatternLng(&H888888, 0.3) 'Fill with gray (30% Alpha-Opacity)
    
      DrawPolyPath CC, Poly1, SplineMode
                   CC.Stroke , Cairo.CreateSolidPatternLng(vbRed, 1) 'Stroke with solid red
    
      DrawPolyPath CC, Poly2, SplineMode
                   CC.Stroke , Cairo.CreateSolidPatternLng(vbBlue, 1) 'Stroke with solid blue
    
      Set Me.Picture = CC.Surface.Picture 'Flip the Cairo-Surface-Content to the Forms Picture-Prop
    End Sub
    The above additions to the initial code should then produce the following output:


    HTH

    Olaf

  7. #7

    Thread Starter
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    9,853

    Re: [RESOLVED] Filling a Polygon on a Picturebox

    It's not exactly about making sinusoidal curves. Most of the stuff I work with is about studying human joint kinematics (and some kinetics too) during a walking gait cycle:

    Name:  GaitCycle.jpg
Views: 1562
Size:  32.8 KB

    With motion capture equipment, and a fair amount of linear algebra, we calculate joint movement in all three planes (sagittal, coronal, and axial) on various joints and segments (pelvis, hip, knee, ankle, foot, etc). By modeling and profiling these kinematics, we can better understand abnormalities and pathologies.

    The gray bands represent the able-bodied-mean (on a particular joint's kinematics, say knee flexion-extension), plus-or-minus one standard deviation. This mean and standard deviation are calculated from a group of able-bodied-children of various ages (4 to 18 years of age).

    Everything (for patients and able-bodied) is normalized to 51 data-points per gait cycle (2% cycle slices). Even with 51 data-points, you can sometimes still see the "bends" in the lines. Therefore, I typically run everything through cubic-spline and plot something like .25% lines. Those always appear smooth. The .25% is the dStep in the above code.

    So, again, it's not at all about sinusoidal-looking curves. It's just about smooth-looking curves. And yeah, I knew I could use some of the other GDI32 functions to get it done. I just like staying with VB6's abilities whenever I can.

    Here are a couple of other examples of what I'm doing. The first is pelvic rotation (axial plane). The second is hip flexion-extension (sagittal plane). The blue and brown lines are actual data of individuals, but it's just test data and we were messing around a bit (not walking normally).

    Name:  PelvicRotation.jpg
Views: 1475
Size:  23.3 KB

    Name:  HipFlexExt.jpg
Views: 1417
Size:  23.7 KB

    And Olaf, you've been trying to "sell" me on RC5 for some time now. You should know by now I'm not going to add any new closed-source code to my project. Sorry, but it just ain't happening. Yeah, I know, the Microsoft stuff is closed source, but we've already had that discussion (more than once).

    You Take Care,
    Elroy
    Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.

  8. #8
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,219

    Re: [RESOLVED] Filling a Polygon on a Picturebox

    Quote Originally Posted by Elroy View Post
    It's not exactly about making sinusoidal curves.
    You are rendering curves from x/y-Pairs which follow a continuous, surjective pattern (or function).
    The Sinus-Function (to determine different y-values for equidistant x-Values) was arbitrary choosen from that class of functions -
    though other mappings between x and y would work as well.

    Quote Originally Posted by Elroy View Post
    Most of the stuff I work with is ...
    ... irrelevant for discussing the problem.

    I've already described, what the code I've posted is trying to solve, at the top of my previous posting
    (filling the interior between two poly-lines - one PolyArr which contains the x/y-pairs of an "upper-border", the second PolyArr containing the x/y-pairs of the "bottom-border" of the "gray-area" which needs to be filled).

    Quote Originally Posted by Elroy View Post
    The gray bands represent the able-bodied-mean... plus-or-minus one standard deviation.
    Well - and my example would work, when one would fill the two PolyArrays appropriately:
    - the "Upper-Array" (in my example Poly1) with y-Values that are = Mean(i) + StdDev(i)
    - the "Lower-Array" (in my example Poly2) with y-Values that are = Mean(i) - StdDev(i)

    That doesn't change the rule, how Poly3 should be filled (with a copy of Poly1-Points - prolonged with an inverse copy of the Points in Poly2).

    Poly3 now contains the Points in a way, that the GDI-Polygon-API (with an invisible Pen and a Grey Brush) could be used directly
    (or - as in case of the cairo-example above - the Cairo-Fill-Method on the rendered Poly-Path of the Poly3-Array).

    Quote Originally Posted by Elroy View Post
    So, again, it's not at all about sinusoidal-looking curves.
    Again, I was not writing about sinusoidal looking curves - I was writing about Polygon-Arrays and an elegant solution for the problem.

    Quote Originally Posted by Elroy View Post
    And Olaf, you've been trying to "sell" me on RC5 for some time now...
    I was not posting to you specifically (we are in a public forum after all)...

    In most of my replies I'm just trying:
    - to isolate the problem behind the question
    - then offering a "best-practice" solution for VB6-users
    - usually via clean code-snippets, implemented in as few lines as possible
    - using libraries that have a future - and are not MS-based

    In that specific case, the usage of a FloodFill-API is suboptimal - not what I'd consider "best practice"
    (it's "last-century" and only works for Pixel-Surfaces ... we can do better than that these days).

    Olaf

  9. #9
    PowerPoster
    Join Date
    Feb 2017
    Posts
    4,997

    Re: [RESOLVED] Filling a Polygon on a Picturebox

    Quote Originally Posted by Elroy View Post
    Okay, I'm drawing a very complex polygon (enclosed) on a PictureBox, and I want to fill it
    I think there are several ways to do that.
    For filled figures I used the API Polygon.

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

    Re: [RESOLVED] Filling a Polygon on a Picturebox

    Quote Originally Posted by Schmidt View Post
    I was not posting to you specifically (we are in a public forum after all)...

    In most of my replies I'm just trying:
    - to isolate the problem behind the question
    - then offering a "best-practice" solution for VB6-users
    - usually via clean code-snippets, implemented in as few lines as possible
    - using libraries that have a future - and are not MS-based

    In that specific case, the usage of a FloodFill-API is suboptimal - not what I'd consider "best practice"
    (it's "last-century" and only works for Pixel-Surfaces ... we can do better than that these days).

    Olaf
    Thank you, Olaf. This is exactly what many people want to see. You have raised the level of the entire vbForums to a very high level. Many people have learned a lot from you that they can't learn in other places. I believe many people will deeply appreciate you from the heart.

  11. #11
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: [RESOLVED] Filling a Polygon on a Picturebox

    Ok, gotta chime in...

    Elroy, I know you are not interested in RC5.
    dreammanor, you are a cheerleader for Olaf and are friendly to the idea that everyone should be using RC5

    If Olaf were sincere in just trying to provide information solely for educational purposes, he could have without using RC5 samples that can only be run by using his RC5. IMO, that was another clear attempt to promote/advertise his tool on someone else's thread. He does this often. He is well aware that Elroy is not interested in RC5 at all. To say that Olaf was being altruistic is probably naive. He could've offered his thoughts and screenshots without promoting RC5, or at the very least offer RC5 sample code if Elroy wanted it.

    I don't buy the idea that most threads in this forum, that can be worked using RC5, is a candidate for RC5 promotion. But that's pretty much how its become. Want to draw something, use RC5. Want to use a recordset, use RC5. Want to [fill in the blank], use RC5 . Why not just have an RC5 section in the forum and be done with it. This place has become a de facto RC5-forum extension, but the funds, tech, and support all being provided by vbForums.com
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

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

    Re: [RESOLVED] Filling a Polygon on a Picturebox

    Quote Originally Posted by dreammanor View Post
    Thank you, Olaf. This is exactly what many people want to see. You have raised the level of the entire vbForums to a very high level. Many people have learned a lot from you that they can't learn in other places. I believe many people will deeply appreciate you from the heart.
    WAT?!



    There are PMs in these forums, btw. . .

    cheers,
    </wqw>

  13. #13
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,219

    Re: [RESOLVED] Filling a Polygon on a Picturebox

    Quote Originally Posted by LaVolpe View Post
    If Olaf were sincere in just trying to provide information solely for educational purposes...
    FWIW, I am (sincere) with the educational part.
    Nobody did mention the (quite trivial and obvious) approach to solving the problem
    by "concatenating" two PolyArrays - so I did... <shrug>

    In *addition* - I've provided test-code, which is using the graphics-lib I'm most familiar with
    (saved me time in writing a working example to demonstrate the approach) -
    feel free to ignore it - and use only the "free-text-description" of the approach, to implement your own version.

    Quote Originally Posted by LaVolpe View Post
    To say that Olaf was being altruistic is probably naive.
    That's bordering on slander Keith...
    would like it very much when you'd point out what it is (other than altruistic reasons),
    which leads me (in my spare-time) to write VB6-examples that demonstrate efficient usage of opensource-libs,
    (cairo and sqlite) - which are pretty much standard in any other language-camp.

    Cairo and SQLite are "plain-C"-libs... so there's:
    - class-based Python-wrappers for cairo and sqlite,
    - class-based C++ wrappers for cairo and sqlite
    - class-based PHP-wrappers for cairo and sqlite
    - wrappers for D, Swift, Ruby etc.

    In forum- or mailinglist-discussions of the above mentioned languages,
    code-examples how to approach a certain problem with one of those wrappers
    are entirely normal and appreciated.

    Why on earth a free provided and maintained (COM)class-wrapper for cairo and sqlite
    should be treated with anything else than at least curtesy (in a VB6-Forum) boggles the mind.

    Be advised, that next to no one in other language-camps:
    - uses the MS-GDI-API for graphics-output
    - nor is ADO/JET in use for smaller or midsized App-DB-scenarios

    So, a bit more openness with regards to libs and tools that are common in other languages,
    might help everybody with potential code-migration-efforts (to said "other languages")
    in case VB6 really bites the dust in a few years.

    I really mean it, when I bring up the term "best practice" (in conjunction with the RC5).

    It usually *is* efficient and sparse VB6-code which it allows -
    and in case one wants to switch to C++ or Python in a few years,
    one *will* be familiar with cairo and sqlite already (double win for RC5-users,
    and no, not a single Cent of "earnings" for myself along the way).

    If you personally think, GDI-based graphics-examples are still "best-practice",
    then you will have to allow the question: For whom?

    Please keep in mind, that many Forum-Users here plan, to be developers for
    another 20-30 years to come.

    Olaf

  14. #14
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: [RESOLVED] Filling a Polygon on a Picturebox

    Saying someone might be naive is slander? Yep, ok.

    There is no doubt in anyone's mind, that frequents this site regularly, that you take any opportunity to promote your RC5 tool. Even when a solution has been accepted/resolved, I've seen threads where you post your "alternate" solution with RC5 code to produce the same results. For what purpose, other than to self-promote? You can search through your 3K posts for examples if you've forgotten any such scenarios.

    And even in this case and nearly all cases where anyone mentions anything RC5-related that you feel is negative, you take the opportunity to further promote your tool, as shown by the lengthy reply above.

    Out of curiosity, why don't you ask the mods to forward a request to vbForums.com for your own section? They might seriously consider it.
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  15. #15
    Fanatic Member
    Join Date
    Feb 2017
    Posts
    858

    Re: [RESOLVED] Filling a Polygon on a Picturebox

    Elroy:
    Elroy:
    Saw this was closed. But maybe the following may be a better solution.

    I just had this issue and solved it recently by drawing a filled rectangle between the two lines.
    I took the current point of each line and the previous point of each line and then filled
    rectangle between them. So in my case as I'm drawing the lines I'm also drawing the colored
    rectangle between them . I found in my case rendering is faster if I draw all Y values at a
    particular X axis point rather than trying to draw each line individually and completely.
    So I would render line pt 1, line pt2, then draw rectangle.

  16. #16
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,219

    Re: [RESOLVED] Filling a Polygon on a Picturebox

    Quote Originally Posted by LaVolpe View Post
    Saying someone might be naive is slander?
    Hmm, your suggestion (in a public Forum) that I'm here for other reasons than trying
    to convey knowledge (which in my book *is* an altruistic motive) borders on slander, yes -
    but I'm repeating myself.

    Quote Originally Posted by LaVolpe View Post
    I've seen threads where you post your "alternate" solution with RC5 code to produce the same results.
    No, the results are in almost all cases better (nicer looking, better performing) -
    and for the most part require less coding-efforts as well.

    Really can't see where the problem is, since comparing several "competing solutions" (for the same problem)
    is what brings life (along with "Aha-effects") into a technical discussion.

    Quote Originally Posted by LaVolpe View Post
    For what purpose, other than to self-promote?
    People with knowledge, who operate more on the answering-side in a public forum
    are automatically "self-promoting" (their knowledge) - and in my opinion (since it helps other people)
    there's nothing to be ashamed of in that regard

    The difference is, that I for my part cannot remember, to ever have pointed out to you,
    that you're "promoting yourself", when you post an efficient solution to a problem.

    Quote Originally Posted by LaVolpe View Post
    And even in this case and nearly all cases where anyone mentions anything RC5-related that you feel is negative,
    you take the opportunity to further promote your tool...
    Other than pointing out (again, since wrong and misleading statements deserve a reply):
    - no, there is no "promotion" (as well as no monetary gain - just a wrapper, which is considered standard-stuff in other languages)
    - no, it was not me, who made an underhanded accusation of "ulterior motives"
    - yes, the solution I suggested in my first post, stands "in competition" to your (FloodFill-) recommendation
    - and yes, that is entirely normal - and one of the reasons people visit technical forums

    BTW, you missed answering my question about "best-practice" - but let me formulate it slightly different this time:

    Do you consider postings, which address proper usage of a modern vector-graphics-lib (currently in use in dozens of other language-camps, as well as in Browsers) -
    showing working VB6-code-snippets, which help to lower the knowledge-difference in case of a potential switch from VB6 to those other languages,
    as "having no place" in this forum?

    Olaf

  17. #17
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    38,989

    Re: [RESOLVED] Filling a Polygon on a Picturebox

    This thread has been resolved...more or less, though vb6forever added a new take on the initial question. Please don't turn it into an argument about RC5. Everybody has had their say. Leave it there.
    My usual boring signature: Nothing

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

    Re: [RESOLVED] Filling a Polygon on a Picturebox

    Thank you Shaggy Hiker. I'm sorry that my comments have caused controversy. In fact, I did not mention RC5 in my comments.

    What I want to say is that what I learned from Olaf is not just RC5 knowledge, but also COM, software architecture, and Web knowledge (IIS, ASP, IE, OpenUI, HTML, JS, Web-Framework), which is what I need most at the moment.

    In addition, I can see completely different ideas and solutions from Olaf, and these ideas and solutions are always full of wisdom and innovation, which I can't see anywhere else.

    Most importantly, I can see hope from Olaf, the hope of VB6 in the future.

    I have no intention of offending anyone. LaVolpe is one of my most respected people in this forum. In 2006, I knew LaVolpe in PsCode.
    Last edited by dreammanor; Aug 13th, 2018 at 08:25 AM.

  19. #19

    Thread Starter
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    9,853

    Re: [RESOLVED] Filling a Polygon on a Picturebox

    Hmmm, well, I'm still not 100% happy with my solution (post #5). In certain extreme cases, it still glitches and fills the wrong area. I'm considering looking further into the Polygon API.

    However, before encouraging this thread to continue, I'd like to respectfully ask for a couple of ground-rules. Please remember that I started this thread, and it's about trying to fill a polygon. Furthermore, regardless of the wonders of RC5, that's not a solution I'm interested in. Please find it in your hearts to respect those wishes, or take it here.

    Vb6forever, your ideas sound interesting, but I'm struggling to see it. As far as I know, rectangles drawn (and maybe filled) with the .Line method can't be rotated. And it's seldom that the polygon defining my fill area has a horizontal line, and it never has a vertical line (other than the lines closing the left-and-right edges). So, I'm not sure I see it.

    I haven't really looked yet, but if anyone has some code that converts .Line method coordinates (X1, Y1, X2, Y2) from a custom .ScaleMode (with negative .ScaleHeight) to pixels, and then builds an array to send to the Polygon API, I'd love to see it.

    Or any other VB6 and/or Windows API ideas are certainly welcome.

    Best Regards,
    Elroy
    Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.

  20. #20

  21. #21

    Thread Starter
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    9,853

    Re: [RESOLVED] Filling a Polygon on a Picturebox

    Quote Originally Posted by The trick View Post
    What's about ScaleX, ScaleY methods? What's about the paths? You can create path (BeginPath) using Line method and then fill it, or get points (GetPath).
    Hi Trick. Yesterday (or maybe it was the day before), I was having trouble with ScaleY working correctly with my negative .ScaleHeight. But I'm also distracted with a couple of other things as well. I probably just need to clear my head, and make sure I understand what's going on. Worst case, I need to develop some functions called PixelFromPicX(pic As PictureBox, X As Single) As Single (and corresponding PixelFromPicY).

    And, thanks for the BeginPath and GetPath tips. I'll definitely take a look at those and see what they have to offer.

    As soon as I get the decks cleared a bit, I'll get back to this.

    Thanks,
    Elroy
    Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.

  22. #22
    Fanatic Member
    Join Date
    Feb 2017
    Posts
    858

    Re: [RESOLVED] Filling a Polygon on a Picturebox

    Elroy:

    In my case I use all API both for lines and rectangles.
    In the case of the rectangle, if you draw the right side at the current X and the
    left at (X-1) or (X - whatever) -- this assumes the minus is moving you toward
    picturebox.scaleleft - you get a thin rectangle that basically follows the line
    with -- in my case - zero bleed past the curve line. I opted for this as IMHO faster
    than API Polygon where you need an array. If polygon is of interest heres an
    example doing an arrow:

    Code:
    Private Sub DrawArrowTriangle(ByVal Index As Integer, ByVal iX1 As Long, ByVal iY1 As Long, ByVal iX2 As Long, ByVal iY2 As Long, enmArrow As enmToolType, ByVal lngColor As Long, Optional ByVal blnBorder As Boolean = False)
    'Triangle Arrow (small)
    'Always make (iX1, iY1) the point
    'X2 is triangle Width, Y2 is triangle Height
    'Note:  Polygon vertices MUST be assigned counterclockwise
    '       per param ALTERNATE of CreatePolygonRgn
    
       #If kDEBUGON Then
           Debug.Print "Begin DrawArrowTriangle"
       #End If
    
       On Error GoTo Error_DrawArrowTriangle
       
       '-----------------
       
       'API
    '   Dim hRgn As Long
       Dim Pen1 As Long
       Dim Brush1 As Long
       Dim oldPen As Long
       Dim oldBrush As Long
    
       Dim ptPoint As POINTAPI
       Dim dl As Long
    
       'Constants
       Const PS_SOLID = 0
    
       'Objects
    '   Dim Region As RECT
       Dim objPBox As PictureBox
       Dim arrArrow(1 To 3) As POINTAPI
    
       '*******
       'STARTUP
       '*******
       Set objPBox = frmChild(Index).PBox(giSubGraphNumber)
    
       '*****
       'MAIN
       '*****
       With objPBox
       
          'Force Pen to be solid, 1 pixel, and User Color
          Pen1 = CreatePen(PS_SOLID, 1, lngColor)
          
          'Allow brush (fill color) to vary
          Brush1 = CreateSolidBrush(lngColor)
          oldPen = SelectObject(.hdc, Pen1)
          oldBrush = SelectObject(.hdc, Brush1)
    
          Select Case enmArrow
       
             Case T_POINTERDN
    
                'Triangle
                arrArrow(1).X = (iX1 + iX2) * 0.5: arrArrow(1).Y = iY1   '<< the arrow point
                arrArrow(2).X = iX1: arrArrow(2).Y = iY2
                arrArrow(3).X = iX2: arrArrow(3).Y = iY2
    
             Case T_POINTERUP
             
                'Triangle
                arrArrow(1).X = (iX1 + iX2) * 0.5: arrArrow(1).Y = iY1   '<< the arrow point
                arrArrow(2).X = iX1: arrArrow(2).Y = iY2
                arrArrow(3).X = iX2: arrArrow(3).Y = iY2
    
          End Select
          
          'Draw the Arrow
          Call Polygon(.hdc, arrArrow(1), 3)
          
          'Restore Orig Object
          SelectObject .hdc, oldPen
          SelectObject .hdc, oldBrush
          
          
          'Give the Triangle A Border
          If blnBorder Then
             .ForeColor = vbBlack
             .DrawWidth = 1
             dl = MoveToEx(.hdc, arrArrow(1).X, arrArrow(1).Y, ptPoint)
             dl = LineTo(.hdc, arrArrow(2).X, arrArrow(2).Y)
             dl = LineTo(.hdc, arrArrow(3).X, arrArrow(3).Y)
             dl = LineTo(.hdc, arrArrow(1).X, arrArrow(1).Y)
          End If
     
       End With   'PBox
    
       '*******
       'WRAPUP
       '*******
       DeleteObject Pen1
       DeleteObject Brush1
    
       #If kDEBUGON Then
           Debug.Print "End DrawArrowTriangle"
       #End If
    
       Exit Sub
    
    Error_DrawArrowTriangle:
    
       With TError
          .Type = ERR_CRITICAL
          .Src = mstrModule & "DrawArrowTriangle"
          .Action = MsgAndLog
       End With
       
       Call DoError
    
    End Sub

  23. #23
    Frenzied Member
    Join Date
    Apr 2012
    Posts
    1,253

    Re: [RESOLVED] Filling a Polygon on a Picturebox

    Quote Originally Posted by Elroy View Post
    And, thanks for the BeginPath and GetPath tips. I'll definitely take a look at those and see what they have to offer.
    This is pretty much what Olaf was suggesting you to look at in Post #6...
    If you don't know where you're going, any road will take you there...

    My VB6 love-children: Vee-Hive and Vee-Launcher

  24. #24

    Thread Starter
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    9,853

    Re: [RESOLVED] Filling a Polygon on a Picturebox

    Alright, I believe the following fixes the ScaleX and ScaleY functions, making them work the way I think they should have worked in the first place.

    Code:
    
    Public Function ScaleToPelX(pic As PictureBox, X As Single) As Long
        ' This works with positive or negative .ScaleWidth or positive or negative .ScaleLeft.
        ' It is mostly designed for custom ScaleModes.
        ScaleToPelX = CLng(pic.ScaleX(X - pic.ScaleLeft, pic.ScaleMode, vbPixels))
    End Function
    
    Public Function ScaleToPelY(pic As PictureBox, Y As Single) As Long
        ' This works with positive or negative .ScaleHeight or positive or negative .ScaleTop.
        ' It is mostly designed for custom ScaleModes.
        ScaleToPelY = CLng(pic.ScaleY(Y - pic.ScaleTop, pic.ScaleMode, vbPixels))
    End Function
    
    

    Now, hopefully things will get easy from there.

    Elroy

    EDIT1: I changed the functions to return a Long, since pixels should be represented as integers.
    Last edited by Elroy; Aug 13th, 2018 at 02:42 PM.
    Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.

  25. #25

    Thread Starter
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    9,853

    Re: [RESOLVED] Filling a Polygon on a Picturebox

    Alrighty, I wrote the following (looking at some of the above code), and it worked first-time-out-of-the-box. I love it. MUCH better, and without the glitches I had before.

    Code:
    
    Private Declare Function CreatePen Lib "Gdi32" (ByVal fnPenStyle As Long, ByVal nWidth As Long, ByVal crColor As Long) As Long
    Private Declare Function CreateSolidBrush Lib "Gdi32" (ByVal crColor As Long) As Long
    Private Declare Function SelectObject Lib "Gdi32" (ByVal hDC As Long, ByVal hObject As Long) As Long
    Private Declare Function Polygon Lib "Gdi32" (ByVal hDC As Long, lpPoint As POINTAPI, ByVal nCount As Long) As Long
    Private Declare Function DeleteObject Lib "Gdi32" (ByVal hObject As Long) As Long
    '
    
    Public Sub DrawAndFillPolygon(pic As PictureBox, uPoints() As POINTAPI, lColor As Long)
        ' Will error if uPoints isn't dimensioned.
        '
        ' The Polygon function draws a polygon consisting of two or more vertices connected by straight lines.
        ' The polygon is outlined by using the current pen and filled by using the current brush and polygon fill mode.
        '
        Dim Pen1 As Long
        Dim Brush1 As Long
        Dim oldPen As Long
        Dim oldBrush As Long
        '
        With pic
            ' Setup.
            Pen1 = CreatePen(vbFSSolid, 1, lColor)
            Brush1 = CreateSolidBrush(lColor)
            oldPen = SelectObject(.hDC, Pen1)
            oldBrush = SelectObject(.hDC, Brush1)
            '
            ' Do it.
            Polygon .hDC, uPoints(LBound(uPoints)), UBound(uPoints) - LBound(uPoints) + 1
            '
            ' Cleanup.
            SelectObject .hDC, oldPen
            SelectObject .hDC, oldBrush
            DeleteObject Pen1
            DeleteObject Brush1
        End With
    End Sub
    
    
    This, along with the functions in post #24, just might be able to help someone else trying to do something similar.

    @vb6forever: Thanks for that sample code. That absolutely helped.

    Now, this issues is truly resolved.

    Y'all Take Care,
    Elroy

    EDIT1: Here's the POINTAPI definition, just to attempt to be complete:

    Code:
    
    Public Type POINTAPI
        X As Long
        Y As Long
    End Type
    
    

    EDIT2: And just a last FYI, uPoints() is all the vertices of the polygon, and there's no need to duplicate the first one as the last one. The GDI32 assumes the last one closes with the first one.
    Last edited by Elroy; Aug 13th, 2018 at 03:36 PM.
    Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.

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