draw.hpp

来自「FreeFem++可以生成高质量的有限元网格。可以用于流体力学」· HPP 代码 · 共 500 行

HPP
500
字号
// -*- Mode : c++ -*-//// SUMMARY  :      // USAGE    :        // ORG      : // AUTHOR   : Antoine Le Hyaric -// E-MAIL   : lehyaric@ann.jussieu.fr///*  This file is part of Freefem++  Freefem++ is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.  Freefem++  is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.  You should have received a copy of the GNU Lesser General Public License along with Freefem++; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */// Graphics window// ---------------// Antoine Le Hyaric - LJLL Paris 6 - lehyaric@ann.jussieu.fr - 21/10/04// $Id: draw.hpp,v 1.3 2006-09-29 20:30:15 hecht Exp $#ifndef DRAW_HPP#define DRAW_HPP#include <cassert>#include <list>#include <vector>#include <string>using namespace std;#ifdef CLIENT#include <FL/Fl_Button.H>#include <FL/Fl_Round_Button.H>#include <FL/Fl_Box.H>#include <FL/Fl_Widget.H>#include <FL/fl_draw.H>#endif#ifndef NOSOCKETS#include "socket.hpp"#endif// Defines a default width and height for FreeFEM++ graphics, that// will be scaled down to the window size when the actual drawing// takes place. Uses "float" to avoid any rounding problems.extern const float virtualwidth,virtualheight;// We also define a virtual font size. It the size of the font that// fits into a window of size virtualwidth x virtualheight. The actual// font size will be scaled to the actual window size.extern const float virtualfontsize;// An object that the FreeFEM++ server can ask to be drawn by the// graphical window.class drawable{public:#ifdef CLIENT  // How to draw that object in the graphical window  virtual void draw()=0;  // Creating a clone of the object (to go into the other drawing  // list, back to front).  virtual drawable *clone()=0;#endif // CLIENT  // When on the server, how to send data about that particular object  // to the client, to enable the client to draw it (it is the default  // constructor of this object that receives data on the client).#ifdef SERVER#ifndef NOSOCKETS  virtual void send() const=0;#endif#endif // SERVER};#ifdef CLIENT// A drawing list shared between FreeFEM++ server thread and the// drawing window. There are two copies to leave the previous one on// screen while the next one is built.extern list<drawable*> drawings;extern list<drawable*> backdrawings;// Clears the front picture and transfers the back picture to the// front.void clearlist(list<drawable*> &l);void flushdrawings();// Zooming coefficientsextern float zoomcenterx,zoomcentery,zoomscale;// Translation coefficientsextern int translatex,translatey;// Limiting zoom to reasonable limits (X could crash if we asked for// stupidly big fonts for instance).void limitzoomscale();// Zooming state (necessary for 1-button mice)extern bool zoominstate;void zoomin(Fl_Widget*,void*);void zoomout(Fl_Widget*,void*);#endif // CLIENT// Information on each specific graphical objectclass coords{public:  coords(){    X=0.0;    Y=0.0;  }  coords(const float x,const float y):X(x),Y(y){}  // Scaling factors, useful only on the client side (where the  // graphical window is displayed).#ifdef CLIENT  // The actual size of the drawing window  static int widgetleft,widgettop,widgetwidth,widgetheight;  // Keeping the picture square even in a rectangular window  static float scale(){    return min(widgetwidth/virtualwidth,widgetheight/virtualheight);  }  // Scaling procedure for x or y  static int windowscaling(const float xy,const float zoomcenterxy,			   const int widgetsize,			   const int widgetstart,const int translate){    // Zoom    float zoomxy;    zoomxy=(xy-zoomcenterxy)*zoomscale;    // Scale    float graphxy=zoomxy*scale();    // Translate    return static_cast<int>(graphxy)+translate+widgetsize/2+widgetstart;  }  // Find virtual coordinates back from window coordinates (to locate  // the center of a zoom as pointed by the mouse).  static float virtualscaling(const float xy,const float zoomcenterxy,			      const int widgetsize,			      const int widgetstart,const int translate){    // Untranslate    float untranslatexy=xy-translate-widgetsize/2-widgetstart;    // Unscale    float unscalexy=untranslatexy/scale();    // Unzoom    float unzoomxy=unscalexy/zoomscale+zoomcenterxy;    return unzoomxy;  }  // how to convert from FreeFEM++ coordinates to FLTK window  // coordinates. Keep the image scaled and centered.  static int widgetx(const float x){    return windowscaling(x,zoomcenterx,widgetwidth,widgetleft,translatex);  }  static int widgety(const float y){    return windowscaling(y,zoomcentery,widgetheight,widgettop,translatey);  }  // Return the values of X and Y for a given widget size  int getx() const{return widgetx(X);}  int gety() const{return widgety(Y);}#endif // CLIENT  // Communication of coordinates from FreeFEM++ server to IDE client#ifndef NOSOCKETS#ifdef CLIENT  void receive(){clientsocket>>X>>Y;}#endif#ifdef SERVER  void send() const{*serversocket<<X<<Y;}#endif#endifprivate:  float X,Y;};#ifdef CLIENT// Job control buttonsextern Fl_Button *runbutton;extern Fl_Button *pausebutton;extern Fl_Button *stopbutton;extern Fl_Round_Button *clickpausebutton;// The graphics toolbar must be accessible from here to be activated// when some graphical data is displayed.extern Fl_Group *graphicstoolbar;// Defines default values for the zoom center, such that the graphics// are well centeredvoid resetzoomcenter();// Create a specific widget for FreeFEM++ drawingsclass Tffgraphics:public Fl_Box{public:  Tffgraphics(int x,int y,int w,int h,const char *label = 0);protected:  void draw();private:  // Compute the zooming center in virtual coordinates from the  // given window coordinates  static void findzoomcenter();  //  Distinguish mouse clicks for zooms (no motion) and translations  //  (dragging motion).  bool mousedrag;  int oldmousex,oldmousey;  // Catches the mouse when it comes by!  int handle(int event);};extern Tffgraphics *graphics;extern Fl_Group *graphicsarea;// Resetting the zoom by clicking on a buttonvoid zoomreset(Fl_Widget*,void*);#endif // CLIENTclass color:public drawable{public:  color(const unsigned char r,const unsigned char g,const unsigned char b):    red(r),green(g),blue(b){}#ifdef CLIENT#ifndef NOSOCKETS  color(){clientsocket>>red>>green>>blue;}#endif  void draw(){    fl_color(fl_rgb_color(red,green,blue));  }  drawable *clone(){return new color(*this);}#endif#ifdef SERVER#ifndef NOSOCKETS  void send() const{*serversocket<<CMD_COLOR<<red<<green<<blue;}#endif#endifprivate:  unsigned char red,green,blue;};// Stores the default color that FreeFem++ selected, because we must// remember it even when FreeFem++ clears the graphics (FF++ sets the// color first, and then clears the image!).extern color *defaultcolor;class point:public drawable,private coords{public:  point(const coords c):coords(c){}#ifdef CLIENT#ifndef NOSOCKETS  point(){coords::receive();}#endif  void draw(){fl_point(getx(),gety());}  drawable *clone(){return new point(*this);}#endif#ifdef SERVER#ifndef NOSOCKETS  void send() const{    *serversocket<<CMD_POINT;    coords::send();  }#endif#endif};class line:public drawable{public:  line(const coords f,const coords t):from(f),to(t){}#ifdef CLIENT#ifndef NOSOCKETS  line(){    from.receive();    to.receive();  }#endif  void draw(){fl_line(from.getx(),from.gety(),to.getx(),to.gety());}  drawable *clone(){return new line(*this);}#endif#ifdef SERVER#ifndef NOSOCKETS  void send() const{    *serversocket<<CMD_LINE;    from.send();    to.send();  }#endif#endifprivate:  coords from,to;};class text:public drawable{public:  text(const coords s,const string l):start(s),label(l){}#ifdef CLIENT#ifndef NOSOCKETS  text(){    start.receive();    clientsocket>>label;  }#endif  void draw(){    // Choose a font size proportional to the corresponding graphics.    float fontsize=virtualfontsize*coords::scale();    fontsize*=zoomscale;    fl_font(FL_COURIER,static_cast<int>(fontsize));    fl_draw(label.c_str(),start.getx(),start.gety());  }  drawable *clone(){return new text(*this);}#endif#ifdef SERVER#ifndef NOSOCKETS  void send() const{    *serversocket<<CMD_TEXT;    start.send();    *serversocket<<label;  }#endif#endifprivate:  coords start;  string label;};class pen:public drawable{public:  pen(const int t):thickness(t){}#ifdef CLIENT#ifndef NOSOCKETS  pen(){clientsocket>>thickness;}#endif  void draw(){fl_line_style(FL_SOLID,thickness);}  drawable *clone(){return new pen(*this);}#endif#ifdef SERVER#ifndef NOSOCKETS  void send() const{*serversocket<<CMD_PEN<<thickness;}#endif#endifprivate:  int thickness;};class circle:public drawable{public:  circle(const coords c,const float r):centre(c),radius(r){}#ifdef CLIENT#ifndef NOSOCKETS  circle(){    centre.receive();    clientsocket>>radius;  }#endif  void draw(){    fl_arc(static_cast<int>(centre.getx()-radius),	   static_cast<int>(centre.gety()-radius),	   static_cast<int>(2*radius),	   static_cast<int>(2*radius),	   0,360);  }  drawable *clone(){return new circle(*this);}#endif#ifdef SERVER#ifndef NOSOCKETS  void send() const{    *serversocket<<CMD_CIRCLE;    centre.send();    *serversocket<<radius;  }#endif#endifprivate:  coords centre;  float radius;};// A convex filled polygonclass polygon:public drawable{public:  polygon(const vector<coords> p):points(p){}#ifdef CLIENT#ifndef NOSOCKETS  polygon(){    // Get the number of points    int n;    clientsocket>>n;    // Get point coordinates    int i;    for(i=0;i<n;i++){      coords c;      c.receive();      points.push_back(c);    }  }#endif  void draw(){    // Can speed up computations when the polygon has three or four    // edges.    assert(points.size()>=3);    if(points.size()==3){      fl_polygon(points[0].getx(),points[0].gety(),		 points[1].getx(),points[1].gety(),		 points[2].getx(),points[2].gety());    }    else if(points.size()==4){      fl_polygon(points[0].getx(),points[0].gety(),		 points[1].getx(),points[1].gety(),		 points[2].getx(),points[2].gety(),		 points[3].getx(),points[3].gety());    }    // More than four edges (and points)    else{      // Find the barycentre of all the points      float x=0,y=0;      for(vector<coords>::const_iterator p=points.begin();p<points.end();p++){	x+=p->getx();	y+=p->gety();      }      x/=points.size();      y/=points.size();      // Draw filled triangles defined by two polygon points and the      // barycentre      for(vector<coords>::const_iterator p=points.begin();p<points.end();	  p++){	// We need to link the last point back to the first	if(p+1==points.end()){	  fl_polygon(p->getx(),p->gety(),		     points.begin()->getx(),points.begin()->gety(),		     static_cast<int>(x),static_cast<int>(y));	}	else{	  fl_polygon(p->getx(),p->gety(),		     (p+1)->getx(),(p+1)->gety(),		     static_cast<int>(x),static_cast<int>(y));	}      }    }  }  drawable *clone(){return new polygon(*this);}#endif#ifdef SERVER#ifndef NOSOCKETS  void send() const{    // Send number of points    *serversocket<<CMD_POLYGON<<points.size();    // Send each point coordinates    for(vector<coords>::const_iterator p=points.begin();p<points.end();p++)      p->send();  }#endif#endifprivate:  vector<coords> points;};#endif // DRAW_HPP

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?