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: AtomRep.C,v $ 00013 * $Author: johns $ $Locker: $ $State: Exp $ 00014 * $Revision: 1.134 $ $Date: 2019年01月17日 21:20:58 $ 00015 * 00016 *************************************************************************** 00017 * DESCRIPTION: 00018 * 00019 * Parse and maintain the data for how a molecule should be represented. 00020 * 00021 ***************************************************************************/ 00022 00023 #include <string.h> 00024 #include <stdlib.h> 00025 #include "AtomRep.h" 00026 #include "Inform.h" 00027 #include "utilities.h" 00028 #include "config.h" 00029 00030 /*********************** NOTES on ADDING NEW REPRESENTATIONS ************ 00031 So, you wanna add a new representation ... here's what you have to do: 00032 1. Choose a a name for the rep, and decide how many parameters it needs. 00033 This object has support for up to MAX_ATOMREP_DATA parameters. 00034 2. Choose the order in which these will be specified in the text command. 00035 3. Add a new identifier in the main RepMethod enumeration for this new 00036 rep. The order is important; where you put the new item is where it 00037 will appear in lists of the different representations. 00038 4. Add a new element to the AtomRepInfo structure array (below). This element 00039 defines the name of the new rep, and gives info about all the parameters 00040 needed for that rep. You must put the item into the array in the same 00041 position where the new enum value was inserted into RepMethod. 00042 5. Once this structure is properly defined, the GUI and text interface will 00043 properly process and display the info for the new rep. At this point, 00044 you must add the code to display the new rep in DrawMolItem. 00045 6. Sit back and enjoy ... 00046 00047 FORMAT for AtomRepInfo STRUCTURE: 00048 --------------------------------- 00049 Easiest thing to do is to copy an item with the same number of parameters, 00050 and change the necessary values. The items in each structure are: 00051 a. Integer enum code for the rep (same as was put in RepMethod enum) 00052 b. Name of rep (should be a single small word; this is the name 00053 used in the GUI list, and what the user calls the rep when typing 00054 in a command to change to this rep) 00055 c. Number of parameters required. 00056 d. An array of Structures which define how each parameter is used 00057 for the representation. The format for these items are: 00058 1. Index of the parameter in the AtomRep internal data 00059 storage array. This should be used when retrieving the 00060 data; call 'get_data' with this index value to retrieve 00061 the value for this parameter. Each parameter for the 00062 representation should have a different index, and they 00063 should be in the range 0 ... MAX_ATOMREP_DATA-1. 00064 There is an enumeration giving names for these indices, 00065 which is used right now primarily for historical reasons. 00066 Older parts of VMD used explicit calls to routines to get 00067 values for things such as the line thickness and sphere 00068 resolution, and these routines are still present. But 00069 since new reps may not necessarily have characteristics 00070 which map to these items, this should not be used in the 00071 future. 00072 2. Default value 00073 ***************************************************************************/ 00074 00075 // default res of cartoon cylinders 00076 #define DEF_CART_RES 12.0 00077 00078 // default res of bond cylinders 00079 #define DEF_BOND_RES 12.0 00080 00081 // default res of spheres 00082 #define DEF_SPH_RES 12.0 00083 00084 // default res of licorice reps 00085 #define DEF_LIC_RES 12.0 00086 00087 // default thickness of lines 00088 #define DEF_LINE_RES 1.0 00089 00090 // default point size 00091 #define DEF_POINT_SIZE 1.0 00092 00093 //const AtomRepDataInfo UNUSED = {0, 0.0}; 00094 #define UNUSED {0, 0.0} 00095 00096 // define structures which indicate what data is needed by each rep 00097 const AtomRepParamStruct AtomRepInfo[AtomRep::TOTAL] = { 00098 // 00099 // Bond-oriented reps 00100 // 00101 00102 // Lines 00103 { "Lines", 2, { 00104 { AtomRep::LINETHICKNESS, DEF_LINE_RES }, 00105 { AtomRep::ISOLINETHICKNESS, 0.0f }, 00106 UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, 00107 UNUSED, UNUSED, UNUSED } 00108 }, 00109 00110 // Bonds 00111 { "Bonds", 2, { 00112 { AtomRep::BONDRAD, 0.3f }, 00113 { AtomRep::BONDRES, DEF_BOND_RES }, 00114 UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, 00115 UNUSED, UNUSED, UNUSED } 00116 }, 00117 00118 // DynamicBonds 00119 { "DynamicBonds", 3, { 00120 { AtomRep::SPHERERAD, 3.0f }, // distance 00121 { AtomRep::BONDRAD, 0.3f }, 00122 { AtomRep::BONDRES, DEF_BOND_RES }, 00123 UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, 00124 UNUSED, UNUSED, UNUSED } 00125 }, 00126 00127 // HBonds 00128 { "HBonds", 3, { 00129 { AtomRep::BONDRAD, 3.0f}, // distance 00130 { AtomRep::SPHERERAD, 20.0f}, // angle 00131 { AtomRep::LINETHICKNESS, 1.0f}, 00132 UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, 00133 UNUSED, UNUSED, UNUSED } 00134 }, 00135 00136 00137 // 00138 // Atom-oriented reps 00139 // 00140 00141 // Points 00142 { "Points", 1, { 00143 { AtomRep::LINETHICKNESS, DEF_POINT_SIZE}, // size 00144 UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, 00145 UNUSED, UNUSED, UNUSED, UNUSED } 00146 }, 00147 00148 // VDW 00149 { "VDW", 2, { 00150 { AtomRep::SPHERERAD, 1.0f}, 00151 { AtomRep::SPHERERES, DEF_SPH_RES }, 00152 UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, 00153 UNUSED, UNUSED, UNUSED } 00154 }, 00155 00156 // CPK 00157 { "CPK", 5, { 00158 { AtomRep::SPHERERAD, 1.0f}, 00159 { AtomRep::BONDRAD, 0.3f}, 00160 { AtomRep::SPHERERES, DEF_SPH_RES}, 00161 { AtomRep::BONDRES, DEF_BOND_RES}, 00162 { AtomRep::ISOLINETHICKNESS, 0.0f }, 00163 UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED } 00164 }, 00165 00166 // Licorice 00167 { "Licorice", 4, { 00168 { AtomRep::BONDRAD, 0.3f }, 00169 { AtomRep::SPHERERES, DEF_LIC_RES}, 00170 { AtomRep::BONDRES, DEF_LIC_RES}, 00171 { AtomRep::ISOLINETHICKNESS, 0.0f }, // if nonzero, cutoff distance 00172 UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, 00173 UNUSED, UNUSED, UNUSED } 00174 }, 00175 00176 00177 #ifdef VMDPOLYHEDRA 00178 // Polyhedra 00179 { "Polyhedra", 1, { 00180 { AtomRep::SPHERERAD, 3.0f }, // distance 00181 UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, 00182 UNUSED, UNUSED, UNUSED, UNUSED } 00183 }, 00184 #endif 00185 00186 // 00187 // Secondary structure reps 00188 // 00189 00190 // C-alpha trace 00191 { "Trace", 2, { 00192 { AtomRep::BONDRAD, 0.3f}, 00193 { AtomRep::BONDRES, DEF_BOND_RES}, 00194 UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, 00195 UNUSED, UNUSED, UNUSED } 00196 }, 00197 00198 // Tube 00199 { "Tube", 2, { 00200 { AtomRep::BONDRAD, 0.3f }, 00201 { AtomRep::BONDRES, DEF_BOND_RES}, 00202 UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, 00203 UNUSED, UNUSED, UNUSED } 00204 }, 00205 00206 // Ribbons 00207 { "Ribbons", 3, { 00208 { AtomRep::BONDRAD, 0.3f}, 00209 { AtomRep::BONDRES, DEF_BOND_RES}, 00210 { AtomRep::LINETHICKNESS, 2.0f}, 00211 UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, 00212 UNUSED, UNUSED, UNUSED } 00213 }, 00214 00215 // NewRibbons 00216 { "NewRibbons", 4, { 00217 { AtomRep::BONDRAD, 0.3f }, 00218 { AtomRep::BONDRES, 12.0f }, 00219 { AtomRep::LINETHICKNESS, 3.0f}, 00220 { AtomRep::SPHERERAD, 0}, // spline basis 00221 UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, 00222 UNUSED, UNUSED, UNUSED } 00223 }, 00224 00225 // Structure 00226 { "Cartoon", 3, { 00227 { AtomRep::BONDRAD, 2.1f}, 00228 { AtomRep::BONDRES, 24.0f }, 00229 { AtomRep::LINETHICKNESS, 5.0f}, 00230 UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, 00231 UNUSED, UNUSED, UNUSED } 00232 }, 00233 00234 // NewCartoon 00235 { "NewCartoon", 4, { 00236 { AtomRep::BONDRAD, 0.3f }, 00237 { AtomRep::BONDRES, 12.0f }, 00238 { AtomRep::LINETHICKNESS, 4.5f}, 00239 { AtomRep::SPHERERAD, 0}, // spline basis 00240 UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, 00241 UNUSED, UNUSED, UNUSED } 00242 }, 00243 00244 #ifdef VMDWITHCARBS 00245 // PaperChain 00246 { "PaperChain", 2, { 00247 { AtomRep::LINETHICKNESS, 1.0f }, // bipyramid_height : height of the pyramids drawn to represent rings 00248 { AtomRep::ISOSTEPSIZE, 10 }, // maxringsize : maximum number of atoms in a small ring 00249 UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, 00250 UNUSED, UNUSED, UNUSED, UNUSED, UNUSED } 00251 }, 00252 00253 // Twister 00254 { "Twister", 7, { 00255 { AtomRep::LINETHICKNESS, 1 }, // start_end_centroid : 0 - start ribbons at the edge of the ring, 1 - start ribbons at the ring centroids 00256 { AtomRep::BONDRES, 0 }, // hide_shared_links: 0 - show all linkage paths, 1 - hide linkage paths which share edges with other paths 00257 { AtomRep::SPHERERAD, 10 }, // rib_steps : number of steps to use when drawing ribbons 00258 { AtomRep::BONDRAD, 0.3f }, // rib_width : width of the ribbon 00259 { AtomRep::SPHERERES, 0.05f }, // rib_height : height of the ribbon 00260 { AtomRep::ISOSTEPSIZE, 10 }, // maxringsize : maximum number of atoms in a small ring 00261 { AtomRep::ISOLINETHICKNESS, 5 }, // maxpathlength : maximum number of atoms in a path joining two small rings 00262 UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED } 00263 }, 00264 #endif 00265 00266 00267 // 00268 // Surface, Isosurface, and Solvent reps 00269 // 00270 00271 #ifdef VMDQUICKSURF 00272 // QuickSurf 00273 { "QuickSurf", 4, { 00274 { AtomRep::SPHERERAD, 1.0f }, // sphere radius multiplier 00275 { AtomRep::BONDRAD, 0.5f }, // density isovalue for surface 00276 { AtomRep::GRIDSPACING, 1.0f}, // lattice grid spacing 00277 { AtomRep::BONDRES, 0 }, // quality 00278 UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, 00279 UNUSED, UNUSED, UNUSED } 00280 }, 00281 #endif 00282 00283 #ifdef VMDMSMS 00284 // MSMS surface 00285 { "MSMS", 4, { 00286 { AtomRep::SPHERERAD, 1.5f }, // probe radius 00287 { AtomRep::SPHERERES, 1.5f }, // density 00288 { AtomRep::LINETHICKNESS, 0}, // all atoms 00289 { AtomRep::BONDRES, 0}, // wireframe 00290 UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, 00291 UNUSED, UNUSED, UNUSED } 00292 }, 00293 #endif 00294 00295 #ifdef VMDNANOSHAPER 00296 // NanoShaper surface 00297 { "NanoShaper", 6, { 00298 { AtomRep::LINETHICKNESS, 0}, // surface type 00299 { AtomRep::BONDRES, 0}, // wireframe 00300 { AtomRep::GRIDSPACING, 0.5f}, // lattice grid spacing 00301 { AtomRep::SPHERERAD, 1.40f }, // probe radius 00302 { AtomRep::SPHERERES, 0.45f }, // skin parm 00303 { AtomRep::BONDRAD, 0.5f }, // blob parm 00304 UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, 00305 UNUSED, UNUSED, UNUSED } 00306 }, 00307 #endif 00308 00309 #ifdef VMDSURF 00310 // Surf 00311 { "Surf", 2, { 00312 { AtomRep::SPHERERAD, 1.4f }, // probe radius 00313 { AtomRep::BONDRES, 0}, // wireframe 00314 UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, 00315 UNUSED, UNUSED, UNUSED } 00316 }, 00317 #endif 00318 00319 // Slice of volumetric data 00320 { "VolumeSlice", 4, { 00321 { AtomRep::SPHERERAD, 0.5f }, // slice 00322 { AtomRep::SPHERERES, 0 }, // VolID 00323 { AtomRep::LINETHICKNESS, 0 }, // slice axis 00324 { AtomRep::BONDRES, 2 }, // quality 00325 UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, 00326 UNUSED, UNUSED, UNUSED } 00327 }, 00328 00329 // Isosurface of volumetric data 00330 { "Isosurface", 6, { 00331 { AtomRep::SPHERERAD, 0.5f }, // isoval 00332 { AtomRep::SPHERERES, 0}, // VolID 00333 { AtomRep::LINETHICKNESS, 2}, // draw box and isosurface by default 00334 { AtomRep::BONDRES, 2}, // use points method by default 00335 { AtomRep::ISOSTEPSIZE, 1}, // use step size of one by default 00336 { AtomRep::ISOLINETHICKNESS, 1}, // lines are thickness one by default 00337 UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, 00338 UNUSED, UNUSED, UNUSED } 00339 }, 00340 00341 // Volumetric gradient field lines 00342 { "FieldLines", 8, { 00343 { AtomRep::SPHERERES, 0}, // VolID 00344 { AtomRep::SPHERERAD, 1.8f}, // seed value 00345 { AtomRep::BONDRAD, 10.0f}, // minimum line length 00346 { AtomRep::BONDRES, 50.0f}, // maximum line length 00347 { AtomRep::LINETHICKNESS, 1}, // line thickness 00348 { AtomRep::FIELDLINESTYLE, 0}, // field lines drawn as lines 00349 { AtomRep::FIELDLINESEEDUSEGRID, 0}, // field line seed type 00350 { AtomRep::FIELDLINEDELTA, 0.25}, // field lines integrator stepsize 00351 UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED} 00352 }, 00353 00354 // Molecular orbital 00355 { "Orbital", 10, { 00356 { AtomRep::SPHERERAD, 0.05f}, // isoval 00357 { AtomRep::SPHERERES, 0}, // Orbital ID 00358 { AtomRep::LINETHICKNESS, 0}, // draw only isosurface by default 00359 { AtomRep::BONDRES, 0}, // use solid method by default 00360 { AtomRep::GRIDSPACING, 0.075f}, // default orbital grid spacing 00361 { AtomRep::ISOLINETHICKNESS, 1}, // lines are thickness one by default 00362 { AtomRep::WAVEFNCTYPE, 0}, // default wavefunction type 00363 { AtomRep::WAVEFNCSPIN, 0}, // default wavefunction spin 00364 { AtomRep::WAVEFNCEXCITATION, 0}, // default wavefunction excitation 00365 { AtomRep::ISOSTEPSIZE, 1}, // use step size of one by default 00366 UNUSED, UNUSED, UNUSED, UNUSED, UNUSED } 00367 }, 00368 00369 // Beads 00370 { "Beads", 2, { 00371 { AtomRep::SPHERERAD, 1.0f}, 00372 { AtomRep::SPHERERES, DEF_SPH_RES }, 00373 UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, 00374 UNUSED, UNUSED, UNUSED } 00375 }, 00376 00377 // Dotted 00378 { "Dotted", 2, { 00379 { AtomRep::SPHERERAD, 1.0f}, 00380 { AtomRep::SPHERERES, DEF_SPH_RES}, 00381 UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, 00382 UNUSED, UNUSED, UNUSED } 00383 }, 00384 00385 // Dot surface 00386 { "Solvent", 3, { 00387 { AtomRep::SPHERERAD, 0 }, // probe 00388 // the max value is set in the constructor for AtomRep, so don't 00389 // change things around too much! 00390 { AtomRep::SPHERERES, 7.0f}, // detail 00391 { AtomRep::LINETHICKNESS, 1.0f }, // method 00392 UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, 00393 UNUSED, UNUSED, UNUSED } 00394 #ifdef VMDLATTICECUBES 00395 }, 00396 00397 // LatticeCubes 00398 { "LatticeCubes", 1, { 00399 { AtomRep::SPHERERAD, 1.0f}, 00400 UNUSED, 00401 UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, 00402 UNUSED, UNUSED, UNUSED } 00403 } 00404 #else 00405 } 00406 #endif 00407 00408 }; 00409 00410 00412 // constructor; parse string and see if OK 00413 AtomRep::AtomRep(void) { 00414 int i, j; 00415 00416 // initialize variables 00417 repMethod = DEFAULT_ATOMREP; 00418 repData = repDataStorage[repMethod]; 00419 strcpy(cmdStr, AtomRepInfo[repMethod].name); 00420 for(j=0; j < TOTAL; j++) { 00421 memset(repDataStorage[j], 0, MAX_ATOMREP_DATA*sizeof(float)); 00422 for(i=0; i < AtomRepInfo[j].numdata ; i++) 00423 repDataStorage[j][AtomRepInfo[j].repdata[i].index] = 00424 AtomRepInfo[j].repdata[i].defValue; 00425 } 00426 00427 } 00428 00429 AtomRep::~AtomRep(void) { } 00430 00432 // parse the given command, and store results. Return success. 00433 int AtomRep::parse_cmd(const char *newcmd) { 00434 int argc, i, j; 00435 char *argv[256], *cmdStrTok = NULL; 00436 00437 // make sure the new command is not too long 00438 if(newcmd && strlen(newcmd) > MAX_ATOMREP_CMD) { 00439 msgErr << "Atom representation string is too long (over "; 00440 msgErr << MAX_ATOMREP_CMD << " characters)." << sendmsg; 00441 return FALSE; 00442 } 00443 00444 // XXX Hack to make the "Off" rep work: alias to "Lines" 00445 if (!strupncmp(newcmd, "off", 3)) newcmd = "Lines"; 00446 00447 // tokenize the command 00448 if(!newcmd || !(cmdStrTok = str_tokenize(newcmd, &argc, argv))) { 00449 // no command; keep current settings 00450 return TRUE; 00451 } 00452 00453 // see if the command matches a representation we know about 00454 for(i=0; i < AtomRep::TOTAL; i++) { 00455 const AtomRepParamStruct *ari = &(AtomRepInfo[i]); 00456 00457 if(!strupncmp(argv[0], ari->name, CMDLEN)) { 00458 // the name matches; make sure we do not have too many arguments 00459 if((argc - 1) > ari->numdata) { 00460 msgErr << "Incorrect atom representation command '" << newcmd << "':"; 00461 msgErr << "\n '" << ari->name << "' only takes " << ari->numdata; 00462 msgErr << " arguments maximum." << sendmsg; 00463 00464 delete [] cmdStrTok; 00465 return FALSE; 00466 } 00467 00468 // indicate that we've changed to a new rep method 00469 repMethod = i; 00470 repData = repDataStorage[i]; 00471 00472 // copy out the data from the command and store it 00473 for(j=1; j < argc; j++) { 00474 // if a '-' is given, do not change that parameter 00475 if(!(argv[j][0] == '-' && argv[j][1] == '0円')) 00476 repData[ari->repdata[j-1].index] = (float) atof(argv[j]); 00477 } 00478 00479 // found a match; break from for loop 00480 break; 00481 } 00482 } 00483 00484 // if i is at the end of the list, we did not find a match 00485 if(i == AtomRep::TOTAL) { 00486 msgErr << "Unknown atom representation command '" << newcmd << "'."; 00487 msgErr << sendmsg; 00488 00489 delete [] cmdStrTok; 00490 return FALSE; 00491 } 00492 00493 // if we are here, everything went OK 00494 strcpy(cmdStr, newcmd); 00495 00496 delete [] cmdStrTok; 00497 return TRUE; 00498 } 00499 00500 00502 00503 // copy contents of another atomrep 00504 AtomRep &AtomRep::operator=(const AtomRep &ar) { 00505 strcpy(cmdStr, ar.cmdStr); 00506 repMethod = ar.repMethod; 00507 repData = repDataStorage[repMethod]; 00508 for(int j=0; j < TOTAL; j++) 00509 for(int i=0; i < MAX_ATOMREP_DATA; i++) 00510 repDataStorage[j][i] = ar.repDataStorage[j][i]; 00511 00512 return *this; 00513 } 00514