From 2d75f9dc74c9bb50df8d8d1eb2c0264b1842d2c1 Mon Sep 17 00:00:00 2001
From: Jean-Francois Remacle <jean-francois.remacle@uclouvain.be>
Date: Mon, 16 Aug 2004 17:52:59 +0000
Subject: [PATCH] *** empty log message ***

---
 Common/Options.cpp          |   6 +-
 Fltk/GUI.cpp                |  61 ++++-
 Graphics/Draw.h             |   1 +
 Graphics/Entity.cpp         |  24 +-
 Graphics/Geom.cpp           |  48 ++--
 Netgen/nglib_addon.cpp      |  12 +-
 Plugin/StructuralSolver.cpp | 483 ++++++++++++++++++++++++++++--------
 Plugin/StructuralSolver.h   |  24 +-
 8 files changed, 503 insertions(+), 156 deletions(-)

diff --git a/Common/Options.cpp b/Common/Options.cpp
index da00660582..777667fd8e 100644
--- a/Common/Options.cpp
+++ b/Common/Options.cpp
@@ -1,4 +1,4 @@
-// $Id: Options.cpp,v 1.178 2004-08-15 02:27:48 geuzaine Exp $
+// $Id: Options.cpp,v 1.179 2004-08-16 17:52:58 remacle Exp $
 //
 // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle
 //
@@ -3142,7 +3142,7 @@ double opt_geometry_point_type(OPT_ARGS_NUM)
   }
 #if defined(HAVE_FLTK)
   if(WID && (action & GMSH_GUI)) {
-    WID->geo_choice[0]->value(CTX.geom.point_type ? 1 : 0);
+    WID->geo_choice[0]->value(CTX.geom.point_type);
   }
 #endif
   return CTX.geom.point_type;
@@ -3177,7 +3177,7 @@ double opt_geometry_line_type(OPT_ARGS_NUM)
   }
 #if defined(HAVE_FLTK)
   if(WID && (action & GMSH_GUI)) {
-    WID->geo_choice[1]->value(CTX.geom.line_type ? 1 : 0);
+    WID->geo_choice[1]->value(CTX.geom.line_type);
   }
 #endif
   return CTX.geom.line_type;
diff --git a/Fltk/GUI.cpp b/Fltk/GUI.cpp
index b25fd67993..db0ba2ae0e 100644
--- a/Fltk/GUI.cpp
+++ b/Fltk/GUI.cpp
@@ -1,4 +1,4 @@
-// $Id: GUI.cpp,v 1.335 2004-08-15 15:25:45 geuzaine Exp $
+// $Id: GUI.cpp,v 1.336 2004-08-16 17:52:59 remacle Exp $
 //
 // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle
 //
@@ -335,12 +335,26 @@ static Fl_Menu_Item menu_point_display[] = {
   {0}
 };
 
+static Fl_Menu_Item menu_point_display_with_plugin[] = {
+  {"Color dot",   0, 0, 0},
+  {"3D sphere",   0, 0, 0},
+  {"Use Solver Plugin",   0, 0, 0},
+  {0}
+};
+
 static Fl_Menu_Item menu_line_display[] = {
   {"Color segment", 0, 0, 0},
   {"3D cylinder",   0, 0, 0},
   {0}
 };
 
