help drawing this on device context

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
Everydaydiesel
Earned some good credits
Earned some good credits
Posts: 125
Joined: Wed Oct 28, 2015 9:48 pm

help drawing this on device context

Post by Everydaydiesel »

Hello,

Does anyone have any advice on how I can draw this image?
stk.png
stk.png (18.46 KiB) Viewed 2459 times
I know how to draw the line and I know how to draw the gradient but how do you only have the gradient below the line?

Thanks for any help you can give
PB
Part Of The Furniture
Part Of The Furniture
Posts: 4193
Joined: Sun Jan 03, 2010 5:45 pm

Re: help drawing this on device context

Post by PB »

If you are using wxDC you need to clip drawing area prior to painting the gradient. Construct wxClippingRegion from the points you need and then use wxDC::SetDeviceClippingRegion().
Everydaydiesel
Earned some good credits
Earned some good credits
Posts: 125
Joined: Wed Oct 28, 2015 9:48 pm

Re: help drawing this on device context

Post by Everydaydiesel »

Thank you for replying.

I cannot find any info on the wxClippingRegion. Could you please show me how I would change this code to draw using the SetDeviceClippingRegion? It seems that SetDeviceClippingRegion only takes a single coordinate? How would I map multiple like in this example?

Code: Select all

    vector<int> lssX;
    vector<int> lssY;
    wxColor colWhite = wxColor(255, 255, 255);
    wxColor colRed = wxColor(255, 0, 0);

    lssX.push_back(25);
    lssX.push_back(50);
    lssX.push_back(75);
    lssX.push_back(100);
    lssX.push_back(125);
    lssX.push_back(150);
    lssX.push_back(175);
    lssX.push_back(200);
    lssX.push_back(225);
    lssX.push_back(250);

    lssY.push_back(25);
    lssY.push_back(50);
    lssY.push_back(75);
    lssY.push_back(131);
    lssY.push_back(65);
    lssY.push_back(125);
    lssY.push_back(30);
    lssY.push_back(110);
    lssY.push_back(65);
    lssY.push_back(85);

    int iOldX = 0;
    int iOldY = 100;

    wxPaintDC dc(Panel1);
    wxRect rect = Panel1->GetClientRect();

    dc.GradientFillLinear(rect, colWhite, colRed, wxNORTH);

    dc.SetDeviceClippingRegion()

    for (int i = 0; i < lssX.size(); ++i)
    {
        dc.DrawLine(iOldX, iOldY, lssX[i], lssY[i]);

        iOldX = lssX[i];
        iOldY = lssY[i];
    }
User avatar
doublemax
Moderator
Moderator
Posts: 19116
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: help drawing this on device context

Post by doublemax »

There is an overload of wxDC::SetDeviceClippingRegion that takes a wxRegion as parameter:
http://docs.wxwidgets.org/trunk/classwx ... 4e9cc0b4b1

And there is a wxRegion constructor that creates a region from a polygon:
http://docs.wxwidgets.org/trunk/classwx ... 56873d50ac
Use the source, Luke!
Everydaydiesel
Earned some good credits
Earned some good credits
Posts: 125
Joined: Wed Oct 28, 2015 9:48 pm

Re: help drawing this on device context

Post by Everydaydiesel »

Thank you for the reply and please excuse my ignorance.

The size_t is the array length?

I would expect the points to be an array or vector but I dont think it is.
So how do I put multiple values in a wxPoint *

Code: Select all

wxRegion::wxRegion	(	size_t 	n,
const wxPoint * 	points,
wxPolygonFillMode 	fillStyle = wxODDEVEN_RULE 
)	
New Pagodi
Super wx Problem Solver
Super wx Problem Solver
Posts: 466
Joined: Tue Jun 20, 2006 6:47 pm
Contact:

Re: help drawing this on device context

Post by New Pagodi »

Everydaydiesel wrote:I would expect the points to be an array or vector but I dont think it is.
So how do I put multiple values in a wxPoint *
You can allocate them with the new operator

Code: Select all

