00001 /*************************************************************************** 00002 *cr 00003 *cr (C) Copyright 1995-2019 The Board of Trustees of the 00004 *cr University of Illinois 00005 *cr All Rights Reserved 00006 *cr 00007 ***************************************************************************/ 00008 00009 /*************************************************************************** 00010 * RCS INFORMATION: 00011 * 00012 * $RCSfile: DrawForce.C,v $ 00013 * $Author: johns $ $Locker: $ $State: Exp $ 00014 * $Revision: 1.57 $ $Date: 2019/01/17 21:20:59 $ 00015 * 00016 *************************************************************************** 00017 * DESCRIPTION: 00018 * 00019 * Another Child Displayable component for a remote molecule; this displays 00020 * and stores the information about the interactive forces being applied to 00021 * the molecule. If no forces are being used, this draws nothing. 00022 * 00023 * The force information is retrieved from the Atom list in the parent 00024 * molecule. No forces are stored here. 00025 * 00026 * This name is now a misnomer as accelerations are changed, _not_ forces. 00027 * This eliminates the problem of having hydrogens acceleterating 12 time 00028 * faster than carbons, etc. 00029 * 00030 * And now I'm changing it back. We should draw the actual force... 00031 * 00032 ***************************************************************************/ 00033 00034 #include "DrawForce.h" 00035 #include "DrawMolecule.h" 00036 #include "DisplayDevice.h" 00037 #include "Scene.h" 00038 #include "Atom.h" 00039 #include "Timestep.h" 00040 #include "Inform.h" 00041 #include "utilities.h" 00042 #include "Mouse.h" 00043 #include "VMDApp.h" 00044 00045 // Force arrow scaling constant 00046 // XXX ideally this should be a user-defined scaling coefficient 00047 // settable in the text commands and GUI interfaces 00048 00049 // Since we now have MUCH faster machines for running simulations, 00050 // we should expect IMD users to be able to apply weaker pulling 00051 // forces to achieve the same end results now. Given this, we 00052 // can now use a much larger scaling factor (1.0f) on the force arrows 00053 // than we did in the past (0.3333f). 00054 #define DRAW_FORCE_SCALE 1.0f 00055 00057 00058 DrawForce::DrawForce(DrawMolecule *mr) 00059 : Displayable(mr) { 00060 00061 // save data 00062 mol = mr; 00063 00064 // initialize variables 00065 needRegenerate = TRUE; 00066 colorCat = (-1); 00067 } 00068 00069 00071 00072 void DrawForce::do_color_changed(int ccat) { 00073 // right now this does nothing, since we always redraw the list. But 00074 // the general thing it would do is set the flag that a redraw is needed, 00075 // so looking ahead I'll do this now. 00076 if(ccat == colorCat) { 00077 needRegenerate = TRUE; 00078 } 00079 } 00080 00082 00083 // regenerate the command list 00084 void DrawForce::create_cmdlist(void) { 00085 // do we need to recreate everything? 00086 if(needRegenerate) { 00087 // regenerate both data block and display commands 00088 needRegenerate = FALSE; 00089 reset_disp_list(); 00090 00091 // only put in commands if there is a current frame 00092 Timestep *ts = mol->current(); 00093 if (ts) { 00094 const float *tsforce = ts->force; 00095 00096 // if we have a force array, draw arrows for all non-zero forces 00097 if (tsforce != NULL) { 00098 append(DMATERIALON); 00099 00100 // for each atom, if it has a nonzero user force, then display it 00101 long maxidx = mol->nAtoms * 3L; 00102 for (int idx=0; idx<maxidx; idx+=3) { 00103 // check for nonzero forces 00104 if (tsforce[idx]>0.0f || tsforce[idx+1]>0.0f || tsforce[idx+2]>0.0f || 00105 tsforce[idx]<0.0f || tsforce[idx+1]<0.0f || tsforce[idx+2]<0.0f) { 00106 // get position of atom, and the position of the force vector 00107 float fval[3], p2[3], p3[3]; 00108 float *p1 = ts->pos + idx; 00109 for (int k=0; k<3; k++) { 00110 fval[k] = tsforce[idx + k] * DRAW_FORCE_SCALE; 00111 p2[k] = p1[k] + fval[k]; 00112 p3[k] = p1[k] + 0.8f * fval[k]; 00113 } 00114 00115 // find length of force 00116 float p2norm = norm(fval); 00117 00118 // set arrow color 00119 int sc = (int)p2norm; 00120 if (sc >= MAPCLRS) 00121 sc = MAPCLRS - 1; 00122 cmdColorIndex.putdata(MAPCOLOR(sc), cmdList); 00123 00124 // compute the cone radii 00125 float rada = 0.2f * p2norm; 00126 if (rada > 0.3f) 00127 rada = 0.3f; 00128 float radb = 1.5f * rada; 00129 00130 // draw the arrow with two cones 00131 cmdCone.putdata(p3, p1, rada, 0, 9, cmdList); 00132 cmdCone.putdata(p3, p2, radb, 0, 9, cmdList); 00133 } 00134 } 00135 } 00136 } 00137 } 00138 } 00139 00140 00142 // prepare for drawing ... do any updates needed right before draw. 00143 void DrawForce::prepare() { 00144 00145 if (parent->needUpdate()) { 00146 needRegenerate = TRUE; 00147 } 00148 00149 create_cmdlist(); 00150 } 00151