diff --git a/Common/DefaultOptions.h b/Common/DefaultOptions.h index f495a48caf1b829f4531f61254b390ea7ece9076..d3493b4216abe419fb676ad4d35235bb980c7763 100644 --- a/Common/DefaultOptions.h +++ b/Common/DefaultOptions.h @@ -1015,6 +1015,8 @@ StringXNumber ViewOptions_Number[] = { { F|O, "PositionY" , opt_view_position1 , 50. , "Vertical position (in pixels) of the upper left corner of the scale or 2D graph" }, + { F|O, "RaisedScalarView" , opt_view_raised_scalar_view , 0. , + "Index of the scalar view raised by the displacement field" }, { F, "RaiseX" , opt_view_raise0 , 0. , "Elevation of the view along X-axis (in model coordinates)" }, { F, "RaiseY" , opt_view_raise1 , 0. , @@ -1046,7 +1048,7 @@ StringXNumber ViewOptions_Number[] = { "Type of graph (1=3D, 2=2D-space, 3=2D-time)" }, { F|O, "VectorType" , opt_view_vector_type , DRAW_POST_ARROW3D , - "Vector display type (1=segment, 2=arrow, 3=pyramid, 4=3D arrow, 5=displacement)" }, + "Vector display type (1=segment, 2=arrow, 3=pyramid, 4=3D arrow, 5=displacement, 6=raised scalar view)" }, { F, "Visible" , opt_view_visible , 1. , "Is the view visible?" }, diff --git a/Common/Options.cpp b/Common/Options.cpp index 777667fd8e4325a0bf49cdbb83cb815f29ae1dc0..f5a3c1e20a92cc22acf4fd9fd5157789589068c2 100644 --- a/Common/Options.cpp +++ b/Common/Options.cpp @@ -1,4 +1,4 @@ -// $Id: Options.cpp,v 1.179 2004-08-16 17:52:58 remacle Exp $ +// $Id: Options.cpp,v 1.180 2004-09-01 20:23:49 geuzaine Exp $ // // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle // @@ -4929,19 +4929,19 @@ double opt_view_tensor_type(OPT_ARGS_NUM) v->TensorType = (int)val; v->Changed = 1; } -#if defined(HAVE_FLTK) - if(_gui_action_valid(action, num)) { - switch (v->TensorType) { - case DRAW_POST_EIGENVECTORS: - WID->view_choice[4]->value(1); - break; - case DRAW_POST_VONMISES: - default: - WID->view_choice[4]->value(0); - break; - } - } -#endif +// #if defined(HAVE_FLTK) +// if(_gui_action_valid(action, num)) { +// switch (v->TensorType) { +// case DRAW_POST_EIGENVECTORS: +// WID->view_choice[4]->value(1); +// break; +// case DRAW_POST_VONMISES: +// default: +// WID->view_choice[4]->value(0); +// break; +// } +// } +// #endif return v->TensorType; } @@ -5066,6 +5066,20 @@ double opt_view_alpha_channel(OPT_ARGS_NUM) return v->AlphaChannel; } +double opt_view_raised_scalar_view(OPT_ARGS_NUM) +{ + GET_VIEW(0.); + if(action & GMSH_SET) { + v->RaisedScalarView = (int)val; + v->Changed = 1; + } +#if defined(HAVE_FLTK) + if(_gui_action_valid(action, num)) + WID->view_value[64]->value(v->RaisedScalarView); +#endif + return v->RaisedScalarView; +} + double opt_print_format(OPT_ARGS_NUM) { if(action & GMSH_SET) diff --git a/Common/Options.h b/Common/Options.h index fa26a6296a61a8e9c5c09b4e165200d575113370..c77df8a3df81f0006a37377219da808502440aff 100644 --- a/Common/Options.h +++ b/Common/Options.h @@ -447,6 +447,7 @@ double opt_view_visible(OPT_ARGS_NUM); double opt_view_intervals_type(OPT_ARGS_NUM); double opt_view_saturate_values(OPT_ARGS_NUM); double opt_view_alpha_channel(OPT_ARGS_NUM); +double opt_view_raised_scalar_view(OPT_ARGS_NUM); double opt_view_type(OPT_ARGS_NUM); double opt_view_grid(OPT_ARGS_NUM); double opt_view_position0(OPT_ARGS_NUM); diff --git a/Common/Views.cpp b/Common/Views.cpp index aeb981331148d7b5f28c1d5e6c946097e210bce7..5343d98448badfd95f324a05304502e4fe68fe84 100644 --- a/Common/Views.cpp +++ b/Common/Views.cpp @@ -1,4 +1,4 @@ -// $Id: Views.cpp,v 1.126 2004-07-16 18:02:19 geuzaine Exp $ +// $Id: Views.cpp,v 1.127 2004-09-01 20:23:49 geuzaine Exp $ // // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle // @@ -650,6 +650,7 @@ void CopyViewOptions(Post_View * src, Post_View * dest) dest->PointType = src->PointType; dest->LineType = src->LineType; dest->Grid = src->Grid; + dest->RaisedScalarView = src->RaisedScalarView; ColorTable_Copy(&src->CT); ColorTable_Paste(&dest->CT); } diff --git a/Common/Views.h b/Common/Views.h index c503a26c7da3548d07b532f9d3e8579201329a2c..659d51e6f77211e0a1c3f235e9eaefdae7cd6955 100644 --- a/Common/Views.h +++ b/Common/Views.h @@ -83,10 +83,15 @@ class Post_View{ int Boundary, Grid, PointType, LineType; double PointSize, LineWidth; GmshColorTable CT; + int RaisedScalarView; // dynamic double (*GVFI) (double min, double max, int nb, int index); int (*GIFV) (double min, double max, int nb, double value); + int ElementForDisplacement; + Post_View *ViewForDisplacement; + double MinForDisplacement, MaxForDisplacement; + // smooth the view void smooth(); // smooth normals @@ -114,11 +119,12 @@ class Post_View{ #define DRAW_POST_NUMERIC 4 // VectorType -#define DRAW_POST_SEGMENT 1 -#define DRAW_POST_ARROW 2 -#define DRAW_POST_PYRAMID 3 -#define DRAW_POST_ARROW3D 4 -#define DRAW_POST_DISPLACEMENT 5 +#define DRAW_POST_SEGMENT 1 +#define DRAW_POST_ARROW 2 +#define DRAW_POST_PYRAMID 3 +#define DRAW_POST_ARROW3D 4 +#define DRAW_POST_DISPLACEMENT 5 +#define DRAW_POST_DISPLACEMENT_EXTERNAL 6 // ArrowLocation #define DRAW_POST_LOCATE_COG 1 diff --git a/Fltk/Callbacks.cpp b/Fltk/Callbacks.cpp index 0db71a88de991855e4c65f20c81c76893bfa0eb7..1a636869cf20bbe613556d53a699eeeefe965650 100644 --- a/Fltk/Callbacks.cpp +++ b/Fltk/Callbacks.cpp @@ -1,4 +1,4 @@ -// $Id: Callbacks.cpp,v 1.265 2004-08-15 02:27:48 geuzaine Exp $ +// $Id: Callbacks.cpp,v 1.266 2004-09-01 20:23:49 geuzaine Exp $ // // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle // @@ -3367,7 +3367,7 @@ void view_options_ok_cb(CALLBACK_ARGS) double line_type = opt_view_line_type(current, GMSH_GET, 0); double vector_type = opt_view_vector_type(current, GMSH_GET, 0); double arrow_location = opt_view_arrow_location(current, GMSH_GET, 0); - double tensor_type = opt_view_tensor_type(current, GMSH_GET, 0); + //double tensor_type = opt_view_tensor_type(current, GMSH_GET, 0); double range_type = opt_view_range_type(current, GMSH_GET, 0); double grid = opt_view_grid(current, GMSH_GET, 0); double boundary = opt_view_boundary(current, GMSH_GET, 0); @@ -3406,6 +3406,7 @@ void view_options_ok_cb(CALLBACK_ARGS) double timestep = opt_view_timestep(current, GMSH_GET, 0); double arrow_size = opt_view_arrow_size(current, GMSH_GET, 0); double displacement_factor = opt_view_displacement_factor(current, GMSH_GET, 0); + double raised_scalar_view = opt_view_raised_scalar_view(current, GMSH_GET, 0); double point_size = opt_view_point_size(current, GMSH_GET, 0); double line_width = opt_view_line_width(current, GMSH_GET, 0); double explode = opt_view_explode(current, GMSH_GET, 0); @@ -3490,6 +3491,9 @@ void view_options_ok_cb(CALLBACK_ARGS) case 4: val = DRAW_POST_DISPLACEMENT; break; + case 5: + val = DRAW_POST_DISPLACEMENT_EXTERNAL; + break; default: // 3 val = DRAW_POST_ARROW3D; break; @@ -3508,16 +3512,16 @@ void view_options_ok_cb(CALLBACK_ARGS) if(force || (val != arrow_location)) opt_view_arrow_location(i, GMSH_SET, val); - switch (WID->view_choice[4]->value()) { - case 0: - val = DRAW_POST_VONMISES; - break; - default: - val = DRAW_POST_EIGENVECTORS; - break; - } - if(force || (val != tensor_type)) - opt_view_tensor_type(i, GMSH_SET, val); +// switch (WID->view_choice[4]->value()) { +// case 0: +// val = DRAW_POST_VONMISES; +// break; +// default: +// val = DRAW_POST_EIGENVECTORS; +// break; +// } +// if(force || (val != tensor_type)) +// opt_view_tensor_type(i, GMSH_SET, val); switch (WID->view_choice[7]->value()) { case 0: @@ -3678,6 +3682,10 @@ void view_options_ok_cb(CALLBACK_ARGS) if(force || (val != displacement_factor)) opt_view_displacement_factor(i, GMSH_SET, val); + val = WID->view_value[64]->value(); + if(force || (val != raised_scalar_view)) + opt_view_raised_scalar_view(i, GMSH_SET, val); + val = WID->view_value[61]->value(); if(force || (val != point_size)) opt_view_point_size(i, GMSH_SET, val); diff --git a/Fltk/GUI.cpp b/Fltk/GUI.cpp index db0ba2ae0e965cd1c98272e51adae2dfb89ce7c7..8bcbd34dc7458ccf74f20611a6cec73722da9643 100644 --- a/Fltk/GUI.cpp +++ b/Fltk/GUI.cpp @@ -1,4 +1,4 @@ -// $Id: GUI.cpp,v 1.336 2004-08-16 17:52:59 remacle Exp $ +// $Id: GUI.cpp,v 1.337 2004-09-01 20:23:50 geuzaine Exp $ // // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle // @@ -456,6 +456,7 @@ int GUI::global_shortcuts(int event) if(g_window && g_window->shown()) g_window->show(); if(opt_window && opt_window->shown()) opt_window->show(); if(vis_window && vis_window->shown()) vis_window->show(); + if(clip_window && clip_window->shown()) clip_window->show(); if(stat_window && stat_window->shown()) stat_window->show(); if(msg_window && msg_window->shown()) msg_window->show(); if(m_window && m_window->shown()) m_window->show(); @@ -2558,6 +2559,7 @@ void GUI::create_option_window() {"Pyramid", 0, 0, 0}, {"3D arrow", 0, 0, 0}, {"Displacement", 0, 0, 0}, + {"Raised scalar view", 0, 0, 0}, {0} }; view_choice[2] = new Fl_Choice(2 * WB, 2 * WB + 6 * BH, IW, BH, "Vector display"); @@ -2575,23 +2577,29 @@ void GUI::create_option_window() view_value[63] = new Fl_Value_Input(2 * WB, 2 * WB + 8 * BH, IW, BH, "Displacement factor"); view_value[63]->align(FL_ALIGN_RIGHT); + view_value[64] = new Fl_Value_Input(2 * WB, 2 * WB + 9 * BH, IW, BH, "Raised scalar view number"); + view_value[64]->minimum(0); + view_value[64]->maximum(10); + view_value[64]->step(1); + view_value[64]->align(FL_ALIGN_RIGHT); + static Fl_Menu_Item menu_vecloc[] = { {"Cell centered", 0, 0, 0}, {"Vertex centered", 0, 0, 0}, {0} }; - view_choice[3] = new Fl_Choice(2 * WB, 2 * WB + 9 * BH, IW, BH, "Arrow location"); + view_choice[3] = new Fl_Choice(2 * WB, 2 * WB + 10 * BH, IW, BH, "Arrow location"); view_choice[3]->menu(menu_vecloc); view_choice[3]->align(FL_ALIGN_RIGHT); - static Fl_Menu_Item menu_tensor[] = { - {"Von-Mises", 0, 0, 0}, + //static Fl_Menu_Item menu_tensor[] = { + //{"Von-Mises", 0, 0, 0}, //{"Eigenvectors", 0, 0, 0}, //not implemented yet - {0} - }; - view_choice[4] = new Fl_Choice(2 * WB, 2 * WB + 10 * BH, IW, BH, "Tensor display"); - view_choice[4]->menu(menu_tensor); - view_choice[4]->align(FL_ALIGN_RIGHT); + //{0} + //}; + //view_choice[4] = new Fl_Choice(2 * WB, 2 * WB + 10 * BH, IW, BH, "Tensor display"); + //view_choice[4]->menu(menu_tensor); + //view_choice[4]->align(FL_ALIGN_RIGHT); view_vector->end(); } @@ -2780,8 +2788,9 @@ void GUI::update_view_window(int num) opt_view_vector_type(num, GMSH_GUI, 0); opt_view_arrow_size(num, GMSH_GUI, 0); opt_view_displacement_factor(num, GMSH_GUI, 0); + opt_view_raised_scalar_view(num, GMSH_GUI, 0); opt_view_arrow_location(num, GMSH_GUI, 0); - opt_view_tensor_type(num, GMSH_GUI, 0); + //opt_view_tensor_type(num, GMSH_GUI, 0); view_push_butt[0]->callback(view_arrow_param_cb, (void*)num); view_colorbar_window->update(v->Name, v->Min, v->Max, &v->CT, &v->Changed); diff --git a/Graphics/Draw.h b/Graphics/Draw.h index 4563f494077e719ece83cd8acf935d57b94b99f8..100d36377c4cd87f908433f8b83357ec66fc365c 100644 --- a/Graphics/Draw.h +++ b/Graphics/Draw.h @@ -100,73 +100,73 @@ void Draw_PlaneInBoundingBox(double xmin, double ymin, double zmin, void Draw_ScalarPoint(Post_View *View, int preproNormals, double ValMin, double ValMax, double *X, double *Y, double *Z, double *V); -void Draw_VectorPoint(Post_View *View, +void Draw_VectorPoint(Post_View *View, int preproNormals, double ValMin, double ValMax, double *X, double *Y, double *Z, double *V); -void Draw_TensorPoint(Post_View *View, +void Draw_TensorPoint(Post_View *View, int preproNormals, double ValMin, double ValMax, double *X, double *Y, double *Z, double *V); void Draw_ScalarLine(Post_View *View, int preproNormals, double ValMin, double ValMax, double *X, double *Y, double *Z, double *V); -void Draw_VectorLine(Post_View *View, +void Draw_VectorLine(Post_View *View, int preproNormals, double ValMin, double ValMax, double *X, double *Y, double *Z, double *V); -void Draw_TensorLine(Post_View *View, +void Draw_TensorLine(Post_View *View, int preproNormals, double ValMin, double ValMax, double *X, double *Y, double *Z, double *V); void Draw_ScalarTriangle(Post_View *View, int preproNormals, double ValMin, double ValMax, double *X, double *Y, double *Z, double *V); -void Draw_VectorTriangle(Post_View *View, +void Draw_VectorTriangle(Post_View *View, int preproNormals, double ValMin, double ValMax, double *X, double *Y, double *Z, double *V); -void Draw_TensorTriangle(Post_View *View, +void Draw_TensorTriangle(Post_View *View, int preproNormals, double ValMin, double ValMax, double *X, double *Y, double *Z, double *V); void Draw_ScalarTetrahedron(Post_View *View, int preproNormals, double ValMin, double ValMax, double *X, double *Y, double *Z, double *V); -void Draw_VectorTetrahedron(Post_View *View, +void Draw_VectorTetrahedron(Post_View *View, int preproNormals, double ValMin, double ValMax, double *X, double *Y, double *Z, double *V); -void Draw_TensorTetrahedron(Post_View *View, +void Draw_TensorTetrahedron(Post_View *View, int preproNormals, double ValMin, double ValMax, double *X, double *Y, double *Z, double *V); void Draw_ScalarQuadrangle(Post_View *View, int preproNormals, double ValMin, double ValMax, double *X, double *Y, double *Z, double *V); -void Draw_VectorQuadrangle(Post_View *View, +void Draw_VectorQuadrangle(Post_View *View, int preproNormals, double ValMin, double ValMax, double *X, double *Y, double *Z, double *V); -void Draw_TensorQuadrangle(Post_View *View, +void Draw_TensorQuadrangle(Post_View *View, int preproNormals, double ValMin, double ValMax, double *X, double *Y, double *Z, double *V); void Draw_ScalarHexahedron(Post_View *View, int preproNormals, double ValMin, double ValMax, double *X, double *Y, double *Z, double *V); -void Draw_VectorHexahedron(Post_View *View, +void Draw_VectorHexahedron(Post_View *View, int preproNormals, double ValMin, double ValMax, double *X, double *Y, double *Z, double *V); -void Draw_TensorHexahedron(Post_View *View, +void Draw_TensorHexahedron(Post_View *View, int preproNormals, double ValMin, double ValMax, double *X, double *Y, double *Z, double *V); void Draw_ScalarPrism(Post_View *View, int preproNormals, double ValMin, double ValMax, double *X, double *Y, double *Z, double *V); -void Draw_VectorPrism(Post_View *View, +void Draw_VectorPrism(Post_View *View, int preproNormals, double ValMin, double ValMax, double *X, double *Y, double *Z, double *V); -void Draw_TensorPrism(Post_View *View, +void Draw_TensorPrism(Post_View *View, int preproNormals, double ValMin, double ValMax, double *X, double *Y, double *Z, double *V); void Draw_ScalarPyramid(Post_View *View, int preproNormals, double ValMin, double ValMax, double *X, double *Y, double *Z, double *V); -void Draw_VectorPyramid(Post_View *View, +void Draw_VectorPyramid(Post_View *View, int preproNormals, double ValMin, double ValMax, double *X, double *Y, double *Z, double *V); -void Draw_TensorPyramid(Post_View *View, +void Draw_TensorPyramid(Post_View *View, int preproNormals, double ValMin, double ValMax, double *X, double *Y, double *Z, double *V); diff --git a/Graphics/Post.cpp b/Graphics/Post.cpp index 5156b028292931a82211c81bb2b48ca8913d0238..c2beef5f80ee67487f6a4d09fddbec7f1824bf62 100644 --- a/Graphics/Post.cpp +++ b/Graphics/Post.cpp @@ -1,4 +1,4 @@ -// $Id: Post.cpp,v 1.76 2004-08-28 00:48:37 geuzaine Exp $ +// $Id: Post.cpp,v 1.77 2004-09-01 20:23:50 geuzaine Exp $ // // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle // @@ -231,19 +231,23 @@ int compareEye8Nodes(const void *a, const void *b) // Draw_Post -void Draw_ScalarList(Post_View * v, double ValMin, double ValMax, - List_T * list, int nbelm, int nbnod, int smoothnormals, - void (*draw) (Post_View *, int, double, double, double *, - double *, double *, double *)) +void Draw_List(Post_View * v, double ValMin, double ValMax, + List_T * list, int nbelm, int nbnod, + void (*draw) (Post_View *, int, double, double, double *, + double *, double *, double *)) { int i, nb; double X[8], Y[8], Z[8]; - if(nbelm && v->DrawScalars) { + if(nbelm) { nb = List_Nbr(list) / nbelm; - if(smoothnormals && v->Light && v->SmoothNormals && v->Changed) { - v->reset_normals(); + + v->ViewForDisplacement = + (Post_View*)List_Pointer_Test(CTX.post.list, v->RaisedScalarView); + + if(v->Light && v->SmoothNormals && v->Changed) { Msg(DEBUG, "Preprocessing of normals in View[%d]", v->Index); + v->ElementForDisplacement = 0; for(i = 0; i < List_Nbr(list); i += nb) { Get_Coords(v->Explode, v->Offset, nbnod, (double *)List_Pointer_Fast(list, i), @@ -251,57 +255,19 @@ void Draw_ScalarList(Post_View * v, double ValMin, double ValMax, (double *)List_Pointer_Fast(list, i + 2 * nbnod), X, Y, Z); draw(v, 1, ValMin, ValMax, X, Y, Z, (double *)List_Pointer_Fast(list, i + 3 * nbnod)); + v->ElementForDisplacement++; } } - for(i = 0; i < List_Nbr(list); i += nb) { - Get_Coords(v->Explode, v->Offset, nbnod, - (double *)List_Pointer_Fast(list, i), - (double *)List_Pointer_Fast(list, i + nbnod), - (double *)List_Pointer_Fast(list, i + 2 * nbnod), X, Y, Z); - draw(v, 0, ValMin, ValMax, X, Y, Z, - (double *)List_Pointer_Fast(list, i + 3 * nbnod)); - } - } -} - -void Draw_VectorList(Post_View * v, double ValMin, double ValMax, - List_T * list, int nbelm, int nbnod, - void (*draw) (Post_View *, double, double, - double *, double *, double *, double *)) -{ - int i, nb; - double X[8], Y[8], Z[8]; - - if(nbelm && v->DrawVectors) { - nb = List_Nbr(list) / nbelm; - for(i = 0; i < List_Nbr(list); i += nb) { - Get_Coords(v->Explode, v->Offset, nbnod, - (double *)List_Pointer_Fast(list, i), - (double *)List_Pointer_Fast(list, i + nbnod), - (double *)List_Pointer_Fast(list, i + 2 * nbnod), X, Y, Z); - draw(v, ValMin, ValMax, X, Y, Z, - (double *)List_Pointer_Fast(list, i + 3 * nbnod)); - } - } -} -void Draw_TensorList(Post_View * v, double ValMin, double ValMax, - List_T * list, int nbelm, int nbnod, - void (*draw) (Post_View *, double, double, - double *, double *, double *, double *)) -{ - int i, nb; - double X[8], Y[8], Z[8]; - - if(nbelm && v->DrawTensors) { - nb = List_Nbr(list) / nbelm; + v->ElementForDisplacement = 0; for(i = 0; i < List_Nbr(list); i += nb) { Get_Coords(v->Explode, v->Offset, nbnod, (double *)List_Pointer_Fast(list, i), (double *)List_Pointer_Fast(list, i + nbnod), (double *)List_Pointer_Fast(list, i + 2 * nbnod), X, Y, Z); - draw(v, ValMin, ValMax, X, Y, Z, + draw(v, 0, ValMin, ValMax, X, Y, Z, (double *)List_Pointer_Fast(list, i + 3 * nbnod)); + v->ElementForDisplacement++; } } } @@ -406,6 +372,8 @@ void Draw_Post(void) ValMax = v->TimeStepMax[v->TimeStep]; break; } + v->MinForDisplacement = ValMin; + v->MaxForDisplacement = ValMax; switch (v->ScaleType) { case DRAW_POST_LINEAR: @@ -422,6 +390,9 @@ void Draw_Post(void) break; } + if(v->Light && v->SmoothNormals && v->Changed) + v->reset_normals(); + // initialize alpha blending for transparency if(CTX.alpha && ColorTable_IsAlpha(&v->CT)){ if(CTX.fake_transparency){ @@ -472,17 +443,22 @@ void Draw_Post(void) } } } - + if(v->DrawPoints) { - if(v->Type == DRAW_POST_3D) - Draw_ScalarList(v, ValMin, ValMax, v->SP, v->NbSP, 1, 0, Draw_ScalarPoint); - Draw_VectorList(v, ValMin, ValMax, v->VP, v->NbVP, 1, Draw_VectorPoint); - Draw_TensorList(v, ValMin, ValMax, v->TP, v->NbTP, 1, Draw_TensorPoint); + if(v->Type == DRAW_POST_3D && v->DrawScalars) + Draw_List(v, ValMin, ValMax, v->SP, v->NbSP, 1, Draw_ScalarPoint); + if(v->DrawVectors) + Draw_List(v, ValMin, ValMax, v->VP, v->NbVP, 1, Draw_VectorPoint); + if(v->DrawTensors) + Draw_List(v, ValMin, ValMax, v->TP, v->NbTP, 1, Draw_TensorPoint); } if(v->DrawLines) { - Draw_ScalarList(v, ValMin, ValMax, v->SL, v->NbSL, 2, 0, Draw_ScalarLine); - Draw_VectorList(v, ValMin, ValMax, v->VL, v->NbVL, 2, Draw_VectorLine); - Draw_TensorList(v, ValMin, ValMax, v->TL, v->NbTL, 2, Draw_TensorLine); + if(v->DrawScalars) + Draw_List(v, ValMin, ValMax, v->SL, v->NbSL, 2, Draw_ScalarLine); + if(v->DrawVectors) + Draw_List(v, ValMin, ValMax, v->VL, v->NbVL, 2, Draw_VectorLine); + if(v->DrawTensors) + Draw_List(v, ValMin, ValMax, v->TL, v->NbTL, 2, Draw_TensorLine); } for(int pass = 0; pass < 2; pass++){ @@ -517,40 +493,52 @@ void Draw_Post(void) pass_0: if(v->DrawTriangles) { - if(!skip_2d) - Draw_ScalarList(v, ValMin, ValMax, v->ST, v->NbST, 3, 1, Draw_ScalarTriangle); - Draw_VectorList(v, ValMin, ValMax, v->VT, v->NbVT, 3, Draw_VectorTriangle); - Draw_TensorList(v, ValMin, ValMax, v->TT, v->NbTT, 3, Draw_TensorTriangle); + if(!skip_2d && v->DrawScalars) + Draw_List(v, ValMin, ValMax, v->ST, v->NbST, 3, Draw_ScalarTriangle); + if(v->DrawVectors) + Draw_List(v, ValMin, ValMax, v->VT, v->NbVT, 3, Draw_VectorTriangle); + if(v->DrawTensors) + Draw_List(v, ValMin, ValMax, v->TT, v->NbTT, 3, Draw_TensorTriangle); } if(v->DrawQuadrangles) { - if(!skip_2d) - Draw_ScalarList(v, ValMin, ValMax, v->SQ, v->NbSQ, 4, 1, Draw_ScalarQuadrangle); - Draw_VectorList(v, ValMin, ValMax, v->VQ, v->NbVQ, 4, Draw_VectorQuadrangle); - Draw_TensorList(v, ValMin, ValMax, v->TQ, v->NbTQ, 4, Draw_TensorQuadrangle); + if(!skip_2d && v->DrawScalars) + Draw_List(v, ValMin, ValMax, v->SQ, v->NbSQ, 4, Draw_ScalarQuadrangle); + if(v->DrawVectors) + Draw_List(v, ValMin, ValMax, v->VQ, v->NbVQ, 4, Draw_VectorQuadrangle); + if(v->DrawTensors) + Draw_List(v, ValMin, ValMax, v->TQ, v->NbTQ, 4, Draw_TensorQuadrangle); } if(v->DrawTetrahedra) { - if(!skip_3d) - Draw_ScalarList(v, ValMin, ValMax, v->SS, v->NbSS, 4, 1, Draw_ScalarTetrahedron); - Draw_VectorList(v, ValMin, ValMax, v->VS, v->NbVS, 4, Draw_VectorTetrahedron); - Draw_TensorList(v, ValMin, ValMax, v->TS, v->NbTS, 4, Draw_TensorTetrahedron); + if(!skip_3d && v->DrawScalars) + Draw_List(v, ValMin, ValMax, v->SS, v->NbSS, 4, Draw_ScalarTetrahedron); + if(v->DrawVectors) + Draw_List(v, ValMin, ValMax, v->VS, v->NbVS, 4, Draw_VectorTetrahedron); + if(v->DrawTensors) + Draw_List(v, ValMin, ValMax, v->TS, v->NbTS, 4, Draw_TensorTetrahedron); } if(v->DrawHexahedra) { - if(!skip_3d) - Draw_ScalarList(v, ValMin, ValMax, v->SH, v->NbSH, 8, 1, Draw_ScalarHexahedron); - Draw_VectorList(v, ValMin, ValMax, v->VH, v->NbVH, 8, Draw_VectorHexahedron); - Draw_TensorList(v, ValMin, ValMax, v->TH, v->NbTH, 8, Draw_TensorHexahedron); + if(!skip_3d && v->DrawScalars) + Draw_List(v, ValMin, ValMax, v->SH, v->NbSH, 8, Draw_ScalarHexahedron); + if(v->DrawVectors) + Draw_List(v, ValMin, ValMax, v->VH, v->NbVH, 8, Draw_VectorHexahedron); + if(v->DrawTensors) + Draw_List(v, ValMin, ValMax, v->TH, v->NbTH, 8, Draw_TensorHexahedron); } if(v->DrawPrisms) { - if(!skip_3d) - Draw_ScalarList(v, ValMin, ValMax, v->SI, v->NbSI, 6, 1, Draw_ScalarPrism); - Draw_VectorList(v, ValMin, ValMax, v->VI, v->NbVI, 6, Draw_VectorPrism); - Draw_TensorList(v, ValMin, ValMax, v->TI, v->NbTI, 6, Draw_TensorPrism); + if(!skip_3d && v->DrawScalars) + Draw_List(v, ValMin, ValMax, v->SI, v->NbSI, 6, Draw_ScalarPrism); + if(v->DrawVectors) + Draw_List(v, ValMin, ValMax, v->VI, v->NbVI, 6, Draw_VectorPrism); + if(v->DrawTensors) + Draw_List(v, ValMin, ValMax, v->TI, v->NbTI, 6, Draw_TensorPrism); } if(v->DrawPyramids) { - if(!skip_3d) - Draw_ScalarList(v, ValMin, ValMax, v->SY, v->NbSY, 5, 1, Draw_ScalarPyramid); - Draw_VectorList(v, ValMin, ValMax, v->VY, v->NbVY, 5, Draw_VectorPyramid); - Draw_TensorList(v, ValMin, ValMax, v->TY, v->NbTY, 5, Draw_TensorPyramid); + if(!skip_3d && v->DrawScalars) + Draw_List(v, ValMin, ValMax, v->SY, v->NbSY, 5, Draw_ScalarPyramid); + if(v->DrawVectors) + Draw_List(v, ValMin, ValMax, v->VY, v->NbVY, 5, Draw_VectorPyramid); + if(v->DrawTensors) + Draw_List(v, ValMin, ValMax, v->TY, v->NbTY, 5, Draw_TensorPyramid); } pass_1: diff --git a/Graphics/PostElement.cpp b/Graphics/PostElement.cpp index fa04e600eb9d7046621c459c0ce6467e8ec50d04..838d6ac8288b0c63caeafea2daf4222dbff06a56 100644 --- a/Graphics/PostElement.cpp +++ b/Graphics/PostElement.cpp @@ -1,4 +1,4 @@ -// $Id: PostElement.cpp,v 1.40 2004-08-07 06:59:16 geuzaine Exp $ +// $Id: PostElement.cpp,v 1.41 2004-09-01 20:23:50 geuzaine Exp $ // // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle // @@ -229,7 +229,7 @@ void Draw_ScalarPoint(Post_View * View, int preproNormals, double d; char Num[100]; - if(View->Boundary > 0) + if(View->Boundary > 0 || preproNormals) return; d = V[View->TimeStep]; @@ -269,6 +269,9 @@ void Draw_ScalarLine(Post_View * View, int preproNormals, double Xp[5], Yp[5], Zp[5], Vp[5], Val[5]; char Num[100]; + if(preproNormals) + return; + double *vv = &V[2 * View->TimeStep]; if(View->Boundary > 0) { @@ -858,9 +861,69 @@ void Draw_ScalarPyramid(Post_View * View, int preproNormals, View->ShowElement = show; } + +int GetScalarDataFromOtherView(int type, int nbnod, Post_View *v, double *d) +{ + static int error1 = -1; + static int error2 = -1; + Post_View *v2 = v->ViewForDisplacement; + int num = v->ElementForDisplacement; + + if(!v2){ + if(error1 != v->Num){ + Msg(GERROR, "Non-existent view for displacement plot"); + error1 = v->Num; + } + return 0; + } + + int nbelm = 0; + List_T *l; + switch (type) { + case POINT: if(v->NbVP == v2->NbSP){ nbelm = v2->NbSP; l = v2->SP; } break; + case LINE: if(v->NbVL == v2->NbSL){ nbelm = v2->NbSL; l = v2->SL; } break; + case TRIANGLE: if(v->NbVT == v2->NbST){ nbelm = v2->NbST; l = v2->ST; } break; + case QUADRANGLE: if(v->NbVQ == v2->NbSQ){ nbelm = v2->NbSQ; l = v2->SQ; } break; + case TETRAHEDRON: if(v->NbVS == v2->NbSS){ nbelm = v2->NbSS; l = v2->SS; } break; + case HEXAHEDRON: if(v->NbVH == v2->NbSH){ nbelm = v2->NbSH; l = v2->SH; } break; + case PRISM: if(v->NbVI == v2->NbSI){ nbelm = v2->NbSI; l = v2->SI; } break; + case PYRAMID: if(v->NbVY == v2->NbSY){ nbelm = v2->NbSY; l = v2->SY; } break; + } + + if(!nbelm || num < 0 || v2->NbTimeStep != v->NbTimeStep){ + if(error2 != v->Num){ + Msg(GERROR, "Incompatible view for displacement plot"); + error2 = v->Num; + } + return 0; + } + + int nb = List_Nbr(l) / nbelm; + double *val = (double *)List_Pointer_Fast(l, num * nb + 3 * nbnod); + for(int k = 0; k < nbnod; k++) + d[k] = val[nbnod * v->TimeStep + k]; + + switch (v->RangeType) { + case DRAW_POST_RANGE_DEFAULT: + v->MinForDisplacement = v2->Min; + v->MaxForDisplacement = v2->Max; + break; + case DRAW_POST_RANGE_CUSTOM: // yes, take the values from v! + v->MinForDisplacement = v->CustomMin; + v->MaxForDisplacement = v->CustomMax; + break; + case DRAW_POST_RANGE_PER_STEP: + v->MinForDisplacement = v2->TimeStepMin[v->TimeStep]; + v->MaxForDisplacement = v2->TimeStepMax[v->TimeStep]; + break; + } + + return 1; +} + // Vector Elements -void Draw_VectorElement(int type, Post_View * View, +void Draw_VectorElement(int type, Post_View * View, int preproNormals, double ValMin, double ValMax, double *X, double *Y, double *Z, double *V) { @@ -888,12 +951,19 @@ void Draw_VectorElement(int type, Post_View * View, d[k] = sqrt(Val[k][0] * Val[k][0] + Val[k][1] * Val[k][1] + Val[k][2] * Val[k][2]); } + if(View->VectorType == DRAW_POST_DISPLACEMENT_EXTERNAL){ + GetScalarDataFromOtherView(type, nbnod, View, d); + ValMin = View->MinForDisplacement; + ValMax = View->MaxForDisplacement; + } + double Raise[3][8]; for(int i = 0; i < 3; i++) for(int k = 0; k < nbnod; k++) Raise[i][k] = View->Raise[i] * d[k]; - if(View->VectorType == DRAW_POST_DISPLACEMENT) { + if(View->VectorType == DRAW_POST_DISPLACEMENT || + View->VectorType == DRAW_POST_DISPLACEMENT_EXTERNAL){ fact = View->DisplacementFactor; for(int k = 0; k < nbnod; k++) { @@ -906,7 +976,7 @@ void Draw_VectorElement(int type, Post_View * View, View->TimeStep = 0; switch (type) { case POINT: - Draw_ScalarPoint(View, 0, ValMin, ValMax, xx, yy, zz, d); + Draw_ScalarPoint(View, preproNormals, ValMin, ValMax, xx, yy, zz, d); if(ts) { //draw trajectory if(View->LineType) { double dx2, dy2, dz2, XX[2], YY[2], ZZ[2]; @@ -950,25 +1020,25 @@ void Draw_VectorElement(int type, Post_View * View, } break; case LINE: - Draw_ScalarLine(View, 0, ValMin, ValMax, xx, yy, zz, d); + Draw_ScalarLine(View, preproNormals, ValMin, ValMax, xx, yy, zz, d); break; case TRIANGLE: - Draw_ScalarTriangle(View, 0, ValMin, ValMax, xx, yy, zz, d); + Draw_ScalarTriangle(View, preproNormals, ValMin, ValMax, xx, yy, zz, d); break; case TETRAHEDRON: - Draw_ScalarTetrahedron(View, 0, ValMin, ValMax, xx, yy, zz, d); + Draw_ScalarTetrahedron(View, preproNormals, ValMin, ValMax, xx, yy, zz, d); break; case QUADRANGLE: - Draw_ScalarQuadrangle(View, 0, ValMin, ValMax, xx, yy, zz, d); + Draw_ScalarQuadrangle(View, preproNormals, ValMin, ValMax, xx, yy, zz, d); break; case HEXAHEDRON: - Draw_ScalarHexahedron(View, 0, ValMin, ValMax, xx, yy, zz, d); + Draw_ScalarHexahedron(View, preproNormals, ValMin, ValMax, xx, yy, zz, d); break; case PRISM: - Draw_ScalarPrism(View, 0, ValMin, ValMax, xx, yy, zz, d); + Draw_ScalarPrism(View, preproNormals, ValMin, ValMax, xx, yy, zz, d); break; case PYRAMID: - Draw_ScalarPyramid(View, 0, ValMin, ValMax, xx, yy, zz, d); + Draw_ScalarPyramid(View, preproNormals, ValMin, ValMax, xx, yy, zz, d); break; } View->TimeStep = ts; @@ -1058,55 +1128,55 @@ void Draw_VectorElement(int type, Post_View * View, } } -#define ARGS Post_View *View, \ - double ValMin, double ValMax, \ +#define ARGS Post_View *View, int preproNormals, \ + double ValMin, double ValMax, \ double *X, double *Y, double *Z, double *V void Draw_VectorPoint(ARGS) { - Draw_VectorElement(POINT, View, ValMin, ValMax, X, Y, Z, V); + Draw_VectorElement(POINT, View, preproNormals, ValMin, ValMax, X, Y, Z, V); } void Draw_VectorLine(ARGS) { - Draw_VectorElement(LINE, View, ValMin, ValMax, X, Y, Z, V); + Draw_VectorElement(LINE, View, preproNormals, ValMin, ValMax, X, Y, Z, V); } void Draw_VectorTriangle(ARGS) { - Draw_VectorElement(TRIANGLE, View, ValMin, ValMax, X, Y, Z, V); + Draw_VectorElement(TRIANGLE, View, preproNormals, ValMin, ValMax, X, Y, Z, V); } void Draw_VectorTetrahedron(ARGS) { - Draw_VectorElement(TETRAHEDRON, View, ValMin, ValMax, X, Y, Z, V); + Draw_VectorElement(TETRAHEDRON, View, preproNormals, ValMin, ValMax, X, Y, Z, V); } void Draw_VectorQuadrangle(ARGS) { - Draw_VectorElement(QUADRANGLE, View, ValMin, ValMax, X, Y, Z, V); + Draw_VectorElement(QUADRANGLE, View, preproNormals, ValMin, ValMax, X, Y, Z, V); } void Draw_VectorHexahedron(ARGS) { - Draw_VectorElement(HEXAHEDRON, View, ValMin, ValMax, X, Y, Z, V); + Draw_VectorElement(HEXAHEDRON, View, preproNormals, ValMin, ValMax, X, Y, Z, V); } void Draw_VectorPrism(ARGS) { - Draw_VectorElement(PRISM, View, ValMin, ValMax, X, Y, Z, V); + Draw_VectorElement(PRISM, View, preproNormals, ValMin, ValMax, X, Y, Z, V); } void Draw_VectorPyramid(ARGS) { - Draw_VectorElement(PYRAMID, View, ValMin, ValMax, X, Y, Z, V); + Draw_VectorElement(PYRAMID, View, preproNormals, ValMin, ValMax, X, Y, Z, V); } #undef ARGS // Tensor Elements -void Draw_TensorElement(int type, Post_View * View, +void Draw_TensorElement(int type, Post_View * View, int preproNormals, double ValMin, double ValMax, double *X, double *Y, double *Z, double *V) { @@ -1138,76 +1208,76 @@ void Draw_TensorElement(int type, Post_View * View, switch (type) { case POINT: - Draw_ScalarPoint(View, 0, ValMin, ValMax, X, Y, Z, V_VonMises); + Draw_ScalarPoint(View, preproNormals, ValMin, ValMax, X, Y, Z, V_VonMises); break; case LINE: - Draw_ScalarLine(View, 0, ValMin, ValMax, X, Y, Z, V_VonMises); + Draw_ScalarLine(View, preproNormals, ValMin, ValMax, X, Y, Z, V_VonMises); break; case TRIANGLE: - Draw_ScalarTriangle(View, 0, ValMin, ValMax, X, Y, Z, V_VonMises); + Draw_ScalarTriangle(View, preproNormals, ValMin, ValMax, X, Y, Z, V_VonMises); break; case QUADRANGLE: - Draw_ScalarQuadrangle(View, 0, ValMin, ValMax, X, Y, Z, V_VonMises); + Draw_ScalarQuadrangle(View, preproNormals, ValMin, ValMax, X, Y, Z, V_VonMises); break; case TETRAHEDRON: - Draw_ScalarTetrahedron(View, 0, ValMin, ValMax, X, Y, Z, V_VonMises); + Draw_ScalarTetrahedron(View, preproNormals, ValMin, ValMax, X, Y, Z, V_VonMises); break; case HEXAHEDRON: - Draw_ScalarHexahedron(View, 0, ValMin, ValMax, X, Y, Z, V_VonMises); + Draw_ScalarHexahedron(View, preproNormals, ValMin, ValMax, X, Y, Z, V_VonMises); break; case PRISM: - Draw_ScalarPrism(View, 0, ValMin, ValMax, X, Y, Z, V_VonMises); + Draw_ScalarPrism(View, preproNormals, ValMin, ValMax, X, Y, Z, V_VonMises); break; case PYRAMID: - Draw_ScalarPyramid(View, 0, ValMin, ValMax, X, Y, Z, V_VonMises); + Draw_ScalarPyramid(View, preproNormals, ValMin, ValMax, X, Y, Z, V_VonMises); break; } View->TimeStep = ts; } -#define ARGS Post_View *View, \ - double ValMin, double ValMax, \ +#define ARGS Post_View *View, int preproNormals, \ + double ValMin, double ValMax, \ double *X, double *Y, double *Z, double *V void Draw_TensorPoint(ARGS) { - Draw_TensorElement(POINT, View, ValMin, ValMax, X, Y, Z, V); + Draw_TensorElement(POINT, View, preproNormals, ValMin, ValMax, X, Y, Z, V); } void Draw_TensorLine(ARGS) { - Draw_TensorElement(LINE, View, ValMin, ValMax, X, Y, Z, V); + Draw_TensorElement(LINE, View, preproNormals, ValMin, ValMax, X, Y, Z, V); } void Draw_TensorTriangle(ARGS) { - Draw_TensorElement(TRIANGLE, View, ValMin, ValMax, X, Y, Z, V); + Draw_TensorElement(TRIANGLE, View, preproNormals, ValMin, ValMax, X, Y, Z, V); } void Draw_TensorTetrahedron(ARGS) { - Draw_TensorElement(TETRAHEDRON, View, ValMin, ValMax, X, Y, Z, V); + Draw_TensorElement(TETRAHEDRON, View, preproNormals, ValMin, ValMax, X, Y, Z, V); } void Draw_TensorQuadrangle(ARGS) { - Draw_TensorElement(QUADRANGLE, View, ValMin, ValMax, X, Y, Z, V); + Draw_TensorElement(QUADRANGLE, View, preproNormals, ValMin, ValMax, X, Y, Z, V); } void Draw_TensorHexahedron(ARGS) { - Draw_TensorElement(HEXAHEDRON, View, ValMin, ValMax, X, Y, Z, V); + Draw_TensorElement(HEXAHEDRON, View, preproNormals, ValMin, ValMax, X, Y, Z, V); } void Draw_TensorPrism(ARGS) { - Draw_TensorElement(PRISM, View, ValMin, ValMax, X, Y, Z, V); + Draw_TensorElement(PRISM, View, preproNormals, ValMin, ValMax, X, Y, Z, V); } void Draw_TensorPyramid(ARGS) { - Draw_TensorElement(PYRAMID, View, ValMin, ValMax, X, Y, Z, V); + Draw_TensorElement(PYRAMID, View, preproNormals, ValMin, ValMax, X, Y, Z, V); } #undef ARGS diff --git a/Graphics/Scale.cpp b/Graphics/Scale.cpp index 7478fa8d00abc548cf855ae3094b10ae6af21d10..f69155eccc319a3f7666fc1820d706871e7d266c 100644 --- a/Graphics/Scale.cpp +++ b/Graphics/Scale.cpp @@ -1,4 +1,4 @@ -// $Id: Scale.cpp,v 1.43 2004-05-29 10:11:12 geuzaine Exp $ +// $Id: Scale.cpp,v 1.44 2004-09-01 20:23:50 geuzaine Exp $ // // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle // @@ -68,20 +68,26 @@ void draw_scale(Post_View * v, glEnd(); } - switch(v->RangeType){ - case DRAW_POST_RANGE_CUSTOM: - ValMin = v->CustomMin; - ValMax = v->CustomMax; - break; - case DRAW_POST_RANGE_PER_STEP: - ValMin = v->TimeStepMin[v->TimeStep]; - ValMax = v->TimeStepMax[v->TimeStep]; - break; - case DRAW_POST_RANGE_DEFAULT: - default: - ValMin = v->Min; - ValMax = v->Max; - break; + if(v->VectorType == DRAW_POST_DISPLACEMENT_EXTERNAL){ + ValMin = v->MinForDisplacement; + ValMax = v->MaxForDisplacement; + } + else{ + switch(v->RangeType){ + case DRAW_POST_RANGE_CUSTOM: + ValMin = v->CustomMin; + ValMax = v->CustomMax; + break; + case DRAW_POST_RANGE_PER_STEP: + ValMin = v->TimeStepMin[v->TimeStep]; + ValMax = v->TimeStepMax[v->TimeStep]; + break; + case DRAW_POST_RANGE_DEFAULT: + default: + ValMin = v->Min; + ValMax = v->Max; + break; + } } switch (v->ScaleType) { diff --git a/TODO b/TODO index 4cdf10484a94f16f33b2691876ee9cad3a63746e..8020a10509d0f4f206329c7fc7c4ce99142db3b9 100644 --- a/TODO +++ b/TODO @@ -1,4 +1,4 @@ -$Id: TODO,v 1.60 2004-08-20 17:54:20 geuzaine Exp $ +$Id: TODO,v 1.61 2004-09-01 20:23:49 geuzaine Exp $ add an interactive way to choose the orientation of surfaces in surface loops and lines in line loops @@ -9,6 +9,10 @@ normals...) ******************************************************************** +Raise & offsets should modify the bouding boxes... (maybe?) + +******************************************************************** + Test and reintroduce the cylindrical surfaces (cylinder, cone, torus) ******************************************************************** diff --git a/doc/VERSIONS b/doc/VERSIONS index 8b0976e5a31fa54bd4ec523515394c766dc432f8..8194e7e0b9245b6c6fc6911c4d9615751231d69a 100644 --- a/doc/VERSIONS +++ b/doc/VERSIONS @@ -1,4 +1,9 @@ -$Id: VERSIONS,v 1.243 2004-08-21 21:10:26 geuzaine Exp $ +$Id: VERSIONS,v 1.244 2004-09-01 20:23:50 geuzaine Exp $ + +New since 1.55: new post-processing option to draw a scalar view +raised by a displacement view without using Plugin(DisplacementRaise) +(makes drawing arbitrary scalar fields on deformed meshes much +easier); small bug fixes. New in 1.55: added background mesh support for Triangle; meshes can now be displayed using "smoothed" normals (like post-processing diff --git a/doc/gmsh.html b/doc/gmsh.html index 0e74e9c47bfdd667354ec9eb591c8fab5caa319b..0b07a860033992e6df25f975ad801eac6263297e 100644 --- a/doc/gmsh.html +++ b/doc/gmsh.html @@ -103,10 +103,10 @@ capabilities</a>. Gmsh is distributed under the terms of the <a href="http://www.gnu.org/copyleft/gpl.html">GNU General Public License -(GPL)</a>. Pre-compiled binaries (dynamically linked with OpenGL<a -href="#opengl-footnote" name="opengl-footmark"><sup>1</sup></a>) are -available for Windows, Linux and Mac OS X. The tutorial and demo files -are included in the archives. +(GPL)</a>. Pre-compiled binaries<a href="#opengl-footnote" +name="opengl-footmark"><sup>1</sup></a> are available for Windows, +Linux and Mac OS X. The tutorial and demo files are included in the +archives. <ul> <li><a href="/gmsh/bin/Windows/gmsh-1.55.0-Windows.zip">Windows zip archive (95/98/NT/2000/XP)</a>