+static Fl_Menu_Item menu_line_display_with_plugin[] = {
+  {"Color segment", 0, 0, 0},
+  {"3D cylinder",   0, 0, 0},
+  {"Use Solver Plugin",   0, 0, 0},
+  {0}
+};
+
 Fl_Menu_Item menu_font_names[] = {
   {"Times-Roman",           0, 0, (void*)FL_TIMES},
   {"Times-Bold",            0, 0, (void*)FL_TIMES_BOLD},
@@ -1774,7 +1788,15 @@ void GUI::create_option_window()
       o->hide();
 
       geo_choice[0] = new Fl_Choice(2 * WB, 2 * WB + 1 * BH, IW, BH, "Point display");
-      geo_choice[0]->menu(menu_point_display);
+      GMSH_Solve_Plugin *sp = GMSH_PluginManager::instance()->findSolverPlugin();   
+      if (sp)
+	{
+	  geo_choice[0]->menu(menu_point_display_with_plugin);
+	}
+      else
+	{
+	  geo_choice[0]->menu(menu_point_display);
+	}
       geo_choice[0]->align(FL_ALIGN_RIGHT);
 
       geo_value[3] = new Fl_Value_Input(2 * WB, 2 * WB + 2 * BH, IW, BH, "Point size");
@@ -1789,9 +1811,20 @@ void GUI::create_option_window()
       geo_value[5]->step(0.1);
       geo_value[5]->align(FL_ALIGN_RIGHT);
 
-      geo_choice[1] = new Fl_Choice(2 * WB, 2 * WB + 4 * BH, IW, BH, "Line display");
-      geo_choice[1]->menu(menu_line_display);
-      geo_choice[1]->align(FL_ALIGN_RIGHT);
+
+      {
+	geo_choice[1] = new Fl_Choice(2 * WB, 2 * WB + 4 * BH, IW, BH, "Line display");
+	GMSH_Solve_Plugin *sp = GMSH_PluginManager::instance()->findSolverPlugin();   
+	if (sp)
+	  {
+	    geo_choice[1]->menu(menu_line_display_with_plugin);
+	  }
+	else
+	  {
+	    geo_choice[1]->menu(menu_line_display);
+	  }
+	geo_choice[1]->align(FL_ALIGN_RIGHT);	
+      }
 
       geo_value[4] = new Fl_Value_Input(2 * WB, 2 * WB + 5 * BH, IW, BH, "Line width");
       geo_value[4]->minimum(0.1);
@@ -2155,14 +2188,16 @@ void GUI::create_option_window()
   {
     Fl_Tabs *o = new Fl_Tabs(WB, WB, width - 2 * WB, height - 2 * WB);
     {
-      Fl_Group *o = new Fl_Group(WB, WB + BH, width - 2 * WB, height - 2 * WB - BH, "General");
-
-      Fl_Box *text = new Fl_Box(FL_NO_BOX, 2 * WB, 3 * WB + 1 * BH, width - 4 * WB, 2 * BH,
-				"There are no global solver options available yet.\n\n"
-				"To define your own solver interface, you have to edit the option file.");
-      text->align(FL_ALIGN_LEFT | FL_ALIGN_TOP | FL_ALIGN_INSIDE | FL_ALIGN_WRAP);
-
-      o->end();
+      {
+	Fl_Group *o = new Fl_Group(WB, WB + BH, width - 2 * WB, height - 2 * WB - BH, "General");
+	
+	Fl_Box *text = new Fl_Box(FL_NO_BOX, 2 * WB, 3 * WB + 1 * BH, width - 4 * WB, 2 * BH,
+				  "There are no global solver options available yet.\n\n"
+				  "To define your own solver interface, you have to edit the option file.");
+	text->align(FL_ALIGN_LEFT | FL_ALIGN_TOP | FL_ALIGN_INSIDE | FL_ALIGN_WRAP);
+	
+	o->end();
+      }
     }
     o->end();
   }
diff --git a/Graphics/Draw.h b/Graphics/Draw.h
index 2a1d412596..4563f49407 100644
--- a/Graphics/Draw.h
+++ b/Graphics/Draw.h
@@ -66,6 +66,7 @@ void Draw_OnScreenMessages(void);
 void Draw_Scales(void);
 void Draw_Axes(double s);
 void Draw_SmallAxes(void);
+void Draw_Disk(double size, double rint, double x, double y, double z, int light);
 void Draw_Sphere(double size, double x, double y, double z, int light);
 void Draw_Cylinder(double width, double *x, double *y, double *z, int light);
 void Draw_Point(int type, double size, double *x, double *y, double *z, 
diff --git a/Graphics/Entity.cpp b/Graphics/Entity.cpp
index 585870a5e7..234f6ff711 100644
--- a/Graphics/Entity.cpp
+++ b/Graphics/Entity.cpp
@@ -1,4 +1,4 @@
-// $Id: Entity.cpp,v 1.45 2004-07-23 04:47:42 geuzaine Exp $
+// $Id: Entity.cpp,v 1.46 2004-08-16 17:52:59 remacle Exp $
 //
 // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle
 //
@@ -63,6 +63,28 @@ void Draw_Sphere(double size, double x, double y, double z, int light)
   glDisable(GL_LIGHTING);
 }
 
+void Draw_Disk(double size, double rint, double x, double y, double z, int light)
+{
+  if(light) glEnable(GL_LIGHTING);
+  static GLUquadricObj *qua;
+  static int first = 1, listnum;
+  double s = size;
+  if(first) {
+    first = 0;
+    qua = gluNewQuadric();
+    listnum = glGenLists(1);
+    glNewList(listnum, GL_COMPILE);
+    gluDisk(qua, rint, 1, 2*CTX.quadric_subdivisions, 2*CTX.quadric_subdivisions);
+    glEndList();
+  }
+  glPushMatrix();
+  glTranslated(x, y, z);
+  glScaled(s, s, s);
+  glCallList(listnum);
+  glPopMatrix();
+  glDisable(GL_LIGHTING);
+}
+
 void Draw_Cylinder(double width, double *x, double *y, double *z, int light)
 {
   if(light) glEnable(GL_LIGHTING);
diff --git a/Graphics/Geom.cpp b/Graphics/Geom.cpp
index 065c8d96b5..cfd99a5b67 100644
--- a/Graphics/Geom.cpp
+++ b/Graphics/Geom.cpp
@@ -1,4 +1,4 @@
-// $Id: Geom.cpp,v 1.70 2004-08-11 13:28:30 remacle Exp $
+// $Id: Geom.cpp,v 1.71 2004-08-16 17:52:59 remacle Exp $
 //
 // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle
 //
@@ -65,7 +65,7 @@ void Draw_Geo_Point(void *a, void *b)
   }
 
   if(CTX.geom.points) {
-    if(CTX.geom.point_type) {
+    if(CTX.geom.point_type == 1) {
       if(v->Frozen)
         Draw_Sphere(CTX.geom.point_sel_size, v->Pos.X, v->Pos.Y, v->Pos.Z, 
 		    CTX.geom.light);
@@ -73,17 +73,23 @@ void Draw_Geo_Point(void *a, void *b)
         Draw_Sphere(CTX.geom.point_size, v->Pos.X, v->Pos.Y, v->Pos.Z,
 		    CTX.geom.light);
     }
+    else if (CTX.geom.point_type == 2)
+      {
+	GMSH_Solve_Plugin *sp = GMSH_PluginManager::instance()->findSolverPlugin();
+	if (sp)
+	  {
+	    sp-> GL_enhancePoint (v);
+	  }
+	glBegin(GL_POINTS);
+	glVertex3d(v->Pos.X, v->Pos.Y, v->Pos.Z);
+	glEnd();
+      }
     else {
       glBegin(GL_POINTS);
       glVertex3d(v->Pos.X, v->Pos.Y, v->Pos.Z);
       glEnd();
     }
 
-    GMSH_Solve_Plugin *sp = GMSH_PluginManager::instance()->findSolverPlugin();
-    if (sp)
-      {
-	sp-> GL_enhancePoint (v);
-      }
   }
 
   if(CTX.geom.points_num) {
@@ -159,7 +165,7 @@ void Draw_Curve(void *a, void *b)
       List_Delete(temp);
     }
     else {
-      if(CTX.geom.line_type) {
+      if(CTX.geom.line_type>=1) {
         for(int i = 0; i < N - 1; i++) {
           v = InterpolateCurve(c, (double)i / (double)(N - 1), 0);
           dv = InterpolateCurve(c, (double)(i + 1) / (double)(N - 1), 0);
@@ -172,6 +178,20 @@ void Draw_Curve(void *a, void *b)
           Draw_Cylinder(c->ipar[3] ? CTX.geom.line_sel_width : CTX.geom.line_width,
 			x, y, z, CTX.geom.light);
         }
+	if(CTX.geom.line_type==2) 
+	  {
+	    GMSH_Solve_Plugin *sp = GMSH_PluginManager::instance()->findSolverPlugin();
+	    if (sp)
+	      {
+		int NN=(N>1)?N:1;
+		const double eps=0.e-2;
+		for(int i = 0; i < NN - 1; i++) {
+		  v = InterpolateCurve(c, (double)i / (double)(NN - 1)-eps, 0);
+		  dv = InterpolateCurve(c, (double)(i + 1) / (double)(NN - 1)+eps, 0);
+		  sp-> GL_enhanceLine (c->Num,&v,&dv);
+		}
+	      }
+	  }
       }
       else {
         glBegin(GL_LINE_STRIP);
@@ -182,18 +202,6 @@ void Draw_Curve(void *a, void *b)
         glEnd();
       }
     }
-
-    GMSH_Solve_Plugin *sp = GMSH_PluginManager::instance()->findSolverPlugin();
-    if (sp)
-      {
-        for(int i = 0; i < N - 1; i++) {
-          v = InterpolateCurve(c, (double)i / (double)(N - 1), 0);
-          dv = InterpolateCurve(c, (double)(i + 1) / (double)(N - 1), 0);
-	  sp-> GL_enhanceLine (c->Num,&v,&dv);
-	}
-      }
-
-
   }
 
   if(CTX.geom.lines_num) {
diff --git a/Netgen/nglib_addon.cpp b/Netgen/nglib_addon.cpp
index 8416c0af55..16339c8460 100644
--- a/Netgen/nglib_addon.cpp
+++ b/Netgen/nglib_addon.cpp
@@ -50,13 +50,13 @@ class mystreambuf: public streambuf
 // replaces the standard Ng_Init
 void NgAddOn_Init ()
 {
-  //mycout = &cout;
-  //myerr = &cerr;
-  //testout = new ofstream ("test.out");
+  mycout = &cout;
+  myerr = &cerr;
+  testout = new ofstream ("test.out");
 
-  mycout = new ostream(new mystreambuf());
-  myerr = new ostream(new mystreambuf());
-  testout = new ofstream ("/dev/null");
+  //mycout = new ostream(new mystreambuf());
+  //myerr = new ostream(new mystreambuf());
+  //testout = new ofstream ("/dev/null");
 }
 
 // generates volume mesh from surface mesh, without optimization
diff --git a/Plugin/StructuralSolver.cpp b/Plugin/StructuralSolver.cpp
index fc7ec12d82..7cc13db1d0 100644
--- a/Plugin/StructuralSolver.cpp
+++ b/Plugin/StructuralSolver.cpp
@@ -8,6 +8,8 @@
 #if defined(HAVE_FLTK)
 #include <FL/Fl.H>
 #include <FL/filename.H>
+#include <FL/Fl_PNG_Image.H>
+#include "GL/glu.h"
 #endif
 
 extern Mesh *THEM;
@@ -90,14 +92,57 @@ void Structural_BeamSection :: computeGeometricalProperties ()
   printf("%s %g %g %g\n",name.c_str(),area,xc,yc);
 }
 
-void Structural_BeamSection ::  GL_DrawBeam (double pinit[3], double dir[3])
+void Structural_Texture::setup ()
 {
+  
+  Fl_PNG_Image image(filename.c_str());
+
+  int width, height;
+  // allocate a texture name
+  glGenTextures( 1, &tag );
+  
+  // select our current texture
+  glBindTexture( GL_TEXTURE_2D, tag );
+   
+  // select modulate to mix texture with color for shading
+  //  glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
+  // when texture area is small, bilinear filter the closest mipmap
+  glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
+  		   GL_LINEAR_MIPMAP_NEAREST );
+  // when texture area is large, bilinear filter the first mipmap
+    glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+  // if wrap is true, the texture wraps over at the edges (repeat)
+  //       ... false, the texture ends at the edges (clamp)
+  bool wrap = false;
+  glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
+		   wrap ? GL_REPEAT : GL_CLAMP );
+  glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
+		    wrap ? GL_REPEAT : GL_CLAMP );
+
+  const uchar *data = image.array;
+  gluBuild2DMipmaps( GL_TEXTURE_2D, 
+		     3, 
+		     image.w(), 
+		     image.h(),
+		     GL_RGB, 
+		     GL_UNSIGNED_BYTE, 
+		     data );
+}
+
+void Structural_BeamSection ::  GL_DrawBeam (double pinit[3], double dir[3], const double dirz[3], Structural_Texture &texture)
+{
+
+  if (texture.tag==0)
+    {
+      texture.setup();
+    }
+
 #ifdef HAVE_FLTK
 
 
   double X[3] = {dir[0],dir[1],dir[2]};
+  double Z[3] = {dirz[0],dirz[1],dirz[2]};
   double Y[3];
-  double Z[3] = {0,0,1};
   double nn = norme(X);
   prodve(X,Z,Y);
   double transl[3] = {pinit[0]-xc,pinit[1]-yc,pinit[2]};
@@ -122,8 +167,14 @@ void Structural_BeamSection ::  GL_DrawBeam (double pinit[3], double dir[3])
 
   List_T *surfaces = Tree2List (m.Surfaces);
   List_T *curves = Tree2List (m.Curves);
+  List_T *points = Tree2List (m.Points);
+  glEnable(GL_POLYGON_OFFSET_FILL);
   if(CTX.geom.light) glEnable(GL_LIGHTING);
   glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+
+  glEnable( GL_TEXTURE_2D );  
+  glBindTexture( GL_TEXTURE_2D, texture.tag );
+
   for (int i=0;i<List_Nbr(surfaces);++i)
     {
       Surface *s;
@@ -136,19 +187,15 @@ void Structural_BeamSection ::  GL_DrawBeam (double pinit[3], double dir[3])
 	  List_Read(triangles,j,&simp);	
 	  glBegin(GL_TRIANGLES);
 	  glNormal3d ( -X[0],-X[1],-X[2] );
-	  glVertex3d ( simp->V[0]->Pos.X,simp->V[0]->Pos.Y,simp->V[0]->Pos.Z);
-	  glNormal3d ( -X[0],-X[1],-X[2] );
-	  glVertex3d ( simp->V[1]->Pos.X,simp->V[1]->Pos.Y,simp->V[1]->Pos.Z);
-	  glNormal3d ( -X[0],-X[1],-X[2] );
-	  glVertex3d ( simp->V[2]->Pos.X,simp->V[2]->Pos.Y,simp->V[2]->Pos.Z);
+	  glTexCoord2d(0,0);glVertex3d ( simp->V[0]->Pos.X,simp->V[0]->Pos.Y,simp->V[0]->Pos.Z);
+	  glTexCoord2d(0,1);glVertex3d ( simp->V[1]->Pos.X,simp->V[1]->Pos.Y,simp->V[1]->Pos.Z);
+	  glTexCoord2d(1,1);glVertex3d ( simp->V[2]->Pos.X,simp->V[2]->Pos.Y,simp->V[2]->Pos.Z);
 	  glEnd();
 	  glBegin(GL_TRIANGLES);
 	  glNormal3d ( X[0],X[1],X[2] );
-	  glVertex3d ( simp->V[0]->Pos.X+dir[0],simp->V[0]->Pos.Y+dir[1],simp->V[0]->Pos.Z+dir[2]);
-	  glNormal3d ( X[0],X[1],X[2] );
-	  glVertex3d ( simp->V[1]->Pos.X+dir[0],simp->V[1]->Pos.Y+dir[1],simp->V[1]->Pos.Z+dir[2]);
-	  glNormal3d ( X[0],X[1],X[2] );
-	  glVertex3d ( simp->V[2]->Pos.X+dir[0],simp->V[2]->Pos.Y+dir[1],simp->V[2]->Pos.Z+dir[2]);
+	  glTexCoord2d(0,0);glVertex3d ( simp->V[0]->Pos.X+dir[0],simp->V[0]->Pos.Y+dir[1],simp->V[0]->Pos.Z+dir[2]);
+	  glTexCoord2d(0,1);glVertex3d ( simp->V[1]->Pos.X+dir[0],simp->V[1]->Pos.Y+dir[1],simp->V[1]->Pos.Z+dir[2]);
+	  glTexCoord2d(1,1);glVertex3d ( simp->V[2]->Pos.X+dir[0],simp->V[2]->Pos.Y+dir[1],simp->V[2]->Pos.Z+dir[2]);
 	  glEnd();
 	}
       List_Delete(triangles);
@@ -167,22 +214,23 @@ void Structural_BeamSection ::  GL_DrawBeam (double pinit[3], double dir[3])
 			     simp->V[0]->Pos.Y-simp->V[1]->Pos.Y,
 			     simp->V[0]->Pos.Z-simp->V[1]->Pos.Z};
 	  double dir2[3];
