Bezier curve control

Are you writing your own components and need help with how to set them up or have questions about the components you are deriving from ? Ask them here.
NoeMurr
In need of some credit
In need of some credit
Posts: 7
Joined: Sat Mar 31, 2018 2:26 pm

Bezier curve control

Postby NoeMurr » Wed Apr 25, 2018 12:17 pm

Hi all,
I'm writing an application that needs to print a Bezier curve on a panel. That curves needs to be clickable, movable, etc. so I need it to be a "control", but wxControl has a rectangular shape and my curve, of course, cannot be wrapped in a rectangle.

Is there a way to have a custom control that does not have rectangular shape?

New Pagodi
Super wx Problem Solver
Super wx Problem Solver
Posts: 252
Joined: Tue Jun 20, 2006 6:47 pm
Contact:

Re: Bezier curve control

Postby New Pagodi » Wed Apr 25, 2018 1:41 pm

Here's one approach for drawing a dragable curve on a panel. The idea is to keep track of the points in a vector and handle the mouse events for adding or dragging points.

Code: Select all

// For compilers that support precompilation, includes "wx/wx.h".
#include "wx/wxprec.h"

#ifdef __BORLANDC__
    #pragma hdrstop
#endif

// for all others, include the necessary headers (this file is usually all you
// need because it includes almost all "standard" wxWidgets headers)
#ifndef WX_PRECOMP
    #include "wx/wx.h"
#endif

class myFrame : public wxFrame
{
    public:
        myFrame( wxWindow* parent, int id = wxID_ANY, wxString title = "Demo"
                , wxPoint pos = wxDefaultPosition, wxSize size = wxDefaultSize
                , int style = wxDEFAULT_FRAME_STYLE|wxTAB_TRAVERSAL );
    private:
        void OnLeftDown( wxMouseEvent& event );
        void OnLeftUp( wxMouseEvent& event );
        void OnMotion( wxMouseEvent& event );
        void OnPaint( wxPaintEvent& event );

        std::vector<wxPoint> m_points;
        std::vector<wxPoint>::iterator m_selection;
        wxPanel* m_panel;
};


myFrame::myFrame( wxWindow* parent, int id, wxString title, wxPoint pos
                 , wxSize size, int style )
        :wxFrame( parent, id, title, pos, size, style )
{
    m_selection=m_points.end();
    m_panel = new wxPanel(this);

    m_panel->Bind( wxEVT_LEFT_DOWN, &myFrame::OnLeftDown, this );
    m_panel->Bind( wxEVT_LEFT_UP, &myFrame::OnLeftUp, this );
    m_panel->Bind( wxEVT_MOTION, &myFrame::OnMotion, this );
    m_panel->Bind( wxEVT_PAINT, &myFrame::OnPaint, this );
}

void myFrame::OnLeftDown( wxMouseEvent& event )
{
    wxPoint p = event.GetPosition();

    for (std::vector<wxPoint>::iterator it=m_points.begin();it!=m_points.end();++it)
    {
        if ( std::abs(it->x-p.x) + std::abs(it->y-p.y) < 8 )
        {
            m_selection=it;
            m_selection->x=p.x;
            m_selection->y=p.y;
        }
    }

    if (m_selection==m_points.end())
    {
        m_points.push_back(p);
        m_selection = m_points.end();
        --m_selection;
    }
    m_panel->Refresh();
}

void myFrame::OnLeftUp( wxMouseEvent& event )
{
    m_selection=m_points.end();
    m_panel->Refresh();
}

void myFrame::OnMotion( wxMouseEvent& event )
{
    if (event.LeftIsDown() && m_selection!=m_points.end())
    {
        wxPoint p = event.GetPosition();
        m_selection->x=p.x;
        m_selection->y=p.y;
        m_panel->Refresh();
    }
}

void myFrame::OnPaint( wxPaintEvent& event )
{
    wxPaintDC dc(m_panel);
    dc.Clear();

    dc.SetPen(*wxBLACK_PEN);
    dc.SetBrush(*wxWHITE_BRUSH);

    if (m_points.size()>2)
    {
        dc.DrawSpline(m_points.size(),&(m_points[0]));
    }

    for (std::vector<wxPoint>::iterator it=m_points.begin();it!=m_points.end();++it)
    {
        dc.DrawCircle(*it, 4);
    }

    if ( m_selection!=m_points.end() )
    {
        dc.SetPen(*wxRED_PEN);
        dc.SetBrush(*wxRED_BRUSH);
        dc.DrawCircle(*m_selection, 4);
    }
}

class myApp : public wxApp
{
    public:
        virtual bool OnInit()
        {
            myFrame* frame = new myFrame(NULL);
            frame->Show();
            return true;
        }
};

wxIMPLEMENT_APP(myApp);


bez.png
bez.png (2.31 KiB) Viewed 337 times


This obviously isn't complete. I know the above code will have problems when the mouse leaves the window. To fix this, either the mouse should be captured in the left down event or an event handler for the wxEVT_LEAVE_WINDOW event should be added. There may be other problems as well.

ONEEYEMAN
Part Of The Furniture
Part Of The Furniture
Posts: 2569
Joined: Sat Apr 16, 2005 7:22 am
Location: USA, Ukraine

Re: Bezier curve control

Postby ONEEYEMAN » Wed Apr 25, 2018 3:37 pm

Hi,
The best way is to use a pre-written library for such stuff.

For wxWidgets, there are wxArt2D, wxShapeFramework and wxWorkspaceView (ref. https://wiki.wxwidgets.org/WxFAQ#How_ca ... d_nodes.3F).

Thank you.


Return to “Component Writing”

Who is online

Users browsing this forum: No registered users and 1 guest