#include "wx/wxprec.h"
#ifdef __BORLANDC__ // addition for Borland C++
#pragma hdrstop
#endif
#ifndef WX_PRECOMP // for other compilers
#include "wx/wx.h"
#endif
#include <iSeeML/fwdPaths>
class ISeeMLDrawingArea : public wxPanel {
wxFrame *parentFrame;
const wxBrush *daGP, *cvGP;
const wxPen *bgGP,
*configGP,
*dubinsGP, *fscpGP,
*dubinsTCGP, *fscpTCGP;
wxPoint centerPoint;
double scale;
bool movingConfig;
double maxCurv, maxDCurv;
public:
ISeeMLDrawingArea(wxFrame& parent, double scl) :
wxPanel(&parent), parentFrame(&parent),
scale(scl), movingConfig(false),
maxCurv(1), maxDCurv(0.8),
dubins(start, goal, maxCurv),
fscp(start, goal, maxCurv, maxDCurv) {
daGP = wxWHITE_BRUSH;
cvGP = wxTRANSPARENT_BRUSH;
bgGP = wxWHITE_PEN;
configGP = wxRED_PEN;
dubinsGP = new wxPen( wxT("BLUE") );
fscpGP = wxGREEN_PEN;
dubinsTCGP = new wxPen( wxT("ORANGE"), 1, wxLONG_DASH );
fscpTCGP = new wxPen( wxT("GOLD"), 1, wxLONG_DASH );
SetBackgroundColour(*wxWHITE);
}
void OnMouseClick(wxMouseEvent& event);
void OnMouseMove (wxMouseEvent& event);
void OnMouseWheel(wxMouseEvent& event);
void OnSize (wxSizeEvent& event);
void OnPaint (wxPaintEvent& event);
void OnChar (wxKeyEvent& event);
private:
return wxPoint( centerPoint.x + (
int)(p.
xCoord() * scale),
centerPoint.y + (
int)(p.
yCoord() * scale) );
}
void Draw (wxDC& dc, const bool erase = false);
DECLARE_EVENT_TABLE()
};
class ISeeMLFrame : public wxFrame
{
enum { ID_MENU_EDIT_CONFIG = 1, ID_MENU_EDIT_MAXIMA,
ID_MENU_EDIT_ZOOM, ID_MENU_VIEW_PATH,
ID_MENU_VIEW_PATH_DUBINS, ID_MENU_VIEW_PATH_FSCP,
ID_MENU_VIEW_PATH_BOTH, ID_MENU_VIEW_TURN_CIRCLES
};
wxMenu* pathSubMenu;
ISeeMLDrawingArea* drawingArea;
public:
ISeeMLFrame(const wxString& title);
bool DrawDubins() const {
return ( pathSubMenu->IsChecked(ID_MENU_VIEW_PATH_DUBINS) ||
pathSubMenu->IsChecked(ID_MENU_VIEW_PATH_BOTH) );}
bool DrawFSCP() const {
return ( pathSubMenu->IsChecked(ID_MENU_VIEW_PATH_FSCP) ||
pathSubMenu->IsChecked(ID_MENU_VIEW_PATH_BOTH) ); }
bool ShowTurnCircles() const {
wxMenu *editMenu = GetMenuBar()->GetMenu(2);
return editMenu->IsChecked(ID_MENU_VIEW_TURN_CIRCLES); }
void enableSave(bool enable)
{ GetMenuBar()->GetMenu(0)->Enable(wxID_SAVEAS, enable); }
void OnSaveAs(wxCommandEvent& event);
void OnQuit (wxCommandEvent& WXUNUSED(event)) { Close(TRUE); }
void OnSetGoal (wxCommandEvent& event);
void OnSetMaxima (wxCommandEvent& event);
void OnSetZoom (wxCommandEvent& event);
void OnSelectPath (wxCommandEvent& event);
void OnShowTurnCirc(wxCommandEvent& WXUNUSED(event))
{ drawingArea->Refresh(); }
void OnAbout (wxCommandEvent& event);
private:
DECLARE_EVENT_TABLE()
};
class ISeeMLApp : public wxApp
{
bool OnInit()
{
ISeeMLFrame *frame =
new ISeeMLFrame( wxT("ISeeML V1.0 Interface") );
frame->Show(TRUE);
SetTopWindow(frame);
return TRUE;
}
};
IMPLEMENT_APP(ISeeMLApp)
BEGIN_EVENT_TABLE(ISeeMLDrawingArea, wxPanel)
EVT_LEFT_DOWN (ISeeMLDrawingArea::OnMouseClick)
EVT_MOTION (ISeeMLDrawingArea::OnMouseMove)
EVT_MOUSEWHEEL (ISeeMLDrawingArea::OnMouseWheel)
EVT_SIZE (ISeeMLDrawingArea::OnSize)
EVT_PAINT (ISeeMLDrawingArea::OnPaint)
EVT_KEY_DOWN (ISeeMLDrawingArea::OnChar)
END_EVENT_TABLE()
void ISeeMLDrawingArea::OnMouseClick(wxMouseEvent&
event)
{
movingConfig = !movingConfig;
OnMouseMove(event);
wxString message;
if (movingConfig) {
((ISeeMLFrame *) parentFrame)->enableSave(false);
message.Printf(wxT("Clic to fix, use arrows or")
wxT(" page up/down to change orientation")
); }
else {
((ISeeMLFrame *) parentFrame)->enableSave(true);
message.Printf(wxT("Clic to change again")
wxT(" goal configuration")
); }
parentFrame->SetStatusText(message);
}
void ISeeMLDrawingArea::OnMouseMove(wxMouseEvent
&event)
{
if (movingConfig) {
wxClientDC dc(this);
PrepareDC(dc);
parentFrame->PrepareDC(dc);
wxPoint pos = event.GetPosition();
int i = (int) dc.DeviceToLogicalX(pos.x),
j = (int) dc.DeviceToLogicalY(pos.y);
(j - centerPoint.y) / scale,
goal.orientation() );
ChangeGoal(newGoal);
}
}
void ISeeMLDrawingArea::OnMouseWheel(wxMouseEvent
&event)
{
static const double PI_196 = M_PI / 196, PI_28 = M_PI / 28,
PI_4 = M_PI / 4;
const int change = goal.sign( event.GetWheelRotation() );
double newTh = goal.orientation();
if ( event.ShiftDown() )
newTh += change * PI_4;
else if ( event.MiddleIsDown() )
newTh += change * PI_196;
else newTh += change * PI_28;
ChangeGoal(newGoal);
}
void ISeeMLDrawingArea::OnSize(wxSizeEvent &event)
{
wxSize size = event.GetSize();
centerPoint.x = size.GetWidth() / 2;
centerPoint.y = size.GetHeight() / 2;
Refresh();
}
void ISeeMLDrawingArea::OnPaint(wxPaintEvent &event)
{
wxClientDC dc(this);
PrepareDC(dc);
parentFrame->PrepareDC(dc);
dc.StartPage();
ClearBackground();
dc.SetBrush(*cvGP);
Draw(dc);
dc.EndPage();
}
void ISeeMLDrawingArea::OnChar(wxKeyEvent &event)
{
static const double PI_196 = M_PI / 196, PI_28 = M_PI / 28,
PI_4 = M_PI / 4;
double newTh = goal.orientation();
if (movingConfig)
switch ( event.GetKeyCode() ) {
case WXK_HOME : newTh = 0; break;
case WXK_END : newTh = M_PI; break;
case WXK_PAGEDOWN: newTh += PI_4; break;
case WXK_PAGEUP : newTh -= PI_4; break;
case WXK_DOWN : newTh += PI_28; break;
case WXK_UP : newTh -= PI_28; break;
case WXK_RIGHT : newTh += PI_196; break;
case WXK_LEFT : newTh -= PI_196; break;
default : event.Skip();
}
else
event.Skip();
ChangeGoal(newGoal);
}
void ISeeMLDrawingArea::Draw(wxDC& dc,
const OrPtConfig& q)
{
const static int configSize = 20;
wxPoint startP = dblPt2intPt( q.
position() );
iF = startP.x + di, jF = startP.y + dj;
dc.DrawLine(startP.x, startP.y, iF, jF);
dc.DrawLine(iF, jF, iF - (di + dj) / 4, jF + (di - dj) / 4);
dc.DrawLine(iF, jF, iF - (di - dj) / 4, jF - (di + dj) / 4);
}
{
int i = 0;
wxPoint endP = dblPt2intPt( linPiece.
end().
position() );
if (linPiece.
length() > 1.5 / scale)
dc.DrawLine(startP.x, startP.y, endP.x, endP.y);
else {
wxPoint cntr = dblPt2intPt
dc.DrawArc(endP.x, endP.y, startP.x, startP.y,
cntr.x, cntr.y);
else
dc.DrawArc(startP.x, startP.y, endP.x, endP.y,
cntr.x, cntr.y); }
else {
double step = 5. / scale, arcLngth = step;
while (arcLngth < linPiece.
length()) {
wxPoint midP =
dblPt2intPt( linPiece[arcLngth].position() );
dc.DrawLine(startP.x, startP.y, midP.x, midP.y);
startP = midP;
arcLngth += step; }
dc.DrawLine(startP.x, startP.y, endP.x, endP.y); }
else
dc.DrawLine(startP.x, startP.y, endP.x, endP.y);
startP = endP;
}
}
{
dc.DrawCircle(dblPt2intPt(centers[i]), radius);
}
void ISeeMLDrawingArea::Draw(wxDC& dc, const bool clean)
{
if (clean) dc.SetPen(*bgGP);
else dc.SetPen(*configGP);
dc.SetBrush(*cvGP);
Draw(dc, start);
Draw(dc, goal);
ISeeMLFrame *parent =
(ISeeMLFrame *) parentFrame;
if ( clean || parent->DrawDubins() ) {
if (!clean) dc.SetPen(*dubinsGP);
Draw(dc, dubins);
if ( clean || parent->ShowTurnCircles() ) {
if (!clean) dc.SetPen(*dubinsTCGP);
DrawTC(dc, dubins); } }
if ( clean || parent->DrawFSCP() ) {
if (!clean) dc.SetPen(*fscpGP);
Draw(dc, fscp);
if ( clean || parent->ShowTurnCircles() ) {
if (!clean) dc.SetPen(*fscpTCGP);
DrawTC(dc, fscp); } }
}
void ISeeMLDrawingArea::ChangeGoal(
const OrPtConfig&
q)
{
wxClientDC dc(this);
PrepareDC(dc);
parentFrame->PrepareDC(dc);
dc.StartPage();
Draw(dc, true);
goal = q;
dubins.connect(start, goal);
fscp.connect(start, goal);
Draw(dc);
dc.EndPage();
}
ISeeMLFrame::ISeeMLFrame(const wxString& title)
: wxFrame((wxFrame *) NULL, -1, title, wxDefaultPosition,
wxSize(750, 800))
{
wxMenuBar *menuBar = new wxMenuBar;
wxMenu *menu = new wxMenu;
menu->Append( wxID_SAVEAS, wxT("&Save/Export as...\tS"),
wxT("Save drawing into various formats") );
menu->AppendSeparator();
menu->Append( wxID_EXIT, wxT("E&xit\tX"),
wxT("Close GUI and quit") );
menuBar->Append( menu, wxT("File") );
menu = new wxMenu;
menu->Append( ID_MENU_EDIT_CONFIG,
wxT("Set Goal &Configuration...\tC"),
wxT("Not yet available!") );
menu->AppendSeparator();
menu->Append( ID_MENU_EDIT_MAXIMA,
wxT("Modify Paths' &Maxima...\tM"),
wxT("Not yet available!") );
menu->AppendSeparator();
menu->Append( ID_MENU_EDIT_ZOOM, wxT("Change &Zoom/Scale...\tZ"),
wxT("Not yet available!") );
menuBar->Append( menu, wxT("Edit") );
menu = new wxMenu;
pathSubMenu = new wxMenu;
pathSubMenu->AppendCheckItem( ID_MENU_VIEW_PATH_DUBINS,
wxT("&Dubins'\tD"),
wxT("Only draw Dubin's path") );
pathSubMenu->AppendCheckItem( ID_MENU_VIEW_PATH_FSCP,
wxT("&Linear Curvature (FSCP)\tL"),
wxT("Only draw FSC path") );
pathSubMenu->AppendCheckItem( ID_MENU_VIEW_PATH_BOTH,
wxT("&Both\tB"),
wxT("Draw both Dubin's and FSC paths") );
pathSubMenu->Check(ID_MENU_VIEW_PATH_DUBINS, true);
menu->Append(ID_MENU_VIEW_PATH, wxT("Draw Paths"), pathSubMenu);
menu->AppendCheckItem( ID_MENU_VIEW_TURN_CIRCLES,
wxT("Show &Turning Circles...\tT"),
wxT("Display turning circles")
wxT(" of drawn path(s)") );
menuBar->Append( menu, wxT("View") );
menu = new wxMenu;
menu->Append( wxID_ABOUT, wxT("&About...\tA"),
wxT("Display information about this application") );
menuBar->Append( menu, wxT("Help") );
SetMenuBar(menuBar);
CreateStatusBar();
wxString message;
message.Printf(wxT("Clic in the drawing array to change")
wxT(" goal configuration")
);
SetStatusText(message);
drawingArea = new ISeeMLDrawingArea(*this, 50);
}
BEGIN_EVENT_TABLE(ISeeMLFrame, wxFrame)
EVT_MENU (wxID_SAVEAS, ISeeMLFrame::OnSaveAs)
EVT_MENU (wxID_EXIT, ISeeMLFrame::OnQuit)
EVT_MENU (ID_MENU_EDIT_CONFIG,
ISeeMLFrame::OnSetGoal)
EVT_MENU (ID_MENU_EDIT_MAXIMA,
ISeeMLFrame::OnSetMaxima)
EVT_MENU (ID_MENU_EDIT_ZOOM,
ISeeMLFrame::OnSetZoom)
EVT_MENU (ID_MENU_VIEW_PATH_DUBINS,
ISeeMLFrame::OnSelectPath)
EVT_MENU (ID_MENU_VIEW_PATH_FSCP,
ISeeMLFrame::OnSelectPath)
EVT_MENU (ID_MENU_VIEW_PATH_BOTH,
ISeeMLFrame::OnSelectPath)
EVT_MENU (ID_MENU_VIEW_TURN_CIRCLES,
ISeeMLFrame::OnShowTurnCirc)
EVT_MENU (wxID_ABOUT, ISeeMLFrame::OnAbout)
END_EVENT_TABLE()
void ISeeMLFrame::OnSaveAs(wxCommandEvent&
WXUNUSED(event))
{
SetStatusText( wxT("Sorry, exporting drawing ")
wxT("is not yet implemented!") );
}
void ISeeMLFrame::OnSetGoal(wxCommandEvent&
WXUNUSED(event))
{
SetStatusText( wxT("Sorry, goal definition's dialog box ")
wxT("is not yet implemented!") );
}
void ISeeMLFrame::OnSetMaxima(wxCommandEvent&
WXUNUSED(event))
{
SetStatusText( wxT("Sorry, maxima changing is not yet implemented!") );
}
void ISeeMLFrame::OnSetZoom(wxCommandEvent&
WXUNUSED(event))
{
SetStatusText( wxT("Sorry, zoom/scale changing ")
wxT("is not yet implemented!") );
}
void ISeeMLFrame::OnSelectPath(wxCommandEvent& event)
{
pathSubMenu->Check(ID_MENU_VIEW_PATH_DUBINS, false);
pathSubMenu->Check(ID_MENU_VIEW_PATH_FSCP, false);
pathSubMenu->Check(ID_MENU_VIEW_PATH_BOTH, false);
pathSubMenu->Check(event.GetId(), true);
drawingArea->Refresh();
}
void ISeeMLFrame::OnAbout(wxCommandEvent&
WXUNUSED(event))
{
wxString message;
message.Printf(wxT("This is ISeeML V1.0 GUI\n\n")
wxT("It uses wxWidgets (www.wxWidgets.org),\n")
wxT("which should become\n")
wxT("ISeeML V1.1 base GUI toolkit.\n\n")
wxT("Written by A. Scheuer\n")
wxT("(Alexis.Scheuer@inria.fr)")
);
wxMessageBox(message,
_T("About ISeeML V1.0 Interface"),
wxOK | wxICON_INFORMATION, this);
}