+	  double L1 = sqrt(dir1[0]*dir1[0]+dir1[1]*dir1[1]+dir1[2]*dir1[2]);
+	  double L = sqrt(dir[0]*dir[0]+dir[1]*dir[1]+dir[2]*dir[2]);
+
 	  norme(dir1);
 	  prodve(dir1,X,dir2);
-
 	  glBegin(GL_POLYGON);
 	  glNormal3dv (dir2); 
-	  glVertex3d ( simp->V[0]->Pos.X,simp->V[0]->Pos.Y,simp->V[0]->Pos.Z);
-	  glNormal3dv (dir2); 
-	  glVertex3d ( simp->V[1]->Pos.X,simp->V[1]->Pos.Y,simp->V[1]->Pos.Z);
-	  glNormal3dv (dir2); 
-	  glVertex3d ( simp->V[1]->Pos.X+dir[0],simp->V[1]->Pos.Y+dir[1],simp->V[1]->Pos.Z+dir[2]);
-	  glNormal3dv (dir2); 
-	  glVertex3d ( simp->V[0]->Pos.X+dir[0],simp->V[0]->Pos.Y+dir[1],simp->V[0]->Pos.Z+dir[2]);
+	  glTexCoord2d(0,0);glVertex3d ( simp->V[0]->Pos.X,simp->V[0]->Pos.Y,simp->V[0]->Pos.Z);
+	  glTexCoord2d(0,L1/L);glVertex3d ( simp->V[1]->Pos.X,simp->V[1]->Pos.Y,simp->V[1]->Pos.Z);
+	  glTexCoord2d(1,L1/L);glVertex3d ( simp->V[1]->Pos.X+dir[0],simp->V[1]->Pos.Y+dir[1],simp->V[1]->Pos.Z+dir[2]);
+	  glTexCoord2d(1,0);glVertex3d ( simp->V[0]->Pos.X+dir[0],simp->V[0]->Pos.Y+dir[1],simp->V[0]->Pos.Z+dir[2]);
 	  glEnd();