wxPoint* myArray = new wxPoint[n];
for (size_t i=0;i<n;++i)
{
    myArray[i].x=...;
    myArray[i].y=...;
}

wxRegion myRegion(n,myArray);

//do something with the region here

//when you're finished with the region, free the points like this:
delete[] myArray;
Obviously, replace the ... in the for loop with an with something that gives the x and y coordinates for your points.
Everydaydiesel
Earned some good credits
Earned some good credits
Posts: 125
Joined: Wed Oct 28, 2015 9:48 pm

Re: help drawing this on device context

Post by Everydaydiesel »

Thanks to everyone who has helped me. I seem to be missing something still because it is not drawing correctly.

The top image is what it looks like when I comment out // dc.SetDeviceClippingRegion(myRegion);
The bottom is with the dc.SetDeviceClippingRegion(myRegion);
Image

Code: Select all

    vector<int> lssX;
    vector<int> lssY;
    int iOldX = 0;
    int iOldY = 100;
    wxColor colWhite = wxColor(255, 255, 255);
    wxColor colRed = wxColor(255, 0, 0);
    wxPaintDC dc(Panel1);
    wxRect rect = Panel1->GetClientRect();

    lssX.push_back(25);
    lssX.push_back(50);
    lssX.push_back(75);
    lssX.push_back(100);
    lssX.push_back(125);
    lssX.push_back(150);
    lssX.push_back(175);
    lssX.push_back(200);
    lssX.push_back(225);
    lssX.push_back(250);

    lssY.push_back(25);
    lssY.push_back(50);
    lssY.push_back(75);
    lssY.push_back(131);
    lssY.push_back(65);
    lssY.push_back(125);
    lssY.push_back(30);
    lssY.push_back(110);
    lssY.push_back(65);
    lssY.push_back(85);

    wxPoint* myArray = new wxPoint[lssX.size()];
    for (int i = 0; i < lssX.size(); ++i)
    {
        myArray[i].x = lssX[i];
        myArray[i].y = lssY[i];
    }

    wxRegion myRegion(lssX.size(), myArray, wxODDEVEN_RULE);
    dc.SetDeviceClippingRegion(myRegion);                                           ///// This line makes the difference
    dc.GradientFillLinear(rect, colWhite, colRed, wxNORTH);

    for (int i = 0; i < lssX.size(); ++i)
    {
        dc.DrawLine(iOldX, iOldY, lssX[i], lssY[i]);

        iOldX = lssX[i];
        iOldY = lssY[i];
    }

    delete[] myArray;
Everydaydiesel
Earned some good credits
Earned some good credits
Posts: 125
Joined: Wed Oct 28, 2015 9:48 pm

Re: help drawing this on device context

Post by Everydaydiesel »

This one looks closer but is still missing something

Image

Code: Select all


    vector<int> lssX;
    vector<int> lssY;
    int iOldX = 0;
    int iOldY = 100;
    wxColor colWhite = wxColor(255, 255, 255);
    wxColor colRed = wxColor(255, 0, 0);
    wxPaintDC dc(Panel1);
    wxRect rect = Panel1->GetClientRect();

    lssX.push_back(0);   // added starting X
    lssX.push_back(25);
    lssX.push_back(50);
    lssX.push_back(75);
    lssX.push_back(100);
    lssX.push_back(125);
    lssX.push_back(150);
    lssX.push_back(175);
    lssX.push_back(200);
    lssX.push_back(225);
    lssX.push_back(250);

    lssY.push_back(100);  // added starting Y
    lssY.push_back(25);
    lssY.push_back(50);
    lssY.push_back(75);
    lssY.push_back(131);
    lssY.push_back(65);
    lssY.push_back(125);
    lssY.push_back(30);
    lssY.push_back(110);
    lssY.push_back(65);
    lssY.push_back(85);

    wxPoint* myArray = new wxPoint[lssX.size()];
    for (int i = 0; i < lssX.size(); ++i)
    {
        myArray[i].x = lssX[i];
        myArray[i].y = lssY[i];
    }

    wxRegion myRegion(lssX.size(), myArray, wxODDEVEN_RULE);
    dc.SetDeviceClippingRegion(myRegion);
    dc.GradientFillLinear(rect, colWhite, colRed, wxNORTH);

    for (int i = 1; i < lssX.size(); ++i)
    {
        dc.DrawLine(lssX[i-1], lssY[i-1], lssX[i], lssY[i]);

        //iOldX = lssX[i];
        //iOldY = lssY[i];
    }

    delete[] myArray;

