00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <string.h>
00022 #include <ctype.h>
00023 #include <stdio.h>
00024 #include <stdlib.h>
00025 #include <tcl.h>
00026 #include "config.h"
00027 #include "GeometryList.h"
00028 #include "GeometryMol.h"
00029 #include "utilities.h"
00030 #include "VMDApp.h"
00031
00032 static int find_atom_from_name(Tcl_Interp *interp, const char *str, int *molid,
00033 int *atomid) {
00034
00035
00036
00037 const char *slash = strchr(str, '/');
00038 if (!slash) {
00039 Tcl_AppendResult(interp, "Illegal format: ", str, NULL);
00040 return -1;
00041 }
00042
00043
00044 if (slash == str) {
00045 Tcl_AppendResult(interp, "Missing molecule specification: ", str, NULL);
00046 return -1;
00047 }
00048 if (strlen(slash+1) == 0) {
00049 Tcl_AppendResult(interp, "Missing atom specification: ", str, NULL);
00050 return -1;
00051 }
00052 const char *s;
00053 for (s = str; s < slash; s++) {
00054 if (!isdigit(*s)) {
00055 Tcl_AppendResult(interp, "Illegal molecule specification: ", str, NULL);
00056 return -1;
00057 }
00058 }
00059 for (s = slash+1; *s; s++) {
00060 if (!isdigit(*s)) {
00061 Tcl_AppendResult(interp, "Illegal atom specification: ", str, NULL);
00062 return -1;
00063 }
00064 }
00065
00066
00067 char *buf = new char[slash-str + 1];
00068 strncpy(buf, str, slash-str);
00069 buf[slash-str] = '\0';
00070 *molid = atoi(buf);
00071 *atomid = atoi(slash+1);
00072 return 0;
00073 }
00074
00075
00076 int text_cmd_label(ClientData cd, Tcl_Interp *interp, int argc,
00077 const char *argv[]) {
00078
00079 VMDApp *app = (VMDApp *)cd;
00080
00081 if (argc < 2) {
00082 Tcl_SetResult(interp,
00083 (char *)
00084 "label add [Atoms|Bonds|Angles|Dihedrals] {atoms as <molid>/<atomid>}\n"
00085 "label addspring <molid> <atomid> <atomid> <k>\n"
00086 "label list -- return label categories\n"
00087 "label list <category> -- return id's of labels in given category\n"
00088 "label [show|hide|delete] <category> [index] -- \n\tControl specific label or all labels in category\n"
00089 "label graph <category> <index> -- Return a list of values for the given label\n\tfor all animation frames\n"
00090 "label textsize [<newsize>]\n"
00091 "label textthickness [<newthick>]\n" ,
00092 TCL_STATIC);
00093 return TCL_ERROR;
00094 }
00095 if(!strupncmp(argv[1], "add", CMDLEN)) {
00096 if(argc > 3) {
00097 int n = argc-3;
00098 const char **items = argv+3;
00099 int *molid= new int[n];
00100 int *atmid = new int[n];
00101 int i;
00102 for(i=0; i < n; i++) {
00103 if (find_atom_from_name(interp, items[i], molid+i, atmid+i))
00104 break;
00105 }
00106 int rc = -1;
00107 if(i == n) {
00108 rc = app->label_add(argv[2], argc-3, molid, atmid, NULL, 0.0f, 1);
00109 }
00110 delete [] molid;
00111 delete [] atmid;
00112 if (rc < 0) {
00113 Tcl_AppendResult(interp, "\nUnable to add label.", NULL);
00114 return TCL_ERROR;
00115 }
00116 }
00117 else
00118 return TCL_ERROR;
00119
00120 }
00121 else if(!strupncmp(argv[1],"addspring",CMDLEN)) {
00122 if(argc != 6) {
00123 Tcl_AppendResult(interp, "usage: label addspring <molid> <atomid> <atomid> <k>", NULL);
00124 return TCL_ERROR;
00125 }
00126 int molid[2];
00127 int atomid[2];
00128 float k;
00129 sscanf(argv[2],"%d",molid);
00130 sscanf(argv[3],"%d",atomid);
00131 sscanf(argv[4],"%d",atomid+1);
00132 sscanf(argv[5],"%f",&k);
00133 molid[1]=molid[0];
00134 if (app->label_add("Springs", 2, molid, atomid, NULL, k, 1) < 0) {
00135 Tcl_AppendResult(interp, "Unable to add spring.", NULL);
00136 return TCL_ERROR;
00137 }
00138 }
00139 else if(!strupncmp(argv[1], "list", CMDLEN)) {
00140 if(argc == 3) {
00141 int cat = app->geometryList->geom_list_index(argv[2]);
00142 if (cat < 0) {
00143 Tcl_AppendResult(interp, "graph list category '", argv[2],
00144 "' was not found", NULL);
00145 return TCL_ERROR;
00146 }
00147
00148 GeomListPtr glist = app->geometryList->geom_list(cat);
00149 int gnum = glist->num();
00150 char s[30];
00151 GeometryMol *g;
00152 for (int i=0; i<gnum; i++) {
00153 g = (*glist)[i];
00154 Tcl_AppendResult(interp, i==0 ? "" : " ", "{", NULL);
00155 for (int j=0; j<g->items(); j++) {
00156
00157 sprintf(s, "%d %d", g -> obj_index(j), g -> com_index(j));
00158 Tcl_AppendElement(interp, s);
00159 }
00160
00161 sprintf(s, "%f", g->ok() ? g->calculate() : 0.0);
00162 Tcl_AppendElement(interp, s);
00163 Tcl_AppendElement(interp, g -> displayed() ? "show" : "hide");
00164 Tcl_AppendResult(interp, "}", NULL);
00165 }
00166 return TCL_OK;
00167 }
00168 else if (argc == 2) {
00169
00170 for (int i=0; i<app->geometryList -> num_lists(); i++) {
00171 Tcl_AppendElement(interp, app->geometryList -> geom_list_name(i));
00172 }
00173 return TCL_OK;
00174 } else
00175 return TCL_ERROR;
00176
00177 } else if(!strupncmp(argv[1], "show", CMDLEN) ||
00178 !strupncmp(argv[1], "hide", CMDLEN)) {
00179 int item;
00180 if(argc == 3 || (argc == 4 && !strupncmp(argv[3], "all", CMDLEN)))
00181 item = (-1);
00182 else if(argc == 4) {
00183 if (Tcl_GetInt(interp, argv[3], &item) != TCL_OK) {
00184 Tcl_AppendResult(interp, " in label ", argv[1], NULL);
00185 return TCL_ERROR;
00186 }
00187 } else
00188 return TCL_ERROR;
00189
00190 app->label_show(argv[2], item, !strupncmp(argv[1], "show", CMDLEN));
00191
00192
00193 } else if(!strupncmp(argv[1], "delete", CMDLEN)) {
00194 int item;
00195 if(argc == 3 || (argc == 4 && !strupncmp(argv[3], "all", CMDLEN))) {
00196 item = (-1);
00197 } else if(argc == 4) {
00198 if (Tcl_GetInt(interp, argv[3], &item) != TCL_OK) {
00199 Tcl_AppendResult(interp, " in label ", argv[1], NULL);
00200 return TCL_ERROR;
00201 }
00202 } else {
00203 return TCL_ERROR;
00204 }
00205
00206 app->label_delete(argv[2], item);
00207
00208
00209 } else if(!strupncmp(argv[1], "graph", CMDLEN) && argc > 3) {
00210 int item;
00211 if (Tcl_GetInt(interp, argv[3], &item) != TCL_OK) {
00212 return TCL_ERROR;
00213 };
00214
00215 int cat = app->geometryList->geom_list_index(argv[2]);
00216 if (cat < 0) {
00217 Tcl_AppendResult(interp, "Invalid geometry type: ", argv[2], NULL);
00218 return TCL_ERROR;
00219 }
00220
00221 GeomListPtr glist = app->geometryList -> geom_list(cat);
00222 int gnum = glist -> num();
00223 if (item < 0 || item >= gnum) {
00224 char buf[512];
00225 sprintf(buf, "label %s index %d out of range", argv[2], item);
00226 Tcl_SetResult(interp, buf, TCL_VOLATILE);
00227 return TCL_ERROR;
00228 }
00229
00230 GeometryMol *g = (*glist)[item];
00231 if (!g->has_value()) {
00232 Tcl_AppendResult(interp, "Geometry type ", argv[2], " has no values to graph.", NULL);
00233 return TCL_ERROR;
00234 }
00235 ResizeArray<float> gValues(1024);
00236 if (!g->calculate_all(gValues)) {
00237 Tcl_AppendResult(interp, "label has no value", NULL);
00238 return TCL_ERROR;
00239 }
00240 if (argc > 4) {
00241
00242 const char *filename = argv[4];
00243 FILE *outfile = fopen(filename, "w");
00244 if (!outfile) {
00245 Tcl_AppendResult(interp, "Cannot write graph data to file ",
00246 filename, NULL);
00247 return TCL_ERROR;
00248 }
00249 for (int i=0; i<gValues.num(); i++) {
00250 fprintf(outfile, "%f %f\n", float(i), gValues[i]);
00251 }
00252 fclose(outfile);
00253 } else {
00254 char s[20];
00255 for (int count = 0; count < gValues.num(); count++) {
00256 sprintf(s, "%f", gValues[count]);
00257 Tcl_AppendElement(interp, s);
00258 }
00259 }
00260 } else if (!strupncmp(argv[1], "textsize", CMDLEN)) {
00261 if (argc == 2) {
00262
00263 Tcl_SetObjResult(interp, Tcl_NewDoubleObj(app->label_get_text_size()));
00264 return TCL_OK;
00265 } else if (argc == 3) {
00266
00267 double newsize = 1;
00268 if (Tcl_GetDouble(interp, argv[2], &newsize) != TCL_OK)
00269 return TCL_ERROR;
00270 if (!app->label_set_text_size((float) newsize)) {
00271 Tcl_AppendResult(interp, "label textsize: Unable to set size to ",
00272 argv[2], NULL);
00273 return TCL_ERROR;
00274 }
00275 } else {
00276 Tcl_SetResult(interp, (char *) "label textsize: wrong number of arguments",
00277 TCL_STATIC);
00278 return TCL_ERROR;
00279 }
00280 } else if (!strupncmp(argv[1], "textthickness", CMDLEN)) {
00281 if (argc == 2) {
00282
00283 Tcl_SetObjResult(interp, Tcl_NewDoubleObj(app->label_get_text_thickness()));
00284 return TCL_OK;
00285 } else if (argc == 3) {
00286
00287 double newthick = 1;
00288 if (Tcl_GetDouble(interp, argv[2], &newthick) != TCL_OK)
00289 return TCL_ERROR;
00290 if (!app->label_set_text_thickness((float) newthick)) {
00291 Tcl_AppendResult(interp, "label textthickness: Unable to set thickness to ", argv[2], NULL);
00292 return TCL_ERROR;
00293 }
00294 } else {
00295 Tcl_SetResult(interp, (char *) "label textthickness: wrong number of arguments",
00296 TCL_STATIC);
00297 return TCL_ERROR;
00298 }
00299 } else if (!strupncmp(argv[1], "textoffset", CMDLEN)) {
00300 if (argc == 4) {
00301
00302 const char *geomtype = argv[2];
00303 int geom;
00304 if (Tcl_GetInt(interp, argv[3], &geom) != TCL_OK) return TCL_ERROR;
00305 const float *offset = app->geometryList->getTextOffset(geomtype, geom);
00306 if (!offset) {
00307 Tcl_SetResult(interp, (char *) "label textoffset: Invalid geometry specified", TCL_STATIC);
00308 return TCL_ERROR;
00309 }
00310 Tcl_Obj *result = Tcl_NewListObj(0, NULL);
00311 Tcl_ListObjAppendElement(interp, result, Tcl_NewDoubleObj(offset[0]));
00312 Tcl_ListObjAppendElement(interp, result, Tcl_NewDoubleObj(offset[1]));
00313 Tcl_SetObjResult(interp, result);
00314 } else if (argc == 5) {
00315 const char *geomtype = argv[2];
00316 int geom;
00317 if (Tcl_GetInt(interp, argv[3], &geom) != TCL_OK) return TCL_ERROR;
00318 float x, y;
00319 if (sscanf(argv[4], "%f %f", &x, &y) != 2) {
00320 Tcl_AppendResult(interp, "Could not understand argument to label textoffset:", argv[2], NULL);
00321 return TCL_ERROR;
00322 }
00323 if (!app->label_set_textoffset(geomtype, geom, x, y)) {
00324 Tcl_SetResult(interp, (char *) "label textoffset: Invalid geometry specified", TCL_STATIC);
00325 return TCL_ERROR;
00326 }
00327 } else {
00328 Tcl_SetResult(interp, (char *) "label textoffset: wrong number of arguments",
00329 TCL_STATIC);
00330 return TCL_ERROR;
00331 }
00332 } else if (!strupncmp(argv[1], "textformat", CMDLEN)) {
00333 if (argc == 4) {
00334
00335 const char *geomtype = argv[2];
00336 int geom;
00337 if (Tcl_GetInt(interp, argv[3], &geom) != TCL_OK) return TCL_ERROR;
00338 const char *format = app->geometryList->getTextFormat(geomtype, geom);
00339 if (!format) {
00340 Tcl_SetResult(interp, (char *) "label textformat: Invalid geometry specified", TCL_STATIC);
00341 return TCL_ERROR;
00342 }
00343 Tcl_SetResult(interp, (char *)format, TCL_VOLATILE);
00344 } else if (argc == 5) {
00345 const char *geomtype = argv[2];
00346 int geom;
00347 if (Tcl_GetInt(interp, argv[3], &geom) != TCL_OK) return TCL_ERROR;
00348 if (!app->label_set_textformat(geomtype, geom, argv[4])) {
00349 Tcl_SetResult(interp, (char *) "label textformat failed.", TCL_STATIC);
00350 return TCL_ERROR;
00351 }
00352 } else {
00353 Tcl_SetResult(interp, (char *) "label textformat: wrong number of arguments",
00354 TCL_STATIC);
00355 return TCL_ERROR;
00356 }
00357 }
00358 return TCL_OK;
00359 }