Main Page Namespace List Class Hierarchy Alphabetical List Compound List File List Namespace Members Compound Members File Members Related Pages

cmd_animate.C

Go to the documentation of this file.
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: cmd_animate.C,v $
00013 * $Author: johns $ $Locker: $ $State: Exp $
00014 * $Revision: 1.52 $ $Date: 2019年01月17日 21:21:03 $
00015 *
00016 ***************************************************************************
00017 * DESCRIPTION:
00018 * text commands for animation control
00019 ***************************************************************************/
00020 
00021 #include <tcl.h>
00022 #include <ctype.h>
00023 #include "config.h"
00024 #include "VMDApp.h"
00025 #include "MoleculeList.h"
00026 #include "TclCommands.h"
00027 #include "Animation.h"
00028 
00029 static void cmd_animate_usage(Tcl_Interp *interp) {
00030 Tcl_AppendResult(interp,
00031 "usage: animate <command> [args...]"
00032 "animate styles\n"
00033 "animate style [once|rock|loop]\n"
00034 "animate dup [|frame <number>] <molecule id>\n"
00035 "animate goto [start|end|<num]\n"
00036 "animate [reverse|rev|forward|for|prev|next|pause]\n"
00037 "animate [speed|skip] [|<value>]\n"
00038 "animate delete all\n"
00039 "animate delete [|beg <num>] [|end <num>] [|skip <num>] <molecule id>\n"
00040 "animate [read|write] <file type> <filename>\n"
00041 " [|beg <num>] [|end <num>] [|skip <num>] [|waitfor <num/all>]\n"
00042 " [|sel <atom selection>] [|<molecule id>]",
00043 NULL);
00044 }
00045 
00046 int text_cmd_animate(ClientData cd, Tcl_Interp *interp, int argc, 
00047 const char *argv[]) {
00048 
00049 VMDApp *app = (VMDApp *)cd;
00050 
00051 // since I cannot easily add this to the rest of the code, I put
00052 // new code here:
00053 if (argc == 1) {
00054 cmd_animate_usage(interp);
00055 }
00056 
00057 if (argc == 2) {
00058 if (!strupncmp(argv[1], "styles", CMDLEN)) {
00059 // enumerate the styles 
00060 size_t loop = 0;
00061 while(loop < sizeof(animationStyleName) / sizeof(char*)) {
00062 Tcl_AppendElement(interp, animationStyleName[loop++]);
00063 }
00064 return TCL_OK;
00065 }
00066 if (!strupncmp(argv[1], "skip", CMDLEN)) {
00067 Tcl_SetObjResult(interp, Tcl_NewIntObj(app->anim->skip()));
00068 return TCL_OK;
00069 }
00070 if (!strupncmp(argv[1], "speed", CMDLEN)) {
00071 Tcl_SetObjResult(interp, Tcl_NewDoubleObj(app->anim->speed()));
00072 return TCL_OK;
00073 }
00074 if (!strupncmp(argv[1], "style", CMDLEN)) {
00075 int style = app->anim->anim_style();
00076 Tcl_AppendElement(interp, animationStyleName[style]);
00077 return TCL_OK;
00078 }
00079 // fall through and let the rest of the code catch the other 2 word cmds
00080 }
00081 
00082 if ((argc == 3 || argc == 5) && !strupncmp(argv[1], "dup", CMDLEN)) {
00083 // option is: animate dup [frame <number>] <molecule id>
00084 // default frame is "now"
00085 // It adds a new animation frame to the molecule, which is a copy of
00086 // the given frame. If there is no frame, {0, 0, 0} is added.
00087 int frame = -1;
00088 int molid = -1;
00089 // get frame number
00090 if (argc == 3) {
00091 if (!strcmp(argv[2], "top")) {
00092 if (app->moleculeList -> top()) {
00093 molid = app->moleculeList -> top() -> id();
00094 } else {
00095 molid = -1;
00096 } 
00097 } else if (Tcl_GetInt(interp, argv[2], &molid) != TCL_OK) {
00098 Tcl_AppendResult(interp, " in animate dup", NULL);
00099 return TCL_ERROR;
00100 }
00101 
00102 } else {
00103 if (strcmp(argv[2], "frame")) {
00104 // error
00105 Tcl_AppendResult(interp,
00106 "format is: animate dup [frame <number>] <molecule id>", NULL);
00107 return TCL_ERROR;
00108 }
00109 if (!strcmp(argv[3], "now")) { // check special cases
00110 frame = -1;
00111 } else if (!strcmp(argv[3], "null")) {
00112 frame = -2;
00113 } else {
00114 if (Tcl_GetInt(interp, argv[3], &frame) != TCL_OK) {
00115 Tcl_AppendResult(interp, " in animate dup frame", NULL);
00116 return TCL_ERROR;
00117 }
00118 }
00119 if (Tcl_GetInt(interp, argv[4], &molid) != TCL_OK) {
00120 Tcl_AppendResult(interp, " in animate dup", NULL);
00121 return TCL_ERROR;
00122 }
00123 }
00124 if (!app->molecule_dupframe(molid, frame)) return TCL_ERROR;
00125 return TCL_OK;
00126 }
00127 
00128 
00129 if (argc == 2) {
00130 Animation::AnimDir newDir;
00131 if(!strupncmp(argv[1], "reverse", CMDLEN) ||
00132 !strupncmp(argv[1], "rev", CMDLEN))
00133 newDir = Animation::ANIM_REVERSE;
00134 else if(!strupncmp(argv[1], "forward", CMDLEN) ||
00135 !strupncmp(argv[1], "for", CMDLEN))
00136 newDir = Animation::ANIM_FORWARD;
00137 else if(!strupncmp(argv[1], "prev", CMDLEN))
00138 newDir = Animation::ANIM_REVERSE1;
00139 else if(!strupncmp(argv[1], "next", CMDLEN))
00140 newDir = Animation::ANIM_FORWARD1;
00141 else if(!strupncmp(argv[1], "pause", CMDLEN))
00142 newDir = Animation::ANIM_PAUSE;
00143 else {
00144 cmd_animate_usage(interp);
00145 return TCL_ERROR; // error
00146 }
00147 app->animation_set_dir(newDir);
00148 } else if(argc == 3) {
00149 if(!strupncmp(argv[1], "skip", CMDLEN)) {
00150 int tmp;
00151 if (Tcl_GetInt(interp, argv[2], &tmp) != TCL_OK) {
00152 Tcl_AppendResult(interp, " in animate skip", NULL);
00153 return TCL_ERROR;
00154 }
00155 app->animation_set_stride(tmp);
00156 } else if(!strupncmp(argv[1], "delete", CMDLEN)) {
00157 if(!strupncmp(argv[2], "all", CMDLEN)) {
00158 int molid = app->molecule_top();
00159 int last = app->molecule_numframes(molid)-1;
00160 int rc = app->molecule_deleteframes(molid, 0, last, -1);
00161 return rc ? TCL_OK : TCL_ERROR;
00162 } else {
00163 cmd_animate_usage(interp);
00164 return TCL_ERROR; // error
00165 }
00166 } else if(!strupncmp(argv[1], "speed", CMDLEN))
00167 app->animation_set_speed((float) atof(argv[2]));
00168 else if(!strupncmp(argv[1], "style", CMDLEN)) {
00169 int newStyle = Animation::ANIM_ONCE;
00170 Animation::AnimStyle enumVal;
00171 while(newStyle < Animation::ANIM_TOTAL_STYLES) {
00172 if(!strupncmp(argv[2], animationStyleName[newStyle], CMDLEN))
00173 break;
00174 newStyle++;
00175 }
00176 if(newStyle == Animation::ANIM_ONCE)
00177 enumVal = Animation::ANIM_ONCE;
00178 else if(newStyle == Animation::ANIM_ROCK)
00179 enumVal = Animation::ANIM_ROCK;
00180 else if(newStyle == Animation::ANIM_LOOP)
00181 enumVal = Animation::ANIM_LOOP;
00182 else {
00183 Tcl_AppendResult(interp, 
00184 "Unknown animate style '" ,argv[2] ,"'\n", NULL);
00185 Tcl_AppendResult(interp, "Valid styles are: ", NULL);
00186 newStyle = Animation::ANIM_ONCE;
00187 while(newStyle < Animation::ANIM_TOTAL_STYLES) {
00188 Tcl_AppendElement(interp, animationStyleName[newStyle]); 
00189 newStyle ++;
00190 }
00191 return TCL_ERROR; // error, unknown style
00192 }
00193 app->animation_set_style(enumVal);
00194 } else if(!strupncmp(argv[1], "goto", CMDLEN)) {
00195 int newframe;
00196 if(!strupncmp(argv[2], "start", CMDLEN))
00197 newframe = -1;
00198 else if(!strupncmp(argv[2], "end", CMDLEN))
00199 newframe = -2;
00200 else if(isdigit(argv[2][0]))
00201 newframe = atoi(argv[2]);
00202 else {
00203 Tcl_AppendResult(interp, "Bad goto parameter '" ,argv[2] ,"'\n", NULL);
00204 Tcl_AppendResult(interp, 
00205 "Valid values are a non-negative number, 'start', or 'end'.", NULL);
00206 return TCL_ERROR; // error, bad frame goto command
00207 }
00208 app->animation_set_frame(newframe);
00209 } else {
00210 cmd_animate_usage(interp);
00211 return TCL_ERROR; // 3 option parameter, didn't understand 3rd term
00212 }
00213 } else if(argc >= 4) {
00214 int bf = 0, ef = (-1), fs = 1, mid = (-1);
00215 const char *fileType = NULL; 
00216 const char *fileName = NULL;
00217 int do_action = (-1);
00218 int currarg = 1;
00219 int waitfor = FileSpec::WAIT_BACK;
00220 
00221 // find out what to do first
00222 if(!strupncmp(argv[currarg], "read", CMDLEN)) {
00223 do_action = 0;
00224 } else if(!strupncmp(argv[currarg], "write", CMDLEN)) {
00225 do_action = 1;
00226 waitfor = FileSpec::WAIT_ALL; // waitfor 'all' by default
00227 } else if(!strupncmp(argv[currarg], "delete", CMDLEN)) {
00228 do_action = 2;
00229 fs = -1; // for "delete", fs=1 means do not delete any frames.
00230 } else {
00231 cmd_animate_usage(interp);
00232 return TCL_ERROR;
00233 }
00234 currarg++;
00235 
00236 // if reading or writing, get file type and name
00237 if(do_action == 0 || do_action == 1) {
00238 fileType = argv[currarg++];
00239 fileName = argv[currarg++];
00240 }
00241 
00242 AtomSel *selection = NULL;
00243 ResizeArray<int> volsets;
00244 mid = app->molecule_top();
00245 // find if any beg, end, or skip specifiers
00246 while(currarg < argc) {
00247 if(currarg < (argc - 1)) {
00248 if(!strupncmp(argv[currarg], "beg", CMDLEN)) {
00249 bf = atoi(argv[currarg+1]);
00250 currarg += 2;
00251 } else if(!strupncmp(argv[currarg], "end", CMDLEN)) {
00252 ef = atoi(argv[currarg+1]);
00253 currarg += 2;
00254 } else if(!strupncmp(argv[currarg], "skip", CMDLEN)) {
00255 fs = atoi(argv[currarg+1]);
00256 currarg += 2;
00257 } else if(do_action == 2 && argc == 4 && currarg == 2 &&
00258 !strupncmp(argv[currarg], "all", CMDLEN)) {
00259 if (strcmp(argv[currarg+1], "top"))
00260 mid = atoi(argv[currarg+1]);
00261 else
00262 mid = app->molecule_top();
00263 currarg += 2;
00264 } else if ((do_action == 0 || do_action == 1) && 
00265 !strupncmp(argv[currarg], "waitfor", CMDLEN)) {
00266 const char *arg = argv[currarg+1];
00267 if (!strupncmp(arg, "all", CMDLEN))
00268 waitfor = FileSpec::WAIT_ALL;
00269 else
00270 waitfor = atoi(arg);
00271 currarg += 2;
00272 } else if (do_action == 1 && // writing
00273 !strupncmp(argv[currarg], "sel", CMDLEN)) {
00274 // interpret the next argument as an atom selection
00275 const char *selstr = argv[currarg+1];
00276 if (!(selection = tcl_commands_get_sel(interp, selstr))) {
00277 Tcl_AppendResult(interp, "Invalid atom selection ", selstr, NULL);
00278 return TCL_ERROR;
00279 }
00280 currarg += 2;
00281 } else if (do_action == 1 && // writing
00282 !strupncmp(argv[currarg], "volsets", CMDLEN)) {
00283 // interpret the next argument as a list of volsets
00284 const char *volstr = argv[currarg+1];
00285 int nsets;
00286 const char **setstrs;
00287 if (Tcl_SplitList(interp, volstr, &nsets, &setstrs) != TCL_OK) {
00288 Tcl_AppendResult(interp, "Invalid volset argument: ", volstr, NULL);
00289 return TCL_ERROR;
00290 }
00291 for (int i=0; i<nsets; i++) {
00292 int tmp;
00293 if (Tcl_GetInt(interp, setstrs[i], &tmp) != TCL_OK) {
00294 Tcl_Free((char *)setstrs);
00295 return TCL_ERROR;
00296 }
00297 volsets.append(tmp);
00298 }
00299 Tcl_Free((char *)setstrs);
00300 currarg += 2;
00301 } else
00302 return TCL_ERROR;
00303 } else {
00304 // only one item left; it must be the molecule id
00305 if (strcmp(argv[currarg], "top")) {
00306 mid = atoi(argv[currarg++]);
00307 } else {
00308 mid = app->molecule_top();
00309 currarg++;
00310 }
00311 }
00312 }
00313 
00314 // if a selection was given, make sure the molid of the selection matches
00315 // the molid for the write command. This ensures that the number of atoms
00316 // in the selection matches those in the molecule.
00317 if (selection) {
00318 if (mid != selection->molid()) {
00319 Tcl_SetResult(interp, (char *) "ERROR: animate: Molecule in selection must match animation molecule.", TCL_STATIC);
00320 return TCL_ERROR;
00321 }
00322 }
00323 
00324 // do action now
00325 FileSpec spec;
00326 spec.first = bf; 
00327 spec.last = ef; 
00328 spec.stride = fs; 
00329 spec.waitfor = waitfor;
00330 if (do_action == 0) {
00331 int rc = app->molecule_load(mid, fileName, fileType, &spec);
00332 if (rc < 0) return TCL_ERROR;
00333 
00334 } else if (do_action == 1) {
00335 spec.selection = selection ? selection->on : NULL;
00336 if (volsets.num()) {
00337 // make a copy of the setids, since FileSpec frees its setids pointer
00338 spec.nvolsets = volsets.num();
00339 spec.setids = new int[spec.nvolsets];
00340 for (int i=0; i<spec.nvolsets; i++) spec.setids[i] = volsets[i];
00341 }
00342 int numwritten = app->molecule_savetrajectory(mid, fileName, fileType, 
00343 &spec);
00344 if (numwritten < 0) return TCL_ERROR;
00345 Tcl_SetObjResult(interp, Tcl_NewIntObj(numwritten));
00346 
00347 } else if (do_action == 2)
00348 app->molecule_deleteframes(mid, bf, ef, fs);
00349 
00350 else
00351 return TCL_ERROR;
00352 
00353 } else
00354 return TCL_ERROR;
00355 
00356 // if here, everything worked out ok
00357 return TCL_OK;
00358 }
00359 
00360 // read raw bytes into a typestep
00361 // Usage; rawtimestep <molid> <bytearray> -start index -frame whichframe 
00362 // Optional start parameter specifies where in the byte array to start reading
00363 // The array must contain at least (12*numatoms) bytes beginning from start 
00364 // or an error will be returned.
00365 // -frame parameter can be last, current, append, or a valid frame number.
00366 // If 'last' and there are no frames, a new frame will be created.
00367 // If 'current' and there are no frames, error.
00368 // If 'append', always append.
00369 
00370 int cmd_rawtimestep(ClientData cd, Tcl_Interp *interp, int argc,
00371 Tcl_Obj * const objv[]) {
00372 VMDApp *app = (VMDApp *)cd;
00373 Molecule *mol;
00374 Timestep *ts;
00375 int molid=-1, start=0, frame=-1, length, neededLength;
00376 unsigned char *bytes;
00377 
00378 if (argc != 3 && argc != 5 && argc != 7) {
00379 Tcl_WrongNumArgs(interp, 1,objv, 
00380 "<molid> <bytearray> ?-start index? ?-frame whichframe?");
00381 return TCL_ERROR;
00382 }
00383 
00384 // get molid, either "top" or a number.
00385 if (!strcmp(Tcl_GetStringFromObj(objv[1], NULL), "top")) 
00386 molid = app->molecule_top();
00387 else if (Tcl_GetIntFromObj(interp, objv[1], &molid) != TCL_OK)
00388 return TCL_ERROR;
00389 if (!(mol = app->moleculeList->mol_from_id(molid))) {
00390 Tcl_SetResult(interp, (char *) "rawtimestep: invalid molid", TCL_STATIC);
00391 return TCL_ERROR;
00392 }
00393 
00394 // Read raw bytes and get length
00395 if (!(bytes = Tcl_GetByteArrayFromObj(objv[2], &length))) {
00396 Tcl_SetResult(interp, (char *) "rawtimestep: could not read bytearray", TCL_STATIC);
00397 return TCL_ERROR;
00398 }
00399 
00400 // Read optional frame and start otions
00401 for (int iarg=3; iarg<argc; iarg += 2) {
00402 const char *opt = Tcl_GetStringFromObj(objv[iarg], NULL);
00403 if (!strcmp(opt, "-start")) {
00404 if (Tcl_GetIntFromObj(interp, objv[iarg+1], &start) != TCL_OK)
00405 return TCL_ERROR;
00406 } else if (!strcmp(opt, "-frame")) {
00407 // check for "last", "current", "append", otherwise must be numeric and
00408 // in the correct range
00409 const char *strframe = Tcl_GetStringFromObj(objv[iarg+1], NULL);
00410 if (!strcmp(strframe, "last")) {
00411 // allow frame to be -1 if the number of frames is zero, which 
00412 // corresponds to "append".
00413 frame = mol->numframes()-1;
00414 } else if (!strcmp(strframe, "current")) {
00415 frame = mol->frame();
00416 } else if (!strcmp(strframe, "append")) {
00417 frame = -1;
00418 } else {
00419 int tmpframe = -1;
00420 if (Tcl_GetIntFromObj(interp, objv[iarg+1], &tmpframe) != TCL_OK) 
00421 return TCL_ERROR;
00422 if (tmpframe < 0 || tmpframe >= mol->numframes()) {
00423 Tcl_SetResult(interp, (char *) "rawtimestep: invalid frame specified.",
00424 TCL_STATIC);
00425 return TCL_ERROR;
00426 }
00427 frame = tmpframe;
00428 }
00429 } else {
00430 Tcl_SetResult(interp, (char *) "rawtimestep: valid options are -frame and -start",
00431 TCL_STATIC);
00432 return TCL_ERROR;
00433 }
00434 }
00435 
00436 // Check that the size of the byte array and the start option are valid
00437 neededLength = 12L*mol->nAtoms;
00438 if (length-start < neededLength) {
00439 Tcl_SetResult(interp, (char *) "rawtimestep: not enough bytes!", TCL_STATIC);
00440 return TCL_ERROR;
00441 }
00442 
00443 // Get the timestep - either existing or new
00444 ts = (frame < 0) ? new Timestep(mol->nAtoms) 
00445 : mol->get_frame(frame);
00446 if (!ts) {
00447 Tcl_SetResult(interp, (char *) "rawtimestep: Unable to find timestep!", TCL_STATIC);
00448 return TCL_ERROR;
00449 }
00450 memcpy(ts->pos, bytes+start, neededLength);
00451 if (frame < 0) {
00452 mol->append_frame(ts);
00453 } else {
00454 mol->force_recalc(DrawMolItem::MOL_REGEN);
00455 }
00456 return TCL_OK;
00457 }
00458 
00459 
00460 // return timestep as byte array.
00461 // arguments: molid, frame
00462 int cmd_gettimestep(ClientData cd, Tcl_Interp *interp, int argc,
00463 Tcl_Obj * const objv[]) {
00464 if (argc != 3) {
00465 Tcl_WrongNumArgs(interp, 1, objv, "molid frame");
00466 return TCL_ERROR;
00467 }
00468 
00469 VMDApp *app = (VMDApp *)cd;
00470 int molid = -1;
00471 const char *molidstr = Tcl_GetStringFromObj(objv[1], NULL);
00472 if (!strcmp(molidstr, "top")) {
00473 molid = app->molecule_top();
00474 } else if (Tcl_GetIntFromObj(interp, objv[1], &molid) != TCL_OK) {
00475 return TCL_ERROR;
00476 }
00477 
00478 Molecule *mol = app->moleculeList->mol_from_id(molid);
00479 if (!mol) {
00480 Tcl_AppendResult(interp, "Invalid molid: ", molidstr, NULL);
00481 return TCL_ERROR;
00482 }
00483 
00484 int frame;
00485 if (Tcl_GetIntFromObj(interp, objv[2], &frame) != TCL_OK)
00486 return TCL_ERROR;
00487 
00488 if (frame < 0 || frame >= mol->numframes()) {
00489 Tcl_AppendResult(interp, "Invalid frame for molecule ", molidstr, NULL);
00490 return TCL_ERROR;
00491 }
00492 
00493 Timestep *ts = mol->get_frame(frame);
00494 Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(
00495 (const unsigned char *)(ts->pos), // bytes
00496 3L*mol->nAtoms*sizeof(float))); // length
00497 
00498 return TCL_OK;
00499 }
00500 

Generated on Mon Nov 17 02:45:34 2025 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002

AltStyle によって変換されたページ (->オリジナル) /