+
 	}
       List_Delete(lines);
     }
+  List_Delete(points);  
   List_Delete(curves);  
   List_Delete(surfaces);  
 
@@ -195,12 +243,15 @@ void Structural_BeamSection ::  GL_DrawBeam (double pinit[3], double dir[3])
       Projette ( vert, invrot);
     }
   List_Delete (vertices);
+  glDisable(GL_POLYGON_OFFSET_FILL);
+  glDisable(GL_LIGHTING);
+  glDisable( GL_TEXTURE_2D );  
+  glColor4ubv((GLubyte *) & CTX.color.geom.line);
 
 #endif
 }
 
 
-
 void StructuralSolver :: RegisterBeamSections ()
 {
 #if defined(HAVE_FLTK)
@@ -221,6 +272,17 @@ void StructuralSolver :: RegisterBeamSections ()
 	  new Structural_BeamSection ( homeplugins, std::string(name) );
 	beam_sections.push_back ( section );
       }
+      if(!strcmp(ext, "png")) {
+	char temp[256];
+	sprintf(temp, "%s/%s", homeplugins,name);
+	//	GLuint texture_id = RegisterTexture ( temp );
+	std::string aaa (name);
+	aaa.erase(aaa.find("."));
+	Structural_Texture tt;
+	tt.filename=std::string(temp);
+	tt.tag=0;
+	textures[aaa] = tt;
+      }
     }
   }
   for(int i = 0; i < nbFiles; i++)
@@ -292,15 +354,26 @@ StructuralSolver :: StructuralSolver ()
 
 StructuralSolver :: ~StructuralSolver ()
 {
-  std::list<struct Structural_BeamSection* > :: iterator it  = beam_sections.begin();
-  std::list<struct Structural_BeamSection* > :: iterator ite = beam_sections.end();
-
-  for (;it!=ite;++it)
-    {
-      delete *it;
-    }
+  {
+    std::list<struct Structural_BeamSection* > :: iterator it  = beam_sections.begin();
+    std::list<struct Structural_BeamSection* > :: iterator ite = beam_sections.end();
+    
+    for (;it!=ite;++it)
+      {
+	delete *it;
+      }
+  }
 #ifdef HAVE_FLTK 
   if(_window)delete _window;;
+  {
+    std::map<std::string, struct Structural_Texture > :: iterator it  = textures.begin();
+    std::map<std::string, struct Structural_Texture > :: iterator ite = textures.end();      
+    for (;it!=ite;++it)
+      {
+	GLuint texture = it->second.tag;
+	glDeleteTextures( 1, &texture );
+      }
+  }
 #endif
 }
 