User avatar
doublemax
Moderator
Moderator
Posts: 19116
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: help drawing this on device context

Post by doublemax »

The polygon is automatically closed by connecting the first and the last point. You need to add two helper points, one in the lower left (as first point) and one in the lower right corner (as last point). Then it should look ok.
Use the source, Luke!
PB
Part Of The Furniture
Part Of The Furniture
Posts: 4193
Joined: Sun Jan 03, 2010 5:45 pm

Re: help drawing this on device context

Post by PB »

Sorry for confusing you before with typing wxClippingRegion instead of wxRegion.

BTW, if a function taking an array expects a pointer, such as wxPoint*, you can just use std::vector<wxPoint> and pass a pointer to its first element to the function, e.g.

Code: Select all

std::vector<wxPoint> points;
... fill points
dc.DrawLines(points.size(), &points[0]);
...
wxRegion clipRegion(points.size(), &points[0]);
...
Everydaydiesel
Earned some good credits
Earned some good credits
Posts: 125
Joined: Wed Oct 28, 2015 9:48 pm

Re: help drawing this on device context

Post by Everydaydiesel »

Now it is working!

Other then graphing more coordinates. Does anyone have any advice on smoothing the rough edges of the lines?

Image


Edit: I see this post
viewtopic.php?p=66885#66885

I linked gdiplus but the #if wxUSE_GRAPHICS_CONTEXT is grayed out.

Code: Select all

    bool m_useContext = true;
#if wxUSE_GRAPHICS_CONTEXT
    wxGCDC gdc( pdc ) ;                                         // this is grayed out
    wxDC &dc = m_useContext ? (wxDC&) gdc : (wxDC&) pdc ;       // this is grayed out
#else
    wxDC &dc = pdc ;
#endif
User avatar
doublemax
Moderator
Moderator
Posts: 19116
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: help drawing this on device context

Post by doublemax »

I linked gdiplus but the #if wxUSE_GRAPHICS_CONTEXT is grayed out.
That means that your wxWidgets version was built without wxGraphicsContext support. Which wx version, platform and compiler are you using?

wxGraphicsContext should be enabled on all major platforms by default now, if you're under Windows with an older wxWidgets version, you can set wxUSE_GRAPHICS_CONTEXT to 1 in setup.h and rebuild the library.
Use the source, Luke!
Everydaydiesel
Earned some good credits
Earned some good credits
Posts: 125
Joined: Wed Oct 28, 2015 9:48 pm

Re: help drawing this on device context

Post by Everydaydiesel »

Thank you for helping.

wx-config --version 3.0.2
uname -a Linux user-desktop 4.13.0-38-generic #43~16.04.1-Ubuntu SMP Wed Mar 14 17:48:43 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
os: linux mint 18.3 - kde plasma: 5.8.8
compiler: codeblocks 16.01
Everydaydiesel
Earned some good credits
Earned some good credits
Posts: 125
Joined: Wed Oct 28, 2015 9:48 pm

Re: help drawing this on device context

Post by Everydaydiesel »

Is it possible to draw with opengl inside of a wxwidgets wxPanel?
User avatar
doublemax
Moderator
Moderator
Posts: 19116
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: help drawing this on device context

Post by doublemax »

Everydaydiesel wrote:Is it possible to draw with opengl inside of a wxwidgets wxPanel?
No, but you could convert the wxPanel to wxGLCanvas. But then you'd also have to replace all the wxDC based drawing with OpenGL commands.
Last edited by doublemax on Mon Apr 23, 2018 5:36 am, edited 1 time in total.
Reason: wrote wxGLPanel instead of wxGLCanvas
Use the source, Luke!
Post Reply