1 // -*- mode:C++ ; compile-command: "g++ -DHAVE_CONFIG_H -I. -I.. -I../include -I../../giac/include -g -c Graph.cc -DHAVE_CONFIG_H -DIN_GIAC" -*- 2 #include "Graph.h" 3 /* 4 * Copyright (C) 2000,2014 B. Parisse, Institut Fourier, 38402 St Martin d'Heres 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 3 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program. If not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 21 #ifdef HAVE_CONFIG_H 22 #include "config.h" 23 #endif 24 #ifdef HAVE_LIBFLTK 25 #include <FL/fl_ask.H> 26 #include <FL/fl_ask.H> 27 #include <FL/Fl.H> 28 #include <FL/Fl_Value_Input.H> 29 #include <FL/Fl_Return_Button.H> 30 #include <FL/Fl_Check_Button.H> 31 #include <FL/fl_show_colormap.H> 32 #include <FL/Fl_Tiled_Image.H> 33 #include <FL/Fl_Image.H> 34 #include <FL/Fl_Shared_Image.H> 35 #include <fstream> 36 #include "vector.h" 37 #include <algorithm> 38 #include <fcntl.h> 39 #include <cmath> 40 #include <time.h> // for nanosleep 41 #include <stdio.h> 42 #include <dirent.h> 43 #include <sys/stat.h> // auto-recovery function 44 #ifdef HAVE_SYS_TIME_H 45 #include <sys/time.h> 46 #endif 47 #include "path.h" 48 #ifndef IN_GIAC 49 #include <giac/plot.h> 50 #else 51 #include "plot.h" 52 #endif 53 #include "Equation.h" 54 #include "Editeur.h" 55 #include "Xcas1.h" 56 #include "Print.h" 57 #include "Graph3d.h" 58 #include <FL/gl.h> 59 #include "Tableur.h" 60 #ifdef HAVE_UNISTD_H 61 #include <unistd.h> 62 #endif 63 64 using namespace std; 65 using namespace giac; 66 67 68 #ifndef NO_NAMESPACE_XCAS 69 namespace xcas { 70 #endif // ndef NO_NAMESPACE_XCAS 71 72 bool do_helpon=true; 73 74 std::map<std::string,std::pair<Fl_Image *,Fl_Image *> *> texture2d_cache; 75 pow10(double d)76 static double pow10(double d){ 77 return std::pow(10.,d); 78 } 79 get_texture2d(const string & s,std::pair<Fl_Image *,Fl_Image * > * & texture)80 void get_texture2d(const string & s,std::pair<Fl_Image *,Fl_Image *> * & texture){ 81 texture=0; 82 std::map<std::string,std::pair<Fl_Image *,Fl_Image*> *>::const_iterator it,itend=texture2d_cache.end(); 83 it=texture2d_cache.find(s); 84 if (it!=itend){ 85 texture=it->second; 86 // texture->uncache(); 87 } 88 else { 89 Fl_Shared_Image * ptr =Fl_Shared_Image::get(s.c_str()); 90 if (ptr) 91 ptr->reload(); 92 texture=new std::pair<Fl_Image *,Fl_Image*>(ptr,0); 93 texture2d_cache[s]=texture; 94 } 95 } 96 xcas_color(int color,bool dim3)97 void xcas_color(int color,bool dim3){ 98 if (color>=0x100 && color<0x17e){ 99 int r,g,b; 100 arc_en_ciel(color-(0x100),r,g,b); 101 #ifdef HAVE_LIBFLTK_GL 102 if (dim3) 103 glColor3f(r/255.,g/255.,b/255.); 104 else 105 #endif 106 fl_color(r,g,b); 107 } 108 else { 109 if (color>=512){ 110 int r=8*((color>>11)&0x1f); 111 int g=4*((color>>5) &0x3f); 112 int b=8*(color & 0x1f); 113 #ifdef HAVE_LIBFLTK_GL 114 if (dim3) 115 glColor3f(r/255.,g/255.,b/255.); 116 else 117 #endif 118 fl_color(r,g,b); 119 } 120 else { 121 if (dim3) 122 gl_color(color); 123 else 124 fl_color(color); 125 } 126 } 127 } 128 129 vector<Graph2d3d *> animations; 130 Min(int i,int j)131 inline int Min(int i,int j) {return i>j?j:i;} 132 Max(int i,int j)133 inline int Max(int i,int j) {return i>j?i:j;} 134 quaternion_double(double theta_x,double theta_y,double theta_z)135 quaternion_double::quaternion_double(double theta_x,double theta_y,double theta_z) { 136 *this=euler_deg_to_quaternion_double(theta_x,theta_y,theta_z); 137 } 138 euler_deg_to_quaternion_double(double a,double b,double c)139 quaternion_double euler_deg_to_quaternion_double(double a,double b,double c){ 140 double phi=a*M_PI/180, theta=b*M_PI/180, psi=c*M_PI/180; 141 double c1 = std::cos(phi/2); 142 double s1 = std::sin(phi/2); 143 double c2 = std::cos(theta/2); 144 double s2 = std::sin(theta/2); 145 double c3 = std::cos(psi/2); 146 double s3 = std::sin(psi/2); 147 double c1c2 = c1*c2; 148 double s1s2 = s1*s2; 149 double w =c1c2*c3 - s1s2*s3; 150 double x =c1c2*s3 + s1s2*c3; 151 double y =s1*c2*c3 + c1*s2*s3; 152 double z =c1*s2*c3 - s1*c2*s3; 153 return quaternion_double(w,x,y,z); 154 } 155 quaternion_double_to_euler_deg(const quaternion_double & q,double & phi,double & theta,double & psi)156 void quaternion_double_to_euler_deg(const quaternion_double & q,double & phi,double & theta, double & psi){ 157 double test = q.x*q.y + q.z*q.w; 158 if (test > 0.499) { // singularity at north pole 159 phi = 2 * atan2(q.x,q.w) * 180/M_PI; 160 theta = 90; 161 psi = 0; 162 return; 163 } 164 if (test < -0.499) { // singularity at south pole 165 phi = -2 * atan2(q.x,q.w) * 180/M_PI; 166 theta = - 90; 167 psi = 0; 168 return; 169 } 170 double sqx = q.x*q.x; 171 double sqy = q.y*q.y; 172 double sqz = q.z*q.z; 173 phi = atan2(2*q.y*q.w-2*q.x*q.z , 1 - 2*sqy - 2*sqz) * 180/M_PI; 174 theta = asin(2*test) * 180/M_PI; 175 psi = atan2(2*q.x*q.w-2*q.y*q.z , 1 - 2*sqx - 2*sqz) * 180/M_PI; 176 } 177 operator *(const quaternion_double & q1,const quaternion_double & q2)178 quaternion_double operator * (const quaternion_double & q1,const quaternion_double & q2){ 179 double z=q1.w*q2.z+q2.w*q1.z+q1.x*q2.y-q2.x*q1.y; 180 double x=q1.w*q2.x+q2.w*q1.x+q1.y*q2.z-q2.y*q1.z; 181 double y=q1.w*q2.y+q2.w*q1.y+q1.z*q2.x-q2.z*q1.x; 182 double w=q1.w*q2.w-q1.x*q2.x-q1.y*q2.y-q1.z*q2.z; 183 return quaternion_double(w,x,y,z); 184 } 185 186 // q must be a unit get_axis_angle_deg(const quaternion_double & q,double & x,double & y,double & z,double & theta)187 void get_axis_angle_deg(const quaternion_double & q,double &x,double &y,double & z, double &theta){ 188 double scale=1-q.w*q.w; 189 if (scale>1e-6){ 190 scale=std::sqrt(scale); 191 theta=2*std::acos(q.w)*180/M_PI; 192 x=q.x/scale; 193 y=q.y/scale; 194 z=q.z/scale; 195 } 196 else { 197 x=0; y=0; z=1; 198 theta=0; 199 } 200 } 201 operator <<(ostream & os,const quaternion_double & q)202 ostream & operator << (ostream & os,const quaternion_double & q){ 203 return os << q.w << "+" << q.x << "i+" << q.y << "j+" << q.z << "k"; 204 } 205 readrgb(const string & s,int W,int H,gen & res)206 bool readrgb(const string & s,int W,int H,gen & res){ 207 Fl_Image * image=Fl_Shared_Image::get(s.c_str()); 208 if (image && W && H) 209 image=image->copy(W,H); 210 if (!image || image->count()!=1) 211 return false; 212 const char * data = image->data()[0]; 213 unsigned ih=image->h(),iw=image->w(),id=image->d(); 214 gen tmpr=vecteur(ih),tmpg=vecteur(ih),tmpb=vecteur(ih),tmpa=vecteur(ih); 215 // alpha is returned before blue because red==1, green==2, blue==4 216 res=gen(makevecteur(makevecteur(4,int(ih),int(iw)),tmpr,tmpg,tmpa,tmpb),_RGBA__VECT); 217 vecteur & vr=*tmpr._VECTptr; 218 vecteur & vg=*tmpg._VECTptr; 219 vecteur & vb=*tmpb._VECTptr; 220 vecteur & va=*tmpa._VECTptr; 221 unsigned l=0; 222 for (unsigned i=0;i<ih;++i){ 223 if (debug_infolevel) 224 cerr << "readrgb, reading row " << i << '\n'; 225 vr[i]=vecteur(iw); 226 vg[i]=vecteur(iw); 227 vb[i]=vecteur(iw); 228 va[i]=vecteur(iw,255); 229 vecteur & wr = *vr[i]._VECTptr; 230 vecteur & wg = *vg[i]._VECTptr; 231 vecteur & wb = *vb[i]._VECTptr; 232 vecteur & wa = *va[i]._VECTptr; 233 for (unsigned j=0;j<iw;++j){ 234 for (unsigned k=0;k<id;++k,++l){ 235 unsigned u=data[l] & 0xff; 236 switch(k){ 237 case 0: 238 wr[j]=int(u); 239 break; 240 case 1: 241 wg[j]=int(u); 242 break; 243 case 2: 244 wb[j]=int(u); 245 break; 246 case 3: 247 wa[j]=int(u); 248 break; 249 } 250 } 251 } 252 } 253 return true; 254 } 255 objet_bidon()256 objet_bidon::objet_bidon(){ 257 // localization code and pointer to RGB image reader 258 if (!giac::readrgb_ptr){ 259 giac::readrgb_ptr=readrgb; 260 #ifdef HAVE_LC_MESSAGES 261 xcas_locale()=getenv("XCAS_LOCALE")?getenv("XCAS_LOCALE"):giac_locale_location; 262 cerr << "// Using locale " << xcas_locale() << '\n'; 263 const char * ptr=setlocale (LC_MESSAGES, ""); 264 if (ptr) 265 cerr << "// " << ptr << '\n'; 266 else 267 cerr << "// setlocale returns 0" << '\n'; 268 #if defined(HAVE_GETTEXT) 269 cerr << "// " << bindtextdomain (PACKAGE, xcas_locale().c_str()) << '\n'; 270 cerr << "// " << textdomain (PACKAGE) << '\n'; 271 cerr << "// " << bind_textdomain_codeset (PACKAGE, "UTF-8") << '\n'; 272 #endif 273 #endif 274 } 275 }; 276 xcas_locale()277 std::string & xcas_locale(){ 278 static string * ans = new string; 279 return * ans; 280 } 281 objet_bidon mon_objet_bidon; 282 // objet_bidon * mon_objet_bidon_ptr=new objet_bidon; 283 284 // New buttons/menus: 285 // row1: z+ up_y up_z 286 // row2: left ortho right 287 // row3: z- down down_z 288 // row4: back forw cfg_menu cb_graph_buttons(Fl_Widget * b,void *)289 void cb_graph_buttons(Fl_Widget * b,void *){ 290 Fl_Group * g = b->parent(); 291 if (!g) return; 292 int i=g->find(b); // position of button inside group of buttons 293 g = g->parent(); // should be mouse_param_group 294 if (!g) return; 295 if (Mouse_Position * mp=dynamic_cast<Mouse_Position *>(g->child(0))){ 296 Graph3d * g3=dynamic_cast<Graph3d *>(mp->graphic); 297 double dh=(mp->graphic->window_ymax-mp->graphic->window_ymin)/10; 298 double dw=(mp->graphic->window_xmax-mp->graphic->window_xmin)/10; 299 double dz=(mp->graphic->window_zmax-mp->graphic->window_zmin)/10; 300 switch (i){ 301 case 0: 302 mp->graphic->zoom(0.707); 303 break; 304 case 1: 305 mp->graphic->up(dh); 306 break; 307 case 2: 308 if (g3) 309 mp->graphic->up_z(dz); 310 else { 311 mp->graphic->zoomy(0.707); 312 mp->graphic->push_cfg(); 313 } 314 break; 315 case 3: 316 mp->graphic->left(dw); 317 break; 318 case 4: 319 if (g3){ 320 g3->below_depth_hidden=!g3->below_depth_hidden; 321 g3->redraw(); 322 } 323 else 324 mp->graphic->orthonormalize(); 325 break; 326 case 5: 327 mp->graphic->right(dw); 328 break; 329 case 6: 330 mp->graphic->zoom(1.414); 331 break; 332 case 7: 333 mp->graphic->down(dh); 334 break; 335 case 8: 336 if (g3) 337 mp->graphic->down_z(dz); 338 else { 339 mp->graphic->zoomy(1.414); 340 mp->graphic->push_cfg(); 341 } 342 break; 343 case 9: 344 mp->graphic->move_cfg(-1); 345 break; 346 case 10: 347 mp->graphic->move_cfg(1); 348 break; 349 case 11: 350 mp->graphic->config(); 351 break; 352 case 12: 353 mp->graphic->paused=!mp->graphic->paused; 354 break; 355 case 13: 356 mp->graphic->autoscale(false); 357 break; 358 } 359 if (Fl_Widget * g=dynamic_cast<Graph2d *>(mp->graphic)) 360 g->redraw(); 361 } 362 } 363 update_infos(const gen & g,GIAC_CONTEXT)364 void Graph2d3d::update_infos(const gen & g,GIAC_CONTEXT){ 365 if (g.type==_VECT && g.subtype==_GRAPH__VECT){ 366 show_axes=false; 367 orthonormalize(); 368 } 369 if (g.is_symb_of_sommet(at_equal)){ 370 // detect a title or a x/y-axis name 371 gen & f = g._SYMBptr->feuille; 372 if (f.type==_VECT && f._VECTptr->size()==2){ 373 gen & optname = f._VECTptr->front(); 374 gen & optvalue= f._VECTptr->back(); 375 if (optname==at_legende && optvalue.type==_VECT){ 376 vecteur & optv=(*optvalue._VECTptr); 377 int optvs=optv.size(); 378 if (optvs>=1) 379 x_axis_unit=printstring(optv[0],contextptr); 380 if (optvs>=2) 381 y_axis_unit=printstring(optv[1],contextptr); 382 if (optvs>=3) 383 z_axis_unit=printstring(optv[2],contextptr); 384 } 385 if (optname.type==_INT_ && optname.subtype == _INT_PLOT){ 386 if (optname.val==_GL_TEXTURE){ 387 if (optvalue.type==_VECT && optvalue._VECTptr->size()==2 && optvalue._VECTptr->front().type==_STRNG && is_undef(optvalue._VECTptr->back())){ 388 // reload cached image 389 optvalue=optvalue._VECTptr->front(); 390 std::map<std::string,std::pair<Fl_Image *,Fl_Image*> *>::iterator it,itend=texture2d_cache.end(); 391 it=texture2d_cache.find(optvalue._STRNGptr->c_str()); 392 if (it!=itend){ 393 std::pair<Fl_Image *,Fl_Image*> * old= it->second; 394 delete old; 395 texture2d_cache.erase(it); 396 } 397 get_texture2d(*optvalue._STRNGptr,background_image); 398 } 399 else { 400 if (optvalue.type==_STRNG){ 401 get_texture2d(*optvalue._STRNGptr,background_image); 402 } 403 else { 404 background_image=0; 405 } 406 } 407 } 408 if (optname.val==_TITLE ) 409 title=printstring(optvalue,contextptr); 410 if (optname.val==_AXES){ 411 if (optvalue.type==_INT_) 412 show_axes=optvalue.val; 413 } 414 if (optname.val==_LABELS && optvalue.type==_VECT){ 415 vecteur & optv=(*optvalue._VECTptr); 416 int optvs=optv.size(); 417 if (optvs>=1) 418 x_axis_name=printstring(optv[0],contextptr); 419 if (optvs>=2) 420 y_axis_name=printstring(optv[1],contextptr); 421 if (optvs>=3) 422 z_axis_name=printstring(optv[2],contextptr); 423 } 424 if (optname.val==_GL_ORTHO && optvalue==1) 425 orthonormalize(); 426 if (optname.val==_GL_X_AXIS_COLOR && optvalue.type==_INT_) 427 x_axis_color=optvalue.val; 428 if (optname.val==_GL_Y_AXIS_COLOR && optvalue.type==_INT_) 429 y_axis_color=optvalue.val; 430 if (optname.val==_GL_Z_AXIS_COLOR && optvalue.type==_INT_) 431 z_axis_color=optvalue.val; 432 if (optname.val>=_GL_X && optname.val<=_GL_Z && optvalue.is_symb_of_sommet(at_interval)){ 433 gen optvf=evalf_double(optvalue._SYMBptr->feuille,1,contextptr); 434 if (optvf.type==_VECT && optvf._VECTptr->size()==2){ 435 gen a=optvf._VECTptr->front(); 436 gen b=optvf._VECTptr->back(); 437 if (a.type==_DOUBLE_ && b.type==_DOUBLE_){ 438 switch (optname.val){ 439 case _GL_X: 440 window_xmin=a._DOUBLE_val; 441 window_xmax=b._DOUBLE_val; 442 break; 443 case _GL_Y: 444 window_ymin=a._DOUBLE_val; 445 window_ymax=b._DOUBLE_val; 446 break; 447 case _GL_Z: 448 window_zmin=a._DOUBLE_val; 449 window_zmax=b._DOUBLE_val; 450 break; 451 } 452 } 453 } 454 } 455 gen optvalf=evalf_double(optvalue,1,contextptr); 456 if (optname.val==_GL_XTICK && optvalf.type==_DOUBLE_) 457 x_tick=optvalf._DOUBLE_val; 458 if (optname.val==_GL_YTICK && optvalf.type==_DOUBLE_) 459 y_tick=optvalf._DOUBLE_val; 460 if (optname.val==_GL_ZTICK && optvalf.type==_DOUBLE_) 461 z_tick=optvalf._DOUBLE_val; 462 if (optname.val==_GL_ANIMATE && optvalf.type==_DOUBLE_) 463 animation_dt=optvalf._DOUBLE_val; 464 if (optname.val==_GL_SHOWAXES && optvalue.type==_INT_) 465 show_axes=optvalue.val; 466 if (optname.val==_GL_SHOWNAMES && optvalue.type==_INT_) 467 show_names=optvalue.val; 468 if (optname.val>=_GL_X_AXIS_NAME && optname.val<=_GL_Z_AXIS_UNIT && optvalue.type==_STRNG){ 469 if (optname.val==_GL_X_AXIS_NAME) x_axis_name=*optvalue._STRNGptr; 470 if (optname.val==_GL_Y_AXIS_NAME) y_axis_name=*optvalue._STRNGptr; 471 if (optname.val==_GL_Z_AXIS_NAME) z_axis_name=*optvalue._STRNGptr; 472 if (optname.val==_GL_X_AXIS_UNIT) x_axis_unit=*optvalue._STRNGptr; 473 if (optname.val==_GL_Y_AXIS_UNIT) y_axis_unit=*optvalue._STRNGptr; 474 if (optname.val==_GL_Z_AXIS_UNIT) z_axis_unit=*optvalue._STRNGptr; 475 } 476 if (optname.val==_GL_QUATERNION && optvalf.type==_VECT && optvalf._VECTptr->size()==4){ 477 vecteur & optvalv=*optvalf._VECTptr; 478 if (optvalv[0].type==_DOUBLE_ && optvalv[1].type==_DOUBLE_ && 479 optvalv[2].type==_DOUBLE_ && optvalv[3].type==_DOUBLE_){ 480 q.x=optvalv[0]._DOUBLE_val; 481 q.y=optvalv[1]._DOUBLE_val; 482 q.z=optvalv[2]._DOUBLE_val; 483 q.w=optvalv[3]._DOUBLE_val; 484 } 485 } 486 if (optname.val==_GL_LOGX && optvalue.type==_INT_){ 487 display_mode &= (0xffff ^ 0x400); 488 if (optvalue.val) 489 display_mode |= 0x400; 490 } 491 if (optname.val==_GL_LOGY && optvalue.type==_INT_){ 492 display_mode &= (0xffff ^ 0x800); 493 if (optvalue.val) 494 display_mode |= 0x800; 495 } 496 if (optname.val==_GL_LOGZ && optvalue.type==_INT_){ 497 display_mode &= (0xffff ^ 0x1000); 498 if (optvalue.val) 499 display_mode |= 0x1000; 500 } 501 if (dynamic_cast<Graph3d *>(this)){ 502 if (optname.val==_GL_ROTATION_AXIS && optvalf.type==_VECT && optvalf._VECTptr->size()==3){ 503 vecteur & optvalv=*optvalf._VECTptr; 504 if (optvalv[0].type==_DOUBLE_ && optvalv[1].type==_DOUBLE_ && 505 optvalv[2].type==_DOUBLE_ ){ 506 rotanim_rx=optvalv[0]._DOUBLE_val; 507 rotanim_ry=optvalv[1]._DOUBLE_val; 508 rotanim_rz=optvalv[2]._DOUBLE_val; 509 } 510 } 511 if (optname.val==_GL_FLAT && optvalue.type==_INT_){ 512 display_mode &= (0xffff ^ 0x10); 513 if (optvalue.val) 514 display_mode |= 0x10; 515 } 516 if (optname.val==_GL_LIGHT && optvalue.type==_INT_){ 517 display_mode &= (0xffff ^ 0x8); 518 if (optvalue.val) 519 display_mode |= 0x8; 520 } 521 if (optname.val==_GL_PERSPECTIVE && optvalue.type==_INT_){ 522 display_mode &= (0xffff ^ 0x4); 523 if (!optvalue.val) 524 display_mode |= 0x4; 525 } 526 // GL_LIGHT_MODEL_COLOR_CONTROL=GL_SEPARATE_SPECULAR_COLOR || GL_SINGLE_COLOR 527 #ifndef WIN32 528 if (optname.val==_GL_LIGHT_MODEL_COLOR_CONTROL && optvalue.type==_INT_) 529 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,optvalue.val); 530 /* GL_LIGHT_MODEL_LOCAL_VIEWER=floating-point value that spec- 531 ifies how specular reflection angles are computed. If params 532 is 0 (or 0.0), specular reflection angles take the view 533 direction to be parallel to and in the direction of the -z 534 axis, regardless of the location of the vertex in eye coordi- 535 nates. Otherwise, specular reflections are computed from the 536 origin of the eye coordinate system. The initial value is 0. */ 537 if (optname.val==_GL_LIGHT_MODEL_LOCAL_VIEWER){ 538 if (optvalf.type==_DOUBLE_) 539 glLightModelf(GL_LIGHT_MODEL_LOCAL_VIEWER,optvalf._DOUBLE_val); 540 } 541 #endif 542 #ifdef HAVE_LIBFLTK_GL 543 /* GL_LIGHT_MODEL_TWO_SIDE = true /false */ 544 if (optname.val==_GL_LIGHT_MODEL_TWO_SIDE && optvalue.type==_INT_){ 545 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE,optvalue.val); 546 } 547 /* GL_LIGHT_MODEL_AMBIENT=[r,g,b,a] */ 548 if (optname.val==_GL_LIGHT_MODEL_AMBIENT && optvalf.type==_VECT && optvalf._VECTptr->size()==4){ 549 vecteur & w=*optvalf._VECTptr; 550 GLfloat tab[4]={(GLfloat)w[0]._DOUBLE_val,(GLfloat)w[1]._DOUBLE_val,(GLfloat)w[2]._DOUBLE_val,(GLfloat)w[3]._DOUBLE_val}; 551 glLightModelfv(GL_LIGHT_MODEL_AMBIENT,tab); 552 } 553 // gl_blend=[d,s] 554 // habituellement gl_blend=[gl_src_alpha,gl_one_minus_src_alpha] 555 if (optname.val==_GL_BLEND){ 556 if (is_zero(optvalue)){ 557 glDisable(GL_BLEND); 558 glEnable(GL_DEPTH_TEST); 559 } 560 else { 561 glDisable(GL_DEPTH_TEST); 562 glEnable(GL_BLEND); 563 if (optvalue.type==_VECT && optvalue._VECTptr->size()==2) 564 glBlendFunc(optvalue._VECTptr->front().val,optvalue._VECTptr->back().val); 565 if (is_minus_one(optvalue)) 566 glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); 567 } 568 } 569 #endif 570 // gl_light0=[option1=value1,...] 571 if (optname.val>=_GL_LIGHT0 && optname.val<=_GL_LIGHT7 && optvalue.type==_VECT){ 572 int j=optname.val-_GL_LIGHT0; 573 // reset light0+j 574 light_x[j]=0;light_y[j]=0;light_z[j]=0;light_w[j]=1; 575 float di=j?0:1; 576 light_diffuse_r[j]=di;light_diffuse_g[j]=di;light_diffuse_b[j]=di;light_diffuse_a[j]=di; 577 light_specular_r[j]=di;light_specular_g[j]=di;light_specular_b[j]=di;light_specular_a[j]=di; 578 light_ambient_r[j]=0;light_ambient_g[j]=0;light_ambient_b[j]=0;light_ambient_a[j]=1; 579 light_spot_x[j]=0;light_spot_y[j]=0;light_spot_z[j]=-1;light_spot_w[j]=0; 580 light_spot_exponent[j]=0;light_spot_cutoff[j]=180; 581 light_0[j]=1;light_1[j]=0;light_2[j]=0; 582 vecteur & optv=*optvalue._VECTptr; 583 for (unsigned i=0;i<optv.size();++i){ 584 gen & optg = optv[i]; 585 if ( (optg.is_symb_of_sommet(at_equal) || optg.is_symb_of_sommet(at_same) ) && optg._SYMBptr->feuille.type==_VECT && g._SYMBptr->feuille._VECTptr->size()==2){ 586 gen & optgname = optg._SYMBptr->feuille._VECTptr->front(); 587 gen optgval = evalf_double(optg._SYMBptr->feuille._VECTptr->back(),1,contextptr); 588 bool vect4=optgval.type==_VECT && optgval._VECTptr->size()==4; 589 vecteur xyzw; 590 if (vect4) 591 xyzw=*optgval._VECTptr; 592 switch (optgname.val){ 593 case _GL_AMBIENT: 594 light_ambient_r[j]=xyzw[0]._DOUBLE_val; 595 light_ambient_g[j]=xyzw[1]._DOUBLE_val; 596 light_ambient_b[j]=xyzw[2]._DOUBLE_val; 597 light_ambient_a[j]=xyzw[3]._DOUBLE_val; 598 break; 599 case _GL_SPECULAR: 600 light_specular_r[j]=xyzw[0]._DOUBLE_val; 601 light_specular_g[j]=xyzw[1]._DOUBLE_val; 602 light_specular_b[j]=xyzw[2]._DOUBLE_val; 603 light_specular_a[j]=xyzw[3]._DOUBLE_val; 604 break; 605 case _GL_DIFFUSE: 606 light_diffuse_r[j]=xyzw[0]._DOUBLE_val; 607 light_diffuse_g[j]=xyzw[1]._DOUBLE_val; 608 light_diffuse_b[j]=xyzw[2]._DOUBLE_val; 609 light_diffuse_a[j]=xyzw[3]._DOUBLE_val; 610 break; 611 case _GL_POSITION: 612 light_x[j]=xyzw[0]._DOUBLE_val; 613 light_y[j]=xyzw[1]._DOUBLE_val; 614 light_z[j]=xyzw[2]._DOUBLE_val; 615 light_w[j]=xyzw[3]._DOUBLE_val; 616 break; 617 case _GL_SPOT_DIRECTION: 618 light_spot_x[j]=xyzw[0]._DOUBLE_val; 619 light_spot_y[j]=xyzw[1]._DOUBLE_val; 620 light_spot_z[j]=xyzw[2]._DOUBLE_val; 621 light_spot_w[j]=xyzw[3]._DOUBLE_val; 622 break; 623 case _GL_SPOT_EXPONENT: 624 light_spot_exponent[j]=optgval._DOUBLE_val; 625 break; 626 case _GL_SPOT_CUTOFF: 627 light_spot_cutoff[j]=optgval._DOUBLE_val; 628 break; 629 case _GL_CONSTANT_ATTENUATION: 630 light_0[j]=optgval._DOUBLE_val; 631 break; 632 case _GL_LINEAR_ATTENUATION: 633 light_1[j]=optgval._DOUBLE_val; 634 break; 635 case _GL_QUADRATIC_ATTENUATION: 636 light_2[j]=optgval._DOUBLE_val; 637 break; 638 } 639 } 640 ; 641 } // end for i 642 } 643 } // end opengl options 644 } 645 } 646 } 647 if (g.type==_VECT){ 648 const_iterateur it=g._VECTptr->begin(),itend=g._VECTptr->end(); 649 for (;it!=itend;++it) 650 update_infos(*it,contextptr); 651 } 652 } 653 move_cfg(int i)654 void Graph2d3d::move_cfg(int i){ 655 if (history.empty()) return; 656 int j=i+history_pos; 657 int s=history.size(); 658 if (j>s) j=s; 659 if (j<1) j=1; 660 history_pos=j; 661 window_xyz & h = history[j-1]; 662 window_xmin=h.xmin; 663 window_xmax=h.xmax; 664 window_ymin=h.ymin; 665 window_ymax=h.ymax; 666 window_zmin=h.zmin; 667 window_zmax=h.zmax; 668 } 669 push_cfg()670 void Graph2d3d::push_cfg(){ 671 int s=history.size(); 672 if (history_pos<s && history_pos>=0){ 673 history.erase(history.begin()+history_pos,history.end()); 674 } 675 history.push_back(window_xyz(window_xmin,window_xmax,window_ymin,window_ymax,window_zmin,window_zmax)); 676 history_pos=history.size(); 677 } 678 clear_cfg()679 void Graph2d3d::clear_cfg(){ 680 history_pos=0; 681 history.clear(); 682 } 683 find_xyz(double i,double j,double k,double & x,double & y,double & z)684 void Graph2d3d::find_xyz(double i,double j,double k,double &x,double&y,double &z){ 685 x=i; y=j; z=k; 686 } 687 find_xy(double i,double j,double & x,double & y) const688 void Graph2d::find_xy(double i,double j,double & x,double & y) const { 689 x=window_xmin+i*(window_xmax-window_xmin)/(w()-(show_axes?ylegende*labelsize():0)); 690 y=window_ymax-j*(window_ymax-window_ymin)/(h()-(show_axes?((title.empty()?1:2)*labelsize()):0)); 691 } 692 find_xyz(double i,double j,double k,double & x,double & y,double & z)693 void Graph2d::find_xyz(double i,double j,double k,double & x,double & y,double & z) { 694 z=k; 695 find_xy(i,j,x,y); 696 } 697 in_find_graph2d3d(Fl_Widget * wid)698 Graph2d3d * in_find_graph2d3d(Fl_Widget * wid){ 699 if (Graph2d3d * g=dynamic_cast<Graph2d3d *>(wid)) 700 return g; 701 if (Fl_Group * gr =dynamic_cast<Fl_Group *>(wid)){ 702 // search in children 703 int n=gr->children(); 704 for (int i=0;i<n;++i){ 705 if (Graph2d3d * res = in_find_graph2d3d(gr->child(i))) 706 return res; 707 } 708 } 709 return 0; 710 } 711 find_graph2d3d(Fl_Widget * wid)712 Graph2d3d * find_graph2d3d(Fl_Widget * wid){ 713 if (!wid) return 0; 714 if (Graph2d3d * res = dynamic_cast<Graph2d3d *>(Fl::focus()) ) 715 return res; 716 if (Graph2d3d * res=in_find_graph2d3d(wid)) 717 return res; 718 return find_graph2d3d(wid->parent()); 719 } 720 cb_Graph2d3d_LaTeX_Preview(Fl_Menu_ * m,void *)721 static void cb_Graph2d3d_LaTeX_Preview(Fl_Menu_* m , void*) { 722 const char * filename=find_graph2d3d(m)->latex(0); 723 if (filename) 724 xdvi(filename); 725 } 726 cb_Graph2d3d_LaTeX_Print(Fl_Menu_ * m,void *)727 static void cb_Graph2d3d_LaTeX_Print(Fl_Menu_* m , void*) { 728 const char * filename=find_graph2d3d(m)->latex(0); 729 if (filename) 730 dvips(filename); 731 } 732 cb_Graph2d3d_Print(Fl_Menu_ * m,void *)733 static void cb_Graph2d3d_Print(Fl_Menu_* m , void*) { 734 Graph2d3d * gr = find_graph2d3d(m); 735 if (gr) 736 widget_print(gr); 737 } 738 cb_Graph2d3d_Preview(Fl_Menu_ * m,void *)739 static void cb_Graph2d3d_Preview(Fl_Menu_* m , void*) { 740 Graph2d3d * gr = find_graph2d3d(m); 741 if (gr) 742 widget_ps_print(gr,gr->title,true); 743 } 744 cb_Graph3dpng(Fl_Menu_ * m,void *)745 static void cb_Graph3dpng(Fl_Menu_* m , void*) { 746 Graph2d3d * gr = find_graph2d3d(m); 747 if (Graph3d * gr3 = dynamic_cast<Graph3d *>(gr)){ 748 char * filename = file_chooser(gettext("Export to PNG file"),"*.png","session.png"); 749 if(!filename) return; 750 gr3->opengl2png(filename); 751 } 752 } 753 cb_Graph2d3d_Autoscale(Fl_Menu_ * m,void *)754 static void cb_Graph2d3d_Autoscale(Fl_Menu_* m , void*) { 755 Graph2d3d * gr = find_graph2d3d(m); 756 if (gr) 757 gr->autoscale(false); 758 } 759 cb_Graph2d3d_AutoscaleFull(Fl_Menu_ * m,void *)760 static void cb_Graph2d3d_AutoscaleFull(Fl_Menu_* m , void*) { 761 Graph2d3d * gr = find_graph2d3d(m); 762 if (gr) 763 gr->autoscale(true); 764 } 765 cb_Graph2d3d_Orthonormalize(Fl_Menu_ * m,void *)766 static void cb_Graph2d3d_Orthonormalize(Fl_Menu_* m , void*) { 767 Graph2d3d * gr = find_graph2d3d(m); 768 if (gr) 769 gr->orthonormalize(); 770 } 771 cb_Graph2d3d_Next(Fl_Menu_ * m,void *)772 static void cb_Graph2d3d_Next(Fl_Menu_* m , void*) { 773 Graph2d3d * gr = find_graph2d3d(m); 774 if (gr) 775 gr->move_cfg(1); 776 } 777 cb_Graph2d3d_Previous(Fl_Menu_ * m,void *)778 static void cb_Graph2d3d_Previous(Fl_Menu_* m , void*) { 779 Graph2d3d * gr = find_graph2d3d(m); 780 if (gr) 781 gr->move_cfg(-1); 782 } 783 cb_Graph2d3d_Zoomout(Fl_Menu_ * m,void *)784 static void cb_Graph2d3d_Zoomout(Fl_Menu_* m , void*) { 785 Graph2d3d * gr = find_graph2d3d(m); 786 if (gr) 787 gr->zoom(1.414); 788 } 789 cb_Graph2d3d_Zoomin(Fl_Menu_ * m,void *)790 static void cb_Graph2d3d_Zoomin(Fl_Menu_* m , void*) { 791 Graph2d3d * gr = find_graph2d3d(m); 792 if (gr) 793 gr->zoom(0.707); 794 } 795 cb_Graph2d3d_Config(Fl_Menu_ * m,void *)796 static void cb_Graph2d3d_Config(Fl_Menu_* m , void*) { 797 Graph2d3d * gr = find_graph2d3d(m); 798 if (gr) 799 gr->config(); 800 } 801 cb_Graph2d3d_Pause(Fl_Menu_ * m,void *)802 static void cb_Graph2d3d_Pause(Fl_Menu_* m , void*) { 803 Graph2d3d * gr = find_graph2d3d(m); 804 if (gr) 805 gr->paused=true; 806 } 807 cb_Graph2d3d_Stop(Fl_Menu_ * m,void *)808 static void cb_Graph2d3d_Stop(Fl_Menu_* m , void*) { 809 Graph2d3d * gr = find_graph2d3d(m); 810 if (gr){ 811 gr->animation_dt=0; 812 gr->animation_instructions_pos=0; 813 } 814 } 815 cb_Graph2d3d_Restart(Fl_Menu_ * m,void *)816 static void cb_Graph2d3d_Restart(Fl_Menu_* m , void*) { 817 Graph2d3d * gr = find_graph2d3d(m); 818 if (gr) 819 gr->paused=false; 820 } 821 cb_Graph2d3d_Faster(Fl_Menu_ * m,void *)822 static void cb_Graph2d3d_Faster(Fl_Menu_* m , void*) { 823 Graph2d3d * gr = find_graph2d3d(m); 824 if (gr){ 825 if (gr->animation_dt) 826 gr->animation_dt /= 2; 827 else 828 gr->animation_dt = 0.2; 829 } 830 } 831 cb_Graph2d3d_Slower(Fl_Menu_ * m,void *)832 static void cb_Graph2d3d_Slower(Fl_Menu_* m , void*) { 833 Graph2d3d * gr = find_graph2d3d(m); 834 if (gr){ 835 if (gr->animation_dt) 836 gr->animation_dt *= 2; 837 else 838 gr->animation_dt = 0.2; 839 } 840 } 841 cb_Graph2d3d_hide(Fl_Menu_ * m,void *)842 static void cb_Graph2d3d_hide(Fl_Menu_* m , void*) { 843 Graph2d3d * gr = find_graph2d3d(m); 844 if (Graph3d * gr3 = dynamic_cast<Graph3d *>(gr)){ 845 gr3->below_depth_hidden=true; 846 gr3->redraw(); 847 } 848 } 849 cb_Graph2d3d_show(Fl_Menu_ * m,void *)850 static void cb_Graph2d3d_show(Fl_Menu_* m , void*) { 851 Graph2d3d * gr = find_graph2d3d(m); 852 if (Graph3d * gr3 = dynamic_cast<Graph3d *>(gr)){ 853 gr3->below_depth_hidden=false; 854 gr3->redraw(); 855 } 856 } 857 cb_Graph2d3d_startview(Fl_Menu_ * m,void *)858 static void cb_Graph2d3d_startview(Fl_Menu_* m , void*) { 859 Graph2d3d * gr = find_graph2d3d(m); 860 if (Graph3d * gr3 = dynamic_cast<Graph3d *>(gr)){ 861 gr3->theta_x=-13; 862 gr3->theta_y=-95; 863 gr3->theta_z=-110; 864 gr3->q=euler_deg_to_quaternion_double(gr3->theta_z,gr3->theta_x,gr3->theta_y); 865 gr3->redraw(); 866 } 867 } 868 cb_Graph2d3d_xview(Fl_Menu_ * m,void *)869 static void cb_Graph2d3d_xview(Fl_Menu_* m , void*) { 870 Graph2d3d * gr = find_graph2d3d(m); 871 if (Graph3d * gr3 = dynamic_cast<Graph3d *>(gr)){ 872 gr3->theta_x=0; 873 gr3->theta_y=-90; 874 gr3->theta_z=-90; 875 gr3->q=euler_deg_to_quaternion_double(gr3->theta_z,gr3->theta_x,gr3->theta_y); 876 gr3->redraw(); 877 } 878 } 879 cb_Graph2d3d_yview(Fl_Menu_ * m,void *)880 static void cb_Graph2d3d_yview(Fl_Menu_* m , void*) { 881 Graph2d3d * gr = find_graph2d3d(m); 882 if (Graph3d * gr3 = dynamic_cast<Graph3d *>(gr)){ 883 gr3->theta_x=0; 884 gr3->theta_y=-90; 885 gr3->theta_z=0; 886 gr3->q=euler_deg_to_quaternion_double(gr3->theta_z,gr3->theta_x,gr3->theta_y); 887 gr3->redraw(); 888 } 889 } 890 cb_Graph2d3d_zview(Fl_Menu_ * m,void *)891 static void cb_Graph2d3d_zview(Fl_Menu_* m , void*) { 892 Graph2d3d * gr = find_graph2d3d(m); 893 if (Graph3d * gr3 = dynamic_cast<Graph3d *>(gr)){ 894 gr3->theta_x=0; 895 gr3->theta_y=0; 896 gr3->theta_z=0; 897 gr3->q=euler_deg_to_quaternion_double(gr3->theta_z,gr3->theta_x,gr3->theta_y); 898 gr3->redraw(); 899 } 900 } 901 cb_Graph2d3d_mouse_plan(Fl_Menu_ * m,void *)902 static void cb_Graph2d3d_mouse_plan(Fl_Menu_* m , void*) { 903 if (!Fl::focus()) 904 return; 905 Graph2d3d * gr = find_graph2d3d(m); 906 if (Graph3d * gr3d = dynamic_cast<Graph3d *>(gr)){ 907 double a,b,c; 908 gr3d->current_normal(a,b,c); 909 gr3d->normal2plan(a,b,c); // divides a,b,c by dx^2,... 910 double x0,y0,z0,t0; 911 gr3d->find_xyz(gr3d->x()+gr3d->w()/2,gr3d->y()+gr3d->h()/2,gr3d->depth,x0,y0,z0); 912 t0=a*x0+b*y0+c*z0; 913 if (std::abs(t0)<std::abs(gr3d->window_zmax-gr3d->window_zmin)/1000) 914 t0=0; 915 string s="plan("+print_DOUBLE_(a)+"*x+"+print_DOUBLE_(b)+"*y+"+print_DOUBLE_(c)+"*z="+print_DOUBLE_(t0)+")"; 916 in_Xcas_input_char(Fl::focus(),s,' '); 917 } 918 } 919 920 // image of (x,y,z) by rotation around axis r(rx,ry,rz) of angle theta rotate(double rx,double ry,double rz,double theta,double x,double y,double z,double & X,double & Y,double & Z)921 void rotate(double rx,double ry,double rz,double theta,double x,double y,double z,double & X,double & Y,double & Z){ 922 /* 923 quaternion_double q=rotation_2_quaternion_double(rx,ry,rz,theta); 924 quaternion_double qx(x,y,z,0); 925 quaternion_double qX=conj(q)*qx*q; 926 */ 927 // r(rx,ry,rz) the axis, v(x,y,z) projects on w=a*r with a such that 928 // w.r=a*r.r=v.r 929 double r2=rx*rx+ry*ry+rz*rz; 930 double r=std::sqrt(r2); 931 double a=(rx*x+ry*y+rz*z)/r2; 932 // v=w+V, w remains stable, V=v-w=v-a*r rotates 933 // Rv=w+RV, where RV=cos(theta)*V+sin(theta)*(r cross V)/sqrt(r2) 934 double Vx=x-a*rx,Vy=y-a*ry,Vz=z-a*rz; 935 // cross product of k with V 936 double kVx=ry*Vz-rz*Vy, kVy=rz*Vx-rx*Vz,kVz=rx*Vy-ry*Vx; 937 double c=std::cos(theta),s=std::sin(theta); 938 X=a*rx+c*Vx+s*kVx/r; 939 Y=a*ry+c*Vy+s*kVy/r; 940 Z=a*rz+c*Vz+s*kVz/r; 941 } 942 943 // type -1 = view point rotation around an axis, 944 // type bit 0 to 7: spot rotation 945 // step is in degree; tstep in seconds 946 // [0,0,0],[rx,ry,rz] axis of the rotation oxyz_rotate(Graph2d3d * gr,int type,int nstep,double tstep,int danim,double rx,double ry,double rz)947 void oxyz_rotate(Graph2d3d* gr,int type,int nstep,double tstep,int danim,double rx,double ry,double rz){ 948 static Fl_Window * w = 0; 949 static Fl_Button * button = 0; 950 if (!w){ 951 Fl_Group::current(0); 952 w=new Fl_Window(100,24); 953 button = new Fl_Button(2,2,w->w()-4,w->h()-4); 954 button->label(gettext("Cancel")); 955 w->label(gettext("Rotate Animation")); 956 w->end(); 957 } 958 if (Graph3d * gr3 = dynamic_cast<Graph3d *>(gr)){ 959 w->set_modal(); 960 w->show(); 961 w->hotspot(w); 962 Fl::focus(button); 963 double step=2*M_PI/nstep,lx[8],ly[8],lz[8],lX,lY,lZ; 964 quaternion_double qsave(gr3->q); 965 for (int j=0;j<8;++j){ 966 lx[j]=gr3->light_x[j]; 967 ly[j]=gr3->light_y[j]; 968 lz[j]=gr3->light_z[j]; 969 } 970 for (int i=1;i<nstep;++i){ 971 double theta=step*i; 972 // type 0 to 7, rotate light by theta 973 for (int j=0;j<8;++j){ 974 if (type & (1<<j)){ 975 rotate(rx,ry,rz,theta,lx[j],ly[j],lz[j],lX,lY,lZ); 976 // cerr << theta << ":" << lX << "," << lY << "," << lZ << '\n'; 977 gr3->light_x[j]=lX; 978 gr3->light_y[j]=lY; 979 gr3->light_z[j]=lZ; 980 } 981 } 982 if (type & (1<<8)) 983 gr3->q=qsave*rotation_2_quaternion_double(rx,ry,rz,theta*180/M_PI); 984 gr3->animation_instructions_pos+=danim; 985 gr3->redraw(); 986 int nwait=int(tstep/0.001),jwait; 987 if (nwait<=0) 988 nwait=1; 989 for (jwait=0;jwait<nwait;++jwait){ 990 Fl_Widget *o = Fl::readqueue(); 991 if (o==button || o==w) 992 break; 993 else { 994 Fl::wait(0.0001); 995 usleep(1000); 996 } 997 } 998 if (jwait<nwait) 999 break; 1000 } // end animation for 1001 w->hide(); 1002 for (int j=0;j<8;++j){ 1003 gr3->light_x[j]=lx[j]; 1004 gr3->light_y[j]=ly[j]; 1005 gr3->light_z[j]=lz[j]; 1006 } 1007 gr3->q=qsave; 1008 gr3->animation_instructions_pos+=danim; 1009 gr3->redraw(); 1010 } 1011 } 1012 cb_Graph2d3d_rotate(Fl_Menu_ * m,void *)1013 static void cb_Graph2d3d_rotate(Fl_Menu_* m , void*) { 1014 if (!Fl::focus()) 1015 return; 1016 Graph2d3d * gr = find_graph2d3d(m); 1017 // control window for args of oxyz_rotate 1018 oxyz_rotate(gr,gr->rotanim_type,gr->rotanim_nstep,gr->rotanim_tstep,gr->rotanim_danim,gr->rotanim_rx,gr->rotanim_ry,gr->rotanim_rz); 1019 } 1020 cb_Graph_Traceclear(Fl_Widget * m,void *)1021 static void cb_Graph_Traceclear(Fl_Widget * m , void*) { 1022 Graph2d3d * gr = find_graph2d3d(m); 1023 if (gr){ 1024 gr->trace_instructions.clear(); 1025 gr->redraw(); 1026 } 1027 } 1028 do_find_figure(Fl_Widget * widget)1029 Figure * do_find_figure(Fl_Widget * widget){ 1030 Fl_Widget * gr = widget; 1031 for (;gr;gr=gr->parent()){ 1032 Figure * f =dynamic_cast<Figure *>(gr); 1033 if (f) 1034 return f; 1035 } 1036 return 0; 1037 } 1038 find_figure(Fl_Widget * widget)1039 Figure * find_figure(Fl_Widget * widget){ 1040 Figure * gr = do_find_figure(widget); 1041 if (gr) 1042 return gr; 1043 gr=do_find_figure(Fl::focus()); 1044 //if (!gr) 1045 // fl_alert("%s","No figure found. Please click in or add one"); 1046 return gr; 1047 } 1048 cb_Graph_Traceobject(Fl_Widget * m,void *)1049 static void cb_Graph_Traceobject(Fl_Widget * m , void*) { 1050 Fl_Widget * wid=Fl::focus(); 1051 Figure * f=find_figure(m); 1052 if (f){ 1053 const char * ch=fl_input(gettext("Trace which object?")); 1054 if (ch){ 1055 History_Pack * hp=f->geo->hp; 1056 if (!hp) 1057 return; 1058 int pos; 1059 if (hp!=get_history_pack(wid,pos)) 1060 pos=hp->children()-1; 1061 hp->add_entry(pos); 1062 string arg="trace("+string(ch)+")"; 1063 hp->set_value(pos,arg,true); 1064 } 1065 } 1066 } 1067 cb_Graph_Traceon(Fl_Widget * m,void *)1068 static void cb_Graph_Traceon(Fl_Widget * m , void*) { 1069 Graph2d3d * gr = find_graph2d3d(m); 1070 if (gr){ 1071 gr->display_mode |= 0x40; // set bit 6 1072 gr->redraw(); 1073 } 1074 } 1075 cb_Graph_Traceoff(Fl_Widget * m,void *)1076 static void cb_Graph_Traceoff(Fl_Widget * m , void*) { 1077 Graph2d3d * gr = find_graph2d3d(m); 1078 if (gr){ 1079 gr->display_mode &= (0xffff ^ 0x40);; // clear bit 6 1080 gr->redraw(); 1081 } 1082 } 1083 cb_Graph_Graphon(Fl_Widget * m,void *)1084 static void cb_Graph_Graphon(Fl_Widget * m , void*) { 1085 Graph2d3d * gr = find_graph2d3d(m); 1086 if (gr){ 1087 gr->display_mode |= 0x1; // set bit 0 1088 gr->redraw(); 1089 } 1090 } 1091 cb_Graph_Graphoff(Fl_Widget * m,void *)1092 static void cb_Graph_Graphoff(Fl_Widget * m , void*) { 1093 Graph2d3d * gr = find_graph2d3d(m); 1094 if (gr){ 1095 gr->display_mode &= (0xffff ^ 0x1); // clear bit 0 1096 gr->redraw(); 1097 } 1098 } 1099 cb_Graph2d3d_Frameoff(Fl_Widget * m,void *)1100 static void cb_Graph2d3d_Frameoff(Fl_Widget * m , void*) { 1101 Graph2d3d * gr = find_graph2d3d(m); 1102 if (gr){ 1103 gr->display_mode |= 0x80; // set bit 6 1104 gr->redraw(); 1105 } 1106 } 1107 cb_Graph2d3d_Frameon(Fl_Widget * m,void *)1108 static void cb_Graph2d3d_Frameon(Fl_Widget * m , void*) { 1109 Graph2d3d * gr = find_graph2d3d(m); 1110 if (gr){ 1111 gr->display_mode &= (0xffff ^ 0x80);; // clear bit 6 1112 gr->redraw(); 1113 } 1114 } 1115 cb_Graph_Animate(Fl_Widget * m,void *)1116 static void cb_Graph_Animate(Fl_Widget * m , void*) { 1117 Graph2d3d * gr = find_graph2d3d(m); 1118 if (gr){ 1119 const char * ch=fl_input(gettext("Frames number? (>0 forward, <0 forward+backward)"),"10"); 1120 if (ch){ 1121 int n=atoi(ch); 1122 gr->animation_instructions=gr->animate(n); 1123 if (gr->animation_instructions.empty()) 1124 fl_alert("%s",gettext("Figure must depend on a parameter (Edit->Add parameter)")); 1125 gr->paused=false; 1126 gr->animation_dt=0.1; 1127 gr->display_mode |= 0x2; // set bit 1 1128 gr->redraw(); 1129 } 1130 } 1131 } 1132 cb_Graph_Unanimate(Fl_Widget * m,void *)1133 static void cb_Graph_Unanimate(Fl_Widget * m , void*) { 1134 Graph2d3d * gr = find_graph2d3d(m); 1135 if (gr){ 1136 gr->animation_instructions.clear(); 1137 gr->paused=false; 1138 gr->animation_dt=0; 1139 gr->display_mode &= (0xffff ^ 0x2);; // clear bit 1 1140 gr->redraw(); 1141 } 1142 } 1143 1144 Fl_Menu_Item Autoscale_menu[] = { 1145 {gettext("auto"), 0, 0, 0, 64, 0, 0, 14, 56}, 1146 {gettext("Autoscale"), 0, (Fl_Callback*)cb_Graph2d3d_Autoscale, 0, 0, 0, 0, 14, 56}, 1147 {gettext("Autoscale (full)"), 0, (Fl_Callback*)cb_Graph2d3d_AutoscaleFull, 0, 0, 0, 0, 14, 56}, 1148 {0}, 1149 {0} 1150 }; 1151 1152 Fl_Menu_Item Graph2d3d_menu[] = { 1153 {gettext("M"), 0, 0, 0, 64, 0, 0, 14, 56}, 1154 {gettext("View"), 0, 0, 0, 64, 0, 0, 14, 56}, 1155 {gettext("Autoscale"), 0, (Fl_Callback*)cb_Graph2d3d_Autoscale, 0, 0, 0, 0, 14, 56}, 1156 {gettext("Autoscale (full)"), 0, (Fl_Callback*)cb_Graph2d3d_AutoscaleFull, 0, 0, 0, 0, 14, 56}, 1157 {gettext("Orthonormalize (2-d)"), 0, (Fl_Callback*)cb_Graph2d3d_Orthonormalize, 0, 0, 0, 0, 14, 56}, 1158 {gettext("Zoom in"), 0, (Fl_Callback*)cb_Graph2d3d_Zoomin, 0, 0, 0, 0, 14, 56}, 1159 {gettext("Zoom out"), 0, (Fl_Callback*)cb_Graph2d3d_Zoomout, 0, 0, 0, 0, 14, 56}, 1160 {gettext("Frame move on"), 0, (Fl_Callback*)cb_Graph2d3d_Frameon, 0, 0, 0, 0, 14, 56}, 1161 {gettext("Frame move off"), 0, (Fl_Callback*)cb_Graph2d3d_Frameoff, 0, 0, 0, 0, 14, 56}, 1162 {gettext("Previous"), 0, (Fl_Callback*)cb_Graph2d3d_Previous, 0, 0, 0, 0, 14, 56}, 1163 {gettext("Next"), 0, (Fl_Callback*)cb_Graph2d3d_Next, 0, 0, 0, 0, 14, 56}, 1164 {gettext("Config"), 0, (Fl_Callback*)cb_Graph2d3d_Config, 0, 0, 0, 0, 14, 56}, 1165 {0}, 1166 {gettext("Trace"), 0, 0, 0, 64, 0, 0, 14, 56}, 1167 {gettext("Trace clear"), 0, (Fl_Callback *) cb_Graph_Traceclear, 0, 0, 0, 0, 14, 56}, 1168 {gettext("Trace on"), 0, (Fl_Callback *) cb_Graph_Traceon, 0, 0, 0, 0, 14, 56}, 1169 {gettext("Trace off"), 0, (Fl_Callback *) cb_Graph_Traceoff, 0, 0, 0, 0, 14, 56}, 1170 {gettext("Trace object"), 0, (Fl_Callback *) cb_Graph_Traceobject, 0, 0, 0, 0, 14, 56}, 1171 {0}, 1172 {gettext("Animation"), 0, 0, 0, 64, 0, 0, 14, 56}, 1173 {gettext("Pause"), 0, (Fl_Callback*)cb_Graph2d3d_Pause, 0, 0, 0, 0, 14, 56}, 1174 {gettext("Stop"), 0, (Fl_Callback*)cb_Graph2d3d_Stop, 0, 0, 0, 0, 14, 56}, 1175 {gettext("Restart"), 0, (Fl_Callback*)cb_Graph2d3d_Restart, 0, 0, 0, 0, 14, 56}, 1176 {gettext("Faster (2x)"), 0, (Fl_Callback*)cb_Graph2d3d_Faster, 0, 0, 0, 0, 14, 56}, 1177 {gettext("Slower (2x)"), 0, (Fl_Callback*)cb_Graph2d3d_Slower, 0, 0, 0, 0, 14, 56}, 1178 {gettext("Build animation"), 0, (Fl_Callback *) cb_Graph_Animate, 0, 0, 0, 0, 14, 56}, 1179 {gettext("Unanimate"), 0, (Fl_Callback *) cb_Graph_Unanimate, 0, 0, 0, 0, 14, 56}, 1180 {gettext("Graph on"), 0, (Fl_Callback *) cb_Graph_Graphon, 0, 0, 0, 0, 14, 56}, 1181 {gettext("Graph off"), 0, (Fl_Callback *) cb_Graph_Graphoff, 0, 0, 0, 0, 14, 56}, 1182 {0}, 1183 {gettext("3-d"), 0, 0, 0, 64, 0, 0, 14, 56}, 1184 {gettext("Mouse plane equation"), 0, (Fl_Callback*)cb_Graph2d3d_mouse_plan, 0, 0, 0, 0, 14, 56}, 1185 {gettext("Oyz view (x=cst=depth)"), 0, (Fl_Callback*)cb_Graph2d3d_xview, 0, 0, 0, 0, 14, 56}, 1186 {gettext("Oxz view (y=cst=depth)"), 0, (Fl_Callback*)cb_Graph2d3d_yview, 0, 0, 0, 0, 14, 56}, 1187 {gettext("Upper view (z=cst=depth)"), 0, (Fl_Callback*)cb_Graph2d3d_zview, 0, 0, 0, 0, 14, 56}, 1188 {gettext("Default view"), 0, (Fl_Callback*)cb_Graph2d3d_startview, 0, 0, 0, 0, 14, 56}, 1189 {gettext("Rotate animation"), 0, (Fl_Callback*)cb_Graph2d3d_rotate, 0, 0, 0, 0, 14, 56}, 1190 {gettext("Hide below depth"), 0, (Fl_Callback*)cb_Graph2d3d_hide, 0, 0, 0, 0, 14, 56}, 1191 {gettext("Show below depth"), 0, (Fl_Callback*)cb_Graph2d3d_show, 0, 0, 0, 0, 14, 56}, 1192 {0}, // end 3-d 1193 {gettext("Export Print"), 0, 0, 0, 64, 0, 0, 14, 56}, 1194 {gettext("EPS PNG and preview"), 0, (Fl_Callback*)cb_Graph2d3d_Preview, 0, 0, 0, 0, 14, 56}, 1195 {gettext("3-d to PNG"), 0, (Fl_Callback*)cb_Graph3dpng, 0, 0, 0, 0, 14, 56}, 1196 {gettext("Print"), 0, (Fl_Callback*)cb_Graph2d3d_Print, 0, 0, 0, 0, 14, 56}, 1197 {gettext("Preview (with Latex)"), 0, (Fl_Callback*)cb_Graph2d3d_LaTeX_Preview, 0, 0, 0, 0, 14, 56}, 1198 {gettext("Print (with Latex)"), 0, (Fl_Callback*)cb_Graph2d3d_LaTeX_Print, 0, 0, 0, 0, 14, 56}, 1199 {0}, 1200 {0}, 1201 {0} 1202 }; 1203 add_mouse_param_group(int x,int y,int w,int h)1204 void Graph2d3d::add_mouse_param_group(int x,int y,int w,int h){ 1205 Fl_Group * group = parent(); 1206 if (!group) return; 1207 bool is3d=dynamic_cast<Graph3d *>(this); 1208 Fl_Group::current(group); 1209 labelsize(group->labelsize()); 1210 // mouse_param_group=new Fl_Tile(x+w-legende_size,y,legende_size,h); 1211 mouse_param_group=new Fl_Group(x+w-legende_size,y,legende_size,h); 1212 mouse_param_group->box(FL_FLAT_BOX); 1213 mouse_position=new Mouse_Position(x+w-legende_size,y,legende_size,(is3d?3:2)*labelsize(),this); 1214 int bx=x+w-legende_size,by=y+mouse_position->h(),bw=legende_size/3,bh=min(group->labelsize()+3,h/8); 1215 button_group = new Fl_Group(bx,by,legende_size,5*bh); 1216 // Buttons 1217 Fl_Button * bzoomin = new Fl_Button(bx,by,bw,bh,"in"); 1218 bzoomin->tooltip(gettext("Zoom in")); 1219 bzoomin->callback(cb_graph_buttons); 1220 Fl_Button * bup = new Fl_Button(bx+bw,by,bw,bh,"@-18"); 1221 bup->color(y_axis_color); 1222 bup->tooltip(gettext("Increase y")); 1223 bup->callback(cb_graph_buttons); 1224 Fl_Button * bupright = new Fl_Button(bx+2*bw,by,bw,bh,"@-18"); 1225 bupright->color(z_axis_color); 1226 bupright->tooltip(gettext("Increase z (3-d)/Zoom in for y (2-d)")); 1227 bupright->callback(cb_graph_buttons); 1228 by += bh; 1229 Fl_Button * bleft = new Fl_Button(bx,by,bw,bh,"@-1<-"); 1230 bleft->when(FL_WHEN_RELEASE); 1231 bleft->color(x_axis_color); 1232 bleft->tooltip(gettext("Decrease x")); 1233 bleft->callback(cb_graph_buttons); 1234 Fl_Button * bortho = new Fl_Button(bx+bw,by,bw,bh,"_|_"); 1235 bortho->tooltip(gettext(is3d?"Hide or show below depth":"Orthonormalize")); 1236 bortho->callback(cb_graph_buttons); 1237 Fl_Button * bright = new Fl_Button(bx+2*bw,by,bw,bh,"@-1->"); 1238 bright->color(x_axis_color); 1239 bright->tooltip(gettext("Increase x")); 1240 bright->callback(cb_graph_buttons); 1241 by += bh; 1242 Fl_Button * bzoomout = new Fl_Button(bx,by,bw,bh,"out"); 1243 bzoomout->tooltip(gettext("Zoom out")); 1244 bzoomout->callback(cb_graph_buttons); 1245 Fl_Button * bdown = new Fl_Button(bx+bw,by,bw,bh,"@-12"); 1246 bdown->color(y_axis_color); 1247 bdown->tooltip(gettext("Decrease y")); 1248 bdown->callback(cb_graph_buttons); 1249 Fl_Button * bdownright = new Fl_Button(bx+2*bw,by,bw,bh,"@-12"); 1250 bdownright->color(z_axis_color); 1251 bdownright->tooltip(gettext("Decrease z (3-d)/Zoom out in y (2-d)")); 1252 bdownright->callback(cb_graph_buttons); 1253 by += bh; 1254 Fl_Button * bback = new Fl_Button(bx,by,bw,bh,"@-1<-"); 1255 bback->tooltip(gettext("Back in cfg history")); 1256 bback->callback(cb_graph_buttons); 1257 Fl_Button * bforw = new Fl_Button(bx+bw,by,bw,bh,"@-1->"); 1258 bforw->tooltip(gettext("Forward in cfg history")); 1259 bforw->callback(cb_graph_buttons); 1260 Fl_Button * bcfg = new Fl_Button(bx+2*bw,by,bw,bh,"cfg"); 1261 bcfg->tooltip(gettext("Configure screen view and axis")); 1262 bcfg->callback(cb_graph_buttons); 1263 by += bh; 1264 Fl_Button * bpause = new Fl_Button(bx+bw,by,bw,bh,"@>|"); 1265 bpause->tooltip(gettext("Stop or restart animation")); 1266 bpause->callback(cb_graph_buttons); 1267 Fl_Menu_Bar * bauto = new Fl_Menu_Bar(bx+2*bw,by,bw,bh,"auto"); 1268 bauto->tooltip(gettext("Autoscale")); 1269 int s= Autoscale_menu->size(); 1270 Fl_Menu_Item * automenuitem = new Fl_Menu_Item[Autoscale_menu->size()]; 1271 for (int i=0;i<s;++i) 1272 *(automenuitem+i)=*(Autoscale_menu+i); 1273 bauto->menu (automenuitem); 1274 menubar= new Fl_Menu_Bar(bx,by,bw,bh,"+"); 1275 menubar->tooltip(gettext("Graphic menu")); 1276 s= Graph2d3d_menu->size(); 1277 Fl_Menu_Item * menuitem = new Fl_Menu_Item[Graph2d3d_menu->size()]; 1278 for (int i=0;i<s;++i) 1279 *(menuitem+i)=*(Graph2d3d_menu+i); 1280 menubar->menu (menuitem); 1281 button_group->end(); 1282 int param_group_y=button_group->y()+button_group->h(); 1283 param_group = new Fl_Group(x+w-legende_size,param_group_y,legende_size,mouse_param_group->h()-button_group->h()-mouse_position->h()); 1284 param_group->box(FL_FLAT_BOX); 1285 param_group->end(); 1286 mouse_param_group->end(); 1287 group->add(mouse_param_group); 1288 set_colors(group); 1289 } 1290 Graph2d3d(int x,int y,int w,int h,const char * l,double xmin,double xmax,double ymin,double ymax,double zmin,double zmax,double ortho,History_Pack * hp_)1291 Graph2d3d::Graph2d3d(int x,int y,int w,int h,const char * l,double xmin,double xmax,double ymin,double ymax,double zmin,double zmax,double ortho,History_Pack * hp_): 1292 Fl_Widget(x,y,w,h,l), 1293 pushed(false), 1294 show_mouse_on_object(false), 1295 mode(255),args_tmp_push_size(0),no_handle(false), 1296 display_mode(0x45), 1297 window_xmin(xmin),window_xmax(xmax),window_ymin(ymin),window_ymax(ymax),window_zmin(zmin),window_zmax(zmax),history_pos(0), 1298 ylegende(2.5), 1299 mouse_param_group(0),mouse_position(0),param_group(0),button_group(0),menubar(0),hp(hp_), 1300 #ifdef IPAQ 1301 npixels(15), 1302 #else 1303 npixels(8), 1304 #endif 1305 show_axes(hp_?giac::show_axes(hp_->contextptr):1),show_names(1), 1306 animation_dt(0),paused(false),animation_instructions_pos(0), 1307 rotanim_type(256),rotanim_danim(0),rotanim_nstep(100),rotanim_tstep(0.03), 1308 rotanim_rx(0),rotanim_ry(0),rotanim_rz(1), 1309 last_event(0),x_tick(1.0),y_tick(1.0),couleur(0),approx(true),hp_pos(-1),moving(false),moving_frame(false),ntheta(24),nphi(18),background_image(0) { 1310 animations.push_back(this); 1311 push_cfg(); 1312 struct timezone tz; 1313 gettimeofday(&animation_last,&tz); 1314 legende_size=giac::LEGENDE_SIZE; 1315 x_axis_color=FL_RED; 1316 y_axis_color=dark_green_color; 1317 z_axis_color=FL_BLUE; 1318 current_i=current_j=RAND_MAX; 1319 in_area=false; 1320 } 1321 Graph2d3d(int x,int y,int w,int h,const char * l,History_Pack * hp_)1322 Graph2d3d::Graph2d3d(int x,int y,int w,int h,const char * l,History_Pack * hp_): 1323 Fl_Widget(x,y,w,h,l), 1324 pushed(false), 1325 show_mouse_on_object(false), 1326 display_mode(0x45), 1327 mode(255),args_tmp_push_size(0),no_handle(false), 1328 window_xmin(Xcas_config.window_xmin),window_xmax(Xcas_config.window_xmax),window_ymin(Xcas_config.window_ymin),window_ymax(Xcas_config.window_ymax),window_zmin(Xcas_config.window_zmin),window_zmax(Xcas_config.window_zmax),history_pos(0), 1329 ylegende(2.5), 1330 mouse_param_group(0),mouse_position(0),param_group(0),button_group(0),menubar(0),hp(hp_), 1331 #ifdef IPAQ 1332 npixels(15), 1333 #else 1334 npixels(8), 1335 #endif 1336 show_axes(hp_?giac::show_axes(hp_->contextptr):1),show_names(1), 1337 animation_dt(0),paused(false),animation_instructions_pos(0), 1338 rotanim_type(256),rotanim_danim(0),rotanim_nstep(100),rotanim_tstep(0.1), 1339 rotanim_rx(0),rotanim_ry(0),rotanim_rz(1), 1340 last_event(0),x_tick(1.0),y_tick(1.0),couleur(0),approx(true),hp_pos(-1),moving(false),moving_frame(false),ntheta(24),nphi(18),background_image(0) { 1341 legende_size=giac::LEGENDE_SIZE; 1342 animations.push_back(this); 1343 struct timezone tz; 1344 gettimeofday(&animation_last,&tz); 1345 push_cfg(); 1346 x_axis_color=FL_RED; 1347 y_axis_color=dark_green_color; 1348 z_axis_color=FL_BLUE; 1349 } 1350 ~Graph2d3d()1351 Graph2d3d::~Graph2d3d(){ 1352 vector<Graph2d3d *>::iterator it=animations.begin(),itend=animations.end(); 1353 for (;it!=itend;++it){ 1354 if (*it==this){ 1355 animations.erase(it); 1356 return; 1357 } 1358 } 1359 } 1360 Graph2d(int x,int y,int w,int h,const char * l,History_Pack * hp_)1361 Graph2d::Graph2d(int x,int y,int w,int h,const char * l,History_Pack * hp_): 1362 Graph2d3d(x,y,w,h,l,Xcas_config.window_xmin,Xcas_config.window_xmax,Xcas_config.window_ymin,Xcas_config.window_ymax,Xcas_config.window_zmin,Xcas_config.window_zmax,1.0,hp_), 1363 orthonormal_factor(1.0),waiting_click(false) 1364 { 1365 box(FL_FLAT_BOX); 1366 legende_size=max(min(legende_size,w/4),w/6); 1367 resize(x,y,w-legende_size,h); 1368 add_mouse_param_group(x,y,w,h); 1369 waiting_click_value=0; 1370 } 1371 find_tick(double dx)1372 double find_tick(double dx){ 1373 double res=std::pow(10.0,std::floor(std::log10(std::abs(dx)))); 1374 int nticks=int(dx/res); 1375 if (nticks<4) 1376 res/=5; 1377 else { 1378 if (nticks<8) 1379 res/=2; 1380 } 1381 return res; 1382 } 1383 current_config()1384 std::string Graph2d3d::current_config(){ 1385 string res="gl_quaternion=["; 1386 res += print_DOUBLE_(q.x); 1387 res += ","; 1388 res += print_DOUBLE_(q.y); 1389 res += ","; 1390 res += print_DOUBLE_(q.z); 1391 res += ","; 1392 res += print_DOUBLE_(q.w); 1393 res += "]"; 1394 return res; 1395 } 1396 reset_light(unsigned i)1397 void Graph2d3d::reset_light(unsigned i){ 1398 light_on[i]=!i; 1399 light_x[i]=0;light_y[i]=0;light_z[i]=1;light_w[i]=0; 1400 float di=i?0:1; 1401 light_diffuse_r[i]=di;light_diffuse_g[i]=di;light_diffuse_b[i]=di;light_diffuse_a[i]=di; 1402 light_specular_r[i]=di;light_specular_g[i]=di;light_specular_b[i]=di;light_specular_a[i]=di; 1403 light_ambient_r[i]=0;light_ambient_g[i]=0;light_ambient_b[i]=0;light_ambient_a[i]=1; 1404 light_spot_x[i]=0;light_spot_y[i]=0;light_spot_z[i]=-1;light_spot_w[i]=0; 1405 light_spot_exponent[i]=0;light_spot_cutoff[i]=180; 1406 light_0[i]=1;light_1[i]=0;light_2[i]=0; 1407 } 1408 config_light(unsigned i)1409 void Graph2d3d::config_light(unsigned i){ 1410 int dx=240,dy=300,l=14; 1411 if (window()){ 1412 dx=int(0.7*window()->w()); 1413 dy=int(0.5*window()->h()); 1414 l=window()->labelsize(); 1415 } 1416 static Fl_Window * w = 0; 1417 static Fl_Value_Input * ambient_r=0, * ambient_g=0, *ambient_b=0, *ambient_a=0, 1418 * diffuse_r=0, * diffuse_g=0, *diffuse_b=0, * diffuse_a=0, 1419 * specular_r=0, *specular_g=0, *specular_b=0, * specular_a=0, 1420 * pos_x=0, * pos_y=0, * pos_z=0, * pos_w=0, 1421 * dir_x=0, * dir_y=0, * dir_z=0, 1422 * spot_exponent=0, * spot_cutoff = 0, 1423 * coeff_0 =0, * coeff_1 = 0, * coeff_2 = 0; 1424 static Fl_Check_Button * enabled = 0; 1425 static Fl_Button * button0 = 0 ; // ok 1426 static Fl_Button * button1 =0; // cancel, quit 1427 static Fl_Button * button2 =0; // reset light, stay 1428 static Fl_Button * button3 =0; // cancel changes, stay 1429 static Fl_Button * button4 =0; // apply, stay 1430 if (!w){ 1431 Fl_Group::current(0); 1432 w=new Fl_Window(dx,dy); 1433 int dh=dy/7; 1434 int dw=dx/8; 1435 int y_=2; 1436 pos_x=new Fl_Value_Input(dw,y_,dw-2,dh-2,"x"); 1437 pos_x->tooltip(gettext("x position of spot")); 1438 pos_y=new Fl_Value_Input(3*dw,y_,dw-2,dh-2,"y"); 1439 pos_y->tooltip(gettext("y position of spot")); 1440 pos_z=new Fl_Value_Input(5*dw,y_,dw-2,dh-2,"z"); 1441 pos_z->tooltip(gettext("z position of spot")); 1442 pos_w=new Fl_Value_Input(7*dw,y_,dw-2,dh-2,"w"); 1443 pos_w->tooltip(gettext("0 directional light source (e.g. sun), 1 position light (e.g. bulb)")); 1444 y_ += dh; 1445 dir_x=new Fl_Value_Input(dw,y_,dw-2,dh-2,"x->"); 1446 dir_x->tooltip(gettext("x direction of spot")); 1447 dir_y=new Fl_Value_Input(3*dw,y_,dw-2,dh-2,"y->"); 1448 dir_y->tooltip(gettext("y direction of spot")); 1449 dir_z=new Fl_Value_Input(5*dw,y_,dw-2,dh-2,"z->"); 1450 dir_z->tooltip(gettext("z direction of spot")); 1451 enabled = new Fl_Check_Button(6*dw,y_,2*dw-2,dh-2,"on"); 1452 enabled->tooltip(gettext("Turn on/off light")); 1453 // spot_w=new Fl_Value_Input(3*dw,y_,dw-2,dh-2,"w"); 1454 // spot_w->tooltip(gettext("0 directional or 1 for position")); 1455 y_ += dh; 1456 ambient_r=new Fl_Value_Input(dw,y_,dw-2,dh-2,"amb_r"); 1457 ambient_r->tooltip(gettext("ambient red component")); 1458 ambient_g=new Fl_Value_Input(3*dw,y_,dw-2,dh-2,"amb_g"); 1459 ambient_g->tooltip(gettext("ambient green component")); 1460 ambient_b=new Fl_Value_Input(5*dw,y_,dw-2,dh-2,"amb_b"); 1461 ambient_b->tooltip(gettext("ambient blue component")); 1462 ambient_a=new Fl_Value_Input(7*dw,y_,dw-2,dh-2,"amb_a"); 1463 ambient_a->tooltip(gettext("ambient alpha component")); 1464 y_ += dh; 1465 diffuse_r=new Fl_Value_Input(dw,y_,dw-2,dh-2,"diff_r"); 1466 diffuse_r->tooltip(gettext("diffuse red component")); 1467 diffuse_g=new Fl_Value_Input(3*dw,y_,dw-2,dh-2,"diff_g"); 1468 diffuse_g->tooltip(gettext("diffuse green component")); 1469 diffuse_b=new Fl_Value_Input(5*dw,y_,dw-2,dh-2,"diff_b"); 1470 diffuse_b->tooltip(gettext("diffuse blue component")); 1471 diffuse_a=new Fl_Value_Input(7*dw,y_,dw-2,dh-2,"diff_a"); 1472 diffuse_a->tooltip(gettext("diffuse alpha component")); 1473 y_ += dh; 1474 specular_r=new Fl_Value_Input(dw,y_,dw-2,dh-2,"spec_r"); 1475 specular_r->tooltip(gettext("specular red component")); 1476 specular_g=new Fl_Value_Input(3*dw,y_,dw-2,dh-2,"spec_g"); 1477 specular_g->tooltip(gettext("specular green component")); 1478 specular_b=new Fl_Value_Input(5*dw,y_,dw-2,dh-2,"spec_b"); 1479 specular_b->tooltip(gettext("specular blue component")); 1480 specular_a=new Fl_Value_Input(7*dw,y_,dw-2,dh-2,"spec_a"); 1481 specular_a->tooltip(gettext("specular alpha component")); 1482 y_ += dh; 1483 dw=dx/10; 1484 spot_exponent=new Fl_Value_Input(dw,y_,dw-2,dh-2,"exp"); 1485 spot_exponent->tooltip(gettext("Spot attenuation exponent: power of cos(theta), e.g. 1")); 1486 spot_cutoff=new Fl_Value_Input(3*dw,y_,dw-2,dh-2,"cutoff"); 1487 spot_cutoff->tooltip(gettext("Spot cutoff angle in 0..90 or 180 for no cutoff")); 1488 coeff_0=new Fl_Value_Input(5*dw,y_,dw-2,dh-2,"att0"); 1489 coeff_0->tooltip(gettext("Attenuation constant coefficient")); 1490 coeff_1=new Fl_Value_Input(7*dw,y_,dw-2,dh-2,"att1"); 1491 coeff_1->tooltip(gettext("Attenuation linear coefficient")); 1492 coeff_2=new Fl_Value_Input(9*dw,y_,dw-2,dh-2,"att1"); 1493 coeff_2->tooltip(gettext("Attenuation quadratic coefficient")); 1494 y_ += dh; 1495 button0 = new Fl_Button(2,y_,dx/5-4,dh-4); 1496 button0->label(gettext("OK")); 1497 button1 = new Fl_Button(dx/5+2,y_,dx/5-4,dh-4); 1498 button1->label(gettext("Cancel")); 1499 button1->shortcut(0xff1b); 1500 button2 = new Fl_Button(2*dx/5+2,y_,dx/5-4,dh-4); 1501 button2->label(gettext("Default")); 1502 button3 = new Fl_Button(3*dx/5+2,y_,dx/5-4,dh-4); 1503 button3->label(gettext("Reset")); 1504 button4 = new Fl_Button(4*dx/5+2,y_,dx/5-4,dh-4); 1505 button4->label(gettext("Apply")); 1506 } 1507 w->label((gettext("Light configuration")+print_INT_(i)).c_str()); 1508 change_group_fontsize(w,l); 1509 w->set_modal(); 1510 w->show(); 1511 autosave_disabled=true; 1512 w->hotspot(w); 1513 Fl::focus(pos_x); 1514 int r=-2; 1515 for (;;) { 1516 if (r==-2){ 1517 diffuse_r->value(light_diffuse_r[i]); 1518 diffuse_g->value(light_diffuse_g[i]); 1519 diffuse_b->value(light_diffuse_b[i]); 1520 diffuse_a->value(light_diffuse_a[i]); 1521 ambient_r->value(light_ambient_r[i]); 1522 ambient_g->value(light_ambient_g[i]); 1523 ambient_b->value(light_ambient_b[i]); 1524 ambient_a->value(light_ambient_a[i]); 1525 specular_r->value(light_specular_r[i]); 1526 specular_g->value(light_specular_g[i]); 1527 specular_b->value(light_specular_b[i]); 1528 specular_a->value(light_specular_a[i]); 1529 pos_x->value(light_x[i]); 1530 pos_y->value(light_y[i]); 1531 pos_z->value(light_z[i]); 1532 pos_w->value(light_w[i]); 1533 dir_x->value(light_spot_x[i]); 1534 dir_y->value(light_spot_y[i]); 1535 dir_z->value(light_spot_z[i]); 1536 spot_exponent->value(light_spot_exponent[i]); 1537 spot_cutoff->value(light_spot_cutoff[i]); 1538 coeff_0->value(light_0[i]); 1539 coeff_1->value(light_1[i]); 1540 coeff_2->value(light_2[i]); 1541 enabled->value(light_on[i]); 1542 } 1543 r=-1; 1544 Fl_Widget *o = Fl::readqueue(); 1545 if (!o) Fl::wait(); 1546 else { 1547 if (o == button0) r = 0; // apply and quit 1548 if (o == button1) r = 1; // cancel changes, quit 1549 if (o == w) r=1; 1550 if (o == button2){ // reset light 1551 reset_light(i); 1552 r=-2; 1553 } 1554 if (o == button3) r=-2; // cancel changes, stay heer 1555 if (o == button4 ) r=2; // apply, stay 1556 } 1557 if (r==0 || r==2 ){ 1558 light_on[i]=enabled->value(); 1559 light_diffuse_r[i]=diffuse_r->value(); 1560 light_diffuse_g[i]=diffuse_g->value(); 1561 light_diffuse_b[i]=diffuse_b->value(); 1562 light_diffuse_a[i]=diffuse_a->value(); 1563 light_ambient_r[i]=ambient_r->value(); 1564 light_ambient_g[i]=ambient_g->value(); 1565 light_ambient_b[i]=ambient_b->value(); 1566 light_ambient_a[i]=ambient_a->value(); 1567 light_specular_r[i]=specular_r->value(); 1568 light_specular_g[i]=specular_g->value(); 1569 light_specular_b[i]=specular_b->value(); 1570 light_specular_a[i]=specular_a->value(); 1571 light_x[i]=pos_x->value(); 1572 light_y[i]=pos_y->value(); 1573 light_z[i]=pos_z->value(); 1574 light_w[i]=pos_w->value(); 1575 light_spot_x[i]=dir_x->value(); 1576 light_spot_y[i]=dir_y->value(); 1577 light_spot_z[i]=dir_z->value(); 1578 light_spot_exponent[i]=spot_exponent->value(); 1579 light_spot_cutoff[i]=spot_cutoff->value(); 1580 light_0[i]=coeff_0->value(); 1581 light_1[i]=coeff_1->value(); 1582 light_2[i]=coeff_2->value(); 1583 redraw(); 1584 } 1585 if (r==0 || r==1) 1586 break; 1587 } 1588 autosave_disabled=false; 1589 w->hide(); 1590 } 1591 1592 // round to 3 decimals setup_round(double x)1593 double setup_round(double x){ 1594 if (x<0) 1595 return -setup_round(-x); 1596 if (x<1e-300) 1597 return 0; 1598 int n=int(floor(log10(x)+.5)); // round to nearest 1599 x=int(floor(x*pow(10.0,3.0-n)+.5)); 1600 x=x*pow(10.0,n-3.0); 1601 return x; 1602 } 1603 config()1604 void Graph2d3d::config(){ 1605 int dx=240,dy=300,l=14; 1606 if (window()){ 1607 dx=int(0.7*window()->w()); 1608 dy=int(0.8*window()->h()); 1609 l=window()->labelsize(); 1610 } 1611 static Fl_Window * w = 0; 1612 static Fl_Value_Input * wxmin=0, * wxmax=0, *wymin=0, *wymax=0, *wzmin=0, *wzmax=0,*tx=0,*ty=0,*nx=0,*ny=0,*nz=0,*nd=0,*animate=0,*ylegendesize=0,*rx=0,*Theta=0,*Phi=0; 1613 static Fl_Value_Input * rotcfg_type=0,*rotcfg_danim=0,*rotcfg_nstep=0,*rotcfg_rx=0,*rotcfg_ry=0,*rotcfg_rz=0,*rotcfg_tstep=0; 1614 static Fl_Input * autoname_input=0; 1615 static Fl_Button * button0 = 0 ; // ok 1616 static Fl_Button * button1 =0; // cancel 1617 static Fl_Button * button2 =0; // apply 1618 static Fl_Button * button3 =0; // reset 1619 static Fl_Button * button4 =0; // autoscale 1620 static Fl_Button * button5 =0; // round 1621 static Fl_Button * l0=0,*l1=0,*l2=0,*l3=0,*l4=0,*l5=0,*l6=0,*l7=0; // lights 1622 static Fl_Check_Button* c1=0,*c2=0,*c3=0,*ct=0,*landscape=0,*notperspective=0,*lights=0,*shade=0,*blend=0,*fbox=0,*triedre=0,*logx=0,*logy=0; 1623 static Fl_Multiline_Output * currentcfg = 0; // display 1624 if (dy<240) 1625 dy=240; 1626 if (dx<240) 1627 dx=240; 1628 Graph3d * gr3d = dynamic_cast<Graph3d *>(this); 1629 Graph2d * gr2d = dynamic_cast<Graph2d *>(this); 1630 if (!w){ 1631 Fl_Group::current(0); 1632 w=new Fl_Window(dx,dy); 1633 int dh=dy/12; 1634 int y_=2; 1635 wxmin=new Fl_Value_Input(dx/6,y_,dx/6-2,dh-4,"WX-"); 1636 wxmin->tooltip(gettext("Xmin for visualisation")); 1637 wxmin->labelcolor(x_axis_color); 1638 wxmax=new Fl_Value_Input(dx/2,y_,dx/6-2,dh-4,"WX+"); 1639 wxmax->tooltip(gettext("Xmax for visualisation")); 1640 wxmax->labelcolor(x_axis_color); 1641 logx=new Fl_Check_Button(5*dx/6,y_,dx/6-2,dh-4,"X-log"); 1642 logx->tooltip(gettext("X Logarithmic scale")); 1643 logx->value(0); 1644 notperspective=new Fl_Check_Button(5*dx/6,y_,dx/6-2,dh-4,"Ortho proj"); 1645 notperspective->tooltip(gettext("Orthonormal or perspective")); 1646 notperspective->value(0); 1647 y_ += dh; 1648 wymin=new Fl_Value_Input(dx/6,y_,dx/6-2,dh-4,"WY-"); 1649 wymin->tooltip(gettext("Ymin for visualisation")); 1650 wymin->labelcolor(y_axis_color); 1651 wymax=new Fl_Value_Input(dx/2,y_,dx/6-2,dh-4,"WY+"); 1652 wymax->tooltip(gettext("Ymax for visualisation")); 1653 wymax->labelcolor(y_axis_color); 1654 logy=new Fl_Check_Button(5*dx/6,y_,dx/6-2,dh-4,"Y-log"); 1655 logy->tooltip(gettext("Y Logarithmic scale")); 1656 logy->value(0); 1657 shade=new Fl_Check_Button(5*dx/6,y_,dx/6-2,dh-4,"Gouraud"); 1658 shade->tooltip(gettext("Flat or Gouraud shading")); 1659 shade->value(0); 1660 y_ += dh; 1661 wzmin=new Fl_Value_Input(dx/6,y_,dx/6-2,dh-4,"WZ-"); 1662 wzmin->tooltip(gettext("Zmin for visualisation")); 1663 wzmin->labelcolor(z_axis_color); 1664 wzmax=new Fl_Value_Input(dx/2,y_,dx/6-2,dh-4,"WZ+"); 1665 wzmax->tooltip(gettext("Zmax for visualisation")); 1666 wzmax->labelcolor(z_axis_color); 1667 blend=new Fl_Check_Button(5*dx/6,y_,dx/6-2,dh-4,"Blend"); 1668 blend->tooltip(gettext("Enable blending")); 1669 blend->value(1); 1670 y_ += dh; 1671 wxmin->minimum(-1e300); 1672 wxmin->maximum(1e300); 1673 wymin->minimum(-1e300); 1674 wymin->maximum(1e300); 1675 wzmin->minimum(-1e300); 1676 wzmin->maximum(1e300); 1677 fbox=new Fl_Check_Button(2,y_,dx/6-4,dh-4,"Framebox"); 1678 fbox->tooltip(gettext("Graphic displayed with a framebox")); 1679 fbox->value(1); 1680 ct=new Fl_Check_Button(dx/6+2,y_,dx/6-4,dh-4,"Pixels"); 1681 ct->tooltip(gettext("Ticks in pixels or units")); 1682 ct->value(0); 1683 triedre=new Fl_Check_Button(2*dx/6+2,y_,dx/6-4,dh-4,"Triedre"); 1684 triedre->tooltip(gettext("View triedre even if axes are hidden")); 1685 triedre->value(1); 1686 tx=new Fl_Value_Input(2*dx/4+dx/8,y_,dx/4-dx/8,dh-4,"X-tick"); 1687 tx->tooltip(gettext("Number of units or pixels for ticks on X")); 1688 ty=new Fl_Value_Input(3*dx/4+dx/8,y_,dx/4-dx/8,dh-4,"Y-tick"); 1689 ty->tooltip(gettext("Number of units or pixels for ticks on Y")); 1690 y_ += dh; 1691 nx=new Fl_Value_Input(30,y_,dx/7-30,dh-4,"x*"); 1692 nx->tooltip(gettext("x coefficient of mouse plane equation")); 1693 nx->step(0.1); 1694 nx->minimum(-10.1); 1695 nx->maximum(10.1); 1696 ny=new Fl_Value_Input(dx/7+30,y_,dx/7-30,dh-4,"+y*"); 1697 ny->tooltip(gettext("y coefficient of mouse plane equation")); 1698 ny->step(0.1); 1699 ny->minimum(-10.1); 1700 ny->maximum(10.1); 1701 nz=new Fl_Value_Input(2*dx/7+30,y_,dx/7-30,dh-4,"+z*"); 1702 nz->tooltip(gettext("z coefficient of mouse plane equation")); 1703 nz->step(0.1); 1704 nz->minimum(-10.1); 1705 nz->maximum(10.1); 1706 nd=new Fl_Value_Input(3*dx/7+30,y_,dx/7-30,dh-4,"="); 1707 nd->tooltip(gettext("constant coefficient of mouse plane equation")); 1708 nd->step(0.1); 1709 nd->minimum(-30.1); 1710 nd->maximum(30.1); 1711 rx=new Fl_Value_Input(4*dx/7+30,y_,dx/7-30,dh-4,"r.x"); 1712 rx->tooltip(gettext("3d rotation")); 1713 rx->step(1); 1714 rx->minimum(-360); 1715 rx->maximum(360); 1716 Theta=new Fl_Value_Input(5*dx/7+30,y_,dx/7-30,dh-4,"lat"); 1717 Theta->tooltip(gettext("Number of latitude divisions for sphere drawing")); 1718 Theta->step(1); 1719 Theta->minimum(5); 1720 Theta->maximum(3000); 1721 Phi=new Fl_Value_Input(6*dx/7+30,y_,dx/7-30,dh-4,"long"); 1722 Phi->tooltip(gettext("Number of longitude divisions for sphere drawing")); 1723 Phi->step(1); 1724 Phi->minimum(5); 1725 Phi->maximum(3000); 1726 ylegendesize=new Fl_Value_Input(3*dx/5+30,y_,dx/5-30,dh-4,"y legende size"); 1727 ylegendesize->tooltip(gettext("Size in pixels for y graduation printing")); 1728 ylegendesize->step(1); 1729 ylegendesize->minimum(1); 1730 ylegendesize->maximum(200); 1731 y_ += dh; 1732 l0=new Fl_Button(2,y_,dx/10-4,dh-4,"L0"); 1733 l0->tooltip(gettext("Configure light")); 1734 l1=new Fl_Button(dx/10+2,y_,dx/10-4,dh-4,"L1"); 1735 l1->tooltip(gettext("Configure light")); 1736 l2=new Fl_Button(dx/5+2,y_,dx/10-4,dh-4,"L2"); 1737 l2->tooltip(gettext("Configure light")); 1738 l3=new Fl_Button(3*dx/10+2,y_,dx/10-4,dh-4,"L3"); 1739 l3->tooltip(gettext("Configure light")); 1740 l4=new Fl_Button(2*dx/5+2,y_,dx/10-4,dh-4,"L4"); 1741 l4->tooltip(gettext("Configure light")); 1742 l5=new Fl_Button(dx/2+2,y_,dx/10-4,dh-4,"L5"); 1743 l5->tooltip(gettext("Configure light")); 1744 l6=new Fl_Button(3*dx/5+2,y_,dx/10-4,dh-4,"L6"); 1745 l6->tooltip(gettext("Configure light")); 1746 l7=new Fl_Button(7*dx/10+2,y_,dx/10-4,dh-4,"L7"); 1747 l7->tooltip(gettext("Configure light")); 1748 lights=new Fl_Check_Button(8*dx/10,y_,dx/5-2,dh-4,"Lights"); 1749 lights->tooltip(gettext("Show scene with lights")); 1750 lights->value(0); 1751 y_ += dh; 1752 c1=new Fl_Check_Button(0,y_,dx/8,dh-4,gettext("Show names")); 1753 c1->tooltip(gettext("Show/Hide names of geometric objects")); 1754 c1->down_box(FL_DOWN_BOX); 1755 c3=new Fl_Check_Button(2*dx/8,y_,dx/8,dh-4,gettext("Plot names")); 1756 c3->tooltip(gettext("Show/Hide names of parametric and function plots")); 1757 c3->down_box(FL_DOWN_BOX); 1758 landscape=new Fl_Check_Button(dx/2,y_,dx/8,dh-4,gettext("Portrait")); 1759 landscape->tooltip(gettext("Portrait or landscape split")); 1760 landscape->down_box(FL_DOWN_BOX); 1761 autoname_input = new Fl_Input(dx/2+3*dx/8,y_,dx/8,dh-4); 1762 autoname_input->label(gettext("Autoname")); 1763 y_ += dh; 1764 c2=new Fl_Check_Button(0,y_,dx/6,dh-4,gettext("Show axis")); 1765 c2->tooltip(gettext("Show or hide axis")); 1766 c2->down_box(FL_DOWN_BOX); 1767 animate=new Fl_Value_Input(dx/2,y_,dx/6-4,dh-4,"animate"); 1768 animate->tooltip(gettext("Time between image changes for animations")); 1769 animate->step(0.1); 1770 animate->minimum(0); 1771 animate->maximum(2); 1772 button5 = new Fl_Button(2*dx/3+2,y_,dx/3-4,dh-4); 1773 button5->label(gettext("Round")); 1774 button5->tooltip(gettext("Round xmin/xmax/ymin/ymax/zmin/zmax")); 1775 y_ += dh; 1776 button3 = new Fl_Button(2,y_,dx/3-4,dh-4); 1777 button3->label(gettext("Default")); 1778 button4 = new Fl_Button(dx/3+2,y_,dx/3-4,dh-4); 1779 button4->label(gettext("Autoscale")); 1780 button2 = new Fl_Button(2*dx/3+2,y_,dx/3-4,dh-4); 1781 button2->label(gettext("Apply")); 1782 button2->shortcut(0xff0d); 1783 y_ += dh; 1784 currentcfg = new Fl_Multiline_Output(dx/6,y_,5*dx/6-4,dh-4); 1785 currentcfg->label(gettext("Cfg")); 1786 currentcfg->tooltip(gettext("Current gl_quaternion= value")); 1787 y_ += dh; 1788 rotcfg_type = new Fl_Value_Input(dx/14+dx/42,y_,dx/14,dh-4); 1789 rotcfg_type->label("Anim"); 1790 rotcfg_type->tooltip(gettext("Rotate what: 1 l1, 2 l2, 4 l3, ..., 128 l8, 256 viewpoint")); 1791 rotcfg_tstep=new Fl_Value_Input(8*dx/42,y_,dx/14,dh-4); 1792 rotcfg_tstep->label("t"); 1793 rotcfg_tstep->tooltip(gettext("Time for 1 step in s")); 1794 rotcfg_nstep=new Fl_Value_Input(7*dx/21,y_,dx/14,dh-4); 1795 rotcfg_nstep->label("n"); 1796 rotcfg_nstep->tooltip(gettext("Number of steps for animation")); 1797 rotcfg_rx=new Fl_Value_Input(10*dx/21,y_,dx/14,dh-4); 1798 rotcfg_rx->label("x"); 1799 rotcfg_rx->tooltip(gettext("x rotation axis coordinate")); 1800 rotcfg_ry=new Fl_Value_Input(13*dx/21,y_,dx/14,dh-4); 1801 rotcfg_ry->label("y"); 1802 rotcfg_ry->tooltip(gettext("y rotation axis coordinate")); 1803 rotcfg_rz=new Fl_Value_Input(16*dx/21,y_,dx/14,dh-4); 1804 rotcfg_rz->label("z"); 1805 rotcfg_rz->tooltip(gettext("z rotation axis coordinate")); 1806 rotcfg_danim=new Fl_Value_Input(19*dx/21,y_,dx/14,dh-4); 1807 rotcfg_danim->label("d"); 1808 rotcfg_danim->tooltip(gettext("Other animation change (normally 0)")); 1809 y_ += dh; 1810 button0 = new Fl_Button(2,y_,dx/2-4,dh-4); 1811 button0->label(gettext("OK")); 1812 button1 = new Fl_Button(dx/2+2,y_,dx/2-4,dh-4); 1813 button1->label(gettext("Cancel")); 1814 button1->shortcut(0xff1b); 1815 w->end(); 1816 w->resizable(w); 1817 } 1818 w->label(gettext("Graph configuration")); 1819 change_group_fontsize(w,l); 1820 if (window_xmin>window_xmax) 1821 std::swap(window_xmin,window_xmax); 1822 if (window_ymin>window_ymax) 1823 std::swap(window_ymin,window_ymax); 1824 if (window_zmin>window_zmax) 1825 std::swap(window_zmin,window_zmax); 1826 Figure * fig=dynamic_cast<Figure *>(parent()); 1827 if (fig){ 1828 // landscape->show(); 1829 landscape->value(fig->disposition); 1830 } 1831 else 1832 landscape->hide(); 1833 window_xmin=setup_round(window_xmin); 1834 window_xmax=setup_round(window_xmax); 1835 window_ymin=setup_round(window_ymin); 1836 window_ymax=setup_round(window_ymax); 1837 window_zmin=setup_round(window_zmin); 1838 window_zmax=setup_round(window_zmax); 1839 double dtmp=(window_xmax-window_xmin)/100; 1840 wxmin->value(window_xmin); 1841 wxmin->step(dtmp); 1842 wxmax->value(window_xmax); 1843 wxmax->step(dtmp); 1844 wxmin->minimum(window_xmin-100000*dtmp); 1845 wxmin->maximum(window_xmax+100000*dtmp); 1846 wxmax->minimum(window_xmin-100000*dtmp); 1847 wxmax->maximum(window_xmax+100000*dtmp); 1848 dtmp=(window_ymax-window_ymin)/100; 1849 wymin->step(dtmp); 1850 wymax->step(dtmp); 1851 wymin->value(window_ymin); 1852 wymax->value(window_ymax); 1853 wymin->minimum(window_ymin-100000*dtmp); 1854 wymin->maximum(window_ymax+100000*dtmp); 1855 wymax->minimum(window_ymin-100000*dtmp); 1856 wymax->maximum(window_ymax+100000*dtmp); 1857 dtmp=(window_zmax-window_zmin)/100; 1858 wzmin->step(dtmp); 1859 wzmax->step(dtmp); 1860 wzmin->value(window_zmin); 1861 wzmax->value(window_zmax); 1862 wzmin->minimum(window_zmin-100000*dtmp); 1863 wzmin->maximum(window_zmax+100000*dtmp); 1864 wzmax->minimum(window_zmin-100000*dtmp); 1865 wzmax->maximum(window_zmax+100000*dtmp); 1866 animate->value(animation_dt); 1867 double a,b,c,i,j,theta,wx=(window_xmax-window_xmin),wy=(window_ymax-window_ymin),wz=(window_zmax-window_zmin); 1868 if (gr3d){ 1869 rotcfg_tstep->show(); rotcfg_nstep->show(); 1870 rotcfg_rx->show(); rotcfg_ry->show(); rotcfg_rz->show(); 1871 rotcfg_danim->show(); rotcfg_type->show(); 1872 rotcfg_tstep->value(rotanim_tstep); 1873 rotcfg_nstep->value(rotanim_nstep); 1874 rotcfg_danim->value(rotanim_danim); 1875 rotcfg_type->value(rotanim_type); 1876 rotcfg_rx->value(rotanim_rx); 1877 rotcfg_ry->value(rotanim_ry); 1878 rotcfg_rz->value(rotanim_rz); 1879 notperspective->show(); 1880 logx->hide(); 1881 logy->hide(); 1882 notperspective->value(display_mode & 0x4); 1883 lights->show(); 1884 lights->value(display_mode & 0x8); 1885 l0->show(); 1886 l1->show(); 1887 l2->show(); 1888 l3->show(); 1889 l4->show(); 1890 l5->show(); 1891 l6->show(); 1892 l7->show(); 1893 shade->show(); 1894 shade->value( !(display_mode & 0x10) ); 1895 blend->show(); 1896 blend->value( (display_mode & 0x20) ); 1897 gr3d->current_normal(a,b,c); 1898 gr3d->normal2plan(a,b,c); // divides a,b,c by dx^2,... 1899 nx->value(a); 1900 ny->value(b); 1901 nz->value(c); 1902 double x0,y0,z0,t0; 1903 find_xyz(gr3d->x()+gr3d->w()/2,gr3d->y()+gr3d->h()/2,gr3d->depth,x0,y0,z0); 1904 t0=a*x0+b*y0+c*z0; 1905 if (std::abs(t0)<std::abs(window_zmax-window_zmin)/1000) 1906 t0=0; 1907 nd->value(t0); 1908 // angle 1909 double res1[4],vect[4]; 1910 if (std::abs(b)>std::abs(c)){ 1911 res1[0]=b*wx; 1912 res1[1]=-a*wy; 1913 res1[2]=0; 1914 } 1915 else { 1916 res1[0]=c*wx; 1917 res1[1]=0; 1918 res1[2]=-a*wz; 1919 } 1920 res1[0] += (window_xmax+window_xmin)/2; 1921 res1[1] += (window_ymax+window_ymin)/2; 1922 res1[2] += (window_zmax+window_zmin)/2; 1923 res1[3]=1; 1924 mult4(gr3d->model,res1,vect); 1925 i=vect[0]/vect[3]; 1926 j=vect[1]/vect[3]; 1927 // (i,j) are the coordinates of OX0 in (OX,OY) 1928 theta=-std::atan2(j,i)*180/M_PI; 1929 rx->value(theta); 1930 nx->show(); 1931 ny->show(); 1932 nz->show(); 1933 nd->show(); 1934 rx->show(); 1935 Theta->value(ntheta); 1936 Theta->show(); 1937 Phi->value(nphi); 1938 Phi->show(); 1939 ylegendesize->hide(); 1940 } 1941 else { 1942 rotcfg_tstep->hide(); rotcfg_nstep->hide(); 1943 rotcfg_rx->hide(); rotcfg_ry->hide(); rotcfg_rz->hide(); 1944 rotcfg_danim->hide(); rotcfg_type->hide(); 1945 notperspective->hide(); 1946 logx->show(); 1947 logy->show(); 1948 logx->value(display_mode & (1<<10)); 1949 logy->value(display_mode & (1<<11)); 1950 lights->hide(); 1951 l0->hide(); 1952 l1->hide(); 1953 l2->hide(); 1954 l3->hide(); 1955 l4->hide(); 1956 l5->hide(); 1957 l6->hide(); 1958 l7->hide(); 1959 shade->hide(); 1960 nx->hide(); 1961 ny->hide(); 1962 nz->hide(); 1963 nd->hide(); 1964 rx->hide(); 1965 Theta->hide(); 1966 Phi->hide(); 1967 ylegendesize->value(ylegende*labelsize()); 1968 ylegendesize->show(); 1969 } 1970 double y_scale=(Graph2d3d::h()-((show_axes && gr2d)?((title.empty()?1:2)*labelsize()):0))/(window_ymax-window_ymin); 1971 double x_scale=(Graph2d3d::w()-ylegende*((show_axes && gr2d)?labelsize():0))/(window_xmax-window_xmin); 1972 if (ct->value()){ 1973 tx->value(x_tick*x_scale); 1974 ty->value(y_tick*y_scale); 1975 } 1976 else { 1977 tx->value(x_tick); 1978 ty->value(y_tick); 1979 } 1980 fbox->value((display_mode & 0x100)); 1981 triedre->value(display_mode & 0x200); 1982 if (!hp) 1983 hp=get_history_pack(this); 1984 if (hp) 1985 autoname_input->value(autoname(hp->contextptr).c_str()); 1986 c1->value(show_names & 1); 1987 c3->value(show_names & 2); 1988 c2->value(show_axes); 1989 currentcfg->value(current_config().c_str()); 1990 w->set_modal(); 1991 w->show(); 1992 autosave_disabled=true; 1993 w->hotspot(w); 1994 Fl::focus(wxmin); 1995 int r; 1996 for (;;) { 1997 r=-1; 1998 Fl_Widget *o = Fl::readqueue(); 1999 if (!o) Fl::wait(); 2000 else { 2001 if (o == button0) r = 0; 2002 if (o == button1) r = 1; 2003 if (o == button2) r = 2; 2004 if (o==notperspective){ 2005 display_mode &= (0xffff ^ 0x4); 2006 if (notperspective->value()) 2007 display_mode |= 0x4; 2008 redraw(); 2009 } 2010 if (o==lights){ 2011 display_mode &= (0xffff ^ 0x8); 2012 if (lights->value()) 2013 display_mode |= 0x8; 2014 redraw(); 2015 } 2016 if (o==shade){ 2017 display_mode &= (0xffff ^ 0x10); 2018 if (!shade->value()) 2019 display_mode |= 0x10; 2020 redraw(); 2021 } 2022 if (o==blend){ 2023 display_mode &= (0xffff ^ 0x20); 2024 if (blend->value()) 2025 display_mode |= 0x20; 2026 redraw(); 2027 } 2028 if (o==logx){ 2029 display_mode &= (0xffff ^ (1<<10)); 2030 if (logx->value()) 2031 display_mode |= (1<<10); 2032 redraw(); 2033 } 2034 if (o==logy){ 2035 display_mode &= (0xffff ^ (1<<11)); 2036 if (logy->value()) 2037 display_mode |= (1<<11); 2038 redraw(); 2039 } 2040 if (o==l0){ 2041 config_light(0); 2042 } 2043 if (o==l1){ 2044 config_light(1); 2045 continue; 2046 } 2047 if (o==l2){ 2048 config_light(2); 2049 continue; 2050 } 2051 if (o==l3){ 2052 config_light(3); 2053 continue; 2054 } 2055 if (o==l4){ 2056 config_light(4); 2057 continue; 2058 } 2059 if (o==l5){ 2060 config_light(5); 2061 continue; 2062 } 2063 if (o==l6){ 2064 config_light(6); 2065 continue; 2066 } 2067 if (o==l7){ 2068 config_light(7); 2069 continue; 2070 } 2071 if (fig && o == landscape){ 2072 fig->disposition=landscape->value(); 2073 fig->resize(fig->x(),fig->y(),fig->w(),fig->h()); 2074 orthonormalize(); 2075 fig->redraw(); 2076 } 2077 if (o==button3 ){ 2078 wxmin->value(gnuplot_xmin); 2079 wxmax->value(gnuplot_xmax); 2080 wymin->value(gnuplot_ymin); 2081 wymax->value(gnuplot_ymax); 2082 wzmin->value(gnuplot_zmin); 2083 wzmax->value(gnuplot_zmax); 2084 nx->value(0); 2085 ny->value(0); 2086 nz->value(1); 2087 nd->value(0); 2088 r=2; 2089 } 2090 if (o==ylegendesize){ 2091 ylegende=ylegendesize->value()/labelsize(); 2092 } 2093 if (o==button4 ){ 2094 autoscale(false); 2095 wxmin->value(window_xmin); 2096 wxmax->value(window_xmax); 2097 wymin->value(window_ymin); 2098 wymax->value(window_ymax); 2099 wzmin->value(window_zmin); 2100 wzmax->value(window_zmax); 2101 } 2102 if (o==button5){ 2103 x_tick=find_tick(window_xmax-window_xmin); 2104 wxmin->value(int( window_xmin/x_tick -1)*x_tick); 2105 wxmax->value(int( window_xmax/x_tick +1)*x_tick); 2106 y_tick=find_tick(window_ymax-window_ymin); 2107 wymin->value(int( window_ymin/y_tick -1)*y_tick); 2108 wymax->value(int( window_ymax/y_tick +1)*y_tick); 2109 z_tick=find_tick(window_zmax-window_zmin); 2110 wzmin->value(int( window_zmin/z_tick -1)*z_tick); 2111 wzmax->value(int( window_zmax/z_tick +1)*z_tick); 2112 } 2113 if (o == w) r=1; 2114 if (r==0 || r==2){ 2115 rotanim_type=int(rotcfg_type->value()); 2116 rotanim_danim=int(rotcfg_danim->value()); 2117 rotanim_tstep=std::abs(rotcfg_tstep->value()); 2118 rotanim_nstep=max(int(rotcfg_nstep->value()),2); 2119 rotanim_rx=rotcfg_rx->value(); 2120 rotanim_ry=rotcfg_ry->value(); 2121 rotanim_rz=rotcfg_rz->value(); 2122 if (rotanim_rx*rotanim_rx+rotanim_ry*rotanim_ry+rotanim_rz*rotanim_rz<1e-6){ 2123 rotanim_rx=0; rotanim_ry=0; rotanim_rz=1; 2124 } 2125 animation_dt=std::abs(animate->value()); 2126 animation_instructions_pos=0; 2127 window_xmin=wxmin->value(); 2128 window_xmax=wxmax->value(); 2129 window_ymin=wymin->value(); 2130 window_ymax=wymax->value(); 2131 window_zmin=wzmin->value(); 2132 window_zmax=wzmax->value(); 2133 if (window_xmin>window_xmax) 2134 std::swap(window_xmin,window_xmax); 2135 if (window_ymin>window_ymax) 2136 std::swap(window_ymin,window_ymax); 2137 if (window_zmin>window_zmax) 2138 std::swap(window_zmin,window_zmax); 2139 y_scale=(Graph2d3d::h()-((gr2d && show_axes)?((title.empty()?1:2)*labelsize()):0))/(window_ymax-window_ymin); 2140 x_scale=(Graph2d3d::w()-ylegende*((gr2d && show_axes)?labelsize():0))/(window_xmax-window_xmin); 2141 if (gr3d){ 2142 ntheta=int(Theta->value()); 2143 nphi=int(Phi->value()); 2144 double a=nx->value(),b=ny->value(),c=nz->value(); 2145 double aorig=a,borig=b,corig=c; 2146 // de-scale a,b,c 2147 a *= (window_xmax-window_xmin); 2148 b *= (window_ymax-window_ymin); 2149 c *= (window_zmax-window_zmin); 2150 double n=std::sqrt(a*a+b*b+c*c); 2151 if (aorig*aorig+borig*borig+corig*corig<1e-3){ 2152 q=quaternion_double(1,0,0,0); 2153 gr3d->depth=nd->value(); 2154 } 2155 else { 2156 a=a/n; b=b/n; c=c/n; // coordinates of OZ 2157 // (0,0,depth) -> depth*(a,b,c) 2158 // rescale (x,y,z)=depth*(dx*a,dy*b,dz*c)+(tx,ty,tz) 2159 // A*x+B*y+C*z=d -> depth=(d-A*tx-B*ty-C*tz)/(A*Zx+B*Zy+C*Zz) 2160 n=aorig*(window_xmax-window_xmin)*a+borig*(window_ymax-window_ymin)*b+corig*(window_zmax-window_zmin)*c; 2161 gr3d->depth = -2/std::sqrt(double(3.0))*(nd->value()-aorig*(window_xmax+window_xmin)/2-borig*(window_ymax+window_ymin)/2-corig*(window_zmax+window_zmin)/2)/n; 2162 // cerr << gr3d->depth << '\n'; 2163 double A0,B0,C0; // coordinates of OX0 2164 if (std::abs(b)>std::abs(c)){ 2165 A0=b; 2166 B0=-a; 2167 C0=0; 2168 } 2169 else { 2170 A0=c; 2171 B0=0; 2172 C0=-a; 2173 } 2174 n=std::sqrt(A0*A0+B0*B0+C0*C0); 2175 A0=A0/n; B0=B0/n; C0=C0/n; 2176 double A1,B1,C1; // coordinates of OY0 2177 A1=b*C0-c*B0; 2178 B1=c*A0-a*C0; 2179 C1=a*B0-b*A0; 2180 double t=rx->value()*M_PI/180; 2181 double A,B,C; // OX coordinates 2182 A=cos(t)*A0+sin(t)*A1; 2183 B=cos(t)*B0+sin(t)*B1; 2184 C=cos(t)*C0+sin(t)*C1; 2185 double D,E,F; // OY coordinates 2186 D=cos(t)*A1-sin(t)*A0; 2187 E=cos(t)*B1-sin(t)*B0; 2188 F=cos(t)*C1-sin(t)*C0; 2189 // matrix of the rotation in column is [A,B,C] [D,E,F] [a,b,c] 2190 /* 1 A D a 2191 2 B E b 2192 3 C F c 2193 */ 2194 // cerr << "axis " << F-b << "," << a-C << "," << B-D << '\n'; 2195 double qx,qy,qz,qw; 2196 qw=std::sqrt(1+A+E+c)/2; 2197 qx=(F-b)/4/qw; 2198 qy=(a-C)/4/qw; 2199 qz=(B-D)/4/qw; 2200 n=std::sqrt(qw*qw+qx*qx+qy*qy+qz*qz); 2201 q=quaternion_double(qw/n,-qx/n,-qy/n,-qz/n); 2202 } 2203 } // end if gr3d 2204 show_axes=c2->value(); 2205 show_names=c1->value() | (c3->value()<< 1); 2206 if (ct->value()){ 2207 x_tick=tx->value()/x_scale; 2208 y_tick=ty->value()/y_scale; 2209 } 2210 else { 2211 x_tick=tx->value(); 2212 y_tick=ty->value(); 2213 } 2214 display_mode &= (0xffff ^ 0x100); 2215 if (fbox->value()) 2216 display_mode |= 0x100; 2217 display_mode &= (0xffff ^ 0x200); 2218 if (triedre->value()) 2219 display_mode |= 0x200; 2220 if (hp &&strlen(autoname_input->value())) 2221 autoname(hp->contextptr)=autoname_input->value(); 2222 redraw(); 2223 if (r==0) 2224 push_cfg(); 2225 } 2226 if (r==0 || r==1) 2227 break; 2228 } // end else 2229 currentcfg->value(current_config().c_str()); 2230 } // end for 2231 autosave_disabled=false; 2232 w->hide(); 2233 } 2234 parameter2slider(const gen & e,const giac::context * contextptr)2235 Gen_Value_Slider * parameter2slider(const gen & e,const giac::context *contextptr){ 2236 if (e.is_symb_of_sommet(at_parameter) && e._SYMBptr->feuille.type==_VECT){ 2237 vecteur v = *e._SYMBptr->feuille.evalf(1,contextptr).evalf_double(1,contextptr)._VECTptr; 2238 if (v.size()>3 &&v[1].type==_DOUBLE_ && v[2].type==_DOUBLE_ && v[3].type == _DOUBLE_ ){ 2239 gen name=e._SYMBptr->feuille._VECTptr->front(); 2240 double step=(v[2]._DOUBLE_val-v[1]._DOUBLE_val)/100.; 2241 if (v.size()>4 && v[4].type==_DOUBLE_) 2242 step=v[4]._DOUBLE_val; 2243 Fl_Group::current(0); 2244 Gen_Value_Slider * gvs = new Gen_Value_Slider(0,0,1,1,-2,v[1]._DOUBLE_val,v[2]._DOUBLE_val,step,name.print(contextptr)); 2245 gvs->align(FL_ALIGN_RIGHT); 2246 gvs->value(v[3]._DOUBLE_val); 2247 return gvs; 2248 } 2249 } 2250 return 0; 2251 } 2252 add(const gen & e)2253 void Graph2d3d::add(const gen & e){ 2254 context * contextptr=hp?hp->contextptr:get_context(this); 2255 if (e.is_symb_of_sommet(at_trace)){ 2256 gen f=symbolic(at_evalf,e._SYMBptr->feuille); 2257 f=protecteval(f,1,contextptr); 2258 trace_instructions.push_back(f); 2259 this->redraw(); 2260 return; 2261 } 2262 plot_instructions.push_back(e); 2263 update_infos(e,contextptr); 2264 if (e.is_symb_of_sommet(at_pnt) && e._SYMBptr->feuille.type==_VECT ){ 2265 vecteur & v = *e._SYMBptr->feuille._VECTptr; 2266 if (v.size()==3 && v.back().type==_STRNG){ 2267 string newauto=*v.back()._STRNGptr; 2268 if (newauto.size()>=1 && v[1].type!=_VECT && newauto>=autoname(contextptr)){ 2269 autoname(contextptr)=newauto; 2270 autoname_plus_plus(); 2271 } 2272 } 2273 } 2274 // gen_value_slider inside normal graphic do not work 2275 // especially if you save them, the output by widget_sprint is unusable 2276 Gen_Value_Slider * gvs=0; 2277 if ( (dynamic_cast<Geo2d *>(this) || dynamic_cast<Geo3d *>(this)) && param_group && (gvs=parameter2slider(e,contextptr)) ){ 2278 int n=param_group->children(); 2279 int x=param_group->x(), y=param_group->y(),h=param_group->h(),w=(6*param_group->w()/7); 2280 int nmax=int(0.5+param_group->h()/(1.5*labelsize())); 2281 if (n>nmax){ // Resize params height h/(n+1) 2282 for (int i=0;i<n;++i) 2283 param_group->child(i)->resize(x,y+h/(n+1)*i,w,h/(n+1)); 2284 } 2285 if (n) 2286 y=param_group->child(n-1)->y()+param_group->child(n-1)->h(); 2287 if (n<nmax) 2288 n=nmax-1; 2289 gvs->resize(x,y,w,param_group->h()/(n+1)); 2290 gvs->pos=plot_instructions.size()-1; 2291 param_group->add(gvs); 2292 param_group->redraw(); 2293 } 2294 this->redraw(); 2295 } 2296 find_ylegende()2297 void Graph2d3d::find_ylegende(){ 2298 const giac::context * contextptr = get_context(this); 2299 vecteur aff=ticks(window_ymin,window_ymax,true); 2300 int affs=aff.size(); 2301 fl_font(FL_HELVETICA,labelsize()); 2302 int taille=5; 2303 for (int i=0;i<affs;++i){ 2304 double d=evalf_double(aff[i],1,contextptr)._DOUBLE_val; 2305 string tmp=print_DOUBLE_(d)+y_axis_unit; 2306 int taillecur=5+int(fl_width(tmp.c_str())); 2307 if (taillecur>taille) 2308 taille=taillecur; 2309 } 2310 ylegende=double(taille)/labelsize(); 2311 } 2312 autoscale(bool fullview)2313 void Graph2d3d::autoscale(bool fullview){ 2314 glequal(false); 2315 if (!plot_instructions.empty()){ 2316 // Find the largest and lowest x/y/z in objects (except lines/plans) 2317 vector<double> vx,vy,vz; 2318 int s; 2319 context * contextptr=hp?hp->contextptr:get_context(this); 2320 bool ortho=autoscaleg(plot_instructions,vx,vy,vz,contextptr); 2321 autoscaleminmax(vx,window_xmin,window_xmax,fullview); 2322 if (display_mode & 0x400){ 2323 if (window_xmin<=0){ 2324 if (vx[0]<=0) 2325 window_xmin=-309; 2326 else 2327 window_xmin=std::log10(vx[0]); 2328 } 2329 else 2330 window_xmin=std::log10(window_xmin); 2331 if (window_xmax<=0) 2332 window_xmax=-300; 2333 else 2334 window_xmax=std::log10(window_xmax); 2335 } 2336 zoomx(1.0); 2337 autoscaleminmax(vy,window_ymin,window_ymax,fullview); 2338 if (display_mode & 0x800){ 2339 if (window_ymin<=0){ 2340 if (vy[0]<=0) 2341 window_ymin=-309; 2342 else 2343 window_ymin=std::log10(vy[0]); 2344 } 2345 else 2346 window_ymin=std::log10(window_ymin); 2347 if (window_ymax<=0) 2348 window_ymax=-300; 2349 else 2350 window_ymax=std::log10(window_ymax); 2351 } 2352 zoomy(1.0); 2353 autoscaleminmax(vz,window_zmin,window_zmax,fullview); 2354 zoomz(1.0); 2355 bool do_ortho=ortho; 2356 if (!do_ortho){ 2357 if (Graph2d * ptr=dynamic_cast<Graph2d *>(this)){ 2358 double h=this->h()*ptr->orthonormal_factor; 2359 double w=this->w(); 2360 double window_w=window_xmax-window_xmin,window_h=window_ymax-window_ymin; 2361 double tst=h/w*window_w/window_h; 2362 if (tst>0.7 && tst<1.4) 2363 do_ortho=true; 2364 } 2365 } 2366 if (do_ortho ) 2367 orthonormalize(); 2368 } 2369 find_ylegende(); 2370 y_tick=find_tick(window_ymax-window_ymin); 2371 redraw(); 2372 push_cfg(); 2373 } 2374 glequalv(vecteur & v,bool rmequal)2375 void glequalv(vecteur & v,bool rmequal){ 2376 iterateur it=v.begin(),itend=v.end(); 2377 if (rmequal){ 2378 for (;it!=itend;++it){ 2379 if (it->type==_VECT) 2380 glequalv(*it->_VECTptr,rmequal); 2381 if (it->is_symb_of_sommet(at_equal)) 2382 *it=symbolic(at_nop,it->_SYMBptr->feuille); 2383 } 2384 } 2385 else { 2386 for (;it!=itend;++it){ 2387 if (it->type==_VECT) 2388 glequalv(*it->_VECTptr,rmequal); 2389 if (it->is_symb_of_sommet(at_nop)) 2390 *it=symbolic(at_equal,it->_SYMBptr->feuille); 2391 } 2392 } 2393 } 2394 glequal(bool rmequal)2395 void Graph2d3d::glequal(bool rmequal){ 2396 glequalv(plot_instructions,rmequal); 2397 } 2398 zoomx(double d,bool round)2399 void Graph2d3d::zoomx(double d,bool round){ 2400 double x_center=(window_xmin+window_xmax)/2; 2401 double dx=(window_xmax-window_xmin); 2402 if (dx==0) 2403 dx=gnuplot_xmax-gnuplot_xmin; 2404 dx *= d/2; 2405 x_tick = find_tick(dx); 2406 window_xmin = x_center - dx; 2407 if (round) 2408 window_xmin=int( window_xmin/x_tick -1)*x_tick; 2409 window_xmax = x_center + dx; 2410 if (round) 2411 window_xmax=int( window_xmax/x_tick +1)*x_tick; 2412 parent_redraw(this); 2413 } 2414 zoomy(double d,bool round)2415 void Graph2d3d::zoomy(double d,bool round){ 2416 double y_center=(window_ymin+window_ymax)/2; 2417 double dy=(window_ymax-window_ymin); 2418 if (dy==0) 2419 dy=gnuplot_ymax-gnuplot_ymin; 2420 dy *= d/2; 2421 y_tick = find_tick(dy); 2422 window_ymin = y_center - dy; 2423 if (round) 2424 window_ymin=int( window_ymin/y_tick -1)*y_tick; 2425 window_ymax = y_center + dy; 2426 if (round) 2427 window_ymax=int( window_ymax/y_tick +1)*y_tick; 2428 find_ylegende(); 2429 parent_redraw(this); 2430 } 2431 zoomz(double d,bool round)2432 void Graph2d3d::zoomz(double d,bool round){ 2433 double z_center=(window_zmin+window_zmax)/2; 2434 double dz=(window_zmax-window_zmin); 2435 if (dz==0) 2436 dz=gnuplot_zmax-gnuplot_zmin; 2437 dz *= d/2; 2438 z_tick=find_tick(dz); 2439 window_zmin = z_center - dz; 2440 if (round) 2441 window_zmin=int(window_zmin/z_tick -1)*z_tick; 2442 window_zmax = z_center + dz; 2443 if (round) 2444 window_zmax=int(window_zmax/z_tick +1)*z_tick; 2445 parent_redraw(this); 2446 } 2447 2448 zoom(double d)2449 void Graph2d3d::zoom(double d){ 2450 glequal(true); 2451 zoomx(d); 2452 zoomy(d); 2453 zoomz(d); 2454 push_cfg(); 2455 } 2456 2457 orthonormalize()2458 void Graph2d3d::orthonormalize(){ 2459 // don't do anything in base class 2460 } 2461 latexfilename(const char * filename_)2462 const char * latexfilename(const char * filename_){ 2463 if (filename_) 2464 return filename_; 2465 char * filename=file_chooser(gettext("LaTeX filaneme"), "*.tex", "session.tex"); 2466 if (!filename) 2467 return 0; 2468 string s=remove_extension(filename)+".tex"; 2469 if (is_file_available(s.c_str())){ 2470 int i=fl_ask("%s",("File "+s+" exists. Overwrite?").c_str()); 2471 if ( !i ) 2472 return 0; 2473 } 2474 return s.c_str(); 2475 } 2476 latex(const char * filename_)2477 const char * Graph2d3d::latex(const char * filename_){ 2478 return latexfilename(filename_); 2479 } 2480 latex(const char * filename_)2481 const char * Graph2d::latex(const char * filename_){ 2482 const char * filename=0; 2483 if ( (filename=Graph2d3d::latex(filename_)) ){ 2484 double xunit=giac::horiz_latex/(window_xmax-window_xmin); 2485 double yunit=(h()*giac::horiz_latex*orthonormal_factor)/w()/(window_ymax-window_ymin); 2486 graph2tex(filename,plot_instructions,window_xmin,window_xmax,window_ymin,window_ymax,xunit,yunit,false,get_context(this)); 2487 } 2488 return filename; 2489 } 2490 up(double d)2491 void Graph2d3d::up(double d){ 2492 glequal(true); 2493 window_ymin += d; 2494 window_ymax += d; 2495 parent_redraw(this); 2496 push_cfg(); 2497 } 2498 down(double d)2499 void Graph2d3d::down(double d){ 2500 glequal(true); 2501 window_ymin -= d; 2502 window_ymax -= d; 2503 parent_redraw(this); 2504 push_cfg(); 2505 } 2506 up_z(double d)2507 void Graph2d3d::up_z(double d){ 2508 glequal(true); 2509 window_zmin += d; 2510 window_zmax += d; 2511 parent_redraw(this); 2512 push_cfg(); 2513 } 2514 down_z(double d)2515 void Graph2d3d::down_z(double d){ 2516 glequal(true); 2517 window_zmin -= d; 2518 window_zmax -= d; 2519 parent_redraw(this); 2520 push_cfg(); 2521 } 2522 left(double d)2523 void Graph2d3d::left(double d){ 2524 glequal(true); 2525 window_xmin -= d; 2526 window_xmax -= d; 2527 parent_redraw(this); 2528 push_cfg(); 2529 } 2530 right(double d)2531 void Graph2d3d::right(double d){ 2532 glequal(true); 2533 window_xmin += d; 2534 window_xmax += d; 2535 parent_redraw(this); 2536 push_cfg(); 2537 } 2538 set_axes(int b)2539 void Graph2d3d::set_axes(int b){ 2540 show_axes = b; 2541 parent_redraw(this); 2542 } 2543 resize_mouse_param_group(int W)2544 void Graph2d3d::resize_mouse_param_group(int W){ 2545 if (mouse_param_group){ 2546 change_group_fontsize(mouse_param_group,labelsize()); 2547 int x=this->x()+w(); 2548 int l=labelsize(); 2549 int bh=min(l+3,h()/8); 2550 int y=this->y(); 2551 mouse_param_group->resize(x,y,W,h()); 2552 bool is3d=dynamic_cast<Graph3d *>(this); 2553 if (mouse_position) mouse_position->resize(x,y,W,(is3d?3:2)*l); 2554 if (mouse_position) y += mouse_position->h(); 2555 button_group->resize(x,y,W,5*bh); 2556 y += 5*bh; 2557 param_group->resize(x,y,W,this->y()-y+h()); 2558 mouse_param_group->init_sizes(); 2559 mouse_param_group->redraw(); 2560 } 2561 } 2562 resize(int X,int Y,int W,int H)2563 void Graph2d3d::resize(int X,int Y,int W,int H){ 2564 /* 2565 if (parent() && !dynamic_cast<Figure *>(parent()) && !dynamic_cast<Tableur_Group *>(parent()) && mouse_param_group){ 2566 if (parent()->w()!=w()+mouse_param_group->w()) 2567 resize_mouse_param_group(parent()->w()-w()); 2568 } 2569 */ 2570 Fl_Widget::resize(X,Y,W,H); 2571 } 2572 copy(const Graph2d3d & gr)2573 void Graph2d3d::copy(const Graph2d3d & gr){ 2574 window_xmin=gr.window_xmin; 2575 window_xmax=gr.window_xmax; 2576 window_ymin=gr.window_ymin; 2577 window_ymax=gr.window_ymax; 2578 window_zmin=gr.window_zmin; 2579 window_zmax=gr.window_zmax; 2580 npixels=gr.npixels; 2581 show_axes=gr.show_axes; 2582 show_names=gr.show_names; 2583 history = gr.history; 2584 labelsize(gr.labelsize()); 2585 resize_mouse_param_group(gr.mouse_param_group->w()); 2586 q=gr.q; 2587 display_mode=gr.display_mode; 2588 // copy lights 2589 for (int i=0;i<8;++i){ 2590 light_on[i]=gr.light_on[i]; 2591 light_x[i]=gr.light_x[i]; 2592 light_y[i]=gr.light_y[i]; 2593 light_z[i]=gr.light_z[i]; 2594 light_w[i]=gr.light_w[i];; 2595 light_diffuse_r[i]=gr.light_diffuse_r[i]; 2596 light_diffuse_g[i]=gr.light_diffuse_g[i]; 2597 light_diffuse_b[i]=gr.light_diffuse_b[i]; 2598 light_diffuse_a[i]=gr.light_diffuse_a[i]; 2599 light_specular_r[i]=gr.light_specular_r[i]; 2600 light_specular_g[i]=gr.light_specular_g[i]; 2601 light_specular_b[i]=gr.light_specular_b[i]; 2602 light_specular_a[i]=gr.light_specular_a[i]; 2603 light_ambient_r[i]=gr.light_ambient_r[i]; 2604 light_ambient_g[i]=gr.light_ambient_g[i]; 2605 light_ambient_b[i]=gr.light_ambient_b[i]; 2606 light_ambient_a[i]=gr.light_ambient_a[i]; 2607 light_spot_x[i]=gr.light_spot_x[i]; 2608 light_spot_y[i]=gr.light_spot_y[i]; 2609 light_spot_z[i]=gr.light_spot_z[i]; 2610 light_spot_w[i]=gr.light_spot_w[i]; 2611 light_spot_exponent[i]=gr.light_spot_exponent[i]; 2612 light_spot_cutoff[i]=gr.light_spot_cutoff[i]; 2613 light_0[i]=gr.light_0[i]; 2614 light_1[i]=gr.light_1[i]; 2615 light_2[i]=gr.light_2[i]; 2616 } 2617 ntheta=gr.ntheta; 2618 nphi=gr.nphi; 2619 } 2620 add(const vecteur & v)2621 void Graph2d3d::add(const vecteur & v){ 2622 const_iterateur it=v.begin(),itend=v.end(); 2623 for (;it!=itend;++it) 2624 add(*it); 2625 } 2626 do_handle(const gen & g)2627 void Graph2d3d::do_handle(const gen & g){ 2628 if (hp){ 2629 hp->update_pos=hp_pos; 2630 hp->set_gen_value(hp_pos,g,true); 2631 } 2632 } 2633 round(double d)2634 int round(double d){ 2635 int res=int(floor(d+0.5)); 2636 int maxpixels=10000; // maximal number of horizontal or vertical pixels 2637 if (d>maxpixels) 2638 return maxpixels; 2639 if (d<-maxpixels) 2640 return -maxpixels; 2641 return res; 2642 } 2643 findij(const gen & e0,double x_scale,double y_scale,double & i0,double & j0,GIAC_CONTEXT) const2644 bool Graph2d::findij(const gen & e0,double x_scale,double y_scale,double & i0,double & j0,GIAC_CONTEXT) const { 2645 gen e,f0,f1; 2646 evalfdouble2reim(e0,e,f0,f1,contextptr); 2647 if ((f0.type==_DOUBLE_) && (f1.type==_DOUBLE_)){ 2648 if (display_mode & 0x400){ 2649 if (f0._DOUBLE_val<=0) 2650 return false; 2651 f0=std::log10(f0._DOUBLE_val); 2652 } 2653 i0=(f0._DOUBLE_val-window_xmin)*x_scale; 2654 if (display_mode & 0x800){ 2655 if (f1._DOUBLE_val<=0) 2656 return false; 2657 f1=std::log10(f1._DOUBLE_val); 2658 } 2659 j0=(window_ymax-f1._DOUBLE_val)*y_scale; 2660 return true; 2661 } 2662 // cerr << "Invalid drawing data" << '\n'; 2663 return false; 2664 } 2665 chooseinvecteur(const vecteur & v)2666 int chooseinvecteur(const vecteur & v){ 2667 int s=v.size(); 2668 if (s==0) 2669 setsizeerr(); 2670 if ((s==1) || (s>5)) 2671 return 0; 2672 fl_font(FL_HELVETICA,10); 2673 fl_message_font(FL_HELVETICA,10); 2674 if (s==2) 2675 return fl_choice("Choose",v[0].print(giac::context0).c_str(),v[1].print(giac::context0).c_str(),NULL); 2676 if (s==3) 2677 return fl_choice("Choose",v[0].print(giac::context0).c_str(),v[1].print(giac::context0).c_str(),v[2].print(giac::context0).c_str()); 2678 if (s==4) 2679 return fl_choice("Choose",v[0].print(giac::context0).c_str(),v[1].print(giac::context0).c_str(),v[2].print(giac::context0).c_str(),v[3].print(giac::context0).c_str()); 2680 return fl_choice("Choose",v[0].print(giac::context0).c_str(),v[1].print(giac::context0).c_str(),v[2].print(giac::context0).c_str(),v[3].print(giac::context0).c_str(),v[4].print(giac::context0).c_str()); 2681 } 2682 printsemi(GIAC_CONTEXT)2683 string printsemi(GIAC_CONTEXT){ 2684 if (xcas_mode(contextptr)==3) 2685 return "�"; 2686 else 2687 return ";"; 2688 } 2689 2690 cas_recalc_name()2691 string cas_recalc_name(){ 2692 if (getenv("XCAS_TMP")) 2693 return getenv("XCAS_TMP")+("/#c#"+print_INT_(parent_id)); 2694 #ifdef WIN32 2695 return "#c#"+print_INT_(parent_id); 2696 #endif 2697 #ifdef IPAQ 2698 return "/tmp/#c#"+print_INT_(parent_id); 2699 #endif 2700 return home_directory()+"#c#"+print_INT_(parent_id); 2701 } 2702 orthonormalize()2703 void Graph2d::orthonormalize(){ 2704 // Center of the directions, orthonormalize 2705 double h=(this->h()-(show_axes?((title.empty()?1:2)*labelsize()):0))*orthonormal_factor; 2706 double w=this->w()-(show_axes?ylegende*labelsize():0); 2707 double window_w=window_xmax-window_xmin,window_h=window_ymax-window_ymin; 2708 double window_hsize=h/w*window_w; 2709 if (window_h > window_hsize*1.01){ // enlarge horizontally 2710 double window_xcenter=(window_xmin+window_xmax)/2; 2711 double window_wsize=w/h*window_h; 2712 window_xmin=window_xcenter-window_wsize/2; 2713 window_xmax=window_xcenter+window_wsize/2; 2714 } 2715 if (window_h < window_hsize*0.99) { // enlarge vertically 2716 double window_ycenter=(window_ymin+window_ymax)/2; 2717 window_ymin=window_ycenter-window_hsize/2; 2718 window_ymax=window_ycenter+window_hsize/2; 2719 } 2720 x_tick=find_tick(window_xmax-window_xmin); 2721 y_tick=find_tick(window_ymax-window_ymin); 2722 parent_redraw(this); 2723 push_cfg(); 2724 } 2725 mouse_rescale()2726 int Graph2d::mouse_rescale(){ 2727 if ( current_i >=0 && current_i <= w() && current_j >= 0 && current_j <= h()){ 2728 if (absint(current_i-push_i)>20 && absint(current_j-push_j)>20 ){ 2729 double y_scale=(window_ymax-window_ymin)/(h()-(show_axes?((title.empty()?1:2)*labelsize()):0)); 2730 double x_scale=(window_xmax-window_xmin)/(w()-(show_axes?ylegende*labelsize():0)); 2731 window_xmax=window_xmin+max(current_i,push_i)*x_scale; 2732 window_xmin=window_xmin+min(current_i,push_i)*x_scale; 2733 window_ymin=window_ymax-max(current_j,push_j)*y_scale; 2734 window_ymax=window_ymax-min(current_j,push_j)*y_scale; 2735 parent_redraw(this); 2736 push_cfg(); 2737 } 2738 else { 2739 ++animation_instructions_pos; 2740 redraw(); 2741 } 2742 return 1; 2743 } 2744 return 0; 2745 } 2746 2747 adjust_cursor_point_type()2748 void Graph2d3d::adjust_cursor_point_type(){ 2749 context * contextptr=hp?hp->contextptr:get_context(this); 2750 if (abs_calc_mode(contextptr)==38){ 2751 double newx,newy,newz; 2752 find_xyz(current_i,current_j,current_depth,newx,newy,newz); 2753 int pos=-1; 2754 gen orig; 2755 gen res=Graph2d3d::geometry_round(newx,newy,newz,find_eps(),orig,pos); 2756 cursor_point_type=pos>=0?6:3; 2757 parent_redraw(this); 2758 } 2759 } 2760 2761 // common to Graph2d and Geo2d 2762 // MOVE: modify arg_tmp.back() 2763 // PUSH: set pushed to true and mark mouse position common_in_handle(int event)2764 int Graph2d::common_in_handle(int event){ 2765 last_event=event; 2766 if (event== FL_MOUSEWHEEL ){ 2767 if (!Fl::event_inside(this)) 2768 return 0; 2769 if (Fl::e_dy<0) 2770 zoom(0.707); 2771 else 2772 zoom(1.414); 2773 return 1; 2774 } 2775 int res=handle_mouse(event); 2776 if (event==FL_UNFOCUS){ 2777 return 1; 2778 } 2779 int deltax=x(),deltay=y(); 2780 context * contextptr=hp?hp->contextptr:get_context(this); 2781 if (event==FL_MOVE || event==FL_DRAG || event==FL_PUSH || event==FL_RELEASE){ 2782 current_i=Fl::event_x()-deltax,current_j=Fl::event_y()-deltay; current_depth=0; 2783 if (abs_calc_mode(contextptr)==38) 2784 adjust_cursor_point_type(); 2785 } 2786 int horizontal_pixels=w()-(show_axes?int(ylegende*labelsize()):0); 2787 int vertical_pixels= h()-((show_axes?1:0)+(!title.empty()))*labelsize(); 2788 double y_scale=(window_ymax-window_ymin)/vertical_pixels; 2789 double x_scale=(window_xmax-window_xmin)/horizontal_pixels; 2790 if (mode!=255 && abs_calc_mode(contextptr)==38 && event==FL_KEYBOARD){ 2791 switch (Fl::event_key()){ 2792 case FL_Right: 2793 if (current_i<horizontal_pixels) 2794 ++current_i; 2795 adjust_cursor_point_type(); 2796 if (mouse_position) mouse_position->redraw(); 2797 if (Geo2d * geo=dynamic_cast<Geo2d *>(this)) 2798 geo->geo_handle(moving?FL_DRAG:FL_MOVE); 2799 return 1; 2800 case FL_Left: 2801 if (current_i>0) 2802 --current_i; 2803 adjust_cursor_point_type(); 2804 if (mouse_position) mouse_position->redraw(); 2805 if (Geo2d * geo=dynamic_cast<Geo2d *>(this)) 2806 geo->geo_handle(moving?FL_DRAG:FL_MOVE); 2807 return 1; 2808 case FL_Down: 2809 if (current_j<vertical_pixels) 2810 ++current_j; 2811 adjust_cursor_point_type(); 2812 if (mouse_position) mouse_position->redraw(); 2813 if (Geo2d * geo=dynamic_cast<Geo2d *>(this)) 2814 geo->geo_handle(moving?FL_DRAG:FL_MOVE); 2815 return 1; 2816 case FL_Up: 2817 if (current_j>0) 2818 --current_j; 2819 adjust_cursor_point_type(); 2820 if (mouse_position) mouse_position->redraw(); 2821 if (Geo2d * geo=dynamic_cast<Geo2d *>(this)) 2822 geo->geo_handle(moving?FL_DRAG:FL_MOVE); 2823 return 1; 2824 case FL_Page_Up: 2825 if (current_j>vertical_pixels/10) 2826 current_j -= vertical_pixels/10; 2827 else 2828 current_j =0; 2829 adjust_cursor_point_type(); 2830 if (mouse_position) mouse_position->redraw(); 2831 if (Geo2d * geo=dynamic_cast<Geo2d *>(this)) 2832 geo->geo_handle(moving?FL_DRAG:FL_MOVE); 2833 return 1; 2834 case FL_Page_Down: 2835 if (current_j<9*vertical_pixels/10) 2836 current_j += vertical_pixels/10; 2837 else 2838 current_j=vertical_pixels; 2839 adjust_cursor_point_type(); 2840 if (mouse_position) mouse_position->redraw(); 2841 if (Geo2d * geo=dynamic_cast<Geo2d *>(this)) 2842 geo->geo_handle(moving?FL_DRAG:FL_MOVE); 2843 return 1; 2844 case FL_End: 2845 if (current_i<9*horizontal_pixels/10) 2846 current_i += horizontal_pixels/10; 2847 else 2848 current_i=horizontal_pixels; 2849 adjust_cursor_point_type(); 2850 if (mouse_position) mouse_position->redraw(); 2851 if (Geo2d * geo=dynamic_cast<Geo2d *>(this)) 2852 geo->geo_handle(moving?FL_DRAG:FL_MOVE); 2853 return 1; 2854 case FL_Home: 2855 if (current_i>horizontal_pixels/10) 2856 current_i -= horizontal_pixels/10; 2857 else 2858 current_i=0; 2859 adjust_cursor_point_type(); 2860 if (mouse_position) mouse_position->redraw(); 2861 if (Geo2d * geo=dynamic_cast<Geo2d *>(this)) 2862 geo->geo_handle(moving?FL_DRAG:FL_MOVE); 2863 return 1; 2864 case FL_Enter: 2865 if (Geo2d * geo=dynamic_cast<Geo2d *>(this)){ 2866 if (!moving){ 2867 pushed=true; 2868 push_i=current_i; 2869 push_j=current_j; 2870 geo->geo_handle(FL_PUSH); 2871 if (moving) 2872 return 1; 2873 } 2874 int res=geo->geo_handle(FL_RELEASE); 2875 pushed=false; 2876 return res; 2877 } 2878 } // end switch 2879 if (Graph2d * gr2d= dynamic_cast<Graph2d *>(this)){ 2880 char ch=Fl::event_text()?Fl::event_text()[0]:0; 2881 if (ch>='a') 2882 ch -= 'a'-'A'; 2883 if (ch>='A' && ch<='Z'){ 2884 gen tmp=gen(string("G")+ch,contextptr); 2885 if (tmp.type==_IDNT){ 2886 tmp=evalf(tmp,1,contextptr); 2887 if (tmp.is_symb_of_sommet(at_pnt)){ 2888 tmp=remove_at_pnt(tmp); 2889 if (tmp.is_symb_of_sommet(at_cercle)) 2890 tmp=(tmp._SYMBptr->feuille[0]+tmp._SYMBptr->feuille[1])/2; 2891 if (tmp.type==_SYMB) 2892 tmp=tmp._SYMBptr->feuille; 2893 if (tmp.type==_VECT && !tmp._VECTptr->empty()) 2894 tmp=tmp._VECTptr->front(); 2895 if (tmp.type==_CPLX){ 2896 int horizontal_pixels=w()-(show_axes?int(ylegende*labelsize()):0); 2897 int vertical_pixels=h()-((show_axes?1:0)+(!title.empty()))*labelsize(); 2898 double y_scale=vertical_pixels/(window_ymax-window_ymin); 2899 double x_scale=horizontal_pixels/(window_xmax-window_xmin); 2900 double i,j; 2901 gr2d->findij(tmp,x_scale,y_scale,i,j,contextptr); 2902 current_i=int(i+.5); 2903 current_j=int(j+.5); 2904 adjust_cursor_point_type(); 2905 if (mouse_position) mouse_position->redraw(); 2906 if (Geo2d * geo=dynamic_cast<Geo2d *>(this)) 2907 geo->geo_handle(moving?FL_DRAG:FL_MOVE); 2908 return 1; 2909 } 2910 } 2911 } 2912 } 2913 } 2914 } 2915 else { 2916 int res=handle_keyboard(event); 2917 if (res) 2918 return res; 2919 } 2920 bool old_in_area=in_area; 2921 in_area=(current_i>=0 && current_i<=horizontal_pixels && current_j>=0 && current_j<=vertical_pixels); 2922 if (old_in_area!=in_area && !args_tmp.empty()) 2923 redraw(); 2924 if (event==FL_FOCUS){ 2925 if (mouse_position) 2926 mouse_position->redraw(); 2927 return 1; 2928 } 2929 Graph2d * gr2d =dynamic_cast<Graph2d *>(this); 2930 if (gr2d && pushed && mode==255 && Fl::event_button()==FL_RIGHT_MOUSE ){ 2931 if (event==FL_DRAG){ 2932 parent_redraw(this); 2933 return 1; 2934 } 2935 if (event==FL_RELEASE ){ 2936 pushed = false; 2937 return gr2d->mouse_rescale(); 2938 } 2939 } 2940 if (event==FL_RELEASE){ 2941 pushed = false; 2942 } 2943 // If the child process expect a user entry, click -> complex number 2944 if ( waiting_click ){ 2945 if ( (event==FL_RELEASE) && (current_i < horizontal_pixels) && (current_j < vertical_pixels) ){ 2946 gen a(window_xmin+current_i*x_scale,window_ymax-current_j*y_scale); 2947 if (waiting_click){ 2948 waiting_click_value=a; 2949 waiting_click=false; 2950 return 1; 2951 } 2952 } 2953 return 1; 2954 } 2955 if (event==FL_PUSH ){ 2956 if (this!=Fl::focus()){ 2957 Fl::focus(this); 2958 in_handle(FL_FOCUS); 2959 } 2960 pushed=true; 2961 push_i=current_i; 2962 push_j=current_j; 2963 push_depth=current_depth; 2964 parent_redraw(this); 2965 return 1; 2966 } 2967 return res; 2968 } 2969 in_handle(int event)2970 int Graph2d::in_handle(int event){ 2971 if (parent() && mouse_param_group->parent()!=parent()) 2972 parent()->add(mouse_param_group); 2973 int res=common_in_handle(event); 2974 if (res) 2975 return res; 2976 if (Fl::event_button()==FL_RIGHT_MOUSE){ 2977 if (event==FL_DRAG){ 2978 parent_redraw(this); 2979 return 1; 2980 } 2981 if ( event==FL_RELEASE ) 2982 return mouse_rescale(); 2983 } 2984 else { 2985 if (event==FL_DRAG || event==FL_RELEASE){ 2986 double newx,newy,newz; 2987 int dw=w()-(show_axes?int(ylegende*labelsize()):0),dh=h()-(show_axes?((title.empty()?1:2)*labelsize()):0); 2988 double dx=window_xmax-window_xmin; 2989 double dy=window_ymax-window_ymin; 2990 double x_scale=dx/dw,y_scale=dy/dh; 2991 newx=(current_i-push_i)*x_scale; 2992 newy=(push_j-current_j)*y_scale; 2993 round3(newx,window_xmin,window_xmax); 2994 round3(newy,window_ymin,window_ymax); 2995 if (!(display_mode & 0x80)){ 2996 window_xmin -= newx; 2997 window_xmax -= newx; 2998 window_ymin -= newy; 2999 window_ymax -= newy; 3000 } 3001 push_i = current_i; 3002 push_j = current_j; 3003 ++animation_instructions_pos; 3004 parent_redraw(this); 3005 return 1; 3006 } 3007 } 3008 return 0; 3009 } 3010 geo_find_history_pack(Fl_Widget * wid)3011 History_Pack * geo_find_history_pack(Fl_Widget * wid){ 3012 Fl_Group * g = wid->parent(); 3013 if (g){ 3014 int n=g->children(); 3015 for (int i=0;i<n;++i){ 3016 Fl_Widget * w = g->child(i); 3017 if (Fl_Scroll * s=dynamic_cast<Fl_Scroll *>(w)) 3018 if (s->children()) 3019 w=s->child(0); 3020 if (History_Pack * h=dynamic_cast<History_Pack *>(w)){ 3021 return h; 3022 } 3023 } 3024 } 3025 return 0; 3026 } 3027 geometry_round_numeric(double x,double y,double eps,bool approx)3028 gen geometry_round_numeric(double x,double y,double eps,bool approx){ 3029 return approx?gen(x,y):exact_double(x,eps)+cst_i*exact_double(y,eps); 3030 } 3031 geometry_round_numeric(double x,double y,double z,double eps,bool approx)3032 gen geometry_round_numeric(double x,double y,double z,double eps,bool approx){ 3033 return approx?makevecteur(x,y,z):makevecteur(exact_double(x,eps),exact_double(y,eps),exact_double(z,eps)); 3034 } 3035 round3(double & x,double xmin,double xmax)3036 void round3(double & x,double xmin,double xmax){ 3037 double dx=std::abs(xmax-xmin); 3038 double logdx=std::log10(dx); 3039 int ndec=int(logdx)-4; 3040 double xpow=std::pow(10.0,ndec); 3041 int newx=int(x/xpow); 3042 x=newx*xpow; 3043 } 3044 change_line_type(int & res,bool show_approx,bool & approx,const string & title,bool dim3,bool & formel,bool & untranslate,bool del,int fontsize)3045 int change_line_type(int & res,bool show_approx,bool & approx,const string & title,bool dim3,bool & formel,bool & untranslate,bool del,int fontsize){ 3046 static Fl_Window * w = 0; 3047 static Fl_Value_Input * epaisseur=0,*epaisseur_point; 3048 static Fl_Return_Button * button0 = 0 ; 3049 static Fl_Button * button1 =0,*button_color=0,*button2=0; 3050 static Fl_Check_Button * button_approx=0, * button_formel=0,*button_untranslate=0; 3051 static Line_Type *ltres=0; 3052 static Line_Type *lt0=0,*lt1=0,*lt2=0,*lt3=0,*lt4=0,*lt5=0,*lt6=0,*lt7=0; 3053 static Line_Type *pt0=0,*pt1=0,*pt2=0,*pt3=0,*pt4=0,*pt5=0,*pt6=0,*pt7=0; 3054 static Line_Type *st0=0,*st1=0,*st2=0,*st3=0; // quadrant1,2,3,4 3055 static Line_Type *fp0=0,*fp1=0; // fill polygone 3056 static Line_Type *hn0=0,*hn1=0; // hidden_name 3057 if (!w){ 3058 #ifdef IPAQ 3059 int dx=240,dy=300; 3060 #else 3061 int dx=25*fontsize, dy=10*fontsize; 3062 #endif 3063 int lignes=6; 3064 Fl_Group::current(0); 3065 w=new Fl_Window(dx,dy); 3066 epaisseur=new Fl_Value_Input(dx/4,2,dx/4-2,dy/lignes-4,gettext("Thickness")); 3067 epaisseur->when(FL_WHEN_CHANGED); 3068 epaisseur->step(0.1); 3069 epaisseur->maximum(8); 3070 epaisseur->minimum(1); 3071 epaisseur_point=new Fl_Value_Input(3*dx/4,2,dx/4-2,dy/lignes-4,gettext("Point width")); 3072 epaisseur_point->when(FL_WHEN_CHANGED); 3073 epaisseur_point->step(0.1); 3074 epaisseur_point->maximum(8); 3075 epaisseur_point->minimum(1); 3076 // ltres->label(gettext("Line type")); 3077 int x=dx/10; 3078 lt0=new Line_Type(x,dy/lignes,dx/10,dy/lignes,0); 3079 x+=lt0->w(); 3080 lt1=new Line_Type(x,dy/lignes,dx/10,dy/lignes,_DASH_LINE); 3081 x+=lt1->w(); 3082 lt2=new Line_Type(x,dy/lignes,dx/10,dy/lignes,_DOT_LINE); 3083 x+=lt2->w(); 3084 lt3=new Line_Type(x,dy/lignes,dx/10,dy/lignes,_DASHDOT_LINE); 3085 x+=lt3->w(); 3086 lt4=new Line_Type(x,dy/lignes,dx/10,dy/lignes,_DASHDOTDOT_LINE); 3087 x+=lt4->w(); 3088 lt5=new Line_Type(x,dy/lignes,dx/10,dy/lignes,_CAP_FLAT_LINE); 3089 x+=lt5->w(); 3090 lt6=new Line_Type(x,dy/lignes,dx/10,dy/lignes,_CAP_ROUND_LINE); 3091 x+=lt6->w(); 3092 lt7=new Line_Type(x,dy/lignes,dx/10,dy/lignes,_CAP_SQUARE_LINE); 3093 x+=lt7->w(); 3094 x=dx/10; 3095 pt0=new Line_Type(x,2*dy/lignes,dx/10,dy/lignes,_POINT_WIDTH_3); 3096 pt0->show_pnt(true); 3097 pt0->show_line(false); 3098 x+=pt0->w(); 3099 pt1=new Line_Type(x,2*dy/lignes,dx/10,dy/lignes,_POINT_LOSANGE | _POINT_WIDTH_3); 3100 pt1->show_pnt(true); 3101 pt1->show_line(false); 3102 x+=pt1->w(); 3103 pt2=new Line_Type(x,2*dy/lignes,dx/10,dy/lignes,_POINT_PLUS | _POINT_WIDTH_3); 3104 pt2->show_pnt(true); 3105 pt2->show_line(false); 3106 x+=pt2->w(); 3107 pt3=new Line_Type(x,2*dy/lignes,dx/10,dy/lignes,_POINT_CARRE| _POINT_WIDTH_3); 3108 pt3->show_pnt(true); 3109 pt3->show_line(false); 3110 x+=pt3->w(); 3111 pt4=new Line_Type(x,2*dy/lignes,dx/10,dy/lignes,_POINT_INVISIBLE | _POINT_WIDTH_3); 3112 pt4->show_pnt(true); 3113 pt4->show_line(false); 3114 x+=pt4->w(); 3115 pt5=new Line_Type(x,2*dy/lignes,dx/10,dy/lignes,_POINT_TRIANGLE| _POINT_WIDTH_3); 3116 x+=pt5->w(); 3117 pt5->show_pnt(true); 3118 pt5->show_line(false); 3119 pt6=new Line_Type(x,2*dy/lignes,dx/10,dy/lignes,_POINT_ETOILE| _POINT_WIDTH_3); 3120 pt6->show_pnt(true); 3121 pt6->show_line(false); 3122 x+=pt6->w(); 3123 pt7=new Line_Type(x,2*dy/lignes,dx/10,dy/lignes,_POINT_POINT |_POINT_WIDTH_3); 3124 pt7->show_pnt(true); 3125 pt7->show_line(false); 3126 x+=pt7->w(); 3127 x=dx/20; 3128 st0=new Line_Type(x,3*dy/lignes,dx/10,dy/lignes,_QUADRANT1); 3129 st0->show_pnt(true); 3130 st0->show_text(true); 3131 st0->show_line(false); 3132 x+=st0->w(); 3133 st1=new Line_Type(x,3*dy/lignes,dx/10,dy/lignes,_QUADRANT2); 3134 st1->show_pnt(true); 3135 st1->show_text(true); 3136 st1->show_line(false); 3137 x+=st1->w(); 3138 st2=new Line_Type(x,3*dy/lignes,dx/10,dy/lignes,_QUADRANT3); 3139 st2->show_pnt(true); 3140 st2->show_text(true); 3141 st2->show_line(false); 3142 x+=st2->w(); 3143 st3=new Line_Type(x,3*dy/lignes,dx/10,dy/lignes,_QUADRANT4); 3144 st3->show_pnt(true); 3145 st3->show_text(true); 3146 st3->show_line(false); 3147 x+=st3->w()+dx/20; 3148 hn0=new Line_Type(x,3*dy/lignes,dx/10,dy/lignes,0); 3149 hn0->show_text(true); 3150 hn0->show_line(false); 3151 x+=hn0->w(); 3152 hn1=new Line_Type(x,3*dy/lignes,dx/10,dy/lignes,_HIDDEN_NAME); 3153 hn1->show_text(true); 3154 hn1->show_line(false); 3155 x+=hn1->w()+dx/20; 3156 fp0=new Line_Type(x,3*dy/lignes,dx/10,dy/lignes,0); 3157 fp0->show_poly(true); 3158 fp0->show_line(false); 3159 x+=fp0->w(); 3160 fp1=new Line_Type(x,3*dy/lignes,dx/10,dy/lignes,_FILL_POLYGON); 3161 fp1->show_poly(true); 3162 fp1->show_line(false); 3163 x+=fp1->w(); 3164 ltres = new Line_Type(2,2+4*dy/lignes,dx/5-4,dy/lignes-4,res); 3165 ltres->show_pnt(true); 3166 ltres->show_poly(true); 3167 button_color = new Fl_Button(dx/5+2,2+4*dy/lignes,dx/5-4,dy/lignes-4); 3168 button_formel=new Fl_Check_Button(2*dx/5+2,2+4*dy/lignes,dx/5-4,dy/lignes-4); 3169 button_formel->label("symb"); 3170 button_formel->tooltip(gettext("Make point symbolic")); 3171 button_untranslate=new Fl_Check_Button(3*dx/5+2,2+4*dy/lignes,dx/5-4,dy/lignes-4); 3172 button_untranslate->label("untranslate"); 3173 button_untranslate->tooltip(gettext("Remove translation")); 3174 button0 = new Fl_Return_Button(2,2+5*dy/lignes,dx/3-4,dy/lignes-4); 3175 button0->shortcut(0xff0d); 3176 button0->label(gettext("OK")); 3177 button1 = new Fl_Button(dx/3+2,2+5*dy/lignes,dx/3-4,dy/lignes-4); 3178 button1->shortcut(0xff1b); 3179 button1->label(gettext("Cancel")); 3180 button2 = new Fl_Button(2*dx/3+2,2+5*dy/lignes,dx/3-4,dy/lignes-4); 3181 button2->label(gettext("Delete")); 3182 button2->tooltip(gettext("Delete current object")); 3183 w->end(); 3184 w->resizable(w); 3185 change_group_fontsize(w,fontsize); 3186 } 3187 if (formel){ 3188 button_formel->show(); 3189 button_formel->value(false); 3190 button_untranslate->show(); 3191 button_untranslate->value(false); 3192 } 3193 else { 3194 button_formel->hide(); 3195 button_untranslate->hide(); 3196 } 3197 if (del) 3198 button2->show(); 3199 else 3200 button2->hide(); 3201 /* 3202 if (dim3){ 3203 pt0->hide(); pt1->hide(); 3204 pt2->hide(); pt3->hide(); 3205 pt4->hide(); pt5->hide(); 3206 pt6->hide(); pt7->hide(); 3207 } 3208 else { 3209 pt0->show(); pt1->show(); 3210 pt2->show(); pt3->show(); 3211 pt4->show(); pt5->show(); 3212 pt6->show(); pt7->show(); 3213 } 3214 */ 3215 static string titlestr; 3216 titlestr=gettext("Object attributs ")+title; 3217 w->label(titlestr.c_str()); 3218 int r=-1; 3219 int lt=(res & 0x01c00000); 3220 int pt=(res & 0x0e000000); 3221 int st=(res & 0x30000000); 3222 bool fp=res&0x40000000; 3223 bool hn=res&0x80000000; 3224 int newcol=res; 3225 Fl_Color couleur=Fl_Color(res&0xffff); 3226 epaisseur->value( ((res&0x00070000) >> 16) +1); 3227 epaisseur_point->value( ((res&0x00380000) >> 19) +1); 3228 ltres->show_text(!hn); 3229 ltres->line_type(res); 3230 button_color->color(couleur); 3231 w->set_modal(); 3232 w->show(); 3233 autosave_disabled=true; 3234 w->hotspot(w); 3235 Fl::focus(epaisseur); 3236 for (;;) { 3237 Fl_Widget *o = Fl::readqueue(); 3238 if (!o) Fl::wait(); 3239 else { 3240 if (o == button0) {r = 0; break;} 3241 if (o == button1) {r = 1; break;} 3242 if (o == button2) {r = 2; break;} 3243 if (o==lt0 || o==lt1 || o==lt2 || o==lt3 || o==lt4 || o==lt5 || o==lt6 || o==lt7) { 3244 lt=(w->find(o)-w->find(lt0)) << 22; 3245 } 3246 if (o==pt0 || o==pt1 || o==pt2 || o==pt3 || o==pt4 || o==pt5 || o==pt6 || o==pt7) { 3247 pt=(w->find(o)-w->find(pt0)) << 25; 3248 } 3249 if (o==st0 || o==st1 || o==st2 || o==st3){ 3250 st=(w->find(o)-w->find(st0)) << 28; 3251 } 3252 if (o==button_color){ 3253 couleur=fl_show_colormap(couleur); 3254 button_color->color(couleur); 3255 } 3256 // if (o==button_approx) 3257 // button_approx->value(!button_approx->value()); 3258 if (o==fp0) 3259 fp=false; 3260 if (o==fp1) 3261 fp=true; 3262 if (o==hn0) 3263 hn=false; 3264 if (o==hn1) 3265 hn=true; 3266 newcol = couleur; 3267 newcol += Min(8,Max(0,int(epaisseur->value())-1))*_LINE_WIDTH_2; 3268 newcol += Min(8,Max(0,int(epaisseur_point->value())-1))*_POINT_WIDTH_2; 3269 newcol += lt+pt+st; 3270 if (fp) 3271 newcol += _FILL_POLYGON; 3272 if (hn) 3273 newcol += _HIDDEN_NAME; 3274 ltres->line_type(newcol); 3275 if (o == w) { r=1; break; } 3276 } 3277 } 3278 autosave_disabled=false; 3279 w->hide(); 3280 if (!r){ 3281 res=newcol; 3282 if (formel){ 3283 formel=button_formel->value(); 3284 untranslate=button_untranslate->value(); 3285 } 3286 } 3287 return r; 3288 } 3289 3290 bool is_numeric(const gen & a); is_numeric(const vecteur & v)3291 bool is_numeric(const vecteur & v){ 3292 const_iterateur it=v.begin(),itend=v.end(); 3293 for (;it!=itend;++it){ 3294 if (!is_numeric(*it)) 3295 return false; 3296 } 3297 return true; 3298 } 3299 is_numeric(const gen & a)3300 bool is_numeric(const gen & a){ 3301 switch (a.type){ 3302 case _DOUBLE_: case _INT_: case _ZINT: case _REAL: 3303 return true; 3304 case _CPLX: 3305 return is_numeric(*a._CPLXptr) && is_numeric(*(a._CPLXptr+1)); 3306 case _VECT: 3307 return is_numeric(*a._VECTptr); 3308 case _FRAC: 3309 return is_numeric(a._FRACptr->num) && is_numeric(a._FRACptr->den); 3310 case _SYMB: 3311 if (a.is_symb_of_sommet(at_prod) || a.is_symb_of_sommet(at_inv) || a.is_symb_of_sommet(at_neg) || a.is_symb_of_sommet(at_plus)) 3312 return is_numeric(a._SYMBptr->feuille); 3313 default: 3314 return false; 3315 } 3316 } 3317 change_attributs(int hp_pos)3318 void Graph2d3d::change_attributs(int hp_pos){ 3319 if (!hp || hp_pos<0) 3320 return; 3321 gen g=hp->parse(hp_pos); 3322 const giac::context * contextptr = hp->contextptr; 3323 gen g2(g),pntname,delta,description; 3324 if (g.is_symb_of_sommet(at_sto)){ 3325 gen & gf=g._SYMBptr->feuille; 3326 if (gf.type==_VECT && gf._VECTptr->size()==2){ 3327 g2=gf._VECTptr->front(); 3328 pntname=gf._VECTptr->back(); 3329 description=gf._VECTptr->front(); 3330 } 3331 } 3332 bool changepntname=is_zero(pntname.type); 3333 if (changepntname){ 3334 pntname=gen(autoname(hp->contextptr),hp->contextptr); 3335 description=g; 3336 autoname_plus_plus(); 3337 } 3338 // A:=point() or A:=point()+... 3339 if (g2.is_symb_of_sommet(at_plus)){ 3340 gen & g2f=g2._SYMBptr->feuille; 3341 if (g2f.type==_VECT && g2f._VECTptr->size()>=2){ 3342 g2=g2f._VECTptr->front(); 3343 delta=symbolic(at_plus,vecteur(g2f._VECTptr->begin()+1,g2f._VECTptr->end())); 3344 } 3345 } 3346 int def=default_color(hp->contextptr); 3347 if (g2.is_symb_of_sommet(at_couleur) || g2.is_symb_of_sommet(at_display)){ 3348 g2=g2._SYMBptr->feuille; 3349 if (g2.type==_VECT && g2._VECTptr->size()==2 && g2._VECTptr->back().type==_INT_){ 3350 def=g2._VECTptr->back().val; 3351 g2=g2._VECTptr->front(); 3352 } 3353 } 3354 if (g2.type==_SYMB){ 3355 gen g3=g2._SYMBptr->feuille; 3356 if (g3.type!=_VECT) 3357 g3=gen(vecteur(1,g3),_SEQ__VECT); 3358 if (g3.type==_VECT && !g3._VECTptr->empty()){ 3359 vecteur attributs(1,def); 3360 int s=read_attributs(*g3._VECTptr,attributs,contextptr); 3361 vecteur v3(g3._VECTptr->begin(),g3._VECTptr->begin()+s); 3362 if (s){ 3363 int g6=attributs[0].val; 3364 bool b,formel=g2.is_symb_of_sommet(at_point) && is_numeric(v3),untranslate=false; 3365 int r=change_line_type(g6,false,b,pntname.print(contextptr)+": "+description.print(contextptr),(dynamic_cast<Graph3d *>(this)),formel,untranslate,true,labelsize()); 3366 if (r!=1){ 3367 if (untranslate) 3368 delta=0; 3369 if (r==2){ 3370 hp->remove_entry(hp_pos); 3371 hp->update(); 3372 hp->resize(); 3373 } 3374 else { 3375 if (changepntname || formel || untranslate || g6!=attributs[0].val){ 3376 int v3s=0; 3377 vecteur savev; 3378 if (formel){ 3379 v3s=v3.size(); 3380 if (v3s>3) 3381 v3s=3; 3382 if (v3s==1){ 3383 v3.push_back(im(v3[0],contextptr)); 3384 v3[0]=re(v3[0],contextptr); 3385 v3s=2; 3386 } 3387 if (v3s>0){ 3388 savev.push_back(makevecteur(v3[0],window_xmin,window_xmax)); 3389 v3[0]=gen(pntname.print(contextptr)+"x",hp->contextptr); 3390 } 3391 if (v3s>1){ 3392 savev.push_back(makevecteur(v3[1],window_ymin,window_ymax)); 3393 v3[1]=gen(pntname.print(contextptr)+"y",hp->contextptr); 3394 } 3395 if (v3s>2){ 3396 savev.push_back(makevecteur(v3[2],window_zmin,window_zmax)); 3397 v3[2]=gen(pntname.print(contextptr)+"z",hp->contextptr); 3398 } 3399 } 3400 gen g7(symbolic(g2._SYMBptr->sommet,gen(v3,_SEQ__VECT))); 3401 g7=add_attributs(g7,g6,contextptr); 3402 g7=symbolic(at_sto,makevecteur((is_zero(delta)?g7:symbolic(at_plus,makevecteur(g7,delta))),pntname)); 3403 hp->set_gen_value(hp_pos,g7,false); 3404 for (int k=v3s-1;k>=0;k--){ 3405 hp->add_entry(hp_pos); 3406 hp->set_gen_value(hp_pos,symbolic(at_assume,symbolic(at_equal,makevecteur(v3[k],savev[k]))),false); 3407 } 3408 hp->update(hp_pos-1); 3409 } 3410 } // end else r==-1 3411 } // end if (r) 3412 } // end if (s) 3413 } 3414 } 3415 hp->focus(hp_pos); 3416 } 3417 change_attributs()3418 void Graph2d3d::change_attributs(){ 3419 if (!hp) 3420 return; 3421 if (!selected.empty()){ 3422 int i=findfirstpoint(selection2vecteur(selected)); 3423 if (i>=0 && i<selected.size()) 3424 hp_pos=selected[i]; 3425 else 3426 hp_pos=selected.front(); 3427 change_attributs(hp_pos); 3428 selected.clear(); 3429 } // end if selected.empty() 3430 } 3431 find_eps()3432 double Graph2d3d::find_eps(){ 3433 double dx=window_xmax-window_xmin; 3434 double dy=window_ymax-window_ymin; 3435 double dz=window_zmax-window_zmin; 3436 double eps,epsx,epsy; 3437 int L=h()>w()?w():h(); 3438 Graph3d * gr3d=dynamic_cast<Graph3d *>(this); 3439 epsx=(npixels*dx)/(gr3d?L:w()); 3440 epsy=(npixels*dy)/(gr3d?L:h()); 3441 eps=(epsx<epsy)?epsy:epsx; 3442 if (gr3d && dz>dy && dz >dx){ 3443 eps=npixels*dz/L; 3444 eps *= 2; 3445 } 3446 return eps; 3447 } 3448 geo_handle(int event)3449 int Graph2d3d::geo_handle(int event){ 3450 Graph3d * gr3d = dynamic_cast<Graph3d *>(this); 3451 Graph2d * gr2d = dynamic_cast<Graph2d *>(this); 3452 if (!gr2d && !gr3d) 3453 return 0; 3454 if (!hp) 3455 return 0; 3456 if (gr3d && !gr3d->push_in_area){ 3457 if (event==FL_RELEASE && Fl::event_button()== FL_RIGHT_MOUSE ){ 3458 pushed=moving=moving_frame=false; 3459 change_attributs(); 3460 args_tmp.clear(); 3461 return 1; 3462 } 3463 return 0; 3464 } 3465 if ( (event==FL_KEYBOARD && Fl::event_key()==FL_Escape ) || (!in_area && event==FL_RELEASE) ){ 3466 pushed=false; 3467 moving=moving_frame=false; 3468 args_tmp.clear(); 3469 redraw(); 3470 return 1; 3471 } 3472 context * contextptr=hp?hp->contextptr:get_context(this); 3473 double eps=find_eps(); 3474 int pos; 3475 gen tmp,tmp2,decal; 3476 if ( pushed && !moving && !moving_frame && mode ==0 && in_area && event==FL_DRAG){ 3477 redraw(); 3478 return 1; 3479 } 3480 if (mode>=2 && event==FL_MOVE && args_tmp.size()>mode) 3481 event=FL_RELEASE; 3482 if ( in_area && ((mode!=1 && event==FL_DRAG) || event==FL_PUSH || event==FL_RELEASE || (mode>=2 && event==FL_MOVE)) ){ 3483 double newx,newy,newz; 3484 find_xyz(current_i,current_j,current_depth,newx,newy,newz); 3485 round3(newx,window_xmin,window_xmax); 3486 round3(newy,window_ymin,window_ymax); 3487 if (gr3d) 3488 round3(newz,window_zmin,window_zmax); 3489 tmp=geometry_round(newx,newy,newz,eps,tmp2,pos,mode==0 || (args_tmp.size()==mode && function_final.type==_FUNC && equalposcomp(transformation_functions,*function_final._FUNCptr)),event==FL_RELEASE); 3490 if (tmp.type==_VECT && tmp._VECTptr->size()==3){ 3491 tmp.subtype=_SEQ__VECT; 3492 tmp=symbolic(at_point,tmp); 3493 } 3494 else { 3495 if (tmp.type!=_IDNT && !tmp.is_symb_of_sommet(at_extract_measure)){ 3496 tmp=symbolic(at_point,makevecteur(re(tmp,contextptr),im(tmp,contextptr))); 3497 } 3498 } 3499 } 3500 double newx,newy,newz; 3501 if (gr2d){ 3502 int dw=w()-(show_axes?int(ylegende*labelsize()):0),dh=h()-(show_axes?((title.empty()?1:2)*labelsize()):0); 3503 double dx=window_xmax-window_xmin; 3504 double dy=window_ymax-window_ymin; 3505 double x_scale=dx/dw,y_scale=dy/dh; 3506 newx=(current_i-push_i)*x_scale; 3507 newy=(push_j-current_j)*y_scale; 3508 newz=0; 3509 } 3510 else { 3511 double x1,y1,z1,x2,y2,z2; 3512 find_xyz(current_i,current_j,current_depth,x1,y1,z1); 3513 find_xyz(push_i,push_j,push_depth,x2,y2,z2); 3514 newx=x1-x2; newy=y1-y2; newz=z1-z2; 3515 } 3516 round3(newx,window_xmin,window_xmax); 3517 round3(newy,window_ymin,window_ymax); 3518 if (gr3d){ 3519 round3(newz,window_zmin,window_zmax); 3520 decal=in_area?geometry_round_numeric(newx,newy,newz,eps,approx):0; 3521 } 3522 else 3523 decal=in_area?geometry_round_numeric(newx,newy,eps,approx):0; 3524 // cerr << in_area << " " << decal << '\n'; 3525 if (event==FL_RELEASE && Fl::event_button()== FL_RIGHT_MOUSE && (is_zero(decal)) ){ 3526 pushed=moving=moving_frame=false; 3527 change_attributs(); 3528 args_tmp.clear(); 3529 return 1; 3530 } 3531 if (mode==0 || mode==255) { 3532 if (event==FL_PUSH){ 3533 // select object && flag to move it 3534 if (mode==0 && pos>=0){ 3535 if (tmp.type==_IDNT){ 3536 drag_original_value=tmp2; 3537 drag_name=tmp; 3538 } 3539 else { 3540 drag_original_value=hp->parse(pos); 3541 drag_name=0; 3542 } 3543 hp_pos=pos; 3544 moving = true; 3545 } 3546 else { // nothing selected, move frame 3547 if (!(display_mode & 0x80)) // disabled by default in 3-d 3548 moving_frame=true; 3549 } 3550 return 1; 3551 } 3552 if (moving_frame && (event==FL_DRAG || event==FL_RELEASE) ){ 3553 window_xmin -= newx; 3554 window_xmax -= newx; 3555 window_ymin -= newy; 3556 window_ymax -= newy; 3557 window_zmin -= newz; 3558 window_zmax -= newz; 3559 push_i = current_i; 3560 push_j = current_j; 3561 redraw(); 3562 if (event==FL_RELEASE) 3563 moving_frame=false; 3564 return 1; 3565 } 3566 if (mode==255) 3567 return 0; 3568 if (moving && (event==FL_DRAG || event==FL_RELEASE) ){ 3569 if (mouse_position) mouse_position->redraw(); 3570 // cerr << current_i << " " << current_j << '\n'; 3571 // avoid point()+complex+complex+complex 3572 gen newval; 3573 if (drag_original_value.is_symb_of_sommet(at_plus) && drag_original_value._SYMBptr->feuille.type==_VECT && drag_original_value._SYMBptr->feuille._VECTptr->size()>=2){ 3574 vecteur v=*drag_original_value._SYMBptr->feuille._VECTptr; 3575 if (v[1].is_symb_of_sommet(at_nop)) 3576 v[1]=v[1]._SYMBptr->feuille; 3577 newval=symbolic(at_plus,makevecteur(v[0],symbolic(at_nop,ratnormal(_plus(vecteur(v.begin()+1,v.end()),contextptr)+decal)))); 3578 } 3579 else { 3580 newval=is_zero(decal)?drag_original_value:symbolic(at_plus,makevecteur(drag_original_value,symbolic(at_nop,decal))); 3581 } 3582 int dclick = Fl::event_clicks() || drag_original_value.type==_VECT; 3583 if (!dclick){ 3584 if (drag_name.type==_IDNT) 3585 do_handle(symbolic(at_sto,makevecteur(in_area?newval:drag_original_value,drag_name))); 3586 else 3587 do_handle(in_area?newval:drag_original_value); 3588 } 3589 if (event==FL_RELEASE) 3590 moving=false; 3591 if (event==FL_RELEASE && dclick ){ 3592 if(is_zero(decal)) 3593 change_attributs(); // Change object properties 3594 } 3595 selected.clear(); 3596 redraw(); 3597 return 1; 3598 } 3599 return 0; 3600 } 3601 selected.clear(); 3602 if (mode==1){ 3603 if (function_final!=at_point){ 3604 if (event==FL_RELEASE){ 3605 string args=autoname(contextptr)+":="; 3606 if (function_final.type==_FUNC) 3607 args += function_final._FUNCptr->ptr()->s; 3608 args +="("; 3609 if (function_final==at_plotode) 3610 args += fcnfield + "," + fcnvars + "," +tmp.print(contextptr) + ",plan)"; 3611 else 3612 args += tmp.print(contextptr) + ")"; 3613 autoname_plus_plus(); 3614 hp->set_value(-1,args,true); 3615 } 3616 if (event==FL_PUSH || event==FL_DRAG || event==FL_RELEASE) 3617 return 1; 3618 return 0; 3619 } 3620 // point|segment mode 3621 if (event==FL_RELEASE){ 3622 hp_pos=-1; 3623 if (hp && !args_tmp.empty() && (std::abs(push_i-current_i)>npixels || std::abs(push_j-current_j)>npixels || (gr3d && std::abs(push_depth-current_depth) >0)) ){ 3624 // make a segment 3625 gen val1,val2; 3626 if (in_area && args_tmp.front().is_symb_of_sommet(at_point)){ 3627 val1=gen(autoname(hp->contextptr),hp->contextptr); 3628 // put in last history pack level 3629 hp->set_gen_value(-1,symbolic(at_sto,makevecteur(add_attributs(args_tmp.front(),couleur,contextptr),val1)),false); 3630 hp_pos=hp->children()-1; 3631 autoname_plus_plus(); 3632 } 3633 else 3634 val1=args_tmp.front(); 3635 if (in_area && tmp.is_symb_of_sommet(at_point)){ 3636 val2=gen(autoname(hp->contextptr),hp->contextptr); 3637 gen tmp3=symbolic(at_sto,makevecteur(add_attributs(tmp,couleur,contextptr),val2)); 3638 hp->set_gen_value(-1,tmp3,false); 3639 if (hp_pos<0) hp_pos=hp->children()-1; 3640 autoname_plus_plus(); 3641 } 3642 else 3643 val2=tmp; 3644 if (in_area){ 3645 gen tmp3=add_attributs(symbolic(at_segment,makevecteur(val1,val2)),couleur,contextptr); 3646 string v1v2=val1.print(contextptr)+val2.print(contextptr); 3647 gen g1g2(v1v2,hp->contextptr); 3648 if (g1g2.type!=_IDNT) 3649 g1g2=gen(v1v2+"_",hp->contextptr); 3650 tmp3=symbolic(at_sto,makevecteur(tmp3,g1g2)); 3651 hp->set_gen_value(-1,tmp3,false); 3652 if (hp_pos<0) hp_pos=hp->children()-1; 3653 hp->update(hp_pos); 3654 } 3655 return 1; 3656 } 3657 if (in_area && tmp.type!=_IDNT) 3658 do_handle(symbolic(at_sto,makevecteur(add_attributs(tmp,couleur,contextptr),gen(autoname(hp->contextptr),hp->contextptr)))); 3659 // element 3660 if (tmp.type==_IDNT && tmp2.type==_SYMB && !equalposcomp(point_sommet_tab_op,tmp2._SYMBptr->sommet)){ 3661 // tmp2 is the geo object, find parameter value 3662 double newx,newy,newz; 3663 find_xyz(current_i,current_j,current_depth,newx,newy,newz); 3664 round3(newx,window_xmin,window_xmax); 3665 round3(newy,window_ymin,window_ymax); 3666 gen t=projection(evalf(tmp2,1,hp->contextptr),gen(newx,newy),hp->contextptr); 3667 if (is_undef(t)) 3668 return 0; 3669 gen tmp3=symbolic(at_element,( (t.type<_IDNT || t.type==_VECT)?gen(makevecteur(tmp,t),_SEQ__VECT):tmp)); 3670 tmp3=symbolic(at_sto,makevecteur(add_attributs(tmp3,couleur,contextptr),gen(autoname(hp->contextptr),hp->contextptr))); 3671 hp->set_gen_value(-1,tmp3,false); 3672 if (hp_pos<0) hp_pos=hp->children()-1; 3673 hp->update(hp_pos); 3674 } 3675 return 1; 3676 } 3677 if (event==FL_PUSH){ 3678 args_tmp=vecteur(1,tmp); 3679 return 1; 3680 } 3681 if (event==FL_DRAG){ 3682 redraw(); 3683 if (mouse_position) mouse_position->redraw(); 3684 return 1; 3685 } 3686 return 0; 3687 } 3688 gen tmpval=remove_at_pnt(tmp.eval(1,contextptr)); 3689 gen somm=symbolic(at_sommets,tmp); 3690 int npoints=1; 3691 if (!equalposcomp(nosplit_polygon_function,*function_final._FUNCptr)){ 3692 if (tmpval.type==_VECT && tmpval.subtype==_GROUP__VECT) 3693 npoints=tmpval._VECTptr->size(); 3694 if (tmpval.is_symb_of_sommet(at_cercle)) 3695 npoints=gr2d?2:3; 3696 } 3697 unsigned args_size=args_tmp.size(); 3698 // mode>=2 3699 if (event==FL_MOVE || event==FL_DRAG || event==FL_RELEASE || event==FL_PUSH){ 3700 if (args_size<args_tmp_push_size) 3701 args_tmp_push_size=args_size; 3702 args_tmp.erase(args_tmp.begin()+args_tmp_push_size,args_tmp.end()); 3703 } 3704 unsigned new_args_size=args_tmp.size(); 3705 gen tmp_push=tmp; 3706 bool swapargs=false; 3707 if (npoints==2 && (new_args_size==2 || new_args_size==1) && (function_final==at_angleat || function_final==at_angleatraw) ){ 3708 // search if args_tmp[0] or args_tmp[1] is a vertex of tmp 3709 gen tmp2=remove_at_pnt(evalf(tmp,1,contextptr)); 3710 gen somm=symbolic(at_sommets,tmp); 3711 if (tmp2.type==_VECT && tmp2._VECTptr->size()==2){ 3712 gen tmpa=remove_at_pnt(evalf(args_tmp[0],1,contextptr)); 3713 gen tmpb=new_args_size==2?remove_at_pnt(evalf(args_tmp[1],1,contextptr)):undef; 3714 if (npoints==2 && tmpa==tmp2._VECTptr->front() && tmpb!=tmp2._VECTptr->back()){ 3715 tmp=symbolic(at_at,gen(makevecteur(somm,1),_SEQ__VECT)); 3716 npoints=1; 3717 } 3718 if (npoints==2 && tmpa==tmp2._VECTptr->back() && tmpb!=tmp2._VECTptr->front()){ 3719 tmp=symbolic(at_at,gen(makevecteur(somm,0),_SEQ__VECT)); 3720 npoints=1; 3721 } 3722 if (npoints==2 && tmpb==tmp2._VECTptr->front() && tmpa!=tmp2._VECTptr->back() ){ 3723 swapargs=true; 3724 tmp=symbolic(at_at,gen(makevecteur(somm,1),_SEQ__VECT)); 3725 npoints=1; 3726 } 3727 if (npoints==2 && tmpb==tmp2._VECTptr->back() && tmpa!=tmp2._VECTptr->front()){ 3728 swapargs=true; 3729 tmp=symbolic(at_at,gen(makevecteur(somm,0),_SEQ__VECT)); 3730 npoints=1; 3731 } 3732 } 3733 } 3734 if (npoints+args_tmp.size()>mode) 3735 npoints=1; 3736 if (event==FL_MOVE || event==FL_DRAG || event==FL_RELEASE){ 3737 if (mouse_position) mouse_position->redraw(); 3738 if (args_size && args_tmp_push_size && args_push!=tmp_push){ 3739 // replace by current mouse position 3740 if (npoints==1) 3741 args_tmp.push_back(tmp); 3742 else { 3743 gen somm=symbolic(at_sommets,tmp); 3744 for (int i=0;i<npoints;++i){ 3745 args_tmp.push_back(symbolic(at_at,gen(makevecteur(somm,i),_SEQ__VECT))); 3746 } 3747 } 3748 redraw(); 3749 if (event!=FL_RELEASE || (abs(push_i-current_i)<=5 && abs(push_j-current_j)<=5)) 3750 return 1; 3751 } 3752 } 3753 if (event==FL_PUSH){ 3754 if (swapargs) 3755 swapgen(args_tmp[0],args_tmp[1]); 3756 args_push=tmp_push; 3757 if (npoints==1) 3758 args_tmp.push_back(tmp); 3759 else { 3760 for (int i=0;i<npoints;++i){ 3761 args_tmp.push_back(symbolic(at_at,gen(makevecteur(somm,i),_SEQ__VECT))); 3762 } 3763 } 3764 args_tmp_push_size=args_tmp.size(); 3765 redraw(); 3766 return 1; 3767 } 3768 if (event==FL_RELEASE){ 3769 int s=args_tmp.size(); 3770 args_tmp_push_size=s; 3771 int save_undo_position=hp->undo_position; 3772 if (mode>1 && s>=mode){ 3773 if (s>mode){ 3774 args_tmp=vecteur(args_tmp.begin(),args_tmp.begin()+mode); 3775 s=mode; 3776 } 3777 gen tmp_plot; 3778 if (in_area && function_final.type==_FUNC) { 3779 gen res,objname=gen(autoname(hp->contextptr),hp->contextptr); 3780 hp_pos=hp->children()-1; 3781 hp->update_pos=hp_pos; 3782 int pos0=hp_pos; 3783 unary_function_ptr * ptr=function_final._FUNCptr; 3784 int ifinal=mode; 3785 if (equalposcomp(measure_functions,*ptr)) 3786 ifinal--; 3787 // first replace points in args_tmp by assignations 3788 for (int i=0;i<ifinal;++i){ 3789 tmp_plot=args_tmp[i]; 3790 if (tmp_plot.is_symb_of_sommet(at_point)){ 3791 tmp_plot=symbolic(at_sto,makevecteur(add_attributs(tmp_plot,couleur,contextptr),objname)); 3792 args_tmp[i]=objname; 3793 hp->set_gen_value(hp_pos,tmp_plot,false); 3794 hp->add_entry(hp_pos+1); 3795 ++hp_pos; 3796 autoname_plus_plus(); 3797 objname=gen(autoname(hp->contextptr),hp->contextptr); 3798 } 3799 } 3800 vecteur argv=args_tmp; 3801 if (*ptr==(gr3d?at_sphere:at_cercle)){ 3802 gen argv1; 3803 try { 3804 argv1=evalf(args_tmp.back(),1,contextptr); 3805 argv1=evalf_double(argv1,1,contextptr); 3806 } 3807 catch (std::runtime_error & e){ 3808 argv1=undef; 3809 } 3810 if (argv1.is_symb_of_sommet(at_pnt) ||argv1.type==_IDNT){ 3811 argv1=remove_at_pnt(argv1); 3812 if ( (argv1.type==_VECT && argv1.subtype==_POINT__VECT) || argv1.type==_CPLX || argv1.type==_IDNT) 3813 argv.back()=args_tmp.back()-args_tmp.front(); 3814 } 3815 } 3816 tmp_plot=symbolic(*ptr,gen(argv,_SEQ__VECT)); 3817 try { 3818 res=evalf(tmp_plot,1,hp->contextptr); 3819 } 3820 catch (std::runtime_error & err){ 3821 res=undef; 3822 } 3823 tmp_plot=symbolic(at_sto,makevecteur(add_attributs(tmp_plot,couleur,contextptr),objname)); 3824 hp->set_gen_value(hp_pos,tmp_plot,false); 3825 hp->add_entry(hp_pos+1); 3826 ++hp_pos; 3827 if (res.is_symb_of_sommet(at_pnt)){ 3828 res=remove_at_pnt(res); 3829 int ns=0; 3830 if (res.type==_VECT && res.subtype==_GROUP__VECT && (ns=res._VECTptr->size())>2){ 3831 vecteur l; 3832 if (res._VECTptr->back()==res._VECTptr->front()) 3833 --ns; 3834 if (function_final.type==_FUNC && equalposcomp(transformation_functions,*function_final._FUNCptr)){ 3835 vecteur argv; 3836 gen objn,som=symbolic(at_sommets,objname); 3837 for (int i=1;i<=ns;++i){ 3838 tmp_plot=symbolic(at_at,gen(makevecteur(som,i-1),_SEQ__VECT)); 3839 objn=gen(autoname(hp->contextptr)+print_INT_(i),hp->contextptr); 3840 argv.push_back(objn); 3841 hp->set_gen_value(hp_pos,symbolic(at_sto,gen(makevecteur(tmp_plot,objn),_SEQ__VECT)),false); 3842 hp->add_entry(hp_pos+1); 3843 ++hp_pos; 3844 } 3845 for (int i=1;i<=ns;++i){ 3846 tmp_plot=symbolic(at_segment,makevecteur(argv[i-1],argv[i%ns])); 3847 hp->set_gen_value(hp_pos,symbolic(at_sto,makevecteur(add_attributs(tmp_plot,couleur,contextptr),gen(autoname(hp->contextptr)+print_INT_(ns+i),hp->contextptr))),false); 3848 hp->add_entry(hp_pos+1); 3849 ++hp_pos; 3850 } 3851 } 3852 else { 3853 for (int i=mode;i<ns;++i){ 3854 tmp_plot=symb_at( 3855 symbolic(at_sommets,gen(autoname(hp->contextptr),hp->contextptr)) 3856 ,i,hp->contextptr); 3857 gen newname=gen(autoname(hp->contextptr)+print_INT_(i),hp->contextptr); 3858 hp->set_gen_value(hp_pos,symbolic(at_sto,makevecteur(tmp_plot,newname)),false); 3859 args_tmp.push_back(newname); 3860 hp->add_entry(hp_pos+1); 3861 ++hp_pos; 3862 } 3863 for (int i=1;i<=ns;++i){ 3864 tmp_plot=symbolic(at_segment,makevecteur(args_tmp[i-1],args_tmp[i%ns])); 3865 hp->set_gen_value(hp_pos,symbolic(at_sto,makevecteur(add_attributs(tmp_plot,couleur,contextptr),gen(autoname(hp->contextptr)+print_INT_(ns+i),hp->contextptr))),false); 3866 hp->add_entry(hp_pos+1); 3867 ++hp_pos; 3868 } 3869 } 3870 } // if res.type==_VECT 3871 } 3872 autoname_plus_plus(); 3873 // hp->undo_position=save_undo_position; 3874 hp->update(pos0); 3875 } 3876 args_tmp.clear(); 3877 args_tmp_push_size=0; 3878 } 3879 redraw(); 3880 return 1; 3881 } 3882 return 0; 3883 } 3884 handle(int event)3885 int Graph2d3d::handle(int event){ 3886 if (no_handle) 3887 return 0; 3888 context * contextptr=hp?hp->contextptr:get_context(this); 3889 #ifdef HAVE_LIBPTHREAD 3890 // cerr << "handle lock" << '\n'; 3891 int locked=pthread_mutex_trylock(&interactive_mutex); 3892 if (locked) 3893 return 0; 3894 #endif 3895 no_handle=true; 3896 bool b=io_graph(contextptr); 3897 io_graph(false,contextptr); 3898 int res=in_handle(event); 3899 io_graph(b,contextptr); 3900 no_handle=false; 3901 #ifdef HAVE_LIBPTHREAD 3902 pthread_mutex_unlock(&interactive_mutex); 3903 // cerr << "handle unlock" << '\n'; 3904 #endif 3905 return res; 3906 } 3907 handle_mouse(int event)3908 int Graph2d3d::handle_mouse(int event){ 3909 if (event==FL_MOVE || event==FL_ENTER || event==FL_LEAVE){ 3910 if (mouse_position) mouse_position->redraw(); 3911 if (event==FL_MOVE && hp && show_mouse_on_object){ 3912 double newx,newy,newz; 3913 Graph3d * gr3d = dynamic_cast<Graph3d *>(this); 3914 find_xyz(Fl::event_x()-(gr3d?0:x()),Fl::event_y()-(gr3d?0:y()),current_depth,newx,newy,newz); 3915 int pos=-1; 3916 gen orig; 3917 gen res=geometry_round(newx,newy,newz,find_eps(),orig,pos); 3918 set_cursor(this, pos>=0?FL_CURSOR_HAND:FL_CURSOR_ARROW); 3919 } 3920 else 3921 set_cursor(this, FL_CURSOR_ARROW); 3922 return 1; 3923 } 3924 return 0; 3925 } 3926 handle_keyboard(int event)3927 int Graph2d3d::handle_keyboard(int event){ 3928 if (event==FL_KEYBOARD){ 3929 // Should bring this event to the current input in the parent() group 3930 switch (Fl::event_key()){ 3931 case FL_Escape: case FL_BackSpace: case FL_Tab: case FL_Enter: 3932 case FL_Print: case FL_Scroll_Lock: case FL_Pause: case FL_Insert: 3933 case FL_Home: case FL_Delete: case FL_End: 3934 case FL_Shift_L: case FL_Shift_R: case FL_Control_L: 3935 case FL_Control_R: case FL_Caps_Lock: case FL_Alt_L: case FL_Alt_R: 3936 case FL_Meta_L: case FL_Meta_R: case FL_Menu: case FL_Num_Lock: 3937 case FL_KP_Enter: 3938 return 1; 3939 case FL_Left: 3940 left((window_xmax-window_xmin)/10); 3941 return 1; 3942 case FL_Up: 3943 up((window_ymax-window_ymin)/10); 3944 return 1; 3945 case FL_Right: 3946 right((window_xmax-window_xmin)/10); 3947 return 1; 3948 case FL_Down: 3949 down((window_ymax-window_ymin)/10); 3950 return 1; 3951 case FL_Page_Up: 3952 up_z((window_zmax-window_zmin)/10); 3953 return 1; 3954 case FL_Page_Down: 3955 down_z((window_zmax-window_zmin)/10); 3956 return 1; 3957 default: 3958 char ch=Fl::event_text()?Fl::event_text()[0]:0; 3959 switch (ch){ 3960 case '-': 3961 zoom(1.414); 3962 return 1; 3963 case '+': 3964 zoom(0.707); 3965 return 1; 3966 case 'A': case 'a': 3967 autoscale(false); 3968 return 1; 3969 case 'V': case 'v': 3970 autoscale(true); 3971 return 1; 3972 case 'R': case 'r': 3973 oxyz_rotate(this,rotanim_type,rotanim_nstep,rotanim_tstep,rotanim_danim,rotanim_rx,rotanim_ry,rotanim_rz); 3974 return 1; 3975 case 'P': case 'p': 3976 paused=!paused; 3977 return 1; 3978 case 'N': case 'n': case 'F': case 'f': 3979 animation_instructions_pos++; 3980 redraw(); 3981 return 1; 3982 case 'B': case 'b': 3983 animation_instructions_pos--; 3984 redraw(); 3985 return 1; 3986 case 'C': case 'c': /* screen capture */ 3987 if (Graph3d * gr3 = dynamic_cast<Graph3d *>(this)){ 3988 char * filename = file_chooser(gettext("Export to PNG file"),"*.png","session.png"); 3989 if(!filename) return 1; 3990 gr3->opengl2png(filename); 3991 return 1; 3992 } 3993 } 3994 } 3995 } 3996 return 0; 3997 } 3998 in_handle(int event)3999 int Graph2d3d::in_handle(int event){ 4000 int res=handle_keyboard(event); 4001 return res?res:handle_mouse(event); 4002 } 4003 selection2vecteur(const vector<int> & v)4004 vecteur Graph2d3d::selection2vecteur(const vector<int> & v){ 4005 int n=v.size(); 4006 vecteur res(n); 4007 for (int i=0;i<n;++i){ 4008 res[i]=plot_instructions[v[i]]; 4009 } 4010 return res; 4011 } 4012 findfirstclosedcurve(const vecteur & v)4013 int findfirstclosedcurve(const vecteur & v){ 4014 int s=v.size(); 4015 for (int i=0;i<s;++i){ 4016 gen g=remove_at_pnt(v[i]); 4017 if (g.is_symb_of_sommet(at_cercle)) 4018 return i; 4019 if (g.type==_VECT && g.subtype==_GROUP__VECT){ 4020 vecteur & w=*g._VECTptr; 4021 if (!w.empty() && w.front()==w.back()) 4022 return i; 4023 } 4024 } 4025 return -1; 4026 } 4027 4028 // find nearest point of x+i*y, returns position in history and either 4029 // a numeric value or the point name geometry_round(double x,double y,double z,double eps,gen & original,int & pos,bool selectfirstlevel,bool setscroller)4030 gen Graph2d3d::geometry_round(double x,double y,double z,double eps,gen & original,int & pos,bool selectfirstlevel,bool setscroller) { 4031 if (!hp) 4032 return undef; 4033 context * contextptr=hp?hp->contextptr:get_context(this); 4034 gen tmp; 4035 pos=-1; 4036 if (block_signal || is_context_busy(contextptr)) 4037 return undef; 4038 geometry_round(x,y,z,eps,tmp,contextptr); 4039 if (selected.empty()) 4040 return tmp; 4041 if (function_final==at_areaatraw || function_final==at_areaat || function_final==at_perimeteratraw || function_final==at_perimeterat){ 4042 int p=findfirstclosedcurve(selection2vecteur(selected)); 4043 if (p>0){ 4044 pos=p; 4045 } 4046 } 4047 if (pos==-1){ 4048 if (selectfirstlevel){ 4049 sort(selected.begin(),selected.end()); 4050 // patch so that we move element and not the curve 4051 int p=findfirstpoint(selection2vecteur(selected)); 4052 if (p>0){ 4053 /* 4054 gen g=hp->parse(selected[p]); 4055 if (g.is_symb_of_sommet(at_sto) && g._SYMBptr->feuille.type==_VECT ){ 4056 vecteur & v = *g._SYMBptr->feuille._VECTptr; 4057 if (v.size()>1 && v[0].is_symb_of_sommet(at_element)) 4058 pos=p; 4059 } 4060 */ 4061 pos=p; 4062 } 4063 } 4064 else 4065 pos=findfirstpoint(selection2vecteur(selected)); 4066 } 4067 gen g=hp->parse( (pos<0)?(pos=selected.front()):(pos=selected[pos]) ); 4068 if (pos>=0 && pos<hp->children()){ 4069 hp->_sel_begin=hp->_sel_end=pos; 4070 if (setscroller) 4071 hp->set_scroller(dynamic_cast<Fl_Group *>(hp->child(pos))); 4072 } 4073 if (g.is_symb_of_sommet(at_plus) && g._SYMBptr->feuille.type==_VECT && !g._SYMBptr->feuille._VECTptr->empty()) 4074 g=g._SYMBptr->feuille._VECTptr->front(); 4075 if (g.is_symb_of_sommet(at_sto) && g._SYMBptr->feuille.type==_VECT ){ 4076 vecteur & v = *g._SYMBptr->feuille._VECTptr; 4077 if (v.size()==2){ 4078 original = v[0]; 4079 tmp = v[1]; 4080 if (tmp.type==_IDNT){ 4081 gen valeur=protecteval(original,1,contextptr); 4082 if (valeur.is_symb_of_sommet(at_pnt)){ 4083 gen & valf = valeur._SYMBptr->feuille; 4084 if (valf.type==_VECT){ 4085 vecteur & valv = *valf._VECTptr; 4086 int s=v.size(); 4087 if (s>1){ 4088 gen valv1=valv[1]; 4089 if (valv1.type==_VECT && valv1._VECTptr->size()>2){ 4090 tmp=symbolic(at_extract_measure,v[1]); 4091 } 4092 } 4093 } 4094 } 4095 } 4096 } 4097 } 4098 return tmp; 4099 } 4100 geometry_round(double x,double y,double z,double eps,gen & tmp,GIAC_CONTEXT)4101 void Graph2d3d::geometry_round(double x,double y,double z,double eps,gen & tmp,GIAC_CONTEXT) { 4102 } 4103 geometry_round(double x,double y,double z,double eps,gen & tmp,GIAC_CONTEXT)4104 void Graph2d::geometry_round(double x,double y,double z,double eps,gen & tmp,GIAC_CONTEXT) { 4105 tmp= geometry_round_numeric(x,y,eps,approx); 4106 try { 4107 selected=nearest_point(plot_instructions,geometry_round_numeric(x,y,eps,true),eps,contextptr); 4108 // bug bonux: when a figure is saved, plot_instructions is saved 4109 // if there are sequences in plot_instructions 4110 // they are not put back in an individual level 4111 while (!selected.empty() && selected.back()>=hp->children()) 4112 selected.pop_back(); 4113 } catch (...){ 4114 } 4115 } 4116 int2color(int couleur_)4117 gen int2color(int couleur_){ 4118 gen col; 4119 if (couleur_){ 4120 gen tmp; 4121 int val; 4122 vecteur colv; 4123 if ( (val=(couleur_ & 0x0000ffff))){ 4124 tmp=val; 4125 tmp.subtype=_INT_COLOR; 4126 colv.push_back(tmp); 4127 } 4128 if ((val =(couleur_ & 0x00070000))){ 4129 tmp=val; 4130 tmp.subtype=_INT_COLOR; 4131 colv.push_back(tmp); 4132 } 4133 if ((val =(couleur_ & 0x00380000))){ 4134 tmp=val; 4135 tmp.subtype=_INT_COLOR; 4136 colv.push_back(tmp); 4137 } 4138 if ((val =(couleur_ & 0x01c00000))){ 4139 tmp=val; 4140 tmp.subtype=_INT_COLOR; 4141 colv.push_back(tmp); 4142 } 4143 if ((val =(couleur_ & 0x0e000000))){ 4144 tmp=val; 4145 tmp.subtype=_INT_COLOR; 4146 colv.push_back(tmp); 4147 } 4148 if ((val =(couleur_ & 0x30000000))){ 4149 tmp=val; 4150 tmp.subtype=_INT_COLOR; 4151 colv.push_back(tmp); 4152 } 4153 if ((val =(couleur_ & 0x40000000))){ 4154 tmp=val; 4155 tmp.subtype=_INT_COLOR; 4156 colv.push_back(tmp); 4157 } 4158 if ((val =(couleur_ & 0x80000000))){ 4159 tmp=val; 4160 tmp.subtype=_INT_COLOR; 4161 colv.push_back(tmp); 4162 } 4163 if (colv.size()==1) 4164 col=colv.front(); 4165 else 4166 col=symbolic(at_plus,gen(colv,_SEQ__VECT)); 4167 } 4168 return col; 4169 } 4170 print_color(int couleur)4171 std::string print_color(int couleur){ 4172 return int2color(couleur).print(context0); 4173 } 4174 add_attributs(const giac::gen & g,int couleur_,GIAC_CONTEXT)4175 giac::gen add_attributs(const giac::gen & g,int couleur_,GIAC_CONTEXT) { 4176 if (g.type!=_SYMB) 4177 return g; 4178 gen & f=g._SYMBptr->feuille; 4179 if (g._SYMBptr->sommet==at_couleur && f.type==_VECT && !f._VECTptr->empty()){ 4180 gen col=couleur_; 4181 col.subtype=_INT_COLOR; 4182 vecteur v(*f._VECTptr); 4183 v.back()=col; 4184 return symbolic(at_couleur,gen(v,_SEQ__VECT)); 4185 } 4186 if (couleur_==default_color(contextptr)) 4187 return g; 4188 if (g._SYMBptr->sommet==at_of){ 4189 gen col=couleur_; 4190 col.subtype=_INT_COLOR; 4191 return symbolic(at_couleur,gen(makevecteur(g,col),_SEQ__VECT)); 4192 } 4193 vecteur v =gen2vecteur(f); 4194 gen col=int2color(couleur_); 4195 v.push_back(symbolic(at_equal,gen(makevecteur(at_display,col),_SEQ__VECT))); 4196 return symbolic(g._SYMBptr->sommet,(v.size()==1 && f.type!=_VECT)?f:gen(v,f.type==_VECT?f.subtype:_SEQ__VECT)); 4197 } 4198 set_mode(const giac::gen & f_tmp,const giac::gen & f_final,int m)4199 void Graph2d3d::set_mode(const giac::gen & f_tmp,const giac::gen & f_final,int m){ 4200 if (mode>=-1){ 4201 pushed=false; 4202 moving=moving_frame=false; 4203 history_pos=-1; 4204 mode=m; 4205 function_final=f_final; 4206 function_tmp=f_tmp; 4207 args_tmp.clear(); 4208 } 4209 } 4210 cb_set_mode(Fl_Widget * m,const gen & f_tmp,const gen & f_final,int mode,const string & help)4211 void cb_set_mode(Fl_Widget * m ,const gen & f_tmp,const gen & f_final,int mode,const string & help){ 4212 static string modestr; 4213 static bool asked=false; 4214 Figure * f=find_figure(m); 4215 if (f && f->geo){ 4216 if (!asked && mode==0 && !f->geo->approx){ 4217 int i=fl_ask("%s","Dynamic geometry works faster in approx mode. Drag in approx mode?"); 4218 if (i) 4219 f->geo->approx=true; 4220 asked=true; 4221 } 4222 if (dynamic_cast<Geo2d *>(f->geo) || dynamic_cast<Geo3d *>(f->geo)){ 4223 f->geo->selected.clear(); 4224 f->geo->redraw(); 4225 f->geo->handle(FL_FOCUS); 4226 context * contextptr=f->geo->hp?f->geo->hp->contextptr:0; 4227 f->geo->set_mode(f_tmp,f_final,mode); 4228 f->geo->args_help.clear(); 4229 if (mode!=0 && mode!=255){ 4230 int oldmode=calc_mode(contextptr); 4231 calc_mode(0,contextptr); 4232 gen g(help,contextptr); 4233 calc_mode(oldmode,contextptr); 4234 if (g.type==_VECT){ 4235 const_iterateur it = g._VECTptr->begin(),itend=g._VECTptr->end(); 4236 for (;it!=itend;++it) 4237 f->geo->args_help.push_back(it->print(contextptr)); 4238 } 4239 else 4240 f->geo->args_help.push_back(g.print(contextptr)); 4241 } 4242 } 4243 if (mode==255) 4244 modestr=gettext("Frame"); 4245 else 4246 modestr=mode?gen2string(f_final):gettext("Pointer"); 4247 f->mode->value(modestr.c_str()); 4248 } 4249 } 4250 Geo2d(int x,int y,int w,int h,History_Pack * _hp,const char * l)4251 Geo2d::Geo2d(int x,int y,int w,int h,History_Pack * _hp,const char * l): Graph2d(x,y,w,h,l) { 4252 orthonormalize(); 4253 hp=_hp?_hp:geo_find_history_pack(this); 4254 if (hp) 4255 show_mouse_on_object=true; 4256 } 4257 in_handle(int event)4258 int Geo2d::in_handle(int event){ 4259 if (!event) 4260 return 1; 4261 if (!hp) 4262 hp=geo_find_history_pack(this); 4263 // cerr << event << " " << mode << '\n'; 4264 int res=common_in_handle(event); 4265 if (Fl::event_button()==FL_RIGHT_MOUSE && res && mode==255) 4266 return res; // right click desactivated 4267 if (event==FL_UNFOCUS){ 4268 return 1; 4269 } 4270 if (event==FL_FOCUS){ 4271 Fl::focus(this); 4272 return 1; 4273 } 4274 if (int gres=geo_handle(event)) 4275 return gres; 4276 // event not handeld by geometry 4277 return res; 4278 } 4279 fltk_point(int deltax,int deltay,int i0,int j0,int epaisseur_point,int type_point)4280 void fltk_point(int deltax,int deltay,int i0,int j0,int epaisseur_point,int type_point){ 4281 fl_line_style(FL_SOLID,epaisseur_point-1,0); 4282 switch (type_point){ 4283 case 1: // losange 4284 fl_line(deltax+i0-epaisseur_point,deltay+j0,deltax+i0,deltay+j0-epaisseur_point); 4285 fl_line(deltax+i0,deltay+j0-epaisseur_point,deltax+i0+epaisseur_point,deltay+j0); 4286 fl_line(deltax+i0-epaisseur_point,deltay+j0,deltax+i0,deltay+j0+epaisseur_point); 4287 fl_line(deltax+i0,deltay+j0+epaisseur_point,deltax+i0+epaisseur_point,deltay+j0); 4288 break; 4289 case 2: // croix verticale 4290 fl_line(deltax+i0,deltay+j0-epaisseur_point,deltax+i0,deltay+j0+epaisseur_point); 4291 fl_line(deltax+i0-epaisseur_point,deltay+j0,deltax+i0+epaisseur_point,deltay+j0); 4292 break; 4293 case 3: // carre 4294 fl_line(deltax+i0-epaisseur_point,deltay+j0-epaisseur_point,deltax+i0-epaisseur_point,deltay+j0+epaisseur_point); 4295 fl_line(deltax+i0+epaisseur_point,deltay+j0-epaisseur_point,deltax+i0+epaisseur_point,deltay+j0+epaisseur_point); 4296 fl_line(deltax+i0-epaisseur_point,deltay+j0-epaisseur_point,deltax+i0+epaisseur_point,deltay+j0-epaisseur_point); 4297 fl_line(deltax+i0-epaisseur_point,deltay+j0+epaisseur_point,deltax+i0+epaisseur_point,deltay+j0+epaisseur_point); 4298 break; 4299 case 5: // triangle 4300 fl_line(deltax+i0-epaisseur_point,deltay+j0,deltax+i0,deltay+j0-epaisseur_point); 4301 fl_line(deltax+i0,deltay+j0-epaisseur_point,deltax+i0+epaisseur_point,deltay+j0); 4302 fl_line(deltax+i0-epaisseur_point,deltay+j0,deltax+i0+epaisseur_point,deltay+j0); 4303 break; 4304 case 7: // point 4305 if (epaisseur_point>2) 4306 fl_arc(deltax+i0-(epaisseur_point-1),deltay+j0-(epaisseur_point-1),2*(epaisseur_point-1),2*(epaisseur_point-1),0,360); 4307 else 4308 fl_line(deltax+i0,deltay+j0,deltax+i0+1,deltay+j0); 4309 break; 4310 case 6: // etoile 4311 fl_line(deltax+i0-epaisseur_point,deltay+j0,deltax+i0+epaisseur_point,deltay+j0); 4312 // no break to add the following lines 4313 case 0: // 0 croix diagonale 4314 fl_line(deltax+i0-epaisseur_point,deltay+j0-epaisseur_point,deltax+i0+epaisseur_point,deltay+j0+epaisseur_point); 4315 fl_line(deltax+i0-epaisseur_point,deltay+j0+epaisseur_point,deltax+i0+epaisseur_point,deltay+j0-epaisseur_point); 4316 break; 4317 default: // 4 nothing drawn 4318 break; 4319 } 4320 fl_line_style(0); 4321 } 4322 draw()4323 void Geo2d::draw(){ 4324 if (!hp) 4325 hp=geo_find_history_pack(this); 4326 context * contextptr = hp?hp->contextptr:0; 4327 int locked=0; 4328 #ifdef HAVE_LIBPTHREAD 4329 // cerr << "geo2d draw lock" << '\n'; 4330 locked=pthread_mutex_trylock(&interactive_mutex); 4331 #endif 4332 bool b,block; 4333 if (!locked){ 4334 b=io_graph(contextptr); 4335 io_graph(contextptr)=false; 4336 block=block_signal; 4337 block_signal=true; 4338 } 4339 int clip_x,clip_y,clip_w,clip_h; 4340 // cerr << "geo2d draw block signal " << this << '\n'; 4341 fl_clip_box(x(),y(),w(),h(),clip_x,clip_y,clip_w,clip_h); 4342 fl_push_clip(clip_x,clip_y,clip_w,clip_h); 4343 int vertical_pixels; 4344 in_draw(clip_x,clip_y,clip_w,clip_h,vertical_pixels); 4345 int horizontal_pixels=w()-(show_axes?int(ylegende*labelsize()):0); 4346 int deltax=x(),deltay=y(); 4347 if (mode<255 && abs_calc_mode(contextptr)==38){ 4348 fl_color(FL_CYAN); 4349 fltk_point(deltax,deltay,current_i,current_j,cursor_point_type,cursor_point_type); 4350 } 4351 // Draw mouse drag 4352 if ( pushed && !waiting_click &&(current_i>=0 && current_i<=horizontal_pixels) && (current_j>=0 && current_j <=vertical_pixels) && (user_screen || (push_i!=current_i) || (push_j!=current_j))){ 4353 fl_color(FL_RED); 4354 if ( (mode==255 && Fl::event_button()==FL_RIGHT_MOUSE) || (mode==0 && !moving && !moving_frame) ) 4355 check_fl_rect(deltax+min(push_i,current_i),deltay+min(push_j,current_j),absint(current_i-push_i),absint(current_j-push_j),clip_x,clip_y,clip_w,clip_h,0,0); 4356 else 4357 check_fl_line(deltax+push_i,deltay+push_j,deltax+current_i,deltay+current_j,clip_x,clip_y,clip_w,clip_h,0,0); 4358 } 4359 fl_pop_clip(); 4360 ++animation_instructions_pos; 4361 if (!locked){ 4362 block_signal=block; 4363 // cerr << "geo2d draw unblock signal " << this << '\n'; 4364 io_graph(contextptr)=b; 4365 #ifdef HAVE_LIBPTHREAD 4366 pthread_mutex_unlock(&interactive_mutex); 4367 // cerr << "geo2d draw unlock" << '\n'; 4368 #endif 4369 } 4370 } 4371 swapint(int & i0,int & i1)4372 inline void swapint(int & i0,int & i1){ 4373 int tmp=i0; 4374 i0=i1; 4375 i1=tmp; 4376 } 4377 check_fl_draw(const char * ch,int i0,int j0,int imin,int jmin,int di,int dj,int delta_i,int delta_j)4378 void check_fl_draw(const char * ch,int i0,int j0,int imin,int jmin,int di,int dj,int delta_i,int delta_j){ 4379 /* int n=fl_size(); 4380 if (j0>=jmin-n && j0<=jmin+dj+n) */ 4381 // cerr << i0 << " " << j0 << '\n'; 4382 if (strlen(ch)>2000) 4383 fl_draw("String too long for display",i0+delta_i,j0+delta_j); 4384 else 4385 fl_draw(ch,i0+delta_i,j0+delta_j); 4386 } 4387 check_fl_point(int i0,int j0,int imin,int jmin,int di,int dj,int delta_i,int delta_j)4388 void check_fl_point(int i0,int j0,int imin,int jmin,int di,int dj,int delta_i,int delta_j){ 4389 /* if (i0>=imin && i0<=imin+di && j0>=jmin && j0<=jmin+dj) */ 4390 fl_point(i0+delta_i,j0+delta_j); 4391 } 4392 check_fl_rect(int i0,int j0,int i1,int j1,int imin,int jmin,int di,int dj,int delta_i,int delta_j)4393 void check_fl_rect(int i0,int j0,int i1,int j1,int imin,int jmin,int di,int dj,int delta_i,int delta_j){ 4394 /* bool clipped=false; 4395 if (imin>i0 || jmin>j0){ 4396 check_fl_line(i0,j0,i0+i1,j0,imin,jmin,di,dj,delta_i,delta_j); 4397 check_fl_line(i0,j0,i0,j0+j1,imin,jmin,di,dj,delta_i,delta_j); 4398 check_fl_line(i0,j0+j1,i0+i1,j0+j1,imin,jmin,di,dj,delta_i,delta_j); 4399 check_fl_line(i0+i1,j0,i0+i1,j0+j1,imin,jmin,di,dj,delta_i,delta_j); 4400 } 4401 else 4402 fl_rect(i0+delta_i,j0+delta_j,min(i1,di),min(j1,dj)); 4403 */ 4404 fl_rect(i0+delta_i,j0+delta_j,i1,j1); 4405 } 4406 check_fl_rectf(int x,int y,int w,int h,int imin,int jmin,int di,int dj,int delta_i,int delta_j)4407 void check_fl_rectf(int x,int y,int w,int h,int imin,int jmin,int di,int dj,int delta_i,int delta_j){ 4408 /* if (x<imin){ 4409 w -= (imin-x); // di -= (imin-x); 4410 x=imin; 4411 } 4412 if (y<jmin){ 4413 h -= (jmin-y); // dj -= (jmin-y); 4414 y=jmin; 4415 } 4416 if (w<=0 || di<=0 || h<=0 || dj<=0) 4417 return ; 4418 fl_rectf(x+delta_i,y+delta_j,min(w,di),min(h,dj)); 4419 */ 4420 fl_rectf(x+delta_i,y+delta_j,w,h); 4421 } 4422 4423 // Calls fl_line, checking with bounds check_fl_line(int i0,int j0,int i1,int j1,int imin,int jmin,int di,int dj,int delta_i,int delta_j)4424 void check_fl_line(int i0,int j0,int i1,int j1,int imin,int jmin,int di,int dj,int delta_i,int delta_j){ 4425 /* int imax=imin+di,jmax=jmin+dj; 4426 if (i0>i1){ 4427 swapint(i0,i1); 4428 swapint(j0,j1); 4429 } 4430 if (i0>=imax || i1<=imin) 4431 return; 4432 if (i0!=i1){ 4433 // Compute line slope 4434 double m=(j1-j0)/double(i1-i0); 4435 if (i0<imin){ // replace i0 by imin, compute corresp. j0 4436 j0 += int(floor((imin-i0)*m+.5)); 4437 i0 = imin; 4438 } 4439 if (i1>imax){ 4440 j1 += int(floor((imax-i1)*m+.5)); 4441 i1 = imax; 4442 } 4443 } 4444 if (j0>j1){ 4445 if (j1>=jmax || j0<=jmin) 4446 return; 4447 // Compute line slope 4448 double m=(i1-i0)/double(j1-j0); 4449 if (j0>jmax){ 4450 i0 += int(floor((jmax-j0)*m+.5)); 4451 j0 = jmax; 4452 } 4453 if (j1<jmin){ 4454 i1 += int(floor((jmin-j1)*m+.5)); 4455 j1 = jmin; 4456 } 4457 } 4458 else { 4459 if (j0>=jmax || j1<=jmin) 4460 return; 4461 if (j0!=j1){ 4462 // Compute line slope 4463 double m=(i1-i0)/double(j1-j0); 4464 if (j0<jmin){ 4465 i0 += int(floor((jmin-j0)*m+.5)); 4466 j0 = jmin; 4467 } 4468 if (j1>jmax){ 4469 i1 += int(floor((jmax-j1)*m+.5)); 4470 j1 = jmax; 4471 } 4472 } 4473 } */ 4474 fl_line(i0+delta_i,j0+delta_j,i1+delta_i,j1+delta_j); 4475 } 4476 4477 int logplot_points=20; 4478 checklog_fl_line(double i0,double j0,double i1,double j1,double deltax,double deltay,bool logx,bool logy,double window_xmin,double x_scale,double window_ymax,double y_scale)4479 void checklog_fl_line(double i0,double j0,double i1,double j1,double deltax,double deltay,bool logx,bool logy,double window_xmin,double x_scale,double window_ymax,double y_scale){ 4480 if (!logx && !logy){ 4481 fl_line(round(i0+deltax),round(j0+deltay),round(i1+deltax),round(j1+deltay)); 4482 return; 4483 } 4484 // interpolate (i0,j0)->(i1,j1) 4485 // if log enabled i0=(log10(x0)-window_xmin)*x_scale -> x0=pow10(i0/x_scale+window_xmin) 4486 // j0=(window_ymax-log10(y1))*y_scale -> y1=pow10(window_ymax-j0/y_scale) 4487 if (logx && logy){ 4488 double prevx=i0,prevy=j0,curx,cury; 4489 double I0=pow10(i0/x_scale+window_xmin),I1=pow10(i1/x_scale+window_xmin), 4490 J0=pow10(window_ymax-j0/y_scale),J1=pow10(window_ymax-j1/y_scale); 4491 for (int i=1;i<logplot_points;++i){ 4492 double t=double(i)/logplot_points; 4493 curx=(log10(I0+t*(I1-I0))-window_xmin)*x_scale; 4494 cury=(window_ymax-log10(J0+t*(J1-J0)))*y_scale; 4495 fl_line(round(prevx+deltax),round(prevy+deltay),round(curx+deltax),round(cury+deltay)); 4496 prevx=curx; prevy=cury; 4497 } 4498 return; 4499 } 4500 if (logy){ 4501 double prevx=i0,prevy=j0,curx,cury; 4502 double J0=pow10(window_ymax-j0/y_scale),J1=pow10(window_ymax-j1/y_scale); 4503 for (int i=1;i<logplot_points;++i){ 4504 double t=double(i)/logplot_points; 4505 curx=i0+t*(i1-i0); 4506 cury=(window_ymax-log10(J0+t*(J1-J0)))*y_scale; 4507 fl_line(round(prevx+deltax),round(prevy+deltay),round(curx+deltax),round(cury+deltay)); 4508 prevx=curx; prevy=cury; 4509 } 4510 return; 4511 } 4512 // logx 4513 double prevx=i0,prevy=j0,curx,cury; 4514 double I0=pow10(i0/x_scale+window_xmin),I1=pow10(i1/x_scale+window_xmin); 4515 for (int i=1;i<logplot_points;++i){ 4516 double t=double(i)/logplot_points; 4517 curx=(log10(I0+t*(I1-I0))-window_xmin)*x_scale; 4518 cury=j0+t*(j1-j0); 4519 fl_line(round(prevx+deltax),round(prevy+deltay),round(curx+deltax),round(cury+deltay)); 4520 prevx=curx; prevy=cury; 4521 } 4522 } 4523 find_dxdy(const string & legendes,int labelpos,int labelsize,int & dx,int & dy)4524 void find_dxdy(const string & legendes,int labelpos,int labelsize,int & dx,int & dy){ 4525 int l=int(fl_width(legendes.c_str())); 4526 dx=3; 4527 dy=1; 4528 switch (labelpos){ 4529 case 1: 4530 dx=-l-3; 4531 break; 4532 case 2: 4533 dx=-l-3; 4534 dy=labelsize-2; 4535 break; 4536 case 3: 4537 dy=labelsize-2; 4538 break; 4539 } 4540 } 4541 draw_legende(const vecteur & f,int i0,int j0,int labelpos,const Graph2d * iptr,int clip_x,int clip_y,int clip_w,int clip_h,int deltax,int deltay)4542 void draw_legende(const vecteur & f,int i0,int j0,int labelpos,const Graph2d * iptr,int clip_x,int clip_y,int clip_w,int clip_h,int deltax,int deltay){ 4543 if (f.empty() ||!iptr->show_names ) 4544 return; 4545 string legendes; 4546 const context * contextptr = get_context(iptr); 4547 if (f[0].is_symb_of_sommet(at_curve)){ 4548 gen & f0=f[0]._SYMBptr->feuille; 4549 if (f0.type==_VECT && !f0._VECTptr->empty()){ 4550 gen & f1 = f0._VECTptr->front(); 4551 if (f1.type==_VECT && f1._VECTptr->size()>4 && (!is_zero((*f1._VECTptr)[4]) || (iptr->show_names & 2)) ){ 4552 gen legende=f1._VECTptr->front(); 4553 gen var=(*f1._VECTptr)[1]; 4554 gen r=re(legende,contextptr),i=im(legende,contextptr),a,b; 4555 if (var.type==_IDNT && is_linear_wrt(r,*var._IDNTptr,a,b,contextptr)){ 4556 i=subst(i,var,(var-b)/a,false,contextptr); 4557 legendes=i.print(contextptr); 4558 } 4559 else 4560 legendes=r.print(contextptr)+","+i.print(contextptr); 4561 if (legendes.size()>18){ 4562 if (legendes.size()>30) 4563 legendes=""; 4564 else 4565 legendes=legendes.substr(0,16)+"..."; 4566 } 4567 } 4568 } 4569 } 4570 if (f.size()>2) 4571 legendes=gen2string(f[2])+(legendes.empty()?"":":")+legendes; 4572 if (legendes.empty()) 4573 return; 4574 if (abs_calc_mode(contextptr)==38 && legendes.size()>1 && legendes[0]=='G') 4575 legendes=legendes.substr(1,legendes.size()-1); 4576 fl_font(cst_greek_translate(legendes),iptr->labelsize()); 4577 int dx=3,dy=1; 4578 find_dxdy(legendes,labelpos,iptr->labelsize(),dx,dy); 4579 check_fl_draw(legendes.c_str(),iptr->x()+i0+dx,iptr->y()+j0+dy,clip_x,clip_y,clip_w,clip_h,deltax,deltay); 4580 } 4581 petite_fleche(double i1,double j1,double dx,double dy,int deltax,int deltay,int width)4582 void petite_fleche(double i1,double j1,double dx,double dy,int deltax,int deltay,int width){ 4583 double dxy=std::sqrt(dx*dx+dy*dy); 4584 if (dxy){ 4585 dxy/=max(2,min(5,int(dxy/10)))+width; 4586 dx/=dxy; 4587 dy/=dxy; 4588 double dxp=-dy,dyp=dx; // perpendicular 4589 dx*=std::sqrt(3.0); 4590 dy*=sqrt(3.0); 4591 fl_polygon(round(i1)+deltax,round(j1)+deltay,round(i1+dx+dxp)+deltax,round(j1+dy+dyp)+deltay,round(i1+dx-dxp)+deltax,round(j1+dy-dyp)+deltay); 4592 } 4593 } 4594 draw_filled_polygon(const vector<vector<int>> & v)4595 void draw_filled_polygon(const vector< vector<int> > & v){ 4596 if (v.empty()) return; 4597 fl_push_matrix(); 4598 fl_begin_complex_polygon(); 4599 for (size_t i=0;i<v.size();++i){ 4600 fl_vertex(v[i][0],v[i][1]); 4601 } 4602 if (v.back()!=v.front()) 4603 fl_vertex(v[0][0],v[0][1]); 4604 fl_end_complex_polygon(); 4605 fl_pop_matrix(); // Restore initial matrix 4606 } 4607 fl_pie_seg(int x,int y,int rx,int ry,int theta1_deg,int theta2_deg,bool segment=false)4608 void fl_pie_seg(int x,int y,int rx,int ry,int theta1_deg,int theta2_deg,bool segment=false){ 4609 if (!segment){ 4610 fl_pie(x,y,rx,ry,theta1_deg,theta2_deg); 4611 return; 4612 } 4613 // approximation by a filled polygon 4614 // points: (x,y), (x+rx*cos(theta)/2,y+ry*sin(theta)/2) theta=theta1..theta2 4615 while (theta2_deg<theta1_deg) 4616 theta2_deg+=360; 4617 if (theta2_deg-theta1_deg>=360){ 4618 theta1_deg=0; 4619 theta2_deg=360; 4620 } 4621 int N0=theta2_deg-theta1_deg+1; 4622 // reduce N if rx or ry is small 4623 double red=double(rx)/1024*double(ry)/768; 4624 if (red>1) red=1; 4625 if (red<0.1) red=0.1; 4626 int N=red*N0; 4627 if (N<5) 4628 N=N0>5?5:N0; 4629 if (N<2) 4630 N=2; 4631 vector< vector<int> > v(segment?N+1:N+2,vector<int>(2)); 4632 x += rx/2; 4633 y += ry/2; 4634 int i=0; 4635 if (!segment){ 4636 v[0][0]=x; 4637 v[0][1]=y; 4638 ++i; 4639 } 4640 double theta=theta1_deg*M_PI/180; 4641 double thetastep=(theta2_deg-theta1_deg)*M_PI/(180*(N-1)); 4642 for (;i<v.size()-1;++i){ 4643 v[i][0]=int(x+rx*std::cos(theta)/2+.5); 4644 v[i][1]=int(y-ry*std::sin(theta)/2+.5); // y is inverted 4645 theta += thetastep; 4646 } 4647 v.back()=v.front(); 4648 draw_filled_polygon(v); 4649 } 4650 4651 // helper for Graph2d::draw method 4652 // plot_i is the position we are drawing in plot_instructions 4653 // f is the vector of arguments and s is the function: we draw s(f) 4654 // legende_x is the x position in pixels of the parameter subwindow 4655 // parameter_y is the current y position for parameter drawing 4656 // x_scale and y_scale are the current scales 4657 // horizontal_pixels and vertical_pixels the size of the window fltk_draw(Graph2d & Mon_image,int plot_i,const gen & g,double x_scale,double y_scale,int clip_x,int clip_y,int clip_w,int clip_h)4658 void fltk_draw(Graph2d & Mon_image,int plot_i,const gen & g,double x_scale,double y_scale,int clip_x,int clip_y,int clip_w,int clip_h){ 4659 int deltax=Mon_image.x(),deltay=Mon_image.y(); 4660 History_Pack * hp =get_history_pack(&Mon_image); 4661 context * contextptr=hp?hp->contextptr:get_context(hp); 4662 if (g.type==_VECT){ 4663 vecteur v = merge_pixon(*g._VECTptr); 4664 const_iterateur it=v.begin(),itend=v.end(); 4665 for (;it!=itend;++it){ 4666 fltk_draw(Mon_image,plot_i,*it,x_scale,y_scale,clip_x,clip_y,clip_w,clip_h); 4667 fl_line_style(0); // back to default line style 4668 } // end for it 4669 } 4670 if (g.type!=_SYMB) 4671 return; 4672 unary_function_ptr s=g._SYMBptr->sommet; 4673 if (s==at_animation){ 4674 fltk_draw(Mon_image,plot_i,get_animation_pnt(g,Mon_image.animation_instructions_pos),x_scale,y_scale,clip_x,clip_y,clip_w,clip_h); 4675 return; 4676 } 4677 if (g._SYMBptr->feuille.type!=_VECT) 4678 return; 4679 vecteur f=*g._SYMBptr->feuille._VECTptr; 4680 int mxw=Mon_image.w(),myw=Mon_image.h()-(Mon_image.show_axes?(Mon_image.title.empty()?1:2):0)*Mon_image.labelsize(); 4681 double i0,j0,i0save,j0save,i1,j1; 4682 int fs=f.size(); 4683 if ((fs==4) && (s==at_parameter)){ 4684 return ; 4685 } 4686 string the_legend; 4687 vecteur style(get_style(f,the_legend)); 4688 int styles=style.size(); 4689 // color 4690 int ensemble_attributs = style.front().val; 4691 bool hidden_name = false; 4692 if (style.front().type==_ZINT){ 4693 ensemble_attributs = mpz_get_si(*style.front()._ZINTptr); 4694 hidden_name=true; 4695 } 4696 else 4697 hidden_name=ensemble_attributs<0; 4698 int width =(ensemble_attributs & 0x00070000) >> 16; // 3 bits 4699 int epaisseur_point =(ensemble_attributs & 0x00380000) >> 19; // 3 bits 4700 int type_line =(ensemble_attributs & 0x01c00000) >> 22; // 3 bits 4701 if (type_line>4) 4702 type_line=(type_line-4)<<8; 4703 int type_point =(ensemble_attributs & 0x0e000000) >> 25; // 3 bits 4704 int labelpos =(ensemble_attributs & 0x30000000) >> 28; // 2 bits 4705 bool fill_polygon =(ensemble_attributs & 0x40000000) >> 30; 4706 int couleur =(ensemble_attributs & 0x0000ffff); 4707 epaisseur_point += 2; 4708 std::pair<Fl_Image *,Fl_Image *> * texture = 0; 4709 for (int i=2;i<styles;++i){ 4710 gen & attr=style[i]; 4711 if (attr.type==_VECT && attr._VECTptr->size()<=3 ){ 4712 gen attrv0=attr._VECTptr->front(); 4713 if (attrv0.type==_INT_ && attrv0.val==_GL_TEXTURE){ 4714 gen attrv1=(*attr._VECTptr)[1]; 4715 if (attrv1.type==_VECT && attrv1._VECTptr->size()==2 && attrv1._VECTptr->front().type==_STRNG && is_undef(attrv1._VECTptr->back())){ 4716 // reload cached image 4717 attrv1=attrv1._VECTptr->front(); 4718 std::map<std::string,std::pair<Fl_Image *,Fl_Image*> *>::iterator it,itend=texture2d_cache.end(); 4719 it=texture2d_cache.find(attrv1._STRNGptr->c_str()); 4720 if (it!=itend){ 4721 std::pair<Fl_Image *,Fl_Image*> * old= it->second; 4722 delete old; 4723 texture2d_cache.erase(it); 4724 } 4725 } 4726 if (attrv1.type==_STRNG){ 4727 get_texture2d(*attrv1._STRNGptr,texture); 4728 } 4729 // set texture 4730 continue; 4731 } // end attrv0 = gl_texture 4732 } 4733 } 4734 if (s==at_pnt){ 4735 // f[0]=complex pnt or vector of complex pnts or symbolic 4736 // f[1] -> style 4737 // f[2] optional=label 4738 gen point=f[0]; 4739 if (point.type==_VECT && point.subtype==_POINT__VECT) 4740 return; 4741 if ( (f[0].type==_SYMB) && (f[0]._SYMBptr->sommet==at_curve) && (f[0]._SYMBptr->feuille.type==_VECT) && (f[0]._SYMBptr->feuille._VECTptr->size()) ){ 4742 // Mon_image.show_mouse_on_object=false; 4743 point=f[0]._SYMBptr->feuille._VECTptr->back(); 4744 if (type_line>=4 && point.type==_VECT && point._VECTptr->size()>2){ 4745 vecteur v=*point._VECTptr; 4746 int vs=v.size()/2; // 3 -> 1 4747 if (Mon_image.findij(v[vs],x_scale,y_scale,i0,j0,contextptr) && Mon_image.findij(v[vs+1],x_scale,y_scale,i1,j1,contextptr)){ 4748 bool logx=Mon_image.display_mode & 0x400,logy=Mon_image.display_mode & 0x800; 4749 checklog_fl_line(i0,j0,i1,j1,deltax,deltay,logx,logy,Mon_image.window_xmin,x_scale,Mon_image.window_ymax,y_scale); 4750 double dx=i0-i1,dy=j0-j1; 4751 petite_fleche(i1,j1,dx,dy,deltax,deltay,width+3); 4752 } 4753 } 4754 } 4755 if (is_undef(point)) 4756 return; 4757 if ( equalposcomp(Mon_image.selected,plot_i)) 4758 fl_color(FL_BLUE); 4759 else 4760 xcas_color(couleur); 4761 fl_line_style(type_line,width+1,0); 4762 if (point.type==_SYMB) { 4763 if (point._SYMBptr->sommet==at_hyperplan || point._SYMBptr->sommet==at_hypersphere) 4764 return; 4765 /* fl_curve is a filled curved, not a Bezier curve! 4766 if (point._SYMBptr->sommet==at_Bezier && point._SYMBptr->feuille.type==_VECT && point._SYMBptr->feuille._VECTptr->size()==4){ 4767 vecteur v=*point._SYMBptr->feuille._VECTptr; 4768 double i2,j2,i3,j3; gen e,f0,f1; 4769 evalfdouble2reim(v[0],e,f0,f1,contextptr); 4770 i0=f0._DOUBLE_val; j0=f1._DOUBLE_val; 4771 evalfdouble2reim(v[1],e,f0,f1,contextptr); 4772 i1=f0._DOUBLE_val; j1=f1._DOUBLE_val; 4773 evalfdouble2reim(v[2],e,f0,f1,contextptr); 4774 i2=f0._DOUBLE_val; j2=f1._DOUBLE_val; 4775 evalfdouble2reim(v[3],e,f0,f1,contextptr); 4776 i3=f0._DOUBLE_val; j3=f1._DOUBLE_val; 4777 fl_push_matrix(); 4778 fl_translate(deltax,deltay); 4779 fl_mult_matrix(x_scale,0,0,-y_scale,0,0); 4780 fl_translate(-Mon_image.window_xmin,-Mon_image.window_ymax); 4781 fl_curve(i0,j0,i1,j1,i2,j2,i3,j3); 4782 fl_end_complex_polygon(); 4783 fl_pop_matrix(); // Restore initial matrix 4784 return; 4785 } 4786 */ 4787 if (point._SYMBptr->sommet==at_cercle && !(Mon_image.display_mode & 0xc00)){ 4788 vecteur v=*point._SYMBptr->feuille._VECTptr; 4789 gen diametre=remove_at_pnt(v[0]); 4790 gen e1=diametre._VECTptr->front().evalf_double(1,contextptr),e2=diametre._VECTptr->back().evalf_double(1,contextptr); 4791 gen centre=rdiv(e1+e2,2.0,contextptr); 4792 gen e12=e2-e1; 4793 double ex=evalf_double(re(e12,contextptr),1,contextptr)._DOUBLE_val,ey=evalf_double(im(e12,contextptr),1,contextptr)._DOUBLE_val; 4794 if (!Mon_image.findij(centre,x_scale,y_scale,i0,j0,contextptr)) 4795 return; 4796 gen diam=std::sqrt(ex*ex+ey*ey); 4797 gen angle=std::atan2(ey,ex); 4798 gen a1=v[1].evalf_double(1,contextptr),a2=v[2].evalf_double(1,contextptr); 4799 if ( (diam.type==_DOUBLE_) && (a1.type==_DOUBLE_) && (a2.type==_DOUBLE_) ){ 4800 i1=diam._DOUBLE_val*x_scale/2.0; 4801 j1=diam._DOUBLE_val*y_scale/2.0; 4802 double a1d=a1._DOUBLE_val,a2d=a2._DOUBLE_val,angled=angle._DOUBLE_val; 4803 bool changer_sens=a1d>a2d; 4804 if (changer_sens){ 4805 double tmp=a1d; 4806 a1d=a2d; 4807 a2d=tmp; 4808 } 4809 double anglei=(angled+a1d),anglef=(angled+a2d),anglem=(anglei+anglef)/2; 4810 double diff=anglef-anglei; 4811 anglei -= floor(anglei/2/M_PI)*2*M_PI; 4812 anglef = anglei + diff; 4813 if (fill_polygon){ 4814 if (v[1]==0 && v[2]==cst_two_pi) 4815 fl_pie(deltax+round(i0-i1),deltay+round(j0-j1),round(2*i1),round(2*j1),0,360); 4816 else 4817 fl_pie(deltax+round(i0-i1),deltay+round(j0-j1),round(2*i1),round(2*j1),anglei*180/M_PI,anglef*180/M_PI); 4818 } 4819 else { 4820 fl_arc(deltax+round(i0-i1),deltay+round(j0-j1),round(2*i1),round(2*j1),anglei*180/M_PI,anglef*180/M_PI); 4821 if (v.size()>=4){ // if cercle has the optionnal 5th arg 4822 if (v[3]==2) 4823 petite_fleche(i0+i1*std::cos(anglem),j0-j1*std::sin(anglem),-i1*std::sin(anglem),-j1*std::cos(anglem),deltax,deltay,width); 4824 else { 4825 if (changer_sens) 4826 petite_fleche(i0+i1*std::cos(anglei),j0-j1*std::sin(anglei),-i1*std::sin(anglei),-j1*std::cos(anglei),deltax,deltay,width); 4827 else 4828 petite_fleche(i0+i1*std::cos(anglef),j0-j1*std::sin(anglef),i1*std::sin(anglef),j1*std::cos(anglef),deltax,deltay,width); 4829 } 4830 } 4831 } 4832 // Label a few degrees from the start angle, 4833 // FIXME should use labelpos 4834 double anglel=angled+a1d+0.3; 4835 if (v.size()>=4 && v[3]==2) 4836 anglel=angled+(0.45*a1d+0.55*a2d); 4837 i0=i0+i1*std::cos(anglel); 4838 j0=j0-j1*std::sin(anglel); 4839 if (!hidden_name) 4840 draw_legende(f,round(i0),round(j0),labelpos,&Mon_image,clip_x,clip_y,clip_w,clip_h,0,0); 4841 return; 4842 } 4843 } // end circle 4844 if (point._SYMBptr->sommet==at_pixon){ 4845 // pixon (i,j,color) 4846 if (point._SYMBptr->feuille.type!=_VECT) 4847 return; 4848 vecteur &v=*point._SYMBptr->feuille._VECTptr; 4849 if (v.size()<3 || v[0].type!=_INT_ || v[1].type!=_INT_ || v[2].type!=_INT_) 4850 return; 4851 int delta_i=v[0].val,delta_j=v[1].val,psx=0,psy=0; 4852 if (v.size()>3 && v[3].type==_INT_){ 4853 if (v[3].val>0) psy=v[3].val; else psx=-v[3].val; 4854 } 4855 psx=pixon_size*(psx+1); 4856 psy=pixon_size*(psy+1); 4857 xcas_color(v[2].val); 4858 delta_i *= pixon_size; 4859 delta_j *= pixon_size; 4860 if (delta_i>=0 && delta_i<mxw && delta_j>=0 && delta_j<myw){ 4861 #if 1 4862 check_fl_rectf(deltax+delta_i,deltay+delta_j,psx,psy,clip_x,clip_y,clip_w,clip_h,0,0); 4863 #else 4864 for (int i=0;i<psx;++i) 4865 for (int j=0;j<psy;++j) 4866 check_fl_point(deltax+delta_i+i,deltay+delta_j+j,clip_x,clip_y,clip_w,clip_h,0,0); 4867 #endif 4868 } 4869 return; 4870 } 4871 if (point._SYMBptr->sommet==at_bitmap){ 4872 // bitmap(vector of int (1 per line)), 1st line, 1st col, [type] 4873 if (point._SYMBptr->feuille.type!=_VECT) 4874 return; 4875 vecteur &v=*point._SYMBptr->feuille._VECTptr; 4876 if (v.size()<3 || v[0].type!=_VECT || v[1].type!=_INT_ || v[2].type!=_INT_ ) 4877 return; 4878 int delta_i=v[1].val,delta_j=v[2].val; 4879 double xmin=Mon_image.window_xmin,ymin=Mon_image.window_ymin,xmax=Mon_image.window_xmax,ymax=Mon_image.window_ymax; 4880 //gen psize=_Pictsize(0); 4881 int bitmap_w=Mon_image.w()-int(Mon_image.ylegende*(Mon_image.show_axes?Mon_image.labelsize():0)), 4882 bitmap_h=Mon_image.h()-(Mon_image.show_axes?((Mon_image.title.empty()?1:2)*Mon_image.labelsize()):0); 4883 if (v.size()>8){ 4884 xmin=v[3]._DOUBLE_val; 4885 xmax=v[4]._DOUBLE_val; 4886 ymin=v[5]._DOUBLE_val; 4887 ymax=v[6]._DOUBLE_val; 4888 bitmap_w=v[7].val; 4889 bitmap_h=v[8].val; 4890 } 4891 double bitmap_scalex=(xmax-xmin)/bitmap_w,scalex=(Mon_image.window_xmax-Mon_image.window_xmin)/(Mon_image.w()-int(Mon_image.ylegende*(Mon_image.show_axes?Mon_image.labelsize():0))); 4892 double bitmap_scaley=(ymax-ymin)/bitmap_h,scaley=(Mon_image.window_ymax-Mon_image.window_ymin)/(Mon_image.h()-(Mon_image.show_axes?((Mon_image.title.empty()?1:2)*Mon_image.labelsize()):0)); 4893 double X,Y; 4894 int ii,jj; 4895 const_iterateur it=v[0]._VECTptr->begin(),itend=v[0]._VECTptr->end(); 4896 for (;it!=itend;++it,++delta_i){ 4897 if (it->type!=_INT_ && it->type!=_ZINT) 4898 continue; 4899 gen z=*it; 4900 mpz_t zz,zr; 4901 if (it->type==_INT_) 4902 mpz_init_set_ui(zz,it->val); 4903 else 4904 mpz_init_set(zz,*it->_ZINTptr); 4905 mpz_init(zr); 4906 for (int j=delta_j;mpz_sgn(zz);++j){ 4907 mpz_tdiv_r_2exp (zr, zz, 1); 4908 mpz_tdiv_q_2exp (zz, zz, 1); 4909 if (mpz_sgn(zr)){ 4910 X=xmin+j*bitmap_scalex; 4911 ii=int(0.5+(X-Mon_image.window_xmin)/scalex); 4912 Y=ymax-delta_i*bitmap_scaley; 4913 jj=int(0.5+(Mon_image.window_ymax-Y)/scaley); 4914 if (ii>0 && ii<mxw && jj>0 && jj<myw) 4915 check_fl_point(deltax+ii,deltay+jj,clip_x,clip_y,clip_w,clip_h,0,0); 4916 } 4917 } 4918 mpz_clear(zr); 4919 mpz_clear(zz); 4920 } 4921 return; 4922 } // end bitmap 4923 if (point._SYMBptr->sommet==at_legende){ 4924 gen & f=point._SYMBptr->feuille; 4925 if (f.type==_VECT && f._VECTptr->size()==3){ 4926 vecteur & fv=*f._VECTptr; 4927 if (fv[0].type==_VECT && fv[0]._VECTptr->size()>=2 && fv[1].type==_STRNG && fv[2].type==_INT_){ 4928 vecteur & fvv=*fv[0]._VECTptr; 4929 if (fvv[0].type==_INT_ && fvv[1].type==_INT_){ 4930 fl_font(FL_HELVETICA,Mon_image.labelsize()); 4931 xcas_color(fv[2].val); 4932 int dx=0,dy=0; 4933 string legendes(*fv[1]._STRNGptr); 4934 find_dxdy(legendes,labelpos,Mon_image.labelsize(),dx,dy); 4935 fl_draw(legendes.c_str(),deltax+fvv[0].val+dx,deltay+fvv[1].val+dy); 4936 } 4937 } 4938 } 4939 } 4940 } // end point.type==_SYMB 4941 if (point.type!=_VECT || (point.type==_VECT && (point.subtype==_GROUP__VECT || point.subtype==_VECTOR__VECT) && point._VECTptr->size()==2 && is_zero(point._VECTptr->back()-point._VECTptr->front())) ){ // single point 4942 if (!Mon_image.findij((point.type==_VECT?point._VECTptr->front():point),x_scale,y_scale,i0,j0,contextptr)) 4943 return; 4944 if (i0>0 && i0<mxw && j0>0 && j0<myw) 4945 fltk_point(deltax,deltay,round(i0),round(j0),epaisseur_point,type_point); 4946 if (!hidden_name) 4947 draw_legende(f,round(i0),round(j0),labelpos,&Mon_image,clip_x,clip_y,clip_w,clip_h,0,0); 4948 return; 4949 } 4950 // path 4951 const_iterateur jt=point._VECTptr->begin(),jtend=point._VECTptr->end(); 4952 if (jt==jtend) 4953 return; 4954 bool logx=Mon_image.display_mode & 0x400,logy=Mon_image.display_mode & 0x800; 4955 if (jtend-jt==2 && logx && point.subtype==_LINE__VECT){ 4956 // find points with + coordinates ax+cx*t=x, ay+cy*t=y= 4957 gen a=*jt,ax=re(a,contextptr),ay=im(a,contextptr),b=*(jt+1),c=b-a,cx=re(c,contextptr),cy=im(c,contextptr); 4958 if (!is_zero(cx)){ 4959 // y=ay+cy/cx*(x-ax) 4960 gen x=pow(10,Mon_image.window_xmin,contextptr); 4961 gen y=ay+cy/cx*(x-ax); 4962 Mon_image.findij(x+cst_i*y,x_scale,y_scale,i0,j0,contextptr); 4963 for (int i=1;i<=logplot_points;++i){ 4964 x=pow(10,Mon_image.window_xmin+i*(Mon_image.window_xmax-Mon_image.window_xmin)/logplot_points,contextptr); 4965 y=ay+cy/cx*(x-ax); 4966 Mon_image.findij(x+cst_i*y,x_scale,y_scale,i1,j1,contextptr); 4967 fl_line(round(i0+deltax),round(j0+deltay),round(i1+deltax),round(j1+deltay)); 4968 i0=i1; 4969 j0=j1; 4970 } 4971 return; 4972 } 4973 } 4974 if (texture && jtend-jt>2){ 4975 // use *jt and *(jt+2) for the rectangle texture 4976 Mon_image.findij(*jt,x_scale,y_scale,i0,j0,contextptr); 4977 if (!Mon_image.findij(*(jt+2),x_scale,y_scale,i1,j1,contextptr)) 4978 return; 4979 if (i0>i1) 4980 std::swap(i0,i1); 4981 if (j0>j1) 4982 std::swap(j0,j1); 4983 int tx=int(i0+.5)+deltax; 4984 int tw=int(i1-i0+.5); 4985 int ty=int(j0+.5)+deltay; 4986 int th=int(j1-j0+.5); 4987 if (texture->second && texture->second->w()==tw && texture->second->h()==th) 4988 texture->second->draw(tx,ty,tw,th); 4989 else { 4990 if (texture->second) 4991 delete texture->second; 4992 if (texture->first){ 4993 texture->second=texture->first->copy(tw,th); 4994 texture->second->draw(tx,ty,tw,th); 4995 } 4996 } 4997 return; 4998 } 4999 if (jt->type==_VECT) 5000 return; 5001 if ( (type_point || epaisseur_point>2) && type_line==0 && width==0){ 5002 for (;jt!=jtend;++jt){ 5003 if (!Mon_image.findij(*jt,x_scale,y_scale,i0,j0,contextptr)) 5004 return; 5005 if (i0>0 && i0<mxw && j0>0 && j0<myw) 5006 fltk_point(deltax,deltay,round(i0),round(j0),epaisseur_point,type_point); 5007 } 5008 if (!hidden_name) 5009 draw_legende(f,round(i0),round(j0),labelpos,&Mon_image,clip_x,clip_y,clip_w,clip_h,0,0); 5010 return; 5011 } 5012 // initial point 5013 if (!Mon_image.findij(*jt,x_scale,y_scale,i0,j0,contextptr)) 5014 return; 5015 if (fill_polygon){ 5016 const_iterateur jtsave=jt; 5017 gen e,f0,f1; 5018 // Compute matrix for complex drawing 5019 fl_push_matrix(); 5020 fl_translate(deltax,deltay); 5021 fl_mult_matrix(x_scale,0,0,-y_scale,0,0); 5022 fl_translate(-Mon_image.window_xmin,-Mon_image.window_ymax); 5023 fl_begin_complex_polygon(); 5024 for (;jt!=jtend;++jt){ 5025 evalfdouble2reim(*jt,e,f0,f1,contextptr); 5026 if ((f0.type==_DOUBLE_) && (f1.type==_DOUBLE_)) 5027 fl_vertex(f0._DOUBLE_val,f1._DOUBLE_val); 5028 } 5029 if (*jtsave!=*(jtend-1)){ 5030 evalfdouble2reim(*jtsave,e,f0,f1,contextptr); 5031 if ((f0.type==_DOUBLE_) && (f1.type==_DOUBLE_)) 5032 fl_vertex(f0._DOUBLE_val,f1._DOUBLE_val); 5033 } 5034 fl_end_complex_polygon(); 5035 fl_pop_matrix(); // Restore initial matrix 5036 if (!width){ 5037 if (!hidden_name) 5038 draw_legende(f,round(i0),round(j0),labelpos,&Mon_image,clip_x,clip_y,clip_w,clip_h,0,0); 5039 return; 5040 } 5041 jt=jtsave; 5042 fl_line_style(type_line,width,0); 5043 fl_color(epaisseur_point-2+(type_point<<3)); 5044 } 5045 i0save=i0; 5046 j0save=j0; 5047 ++jt; 5048 if (jt==jtend){ 5049 if (i0>0 && i0<mxw && j0>0 && j0<myw) 5050 check_fl_point(deltax+round(i0),deltay+round(j0),clip_x,clip_y,clip_w,clip_h,0,0); 5051 if (!hidden_name) 5052 draw_legende(f,round(i0),round(j0),labelpos,&Mon_image,clip_x,clip_y,clip_w,clip_h,0,0); 5053 return; 5054 } 5055 bool seghalfline=( point.subtype==_LINE__VECT || point.subtype==_HALFLINE__VECT ) && (point._VECTptr->size()==2); 5056 // rest of the path 5057 for (;;){ 5058 if (!Mon_image.findij(*jt,x_scale,y_scale,i1,j1,contextptr)) 5059 return; 5060 if (!seghalfline){ 5061 checklog_fl_line(i0,j0,i1,j1,deltax,deltay,logx,logy,Mon_image.window_xmin,x_scale,Mon_image.window_ymax,y_scale); 5062 if (point.subtype==_VECTOR__VECT){ 5063 double dx=i0-i1,dy=j0-j1; 5064 petite_fleche(i1,j1,dx,dy,deltax,deltay,width); 5065 } 5066 } 5067 ++jt; 5068 if (jt==jtend){ // label of line at midpoint 5069 if (point.subtype==_LINE__VECT){ 5070 i0=(6*i1-i0)/5-8; 5071 j0=(6*j1-j0)/5-8; 5072 } 5073 else { 5074 i0=(i0+i1)/2-8; 5075 j0=(j0+j1)/2; 5076 } 5077 break; 5078 } 5079 i0=i1; 5080 j0=j1; 5081 } 5082 // check for a segment/halfline/line 5083 if ( seghalfline){ 5084 double deltai=i1-i0save,adeltai=std::abs(deltai); 5085 double deltaj=j1-j0save,adeltaj=std::abs(deltaj); 5086 if (point.subtype==_LINE__VECT){ 5087 if (deltai==0) 5088 checklog_fl_line(i1,0,i1,clip_h,deltax,deltay,logx,logy,Mon_image.window_xmin,x_scale,Mon_image.window_ymax,y_scale); 5089 else { 5090 if (deltaj==0) 5091 checklog_fl_line(0,j1,clip_w,j1,deltax,deltay,Mon_image.display_mode & 0x400,Mon_image.display_mode & 0x800,Mon_image.window_xmin,x_scale,Mon_image.window_ymax,y_scale); 5092 else { 5093 // Find the intersections with the 4 rectangle segments 5094 // Horizontal x=0 or w =i1+t*deltai: y=j1+t*deltaj 5095 vector< complex<double> > pts; 5096 double y0=j1-i1/deltai*deltaj,tol=clip_h*1e-6; 5097 if (y0>=-tol && y0<=clip_h+tol) 5098 pts.push_back(complex<double>(0.0,y0)); 5099 double yw=j1+(clip_w-i1)/deltai*deltaj; 5100 if (yw>=-tol && yw<=clip_h+tol) 5101 pts.push_back(complex<double>(clip_w,yw)); 5102 // Vertical y=0 or h=j1+t*deltaj, x=i1+t*deltai 5103 double x0=i1-j1/deltaj*deltai; 5104 tol=clip_w*1e-6; 5105 if (x0>=-tol && x0<=clip_w+tol) 5106 pts.push_back(complex<double>(x0,0.0)); 5107 double xh=i1+(clip_h-j1)/deltaj*deltai; 5108 if (xh>=-tol && xh<=clip_w+tol) 5109 pts.push_back(complex<double>(xh,clip_h)); 5110 if (pts.size()>=2) 5111 checklog_fl_line(pts[0].real(),pts[0].imag(),pts[1].real(),pts[1].imag(),deltax,deltay,Mon_image.display_mode & 0x400,Mon_image.display_mode & 0x800,Mon_image.window_xmin,x_scale,Mon_image.window_ymax,y_scale); 5112 } // end else adeltai==0 , adeltaj==0 5113 } // end else adeltai==0 5114 } // end LINE_VECT 5115 else { 5116 double N=1; 5117 if (adeltai){ 5118 N=clip_w/adeltai+1; 5119 if (adeltaj) 5120 N=max(N,clip_h/adeltaj+1); 5121 } 5122 else { 5123 if (adeltaj) 5124 N=clip_h/adeltaj+1; 5125 } 5126 N *= 2; // increase N since rounding might introduce too small clipping 5127 while (fabs(N*deltai)>10000) 5128 N /= 2; 5129 while (fabs(N*deltaj)>10000) 5130 N /= 2; 5131 checklog_fl_line(i0save,j0save,i1+N*deltai,j1+N*deltaj,deltax,deltay,Mon_image.display_mode & 0x400,Mon_image.display_mode & 0x800,Mon_image.window_xmin,x_scale,Mon_image.window_ymax,y_scale); 5132 } 5133 } // end seghalfline 5134 if ( (point.subtype==_GROUP__VECT) && (point._VECTptr->size()==2)) 5135 ; // no legend for segment 5136 else { 5137 if (!hidden_name) 5138 draw_legende(f,round(i0),round(j0),labelpos,&Mon_image,clip_x,clip_y,clip_w,clip_h,0,0); 5139 } 5140 } // end pnt subcase 5141 5142 } 5143 draw()5144 void Mouse_Position::draw(){ 5145 int clip_x,clip_y,clip_w,clip_h; 5146 fl_clip_box(x(),y(),w(),h(),clip_x,clip_y,clip_w,clip_h); 5147 fl_push_clip(clip_x,clip_y,clip_w,clip_h); 5148 fl_color(FL_CYAN); 5149 check_fl_rectf(x(),y(),w(),h(),clip_x,clip_y,clip_w,clip_h,0,0); 5150 fl_color(FL_BLACK); 5151 check_fl_rect(x(), y(), w(), h(),clip_x,clip_y,clip_w,clip_h,0,0); 5152 fl_font(FL_HELVETICA,labelsize()); 5153 int cur_x,cur_y; 5154 // giac::context * contextptr = get_context(graphic); 5155 if (Graph2d * gr=dynamic_cast<Graph2d *>(graphic)){ 5156 cur_x=gr->current_i; // Fl::event_x()-gr->x(); 5157 cur_y=gr->current_j; // Fl::event_y()-gr->y(); 5158 double y_scale=(gr->h()-(gr->show_axes?((gr->title.empty()?1:2)*gr->labelsize()):0))/(graphic->window_ymax-graphic->window_ymin); 5159 double x_scale=(gr->w()-(gr->show_axes?gr->ylegende*gr->labelsize():0))/(graphic->window_xmax-graphic->window_xmin); 5160 double d_mouse_x=graphic->window_xmin+cur_x/x_scale; 5161 double d_mouse_y=graphic->window_ymax-cur_y/y_scale; 5162 check_fl_draw(("x:"+giac::print_DOUBLE_(d_mouse_x,3)).c_str(),x()+2,y()+h()/2-2,clip_x,clip_y,clip_w,clip_h,0,0); 5163 check_fl_draw(("y:"+giac::print_DOUBLE_(d_mouse_y,3)).c_str(),x()+2,y()+h()-2,clip_x,clip_y,clip_w,clip_h,0,0); 5164 } 5165 if (Graph3d * gr=dynamic_cast<Graph3d *>(graphic)){ 5166 cur_x=gr->current_i; // Fl::event_x(); 5167 cur_y=gr->current_j; // Fl::event_y(); 5168 double x0,y0,z0; 5169 gr->find_xyz(cur_x,cur_y,gr->depth,x0,y0,z0); 5170 fl_draw(("x:"+giac::print_DOUBLE_(x0,3)).c_str(),x()+2,y()+labelsize()-2); 5171 fl_draw(("y:"+giac::print_DOUBLE_(y0,3)).c_str(),x()+2,y()+2*labelsize()-2); 5172 fl_draw(("z:"+giac::print_DOUBLE_(z0,3)).c_str(),x()+2,y()+3*labelsize()-2); 5173 } 5174 fl_pop_clip(); 5175 } 5176 printstring(const gen & g,GIAC_CONTEXT)5177 string printstring(const gen & g,GIAC_CONTEXT){ 5178 if (g.type==_STRNG) 5179 return *g._STRNGptr; 5180 return g.print(contextptr); 5181 } 5182 find_title_plot(gen & title_tmp,gen & plot_tmp,GIAC_CONTEXT)5183 void Graph2d3d::find_title_plot(gen & title_tmp,gen & plot_tmp,GIAC_CONTEXT){ 5184 if (in_area && mode && !args_tmp.empty()){ 5185 if (args_tmp.size()>=2){ 5186 gen function=(mode==int(args_tmp.size()))?function_final:function_tmp; 5187 if (function.type==_FUNC){ 5188 bool dim2=dynamic_cast<Graph2d *>(this); 5189 vecteur args2=args_tmp; 5190 if ( *function._FUNCptr==(dim2?at_cercle:at_sphere)){ 5191 gen argv1; 5192 try { 5193 argv1=evalf(args_tmp.back(),1,contextptr); 5194 argv1=evalf_double(argv1,1,contextptr); 5195 } 5196 catch (std::runtime_error & e){ 5197 argv1=undef; 5198 } 5199 if (argv1.is_symb_of_sommet(at_pnt) ||argv1.type==_IDNT){ 5200 argv1=remove_at_pnt(argv1); 5201 if ( (argv1.type==_VECT && argv1.subtype==_POINT__VECT) || argv1.type==_CPLX || argv1.type==_IDNT) 5202 args2.back()=args_tmp.back()-args_tmp.front(); 5203 } 5204 } 5205 if (function==at_ellipse) 5206 ; 5207 title_tmp=gen(args2,_SEQ__VECT); 5208 bool b=approx_mode(contextptr); 5209 if (!b) 5210 approx_mode(true,contextptr); 5211 plot_tmp=symbolic(*function._FUNCptr,title_tmp); 5212 if (!lidnt(title_tmp).empty()) 5213 ; // cerr << plot_tmp << '\n'; 5214 bool bb=io_graph(contextptr); 5215 int locked=0; 5216 if (bb){ 5217 #ifdef HAVE_LIBPTHREAD 5218 // cerr << "plot title lock" << '\n'; 5219 locked=pthread_mutex_trylock(&interactive_mutex); 5220 #endif 5221 if (!locked) 5222 io_graph(false,contextptr); 5223 } 5224 plot_tmp=protecteval(plot_tmp,1,contextptr); 5225 if (bb && !locked){ 5226 io_graph(bb,contextptr); 5227 #ifdef HAVE_LIBPTHREAD 5228 pthread_mutex_unlock(&interactive_mutex); 5229 // cerr << "plot title unlock" << '\n'; 5230 #endif 5231 } 5232 if (!b) 5233 approx_mode(false,contextptr); 5234 } // end function.type==_FUNC 5235 else 5236 title_tmp=gen(args_tmp,_SEQ__VECT); 5237 } // end size()>=2 5238 else 5239 title_tmp=args_tmp; 5240 } 5241 } 5242 in_draw(int clip_x,int clip_y,int clip_w,int clip_h,int & vertical_pixels)5243 void Graph2d::in_draw(int clip_x,int clip_y,int clip_w,int clip_h,int & vertical_pixels){ 5244 if (window_xmax-window_xmin<1e-100){ 5245 window_xmax=gnuplot_xmax; 5246 window_xmin=gnuplot_xmin; 5247 } 5248 if (window_ymax-window_ymin<1e-100){ 5249 window_ymax=gnuplot_ymax; 5250 window_ymin=gnuplot_ymin; 5251 } 5252 struct timezone tz; 5253 gettimeofday(&animation_last,&tz); 5254 gen title_tmp; 5255 gen plot_tmp; 5256 History_Pack * hp =get_history_pack(this); 5257 context * contextptr=hp?hp->contextptr:get_context(this); 5258 find_title_plot(title_tmp,plot_tmp,contextptr); 5259 #if 1 // changes by L. Marohnic 5260 int horizontal_pixels=w()-(show_axes>0?int(ylegende*labelsize())+2:0); 5261 vertical_pixels=h()-((show_axes!=0 && show_axes!=2?2:0)+(!title.empty()))*labelsize(); 5262 int deltax=x(),deltay=y(); 5263 double y_scale=vertical_pixels/(window_ymax-window_ymin); 5264 double x_scale=horizontal_pixels/(window_xmax-window_xmin); 5265 // Then redraw the background 5266 fl_color(FL_WHITE); 5267 fl_rectf(clip_x, clip_y, clip_w, clip_h); 5268 if (background_image){ 5269 if (!background_image->second || background_image->second->w()!=w() || background_image->second->h()!=h()){ 5270 if (background_image->second) 5271 delete background_image->second; 5272 if (background_image->first) 5273 background_image->second=background_image->first->copy(w(),h()); 5274 } 5275 if (background_image->second) 5276 background_image->second->draw(x(),y(),w(),h()); 5277 } 5278 // History draw 5279 /****************/ 5280 int xx,yy,ww,hh; 5281 fl_clip_box(clip_x,clip_y,horizontal_pixels,vertical_pixels,xx,yy,ww,hh); 5282 fl_push_clip(xx,yy,ww,hh); 5283 // fl_push_clip(clip_x,clip_y,horizontal_pixels,vertical_pixels); 5284 /****************/ 5285 fl_color(FL_BLACK); 5286 fl_font(FL_HELVETICA,labelsize()); 5287 if ( (display_mode & 2) && !animation_instructions.empty()){ 5288 gen tmp=animation_instructions[animation_instructions_pos % animation_instructions.size()]; 5289 fltk_draw(*this,-1,tmp,x_scale,y_scale,clip_x,clip_y,clip_w,clip_h); 5290 } 5291 if ( display_mode & 0x40 ){ 5292 fltk_draw(*this,-1,trace_instructions,x_scale,y_scale,clip_x,clip_y,clip_w,clip_h); 5293 } 5294 if (display_mode & 1) { 5295 const_iterateur at=plot_instructions.begin(),atend=plot_instructions.end(),it,itend; 5296 for (int plot_i=0;at!=atend;++at,++plot_i){ 5297 if (at->type==_INT_) 5298 continue; 5299 update_infos(*at,contextptr); 5300 if (at->is_symb_of_sommet(at_parameter)){ 5301 gen ff = at->_SYMBptr->feuille; 5302 vecteur f; 5303 if (ff.type==_VECT && (f=*ff._VECTptr).size()==4){ 5304 // parameters.push_back(f); 5305 } 5306 continue; 5307 } 5308 fltk_draw(*this,plot_i,*at,x_scale,y_scale,clip_x,clip_y,clip_w,clip_h); 5309 } // end for at 5310 } 5311 vecteur plot_tmp_v=gen2vecteur(plot_tmp); 5312 const_iterateur jt=plot_tmp_v.begin(),jtend=plot_tmp_v.end(); 5313 for (;jt!=jtend;++jt){ 5314 gen plot_tmp=*jt; 5315 if (plot_tmp.is_symb_of_sommet(at_pnt) && plot_tmp._SYMBptr->feuille.type==_VECT && !plot_tmp._SYMBptr->feuille._VECTptr->empty()){ 5316 vecteur & v=*plot_tmp._SYMBptr->feuille._VECTptr; 5317 // cerr << v << '\n'; 5318 if (v[1].type==_INT_) 5319 plot_tmp=symbolic(at_pnt,makevecteur(v[0],v[1].val | _DOT_LINE | _LINE_WIDTH_2)); 5320 else 5321 plot_tmp=symbolic(at_pnt,v); 5322 try { 5323 fltk_draw(*this,-1,plot_tmp,x_scale,y_scale,clip_x,clip_y,clip_w,clip_h); 5324 } 5325 catch (...){ 5326 } 5327 } 5328 } 5329 fl_line_style(0); // back to default line style 5330 // Draw axis 5331 double I0,J0; 5332 findij(zero,x_scale,y_scale,I0,J0,contextptr); 5333 int i_0=round(I0),j_0=round(J0); 5334 if ( show_axes==1 && (window_ymax>=0) && (window_ymin<=0)){ // X-axis 5335 fl_color(x_axis_color); 5336 check_fl_line(deltax,deltay+j_0,deltax+horizontal_pixels,deltay+j_0,clip_x,clip_y,clip_w,clip_h,0,0); 5337 fl_color(FL_CYAN); 5338 check_fl_line(deltax+i_0,deltay+j_0,deltax+i_0+int(x_scale),deltay+j_0,clip_x,clip_y,clip_w,clip_h,0,0); 5339 fl_color(x_axis_color); 5340 if (x_tick>0 && (horizontal_pixels)/(x_scale*x_tick) < 40){ 5341 double nticks=(horizontal_pixels-I0)/(x_scale*x_tick); 5342 int count=0; 5343 for (int ii=int(-I0/(x_tick*x_scale));ii<=nticks && count<40;++ii,++count){ 5344 int iii=int(I0+ii*x_scale*x_tick+.5); 5345 check_fl_line(deltax+iii,deltay+j_0+2,deltax+iii,deltay+j_0-2,clip_x,clip_y,clip_w,clip_h,0,0); 5346 } 5347 } 5348 string tmp=(x_axis_name.empty()?"x":x_axis_name)+" "; 5349 check_fl_draw(tmp.c_str(),deltax+horizontal_pixels-int(fl_width(tmp.c_str())),deltay+j_0+labelsize(),clip_x,clip_y,clip_w,clip_h,0,0); 5350 } 5351 if ( show_axes==1 && (window_xmax>=0) && (window_xmin<=0) ) {// Y-axis 5352 fl_color(y_axis_color); 5353 check_fl_line(deltax+i_0,deltay,deltax+i_0,deltay+vertical_pixels,clip_x,clip_y,clip_w,clip_h,0,0); 5354 fl_color(FL_CYAN); 5355 check_fl_line(deltax+i_0,deltay+j_0,deltax+i_0,deltay+j_0-int(y_scale),clip_x,clip_y,clip_w,clip_h,0,0); 5356 fl_color(y_axis_color); 5357 if (y_tick>0 && vertical_pixels/(y_tick*y_scale) <40 ){ 5358 double nticks=(vertical_pixels-J0)/(y_tick*y_scale); 5359 int count=0; 5360 for (int jj=int(-J0/(y_tick*y_scale));jj<=nticks && count<25;++jj,++count){ 5361 int jjj=int(J0+jj*y_scale*y_tick+.5); 5362 check_fl_line(deltax+i_0-2,deltay+jjj,deltax+i_0+2,deltay+jjj,clip_x,clip_y,clip_w,clip_h,0,0); 5363 } 5364 } 5365 string tmp=" "+(y_axis_name.empty()?"y":y_axis_name); 5366 check_fl_draw(tmp.c_str(),deltax+i_0+2,deltay+labelsize(),clip_x,clip_y,clip_w,clip_h,0,0); 5367 } 5368 // Ticks 5369 if (show_axes==1 && (horizontal_pixels)/(x_scale*x_tick) < 40 && vertical_pixels/(y_tick*y_scale) <40 ){ 5370 if (x_tick>0 && y_tick>0 ){ 5371 fl_color(FL_BLACK); 5372 double nticks=(horizontal_pixels-I0)/(x_scale*x_tick); 5373 double mticks=(vertical_pixels-J0)/(y_tick*y_scale); 5374 int count=0; 5375 for (int ii=int(-I0/(x_tick*x_scale));ii<=nticks;++ii){ 5376 int iii=int(I0+ii*x_scale*x_tick+.5); 5377 for (int jj=int(-J0/(y_tick*y_scale));jj<=mticks && count<1600;++jj,++count){ 5378 int jjj=int(J0+jj*y_scale*y_tick+.5); 5379 check_fl_point(deltax+iii,deltay+jjj,clip_x,clip_y,clip_w,clip_h,0,0); 5380 } 5381 } 5382 } 5383 } 5384 /****************/ 5385 fl_pop_clip(); 5386 /****************/ 5387 fl_color(FL_BLACK); 5388 fl_font(FL_HELVETICA,labelsize()); 5389 if (!args_help.empty() && args_tmp.size()<= args_help.size()){ 5390 fl_draw((gettext("Click ")+args_help[giacmax(1,args_tmp.size())-1]).c_str(),x(),y()+labelsize()-2); 5391 } 5392 string mytitle(title); 5393 if (!is_zero(title_tmp) && function_final.type==_FUNC) 5394 mytitle=gen(symbolic(*function_final._FUNCptr,title_tmp)).print(contextptr); 5395 if (!mytitle.empty()){ 5396 int dt=int(fl_width(mytitle.c_str())); 5397 check_fl_draw(mytitle.c_str(),deltax+(horizontal_pixels-dt)/2,deltay+h()-labelsize()/4,clip_x,clip_y,clip_w,clip_h,0,0); 5398 } 5399 // Boundary values 5400 fl_font(FL_HELVETICA,labelsize()); 5401 if (show_axes>=1){ 5402 int taille,affs,delta; 5403 vecteur aff; 5404 string tmp; 5405 bool logx=display_mode & 0x400,logy=display_mode & 0x800; 5406 if (show_axes!=2) { 5407 // X 5408 //fl_color(x_axis_color); 5409 aff=ticks(window_xmin,window_xmax,true); 5410 affs=aff.size(); 5411 double tickx,minx=DBL_MAX,maxx=DBL_MIN; 5412 for (int i=0;i<affs;++i){ 5413 double d=evalf_double(aff[i],1,contextptr)._DOUBLE_val; 5414 tmp=print_DOUBLE_(logx?std::pow(10,d):d); 5415 delta=int(horizontal_pixels*(d-window_xmin)/(window_xmax-window_xmin)); 5416 taille=int(fl_width(tmp.c_str())); 5417 if (delta>=taille/2 && delta<=horizontal_pixels){ 5418 tickx=x()+delta; 5419 if (show_axes>1 || logx || d!=0) 5420 fl_line(tickx,y()+vertical_pixels-1,tickx,y()+vertical_pixels-5); 5421 if (minx>tickx) minx=tickx; 5422 if (maxx<tickx) maxx=tickx; 5423 if (args_tmp.empty()) { 5424 if (show_axes==1) fl_color(x_axis_color); 5425 fl_draw(tmp.c_str(),tickx-taille/2,y()+vertical_pixels+labelsize()); 5426 if (show_axes==1) fl_color(FL_BLACK); 5427 } 5428 } 5429 } 5430 if (args_tmp.empty()) 5431 fl_draw(x_axis_unit.c_str(),x()+horizontal_pixels,y()+vertical_pixels+labelsize()-2); 5432 if (show_axes==3 && maxx!=DBL_MIN && minx!=DBL_MAX) 5433 fl_line(minx,y()+vertical_pixels,maxx,y()+vertical_pixels); 5434 } 5435 // Y 5436 //fl_color(y_axis_color); 5437 aff=ticks(window_ymin,window_ymax,true); 5438 affs=aff.size(); 5439 taille=labelsize()/2; 5440 double ticky,miny=DBL_MAX,maxy=DBL_MIN; 5441 for (int j=0;j<affs;++j){ 5442 double d=evalf_double(aff[j],1,contextptr)._DOUBLE_val; 5443 if (show_axes>=2 && !logy && d<0) 5444 continue; 5445 tmp=print_DOUBLE_(logy?std::pow(10,d):d)+y_axis_unit; 5446 delta=int(vertical_pixels*(window_ymax-d)/(window_ymax-window_ymin)); 5447 if (delta>=taille && delta<=vertical_pixels-taille){ 5448 ticky=y()+delta; 5449 if (show_axes>1 || logy || d!=0) 5450 fl_line(x()+horizontal_pixels-1,ticky,x()+horizontal_pixels-5,ticky); 5451 if (miny>ticky) miny=ticky; 5452 if (maxy<ticky) maxy=ticky; 5453 if (show_axes==1) fl_color(y_axis_color); 5454 fl_draw(tmp.c_str(),x()+horizontal_pixels+3,ticky+taille); 5455 if (show_axes==1) fl_color(FL_BLACK); 5456 int tmpi=fl_width(tmp.c_str()); 5457 if (tmpi+horizontal_pixels+3>w()){ 5458 ylegende=(tmpi+3.)/labelsize(); 5459 redraw(); 5460 } 5461 } 5462 } 5463 if (show_axes>=2 && maxy!=DBL_MIN && miny!=DBL_MAX) 5464 fl_line(x()+horizontal_pixels,miny,x()+horizontal_pixels,maxy); 5465 } 5466 if (show_axes==1 || background_image) { 5467 fl_color(FL_BLACK); 5468 if ( !(display_mode & 0x100) ) 5469 fl_rect(x(), y(), horizontal_pixels, vertical_pixels); 5470 } 5471 #else 5472 int horizontal_pixels=w()-(show_axes?int(ylegende*labelsize()):0); 5473 vertical_pixels=h()-((show_axes?1:0)+(!title.empty()))*labelsize(); 5474 int deltax=x(),deltay=y(); 5475 double y_scale=vertical_pixels/(window_ymax-window_ymin); 5476 double x_scale=horizontal_pixels/(window_xmax-window_xmin); 5477 // Then redraw the background 5478 fl_color(FL_WHITE); 5479 fl_rectf(clip_x, clip_y, clip_w, clip_h); 5480 fl_color(FL_BLACK); 5481 if ( !(display_mode & 0x100) ) 5482 fl_rect(x(), y(), horizontal_pixels, vertical_pixels); 5483 if (background_image){ 5484 if (!background_image->second || background_image->second->w()!=w() || background_image->second->h()!=h()){ 5485 if (background_image->second) 5486 delete background_image->second; 5487 if (background_image->first) 5488 background_image->second=background_image->first->copy(w(),h()); 5489 } 5490 if (background_image->second) 5491 background_image->second->draw(x(),y(),w(),h()); 5492 } 5493 // History draw 5494 /****************/ 5495 int xx,yy,ww,hh; 5496 fl_clip_box(clip_x,clip_y,horizontal_pixels,vertical_pixels,xx,yy,ww,hh); 5497 fl_push_clip(xx,yy,ww,hh); 5498 // fl_push_clip(clip_x,clip_y,horizontal_pixels,vertical_pixels); 5499 /****************/ 5500 fl_color(FL_BLACK); 5501 fl_font(FL_HELVETICA,labelsize()); 5502 if ( (display_mode & 2) && !animation_instructions.empty()){ 5503 gen tmp=animation_instructions[animation_instructions_pos % animation_instructions.size()]; 5504 fltk_draw(*this,-1,tmp,x_scale,y_scale,clip_x,clip_y,clip_w,clip_h); 5505 } 5506 if ( display_mode & 0x40 ){ 5507 fltk_draw(*this,-1,trace_instructions,x_scale,y_scale,clip_x,clip_y,clip_w,clip_h); 5508 } 5509 if (display_mode & 1) { 5510 const_iterateur at=plot_instructions.begin(),atend=plot_instructions.end(),it,itend; 5511 for (int plot_i=0;at!=atend;++at,++plot_i){ 5512 if (at->type==_INT_) 5513 continue; 5514 update_infos(*at,contextptr); 5515 if (at->is_symb_of_sommet(at_parameter)){ 5516 gen ff = at->_SYMBptr->feuille; 5517 vecteur f; 5518 if (ff.type==_VECT && (f=*ff._VECTptr).size()==4){ 5519 // parameters.push_back(f); 5520 } 5521 continue; 5522 } 5523 fltk_draw(*this,plot_i,*at,x_scale,y_scale,clip_x,clip_y,clip_w,clip_h); 5524 } // end for at 5525 } 5526 vecteur plot_tmp_v=gen2vecteur(plot_tmp); 5527 const_iterateur jt=plot_tmp_v.begin(),jtend=plot_tmp_v.end(); 5528 for (;jt!=jtend;++jt){ 5529 gen plot_tmp=*jt; 5530 if (plot_tmp.is_symb_of_sommet(at_pnt) && plot_tmp._SYMBptr->feuille.type==_VECT && !plot_tmp._SYMBptr->feuille._VECTptr->empty()){ 5531 vecteur & v=*plot_tmp._SYMBptr->feuille._VECTptr; 5532 // cerr << v << '\n'; 5533 if (v[1].type==_INT_) 5534 plot_tmp=symbolic(at_pnt,makevecteur(v[0],v[1].val | _DOT_LINE | _LINE_WIDTH_2)); 5535 else 5536 plot_tmp=symbolic(at_pnt,v); 5537 try { 5538 fltk_draw(*this,-1,plot_tmp,x_scale,y_scale,clip_x,clip_y,clip_w,clip_h); 5539 } 5540 catch (...){ 5541 } 5542 } 5543 } 5544 fl_line_style(0); // back to default line style 5545 // Draw axis 5546 double I0,J0; 5547 findij(zero,x_scale,y_scale,I0,J0,contextptr); 5548 int i_0=round(I0),j_0=round(J0); 5549 if ( show_axes && (window_ymax>=0) && (window_ymin<=0)){ // X-axis 5550 fl_color(x_axis_color); 5551 check_fl_line(deltax,deltay+j_0,deltax+horizontal_pixels,deltay+j_0,clip_x,clip_y,clip_w,clip_h,0,0); 5552 fl_color(FL_CYAN); 5553 check_fl_line(deltax+i_0,deltay+j_0,deltax+i_0+int(x_scale),deltay+j_0,clip_x,clip_y,clip_w,clip_h,0,0); 5554 fl_color(x_axis_color); 5555 if (x_tick>0 && (horizontal_pixels)/(x_scale*x_tick) < 40){ 5556 double nticks=(horizontal_pixels-I0)/(x_scale*x_tick); 5557 int count=0; 5558 for (int ii=int(-I0/(x_tick*x_scale));ii<=nticks && count<40;++ii,++count){ 5559 int iii=int(I0+ii*x_scale*x_tick+.5); 5560 check_fl_line(deltax+iii,deltay+j_0,deltax+iii,deltay+j_0-4,clip_x,clip_y,clip_w,clip_h,0,0); 5561 } 5562 } 5563 string tmp=x_axis_name.empty()?"x":x_axis_name; 5564 check_fl_draw(tmp.c_str(),deltax+horizontal_pixels-int(fl_width(tmp.c_str())),deltay+j_0+labelsize(),clip_x,clip_y,clip_w,clip_h,0,0); 5565 } 5566 if ( show_axes && (window_xmax>=0) && (window_xmin<=0) ) {// Y-axis 5567 fl_color(y_axis_color); 5568 check_fl_line(deltax+i_0,deltay,deltax+i_0,deltay+vertical_pixels,clip_x,clip_y,clip_w,clip_h,0,0); 5569 fl_color(FL_CYAN); 5570 check_fl_line(deltax+i_0,deltay+j_0,deltax+i_0,deltay+j_0-int(y_scale),clip_x,clip_y,clip_w,clip_h,0,0); 5571 fl_color(y_axis_color); 5572 if (y_tick>0 && vertical_pixels/(y_tick*y_scale) <40 ){ 5573 double nticks=(vertical_pixels-J0)/(y_tick*y_scale); 5574 int count=0; 5575 for (int jj=int(-J0/(y_tick*y_scale));jj<=nticks && count<25;++jj,++count){ 5576 int jjj=int(J0+jj*y_scale*y_tick+.5); 5577 check_fl_line(deltax+i_0,deltay+jjj,deltax+i_0+4,deltay+jjj,clip_x,clip_y,clip_w,clip_h,0,0); 5578 } 5579 } 5580 check_fl_draw(y_axis_name.empty()?"y":y_axis_name.c_str(),deltax+i_0+2,deltay+labelsize(),clip_x,clip_y,clip_w,clip_h,0,0); 5581 } 5582 // Ticks 5583 if (show_axes && (horizontal_pixels)/(x_scale*x_tick) < 40 && vertical_pixels/(y_tick*y_scale) <40 ){ 5584 if (x_tick>0 && y_tick>0 ){ 5585 fl_color(FL_BLACK); 5586 double nticks=(horizontal_pixels-I0)/(x_scale*x_tick); 5587 double mticks=(vertical_pixels-J0)/(y_tick*y_scale); 5588 int count=0; 5589 for (int ii=int(-I0/(x_tick*x_scale));ii<=nticks;++ii){ 5590 int iii=int(I0+ii*x_scale*x_tick+.5); 5591 for (int jj=int(-J0/(y_tick*y_scale));jj<=mticks && count<1600;++jj,++count){ 5592 int jjj=int(J0+jj*y_scale*y_tick+.5); 5593 check_fl_point(deltax+iii,deltay+jjj,clip_x,clip_y,clip_w,clip_h,0,0); 5594 } 5595 } 5596 } 5597 } 5598 /****************/ 5599 fl_pop_clip(); 5600 /****************/ 5601 fl_color(FL_BLACK); 5602 fl_font(FL_HELVETICA,labelsize()); 5603 if (!args_help.empty() && args_tmp.size()<= args_help.size()){ 5604 fl_draw((gettext("Click ")+args_help[giacmax(1,args_tmp.size())-1]).c_str(),x(),y()+labelsize()-2); 5605 } 5606 string mytitle(title); 5607 if (!is_zero(title_tmp) && function_final.type==_FUNC) 5608 mytitle=gen(symbolic(*function_final._FUNCptr,title_tmp)).print(contextptr); 5609 if (!mytitle.empty()){ 5610 int dt=int(fl_width(mytitle.c_str())); 5611 check_fl_draw(mytitle.c_str(),deltax+(horizontal_pixels-dt)/2,deltay+h()-labelsize()/4,clip_x,clip_y,clip_w,clip_h,0,0); 5612 } 5613 // Boundary values 5614 fl_font(FL_HELVETICA,labelsize()); 5615 if (show_axes){ 5616 int taille,affs,delta; 5617 vecteur aff; 5618 string tmp; 5619 bool logx=display_mode & 0x400,logy=display_mode & 0x800; 5620 // X 5621 fl_color(x_axis_color); 5622 aff=ticks(window_xmin,window_xmax,true); 5623 affs=aff.size(); 5624 for (int i=0;i<affs;++i){ 5625 double d=evalf_double(aff[i],1,contextptr)._DOUBLE_val; 5626 tmp=print_DOUBLE_(logx?std::pow(10,d):d); 5627 delta=int(horizontal_pixels*(d-window_xmin)/(window_xmax-window_xmin)); 5628 taille=int(fl_width(tmp.c_str())); 5629 if (delta>=taille/2 && delta<=horizontal_pixels){ 5630 fl_line(x()+delta,y()+vertical_pixels,x()+delta,y()+vertical_pixels+3); 5631 if (args_tmp.empty()) 5632 fl_draw(tmp.c_str(),x()+delta-taille/2,y()+vertical_pixels+labelsize()-2); 5633 } 5634 } 5635 if (args_tmp.empty()) 5636 fl_draw(x_axis_unit.c_str(),x()+horizontal_pixels,y()+vertical_pixels+labelsize()-2); 5637 // Y 5638 fl_color(y_axis_color); 5639 aff=ticks(window_ymin,window_ymax,true); 5640 affs=aff.size(); 5641 taille=labelsize()/2; 5642 for (int j=0;j<affs;++j){ 5643 double d=evalf_double(aff[j],1,contextptr)._DOUBLE_val; 5644 tmp=print_DOUBLE_(logy?std::pow(10,d):d)+y_axis_unit; 5645 delta=int(vertical_pixels*(window_ymax-d)/(window_ymax-window_ymin)); 5646 if (delta>=taille && delta<=vertical_pixels-taille){ 5647 fl_line(x()+horizontal_pixels,y()+delta,x()+horizontal_pixels+3,y()+delta); 5648 fl_draw(tmp.c_str(),x()+horizontal_pixels+3,y()+delta+taille); 5649 int tmpi=fl_width(tmp.c_str()); 5650 if (tmpi+horizontal_pixels+3>w()){ 5651 ylegende=(tmpi+3.)/labelsize(); 5652 redraw(); 5653 } 5654 } 5655 } 5656 } 5657 #endif 5658 } 5659 draw()5660 void Graph2d::draw(){ 5661 int clip_x,clip_y,clip_w,clip_h; 5662 if (!hp) 5663 hp=geo_find_history_pack(this); 5664 context * contextptr = hp?hp->contextptr:0; 5665 #ifdef HAVE_LIBPTHREAD 5666 // cerr << "graph2d draw lock" << '\n'; 5667 int locked=pthread_mutex_trylock(&interactive_mutex); 5668 if (locked) 5669 return; 5670 #endif 5671 bool b=io_graph(contextptr); 5672 io_graph(false,contextptr); 5673 bool block=block_signal; 5674 block_signal=true; 5675 // cerr << "graph2d draw " << this << " block_signal" << '\n'; 5676 fl_clip_box(x(),y(),w(),h(),clip_x,clip_y,clip_w,clip_h); 5677 fl_push_clip(clip_x,clip_y,clip_w,clip_h); 5678 int horizontal_pixels=w()-(show_axes?int(ylegende*labelsize()):0); 5679 int vertical_pixels; 5680 int deltax=x(),deltay=y(); 5681 in_draw(clip_x,clip_y,clip_w,clip_h,vertical_pixels); 5682 // Draw mouse drag 5683 if ( pushed && !waiting_click && current_i>=0 && current_i<=horizontal_pixels && current_j>=0 && current_j <=vertical_pixels && (push_i!=current_i || push_j!=current_j ) ){ 5684 fl_color(FL_RED); 5685 check_fl_rect(deltax+min(push_i,current_i),deltay+min(push_j,current_j),absint(current_i-push_i),absint(current_j-push_j),clip_x,clip_y,clip_w,clip_h,0,0); 5686 } 5687 fl_pop_clip(); 5688 if (!paused) 5689 ++animation_instructions_pos; 5690 // cerr << "graph2d draw " << this << " restore block_signal" << '\n'; 5691 block_signal=block; 5692 io_graph(b,contextptr); 5693 #ifdef HAVE_LIBPTHREAD 5694 pthread_mutex_unlock(&interactive_mutex); 5695 // cerr << "graph2d draw unlock" << '\n'; 5696 #endif 5697 } 5698 autoname_plus_plus()5699 void Graph2d3d::autoname_plus_plus(){ 5700 if (hp){ 5701 string s=autoname(hp->contextptr); 5702 giac::autoname_plus_plus(s); 5703 autoname(s,hp->contextptr); 5704 } 5705 } 5706 update(Fl_Group * pack,int pos)5707 void Graph2d3d::update(Fl_Group * pack,int pos){ 5708 if (!pack) 5709 return; 5710 show(); 5711 if (pos>=0){ // Check if we need to update from pos or pos+1 5712 if ( (last_event=FL_DRAG || last_event==FL_RELEASE) && pack->children()>pos){ 5713 Gen_Value_Slider * gs=dynamic_cast<Gen_Value_Slider *>(Fl::belowmouse()); 5714 if (gs){ // last handle required by a cursor? 5715 Fl_Widget * wid=pack->child(pos); 5716 Fl_Tile * t=dynamic_cast<Fl_Tile *>(wid); 5717 if (t && t->children()>=3) 5718 wid=t->child(2); 5719 Fl_Scroll * s =dynamic_cast<Fl_Scroll *>(wid); 5720 if (s) 5721 wid=s->child(0); 5722 if (const Gen_Output * go = dynamic_cast<const Gen_Output *>(wid)){ 5723 if (go->value().is_symb_of_sommet(at_parameter)) 5724 ++pos; 5725 } 5726 // cerr << clock() << " ++pos " << pos << " " << last_event << '\n'; 5727 } 5728 else 5729 ; // cerr << clock() << " =pos " << pos << " " << last_event << '\n'; 5730 } 5731 } 5732 else 5733 ++pos; 5734 // pack is normally a History_Pack 5735 clear(pos); 5736 add(pack,pos); 5737 } 5738 add(const Fl_Widget * wid,int pos)5739 void Graph2d3d::add(const Fl_Widget * wid,int pos){ 5740 if (const Gen_Output * g = dynamic_cast<const Gen_Output *>(wid)){ 5741 add(g->value()); 5742 return; 5743 } 5744 if (const Fl_Group * g = dynamic_cast<const Fl_Group *>(wid)){ 5745 int n=g->children(); 5746 for (int i=pos;i<n;++i){ 5747 const Fl_Widget * wid = g->child(i); 5748 add(wid); 5749 } 5750 } 5751 } 5752 clear(unsigned pos)5753 void Graph2d3d::clear(unsigned pos){ 5754 redraw(); 5755 // Clear plot_instructions starting at pos+1, 5756 // clear parameters starting at pos+1 5757 if (pos<plot_instructions.size()) 5758 plot_instructions.erase(plot_instructions.begin()+pos,plot_instructions.end()); 5759 if (param_group){ 5760 param_group->redraw(); 5761 int n=param_group->children(),i=0; 5762 for (;i<n;++i){ 5763 if (Gen_Value_Slider * gvs=dynamic_cast<Gen_Value_Slider *>(param_group->child(i))){ 5764 if (gvs->pos>=int(pos)) 5765 break; 5766 } 5767 } 5768 for (;i<n;--n){ 5769 param_group->remove(param_group->child(n-1)); 5770 } 5771 } 5772 } 5773 handle(int event)5774 int Figure::handle(int event){ 5775 if (event==FL_MOUSEWHEEL){ 5776 if (!Fl::event_inside(this)) 5777 return 0; 5778 if (Fl::focus()==geo){ 5779 int res=geo->handle(event); 5780 if (res) 5781 return res; 5782 } 5783 if (!Fl::event_inside(s)) 5784 return 0; 5785 return s->child(2)->handle(event); 5786 } 5787 return Fl_Tile::handle(event); 5788 } 5789 rename(const string & s)5790 void Figure::rename(const string & s){ 5791 if (namestr) 5792 delete namestr; 5793 string s1="Save "+s; 5794 namestr = new char[s1.size()+1]; 5795 strcpy(namestr,s1.c_str()); 5796 name->label(namestr); 5797 name->show(); 5798 } 5799 save_figure_as(const string & s_orig)5800 void Figure::save_figure_as(const string & s_orig){ 5801 if (!geo->hp) 5802 return; 5803 string s(s_orig); 5804 if (s.empty()){ 5805 // Get filename 5806 for (;;){ 5807 char * newfile = file_chooser(gettext("Save figure"), "*.cas", "session.cas"); 5808 if ( (!newfile) || (!*newfile)) 5809 return; 5810 s=newfile; // remove_path(newfile); 5811 //s=remove_path(remove_extension(s.substr(0,1000).c_str()))+".cas"; 5812 s=remove_extension(s.substr(0,1000).c_str())+".cas"; 5813 if (access(s.c_str(),R_OK)) 5814 break; 5815 int i=fl_ask("%s",(s+gettext(": file exists. Overwrite?")).c_str()); 5816 if (i==1) 5817 break; 5818 } 5819 } 5820 rename(s); 5821 ofstream of(s.c_str()); 5822 int n=geo->hp->children(); 5823 // geo->hp->clear_modified(); 5824 for (int i=0;i<n;i++){ 5825 Fl_Widget * w = geo->hp->child(i); 5826 if (Fl_Group * g = dynamic_cast<Fl_Group *>(w)){ 5827 if (g->children()){ 5828 w=g->child(0); 5829 if (Fl_Scroll * s =dynamic_cast<Fl_Scroll *>(w)) 5830 w=s->child(0); 5831 if (Multiline_Input_tab * m=dynamic_cast<Multiline_Input_tab *>(w)){ 5832 if (strlen(m->value())) 5833 of << replace(m->value(),'\n',' ')+";" << '\n'; 5834 } 5835 if (Xcas_Text_Editor * m=dynamic_cast<Xcas_Text_Editor *>(w)){ 5836 string s=m->value(); 5837 if (!s.empty()) 5838 of << replace(s,'\n',' ')+";" << '\n'; 5839 } 5840 } 5841 } 5842 } 5843 } 5844 latex_save_figure()5845 std::string Figure::latex_save_figure(){ 5846 static int nsession=0; 5847 nsession++; 5848 string thename="session"+print_INT_(nsession)+".tex"; 5849 if (strlen(this->name->label())){ 5850 thename=remove_extension(remove_path(this->name->label()))+".tex"; 5851 } 5852 return geo->latex(thename.c_str()); 5853 } 5854 cb_Figure_Save(Fl_Widget * m,void *)5855 static void cb_Figure_Save(Fl_Widget * m , void*) { 5856 Figure * f=find_figure(m); 5857 if (f){ 5858 if (f->namestr){ 5859 string tmp(f->namestr); 5860 f->save_figure_as(tmp.substr(5,tmp.size()-5)); 5861 } 5862 else 5863 f->save_figure_as(""); 5864 } 5865 } 5866 cb_Figure_Save_as(Fl_Widget * m,void *)5867 static void cb_Figure_Save_as(Fl_Widget * m , void*) { 5868 Figure * f=find_figure(m); 5869 if (f) 5870 f->save_figure_as(""); 5871 } 5872 figure_insert(Figure * f)5873 std::string figure_insert(Figure * f){ 5874 if (!f->geo->hp) 5875 return ""; 5876 if (f){ 5877 char * newfile = load_file_chooser(gettext("Insert figure"), "*.cas", "",0,false); 5878 if ( file_not_available(newfile)) 5879 return ""; 5880 // Put newfile in selection and paste to f->geo->hp 5881 FILE * fich =fopen(newfile,"r"); 5882 string s; char ch; 5883 for (;fich;){ 5884 ch=fgetc(fich); 5885 if (feof(fich)) 5886 break; 5887 s += ch; 5888 } 5889 Fl::selection(*f,s.c_str(),s.size()); 5890 Fl::focus(f->geo->hp); 5891 Fl::paste(*f->geo->hp); 5892 return newfile; 5893 } 5894 return ""; 5895 } 5896 cb_Figure_Insert(Fl_Widget * m,void *)5897 static void cb_Figure_Insert(Fl_Widget * m , void*) { 5898 Figure * f=find_figure(m); 5899 if (!f) return; 5900 figure_insert(f); 5901 } 5902 cb_Figure_Preview(Fl_Widget * m,void *)5903 static void cb_Figure_Preview(Fl_Widget * m , void*) { 5904 Figure * f=find_figure(m); 5905 if (f) 5906 widget_ps_print(f->geo,remove_path(f->name->label()),true); 5907 } 5908 cb_Figure_Print(Fl_Widget * m,void *)5909 static void cb_Figure_Print(Fl_Widget * m , void*) { 5910 Figure * f=find_figure(m); 5911 if (f) 5912 widget_print(f->geo); 5913 } 5914 cb_Figure_LaTeX_Preview(Fl_Widget * m,void *)5915 static void cb_Figure_LaTeX_Preview(Fl_Widget * m , void*) { 5916 Figure * f=find_figure(m); 5917 if (f){ 5918 string name=f->latex_save_figure(); 5919 xdvi(name); 5920 } 5921 } 5922 cb_Figure_LaTeX_Print(Fl_Widget * m,void *)5923 static void cb_Figure_LaTeX_Print(Fl_Widget * m , void*) { 5924 Figure * f=find_figure(m); 5925 if (f){ 5926 string name=f->latex_save_figure(); 5927 dvips(name); 5928 } 5929 } 5930 5931 figure_param_dialog(Fl_Widget * f,bool adjust,double & tmin,double & tmax,double & tcurrent,double & tstep,string & name,bool symb,string & tmp)5932 int figure_param_dialog(Fl_Widget * f,bool adjust,double & tmin,double & tmax,double & tcurrent,double & tstep,string & name,bool symb,string & tmp){ 5933 static Fl_Window * w = 0; 5934 static Fl_Value_Input * wxmin=0, * wxmax=0, *wcurrent=0,*wstep=0; 5935 static Fl_Input * wname=0; 5936 static Fl_Check_Button * wsymb = 0 ; 5937 static Fl_Return_Button * button0 = 0 ; // ok 5938 static Fl_Button * button1 =0; // cancel 5939 static string paramname; 5940 if (f){ 5941 if (!w){ 5942 int l=f->labelsize(); 5943 int dx=18*l,dy=6*l,dh=dy/3; 5944 Fl_Group::current(0); 5945 w=new Fl_Window(dx,dy); 5946 wxmin=new Fl_Value_Input(dx/9,2,2*dx/9-2,dh-4,"t-"); 5947 wxmin->tooltip(gettext("Parameter minimal value")); 5948 wxmin->value(-5); 5949 wxmax=new Fl_Value_Input(dx/3+dx/9,2,2*dx/9-2,dh-4,"t+"); 5950 wxmax->tooltip(gettext("Parameter maximal value")); 5951 wxmax->value(5); 5952 wcurrent=new Fl_Value_Input(2*dx/3+dx/9,2,2*dx/9-2,dh-4,"t="); 5953 wcurrent->tooltip(gettext("Parameter current value")); 5954 wstep=new Fl_Value_Input(dx/6,2+dh,dx/6-2,dh-4,"step"); 5955 wstep->tooltip(gettext("Parameter step value")); 5956 wstep->minimum(0); 5957 wstep->maximum(1000); 5958 wstep->step(0.001); 5959 wstep->value(0.1); 5960 wname=new Fl_Input(dx/2,2+dh,dx/6-2,dh-4,"name"); 5961 wname->tooltip(gettext("Parameter variable name")); 5962 paramname="a"; 5963 wsymb=new Fl_Check_Button(2*dx/3+l+5,2+dh,l,dh-4,"symb"); 5964 wsymb->tooltip(gettext("Numeric or formal parameter")); 5965 wsymb->value(true); 5966 button0 = new Fl_Return_Button(2,2+2*dh,dx/2-4,dh-4); 5967 button0->shortcut(0xff0d); 5968 button0->label(gettext("OK")); 5969 button1 = new Fl_Button(dx/2+2,2+ 2*dh,dx/2-4,dh-4); 5970 button1->shortcut(0xff1b); 5971 button1->label(gettext("Cancel")); 5972 w->end(); 5973 change_group_fontsize(w,l); 5974 w->resizable(w); 5975 w->label(gettext("Parameter definition")); 5976 } 5977 if (adjust){ 5978 wxmin->value(tmin); 5979 wxmax->value(tmax); 5980 wcurrent->value(tcurrent); 5981 wstep->value(tstep); 5982 paramname=name; 5983 wsymb->value(symb); 5984 } 5985 wname->value(paramname.c_str()); 5986 w->set_modal(); 5987 w->show(); 5988 autosave_disabled=true; 5989 w->hotspot(w); 5990 Fl::focus(wxmin); 5991 int r; 5992 for (;;) { 5993 Fl_Widget *o = Fl::readqueue(); 5994 if (!o) Fl::wait(); 5995 else { 5996 if (o == button0) {r = 0; break;} 5997 if (o == button1) {r = 1; break;} 5998 if (o == w) { r=1; break; } 5999 } 6000 } 6001 w->hide(); 6002 autosave_disabled=false; 6003 if (!r){ // insert parameter in figure pack 6004 autoname_plus_plus(paramname); 6005 name=wname->value(); 6006 tmin=wxmin->value(); 6007 tmax=wxmax->value(); 6008 tcurrent=wcurrent->value(); 6009 tstep=wstep->value(); 6010 if (wsymb->value()) 6011 tmp="assume("+string(wname->value())+"=["+print_DOUBLE_(tcurrent)+","+print_DOUBLE_(tmin)+","+print_DOUBLE_(tmax)+","+print_DOUBLE_(tstep)+"])"; 6012 else 6013 tmp=string(wname->value())+" := element("+print_DOUBLE_(tmin)+".."+print_DOUBLE_(tmax)+","+print_DOUBLE_(tcurrent)+","+print_DOUBLE_(tstep)+")"; 6014 return 1; 6015 } 6016 } // end if (f) 6017 return 0; 6018 } 6019 cb_Figure_Parameter(Fl_Widget * m,void *)6020 static void cb_Figure_Parameter(Fl_Widget * m , void*) { 6021 Fl_Widget * wid=Fl::focus(); 6022 Figure * f=find_figure(m); 6023 if (f){ 6024 if (!f->geo->hp) 6025 return; 6026 string tmp,name; 6027 double tmin,tmax,tcur,tstep; 6028 if (figure_param_dialog(f,false,tmin,tmax,tcur,tstep,name,false,tmp)){ 6029 History_Pack * hp=f->geo->hp; 6030 int pos; 6031 if (hp!=get_history_pack(wid,pos)) 6032 pos=hp->children()-1; 6033 hp->add_entry(pos); 6034 hp->set_value(pos,tmp,true); 6035 } 6036 } 6037 } 6038 6039 6040 // modeplot==0 (paramplot2d), 1 (paramplot3d), 2 (plotfield), 3 (implicit), -1 (polarplot) plotparam_dialog(Fl_Widget * spread_ptr,std::string & arg,int modeplot)6041 int plotparam_dialog(Fl_Widget * spread_ptr,std::string & arg,int modeplot){ 6042 static Fl_Window * w = 0; 6043 static Fl_Input *fcnxt=0, *fcnyt=0, *fcnrhot=0, *fcnxuv=0, *fcnyuv=0, *fcnzuv=0, *fcnfield=0, *fcnimplicit=0,*varnamet=0, * varnameu=0, * varnamev=0, *varnametfield=0,*varnameyfield=0,*varnamex=0,*varnamey=0; 6044 static Fl_Value_Input * tmin=0,*tstep=0,*tmax=0; 6045 static Fl_Value_Input * umin=0,*ustep=0,*umax=0; 6046 static Fl_Value_Input * vmin=0,*vstep=0,*vmax=0; 6047 static Fl_Value_Input * xmin=0,*xstep=0,*xmax=0; 6048 static Fl_Value_Input * ymin=0,*ystep=0,*ymax=0; 6049 static Fl_Return_Button * button0 = 0 ; 6050 static Fl_Button * button1 =0; 6051 static Fl_Check_Button * do_plotfield = 0,*do_normal=0,*do_autonome=0; 6052 static Line_Type *ltres=0; 6053 // static int curvestyle=0; 6054 Graph2d3d * gr = dynamic_cast<Graph2d3d *>(spread_ptr); 6055 if (!gr){ 6056 if (Figure * fig=dynamic_cast<Figure *>(spread_ptr)) 6057 gr=fig->geo; 6058 } 6059 if (!w){ 6060 #ifdef IPAQ 6061 int dx=240,dy=300; 6062 #else 6063 int dx=(spread_ptr?30*spread_ptr->labelsize():500), 6064 dy=spread_ptr?12*spread_ptr->labelsize():400; 6065 #endif 6066 int lignes=5; 6067 Fl_Group::current(0); 6068 w=new Fl_Window(dx,dy); 6069 int l=spread_ptr->labelsize(); 6070 ltres = new Line_Type(2,2,l,l,_MAGENTA+_CAP_FLAT_LINE); 6071 ltres->show_pnt(true); 6072 ltres->show_poly(true); 6073 do_plotfield= new Fl_Check_Button (l+2,2,dx/6-4-l,dy/lignes-4,"Field"); 6074 do_plotfield->value(true); 6075 do_plotfield->tooltip(gettext("Draw slopefield")); 6076 do_autonome= new Fl_Check_Button (2+dx/6,2,dx/6-4,dy/lignes-4,"d=2"); 6077 do_autonome->value(false); 6078 do_autonome->tooltip(gettext("Autonomous 2d systems.")); 6079 do_normal= new Fl_Check_Button (2+dx/3,2,dx/6-4,dy/lignes-4,"||=1"); 6080 do_normal->value(true); 6081 do_normal->tooltip(gettext("Normalize slopefield")); 6082 fcnimplicit=new Fl_Input(dx/2,2,dx/2-4,dy/lignes-4,gettext("F(x,y)=")); 6083 fcnimplicit->value("x^4+y^4+x*y=25"); 6084 fcnimplicit->tooltip(gettext("Implicit expression")); 6085 fcnfield=new Fl_Input(dx/2+dx/6,2,dx/2-dx/6-4,dy/lignes-4,gettext("dy/dt(t,y)=")); 6086 fcnfield->value("sin(t*y)"); 6087 fcnfield->tooltip(gettext("Expression of dy/dt in terms of y and t, e.g. sin(t*y). For autonomous 2d system,change time variable to x and enter d[x,y]/dt in terms of [x,y], e.g. [[1,2],[3,4]]*[x,y]")); 6088 fcnrhot=new Fl_Input(dx/2,2,dx/2-4,dy/lignes-4,gettext("rho(t)=")); 6089 fcnrhot->value("2*t"); 6090 fcnrhot->tooltip(gettext("Expression of modulus rho wrt to angle t (e.g sin(t))")); 6091 fcnxt=new Fl_Input(dx/4,2,dx/4-4,dy/lignes-4,gettext("x(t)=")); 6092 fcnxt->value("sin(2*t)"); 6093 fcnxt->tooltip(gettext("Expression of x wrt to t (e.g sin(t))")); 6094 fcnyt=new Fl_Input(3*dx/4,2,dx/4-4,dy/lignes-4,gettext("y(t)=")); 6095 fcnyt->value("cos(3*t)"); 6096 fcnyt->tooltip(gettext("Expression of y wrt to t (e.g cos(t))")); 6097 fcnxuv=new Fl_Input(dx/6,2,dx/6-4,dy/lignes-4,gettext("x=")); 6098 fcnxuv->value("u+v^2"); 6099 fcnxuv->tooltip(gettext("Expression of x wrt to u and v (e.g. u+v)")); 6100 fcnyuv=new Fl_Input(3*dx/6,2,dx/6-4,dy/lignes-4,gettext("y=")); 6101 fcnyuv->value("cos(u)+v"); 6102 fcnyuv->tooltip(gettext("Expression of y wrt to u and v (e.g exp(u)-v)")); 6103 fcnzuv=new Fl_Input(5*dx/6,2,dx/6-4,dy/lignes-4,gettext("y=")); 6104 fcnzuv->value("sin(u)+v"); 6105 fcnzuv->tooltip(gettext("Expression of z wrt to u and v (e.g u-v)")); 6106 varnamet=new Fl_Input(dx/2,2+dy/lignes,dx/2-4,dy/lignes-4,gettext("Var")); 6107 varnamet->value("t"); 6108 varnamet->tooltip(gettext("Independant variable name (e.g t)")); 6109 varnameu=new Fl_Input(dx/4,2+dy/lignes,dx/4-4,dy/lignes-4,gettext("1st var")); 6110 varnameu->value("u"); 6111 varnameu->tooltip(gettext("First independant variable name (e.g u)")); 6112 varnamev=new Fl_Input(3*dx/4,2+dy/lignes,dx/4-4,dy/lignes-4,gettext("2nd var")); 6113 varnamev->value("v"); 6114 varnamev->tooltip(gettext("Second independant variable name (e.g v)")); 6115 varnamex=new Fl_Input(dx/4,2+dy/lignes,dx/4-4,dy/lignes-4,gettext("1st var")); 6116 varnamex->value("x"); 6117 varnamex->tooltip(gettext("First independant variable name (e.g x)")); 6118 varnamey=new Fl_Input(3*dx/4,2+dy/lignes,dx/4-4,dy/lignes-4,gettext("2nd var")); 6119 varnamey->value("y"); 6120 varnamey->tooltip(gettext("Second independant variable name (e.g y)")); 6121 varnametfield=new Fl_Input(dx/4,2+dy/lignes,dx/4-4,dy/lignes-4,gettext("Time var")); 6122 varnametfield->value("t"); 6123 varnametfield->tooltip(gettext("Time variable name")); 6124 varnameyfield=new Fl_Input(3*dx/4,2+dy/lignes,dx/4-4,dy/lignes-4,gettext("2nd var")); 6125 varnameyfield->value("y"); 6126 varnameyfield->tooltip(gettext("Function variable name")); 6127 tmin = new Fl_Value_Input(dx/6,2+2*dy/lignes,dx/6-2,dy/lignes-4,gettext("tmin")); 6128 tmin->value(-3.14); 6129 tmin->step(0.5); 6130 tstep = new Fl_Value_Input(3*dx/6,2+2*dy/lignes,dx/6-2,dy/lignes-4,gettext("tstep")); 6131 tstep->value(0.1); 6132 tstep->step(0.01); 6133 tmax = new Fl_Value_Input(5*dx/6,2+2*dy/lignes,dx/6-2,dy/lignes-4,gettext("tmax")); 6134 tmax->value(3.14); 6135 tmax->step(0.5); 6136 umin = new Fl_Value_Input(dx/6,2+2*dy/lignes,dx/6-2,dy/lignes-4,gettext("umin")); 6137 umin->value(-4); 6138 umin->step(0.5); 6139 ustep = new Fl_Value_Input(3*dx/6,2+2*dy/lignes,dx/6-2,dy/lignes-4,gettext("ustep")); 6140 ustep->value(0.5); 6141 ustep->step(0.01); 6142 umax = new Fl_Value_Input(5*dx/6,2+2*dy/lignes,dx/6-2,dy/lignes-4,gettext("umax")); 6143 umax->value(4); 6144 umax->step(0.5); 6145 vmin = new Fl_Value_Input(dx/6,2+3*dy/lignes,dx/6-2,dy/lignes-4,gettext("vmin")); 6146 vmin->value(-4); 6147 vmin->step(0.5); 6148 vstep = new Fl_Value_Input(3*dx/6,2+3*dy/lignes,dx/6-2,dy/lignes-4,gettext("vstep")); 6149 vstep->value(0.5); 6150 vstep->step(0.01); 6151 vmax = new Fl_Value_Input(5*dx/6,2+3*dy/lignes,dx/6-2,dy/lignes-4,gettext("vmax")); 6152 vmax->value(4); 6153 vmax->step(0.5); 6154 xmin = new Fl_Value_Input(dx/6,2+2*dy/lignes,dx/6-2,dy/lignes-4,gettext("xmin")); 6155 xmin->value(-5); 6156 xmin->step(0.5); 6157 xstep = new Fl_Value_Input(3*dx/6,2+2*dy/lignes,dx/6-2,dy/lignes-4,gettext("xstep")); 6158 xstep->value(0.1); 6159 xstep->step(0.01); 6160 xmax = new Fl_Value_Input(5*dx/6,2+2*dy/lignes,dx/6-2,dy/lignes-4,gettext("xmax")); 6161 xmax->value(5); 6162 xmax->step(0.5); 6163 ymin = new Fl_Value_Input(dx/6,2+3*dy/lignes,dx/6-2,dy/lignes-4,gettext("ymin")); 6164 ymin->value(-5); 6165 ymin->step(0.5); 6166 ystep = new Fl_Value_Input(3*dx/6,2+3*dy/lignes,dx/6-2,dy/lignes-4,gettext("ystep")); 6167 ystep->value(0.1); 6168 ystep->step(0.01); 6169 ymax = new Fl_Value_Input(5*dx/6,2+3*dy/lignes,dx/6-2,dy/lignes-4,gettext("ymax")); 6170 ymax->value(5); 6171 ymax->step(0.5); 6172 button0 = new Fl_Return_Button(2,2+4*dy/lignes,dx/2-4,dy/lignes-4); 6173 button0->shortcut(0xff0d); 6174 button0->label(gettext("OK")); 6175 button1 = new Fl_Button(dx/2+2,2+4*dy/lignes,dx/2-4,dy/lignes-4); 6176 button1->shortcut(0xff1b); 6177 button1->label(gettext("Cancel")); 6178 w->end(); 6179 change_group_fontsize(w,spread_ptr?spread_ptr->labelsize():14); 6180 w->resizable(w); 6181 } 6182 switch (modeplot){ 6183 case -1: 6184 w->label(gettext("Polar plot")); 6185 break; 6186 case 0: case 1: 6187 w->label(gettext("Parametric plot")); 6188 break; 6189 case 2: 6190 w->label(gettext("Field/Odeplot")); 6191 break; 6192 case 3: 6193 w->label(gettext("Implicitplot")); 6194 break; 6195 } 6196 fcnxt->hide(); 6197 fcnyt->hide(); 6198 fcnrhot->hide(); 6199 fcnxuv->hide(); 6200 fcnyuv->hide(); 6201 fcnzuv->hide(); 6202 fcnfield->hide(); 6203 fcnimplicit->hide(); 6204 varnamet->hide(); 6205 varnameu->hide(); 6206 varnamev->hide(); 6207 varnamex->hide(); 6208 varnamey->hide(); 6209 varnametfield->hide(); 6210 varnameyfield->hide(); 6211 tmax->hide(); 6212 tmin->hide(); 6213 tstep->hide(); 6214 umax->hide(); 6215 umin->hide(); 6216 ustep->hide(); 6217 vmax->hide(); 6218 vmin->hide(); 6219 vstep->hide(); 6220 xmax->hide(); 6221 xmin->hide(); 6222 xstep->hide(); 6223 ymax->hide(); 6224 ymin->hide(); 6225 ystep->hide(); 6226 do_plotfield->hide(); 6227 do_normal->hide(); 6228 do_autonome->hide(); 6229 if (modeplot>=2){ 6230 xmin->show(); 6231 xstep->show(); 6232 xmax->show(); 6233 ymin->show(); 6234 ystep->show(); 6235 ymax->show(); 6236 if (modeplot==2){ 6237 varnametfield->show(); 6238 varnameyfield->show(); 6239 fcnfield->show(); 6240 do_plotfield->show(); 6241 do_normal->show(); 6242 do_autonome->show(); 6243 } 6244 else { 6245 varnamex->show(); 6246 varnamey->show(); 6247 fcnimplicit->show(); 6248 } 6249 } 6250 if (modeplot==1){ 6251 umax->show(); 6252 umin->show(); 6253 ustep->show(); 6254 vmax->show(); 6255 vmin->show(); 6256 vstep->show(); 6257 varnameu->show(); 6258 varnamev->show(); 6259 fcnxuv->show(); 6260 fcnyuv->show(); 6261 fcnzuv->show(); 6262 } 6263 if (modeplot<=0) { 6264 tmax->show(); 6265 tmin->show(); 6266 tstep->show(); 6267 varnamet->show(); 6268 if (modeplot==-1){ 6269 fcnrhot->show(); 6270 tmin->value(0.0); 6271 } 6272 else { 6273 fcnxt->show(); 6274 fcnyt->show(); 6275 } 6276 } 6277 if (gr) { 6278 if (!gr->fcnfield.empty()) 6279 fcnfield->value(gr->fcnfield.c_str()); 6280 xmin->value(gr->window_xmin); 6281 xmax->value(gr->window_xmax); 6282 xstep->value((xmax->value()-xmin->value())/64); 6283 ymin->value(gr->window_xmin); 6284 ymax->value(gr->window_xmax); 6285 ystep->value((xmax->value()-xmin->value())/64); 6286 } 6287 int r=-1; 6288 w->set_modal(); 6289 w->show(); 6290 autosave_disabled=true; 6291 w->hotspot(w); 6292 Fl::focus(button0); 6293 for (;;) { 6294 Fl_Widget *o = Fl::readqueue(); 6295 if (!o) Fl::wait(); 6296 else { 6297 if (o==ltres){ 6298 int i=ltres->line_type(); 6299 bool formel=false,untranslate=false,approx=false; 6300 change_line_type(i,true,approx,"",fcnzuv->visible(),formel,untranslate,false,spread_ptr?spread_ptr->labelsize():14); 6301 ltres->line_type(i); 6302 } 6303 if (o==do_autonome){ 6304 if (do_autonome->value()){ 6305 fcnfield->value("[[1,2],[3,4]]*[x,y]"); 6306 varnametfield->value("x"); 6307 varnameyfield->value("y"); 6308 } 6309 else { 6310 fcnfield->value("sin(t*y)"); 6311 varnametfield->value("t"); 6312 varnameyfield->value("y"); 6313 } 6314 } 6315 if (o == button0) {r = 0; break;} 6316 if (o == button1) {r = 1; break;} 6317 if (o == w) { r=1; break; } 6318 } 6319 } 6320 autosave_disabled=false; 6321 w->hide(); 6322 if (!r){ 6323 if (modeplot==3){ 6324 arg=string(fcnimplicit->value())+",["+string(varnamex->value())+"="+print_DOUBLE_(xmin->value())+".."+print_DOUBLE_(xmax->value()) + string(",")+varnamey->value()+string("=")+print_DOUBLE_(ymin->value())+".."+print_DOUBLE_(ymax->value())+"],xstep="+print_DOUBLE_(xstep->value())+",ystep="+print_DOUBLE_(ystep->value())+",display="+print_color(ltres->line_type()); 6325 return 1; 6326 } 6327 if (modeplot==2){ 6328 if (gr){ 6329 gr->fcnfield=fcnfield->value(); 6330 gr->fcnvars="["+string(varnametfield->value())+","+string(varnameyfield->value())+"]"; 6331 } 6332 arg=string(fcnfield->value())+",["+string(varnametfield->value())+"="+print_DOUBLE_(xmin->value())+".."+print_DOUBLE_(xmax->value()) + string(",")+varnameyfield->value()+string("=")+print_DOUBLE_(ymin->value())+".."+print_DOUBLE_(ymax->value())+"]"; 6333 if (do_normal->value()) 6334 arg+=",normalize"; 6335 arg+= ",xstep="+print_DOUBLE_(xstep->value())+",ystep="+print_DOUBLE_(ystep->value())+",display="+print_color(ltres->line_type()); 6336 return do_plotfield->value()?2:1; 6337 } 6338 if (modeplot==1) { 6339 arg = "["+string(fcnxuv->value())+","+string(fcnyuv->value())+","+string(fcnzuv->value())+"]"; 6340 arg += ",\n["+string(varnameu->value())+"="+print_DOUBLE_(umin->value())+".."+print_DOUBLE_(umax->value()) + string(",")+varnamev->value()+string("=")+print_DOUBLE_(vmin->value())+".."+print_DOUBLE_(vmax->value())+"],\nustep="+print_DOUBLE_(ustep->value())+",vstep="+print_DOUBLE_(vstep->value())+",display="+print_color(ltres->line_type()); 6341 return 1; 6342 } 6343 if (modeplot==-1) 6344 arg = string(fcnrhot->value())+","; 6345 else 6346 arg = "["+string(fcnxt->value())+","+string(fcnyt->value())+"]\n,"; 6347 arg += string(varnamet->value())+"="+print_DOUBLE_(tmin->value())+".."+print_DOUBLE_(tmax->value())+",tstep="+print_DOUBLE_(tstep->value())+",display="+print_color(ltres->line_type()); 6348 return 1; 6349 } 6350 return 0; 6351 } 6352 multiline_focus_error()6353 void multiline_focus_error(){ 6354 fl_alert("%s",gettext("Click first in a commandline")); 6355 } 6356 cb_Figure_Function(Fl_Widget * m,void *)6357 static void cb_Figure_Function(Fl_Widget * m , void*) { 6358 Fl_Widget * wid=Xcas_input_focus; 6359 Figure * f=find_figure(wid); 6360 if (f){ 6361 string arg; 6362 bool dim3=dynamic_cast<Graph3d *>(f->geo); 6363 if (f && tablefunc_dialog(f,arg,true,(dim3?1:0),gettext("Graph of a function"))){ 6364 History_Pack * hp=f->geo->hp; 6365 int pos; 6366 if (hp!=get_history_pack(wid,pos)) 6367 pos=hp->children()-1; 6368 hp->add_entry(pos); 6369 // arg=autoname(hp->contextptr)+(dim3?":= plotfunc(":":=plot(")+arg+")"; 6370 arg=autoname(hp->contextptr)+":=plot("+arg+")"; 6371 f->geo->autoname_plus_plus(); 6372 hp->set_value(pos,arg,true); 6373 } 6374 else Fl::focus(wid); 6375 } 6376 } 6377 cb_Figure_helpon(Fl_Widget * m,const string & cmd)6378 static void cb_Figure_helpon(Fl_Widget * m ,const string & cmd) { 6379 Fl_Widget * wid=Xcas_input_focus; 6380 Figure * f=find_figure(wid); 6381 if (f){ 6382 string ans; 6383 int remove=0; 6384 int r; 6385 if (do_helpon) 6386 r=handle_tab(cmd,*giac::vector_completions_ptr(),2*f->w()/3,2*f->h()/3,remove,ans); 6387 else { 6388 ans=cmd+"()"; 6389 r=1; 6390 } 6391 if (r){ 6392 if (!f->geo->hp) 6393 return; 6394 History_Pack * hp=f->geo->hp; 6395 int pos; 6396 if (hp!=get_history_pack(wid,pos)) 6397 pos=hp->children()-1; 6398 hp->add_entry(pos); 6399 hp->set_value(pos,ans,false); 6400 } 6401 else Fl::focus(wid); 6402 } 6403 } 6404 cb_Figure_Tangent(Fl_Widget * m,void *)6405 static void cb_Figure_Tangent(Fl_Widget * m , void*) { 6406 // cb_set_mode(m,at_segment,at_tangent,2,gettext("Curve,Point")); 6407 cb_Figure_helpon(m,"tangent"); 6408 } 6409 cb_Figure_Implicit(Fl_Widget * m,void *)6410 static void cb_Figure_Implicit(Fl_Widget * m , void*) { 6411 Fl_Widget * wid=Xcas_input_focus; 6412 Figure * f=find_figure(wid); 6413 if (f){ 6414 if (!f->geo->hp) 6415 return; 6416 string arg; 6417 bool dim3=dynamic_cast<Graph3d *>(f->geo); 6418 if (dim3) 6419 fl_message("%s","Currently limited to 2-d"); 6420 else { 6421 if (f && plotparam_dialog(f,arg,3)){ 6422 History_Pack * hp=f->geo->hp; 6423 int pos; 6424 if (hp!=get_history_pack(wid,pos)) 6425 pos=hp->children()-1; 6426 hp->add_entry(pos); 6427 arg=autoname(hp->contextptr)+":=plotimplicit("+arg+")"; 6428 f->geo->autoname_plus_plus(); 6429 hp->set_value(pos,arg,true); 6430 } 6431 else Fl::focus(wid); 6432 } 6433 } 6434 } 6435 cb_Figure_Plotfield(Fl_Widget * m,void *)6436 static void cb_Figure_Plotfield(Fl_Widget * m , void*) { 6437 Fl_Widget * wid=Xcas_input_focus; 6438 Figure * f=find_figure(wid); 6439 if (f){ 6440 if (!f->geo->hp) 6441 return; 6442 string arg; 6443 bool dim3=dynamic_cast<Graph3d *>(f->geo); 6444 int res; 6445 if (dim3) 6446 fl_message("%s","Currently limited to 2-d"); 6447 else { 6448 if (f && (res=plotparam_dialog(f,arg,2))){ 6449 if (res==2){ 6450 History_Pack * hp=f->geo->hp; 6451 int pos; 6452 if (hp!=get_history_pack(wid,pos)) 6453 pos=hp->children()-1; 6454 hp->add_entry(pos); 6455 arg="plotfield("+arg+")"; 6456 hp->set_value(pos,arg,true); 6457 } 6458 cb_set_mode(f,0,at_plotode,1,gettext("Point_on_ode_curve")); 6459 fl_message("%s",gettext("Click initials conditions in graphic window. Change mode when finished.")); 6460 } 6461 else Fl::focus(wid); 6462 } 6463 } 6464 } 6465 cb_plotode(Fl_Widget * m,void *)6466 static void cb_plotode(Fl_Widget * m , void*) { 6467 Figure * f=find_figure(m); 6468 if (f){ 6469 if (f->geo->fcnfield.empty()) 6470 cb_Figure_Plotfield(m,0); 6471 else 6472 cb_set_mode(m,0,at_plotode,1,gettext("Point_on_ode_curve")); 6473 } 6474 } 6475 cb_Figure_Param(Fl_Widget * m,void *)6476 static void cb_Figure_Param(Fl_Widget * m , void*) { 6477 Fl_Widget * wid=Xcas_input_focus; 6478 Figure * f=find_figure(wid); 6479 if (f){ 6480 if (!f->geo->hp) 6481 return; 6482 string arg; 6483 bool dim3=dynamic_cast<Graph3d *>(f->geo); 6484 if (f && plotparam_dialog(f,arg,(dim3?1:0))){ 6485 History_Pack * hp=f->geo->hp; 6486 int pos; 6487 if (hp!=get_history_pack(wid,pos)) 6488 pos=hp->children()-1; 6489 hp->add_entry(pos); 6490 arg=autoname(hp->contextptr)+":=plotparam("+arg+")"; 6491 f->geo->autoname_plus_plus(); 6492 hp->set_value(pos,arg,true); 6493 } 6494 else Fl::focus(wid); 6495 } 6496 } 6497 cb_Figure_Polar(Fl_Widget * m,void *)6498 static void cb_Figure_Polar(Fl_Widget * m , void*) { 6499 Fl_Widget * wid=Xcas_input_focus; 6500 Figure * f=find_figure(wid); 6501 if (f){ 6502 if (!f->geo->hp) 6503 return; 6504 string arg; 6505 bool dim3=dynamic_cast<Graph3d *>(f->geo); 6506 if (dim3) 6507 fl_alert("%s","Not a 3-d graph"); 6508 else { 6509 if (f && plotparam_dialog(f,arg,-1)){ 6510 History_Pack * hp=f->geo->hp; 6511 int pos; 6512 if (hp!=get_history_pack(wid,pos)) 6513 pos=hp->children()-1; 6514 hp->add_entry(pos); 6515 arg=autoname(hp->contextptr)+":=plotpolar("+arg+")"; 6516 f->geo->autoname_plus_plus(); 6517 hp->set_value(pos,arg,true); 6518 } 6519 else Fl::focus(wid); 6520 } 6521 } 6522 } 6523 cb_Figure_Plotarea(Fl_Widget * m,void *)6524 static void cb_Figure_Plotarea(Fl_Widget * m , void*) { 6525 Fl_Widget * wid=Xcas_input_focus; 6526 Figure * f=find_figure(wid); 6527 if (f){ 6528 if (!f->geo->hp) 6529 return; 6530 string arg; 6531 bool dim3=dynamic_cast<Graph3d *>(f->geo); 6532 if (dim3) 6533 fl_alert("%s","Not a 3-d graph"); 6534 else { 6535 if (f && tablefunc_dialog(f,arg,true,2,gettext("Shade area under a curve"))){ 6536 History_Pack * hp=f->geo->hp; 6537 int pos; 6538 if (hp!=get_history_pack(wid,pos)) 6539 pos=hp->children()-1; 6540 hp->add_entry(pos); 6541 arg="plotarea("+arg+")"; 6542 hp->set_value(pos,arg,true); 6543 } 6544 else Fl::focus(wid); 6545 } 6546 } 6547 } 6548 cb_Figure_Sequence(Fl_Widget * m,void *)6549 static void cb_Figure_Sequence(Fl_Widget * m , void*) { 6550 Fl_Widget * wid=Xcas_input_focus; 6551 Figure * f=find_figure(wid); 6552 if (f){ 6553 if (!f->geo->hp) 6554 return; 6555 string arg,u0param; 6556 bool dim3=dynamic_cast<Graph3d *>(f->geo); 6557 if (dim3) 6558 fl_alert("%s","Not a 2-d graph"); 6559 else { 6560 if (f && tableseq_dialog(f,arg,true,gettext("Graph of a recurrent sequence"),u0param)){ 6561 History_Pack * hp=f->geo->hp; 6562 int pos; 6563 if (hp!=get_history_pack(wid,pos)) 6564 pos=hp->children()-1; 6565 hp->add_entry(pos); 6566 arg="plotseq("+arg+")"; 6567 hp->set_value(pos,arg,false); 6568 hp->add_entry(pos); 6569 hp->set_value(pos,u0param,true); 6570 } 6571 else Fl::focus(wid); 6572 } 6573 } 6574 } 6575 6576 /* model for new callbacks 6577 static void cb_Figure(Fl_Widget * m , void*) { 6578 Figure * f=find_figure(m); 6579 if (f){ 6580 } 6581 } 6582 */ 6583 contrast(Fl_Color c)6584 int contrast(Fl_Color c){ 6585 if (c<=7) 6586 return 7-c; 6587 if (c>=8 && c<0x10) 6588 return 7; 6589 if (c>=0x10 && c<0x50) 6590 return 0xf8; 6591 if (c & 0x4) 6592 return 0; 6593 return 7; 6594 } 6595 cb_Figure_Color(Fl_Button * b,void *)6596 static void cb_Figure_Color(Fl_Button * b , void*) { 6597 static string s; 6598 Figure * f=find_figure(b); 6599 if (f){ 6600 Fl_Color col=b->color(); 6601 col=fl_show_colormap(col); 6602 f->couleur->color(col); 6603 Fl_Color col2=Fl_Color(contrast(col)); 6604 f->couleur->labelcolor(col2); 6605 s=col<1000?print_INT_(col):""; 6606 f->couleur->label(s.c_str()); 6607 f->geo->couleur=(col&0xffff) | (f->geo->couleur & 0xffff0000); 6608 f->lt->line_type(f->geo->couleur); 6609 } 6610 } 6611 cb_Figure_Disposition(Fl_Button * b,void *)6612 static void cb_Figure_Disposition(Fl_Button * b , void*) { 6613 Figure * fig=find_figure(b); 6614 if (!fig) return; 6615 fig->disposition=b->value(); 6616 fig->resize(fig->x(),fig->y(),fig->w(),fig->h()); 6617 fig->geo->orthonormalize(); 6618 fig->redraw(); 6619 } 6620 cb_Figure_Approx(Fl_Button * b,void *)6621 static void cb_Figure_Approx(Fl_Button * b , void*) { 6622 Figure * fig=find_figure(b); 6623 if (!fig) return; 6624 fig->geo->approx=b->value(); 6625 } 6626 cb_Figure_Autoeval(Fl_Button * b,void *)6627 static void cb_Figure_Autoeval(Fl_Button * b , void*) { 6628 static string s; 6629 Figure * f=find_figure(b); 6630 if (!f) return; 6631 f->geo->hp->eval_below=!b->value(); 6632 f->geo->clear(); 6633 if (!f->geo->hp->children()) 6634 return; 6635 f->geo->hp->focus(0,true); 6636 } 6637 cb_Exact(Fl_Button * b,void *)6638 static void cb_Exact(Fl_Button * b , void*) { 6639 Figure * f=find_figure(b); 6640 if (f){ 6641 f->geo->approx=false; 6642 } 6643 } 6644 cb_Approx(Fl_Button * b,void *)6645 static void cb_Approx(Fl_Button * b , void*) { 6646 Figure * f=find_figure(b); 6647 if (f){ 6648 f->geo->approx=true; 6649 } 6650 } 6651 cb_Figure_Line_Type(Fl_Widget * b,void *)6652 static void cb_Figure_Line_Type(Fl_Widget * b , void*) { 6653 static string s; 6654 Figure * f=find_figure(b); 6655 if (f){ 6656 int i=f->lt->line_type(); 6657 bool formel=false,untranslate=false; 6658 change_line_type(i,true,f->geo->approx," (next mouse created objects)",(dynamic_cast<Graph3d *>(f->geo)),formel,untranslate,false,f->geo->labelsize()); 6659 Fl_Color col = Fl_Color(i&0xffff); 6660 f->couleur->color(col); 6661 Fl_Color col2=Fl_Color(contrast(col)); 6662 f->couleur->labelcolor(col2); 6663 s=col<1000?print_INT_(col):""; 6664 f->couleur->label(s.c_str()); 6665 f->lt->line_type(i); 6666 f->geo->couleur=i; 6667 } 6668 } 6669 cb_Figure_Portrait(Fl_Widget * b,void *)6670 static void cb_Figure_Portrait(Fl_Widget * b , void*) { 6671 Figure * f=find_figure(b); 6672 if (f){ 6673 f->disposition=0; 6674 f->resize(f->x(),f->y(),f->w(),f->h()); 6675 f->geo->orthonormalize(); 6676 f->redraw(); 6677 } 6678 } 6679 cb_Figure_Landscape(Fl_Widget * b,void *)6680 static void cb_Figure_Landscape(Fl_Widget * b , void*) { 6681 Figure * f=find_figure(b); 6682 if (f){ 6683 f->disposition=1; 6684 f->resize(f->x(),f->y(),f->w(),f->h()); 6685 f->geo->orthonormalize(); 6686 f->redraw(); 6687 } 6688 } 6689 cb_Figure_Focus(Fl_Widget * b,void *)6690 static void cb_Figure_Focus(Fl_Widget * b , void*) { 6691 Figure * f=find_figure(b); 6692 if (f){ 6693 f->geo->handle(FL_FOCUS); 6694 } 6695 } 6696 cb_Figure_Change_Attributs(Fl_Widget * b,void *)6697 static void cb_Figure_Change_Attributs(Fl_Widget * b , void*) { 6698 Figure * f=find_figure(b); 6699 if (!f) return; 6700 if (!f->geo->hp) 6701 return; 6702 if (f && f->geo && f->geo->hp){ 6703 int hp_pos=f->geo->hp->_sel_begin; 6704 f->geo->change_attributs(hp_pos); 6705 } 6706 } 6707 cb_NumericalEdit(Fl_Widget * b,void *)6708 static void cb_NumericalEdit(Fl_Widget * b , void*) { 6709 Figure * f=find_figure(b); 6710 if (!f) return; 6711 if (!f->geo->hp) 6712 return; 6713 if (f && f->geo && f->geo->hp){ 6714 History_Pack * hp =f->geo->hp; 6715 const char * ch=fl_input(gettext("Real number?"),"1"); 6716 static string s; 6717 if (ch){ 6718 double n=atof(ch); 6719 gen g=symbolic(at_legende,makevecteur(gen(f->geo->window_xmin+(f->geo->window_xmax-f->geo->window_xmin)/20,f->geo->window_ymin+(f->geo->window_ymax-f->geo->window_ymin)/20),n)); 6720 gen pntname(autoname(hp->contextptr),hp->contextptr); 6721 g=symbolic(at_sto,gen(makevecteur(g,pntname),_SEQ__VECT)); 6722 f->geo->autoname_plus_plus(); 6723 f->geo->hp->set_gen_value(-1,g); 6724 } 6725 } 6726 } 6727 dim3(Fl_Widget * m)6728 bool dim3(Fl_Widget * m){ 6729 Figure * f=find_figure(m); 6730 if (f && f->geo) 6731 return dynamic_cast<Graph3d *>(f->geo); 6732 else 6733 return false; 6734 } 6735 cb_Frame(Fl_Widget * m,void *)6736 static void cb_Frame(Fl_Widget * m , void*) { 6737 cb_set_mode(m,0,0,255," object_selects_level"); 6738 } 6739 cb_Pointer(Fl_Widget * m,void *)6740 static void cb_Pointer(Fl_Widget * m , void*) { 6741 cb_set_mode(m,0,0,0," point_to_move"); 6742 } 6743 cb_Point(Fl_Widget * m,void *)6744 static void cb_Point(Fl_Widget * m , void*) { 6745 cb_set_mode(m,0,at_point,1,"Point"); 6746 } 6747 cb_Circle(Fl_Widget * m,void *)6748 static void cb_Circle(Fl_Widget * m , void*) { 6749 cb_set_mode(m,at_segment,at_cercle,(dim3(m)?3:2),(dim3(m)?gettext("Center,Point_on_circle,Point_in_plane"):gettext("Center,Point_on_circle"))); 6750 } 6751 cb_Inter_Unique(Fl_Widget * m,void *)6752 static void cb_Inter_Unique(Fl_Widget * m , void*) { 6753 cb_set_mode(m,at_segment,at_inter_unique,2,gettext("Curve1,Curve2")); 6754 } 6755 cb_Inter(Fl_Widget * m,void *)6756 static void cb_Inter(Fl_Widget * m , void*) { 6757 cb_set_mode(m,at_segment,at_inter,2,gettext("Curve1,Curve2")); 6758 } 6759 cb_Inter_3(Fl_Widget * m,void *)6760 static void cb_Inter_3(Fl_Widget * m , void*) { 6761 cb_set_mode(m,at_polygone_ouvert,at_inter,3,gettext("Curve1,Curve2,Point")); 6762 } 6763 cb_Tangent(Fl_Widget * m,void *)6764 static void cb_Tangent(Fl_Widget * m , void*) { 6765 cb_set_mode(m,at_segment,at_tangent,2,gettext("Curve,Point")); 6766 } 6767 cb_Segment(Fl_Widget * m,void *)6768 static void cb_Segment(Fl_Widget * m , void*) { 6769 cb_set_mode(m,at_segment,at_segment,2,gettext("Point1,Point2")); 6770 } 6771 cb_Vector(Fl_Widget * m,void *)6772 static void cb_Vector(Fl_Widget * m , void*) { 6773 cb_set_mode(m,at_vector,at_vector,2,gettext("Point1,Point2")); 6774 } 6775 cb_Demi_Droite(Fl_Widget * m,void *)6776 static void cb_Demi_Droite(Fl_Widget * m , void*) { 6777 cb_set_mode(m,at_demi_droite,at_demi_droite,2,gettext("Point1,Point2")); 6778 } 6779 cb_Droite(Fl_Widget * m,void *)6780 static void cb_Droite(Fl_Widget * m , void*) { 6781 cb_set_mode(m,at_droite,at_droite,2,gettext("Point1,Point2")); 6782 } 6783 cb_DistanceAB(Fl_Widget * m,void *)6784 static void cb_DistanceAB(Fl_Widget * m , void*) { 6785 cb_set_mode(m,at_segment,at_distanceat,3,gettext("Object1,Object2,Position")); 6786 } cb_DistanceABraw(Fl_Widget * m,void *)6787 static void cb_DistanceABraw(Fl_Widget * m , void*) { 6788 cb_set_mode(m,at_segment,at_distanceatraw,3,gettext("Object1,Object2,Position")); 6789 } 6790 cb_AngleABC(Fl_Widget * m,void *)6791 static void cb_AngleABC(Fl_Widget * m , void*) { 6792 cb_set_mode(m,at_triangle,at_angleat,4,gettext("Angle_vertex,Direction1,Direction2,Position")); 6793 } cb_AngleABCraw(Fl_Widget * m,void *)6794 static void cb_AngleABCraw(Fl_Widget * m , void*) { 6795 cb_set_mode(m,at_triangle,at_angleatraw,4,gettext("Angle_vertex,Direction1,Direction2,Position")); 6796 } 6797 cb_Arearaw(Fl_Widget * m,void *)6798 static void cb_Arearaw(Fl_Widget * m , void*) { 6799 cb_set_mode(m,at_areaatraw,at_areaatraw,2,gettext("Object,Position")); 6800 } 6801 cb_Area(Fl_Widget * m,void *)6802 static void cb_Area(Fl_Widget * m , void*) { 6803 cb_set_mode(m,at_areaat,at_areaat,2,gettext("Object,Position")); 6804 } 6805 cb_Perimeterraw(Fl_Widget * m,void *)6806 static void cb_Perimeterraw(Fl_Widget * m , void*) { 6807 cb_set_mode(m,at_perimeteratraw,at_perimeteratraw,2,gettext("Object,Position")); 6808 } 6809 cb_Perimeter(Fl_Widget * m,void *)6810 static void cb_Perimeter(Fl_Widget * m , void*) { 6811 cb_set_mode(m,at_perimeterat,at_perimeterat,2,gettext("Object,Position")); 6812 } 6813 cb_Sloperaw(Fl_Widget * m,void *)6814 static void cb_Sloperaw(Fl_Widget * m , void*) { 6815 cb_set_mode(m,at_slopeatraw,at_slopeatraw,2,gettext("Object,Position")); 6816 } 6817 cb_Slope(Fl_Widget * m,void *)6818 static void cb_Slope(Fl_Widget * m , void*) { 6819 cb_set_mode(m,at_slopeat,at_slopeat,2,gettext("Object,Position")); 6820 } 6821 cb_Symetrie(Fl_Widget * m,void *)6822 static void cb_Symetrie(Fl_Widget * m , void*) { 6823 cb_set_mode(m,at_segment,at_symetrie,2,gettext("Symmetry_center_axis,Object")); 6824 } 6825 cb_Inversion(Fl_Widget * m,void *)6826 static void cb_Inversion(Fl_Widget * m , void*) { 6827 cb_set_mode(m,at_segment,at_inversion,3,gettext("Center,Ratio,Object")); 6828 } 6829 cb_Projection(Fl_Widget * m,void *)6830 static void cb_Projection(Fl_Widget * m , void*) { 6831 cb_set_mode(m,at_segment,at_projection,2,gettext("Curve,Object")); 6832 } 6833 cb_Reciprocation(Fl_Widget * m,void *)6834 static void cb_Reciprocation(Fl_Widget * m , void*) { 6835 cb_set_mode(m,at_segment,at_polaire_reciproque,2,gettext("Circle,Object")); 6836 } 6837 cb_Rotation(Fl_Widget * m,void *)6838 static void cb_Rotation(Fl_Widget * m , void*) { 6839 cb_set_mode(m,at_polygone_ouvert,at_rotation,3,gettext("Center,Angle,Object")); 6840 } 6841 cb_Homothetie(Fl_Widget * m,void *)6842 static void cb_Homothetie(Fl_Widget * m , void*) { 6843 cb_set_mode(m,at_polygone_ouvert,at_homothetie,3,gettext("Center,Ratio,Object")); 6844 } 6845 cb_Translation(Fl_Widget * m,void *)6846 static void cb_Translation(Fl_Widget * m , void*) { 6847 cb_set_mode(m,at_segment,at_translation,2,gettext("Vector,Object")); 6848 } 6849 cb_Similitude(Fl_Widget * m,void *)6850 static void cb_Similitude(Fl_Widget * m , void*) { 6851 cb_set_mode(m,at_polygone_ouvert,at_similitude,4,gettext("Center,Ratio,Angle,Object")); 6852 } 6853 cb_Polygone(Fl_Widget * m,void *)6854 static void cb_Polygone(Fl_Widget * m , void*) { 6855 const char * ch=fl_input(gettext("Number of vertices?"),"5"); 6856 static string s; 6857 if (ch){ 6858 int n=atoi(ch); 6859 s=""; 6860 if (n>=2){ 6861 for (int i=1;i<=n;++i){ 6862 s+=gettext("Point")+print_INT_(i); 6863 if (i<n) 6864 s+=","; 6865 } 6866 cb_set_mode(m,at_polygone_ouvert,at_polygone,n,s); 6867 } 6868 } 6869 } 6870 cb_Triangle(Fl_Widget * m,void *)6871 static void cb_Triangle(Fl_Widget * m , void*) { 6872 cb_set_mode(m,at_segment,at_triangle,3,gettext("Point1,Point2,Point3")); 6873 } 6874 cb_Carre(Fl_Widget * m,void *)6875 static void cb_Carre(Fl_Widget * m , void*) { 6876 cb_set_mode(m,at_carre,at_carre,2,gettext("Point1,Point2")); 6877 } 6878 cb_Mediatrice(Fl_Widget * m,void *)6879 static void cb_Mediatrice(Fl_Widget * m , void*) { 6880 cb_set_mode(m,at_segment,at_mediatrice,2,gettext("Point1,Point2")); 6881 } 6882 cb_Perpendiculaire(Fl_Widget * m,void *)6883 static void cb_Perpendiculaire(Fl_Widget * m , void*) { 6884 cb_set_mode(m,at_segment,at_perpendiculaire,2,gettext("Point,Line")); 6885 } 6886 cb_Parallele(Fl_Widget * m,void *)6887 static void cb_Parallele(Fl_Widget * m , void*) { 6888 cb_set_mode(m,at_segment,at_parallele,2,gettext("Point,Line")); 6889 } 6890 cb_Mediane(Fl_Widget * m,void *)6891 static void cb_Mediane(Fl_Widget * m , void*) { 6892 cb_set_mode(m,at_segment,at_mediane,3,gettext("Sommet_angle,Point2,Point3")); 6893 } 6894 cb_Bissectrice(Fl_Widget * m,void *)6895 static void cb_Bissectrice(Fl_Widget * m , void*) { 6896 cb_set_mode(m,at_segment,at_bissectrice,3,gettext("Sommet_angle,Point2,Point3")); 6897 } 6898 cb_Quadrilatere(Fl_Widget * m,void *)6899 static void cb_Quadrilatere(Fl_Widget * m , void*) { 6900 cb_set_mode(m,at_polygone_ouvert,at_quadrilatere,4,gettext("Point1,Point2,Point3,Point4")); 6901 } 6902 cb_Triangle_Equilateral(Fl_Widget * m,void *)6903 static void cb_Triangle_Equilateral(Fl_Widget * m , void*) { 6904 cb_set_mode(m,at_segment,at_triangle_equilateral,(dim3(m)?3:2),(dim3(m)?gettext("Point1,Point2,Point_in_plane"):gettext("Point1,Point2"))); 6905 } 6906 cb_inscrit(Fl_Widget * m,void *)6907 static void cb_inscrit(Fl_Widget * m , void*) { 6908 cb_set_mode(m,at_segment,at_inscrit,3,gettext("Point1,Point2,Point3")); 6909 } 6910 cb_exinscrit(Fl_Widget * m,void *)6911 static void cb_exinscrit(Fl_Widget * m , void*) { 6912 cb_set_mode(m,at_segment,at_exinscrit,3,gettext("Point1,Point2,Point3")); 6913 } 6914 cb_circonscrit(Fl_Widget * m,void *)6915 static void cb_circonscrit(Fl_Widget * m , void*) { 6916 cb_set_mode(m,at_segment,at_circonscrit,3,gettext("Point1,Point2,Point3")); 6917 } 6918 cb_ellipse(Fl_Widget * m,void *)6919 static void cb_ellipse(Fl_Widget * m , void*) { 6920 cb_set_mode(m,at_segment,at_ellipse,3,gettext("Focus1,Focus2,Point_on_ellipse")); 6921 } 6922 cb_parabole(Fl_Widget * m,void *)6923 static void cb_parabole(Fl_Widget * m , void*) { 6924 cb_set_mode(m,at_segment,at_parabole,2,gettext("Focus,Point_or_line")); 6925 } 6926 cb_hyperbole(Fl_Widget * m,void *)6927 static void cb_hyperbole(Fl_Widget * m , void*) { 6928 cb_set_mode(m,at_segment,at_hyperbole,3,gettext("Focus1,Focus2,Point_on_hyperbola")); 6929 } 6930 cb_plan(Fl_Widget * m,void *)6931 static void cb_plan(Fl_Widget * m , void*) { 6932 cb_set_mode(m,at_segment,at_plan,3,gettext("Point1,Point2,Point3")); 6933 } 6934 cb_sphere(Fl_Widget * m,void *)6935 static void cb_sphere(Fl_Widget * m , void*) { 6936 cb_set_mode(m,at_sphere,at_sphere,2,gettext("Center,Point_on_sphere")); 6937 } 6938 6939 Fl_Menu_Item Figure_menu[] = { 6940 {gettext("Fig"), 0, 0, 0, 64, 0, 0, 14, 56}, 6941 {gettext("Save figure as text"), 0, (Fl_Callback*)cb_Figure_Save, 0, 0, 0, 0, 14, 56}, 6942 {gettext("Save as alternate filename"), 0, (Fl_Callback*)cb_Figure_Save_as, 0, 0, 0, 0, 14, 56}, 6943 {gettext("Insert"), 0, (Fl_Callback*)cb_Figure_Insert, 0, 0, 0, 0, 14, 56}, 6944 {gettext("Export Print"), 0, 0, 0, 64, 0, 0, 14, 56}, 6945 {gettext("EPS PNG and preview"), 0, (Fl_Callback*)cb_Figure_Preview, 0, 0, 0, 0, 14, 56}, 6946 {gettext("To printer"), 0, (Fl_Callback*)cb_Figure_Print, 0, 0, 0, 0, 14, 56}, 6947 {gettext("Latex preview"), 0, (Fl_Callback*)cb_Figure_LaTeX_Preview, 0, 0, 0, 0, 14, 56}, 6948 {gettext("Latex printer"), 0, (Fl_Callback*)cb_Figure_LaTeX_Print, 0, 0, 0, 0, 14, 56}, 6949 {0}, // end print 6950 {0}, // end file 6951 {gettext("Edit"), 0, 0, 0, 64, 0, 0, 14, 56}, 6952 {gettext("Add parameter"), 0, (Fl_Callback *) cb_Figure_Parameter, 0, 0, 0, 0, 14, 56}, 6953 {gettext("Add numerical value"), 0, (Fl_Callback *) cb_NumericalEdit, 0, 0, 0, 0, 14, 56}, 6954 {gettext("Add new entry"), 0x8006e, (Fl_Callback *) cb_New_Input, 0, 0, 0, 0, 14, 56}, 6955 {gettext("Add an object trace"), 0, (Fl_Callback *) cb_Graph_Traceobject, 0, 0, 0, 0, 14, 56}, 6956 {gettext("Change selection attribut"), 0, (Fl_Callback *) cb_Figure_Change_Attributs, 0, 0, 0, 0, 14, 56}, 6957 {gettext("Paste"), 0, (Fl_Callback *) cb_Paste, 0, 0, 0, 0, 14, 56}, 6958 {gettext("Delete selected levels"), 0, (Fl_Callback *) cb_Delete, 0, 0, 0, 0, 14, 56}, 6959 {gettext("Portrait"), 0, (Fl_Callback *) cb_Figure_Portrait, 0, 0, 0, 0, 14, 56}, 6960 {gettext("Landscape"), 0, (Fl_Callback *) cb_Figure_Landscape, 0, 0, 0, 0, 14, 56}, 6961 {gettext("Undo"), 0x4007a, (Fl_Callback *) History_cb_Undo, 0, 0, 0, 0, 14, 56}, 6962 {gettext("Redo"), 0x40079, (Fl_Callback *) History_cb_Redo, 0, 0, 0, 0, 14, 56}, 6963 {gettext("Focus"), 0x8006d, (Fl_Callback *) cb_Figure_Focus, 0, 0, 0, 0, 14, 56}, 6964 {0}, // end Edit 6965 {gettext("Graph"), 0, 0, 0, 64, 0, 0, 14, 56}, 6966 {gettext("Function"), 0, (Fl_Callback *) cb_Figure_Function, 0, 0, 0, 0, 14, 56}, 6967 {gettext("Tangent"), 0, (Fl_Callback *) cb_Figure_Tangent, 0, 0, 0, 0, 14, 56}, 6968 {gettext("Recurrent sequence (2-d)"), 0, (Fl_Callback *) cb_Figure_Sequence, 0, 0, 0, 0, 14, 56}, 6969 {gettext("Area under curve"), 0, (Fl_Callback *) cb_Figure_Plotarea, 0, 0, 0, 0, 14, 56}, 6970 {gettext("Parametric"), 0, (Fl_Callback *) cb_Figure_Param, 0, 0, 0, 0, 14, 56}, 6971 {gettext("Polar (2-d)"), 0, (Fl_Callback *) cb_Figure_Polar, 0, 0, 0, 0, 14, 56}, 6972 {gettext("Implicit"), 0, (Fl_Callback *) cb_Figure_Implicit, 0, 0, 0, 0, 14, 56}, 6973 {gettext("Slopefield Ode (2-d)"), 0, (Fl_Callback *) cb_Figure_Plotfield, 0, 0, 0, 0, 14, 56}, 6974 {0}, // end Math 6975 {0}, // end menu 6976 }; 6977 6978 Fl_Menu_Item Figure_menubut[] = { 6979 {gettext("Frame"), 0, (Fl_Callback *) cb_Frame, 0, 0, 0, 0, 14, 56}, 6980 {gettext("Pointer"), 0, (Fl_Callback *) cb_Pointer, 0, 0, 0, 0, 14, 56}, 6981 {gettext("point"), 0, (Fl_Callback *) cb_Point, 0, 0, 0, 0, 14, 56}, 6982 {gettext("Lines"), 0, 0, 0, 64, 0, 0, 14, 56}, 6983 {gettext("segment"), 0, (Fl_Callback *) cb_Segment, 0, 0, 0, 0, 14, 56}, 6984 {gettext("vector"), 0, (Fl_Callback *) cb_Vector, 0, 0, 0, 0, 14, 56}, 6985 {gettext("half_line"), 0, (Fl_Callback *) cb_Demi_Droite, 0, 0, 0, 0, 14, 56}, 6986 {gettext("line"), 0, (Fl_Callback *) cb_Droite, 0, 0, 0, 0, 14, 56}, 6987 {gettext("parallel"), 0, (Fl_Callback *) cb_Parallele, 0, 0, 0, 0, 14, 56}, 6988 {gettext("perpendicular"), 0, (Fl_Callback *) cb_Perpendiculaire, 0, 0, 0, 0, 14, 56}, 6989 {gettext("perpen_bisector"), 0, (Fl_Callback *) cb_Mediatrice, 0, 0, 0, 0, 14, 56}, 6990 {gettext("median_line"), 0, (Fl_Callback *) cb_Mediane, 0, 0, 0, 0, 14, 56}, 6991 {gettext("bisector"), 0, (Fl_Callback *) cb_Bissectrice, 0, 0, 0, 0, 14, 56}, 6992 {0}, // end Lines 6993 {gettext("Polygons"), 0, 0, 0, 64, 0, 0, 14, 56}, 6994 {gettext("triangle"), 0, (Fl_Callback *) cb_Triangle, 0, 0, 0, 0, 14, 56}, 6995 {gettext("equilateral_triangle"), 0, (Fl_Callback *) cb_Triangle_Equilateral, 0, 0, 0, 0, 14, 56}, 6996 {gettext("square"), 0, (Fl_Callback *) cb_Carre, 0, 0, 0, 0, 14, 56}, 6997 {gettext("quadrilateral"), 0, (Fl_Callback *) cb_Quadrilatere, 0, 0, 0, 0, 14, 56}, 6998 {gettext("polygon"), 0, (Fl_Callback *) cb_Polygone, 0, 0, 0, 0, 14, 56}, 6999 {0}, // end Triangle 7000 {gettext("Circles"), 0, 0, 0, 64, 0, 0, 14, 56}, 7001 {gettext("circle"), 0, (Fl_Callback *) cb_Circle, 0, 0, 0, 0, 14, 56}, 7002 {gettext("incircle"), 0, (Fl_Callback *) cb_inscrit, 0, 0, 0, 0, 14, 56}, 7003 {gettext("excircle"), 0, (Fl_Callback *) cb_exinscrit, 0, 0, 0, 0, 14, 56}, 7004 {gettext("circumcircle"), 0, (Fl_Callback *) cb_circonscrit, 0, 0, 0, 0, 14, 56}, 7005 {0}, // end Circles 7006 {gettext("Curves"), 0, 0, 0, 64, 0, 0, 14, 56}, 7007 {gettext("ellipse"), 0, (Fl_Callback *) cb_ellipse, 0, 0, 0, 0, 14, 56}, 7008 {gettext("hyperbola"), 0, (Fl_Callback *) cb_hyperbole, 0, 0, 0, 0, 14, 56}, 7009 {gettext("parabola"), 0, (Fl_Callback *) cb_parabole, 0, 0, 0, 0, 14, 56}, 7010 {gettext("plotode"), 0, (Fl_Callback *) cb_plotode, 0, 0, 0, 0, 14, 56}, 7011 {0}, // end Conics 7012 {gettext("Surfaces (3d)"), 0, 0, 0, 64, 0, 0, 14, 56}, 7013 {gettext("plane"), 0, (Fl_Callback *) cb_plan, 0, 0, 0, 0, 14, 56}, 7014 {gettext("sphere"), 0, (Fl_Callback *) cb_sphere, 0, 0, 0, 0, 14, 56}, 7015 {0}, // end Surfaces 7016 {gettext("Measures"), 0, 0, 0, 64, 0, 0, 14, 56}, 7017 {gettext("distanceat"), 0, (Fl_Callback *) cb_DistanceAB, 0, 0, 0, 0, 14, 56}, 7018 {gettext("angleat"), 0, (Fl_Callback *) cb_AngleABC, 0, 0, 0, 0, 14, 56}, 7019 {gettext("areaat"), 0, (Fl_Callback *) cb_Area, 0, 0, 0, 0, 14, 56}, 7020 {gettext("perimeterat"), 0, (Fl_Callback *) cb_Perimeter, 0, 0, 0, 0, 14, 56}, 7021 {gettext("slopeat"), 0, (Fl_Callback *) cb_Slope, 0, 0, 0, 0, 14, 56}, 7022 {gettext("distanceatraw"), 0, (Fl_Callback *) cb_DistanceABraw, 0, 0, 0, 0, 14, 56}, 7023 {gettext("angleatraw"), 0, (Fl_Callback *) cb_AngleABCraw, 0, 0, 0, 0, 14, 56}, 7024 {gettext("areaatraw"), 0, (Fl_Callback *) cb_Arearaw, 0, 0, 0, 0, 14, 56}, 7025 {gettext("perimeteratraw"), 0, (Fl_Callback *) cb_Perimeterraw, 0, 0, 0, 0, 14, 56}, 7026 {gettext("slopeatraw"), 0, (Fl_Callback *) cb_Sloperaw, 0, 0, 0, 0, 14, 56}, 7027 {0}, // end measures 7028 {gettext("Transformations"), 0, 0, 0, 64, 0, 0, 14, 56}, 7029 {gettext("reflection"), 0, (Fl_Callback *) cb_Symetrie, 0, 0, 0, 0, 14, 56}, 7030 {gettext("rotation"), 0, (Fl_Callback *) cb_Rotation, 0, 0, 0, 0, 14, 56}, 7031 {gettext("translation"), 0, (Fl_Callback *) cb_Translation, 0, 0, 0, 0, 14, 56}, 7032 {gettext("projection"), 0, (Fl_Callback *) cb_Projection, 0, 0, 0, 0, 14, 56}, 7033 {gettext("homothety"), 0, (Fl_Callback *) cb_Homothetie, 0, 0, 0, 0, 14, 56}, 7034 {gettext("similarity"), 0, (Fl_Callback *) cb_Similitude, 0, 0, 0, 0, 14, 56}, 7035 {gettext("inversion"), 0, (Fl_Callback *) cb_Inversion, 0, 0, 0, 0, 14, 56}, 7036 {gettext("reciprocation"), 0, (Fl_Callback *) cb_Reciprocation, 0, 0, 0, 0, 14, 56}, 7037 {0}, // end transformations 7038 {gettext("Intersections"), 0, 0, 0, 64, 0, 0, 14, 56}, 7039 {gettext("inter_unique (1 point)"), 0, (Fl_Callback *) cb_Inter_Unique, 0, 0, 0, 0, 14, 56}, 7040 {gettext("inter (close to a point)"), 0, (Fl_Callback *) cb_Inter_3, 0, 0, 0, 0, 14, 56}, 7041 {gettext("inter (list of points)"), 0, (Fl_Callback *) cb_Inter, 0, 0, 0, 0, 14, 56}, 7042 {0}, // end intersections 7043 {gettext("tangent"), 0, (Fl_Callback *) cb_Tangent, 0, 0, 0, 0, 14, 56}, 7044 // {gettext("Exact"), 0, (Fl_Callback *) cb_Exact, 0, 0, 0, 0, 14, 56}, 7045 // {gettext("Approx"), 0, (Fl_Callback *) cb_Approx, 0, 0, 0, 0, 14, 56}, 7046 {0}, // end Menu 7047 }; 7048 7049 // Create a tile with 1st element = a History_Pack, 2nd element geometry 7050 // Pressing enter in a History_Pack Multiline_input should 7051 // eval it + eval below + update parameters and geometry 7052 // by reading Gen_Output values below current level Figure(int X,int Y,int W,int H,int L,bool dim3)7053 Figure::Figure(int X,int Y,int W,int H,int L,bool dim3):Fl_Tile(X,Y,W,H),namestr(0){ 7054 BorderBox * borderbox = new BorderBox(X,Y,w()-labelsize(),h()-labelsize()); 7055 resizable(borderbox); 7056 Fl_Tile::end(); 7057 #ifdef IPAQ 7058 disposition=1; 7059 if (H<340) 7060 H=340; 7061 #else 7062 disposition=0; 7063 #endif 7064 box(FL_FLAT_BOX); 7065 if (L>H/2) 7066 L=H/2; 7067 labelsize(L); 7068 int l=L+6; 7069 Fl_Group::current(this); 7070 if (disposition==1) 7071 s = new xcas::HScroll (X,Y+l+H/2,W,H/2-l); 7072 else 7073 s = new xcas::HScroll (X,Y+l,W/3,H-l); 7074 s->type(Fl_Scroll::VERTICAL_ALWAYS); 7075 s->box(FL_FLAT_BOX); 7076 History_Pack * hp = new History_Pack (s->x(),s->y(),max(s->w()-2*L,20),max(s->h()-L,20)); 7077 // hp->new_question=new_question_multiline_input; 7078 if (hp){ 7079 hp->eval_below=true; 7080 hp->eval_below_once=false; 7081 } 7082 hp->labelsize(L); 7083 hp->pretty_output=false; 7084 hp->eval_below=true; 7085 hp->eval=xcas::Xcas_eval; 7086 hp->_insert=xcas::Xcas_pack_insert; 7087 hp->_select=xcas::Xcas_pack_select; 7088 hp->end(); 7089 hp->add_entry(-1); 7090 s->end(); 7091 win=0; 7092 if (dim3){ 7093 #ifdef GRAPH_WINDOW 7094 Fl_Group::current(this); 7095 if (disposition==1){ 7096 win = new Fl_Window(X,Y+l,W,H/2); 7097 geo = new Geo3d(0,0,W,H/2,hp); 7098 win->end(); 7099 } 7100 else { 7101 win = new Fl_Window(X+W/3,Y+l,2*W/3,H-l); 7102 geo = new Geo3d(0,0,2*W/3,H-l,hp); 7103 Fl_Group::current(win); 7104 win->end(); 7105 } 7106 // Problem: win is not in the window hierarchy, can not call win->show() 7107 Fl_Group::current(this); 7108 #else 7109 if (disposition==1) 7110 geo = new Geo3d(X,Y+l,W,H/2,hp); 7111 else 7112 geo = new Geo3d(X+W/3,Y+l,2*W/3,H-l,hp); 7113 #endif 7114 } 7115 else { 7116 if (disposition==1) 7117 geo = new Geo2d(X,Y+l,W,H/2,hp); 7118 else 7119 geo = new Geo2d(X+W/3,Y+l,2*W/3,H-l,hp); 7120 } 7121 geo->labelsize(L); 7122 geo->autoscale(); 7123 geo->orthonormalize(); 7124 hp->focus(0,true); //geo->handle(FL_FOCUS); 7125 barre=new Fl_Group(X,Y,W,l); 7126 Fl_Menu_Bar * menubar = new Fl_Menu_Bar(X,Y,Max(W/4,68),l); 7127 int n= Figure_menu->size(); 7128 Fl_Menu_Item * menuitem = new Fl_Menu_Item[n]; 7129 for (int i=0;i<n;++i) 7130 *(menuitem+i)=*(Figure_menu+i); 7131 menubar->menu (menuitem); 7132 change_menu_fontsize(menuitem,2,L); // 2=#submenus 7133 int x=X; 7134 x += menubar->w(); 7135 mode = new Fl_Output(x,Y,Max((7*W)/60,35),l); 7136 x += mode->w(); 7137 mode->value(gettext("Frame")); 7138 Fl_Menu_Button * menubut = new Fl_Menu_Button(x,Y,(4*W)/60,l); 7139 menubut->tooltip(gettext("Set mode for mouse constructions")); 7140 #ifndef IPAQ 7141 menubut->label("Mode"); 7142 #endif 7143 n = Figure_menubut->size(); 7144 Fl_Menu_Item * menuitembut = new Fl_Menu_Item[n]; 7145 for (int i=0;i<n;++i) 7146 *(menuitembut+i)=*(Figure_menubut+i); 7147 menubut->menu (menuitembut); 7148 change_menu_fontsize(menuitembut,2,L); // 2=#submenus 7149 x += menubut->w(); 7150 couleur = new Fl_Button(x,Y,(3*l)/2,l); 7151 x += couleur->w(); 7152 couleur->color(0); 7153 couleur->tooltip(gettext("Color used for next mouse drawings")); 7154 couleur->callback((Fl_Callback *) cb_Figure_Color); 7155 lt = new Line_Type(x,Y,l,l); 7156 lt->show_pnt(true); 7157 lt->show_text(true); 7158 lt->show_poly(true); 7159 lt->tooltip(gettext("Line style used for next mouse drawings")); 7160 lt->callback((Fl_Callback *) cb_Figure_Line_Type); 7161 x += l; 7162 Fl_Check_Button * checkb = new Fl_Check_Button(x,Y,3*l,l,"Step"); 7163 checkb->value(false); 7164 checkb->tooltip(gettext("Check for step evaluation")); 7165 checkb->callback((Fl_Callback *) cb_Figure_Autoeval); 7166 x += checkb->w(); 7167 checkdisp = new Fl_Check_Button(x,Y,6*l,l,"Landscape"); 7168 checkdisp->value(false); 7169 checkdisp->tooltip(gettext("Check for landscape")); 7170 checkdisp->callback((Fl_Callback *) cb_Figure_Disposition); 7171 x += checkdisp->w(); 7172 Fl_Check_Button * checkex = new Fl_Check_Button(x,Y,l,l,"~"); 7173 checkex->value(true); 7174 checkex->tooltip(gettext("Check if mouse clicks in approx mode")); 7175 checkex->callback((Fl_Callback *) cb_Figure_Approx); 7176 x += checkex->w(); 7177 name = new Fl_Button(x,Y,W+X-x,l,"<Save figure as text>"); 7178 name->callback((Fl_Callback *) cb_Figure_Save); 7179 name->tooltip(gettext("Save current figure commands independently of the session")); 7180 name->labelsize(L); 7181 name->hide(); 7182 barre->end(); 7183 parent_redraw(this); 7184 } 7185 handle(int event)7186 int BorderBox::handle(int event){ 7187 return 0; 7188 } 7189 draw()7190 void Figure::draw(){ 7191 if (win && !win->shown()) 7192 win->show(); 7193 Fl_Tile::draw(); 7194 } 7195 resize(int X,int Y,int W,int H,double dhp,double dgeo,double dmp)7196 void Figure::resize(int X,int Y,int W,int H,double dhp,double dgeo,double dmp){ 7197 Fl_Widget::resize(X,Y,W,H); 7198 double dall=dhp+dgeo+dmp; 7199 dhp /= dall; dgeo /= dall; dmp /= dall; 7200 int l=labelsize()+6; 7201 if (W>10*l && dmp*W<4*l){ 7202 dmp=4.0/W*l; 7203 dhp=dhp/(dhp+dgeo); 7204 dgeo=1.0-dhp-dmp; 7205 } 7206 barre->resize(X,Y,W,l); 7207 if (disposition==1){ 7208 checkdisp->value(true); 7209 double dgeomp=dgeo+dmp; 7210 geo->resize(X,Y+l,max(W-5*l,int(W*dgeo/dgeomp+.5)),int(H*dgeomp+.5)); 7211 geo->mouse_param_group->resize(X+geo->w(),Y+l,W-geo->w(),geo->h()); 7212 s->resize(X,geo->y()+geo->h(),W,H-geo->h()-l); 7213 } 7214 else { 7215 checkdisp->value(false); 7216 int sw=s->w(),gw=geo->w(),mw=geo->mouse_param_group->w(); 7217 int dw= W-(sw+gw+mw); 7218 sw += dw; 7219 if (sw<l || dhp!=0.25 || dgeo!=0.5 || dmp!=0.25 ){ 7220 sw=int(W*dhp+.5); 7221 gw=int(W*dgeo+.5); 7222 } 7223 s->resize(X,Y+l,sw,H-l); 7224 geo->resize(X+s->w(),Y+l,gw,H-l); 7225 geo->mouse_param_group->resize(X+s->w()+geo->w(),Y+l,W-gw-sw,H-l); 7226 } 7227 //geo->hp->Fl_Group::resize(s->x(),s->y(),max(s->w()-l,20),max(s->h()-l,20)); 7228 init_sizes(); 7229 Fl_Group::resize(x(),y(),w(),h()); 7230 redraw(); 7231 } 7232 animate(int nframes)7233 vecteur Graph2d3d::animate(int nframes){ 7234 int n=param_group->children(); 7235 vecteur res; 7236 if (!n || !hp) 7237 return res; 7238 bool back=nframes<0; 7239 if (back) 7240 nframes=-nframes; 7241 if (nframes<2) 7242 nframes=2; 7243 Gen_Value_Slider * last=0; 7244 for (int i=0;i<nframes;++i){ 7245 for (int j=n-1;j>=0;--j){ 7246 if (Gen_Value_Slider * gvs = dynamic_cast<Gen_Value_Slider *>(param_group->child(j))){ 7247 last=gvs; 7248 double v=gvs->minimum()+(i*(gvs->maximum()-gvs->minimum()))/(nframes-1); 7249 gvs->value(v); 7250 gvs->adjust(false); 7251 } 7252 } 7253 if (!last) 7254 return res; 7255 last->adjust(true); 7256 // wait for the end of evaluation 7257 for (;;){ 7258 Fl_Widget *o = Fl::readqueue(); 7259 if (Xcas_Cancel && o==Xcas_Cancel){ 7260 o->do_callback(); 7261 hp->doing_eval=false; 7262 return res; 7263 } 7264 Xcas_idle_function(0); 7265 if (!hp->doing_eval && !is_context_busy(hp->contextptr)) 7266 break; 7267 } 7268 Fl::flush(); 7269 vecteur resi; 7270 const_iterateur it=plot_instructions.begin(),itend=plot_instructions.end(); 7271 for (;it!=itend;++it){ 7272 gen tmp = *it; 7273 if (tmp.is_symb_of_sommet(at_parameter)) 7274 continue; 7275 if (tmp.is_symb_of_sommet(at_pnt) && tmp._SYMBptr->feuille.type==_VECT){ 7276 vecteur attributs=*tmp._SYMBptr->feuille._VECTptr; 7277 tmp=evalf(attributs[0],eval_level(hp->contextptr),hp->contextptr); 7278 attributs=vecteur(attributs.begin()+1,attributs.end()); 7279 tmp=pnt_attrib(tmp,attributs,hp->contextptr); 7280 } 7281 else 7282 tmp=evalf(tmp,eval_level(hp->contextptr),hp->contextptr); 7283 resi.push_back(tmp); 7284 } 7285 res.push_back(resi); 7286 } 7287 if (back){ 7288 for (int i=nframes-1;i>=0;i--) 7289 res.push_back(res[i]); 7290 } 7291 return res; 7292 } 7293 latex_save_figure()7294 std::string Turtle::latex_save_figure(){ 7295 static int nsession=0; 7296 nsession++; 7297 double xunit=giac::horiz_latex/w(); 7298 double save_vert_latex=giac::vert_latex; 7299 giac::vert_latex=xunit*h(); 7300 string thename="tortue"+print_INT_(nsession)+".tex"; 7301 char * filename = file_chooser(gettext("Export to LaTeX"),"*.tex",thename.c_str()); 7302 7303 if (filename) 7304 graph2tex(filename,turtlevect2vecteur(*turtleptr),0,w(),0,h(),xunit,xunit,true,get_context(this)); 7305 giac::vert_latex=save_vert_latex; 7306 return thename; 7307 } 7308 7309 draw()7310 void Turtle::draw(){ 7311 #if 0 7312 context * contextptr=get_context(this); 7313 if (is_context_busy(contextptr)) 7314 return; 7315 #endif 7316 pthread_mutex_lock(&turtle_mutex); 7317 try { 7318 int clip_x,clip_y,clip_w,clip_h; 7319 fl_clip_box(x(),y(),w(),h(),clip_x,clip_y,clip_w,clip_h); 7320 fl_push_clip(clip_x,clip_y,clip_w,clip_h); 7321 indraw(); 7322 fl_pop_clip(); 7323 } catch (...){ } 7324 pthread_mutex_unlock(&turtle_mutex); 7325 } 7326 indraw()7327 void Turtle::indraw(){ 7328 int deltax=x(),deltay=y(); 7329 int horizontal_pixels=w()-2*giac::COORD_SIZE; 7330 // Check for fast redraw 7331 // Then redraw the background 7332 fl_color(FL_WHITE); 7333 if (!redraw_cap_only) 7334 fl_rectf(deltax, deltay, w(), h()); 7335 if (turtleptr && !turtleptr->empty()){ 7336 if (turtlezoom>8) 7337 turtlezoom=8; 7338 if (turtlezoom<0.125) 7339 turtlezoom=0.125; 7340 // check that position is not out of screen 7341 logo_turtle t=turtleptr->back(); 7342 double x=turtlezoom*(t.x-turtlex); 7343 if (x<0) 7344 turtlex += int(x/turtlezoom); 7345 if (x>=w()-10) 7346 turtlex += int((x-w()+10)/turtlezoom); 7347 double y=turtlezoom*(t.y-turtley); 7348 if (y<0) 7349 turtley += int(y/turtlezoom); 7350 if (y>h()-10) 7351 turtley += int((y-h()+10)/turtlezoom); 7352 } 7353 if (maillage & 0x3){ 7354 fl_color(FL_BLACK); 7355 double xdecal=std::floor(turtlex/10.0)*10; 7356 double ydecal=std::floor(turtley/10.0)*10; 7357 if ( (maillage & 0x3)==1){ 7358 for (double i=xdecal;i<w()+xdecal;i+=10){ 7359 for (double j=ydecal;j<h()+ydecal;j+=10){ 7360 fl_point(deltax+int((i-turtlex)*turtlezoom+.5),deltay+h()-int((j-turtley)*turtlezoom+.5)); 7361 } 7362 } 7363 } 7364 else { 7365 double dj=std::sqrt(3.0)*10,i0=xdecal; 7366 for (double j=ydecal;j<h()+ydecal;j+=dj){ 7367 int J=deltay+int(h()-(j-turtley)*turtlezoom); 7368 for (double i=i0;i<w()+xdecal;i+=10){ 7369 fl_point(deltax+int((i-turtlex)*turtlezoom+.5),J); 7370 } 7371 i0 += dj; 7372 while (i0>=10) 7373 i0 -= 10; 7374 } 7375 } 7376 } 7377 // Show turtle position/cap 7378 if (turtleptr && !turtleptr->empty() && !(maillage & 0x4)){ 7379 logo_turtle turtle=turtleptr->back(); 7380 fl_color(FL_YELLOW); 7381 fl_rectf(deltax+horizontal_pixels,deltay,w()-horizontal_pixels,2*COORD_SIZE); 7382 fl_color(FL_BLACK); 7383 fl_rect(deltax, deltay, w(), h()); 7384 fl_font(FL_HELVETICA,labelsize()); 7385 fl_draw(("x "+print_INT_(int(turtle.x+.5))).c_str(),deltax+horizontal_pixels,deltay+(2*COORD_SIZE)/3-2); 7386 fl_draw(("y "+print_INT_(int(turtle.y+.5))).c_str(),deltax+horizontal_pixels,deltay+(4*COORD_SIZE)/3-3); 7387 fl_draw(("t "+print_INT_(int(turtle.theta+.5))).c_str(),deltax+horizontal_pixels,deltay+2*COORD_SIZE-4); 7388 } 7389 if (redraw_cap_only){ 7390 redraw_cap_only=false; 7391 return; 7392 } 7393 // draw turtle Logo 7394 if (turtleptr){ 7395 int l=turtleptr->size(); 7396 if (l>0){ 7397 logo_turtle prec =(*turtleptr)[0]; 7398 for (int k=1;k<l;++k){ 7399 logo_turtle current =(*turtleptr)[k]; 7400 if (!current.s.empty()){ // Write a string 7401 fl_font(FL_HELVETICA,current.radius); 7402 xcas_color(current.color); 7403 fl_draw(current.s.c_str(),int(deltax+turtlezoom*(current.x-turtlex)),int(deltay+h()-turtlezoom*(current.y-turtley))); 7404 } 7405 else { 7406 if (current.radius>0){ 7407 int r=current.radius & 0x1ff; // bit 0-8 7408 double theta1,theta2; 7409 if (current.direct){ 7410 theta1=prec.theta+double((current.radius >> 9) & 0x1ff); // bit 9-17 7411 theta2=prec.theta+double((current.radius >> 18) & 0x1ff); // bit 18-26 7412 } 7413 else { 7414 theta1=prec.theta-double((current.radius >> 9) & 0x1ff); // bit 9-17 7415 theta2=prec.theta-double((current.radius >> 18) & 0x1ff); // bit 18-26 7416 } 7417 bool rempli=(current.radius >> 27) & 0x1; 7418 bool seg=(current.radius >> 28) & 0x1; // not yet supported 7419 double angle; 7420 int x,y,R; 7421 R=int(2*turtlezoom*r+.5); 7422 angle = M_PI/180*(theta2-90); 7423 if (current.direct){ 7424 x=int(turtlezoom*(current.x-turtlex-r*std::cos(angle) - r)+.5); 7425 y=int(turtlezoom*(current.y-turtley-r*std::sin(angle) + r)+.5); 7426 } 7427 else { 7428 x=int(turtlezoom*(current.x-turtlex+r*std::cos(angle) -r)+.5); 7429 y=int(turtlezoom*(current.y-turtley+r*std::sin(angle) +r)+.5); 7430 } 7431 xcas_color(current.color); 7432 if (current.direct){ 7433 if (rempli) 7434 fl_pie_seg(deltax+x,deltay+h()-y,R,R,theta1-90,theta2-90,seg); 7435 else 7436 fl_arc(deltax+x,deltay+h()-y,R,R,theta1-90,theta2-90); 7437 } 7438 else { 7439 if (rempli) 7440 fl_pie_seg(deltax+x,deltay+h()-y,R,R,90+theta2,90+theta1,seg); 7441 else 7442 fl_arc(deltax+x,deltay+h()-y,R,R,90+theta2,90+theta1); 7443 } 7444 } // end radius>0 7445 else { 7446 if (prec.mark){ 7447 xcas_color(prec.color); 7448 fl_line(deltax+int(turtlezoom*(prec.x-turtlex)+.5),deltay+int(h()+turtlezoom*(turtley-prec.y)+.5),deltax+int(turtlezoom*(current.x-turtlex)+.5),deltay+int(h()+turtlezoom*(turtley-current.y)+.5)); 7449 } 7450 } 7451 if (current.radius<-1 && k+current.radius>=0){ 7452 // poly-line from (*turtleptr)[k+current.radius] to (*turtleptr)[k] 7453 fl_begin_complex_polygon(); 7454 for (int i=0;i>=current.radius;--i){ 7455 logo_turtle & t=(*turtleptr)[k+i]; 7456 fl_vertex(deltax+turtlezoom*(t.x-turtlex),deltay+h()+turtlezoom*(turtley-t.y)); 7457 } 7458 fl_vertex(deltax+turtlezoom*(current.x-turtlex),deltay+h()+turtlezoom*(turtley-current.y)); 7459 fl_end_complex_polygon(); 7460 } 7461 } // end else (non-string turtle record) 7462 prec=current; 7463 } // end for (all turtle records) 7464 logo_turtle & t = (*turtleptr)[l-1]; 7465 int x=int(turtlezoom*(t.x-turtlex)+.5); 7466 int y=int(turtlezoom*(t.y-turtley)+.5); 7467 double cost=std::cos(t.theta*deg2rad_d); 7468 double sint=std::sin(t.theta*deg2rad_d); 7469 int Dx=int(turtlezoom*t.turtle_length*cost/2+.5); 7470 int Dy=int(turtlezoom*t.turtle_length*sint/2+.5); 7471 xcas_color(t.color); 7472 if (t.visible){ 7473 fl_line(deltax+x+Dy,deltay+h()-(y-Dx),deltax+x-Dy,deltay+h()-(y+Dx)); 7474 if (!t.mark) 7475 xcas_color(t.color+1); 7476 fl_line(deltax+x+Dy,deltay+h()-(y-Dx),deltax+x+3*Dx,deltay+h()-(y+3*Dy)); 7477 fl_line(deltax+x-Dy,deltay+h()-(y+Dx),deltax+x+3*Dx,deltay+h()-(y+3*Dy)); 7478 } 7479 } 7480 return; 7481 } // End logo mode 7482 } 7483 handle(int event)7484 int Turtle::handle(int event){ 7485 #if 0 7486 context * contextptr=get_context(this); 7487 if (is_context_busy(contextptr)) 7488 return 0; 7489 #endif 7490 // cerr << event << '\n'; 7491 if ( (event==FL_ENTER) || (event==FL_LEAVE) ){ 7492 if (event==FL_LEAVE) 7493 redraw_cap_only=true; 7494 redraw(); 7495 return 1; 7496 } 7497 if (event==FL_FOCUS){ 7498 Fl::focus(this); 7499 return 1; 7500 } 7501 if (event==FL_PUSH){ 7502 push_x=Fl::event_x()-x(); 7503 push_y=Fl::event_y()-y(); 7504 Fl::focus(this); 7505 return 1; 7506 } 7507 int current_x=Fl::event_x()-x(),current_y=Fl::event_y()-y(); 7508 // int horizontal_pixels=w(); 7509 if (event== FL_MOUSEWHEEL ){ 7510 if (Fl::e_dy<0) 7511 turtlezoom *= 0.707 ; 7512 else 7513 turtlezoom *= 1.414 ; 7514 redraw(); 7515 return 1; 7516 } 7517 if (event==FL_RELEASE || event==FL_DRAG){ 7518 if (current_y!=push_y){ 7519 turtley += int((current_y-push_y)); 7520 redraw(); 7521 } 7522 if (current_x!=push_x){ 7523 turtlex += int((push_x-current_x)); 7524 redraw(); 7525 } 7526 push_y=current_y; 7527 push_x=current_x; 7528 return 1; 7529 } 7530 if (event==FL_KEYBOARD){ 7531 switch (Fl::event_key()){ 7532 case FL_Left: 7533 turtlex += 10; 7534 redraw(); 7535 return 1; 7536 case FL_Up: 7537 turtley -= 10; 7538 redraw(); 7539 return 1; 7540 case FL_Right: 7541 turtlex -= 10; 7542 redraw(); 7543 return 1; 7544 case FL_Down: 7545 turtley += 10; 7546 redraw(); 7547 return 1; 7548 case '+': 7549 turtlezoom *= 1.414 ; 7550 redraw(); 7551 return 1; 7552 case '-': 7553 turtlezoom *= 0.707 ; 7554 redraw(); 7555 return 1; 7556 } 7557 } 7558 return 0; 7559 } 7560 ~Turtle()7561 Turtle::~Turtle(){ 7562 context * contextptr=get_context(this); 7563 if (turtle(contextptr).widget==this) 7564 turtle(contextptr).widget=0; 7565 } 7566 cb_Logo_button(No_Focus_Button * b,void *)7567 void cb_Logo_button(No_Focus_Button * b,void *){ 7568 if (!Fl::focus()) 7569 return; 7570 context * contextptr=get_context(b); 7571 int l=language(contextptr); 7572 string text; 7573 if (b->label()==gettext("fw")) 7574 text=localize("avance ",l); 7575 if (b->label()==gettext("bw")) 7576 text=localize("recule ",l); 7577 if (b->label()==gettext("tr")) 7578 text=localize("tourne_droite ",l); 7579 if (b->label()==gettext("tl")) 7580 text=localize("tourne_gauche ",l); 7581 if (b->label()==gettext("ss")) 7582 text=localize("pas_de_cote ",l); 7583 if (b->label()==gettext("ju")) 7584 text=localize("saute ",l); 7585 if (b->label()==gettext("pe")){ 7586 context * contextptr=get_context(b); 7587 text=localize("crayon ",l); 7588 int col = turtle(contextptr).color; 7589 col=fl_show_colormap((Fl_Color) col); 7590 string s=col<1000?print_INT_(col):""; 7591 text += s; 7592 // b->color(col); 7593 } 7594 if (b->label()==gettext("ci")) 7595 text=localize("rond ",l); 7596 if (b->label()==gettext("di")) 7597 text=localize("disque ",l); 7598 if (b->label()==gettext("fr")) 7599 text=localize("rectangle_plein ",l); 7600 if (b->label()==gettext("ft")) 7601 text=localize("triangle_plein ",l); 7602 if (b->label()==gettext("cl")) 7603 text=localize("efface ",l); 7604 if (b->label()==gettext("ec")) 7605 text=localize("ecris ",l); 7606 if (b->label()==gettext("sg")) 7607 text=localize("signe ",l); 7608 if (Fl_Text_Editor * ed=dynamic_cast<Fl_Text_Editor *>(Xcas_input_focus)){ 7609 int i=ed->insert_position(); 7610 ed->buffer()->insert(i,text.c_str()); 7611 ed->insert_position(i+text.size()); 7612 return; 7613 } 7614 Fl::focus(Xcas_input_focus); 7615 if (!text.empty()) 7616 help_output(text.substr(0,text.size()-1),language(get_context(Fl::focus()))); 7617 #ifdef __APPLE__ 7618 const char * ch=text.c_str(); 7619 int ll=strlen(ch); 7620 for (int i=0;i<ll;++ch,++i){ 7621 Fl::e_text= (char *) ch; 7622 Fl::e_length=1; 7623 fl_handle(Fl::focus()); 7624 } 7625 #else 7626 Fl::e_text= (char *) text.c_str(); 7627 Fl::e_length=text.size(); 7628 fl_handle(Fl::focus()); 7629 #endif 7630 } 7631 Logo_eval(Fl_Widget * w)7632 Fl_Widget * Logo_eval(Fl_Widget * w) { 7633 // Check if w is inside a pack inside a scroll inside a Logo group 7634 const context * contextptr = get_context(w); 7635 if (Fl_Input * i=dynamic_cast<Fl_Input *>(w)){ 7636 Fl_Group * g=parent_skip_scroll(w->parent()); // should be a pack 7637 if (g) 7638 g=parent_skip_scroll(g); 7639 if (Logo * l= dynamic_cast<Logo *>(g)){ 7640 string s(i->value()); 7641 if (dynamic_cast<Multiline_Input_tab *>(i)){ 7642 if (!s.empty() && s[s.size()-1]!=';') 7643 s += ";\n"; 7644 else 7645 s += '\n'; 7646 gen g(s,contextptr); 7647 if (!giac::first_error_line(contextptr)){ 7648 l->ed->editor->insert_position(l->ed->editor->buffer()->length()); 7649 l->ed->editor->insert(s.c_str()); 7650 } 7651 else { 7652 string logs(gettext("Not registered\n")); 7653 logs += gettext("Parse error line ")+giac::print_INT_(giac::first_error_line(contextptr))+ gettext(" column ")+print_INT_(giac::lexer_column_number(contextptr))+ gettext(" at ") +giac::error_token_name(contextptr); 7654 fl_alert("%s",logs.c_str()); 7655 } 7656 } 7657 else 7658 s = "// "+s+'\n'; 7659 l->t->redraw(); 7660 } 7661 } 7662 if (Xcas_Text_Editor * i=dynamic_cast<Xcas_Text_Editor *>(w)){ 7663 Fl_Group * g=parent_skip_scroll(w->parent()); // should be a pack 7664 if (g) 7665 g=parent_skip_scroll(g); 7666 if (Logo * l= dynamic_cast<Logo *>(g)){ 7667 string s(i->value()); 7668 if (!s.empty() && s[s.size()-1]!=';') 7669 s += ";\n"; 7670 else 7671 s += '\n'; 7672 gen g(s,contextptr); 7673 if (!giac::first_error_line(contextptr)){ 7674 l->ed->editor->insert_position(l->ed->editor->buffer()->length()); 7675 l->ed->editor->insert(s.c_str()); 7676 } 7677 else { 7678 string logs(gettext("Not registered\n")); 7679 logs += gettext("Parse error line ")+giac::print_INT_(giac::first_error_line(contextptr))+ gettext(" column ")+print_INT_(giac::lexer_column_number(contextptr))+ gettext(" at ") +giac::error_token_name(contextptr); 7680 fl_alert("%s",logs.c_str()); 7681 } 7682 l->t->redraw(); 7683 } 7684 } 7685 return Xcas_eval(w); 7686 } 7687 in_find_turtle(Fl_Widget * wid)7688 Turtle * in_find_turtle(Fl_Widget * wid){ 7689 if (Turtle * g=dynamic_cast<Turtle *>(wid)) 7690 return g; 7691 if (Fl_Group * gr =dynamic_cast<Fl_Group *>(wid)){ 7692 // search in children 7693 int n=gr->children(); 7694 for (int i=0;i<n;++i){ 7695 if (Turtle * res = in_find_turtle(gr->child(i))) 7696 return res; 7697 } 7698 } 7699 return 0; 7700 } 7701 find_turtle(Fl_Widget * wid)7702 Turtle * find_turtle(Fl_Widget * wid){ 7703 if (!wid) return 0; 7704 if (Turtle * res=in_find_turtle(wid)) 7705 return res; 7706 return find_turtle(wid->parent()); 7707 } 7708 cb_Logo_Preview(Fl_Menu_ * m,void *)7709 static void cb_Logo_Preview(Fl_Menu_* m , void*) { 7710 Turtle * gr = find_turtle(m); 7711 if (gr) 7712 widget_ps_print(gr,"tortue",true); 7713 } 7714 cb_Logo_Print(Fl_Menu_ * m,void *)7715 static void cb_Logo_Print(Fl_Menu_* m , void*) { 7716 Turtle * gr = find_turtle(m); 7717 if (gr) 7718 widget_print(gr); 7719 } 7720 latex(const char * filename_) const7721 const char * Turtle::latex(const char * filename_) const { 7722 const char * filename=0; 7723 if ( (filename=latexfilename(filename_)) ){ 7724 double xunit=giac::horiz_latex/w(); 7725 double yunit=giac::vert_latex/h(); 7726 double unit=xunit<yunit?yunit:xunit; 7727 graph2tex(filename,turtlevect2vecteur(*turtleptr),0,w(),0,h(),unit,unit,true,get_context(this)); 7728 } 7729 return filename; 7730 } 7731 7732 cb_Logo_LaTeX_Preview(Fl_Menu_ * m,void *)7733 static void cb_Logo_LaTeX_Preview(Fl_Menu_* m , void*) { 7734 Turtle * f=find_turtle(m); 7735 if (f){ 7736 string name=f->latex_save_figure(); 7737 xdvi(name); 7738 } 7739 } 7740 cb_Logo_LaTeX_Print(Fl_Menu_ * m,void *)7741 static void cb_Logo_LaTeX_Print(Fl_Menu_* m , void*) { 7742 Turtle * f=find_turtle(m); 7743 if (f){ 7744 string name=f->latex_save_figure(); 7745 dvips(name); 7746 } 7747 } 7748 cb_Logo_None(Fl_Menu_ * m,void *)7749 static void cb_Logo_None(Fl_Menu_* m , void*) { 7750 Turtle * f=find_turtle(m); 7751 if (f) { f->maillage=f->maillage & 0x4; f->redraw(); } 7752 } 7753 cb_Logo_Square(Fl_Menu_ * m,void *)7754 static void cb_Logo_Square(Fl_Menu_* m , void*) { 7755 Turtle * f=find_turtle(m); 7756 if (f) { f->maillage=1 | (f->maillage & 0x4); f->redraw(); } 7757 } 7758 cb_Logo_Triangle(Fl_Menu_ * m,void *)7759 static void cb_Logo_Triangle(Fl_Menu_* m , void*) { 7760 Turtle * f=find_turtle(m); 7761 if (f) { f->maillage = 2 | (f->maillage & 0x4); f->redraw(); } 7762 } 7763 cb_Logo_ShowPosition(Fl_Menu_ * m,void *)7764 static void cb_Logo_ShowPosition(Fl_Menu_* m , void*) { 7765 Turtle * f=find_turtle(m); 7766 if (f) { f->maillage=f->maillage & 0x3; f->redraw(); } 7767 } 7768 cb_Logo_HidePosition(Fl_Menu_ * m,void *)7769 static void cb_Logo_HidePosition(Fl_Menu_* m , void*) { 7770 Turtle * f=find_turtle(m); 7771 if (f) { f->maillage=f->maillage | 0x4; f->redraw(); } 7772 } 7773 cb_Logo_Color(Fl_Menu_ * m,void *)7774 static void cb_Logo_Color(Fl_Menu_* m , void*) { 7775 const giac::context * contextptr=get_context(m); 7776 int i=fl_show_colormap(Fl_Color(turtle(contextptr).color)); 7777 string s="crayon "+print_INT_(i); 7778 if (Fl_Input * i=dynamic_cast<Fl_Input *>(Fl::focus())) 7779 i->insert(s.c_str()); 7780 else 7781 fl_message("%s",s.c_str()); 7782 } 7783 cb_Logo_Zoomin(Fl_Menu_ * m,void *)7784 static void cb_Logo_Zoomin(Fl_Menu_* m , void*) { 7785 Turtle * gr = find_turtle(m); 7786 if (gr){ 7787 gr->turtlezoom*=1.414; 7788 gr->redraw(); 7789 } 7790 } 7791 cb_Logo_Zoomout(Fl_Menu_ * m,void *)7792 static void cb_Logo_Zoomout(Fl_Menu_* m , void*) { 7793 Turtle * gr = find_turtle(m); 7794 if (gr){ 7795 gr->turtlezoom*=0.707; 7796 gr->redraw(); 7797 } 7798 } 7799 cb_Logo_Right(Fl_Menu_ * m,void *)7800 static void cb_Logo_Right(Fl_Menu_* m , void*) { 7801 Turtle * gr = find_turtle(m); 7802 if (gr){ 7803 gr->turtlex -= 10 ; 7804 gr->redraw(); 7805 } 7806 } 7807 cb_Logo_Left(Fl_Menu_ * m,void *)7808 static void cb_Logo_Left(Fl_Menu_* m , void*) { 7809 Turtle * gr = find_turtle(m); 7810 if (gr){ 7811 gr->turtlex += 10 ; 7812 gr->redraw(); 7813 } 7814 } 7815 cb_Logo_Up(Fl_Menu_ * m,void *)7816 static void cb_Logo_Up(Fl_Menu_* m , void*) { 7817 Turtle * gr = find_turtle(m); 7818 if (gr){ 7819 gr->turtley -= 10 ; 7820 gr->redraw(); 7821 } 7822 } 7823 cb_Logo_Down(Fl_Menu_ * m,void *)7824 static void cb_Logo_Down(Fl_Menu_* m , void*) { 7825 Turtle * gr = find_turtle(m); 7826 if (gr){ 7827 gr->turtley += 10 ; 7828 gr->redraw(); 7829 } 7830 } 7831 7832 Fl_Menu_Item Logo_menu[] = { 7833 {gettext("M"), 0, 0, 0, 64, 0, 0, 14, 56}, 7834 {gettext("Mesh"), 0, 0, 0, 64, 0, 0, 14, 56}, 7835 {gettext("None"), 0, (Fl_Callback*)cb_Logo_None, 0, 0, 0, 0, 14, 56}, 7836 {gettext("Square"), 0, (Fl_Callback*)cb_Logo_Square, 0, 0, 0, 0, 14, 56}, 7837 {gettext("Triangle"), 0, (Fl_Callback*)cb_Logo_Triangle, 0, 0, 0, 0, 14, 56}, 7838 {0}, 7839 {gettext("View"), 0, 0, 0, 64, 0, 0, 14, 56}, 7840 {gettext("Zoom in"), 0, (Fl_Callback*)cb_Logo_Zoomin, 0, 0, 0, 0, 14, 56}, 7841 {gettext("Zoom out"), 0, (Fl_Callback*)cb_Logo_Zoomout, 0, 0, 0, 0, 14, 56}, 7842 {gettext("Right"), 0, (Fl_Callback*)cb_Logo_Right, 0, 0, 0, 0, 14, 56}, 7843 {gettext("Left"), 0, (Fl_Callback*)cb_Logo_Left, 0, 0, 0, 0, 14, 56}, 7844 {gettext("Up"), 0, (Fl_Callback*)cb_Logo_Up, 0, 0, 0, 0, 14, 56}, 7845 {gettext("Down"), 0, (Fl_Callback*)cb_Logo_Down, 0, 0, 0, 0, 14, 56}, 7846 {gettext("ShowPosition"), 0, (Fl_Callback*)cb_Logo_ShowPosition, 0, 0, 0, 0, 14, 56}, 7847 {gettext("HidePosition"), 0, (Fl_Callback*)cb_Logo_HidePosition, 0, 0, 0, 0, 14, 56}, 7848 {0}, 7849 {gettext("Export/Print"), 0, 0, 0, 64, 0, 0, 14, 56}, 7850 {gettext("EPS/PNG and preview"), 0, (Fl_Callback*)cb_Logo_Preview, 0, 0, 0, 0, 14, 56}, 7851 {gettext("Print"), 0, (Fl_Callback*)cb_Logo_Print, 0, 0, 0, 0, 14, 56}, 7852 {gettext("Preview (with Latex)"), 0, (Fl_Callback*)cb_Logo_LaTeX_Preview, 0, 0, 0, 0, 14, 56}, 7853 {gettext("Print (with Latex)"), 0, (Fl_Callback*)cb_Logo_LaTeX_Print, 0, 0, 0, 0, 14, 56}, 7854 {0}, 7855 {gettext("Color"), 0, (Fl_Callback*)cb_Logo_Color, 0, 0, 0, 0, 14, 56}, 7856 {0}, 7857 {0} 7858 }; 7859 Logo(int X,int Y,int W,int H,int L)7860 Logo::Logo(int X,int Y,int W,int H,int L):Fl_Tile(X,Y,W,H){ 7861 Fl_Tile::end(); 7862 scroll_position = -1; 7863 box(FL_FLAT_BOX); 7864 if (L>H/2) 7865 L=H/2; 7866 Fl_Group::current(this); 7867 xcas::HScroll * s = new xcas::HScroll (X,Y,W/4,H); 7868 s->box(FL_FLAT_BOX); 7869 hp = new History_Pack (X,Y,max(W/4-20,W/5),max(H-L-20,20)); 7870 // hp->new_question=new_question_multiline_input; 7871 hp->labelsize(L); 7872 hp->pretty_output=false; 7873 hp->eval_below=false; 7874 hp->eval=xcas::Logo_eval; 7875 hp->_insert=xcas::Xcas_pack_insert; 7876 hp->_select=xcas::Xcas_pack_select; 7877 hp->end(); 7878 s->end(); 7879 t = new Turtle(X+W/4,Y,W/2,H-L); 7880 t->labelsize(L); 7881 t->turtleptr=&giac::turtle_stack(context0); // will be overwritten by new_logo in History.cc 7882 t->turtlezoom=2; 7883 int bw=(W/2-5*L/2)/14; 7884 button_group = new Fl_Group(X+W/4,Y+H-L,bw*14,L); 7885 int bx=button_group->x(),by=button_group->y(); 7886 No_Focus_Button * avance = new No_Focus_Button(bx,by,bw,L); 7887 avance->label(gettext("fw")); 7888 avance->tooltip(gettext("Turtle n steps forward")); 7889 avance->callback((Fl_Callback *) cb_Logo_button); 7890 bx += bw; 7891 No_Focus_Button * recule = new No_Focus_Button(bx,by,bw,L); 7892 recule->label(gettext("bw")); 7893 recule->tooltip(gettext("Turtle n steps backward")); 7894 recule->callback((Fl_Callback *) cb_Logo_button); 7895 bx += bw; 7896 No_Focus_Button * td = new No_Focus_Button(bx,by,bw,L); 7897 td->label(gettext("tr")); 7898 td->tooltip(gettext("Turtle turns right n degrees")); 7899 td->callback((Fl_Callback *) cb_Logo_button); 7900 bx += bw; 7901 No_Focus_Button * tg = new No_Focus_Button(bx,by,bw,L); 7902 tg->label(gettext("tl")); 7903 tg->tooltip(gettext("Turtle turns left n degrees")); 7904 tg->callback((Fl_Callback *) cb_Logo_button); 7905 bx += bw; 7906 No_Focus_Button * pc = new No_Focus_Button(bx,by,bw,L); 7907 pc->label(gettext("ss")); 7908 pc->tooltip(gettext("Turtle steps to the left from n steps")); 7909 pc->callback((Fl_Callback *) cb_Logo_button); 7910 bx += bw; 7911 No_Focus_Button * sa = new No_Focus_Button(bx,by,bw,L); 7912 sa->label(gettext("ju")); 7913 sa->tooltip(gettext("Turtle jumps n steps")); 7914 sa->callback((Fl_Callback *) cb_Logo_button); 7915 bx += bw; 7916 No_Focus_Button * cr = new No_Focus_Button(bx,by,bw,L); 7917 cr->label(gettext("pe")); 7918 cr->tooltip(gettext("Change pen color")); 7919 cr->callback((Fl_Callback *) cb_Logo_button); 7920 bx += bw; 7921 No_Focus_Button * ro = new No_Focus_Button(bx,by,bw,L); 7922 ro->label(gettext("ci")); 7923 ro->tooltip(gettext("Circle arc")); 7924 ro->callback((Fl_Callback *) cb_Logo_button); 7925 bx += bw; 7926 No_Focus_Button * di = new No_Focus_Button(bx,by,bw,L); 7927 di->label(gettext("di")); 7928 di->tooltip(gettext("Filled circle arc")); 7929 di->callback((Fl_Callback *) cb_Logo_button); 7930 bx += bw; 7931 No_Focus_Button * rp = new No_Focus_Button(bx,by,bw,L); 7932 rp->label(gettext("fr")); 7933 rp->tooltip(gettext("Filled rectangle")); 7934 rp->callback((Fl_Callback *) cb_Logo_button); 7935 bx += bw; 7936 No_Focus_Button * tp = new No_Focus_Button(bx,by,bw,L); 7937 tp->label(gettext("ft")); 7938 tp->tooltip(gettext("Filled triangle")); 7939 tp->callback((Fl_Callback *) cb_Logo_button); 7940 bx += bw; 7941 No_Focus_Button * ec = new No_Focus_Button(bx,by,bw,L); 7942 ec->label(gettext("ec")); 7943 ec->tooltip(gettext("Write to the right of the turtle")); 7944 ec->callback((Fl_Callback *) cb_Logo_button); 7945 bx += bw; 7946 No_Focus_Button * sg = new No_Focus_Button(bx,by,bw,L); 7947 sg->label(gettext("sg")); 7948 sg->tooltip(gettext("Sign picture")); 7949 sg->callback((Fl_Callback *) cb_Logo_button); 7950 bx += bw; 7951 No_Focus_Button * ef = new No_Focus_Button(bx,by,bw,L); 7952 ef->label(gettext("cl")); 7953 ef->tooltip(gettext("Clear all")); 7954 ef->callback((Fl_Callback *) cb_Logo_button); 7955 button_group->end(); 7956 menubar = new Fl_Menu_Bar(button_group->x()+button_group->w(),button_group->y(),W/2-button_group->w(),L); 7957 int ls= Logo_menu->size(); 7958 Fl_Menu_Item * menuitem = new Fl_Menu_Item[Logo_menu->size()]; 7959 for (int i=0;i<ls;++i) 7960 *(menuitem+i)=*(Logo_menu+i); 7961 menubar->menu (menuitem); 7962 menubar->tooltip(gettext("Turtle menu")); 7963 ed = new Editeur(X+W/4+W/2,Y,W/4,H); 7964 // ed->callback(History_Pack_cb_eval,0); 7965 ed->extension="tor"; 7966 ed->editor->buffer()->insert(0,"efface ;\n"); 7967 ed->editor->insert_position(9); 7968 hp->add_entry(-1); 7969 hp->resize(); 7970 parent_redraw(this); 7971 } 7972 handle(int event)7973 int Logo::handle(int event){ 7974 if (event==FL_MOUSEWHEEL){ 7975 if (!Fl::event_inside(this)) 7976 return 0; 7977 if (Fl::focus()==t){ 7978 int res=t->handle(event); 7979 if (res) 7980 return res; 7981 } 7982 if (!Fl::event_inside(hp->parent())) 7983 return 0; 7984 return hp->parent()->handle(event); 7985 } 7986 return Fl_Tile::handle(event); 7987 } 7988 draw()7989 void Logo::draw(){ 7990 Fl_Tile::draw(); 7991 if (scroll_position>0 && hp){ 7992 if (Fl_Scroll * scroll = dynamic_cast<Fl_Scroll *>(hp->parent())){ 7993 #ifdef _HAVE_FL_UTF8_HDR_ 7994 scroll->scroll_to(0,scroll_position); 7995 #else 7996 scroll->position(0,scroll_position); 7997 #endif 7998 scroll_position=-1; 7999 Fl_Tile::draw(); 8000 } 8001 } 8002 } 8003 resize(int X,int Y,int W,int H)8004 void Logo::resize(int X,int Y,int W,int H){ 8005 Fl_Tile::resize(X,Y,W,H); 8006 int L=labelsize(); 8007 if (L>H/2) 8008 L=H/2; 8009 int hph=hp->h(); 8010 Fl_Group * g = hp->parent(); 8011 if (Fl_Scroll * scroll = dynamic_cast<Fl_Scroll *>(g)) 8012 scroll_position = scroll->yposition(); 8013 g->resize(X,Y,W/4,H); 8014 hp->Fl_Group::resize(X,Y,max(W/4-20,W/5),hph); 8015 hp->resize(); 8016 t->resize(X+W/4,Y,W/2,H-L); 8017 int bw=(W/2-5*L/2)/14*14; 8018 button_group->resize(X+W/4,Y+H-L,bw,L); 8019 menubar->resize(X+W/4+bw,Y+H-L,W/2-bw,L); 8020 ed->resize(X+W/4+W/2,Y,W/4,H); 8021 } 8022 fltk_fl_widget_archive_function(ostream & os,void * ptr)8023 ostream & fltk_fl_widget_archive_function(ostream & os,void * ptr){ 8024 Fl_Widget * w=(Fl_Widget *) ptr; 8025 const context * contextptr=get_context(w); 8026 Graph2d *i=dynamic_cast<Graph2d *>(w); 8027 if (!i) 8028 return archive(os,string2gen("Done",false),contextptr); 8029 os << _POINTER_ << " " << _FL_WIDGET_POINTER << '\n'; 8030 archive(os,i->plot_instructions,contextptr); 8031 archive(os,makevecteur(i->x(),i->y(),i->w(),i->h(),i->window_xmin,i->window_xmax,i->window_ymin,i->window_ymax),contextptr); 8032 return os; 8033 } 8034 fltk_fl_widget_unarchive_function(istream & os)8035 gen fltk_fl_widget_unarchive_function(istream & os){ 8036 // FIXME GIAC_CONTEXT 8037 gen gplot=unarchive(os,context0),gparam=unarchive(os,context0); 8038 if (gplot.type!=_VECT || gparam.type!=_VECT || gparam._VECTptr->size()<8) 8039 return 0; 8040 vecteur v=*gparam._VECTptr; 8041 Fl_Group::current(0); 8042 Graph2d * ptr= new Graph2d(v[0].val,v[1].val,v[2].val,v[3].val,""); 8043 ptr->plot_instructions=vecteur(*gplot._VECTptr); 8044 ptr->window_xmin=v[4]._DOUBLE_val; 8045 ptr->window_xmax=v[5]._DOUBLE_val; 8046 ptr->window_ymin=v[6]._DOUBLE_val; 8047 ptr->window_ymax=v[7]._DOUBLE_val; 8048 return gen(ptr,_FL_WIDGET_POINTER); 8049 } 8050 fltk_fl_widget_texprint_function(void * ptr)8051 std::string fltk_fl_widget_texprint_function(void * ptr){ 8052 static int counter=0; 8053 Fl_Widget * w=(Fl_Widget *) ptr; 8054 Graph2d * i=dynamic_cast<Graph2d *>(w); 8055 ++counter; 8056 double horiz_unit=horiz_latex/(i->window_xmax-i->window_xmin); 8057 double vert_unit=vert_latex/(i->window_ymax-i->window_ymin); 8058 double unit=horiz_unit; 8059 if (horiz_unit>vert_unit) 8060 unit=vert_unit; 8061 string tmpfilename("#tmp"+print_INT_(counter)); 8062 FILE * out =fopen(tmpfilename.c_str(),"w"); 8063 if (!out) 8064 return "Write error"; 8065 if (!graph2tex(out,i->plot_instructions,i->window_xmin,i->window_xmax,i->window_ymin,i->window_ymax,unit,tmpfilename.c_str(),false,get_context(i))) 8066 return "Graph2tex Error"; 8067 fclose(out); 8068 FILE * in=fopen(tmpfilename.c_str(),"r"); 8069 if (!in) 8070 return "Read Error"; 8071 string res; 8072 while (!feof(in)) 8073 res += fgetc(in); 8074 return res; 8075 } 8076 8077 extern Multiline_Input_tab * Xcas_multiline_input; 8078 8079 // adjust history level to the slider value, and eval history pack 8080 // if eval_hp is true adjust(bool eval_hp)8081 void Gen_Value_Slider::adjust(bool eval_hp){ 8082 Fl_Group * g = parent(); // param_group or tile 8083 if (!g) return; 8084 g=parent_skip_scroll(g); // mouse_param_group or history_pack 8085 if (!g) return; 8086 History_Pack * hp=0; 8087 int position=pos; 8088 if (pos==-2){ 8089 hp=dynamic_cast<History_Pack *>(g); 8090 if (hp){ 8091 for (int i=0;i<hp->children();i++){ 8092 if (hp->child(i)==parent()){ 8093 position=i; 8094 break; 8095 } 8096 } 8097 } 8098 } 8099 else { 8100 g=parent_skip_scroll(g); // parent of Graph2d screen 8101 if (!g) return; 8102 // Now find an history_pack inside g 8103 int n=g->children(); 8104 for (int i=0;i<n;++i){ 8105 Fl_Widget * wid = g->child(i); 8106 if (Fl_Scroll * s=dynamic_cast<Fl_Scroll *>(wid)) 8107 if (s->children()) 8108 wid=s->child(0); 8109 if ( (hp=dynamic_cast<History_Pack *>(wid)) ) 8110 break; 8111 } // end for i 8112 } 8113 if (hp){ 8114 // check that level is gvs->g := ... 8115 unsigned m=hp->children(); 8116 if (position>=0 && position<int(m)){ 8117 bool do_cb=false; 8118 giac::gen gt(hp->value(position),hp->contextptr); 8119 if (gt.is_symb_of_sommet(at_sto) && gt._SYMBptr->feuille.type==_VECT && !gt._SYMBptr->feuille._VECTptr->empty() ){ 8120 // Check for element 8121 gen & f = gt._SYMBptr->feuille._VECTptr->front(); 8122 if (f.is_symb_of_sommet(at_element)){ 8123 gen ff = f._SYMBptr->feuille; 8124 if (ff.type==_VECT && !ff._VECTptr->empty()) 8125 ff = ff._VECTptr->front(); 8126 // Change gt value with parameter 8127 ff = symbolic(at_element,gen(makevecteur(ff,value(),Fl_Valuator::step()),_SEQ__VECT)); 8128 gt=symbolic(at_sto,makevecteur(ff,gt._SYMBptr->feuille._VECTptr->back())); 8129 do_cb=true; 8130 } 8131 } // end element 8132 if (gt.is_symb_of_sommet(at_assume)){ 8133 gen & f = gt._SYMBptr->feuille; 8134 if (f.is_symb_of_sommet(at_equal)||f.is_symb_of_sommet(at_same)){ 8135 gen & ff = f._SYMBptr->feuille; 8136 if (ff.type==_VECT && !ff._VECTptr->empty()){ 8137 vecteur v=*ff._VECTptr; 8138 if (v.back().type==_VECT && v.back()._VECTptr->size()>=3){ 8139 vecteur & vb=*v.back()._VECTptr; 8140 gen step=(vb[2]-vb[1])/100; 8141 if (vb.size()>3) 8142 step=vb[3]; 8143 v.back()=makevecteur(value(),vb[1],vb[2],step); 8144 } 8145 else 8146 v.back()=makevecteur(value(),minimum(),maximum(),Fl_Valuator::step()); 8147 gt = symbolic(at_equal,v); 8148 gt = symbolic(at_assume,gt); 8149 do_cb = true; 8150 } 8151 } 8152 if (f.is_symb_of_sommet(at_sto)){ 8153 gen & ff = f._SYMBptr->feuille; 8154 if (ff.type==_VECT && !ff._VECTptr->empty()){ 8155 vecteur v=*ff._VECTptr; 8156 if (v.front().type==_VECT && v.front()._VECTptr->size()>=3){ 8157 vecteur & vf=*v.front()._VECTptr; 8158 gen step=(vf[2]-vf[1])/100.; 8159 if (vf.size()>3) 8160 step=vf[3]; 8161 v.front()=makevecteur(value(),vf[1],vf[2],step); 8162 } 8163 else 8164 v.front() = makevecteur(value(),minimum(),maximum(),Fl_Valuator::step()); 8165 gt = symbolic(at_sto,v); 8166 gt = symbolic(at_assume,gt); 8167 do_cb = true; 8168 } 8169 } 8170 } // end assume 8171 if (do_cb){ 8172 hp->update_pos=position; 8173 if (pos==-2) 8174 hp->eval_below=true; 8175 gen curseur=protecteval(gt,1,hp->contextptr); 8176 Graph2d3d * graph=find_graph2d3d(hp); 8177 if (curseur.is_symb_of_sommet(at_parameter) && graph){ 8178 vecteur & v=graph->plot_instructions; 8179 if (position>=0 && v.size()>position){ 8180 gen & vp=v[position]; 8181 if (vp.is_symb_of_sommet(at_parameter) && vp._SYMBptr->feuille[0]==curseur._SYMBptr->feuille[0]) 8182 vp=curseur; 8183 } 8184 } 8185 // check how to update (parameter in a figure or in history) 8186 Fl_Group * gr = hp->widget_group(position); 8187 if (gr && gr->children()>=3){ 8188 if (dynamic_cast<Fl_Output*>(gr->child(2))){ 8189 hp->update_pos=position; 8190 hp->set_gen_value(position,gt,true); 8191 return; 8192 } 8193 } 8194 hp->set_gen_value(position,gt,false); 8195 if (eval_hp && hp->children()>position+1){ 8196 hp->update_pos=position+1; 8197 gt=hp->parse(position+1); 8198 if (!is_undef(gt)) 8199 hp->set_gen_value(position+1,gt,true); 8200 } 8201 } // end do_cb 8202 } // end if gvs->pos<children() 8203 } // end if history_pack hp 8204 } 8205 get_figure(Fl_Widget * widget)8206 Figure * get_figure(Fl_Widget * widget){ 8207 for (;widget;){ 8208 if (Figure * f =dynamic_cast<Figure *>(widget)) 8209 return f; 8210 widget = widget->parent(); 8211 } 8212 return 0; 8213 } 8214 handle(int event)8215 int Gen_Value_Slider::handle(int event){ 8216 string tmp; 8217 Figure * f=get_figure(this); 8218 int position=pos; 8219 History_Pack * hp=f?f->geo->hp:get_history_pack(this,position); 8220 double tmin=minimum(),tmax=maximum(),tcur=value(),tstep=Fl_Valuator::step(); 8221 // tstep=100*tstep/(tmax-tmin); 8222 if ((event==FL_PUSH || event==FL_DRAG || event==FL_RELEASE) &&Fl::event_button()== FL_RIGHT_MOUSE){ 8223 if (event==FL_RELEASE && hp->children()>position){ 8224 Fl_Widget * wid=hp->child(position); 8225 while (Fl_Group * s=dynamic_cast<Fl_Group *>(wid)) { 8226 if (dynamic_cast<Xcas_Text_Editor *>(wid)) 8227 break; 8228 if (s->children()) 8229 wid=s->child(0); 8230 } 8231 if (Multiline_Input_tab * m=dynamic_cast<Multiline_Input_tab *>(wid)){ 8232 gen g=m->g(); 8233 if (figure_param_dialog(hp,true,tmin,tmax,tcur,tstep,paramname,g.is_symb_of_sommet(at_assume),tmp) ){ 8234 minimum(tmin); 8235 maximum(tmax); 8236 value(tcur); 8237 // tstep=tstep*(tmax-tmin)/100.; 8238 step(tstep,10*tstep); 8239 redraw(); 8240 label(paramname.c_str()); 8241 hp->set_value(position,tmp,true); 8242 // if (!f) 8243 hp->eval_below=true; 8244 } 8245 } 8246 if (Xcas_Text_Editor * m=dynamic_cast<Xcas_Text_Editor *>(wid)){ 8247 gen g=m->g(); 8248 if (figure_param_dialog(hp,true,tmin,tmax,tcur,tstep,paramname,g.is_symb_of_sommet(at_assume),tmp) ){ 8249 minimum(tmin); 8250 maximum(tmax); 8251 value(tcur); 8252 // tstep=tstep*(tmax-tmin)/100.; 8253 step(tstep,10*tstep); 8254 redraw(); 8255 label(paramname.c_str()); 8256 hp->set_value(position,tmp,true); 8257 // if (!f) 8258 hp->eval_below=true; 8259 } 8260 } 8261 } 8262 return 1; 8263 } 8264 return Fl_Counter::handle(event); 8265 } 8266 Gen_Value_Slider(int x,int y,int w,int h,int _pos,double m,double M,double mystep,const std::string & pname)8267 Gen_Value_Slider::Gen_Value_Slider(int x,int y,int w,int h,int _pos,double m,double M,double mystep,const std::string & pname):Fl_Counter(x,y,w,h),pos(_pos) { 8268 // type(FL_HOR_NICE_SLIDER); 8269 // type(FL_HOR_FILL_SLIDER); 8270 minimum(m); maximum(M); 8271 if (mystep>(M-m)/2 || mystep<0) 8272 mystep=(M-m)/2; 8273 step(mystep,10*mystep); 8274 // slider_size(0.05); 8275 callback(gen_value_slider_cb); 8276 paramname=pname; 8277 label(paramname.c_str()); 8278 align(FL_ALIGN_LEFT); 8279 } 8280 gen_value_slider_cb(Fl_Widget * widget,void *)8281 void gen_value_slider_cb(Fl_Widget * widget,void *){ 8282 if (Gen_Value_Slider * gvs=dynamic_cast<Gen_Value_Slider *>(widget)) 8283 gvs->adjust(true); 8284 } 8285 Xcas_xyztrange(const gen & g,GIAC_CONTEXT)8286 gen Xcas_xyztrange(const gen & g,GIAC_CONTEXT){ 8287 gen res=_xyztrange(g,contextptr); 8288 // Search if focus is inside a Graph2d group, if so adapt current cfg 8289 Fl_Widget * w = Fl::focus(); 8290 Graph2d3d * gr=0; 8291 Figure * fig = 0; 8292 for (;w;){ 8293 if ( (gr=dynamic_cast<Graph2d3d *>(w)) ) 8294 break; 8295 if ( (fig=dynamic_cast<Figure *>(w)) ){ 8296 gr = fig->geo; 8297 break; 8298 } 8299 w = w->parent(); 8300 } 8301 if (gr){ 8302 gr->window_xmin=global_window_xmin; 8303 gr->window_xmax=global_window_xmax; 8304 gr->window_ymin=global_window_ymin; 8305 gr->window_ymax=global_window_ymax; 8306 // gr->window_zmin=global_window_zmin; 8307 // gr->window_zmax=global_window_zmax; 8308 gr->show_axes=giac::show_axes(contextptr); 8309 } 8310 return res; 8311 } 8312 draw()8313 void Line_Type::draw(){ 8314 xcas_color(color()); 8315 fl_rectf(x(),y(),w(),h()); 8316 int color=(line_type_ & 0xffff); 8317 xcas_color(color); 8318 fl_rect(x(),y(),w(),h()); 8319 int width =(line_type_ & 0x00070000) >> 16; // 3 bits 8320 int epaisseur_point =(line_type_ & 0x00380000) >> 19; // 3 bits 8321 epaisseur_point += 2; 8322 int type_line =(line_type_ & 0x01c00000) >> 22; // 3 bits 8323 if (type_line>4) 8324 type_line=(type_line-4)<<8; 8325 int type_point =(line_type_ & 0x0e000000) >> 25; // 3 bits 8326 int labelpos =(line_type_ & 0x30000000) >> 28; // 2 bits 8327 bool fill_polygon =(line_type_ & 0x40000000) >> 30; 8328 bool hidden_name =(line_type_ & 0x80000000) >> 30; 8329 if (show_line_){ 8330 fl_line_style(type_line,width+1,0); 8331 xcas_color(color); 8332 fl_line(x(),y()+h()/2,x()+w(),y()+h()/2); 8333 fl_line_style(0); // back to default line style 8334 } 8335 if (show_pnt_){ 8336 xcas_color(color); 8337 fltk_point(x(),y(),w()/2,h()/2-2,epaisseur_point,type_point); 8338 } 8339 if (show_text_ && !hidden_name){ 8340 xcas_color(color); 8341 fl_font(FL_HELVETICA,14); 8342 int dx=2,dy=0; 8343 if (labelpos==1 || labelpos==2) 8344 dx=-14; 8345 if (labelpos==2 || labelpos==3) 8346 dy=+14; 8347 fl_draw("A",x()+w()/2+dx,y()+h()/2-2+dy); 8348 } 8349 if (show_poly_){ 8350 xcas_color(color); 8351 if (fill_polygon) 8352 fl_pie(x()+w()/2,y()+h()/2,w()/2,h()/2,0,360); 8353 else 8354 fl_arc(x()+w()/2,y()+h()/2,w()/2,h()/2,0,360); 8355 } 8356 } 8357 Line_Type(int x,int y,int w,int h,int lt)8358 Line_Type::Line_Type(int x,int y,int w,int h,int lt):Fl_Button(x,y,w,h),line_type_(lt),show_pnt_(false),show_line_(true),show_text_(false),show_poly_(false) { 8359 box(FL_UP_FRAME); 8360 color(FL_WHITE); 8361 } 8362 line_type(int l)8363 void Line_Type::line_type(int l){ 8364 line_type_=l; 8365 damage(FL_DAMAGE_ALL); 8366 } 8367 8368 8369 #ifndef NO_NAMESPACE_XCAS 8370 } // namespace giac 8371 #endif // ndef NO_NAMESPACE_XCAS 8372 8373 #endif // HAVE_LIBFLTK 8374