@@ -319,15 +392,14 @@ Structural_BeamSection * StructuralSolver :: GetBeamSection (const std::string &
 
 #define BEAM_SECTION_ 3
 #define BEAM_MATERIAL_ 4
-#define POINT_X_ 0
-#define POINT_Y_ 1
-#define POINT_Z_ 2
-#define X_A_ 0
-#define X_B_ 1
-#define Y_A_ 2
-#define Y_B_ 3
-#define Z_A_ 4
-#define Z_B_ 5
+#define POINT_ALONG_ 0
+#define POINT_ACROSS_ 1
+#define POINT_AROUND_ 2
+#define ANGLE_ 3
+#define ALONG_ 0
+#define ACROSS_ 1
+#define AROUND_ 2
+
 
 void StructuralSolver ::popupPropertiesForPhysicalEntity (int dim)
 { 
@@ -361,39 +433,39 @@ void StructuralSolver ::popupPropertiesForPhysicalEntity (int dim)
       g[0] = new Fl_Group(WB, WB + BH, width - 2 * WB, height - 3 * WB - 2 * BH, "Physical Point");
       
       static Fl_Menu_Item _type[] = {
-	{"Displacement fixed", 0, 0, 0},
-	{"Load fixed", 0, 0, 0},
+	{"Displacement fixed (mm)", 0, 0, 0},
+	{"Load fixed (kN)", 0, 0, 0},
 	{0}
       };
-      _choice[POINT_X_] = new Fl_Choice(2 * WB, 2 * WB + 1 * BH, IW, BH, "X-component");
-      _choice[POINT_X_]->menu(_type);
-      _choice[POINT_X_]->align(FL_ALIGN_RIGHT);
-      
-      _value[X_A_] = new Fl_Value_Input(2 * WB, 2 * WB + 2 * BH, IW/2, BH,       "");
-      _value[X_A_]->align(FL_ALIGN_RIGHT);
-      _value[X_B_] = new Fl_Value_Input(2 * WB+IW/2, 2 * WB + 2 * BH, IW/2, BH, "VAL = A * X + B");
-      _value[X_B_]->align(FL_ALIGN_RIGHT);
-      
-      _choice[POINT_Y_] = new Fl_Choice(2 * WB, 2 * WB + 3 * BH, IW, BH, "Y-component");
-      _choice[POINT_Y_]->menu(_type);
-      _choice[POINT_Y_]->align(FL_ALIGN_RIGHT);
+
+      _value[ANGLE_] = new Fl_Value_Input(2 * WB, 2 * WB + 1 * BH, IW, BH, "Angle of Rotation");
+      _value[ANGLE_]->value(90);
+      _value[ANGLE_]->align(FL_ALIGN_RIGHT);
+
+      _choice[POINT_ALONG_] = new Fl_Choice(2 * WB, 2 * WB + 2 * BH, IW, BH, "Along the Local Axis");
+      _choice[POINT_ALONG_]->menu(_type);
+      _choice[POINT_ALONG_]->align(FL_ALIGN_RIGHT);
       
+      _value[ALONG_] = new Fl_Value_Input(2 * WB, 2 * WB + 3 * BH, IW, BH,"Value");
+      _value[ALONG_]->value(0.0);
+      _value[ALONG_]->align(FL_ALIGN_RIGHT);
       
-      _value[Y_A_] = new Fl_Value_Input(2 * WB, 2 * WB + 4 * BH, IW/2, BH,       "");
-      _value[Y_A_]->align(FL_ALIGN_RIGHT);
-      _value[Y_B_] = new Fl_Value_Input(2 * WB+IW/2, 2 * WB + 4 * BH, IW/2, BH, "VAL = A * X + B");
-      _value[Y_B_]->align(FL_ALIGN_RIGHT);
+      _choice[POINT_ACROSS_] = new Fl_Choice(2 * WB, 2 * WB + 4 * BH, IW, BH, "Across the Local Axis");
+      _choice[POINT_ACROSS_]->menu(_type);
+      _choice[POINT_ACROSS_]->align(FL_ALIGN_RIGHT);
       
-      _choice[POINT_Z_] = new Fl_Choice(2 * WB, 2 * WB + 5 * BH, IW, BH, "Z-component (moment)");
-      _choice[POINT_Z_]->menu(_type);
-      _choice[POINT_Z_]->align(FL_ALIGN_RIGHT);
+      _value[ACROSS_] = new Fl_Value_Input(2 * WB, 2 * WB + 5 * BH, IW, BH,"Value");
+      _value[ACROSS_]->value(0.0);
+      _value[ACROSS_]->align(FL_ALIGN_RIGHT);
       
-      _value[Z_A_] = new Fl_Value_Input(2 * WB, 2 * WB + 6 * BH, IW/2, BH,       "");
-      _value[Z_A_]->align(FL_ALIGN_RIGHT);
-      _value[Z_B_] = new Fl_Value_Input(2 * WB+IW/2, 2 * WB + 6 * BH, IW/2, BH, "VAL = A * X + B");
-      _value[Z_B_]->align(FL_ALIGN_RIGHT);
       
+      _choice[POINT_AROUND_] = new Fl_Choice(2 * WB, 2 * WB + 6 * BH, IW, BH, "Around Z axis");
+      _choice[POINT_AROUND_]->menu(_type);
+      _choice[POINT_AROUND_]->align(FL_ALIGN_RIGHT);
       
+      _value[AROUND_] = new Fl_Value_Input(2 * WB, 2 * WB + 7 * BH, IW, BH,       "");
+      _value[AROUND_]->value(0.0);
+      _value[AROUND_]->align(FL_ALIGN_RIGHT);
       g[0]->end();
     }
     // 2: Physical Line
@@ -419,6 +491,7 @@ void StructuralSolver ::popupPropertiesForPhysicalEntity (int dim)
 	  }
 	_choice[BEAM_MATERIAL_]->align(FL_ALIGN_RIGHT);
       }
+
       _value[6] = new Fl_Value_Input(2 * WB, 2 * WB + 3 * BH, IW/2, BH,       "");
       _value[6]->value(0.0);
       _value[6]->align(FL_ALIGN_RIGHT);
@@ -431,6 +504,22 @@ void StructuralSolver ::popupPropertiesForPhysicalEntity (int dim)
       _value[9] = new Fl_Value_Input(2 * WB+IW/2, 2 * WB + 4 * BH, IW/2, BH, "Y-Load");
       _value[9]->value(0.0);
       _value[9]->align(FL_ALIGN_RIGHT);
+      _value[10] = new Fl_Value_Input(2 * WB, 2 * WB + 5 * BH, IW/2, BH,       "");
+      _value[10]->value(0.0);
+      _value[10]->align(FL_ALIGN_RIGHT);
+      _value[11] = new Fl_Value_Input(2 * WB+IW/2, 2 * WB + 5 * BH, IW/2, BH, "Z-Load");
+      _value[11]->value(0.0);
+      _value[11]->align(FL_ALIGN_RIGHT);
+      
+      _value[12] = new Fl_Value_Input(2 * WB, 2 * WB + 6 * BH, IW/3, BH,       "");
+      _value[12]->value(0.0);
+      _value[12]->align(FL_ALIGN_RIGHT);
+      _value[13] = new Fl_Value_Input(2 * WB+IW/3, 2 * WB + 6 * BH, IW/3, BH,       "");
+      _value[13]->value(0.0);
+      _value[13]->align(FL_ALIGN_RIGHT);
+      _value[14] = new Fl_Value_Input(2 * WB+2*IW/3, 2 * WB + 6 * BH, IW/3, BH, "Y-Direction");
+      _value[14]->value(1.0);
+      _value[14]->align(FL_ALIGN_RIGHT);
       
       g[1]->end();
     }
@@ -442,9 +531,12 @@ void StructuralSolver ::popupPropertiesForPhysicalEntity (int dim)
 void StructuralSolver :: addPhysicalLine (int id)
 { 
 #ifdef HAVE_FLTK 
-  PhysicalLineInfo info;
+  PhysicalLineInfo info;  
   info.section = std::string(_choice[BEAM_SECTION_] ->mvalue()->text);  
-  info.material= std::string(_choice[BEAM_MATERIAL_]->mvalue()->text); 
+  info.material= std::string(_choice[BEAM_MATERIAL_]->mvalue()->text);
+  info.dirz[0]  = _value[12]->value();
+  info.dirz[1]  = _value[13]->value();
+  info.dirz[2]  = _value[14]->value();
   lines[id] = info;
 #endif  
 }
@@ -454,15 +546,14 @@ void StructuralSolver :: addPhysicalPoint (int id)
 #ifdef HAVE_FLTK 
   PhysicalPointInfo info;
 
-  info.disp[0] = _choice[POINT_X_] ->value();
-  info.disp[1] = _choice[POINT_Y_] ->value();
-  info.disp[2] = _choice[POINT_Z_] ->value();
-  info.val[0] = _value[X_A_]->value();
-  info.val[1] = _value[X_B_]->value();
-  info.val[2] = _value[Y_A_]->value();
-  info.val[3] = _value[Y_B_]->value();
-  info.val[4] = _value[Z_A_]->value();
-  info.val[5] = _value[Z_B_]->value();
+  info.angle = _value[ANGLE_]->value();
+
+  info.disp[0] = _choice[POINT_ALONG_] ->value();
+  info.disp[1] = _choice[POINT_ACROSS_] ->value();
+  info.disp[2] = _choice[POINT_AROUND_] ->value();
+  info.val[0] = _value[ALONG_]->value();
+  info.val[1] = _value[ACROSS_]->value();
+  info.val[2] = _value[AROUND_]->value();
 
   if (info.disp[0] == 0)
     MAX_FORCE = (MAX_FORCE>info.val[0])?MAX_FORCE:info.val[0];
