mirror of https://github.com/CGAL/cgal
615 lines
18 KiB
C++
615 lines
18 KiB
C++
// if QT is not installed, a message will be issued in runtime.
|
|
|
|
#include <CGAL/basic.h>
|
|
#include <iostream>
|
|
|
|
#ifndef CGAL_USE_QT
|
|
|
|
int main(int, char*)
|
|
{
|
|
std::cout << "Sorry, this demo needs QT...";
|
|
std::cout << std::endl;
|
|
return 0;
|
|
}
|
|
|
|
#else
|
|
#include <qapplication.h>
|
|
#include <qfont.h>
|
|
#include <qpushbutton.h>
|
|
#include <qfiledialog.h>
|
|
#include <qimage.h>
|
|
#include <qinputdialog.h>
|
|
#include <qpainter.h>
|
|
#include <qstatusbar.h>
|
|
#include <qlabel.h>
|
|
#include <qmenubar.h>
|
|
#include <qpopupmenu.h>
|
|
#include <qgl.h>
|
|
|
|
#include <sstream>
|
|
#include <string>
|
|
#include <CGAL/Stream_lines_2.h>
|
|
#include <CGAL/Runge_kutta_integrator_2.h>
|
|
#include <CGAL/Regular_grid_2.h>
|
|
|
|
#include <CGAL/Timer.h>
|
|
|
|
typedef double coord_type;
|
|
typedef CGAL::Cartesian<coord_type> K;
|
|
typedef CGAL::Regular_grid_2<K> Field;
|
|
typedef CGAL::Runge_kutta_integrator_2<Field> Runge_kutta_integrator;
|
|
typedef CGAL::Stream_lines_2<Field, Runge_kutta_integrator> Strl;
|
|
typedef CGAL::Stream_lines_2<Field, Runge_kutta_integrator>::Stream_line_iterator_2 Strl_iterator;
|
|
typedef CGAL::Stream_lines_2<Field, Runge_kutta_integrator>::Point_iterator_2 Pt_iterator;
|
|
typedef CGAL::Stream_lines_2<Field, Runge_kutta_integrator>::Point_2 Point_2;
|
|
typedef CGAL::Stream_lines_2<Field, Runge_kutta_integrator>::Vector_2 Vector;
|
|
|
|
bool d_stl = true;
|
|
bool d_pq = false;
|
|
bool d_tr = false;
|
|
bool d_bc = false;
|
|
std::list<Point_2> _list;
|
|
std::list<std::pair<Point_2, Point_2 > > _tr_list;
|
|
std::pair<Point_2, double> bc;
|
|
std::list<Point_2> _bc_list;
|
|
|
|
QMenuBar * menu;
|
|
QPopupMenu * file;
|
|
QPopupMenu * save;
|
|
QPopupMenu * placement;
|
|
QPopupMenu * options;
|
|
QPopupMenu * view;
|
|
|
|
|
|
int generate_id;
|
|
int generatefirst_id;
|
|
int generatenext_id;
|
|
int generateten_id;
|
|
int generateresume_id;
|
|
int view_id;
|
|
int drawstl_id;
|
|
int drawpq_id;
|
|
int drawtr_id;
|
|
int drawbc_id;
|
|
int addimage_id;
|
|
int clear_id;
|
|
int save_id;
|
|
|
|
|
|
template <class T>
|
|
std::string five_letters(T i)
|
|
{
|
|
std::ostringstream ss ;
|
|
ss << i ;
|
|
std::string s = ss.str().substr(0,5);
|
|
|
|
if(s.length()<5){
|
|
s.insert((std::string::size_type)0, 5-s.length(), ' ');
|
|
}
|
|
return s;
|
|
}
|
|
|
|
class Placement : public QObject
|
|
{
|
|
Q_OBJECT
|
|
public:
|
|
bool completed;
|
|
double density_;
|
|
double ratio_;
|
|
double integrating_;
|
|
int sampling_;
|
|
int number_of_lines_;
|
|
Strl * Stream_lines;
|
|
Runge_kutta_integrator * runge_kutta_integrator;
|
|
Field * regular_grid;
|
|
Strl_iterator begin_iterator;
|
|
Strl_iterator end_iterator;
|
|
Placement() :
|
|
completed(false), density_(12.0), ratio_(1.6), integrating_(1.0), sampling_(1), number_of_lines_(0),
|
|
Stream_lines(NULL), runge_kutta_integrator(NULL), regular_grid(NULL), begin_iterator(){}
|
|
Strl_iterator begin() const
|
|
{
|
|
return begin_iterator;
|
|
}
|
|
Strl_iterator end() const
|
|
{
|
|
return end_iterator;
|
|
}
|
|
bool is_empty() const
|
|
{
|
|
return Stream_lines == NULL;
|
|
}
|
|
~Placement(){
|
|
delete Stream_lines;
|
|
delete runge_kutta_integrator;
|
|
delete regular_grid;}
|
|
public slots :
|
|
void clear()
|
|
{
|
|
if (Stream_lines != NULL)
|
|
{
|
|
delete Stream_lines;
|
|
Stream_lines = NULL;
|
|
delete runge_kutta_integrator;
|
|
runge_kutta_integrator = NULL;
|
|
delete regular_grid;
|
|
regular_grid = NULL;
|
|
d_stl = true;
|
|
d_pq = false;
|
|
d_tr = false;
|
|
d_bc = false;
|
|
completed = false;
|
|
}
|
|
}
|
|
void load( const QString & s )
|
|
{
|
|
runge_kutta_integrator = new Runge_kutta_integrator(integrating_);
|
|
std::ifstream infile(s, std::ios::in);
|
|
double iXSize, iYSize;
|
|
iXSize = iYSize = 512;
|
|
unsigned int x_samples, y_samples;
|
|
infile >> x_samples;
|
|
infile >> y_samples;
|
|
regular_grid = new Field(x_samples, y_samples, iXSize, iYSize);
|
|
/*fill the grid with the appropreate values*/
|
|
for (unsigned int i=0;i<x_samples;i++)
|
|
for (unsigned int j=0;j<y_samples;j++)
|
|
{
|
|
double xval, yval;
|
|
infile >> xval;
|
|
infile >> yval;
|
|
regular_grid->set_field(i, j, Vector(xval, yval));
|
|
}
|
|
infile.close();
|
|
completed = false;
|
|
number_of_lines_ = 0;
|
|
d_stl = true;
|
|
d_pq = false;
|
|
d_tr = false;
|
|
d_bc = false;
|
|
/*enable menu items*/
|
|
placement->setItemEnabled(generate_id, true);
|
|
placement->setItemEnabled(generatefirst_id, true);
|
|
menu->setItemEnabled(view_id, true);
|
|
}
|
|
void generate()
|
|
{
|
|
Stream_lines = new Strl(*regular_grid, *runge_kutta_integrator, density_, ratio_, sampling_);
|
|
number_of_lines_ = Stream_lines->number_of_lines();
|
|
std::cout << "success\n";
|
|
completed = true;
|
|
d_stl = true;
|
|
d_pq = false;
|
|
d_tr = false;
|
|
d_bc = false;
|
|
/*enable menu items*/
|
|
placement->setItemEnabled(generate_id, false);
|
|
placement->setItemEnabled(generatefirst_id, false);
|
|
placement->setItemEnabled(clear_id, true);
|
|
draw();
|
|
}
|
|
void generateFirst()
|
|
{
|
|
if (!completed)
|
|
Stream_lines = new Strl(*regular_grid, *runge_kutta_integrator, density_, ratio_, sampling_, true);
|
|
number_of_lines_ = Stream_lines->number_of_lines();
|
|
d_stl = true;
|
|
d_pq = false;
|
|
d_tr = false;
|
|
d_bc = false;
|
|
placement->setItemEnabled(generate_id, false);
|
|
placement->setItemEnabled(generatefirst_id, false);
|
|
placement->setItemEnabled(generatenext_id, !completed);
|
|
placement->setItemEnabled(generateten_id, !completed);
|
|
placement->setItemEnabled(generateresume_id, !completed);
|
|
placement->setItemEnabled(clear_id, !completed);
|
|
draw();
|
|
}
|
|
void generateNext(bool b = true)
|
|
{
|
|
if (!completed){
|
|
completed = ! Stream_lines->continue_next(*regular_grid, *runge_kutta_integrator, sampling_);
|
|
if (completed)
|
|
std::cerr << "placement completed!\n";}
|
|
d_stl = true;
|
|
d_pq = false;
|
|
d_tr = false;
|
|
d_bc = false;
|
|
if (b)
|
|
draw();
|
|
placement->setItemEnabled(generatenext_id, !completed);
|
|
placement->setItemEnabled(generateten_id, !completed);
|
|
placement->setItemEnabled(generateresume_id, !completed);
|
|
placement->setItemEnabled(clear_id, !completed);
|
|
}
|
|
void generateTen()
|
|
{
|
|
for (int i=0;i<10;i++)
|
|
generateNext(false);
|
|
draw();
|
|
}
|
|
void generateAll()
|
|
{
|
|
while (!completed)
|
|
generateNext(false);
|
|
draw();
|
|
}
|
|
void purge()
|
|
{
|
|
if (Stream_lines != NULL)
|
|
delete Stream_lines;
|
|
Stream_lines = NULL;
|
|
|
|
// desable all generator menu items
|
|
placement->setItemEnabled(generate_id, true);
|
|
placement->setItemEnabled(generatefirst_id, true);
|
|
placement->setItemEnabled(generatenext_id, false);
|
|
placement->setItemEnabled(generateten_id, false);
|
|
placement->setItemEnabled(generateresume_id, false);
|
|
placement->setItemEnabled(clear_id, false);
|
|
file->setItemEnabled(save_id, false);
|
|
completed = false;
|
|
|
|
draw();
|
|
}
|
|
void draw()
|
|
{
|
|
if (Stream_lines!=NULL)
|
|
{
|
|
begin_iterator = Stream_lines->begin();
|
|
end_iterator = Stream_lines->end();
|
|
}
|
|
}
|
|
void draw_stl()
|
|
{
|
|
d_stl = !d_stl;
|
|
}
|
|
void draw_pq()
|
|
{
|
|
d_pq = !d_pq;
|
|
_list = Stream_lines->get_pq();
|
|
}
|
|
void draw_tr()
|
|
{
|
|
d_tr = !d_tr;
|
|
_tr_list = Stream_lines->get_tr();
|
|
}
|
|
void draw_bc()
|
|
{
|
|
d_bc = !d_bc;
|
|
bc = Stream_lines->get_biggest_circle();
|
|
_bc_list.clear();
|
|
for (double f=0.0;f<=6.29;f=f+0.05)
|
|
{
|
|
Point_2 p1 ( bc.first.x() + ((bc.second) * cos(f)) , bc.first.y() + ((bc.second) * sin(f)) );
|
|
_bc_list.push_front(p1);
|
|
}
|
|
}
|
|
void image( const QString & s )
|
|
{
|
|
QImage bckgnd( s );
|
|
std::cout << bckgnd.width() << " " << bckgnd.height() << "\n";
|
|
}
|
|
void density()
|
|
{
|
|
density_ = QInputDialog::getDouble("Get density" , "Density", density_, 1.0, 12.0, 2);
|
|
emit(optionschanged());
|
|
}
|
|
void ratio()
|
|
{
|
|
ratio_ = QInputDialog::getDouble("Get saturation ratio" , "Saturation ratio", ratio_, 1.0, 5.0, 1);
|
|
emit(optionschanged());
|
|
}
|
|
void integrating()
|
|
{
|
|
integrating_ = QInputDialog::getDouble("Get integrating step" , "integrating step", integrating_, 1.0, 10.0,1);
|
|
emit(optionschanged());
|
|
}
|
|
void sampling()
|
|
{
|
|
sampling_ = QInputDialog::getInteger("Get sampling step" , "Sampling step", sampling_, 0, 10);
|
|
emit(optionschanged());
|
|
}
|
|
signals:
|
|
void optionschanged();
|
|
};
|
|
|
|
|
|
class MyWidget : public QGLWidget
|
|
{
|
|
Q_OBJECT
|
|
public:
|
|
Placement p;
|
|
|
|
QStatusBar * statusbar;
|
|
QLabel * densitylabel;
|
|
QLabel * densitytextlabel;
|
|
QLabel * densityspacelabel;
|
|
QLabel * ratiolabel;
|
|
QLabel * ratiotextlabel;
|
|
QLabel * ratiospacelabel;
|
|
QLabel * samplinglabel;
|
|
QLabel * samplingtextlabel;
|
|
QLabel * samplingspacelabel;
|
|
QLabel * numberlabel;
|
|
QLabel * numbertextlabel;
|
|
QLabel * numberspacelabel;
|
|
QLabel * xcursorposition;
|
|
QLabel * ycursorposition;
|
|
|
|
MyWidget(QGLWidget *parent = 0);
|
|
~MyWidget(){
|
|
delete menu;
|
|
delete file;
|
|
delete save;
|
|
delete placement;}
|
|
public slots :
|
|
QString openedfile(){
|
|
p.clear();
|
|
QString s = QFileDialog::getOpenFileName( "",
|
|
"Vector fields (*.vec.cin)", this, "open file dialog", "Choose a file to load" );
|
|
if (!s.isEmpty())
|
|
emit(fileloaded(s));
|
|
return s;
|
|
}
|
|
QString openedimage(){
|
|
p.clear();
|
|
QString s = QFileDialog::getOpenFileName( "",
|
|
"Image (*.*)", this, "open file dialog", "Choose a file to load" );
|
|
emit(imageloaded(s));
|
|
return s;
|
|
}
|
|
QString savedepsfile(){
|
|
QString s = QFileDialog::getSaveFileName( ".",
|
|
"Encapsulated PostScript files (*.eps)", this, "save file dialog", "Save file to" );
|
|
std::ofstream fw(s,std::ios::out);
|
|
p.Stream_lines->print_stream_lines_eps(fw);
|
|
return s;
|
|
}
|
|
QString savedstlfile(){
|
|
QString s = QFileDialog::getSaveFileName( ".",
|
|
"STreamLine files (*.stl)", this, "save file dialog", "Save file to" );
|
|
std::ofstream fw(s,std::ios::out);
|
|
p.Stream_lines->print_stream_lines(fw);
|
|
return s;
|
|
}
|
|
|
|
void drawing()
|
|
{
|
|
glClearColor(1.0, 1.0, 1.0, 0.0);
|
|
glClear(GL_COLOR_BUFFER_BIT);
|
|
|
|
|
|
glEnable(GL_LINE_SMOOTH);
|
|
glEnable(GL_BLEND);
|
|
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
|
|
glHint(GL_LINE_SMOOTH_HINT,GL_NICEST);
|
|
|
|
|
|
glLineWidth(0.5f);
|
|
|
|
int XSize = width();
|
|
int YSize = height();
|
|
int Diff = div(XSize - YSize, 2).quot;
|
|
if (Diff > 0)
|
|
glViewport ( 10+Diff, 40, YSize - 80, height() - 80);
|
|
else
|
|
{
|
|
Diff = -Diff;
|
|
glViewport ( 10, 40+Diff, width() - 20, XSize - 20);
|
|
}
|
|
|
|
glMatrixMode ( GL_PROJECTION );
|
|
glLoadIdentity ();
|
|
glOrtho(0.0, 1.0, 0.0, 1.0, -1.0, 1.0);
|
|
|
|
glColor3f(0.0, 0.0, 0.0);
|
|
glBegin(GL_LINE_LOOP);
|
|
glVertex2f(1.0, 1.0);
|
|
glVertex2f(0.0, 1.0);
|
|
glVertex2f(0.0, 0.0);
|
|
glVertex2f(1.0, 0.0);
|
|
glEnd();
|
|
|
|
if (d_pq)
|
|
{
|
|
glColor3f(1.0, 0.0, 0.0);
|
|
glLineWidth(0.5f);
|
|
glBegin(GL_POINTS);
|
|
for (std::list<Point_2>::iterator pit = _list.begin(); pit != _list.end(); pit++)
|
|
{
|
|
glVertex2f((*pit).x() / 512, (*pit).y() / 512);
|
|
}
|
|
glEnd();
|
|
}
|
|
if (d_tr)
|
|
{
|
|
glColor3f(0.0, 0.0, 1.0);
|
|
glLineWidth(0.25f);
|
|
for (std::list< std::pair<Point_2, Point_2> >::iterator pit = _tr_list.begin(); pit != _tr_list.end(); pit++)
|
|
{
|
|
glBegin(GL_LINES);
|
|
glVertex2f((*pit).first.x() / 512, (*pit).first.y() / 512);
|
|
glVertex2f((*pit).second.x() / 512, (*pit).second.y() / 512);
|
|
glEnd();
|
|
}
|
|
}
|
|
if (d_bc)
|
|
{
|
|
glColor3f(0.0, 1.0, 0.0);
|
|
glLineWidth(0.5f);
|
|
glBegin(GL_LINE_STRIP);
|
|
for (std::list<Point_2>::iterator pit = _bc_list.begin(); pit != _bc_list.end(); pit++)
|
|
{
|
|
glVertex2f((*pit).x() / 512, (*pit).y() / 512);
|
|
}
|
|
glEnd();
|
|
}
|
|
|
|
if (d_stl)
|
|
{
|
|
glColor3f(0.0, 0.0, 0.0);
|
|
glLineWidth(1.5f);
|
|
if (!p.is_empty())
|
|
for (Strl_iterator sit = p.begin(); sit != p.end(); sit++)
|
|
{
|
|
glBegin(GL_LINE_STRIP);
|
|
for (Pt_iterator pit = (*sit).first; pit != (*sit).second; pit++)
|
|
{
|
|
glVertex2f((*pit).x() / 512, (*pit).y() / 512);
|
|
}
|
|
glEnd();
|
|
}
|
|
}
|
|
update();
|
|
}
|
|
|
|
void paintGL()
|
|
{
|
|
updatestatus();
|
|
drawing();
|
|
}
|
|
|
|
void updatestatus()
|
|
{
|
|
std::string s = five_letters( p.density_ ) + five_letters( p.ratio_ ) + five_letters( p.sampling_ ) + five_letters(p.number_of_lines_);
|
|
|
|
numberlabel->setText(s.c_str());
|
|
}
|
|
|
|
void setstatus()
|
|
{
|
|
statusbar = new QStatusBar(this, "Status bar");
|
|
|
|
densitytextlabel = new QLabel(this);
|
|
|
|
|
|
|
|
densitytextlabel->setText("Separating distance");
|
|
statusbar->addWidget(densitytextlabel);
|
|
densitylabel = new QLabel(this);
|
|
densitylabel->setText(five_letters(p.density_).c_str());
|
|
statusbar->addWidget(densitylabel);
|
|
densityspacelabel = new QLabel(this);
|
|
densityspacelabel->setText(" ");
|
|
statusbar->addWidget(densityspacelabel);
|
|
|
|
ratiotextlabel = new QLabel(this);
|
|
ratiotextlabel->setText("Saturation ratio");
|
|
statusbar->addWidget(ratiotextlabel);
|
|
ratiolabel = new QLabel(this);
|
|
ratiolabel->setText(five_letters(p.ratio_).c_str());
|
|
statusbar->addWidget(ratiolabel);
|
|
ratiospacelabel = new QLabel(this);
|
|
ratiospacelabel->setText(" ");
|
|
statusbar->addWidget(ratiospacelabel);
|
|
|
|
samplingtextlabel = new QLabel(this);
|
|
samplingtextlabel->setText("Sampling step");
|
|
statusbar->addWidget(samplingtextlabel);
|
|
samplinglabel = new QLabel(this);
|
|
samplinglabel->setText(five_letters(p.sampling_).c_str());
|
|
statusbar->addWidget(samplinglabel);
|
|
samplingspacelabel = new QLabel(this);
|
|
samplingspacelabel->setText(" ");
|
|
statusbar->addWidget(samplingspacelabel);
|
|
|
|
numbertextlabel = new QLabel(this);
|
|
numbertextlabel->setText("Number of lines");
|
|
statusbar->addWidget(numbertextlabel);
|
|
numberlabel = new QLabel(this);
|
|
numberlabel->setText(five_letters(p.number_of_lines_).c_str());
|
|
statusbar->addWidget(numberlabel);
|
|
numberspacelabel = new QLabel(this);
|
|
numberspacelabel->setText(" ");
|
|
statusbar->addWidget(numberspacelabel);
|
|
|
|
statusbar->move(0, height() - 30);
|
|
statusbar->resize(width(), 30);
|
|
}
|
|
|
|
void resizeEvent ( QResizeEvent * )
|
|
{
|
|
statusbar->move(0, height() - 30);
|
|
statusbar->resize(width(), 30);
|
|
}
|
|
signals:
|
|
void fileloaded(const QString & s);
|
|
void imageloaded(const QString & s);
|
|
};
|
|
|
|
MyWidget::MyWidget(QGLWidget *parent)
|
|
: QGLWidget(QGLFormat(), parent)
|
|
{
|
|
|
|
setMouseTracking(true);
|
|
|
|
setPaletteBackgroundColor(QColor(255,255,255));
|
|
|
|
setstatus();
|
|
|
|
menu = new QMenuBar(this, "Menu bar");
|
|
file = new QPopupMenu( this , "file");
|
|
save = new QPopupMenu( this , "save");
|
|
placement = new QPopupMenu( this , "placement");
|
|
options = new QPopupMenu( this , "options");
|
|
view = new QPopupMenu( this , "viewing");
|
|
save->insertItem( "Save &eps file", this, SLOT(savedepsfile()), CTRL+Key_E );
|
|
save->insertItem( "Save &stl file", this, SLOT(savedstlfile()), CTRL+Key_S );
|
|
file->insertItem( "&Load", this, SLOT(openedfile()), CTRL+Key_L );
|
|
generate_id = placement->insertItem( "&Generate", &p, SLOT(generate()), CTRL+Key_G );
|
|
generatefirst_id = placement->insertItem( "Generate &First", &p, SLOT(generateFirst()), CTRL+Key_F );
|
|
generatenext_id = placement->insertItem( "Generate &Next", &p, SLOT(generateNext()), CTRL+Key_N );
|
|
generateten_id = placement->insertItem( "Next &ten streamlines", &p, SLOT(generateTen()), CTRL+Key_T );
|
|
generateresume_id = placement->insertItem( "&Resume the placement", &p, SLOT(generateAll()), CTRL+Key_C );
|
|
clear_id = placement->insertItem( "&Clear", &p, SLOT(purge()), CTRL+Key_M );
|
|
drawstl_id = view->insertItem( "&Draw streamlines", &p, SLOT(draw_stl()), CTRL+Key_D );
|
|
drawpq_id = view->insertItem( "Draw &queue elements", &p, SLOT(draw_pq()), CTRL+Key_Q );
|
|
drawtr_id = view->insertItem( "Draw t&riangulation", &p, SLOT(draw_tr()), CTRL+Key_R );
|
|
drawbc_id = view->insertItem( "Draw &biggest circle", &p, SLOT(draw_bc()), CTRL+Key_B );
|
|
addimage_id = placement->insertItem( "&Image", this, SLOT(openedimage()), CTRL+Key_I );
|
|
options->insertItem( "Density...", &p, SLOT(density()));
|
|
options->insertItem( "Saturation ration...", &p, SLOT(ratio()));
|
|
options->insertItem( "Sampling step...", &p, SLOT(sampling()));
|
|
options->insertItem( "Integrating step...", &p, SLOT(integrating()));
|
|
placement->insertItem( "&Options ", options );
|
|
save_id = file->insertItem( "&Save", save );
|
|
menu->insertItem( "&File", file );
|
|
menu->insertItem( "&Placement", placement );
|
|
view_id = menu->insertItem( "&View ", view );
|
|
file->insertItem( "&Quit", qApp, SLOT(quit()), ALT+Key_F4 );
|
|
|
|
// desable all generator menu items
|
|
placement->setItemEnabled(generate_id, false);
|
|
placement->setItemEnabled(generatefirst_id, false);
|
|
placement->setItemEnabled(generatenext_id, false);
|
|
placement->setItemEnabled(generateten_id, false);
|
|
placement->setItemEnabled(generateresume_id, false);
|
|
placement->setItemEnabled(clear_id, false);
|
|
|
|
menu->setItemEnabled(view_id, false);
|
|
|
|
placement->setItemEnabled(addimage_id, false);
|
|
file->setItemEnabled(save_id, false);
|
|
|
|
|
|
connect(this, SIGNAL(fileloaded(const QString &)), &p, SLOT(load(const QString &)));
|
|
connect(this, SIGNAL(imageloaded(const QString &)), &p, SLOT(image(const QString &)));
|
|
connect(&p, SIGNAL(optionschanged()), this, SLOT(updatestatus()));
|
|
|
|
}
|
|
|
|
#include "streamlines.moc"
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
QApplication app(argc, argv);
|
|
MyWidget widget;
|
|
app.setMainWidget(&widget);
|
|
widget.show();
|
|
qWarning("this is an OpenGL application for drawing streamline placements");
|
|
return app.exec();
|
|
}
|
|
|
|
#endif
|