@@ -487,7 +578,8 @@ void StructuralSolver :: writeSolverFile ( const char *geom_file ) const
       {
 	const PhysicalLineInfo &i = (*it).second;
 	int id = (*it).first;
-	fprintf(f,"BEAM PHYSICAL %d SECTION %s MATERIAL %s LOADS %g %g %g %g\n",id,i.section.c_str(),i.material.c_str(),i.fx1,i.fy1,i.fx2,i.fy2);
+	fprintf(f,"BEAM PHYSICAL %d SECTION %s MATERIAL %s LOADS %g %g %g %g %g %g %g %g %g \n",
+		id,i.section.c_str(),i.material.c_str(),i.fx1,i.fy1,i.fx2,i.fy2,i.fz1,i.fz2,i.dirz[0],i.dirz[1],i.dirz[2]);
       }
   }
   {
@@ -497,7 +589,7 @@ void StructuralSolver :: writeSolverFile ( const char *geom_file ) const
       {
 	const PhysicalPointInfo &i = (*it).second;
 	int id = (*it).first;
-	fprintf(f,"NODE PHYSICAL %d DEPLX %d %g %g DEPLY %d %g %g DEPLZ %d %g %g\n",id,i.disp[0],i.val[0],i.val[1],i.disp[1],i.val[2],i.val[3],i.disp[2],i.val[4],i.val[5]);
+	fprintf(f,"NODE %d %g %d %g %d %g %d %g \n",id,i.angle,i.disp[0],i.val[0],i.disp[1],i.val[1],i.disp[2],i.val[2]);
       }
   }
   fclose(f);  
@@ -518,7 +610,8 @@ void StructuralSolver :: readSolverFile ( const char *geom_file )
 	{
 	  int id;
 	  PhysicalLineInfo info;
-	  sscanf(line,"%s %s %d %s %s %s %s %s %lf %lf %lf %lf\n",a1,a2,&id,a3,a4,a5,a6,a7,&info.fx1,&info.fy1,&info.fx2,&info.fy2);
+	  sscanf(line,"%s %s %d %s %s %s %s %s %lf %lf %lf %lf %lf %lf %lf %lf %lf \n",
+		 a1,a2,&id,a3,a4,a5,a6,a7,&info.fx1,&info.fy1,&info.fx2,&info.fy2,&info.fz1,&info.fz2,&info.dirz[0],&info.dirz[1],&info.dirz[2]);
 	  info.material = std::string(a6);
 	  info.section  = std::string(a4);
 	  lines[id] = info;
@@ -527,24 +620,177 @@ void StructuralSolver :: readSolverFile ( const char *geom_file )
 	{
 	  int id;
 	  PhysicalPointInfo info;
-	  sscanf(line,"%s %s %d %s %d %lf %lf %s %d %lf %lf %s %d %lf %lf\n",a1,a2,&id,
-		 a3,&info.disp[0],&info.val[0],&info.val[1],
-		 a4,&info.disp[1],&info.val[2],&info.val[3],
-		 a5,&info.disp[2],&info.val[4],&info.val[5]);
+	  sscanf(line,"%s %d %lf %d %lf %d %lf %d %lf \n",a1,&id,
+		 &info.angle,
+		 &info.disp[0],&info.val[0],
+		 &info.disp[1],&info.val[1],
+		 &info.disp[2],&info.val[2]);
 	  points[id] = info;
-	  if (info.disp[0] == 0)
-	    MAX_FORCE = (MAX_FORCE>info.val[0])?MAX_FORCE:info.val[0];
-	  if (info.disp[1] == 0)
-	    MAX_FORCE = (MAX_FORCE>info.val[1])?MAX_FORCE:info.val[1];
-	  if (info.disp[2] == 0)
-	    MAX_FORCE = (MAX_FORCE>info.val[2])?MAX_FORCE:info.val[2];
-
+	  if (info.disp[0] == 1)
+	    MAX_FORCE = (MAX_FORCE>fabs(info.val[0]))?MAX_FORCE:fabs(info.val[0]);
+	  if (info.disp[1] == 1)
+	    MAX_FORCE = (MAX_FORCE>fabs(info.val[1]))?MAX_FORCE:fabs(info.val[1]);
 	}
       if (feof(f) )break;
     }
+  printf("max force = %g\n",MAX_FORCE);
   fclose(f);
 }
 
+
+void Draw_Kinematic_Constraint ( const int type [3], 
+				 const double size, 
+				 const double pos[3], 
+				 double dir[3])
+{
+  // presently, it's only 2D , 1st and second component are for dir and dir2 
+  // and third one is for rotation around z
+
+  double dir2[3];
+  double ez[3]={0,0,1};
+  prodve(dir,ez,dir2);
+
+  double size_feature = size*0.5;
+  double width_ground = size*0.25;
+
+  if(!type[0] && !type[1] && !type[2]) // clamped
+    {
+      size_feature = 0.0;
+      width_ground = 0.5*size;
+    }
+
+  if(type[0] && type[1] && type[2]) // free
+    {
+      return;
+    }
+
+  if(CTX.geom.light) glEnable(GL_LIGHTING);
+
+  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+  glEnable(GL_POLYGON_OFFSET_FILL);
+  glColor3f    (0.8,0.8,0.8);
+  
+  glBegin(GL_QUADS);
+  glVertex3d ( pos[0] - size_feature * dir [0] - size * 0.5 * dir2 [0],
+	       pos[1] - size_feature * dir [1] - size * 0.5 * dir2 [1],
+	       pos[2] - size_feature * dir [2] - size * 0.5 * dir2 [2]);
+  glVertex3d ( pos[0] - size_feature * dir [0] + size * 0.5 * dir2 [0],
+	       pos[1] - size_feature * dir [1] + size * 0.5 * dir2 [1],
+	       pos[2] - size_feature * dir [2] + size * 0.5 * dir2 [2]);
+  glVertex3d ( pos[0] - size_feature * dir [0] - width_ground * dir[0] + size * 0.5 * dir2 [0],
+	       pos[1] - size_feature * dir [1] - width_ground * dir[1] + size * 0.5 * dir2 [1],
+	       pos[2] - size_feature * dir [2] - width_ground * dir[2] + size * 0.5 * dir2 [2]);
+  glVertex3d ( pos[0] - size_feature * dir [0] - width_ground * dir[0] - size * 0.5 * dir2 [0],
+	       pos[1] - size_feature * dir [1] - width_ground * dir[1] - size * 0.5 * dir2 [1],
+	       pos[2] - size_feature * dir [2] - width_ground * dir[2] - size * 0.5 * dir2 [2]);
+  glEnd();
+  
+  
+  glColor3f(0,0,0);
+
+  glLineWidth(2);
+
+  if (!type[0])
+    {
+      glBegin(GL_LINES);
+      glVertex3d ( pos[0] - size_feature * dir [0] - size * 0.5 * dir2 [0],
+		   pos[1] - size_feature * dir [1] - size * 0.5 * dir2 [1],
+		   pos[2] - size_feature * dir [2] - size * 0.5 * dir2 [2]);
+      glVertex3d ( pos[0] - size_feature * dir [0] + size * 0.5 * dir2 [0],
+		   pos[1] - size_feature * dir [1] + size * 0.5 * dir2 [1],
+		   pos[2] - size_feature * dir [2] + size * 0.5 * dir2 [2]);
+      glEnd();
+    }
+  
+  if(type[0] || type[1] || type[2]) // everything except clamped
+    {
+      double radius_circle = size_feature * 0.5;
+      double radius_circle2 = size_feature * 0.5;
+
+      if (!type[1]) radius_circle = 0;
+      if (!type[2]) radius_circle2 = 0;
+
+      if (!type[0])
+	{
+	  glBegin(GL_LINES);
+	  
+	  glVertex3d ( pos[0] - (size_feature-radius_circle) * dir [0] - size * 0.5 * dir2 [0],
+		       pos[1] - (size_feature-radius_circle) * dir [1] - size * 0.5 * dir2 [1],
+		       pos[2] - (size_feature-radius_circle) * dir [2] - size * 0.5 * dir2 [2]);
+	  glVertex3d ( pos[0],pos[1],pos[2] );
+	  glEnd();
+	  
+	  glBegin(GL_LINES);
+	  glVertex3d ( pos[0] - (size_feature-radius_circle) * dir [0] + size * 0.5 * dir2 [0],
+		       pos[1] - (size_feature-radius_circle) * dir [1] + size * 0.5 * dir2 [1],
+		       pos[2] - (size_feature-radius_circle) * dir [2] + size * 0.5 * dir2 [2]);
+	  glVertex3d ( pos[0],pos[1],pos[2] );
+	  glEnd();
+	}
+
+      if (!type[0]){
+	glColor4f(1,1,1,1);
+	Draw_Disk (radius_circle2*.5*.8, 0.00, pos[0], pos[1], pos[2]+0.01*radius_circle2,CTX.geom.light); 
+	glColor4f(0,0,0,1);
+	Draw_Disk (radius_circle2*.5, 0.8, pos[0], pos[1], pos[2],CTX.geom.light); 
+      }
+
+      if (!type[1] || !type[0]){
+	glBegin(GL_LINES);
+	glVertex3d ( pos[0] - (size_feature-radius_circle) * dir [0] - size * 0.5 * dir2 [0],
+		     pos[1] - (size_feature-radius_circle) * dir [1] - size * 0.5 * dir2 [1],
+		     pos[2] - (size_feature-radius_circle) * dir [2] - size * 0.5 * dir2 [2]);
+	
+	glVertex3d ( pos[0] - (size_feature-radius_circle) * dir [0] + size * 0.5 * dir2 [0],
+		     pos[1] - (size_feature-radius_circle) * dir [1] + size * 0.5 * dir2 [1],
+		     pos[2] - (size_feature-radius_circle) * dir [2] + size * 0.5 * dir2 [2]);
+	glEnd();	
+	glColor4f(1,1,1,1);
+	Draw_Disk (radius_circle*.5 * .8, 0.0, 
+		   pos[0] - (size_feature-radius_circle) * dir [0] - size * 0.5 * dir2 [0] - radius_circle * 0.5 * dir[0] + radius_circle * 0.5 * dir2[0],
+		   pos[1] - (size_feature-radius_circle) * dir [1] - size * 0.5 * dir2 [1] - radius_circle * 0.5 * dir[1] + radius_circle * 0.5 * dir2[1],
+		   pos[2] - (size_feature-radius_circle) * dir [2] - size * 0.5 * dir2 [2] - radius_circle * 0.5 * dir[2] + radius_circle * 0.5 * dir2[2],
+		   CTX.geom.light); 
+	Draw_Disk (radius_circle*.5 * .8, 0.0, 
+		   pos[0] - (size_feature-radius_circle) * dir [0] + size * 0.5 * dir2 [0] - radius_circle * 0.5 * dir[0] - radius_circle * 0.5 * dir2[0],
+		   pos[1] - (size_feature-radius_circle) * dir [1] + size * 0.5 * dir2 [1] - radius_circle * 0.5 * dir[1] - radius_circle * 0.5 * dir2[1],
+		   pos[2] - (size_feature-radius_circle) * dir [2] + size * 0.5 * dir2 [2] - radius_circle * 0.5 * dir[2] - radius_circle * 0.5 * dir2[2],
+		   CTX.geom.light); 
+	Draw_Disk (radius_circle*.5 * .8, 0., 
+		   pos[0] - (size_feature-radius_circle) * dir [0] - radius_circle * 0.5 * dir[0],
+		   pos[1] - (size_feature-radius_circle) * dir [1] - radius_circle * 0.5 * dir[1],
+		   pos[2] - (size_feature-radius_circle) * dir [2] - radius_circle * 0.5 * dir[2],
+		   CTX.geom.light); 
+	glColor4f(0,0,0,1);
+	Draw_Disk (radius_circle*.5, 0.8, 
+		   pos[0] - (size_feature-radius_circle) * dir [0] - size * 0.5 * dir2 [0] - radius_circle * 0.5 * dir[0] + radius_circle * 0.5 * dir2[0],
+		   pos[1] - (size_feature-radius_circle) * dir [1] - size * 0.5 * dir2 [1] - radius_circle * 0.5 * dir[1] + radius_circle * 0.5 * dir2[1],
+		   pos[2] - (size_feature-radius_circle) * dir [2] - size * 0.5 * dir2 [2] - radius_circle * 0.5 * dir[2] + radius_circle * 0.5 * dir2[2],
+		   CTX.geom.light); 
+	Draw_Disk (radius_circle*.5, 0.8, 
+		   pos[0] - (size_feature-radius_circle) * dir [0] + size * 0.5 * dir2 [0] - radius_circle * 0.5 * dir[0] - radius_circle * 0.5 * dir2[0],
+		   pos[1] - (size_feature-radius_circle) * dir [1] + size * 0.5 * dir2 [1] - radius_circle * 0.5 * dir[1] - radius_circle * 0.5 * dir2[1],
+		   pos[2] - (size_feature-radius_circle) * dir [2] + size * 0.5 * dir2 [2] - radius_circle * 0.5 * dir[2] - radius_circle * 0.5 * dir2[2],
+		   CTX.geom.light); 
+	Draw_Disk (radius_circle*.5, 0.8, 
+		   pos[0] - (size_feature-radius_circle) * dir [0] - radius_circle * 0.5 * dir[0],
+		   pos[1] - (size_feature-radius_circle) * dir [1] - radius_circle * 0.5 * dir[1],
+		   pos[2] - (size_feature-radius_circle) * dir [2] - radius_circle * 0.5 * dir[2],
+		   CTX.geom.light); 
+      }
+
+    }
+
+
+  glDisable(GL_POLYGON_OFFSET_FILL);
+  glDisable(GL_LIGHTING);
+  glColor4ubv((GLubyte *) & CTX.color.geom.point);
+
+  
+
+}
+
+
 bool StructuralSolver :: GL_enhancePoint ( Vertex *v) 
 {
 #ifdef HAVE_FLTK  
@@ -557,26 +803,48 @@ bool StructuralSolver :: GL_enhancePoint ( Vertex *v)
 	if(List_Search(p->Entities, &v->Num, fcmp_absint)) { 
 	  std::map<int,struct PhysicalPointInfo>::const_iterator it = points.find(p->Num);
 	  if (it !=points.end())
-	    {	      
-	      for (int icomp=0;icomp<3;++icomp)
+	    {	
+    
+	      double angle = 3.1415926*it->second.angle/180;
+	      
+	      double size = 0.05*(CTX.max[0]-CTX.min[0]);
+	      double dir[3] = {cos(angle),sin(angle),0};
+	      double dir2[3];
+	      double Z[3]={0,0,1};
+	      prodve(dir,Z,dir2);
+	      norme(dir);
+	      double pos[3] = {v->Pos.X,v->Pos.Y,v->Pos.Z};
+	      Draw_Kinematic_Constraint (it->second.disp,size,pos,dir);
+
+	      double dv[3] = {0,0,0};		  
+	      
+	      if (it->second.disp[0] == 1)
+		{
+		  dv[0] += dir[0] * it->second.val[0];
+		  dv[1] += dir[1] * it->second.val[0];
+		}
+	      if (it->second.disp[1] == 1)
+		{
+		  dv[0] += dir2[0] * it->second.val[1];
+		  dv[1] += dir2[1] * it->second.val[1];
+		}
+
+	      const double offset = 0.5 * CTX.gl_fontsize * CTX.pixel_equiv_x;
+	      const double l = sqrt (dv[0]*dv[0]+dv[1]*dv[1]);
+	      const double kk = (CTX.max[0]-CTX.min[0])*.1*l / (MAX_FORCE);
+	      if (l != 0.0)
 		{
-		  double dv[3] = {0,0,0};
-		  if (it->second.disp[icomp] == 1)
-		    {
-		      double offset = 0.5 * CTX.gl_fontsize * CTX.pixel_equiv_x;
-		      
-		      dv[icomp] =  (CTX.max[0]-CTX.min[0])*it->second.val[1+2*icomp]*.2 / (MAX_FORCE *CTX.s[icomp]);
-
-		      Draw_Vector (CTX.vector_type,  0, CTX.arrow_rel_head_radius, 
-				   CTX.arrow_rel_stem_length, CTX.arrow_rel_stem_radius,
-				   v->Pos.X, v->Pos.Y, v->Pos.Z,
-				   dv[0], dv[1], dv[2], NULL, CTX.geom.light);
-		      sprintf(Num, "%g kN", it->second.val[1]);
-		      glRasterPos3d((v->Pos.X + dv[0])+ offset / CTX.s[0],
-				    (v->Pos.Y + dv[1])+ offset / CTX.s[1],
-				    (v->Pos.Z + dv[2])+ offset / CTX.s[2]);
-		      Draw_String(Num);
-		    } 
+		  glColor4ubv((GLubyte *) & CTX.color.text);
+		  Draw_Vector (CTX.vector_type,  0, 0.5*CTX.arrow_rel_head_radius, 
+			       CTX.arrow_rel_stem_length, 0.5*CTX.arrow_rel_stem_radius,
+			       v->Pos.X-dv[0]*kk, v->Pos.Y-dv[1]*kk, v->Pos.Z-dv[2]*kk,
+			       dv[0]*kk, dv[1]*kk, dv[2]*kk, NULL, CTX.geom.light);
+		  sprintf(Num, "%g kN", l);
+		  glRasterPos3d((v->Pos.X + dv[0])+ offset / CTX.s[0],
+				(v->Pos.Y + dv[1])+ offset / CTX.s[1],
+				(v->Pos.Z + dv[2])+ offset / CTX.s[2]);
+		  Draw_String(Num);
+		  glColor4ubv((GLubyte *) & CTX.color.geom.line);
 		}
 	      return true;
 	    }
@@ -590,6 +858,7 @@ bool StructuralSolver :: GL_enhancePoint ( Vertex *v)
 bool StructuralSolver :: GL_enhanceLine ( int CurveId, Vertex *v1, Vertex *v2) 
 {
 #ifdef HAVE_FLTK  
+  //  return true;
   PhysicalGroup *p;
   for(int i = 0; i < List_Nbr(THEM->PhysicalGroups); i++) 
     { 
@@ -605,7 +874,7 @@ bool StructuralSolver :: GL_enhanceLine ( int CurveId, Vertex *v1, Vertex *v2)
 	      Structural_BeamSection *section =  GetBeamSection (it->second.section);
 	      if (section)
 		{
-		  section -> GL_DrawBeam (pinit,dir);
+		  section -> GL_DrawBeam (pinit,dir,it->second.dirz,textures[it->second.material]);
 		  return true;
 		}
 	    }
diff --git a/Plugin/StructuralSolver.h b/Plugin/StructuralSolver.h
index 4ed9823107..d00362c24f 100644
--- a/Plugin/StructuralSolver.h
+++ b/Plugin/StructuralSolver.h
@@ -54,6 +54,7 @@
 #include <FL/Fl_Color_Chooser.H>
 #include <FL/fl_ask.H>
 #include <FL/Fl_Tooltip.H>
+#include <GL/glu.h>
 #endif
 
 extern "C"
@@ -61,6 +62,13 @@ extern "C"
   GMSH_Plugin *GMSH_RegisterStructuralSolverPlugin();
 }
 
+struct Structural_Texture
+{
+  std::string filename;
+  GLuint  tag ;
+  void setup();
+};
+
 struct Structural_BeamSection
 {
   Mesh m;
@@ -69,7 +77,7 @@ struct Structural_BeamSection
   Structural_BeamSection ( const char *direct, std::string _name );
   ~Structural_BeamSection();
   void computeGeometricalProperties();
-  void GL_DrawBeam (double pinit[3], double dir[3]);
+  void GL_DrawBeam (double pinit[3], double dir[3], const double Y[3], Structural_Texture &texture);
 };
 
 struct Structural_Material
@@ -79,17 +87,20 @@ struct Structural_Material
 };
 
 
+
 struct PhysicalPointInfo 
 {
+  double angle;
   int disp[3];
-  double val[6];
+  double val[3];
 };
 
 struct PhysicalLineInfo 
 {
-  PhysicalLineInfo() : fx1(0),fx2(0),fy1(0),fy2(0){}
+  PhysicalLineInfo() : fx1(0),fx2(0),fy1(0),fy2(0),fz1(0),fz2(0){dirz[0]=0;dirz[1]=0;dirz[2]=1;}
   std::string material, section;
-  double fx1,fx2,fy1,fy2;
+  double fx1,fx2,fy1,fy2,fz1,fz2;
+  double dirz[3];
 };
 
 
@@ -99,8 +110,9 @@ class StructuralSolver : public GMSH_Solve_Plugin
   std::list < struct Structural_Material  > materials;
   std::map <int, struct PhysicalPointInfo  > points;
   std::map <int, struct PhysicalLineInfo   > lines;
-  void RegisterBeamSections     ();
-  void RegisterMaterials        ();
+  std::map <std::string , struct Structural_Texture   > textures;
+  void    RegisterBeamSections     ();
+  void    RegisterMaterials        ();
   void addPhysicalPoint         (int id);
   void addPhysicalLine          (int id);
 #ifdef HAVE_FLTK 
-- 
GitLab