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: TclGraphics.C,v $ 00013 * $Author: johns $ $Locker: $ $State: Exp $ 00014 * $Revision: 1.60 $ $Date: 2020年11月30日 07:09:12 $ 00015 * 00016 *************************************************************************** 00017 * DESCRIPTION: 00018 * Parse the text input into a new graphics element. 00019 * 00020 ***************************************************************************/ 00021 00022 00023 #include <stdlib.h> 00024 #include "VMDApp.h" 00025 #include "Molecule.h" 00026 #include "MoleculeList.h" 00027 #include "MaterialList.h" 00028 #include "tcl.h" 00029 #include "TclCommands.h" // for my own, external function definitions 00030 #include "Scene.h" 00031 #include "MoleculeGraphics.h" 00032 00033 // option 's' needs at least 'n' parameters 00034 #define AT_LEAST(n, s) \ 00035 { \ 00036 if (argc < n) { \ 00037 Tcl_SetResult(interp, \ 00038 (char *) "graphics: " s ": not enough parameters", \ 00039 TCL_STATIC); \ 00040 return TCL_ERROR; \ 00041 } \ 00042 } 00043 00044 // option 's' takes exactly 'n' parameters 00045 #define MUST_HAVE(n, s) \ 00046 { \ 00047 if (argc != n) { \ 00048 Tcl_SetResult(interp, \ 00049 (char *) "graphics: " s ": incorrect number of parameters", \ 00050 TCL_STATIC); \ 00051 return TCL_ERROR; \ 00052 } \ 00053 } 00054 00055 // evaluate data for a triangle 00056 static int tcl_graphics_triangle(MoleculeGraphics *gmol, 00057 int argc, const char *argv[], 00058 Tcl_Interp *interp) 00059 { 00060 // the first three are {x, y, z} coordinates 00061 MUST_HAVE(3, "triangle"); 00062 float vals[9]; 00063 if (tcl_get_vector(argv[0], vals+0, interp) != TCL_OK || 00064 tcl_get_vector(argv[1], vals+3, interp) != TCL_OK || 00065 tcl_get_vector(argv[2], vals+6, interp) != TCL_OK ) { 00066 return TCL_ERROR; 00067 } 00068 00069 // I have a triangle, so add it 00070 char tmpstring[64]; 00071 sprintf(tmpstring, "%d", gmol->add_triangle(vals+0, vals+3, vals+6)); 00072 Tcl_SetResult(interp, tmpstring, TCL_VOLATILE); 00073 return TCL_OK; 00074 } 00075 00076 // a triangle with the normals specified 00077 static int tcl_graphics_trinorm(MoleculeGraphics *gmol, 00078 int argc, const char *argv[], 00079 Tcl_Interp *interp) 00080 { 00081 // the first three are {x, y, z} coordinates 00082 // the next three are {x, y, z} normals 00083 MUST_HAVE(6, "trinorm"); 00084 float vals[19]; 00085 if (tcl_get_vector(argv[0], vals+0, interp) != TCL_OK || 00086 tcl_get_vector(argv[1], vals+3, interp) != TCL_OK || 00087 tcl_get_vector(argv[2], vals+6, interp) != TCL_OK || 00088 tcl_get_vector(argv[3], vals+9, interp) != TCL_OK || 00089 tcl_get_vector(argv[4], vals+12, interp) != TCL_OK || 00090 tcl_get_vector(argv[5], vals+15, interp) != TCL_OK ) { 00091 return TCL_ERROR; 00092 } 00093 00094 // I have a triangle, so add it 00095 char tmpstring[64]; 00096 sprintf(tmpstring, "%d", 00097 gmol->add_trinorm(vals+0, vals+3, vals+6, 00098 vals+9, vals+12, vals+15)); 00099 Tcl_SetResult(interp, tmpstring, TCL_VOLATILE); 00100 return TCL_OK; 00101 } 00102 00103 // a triangle with the normals and colors specified 00104 static int tcl_graphics_tricolor(MoleculeGraphics *gmol, 00105 int argc, const char *argv[], 00106 Tcl_Interp *interp) 00107 { 00108 // the first three are {x, y, z} coordinates 00109 // the next three are {x, y, z} normals 00110 MUST_HAVE(9, "tricolor"); 00111 float vals[19]; 00112 if (tcl_get_vector(argv[0], vals+0, interp) != TCL_OK || 00113 tcl_get_vector(argv[1], vals+3, interp) != TCL_OK || 00114 tcl_get_vector(argv[2], vals+6, interp) != TCL_OK || 00115 tcl_get_vector(argv[3], vals+9, interp) != TCL_OK || 00116 tcl_get_vector(argv[4], vals+12, interp) != TCL_OK || 00117 tcl_get_vector(argv[5], vals+15, interp) != TCL_OK ) { 00118 return TCL_ERROR; 00119 } 00120 int c1, c2, c3; 00121 if (Tcl_GetInt(interp, argv[6], &c1) != TCL_OK || 00122 Tcl_GetInt(interp, argv[7], &c2) != TCL_OK || 00123 Tcl_GetInt(interp, argv[8], &c3) != TCL_OK) { 00124 return TCL_ERROR; 00125 } 00126 00127 // I have a triangle, so add it 00128 char tmpstring[64]; 00129 sprintf(tmpstring, "%d", 00130 gmol->add_tricolor(vals+0, vals+3, vals+6, 00131 vals+9, vals+12, vals+15, c1, c2, c3)); 00132 Tcl_SetResult(interp, tmpstring, TCL_VOLATILE); 00133 return TCL_OK; 00134 } 00135 00136 // a cylinder has endpoints, radius, and resolution 00137 static int tcl_graphics_cylinder(MoleculeGraphics *gmol, 00138 int argc, const char *argv[], 00139 Tcl_Interp *interp) 00140 { 00141 // the first two are {x, y, z} coordinates 00142 AT_LEAST(2, "cylinder"); 00143 float vals[6]; 00144 if (tcl_get_vector(argv[0], vals+0, interp) != TCL_OK || 00145 tcl_get_vector(argv[1], vals+3, interp) != TCL_OK) { 00146 return TCL_ERROR; 00147 } 00148 00149 // get the optional values 00150 double radius = 1.0; 00151 int resolution = 6; 00152 int filled = 0; 00153 argc -= 2; 00154 argv += 2; 00155 if (argc %2) { 00156 Tcl_SetResult(interp, (char *) "graphics: cylinder has wrong number of options", TCL_STATIC); 00157 return TCL_ERROR; 00158 } 00159 while (argc) { 00160 if (!strcmp(argv[0], "radius")) { 00161 if (Tcl_GetDouble(interp, argv[1], &radius) != TCL_OK) { 00162 return TCL_ERROR; 00163 } 00164 if (radius <0) radius = 0; 00165 argc -= 2; 00166 argv += 2; 00167 continue; 00168 } 00169 if (!strcmp(argv[0], "resolution")) { 00170 if (Tcl_GetInt(interp, argv[1], &resolution) != TCL_OK) { 00171 return TCL_ERROR; 00172 } 00173 if (resolution < 0) resolution = 0; 00174 if (resolution > 30) resolution = 30; 00175 argc -= 2; 00176 argv += 2; 00177 continue; 00178 } 00179 if (!strcmp(argv[0], "filled")) { 00180 if (Tcl_GetBoolean(interp, argv[1], &filled) != TCL_OK) { 00181 return TCL_ERROR; 00182 } 00183 argc -= 2; 00184 argv += 2; 00185 continue; 00186 } 00187 // reaching here is an error 00188 Tcl_AppendResult(interp, "graphics: unknown option for cylinder: ", 00189 argv[0], NULL); 00190 return TCL_ERROR; 00191 } 00192 00193 // I have a cylinder, so add it 00194 char tmpstring[64]; 00195 sprintf(tmpstring, "%d", 00196 gmol->add_cylinder(vals+0, vals+3, (float) radius, resolution, filled)); 00197 Tcl_SetResult(interp, tmpstring, TCL_VOLATILE); 00198 return TCL_OK; 00199 } 00200 00201 // only has coordinates 00202 static int tcl_graphics_point(MoleculeGraphics *gmol, 00203 int argc, const char *argv[], 00204 Tcl_Interp *interp) 00205 { 00206 MUST_HAVE(1, "point"); 00207 float vals[3]; 00208 if (tcl_get_vector(argv[0], vals+0, interp) != TCL_OK) { 00209 return TCL_ERROR; 00210 } 00211 00212 // we've got a point, so add it 00213 char tmpstring[64]; 00214 sprintf(tmpstring, "%d", gmol->add_point(vals+0)); 00215 Tcl_SetResult(interp, tmpstring, TCL_VOLATILE); 00216 return TCL_OK; 00217 } 00218 00219 // only has coordinates 00220 static int tcl_graphics_pickpoint(MoleculeGraphics *gmol, 00221 int argc, const char *argv[], 00222 Tcl_Interp *interp) 00223 { 00224 MUST_HAVE(1, "pickpoint"); 00225 float vals[3]; 00226 if (tcl_get_vector(argv[0], vals+0, interp) != TCL_OK) { 00227 return TCL_ERROR; 00228 } 00229 00230 // we've got a point, so add it 00231 char tmpstring[64]; 00232 sprintf(tmpstring, "%d", gmol->add_pickpoint(vals+0)); 00233 Tcl_SetResult(interp, tmpstring, TCL_VOLATILE); 00234 return TCL_OK; 00235 } 00236 00237 00238 // has begin and end points, a "style", and a width 00239 static int tcl_graphics_line(MoleculeGraphics *gmol, 00240 int argc, const char *argv[], 00241 Tcl_Interp *interp) 00242 { 00243 // just need the start and end values 00244 AT_LEAST(2, "line"); 00245 float vals[6]; 00246 if (tcl_get_vector(argv[0], vals+0, interp) != TCL_OK || 00247 tcl_get_vector(argv[1], vals+3, interp) != TCL_OK) { 00248 return TCL_ERROR; 00249 } 00250 // options: 00251 // 'style' is "solid" or "dashed" 00252 // 'width' is 0 .. 255; 00253 int line_style = ::SOLIDLINE; 00254 int width = 1; 00255 argc -= 2; 00256 argv += 2; 00257 if (argc %2) { 00258 Tcl_SetResult(interp, (char *) "graphics: line has wrong number of options", TCL_STATIC); 00259 return TCL_ERROR; 00260 } 00261 while (argc) { 00262 if (!strcmp(argv[0], "style")) { 00263 if (!strcmp(argv[1], "solid")) { 00264 line_style = ::SOLIDLINE; 00265 } else if (!strcmp(argv[1], "dashed")) { 00266 line_style = ::DASHEDLINE; 00267 } else { 00268 Tcl_AppendResult(interp, "graphics: don't understand the line style ", 00269 argv[1], NULL); 00270 return TCL_ERROR; 00271 } 00272 } else if (!strcmp(argv[0], "width")) { 00273 if (Tcl_GetInt(interp, argv[1], &width) != TCL_OK) { 00274 return TCL_ERROR; 00275 } 00276 if (width > 255) width = 255; 00277 if (width < 0) width = 0; 00278 } else { 00279 Tcl_AppendResult(interp, "graphics: don't understand the line option ", 00280 argv[0], NULL); 00281 return TCL_ERROR; 00282 } 00283 argc -= 2; 00284 argv += 2; 00285 } 00286 00287 // otherwise, just draw the line 00288 char tmpstring[64]; 00289 sprintf(tmpstring, "%d", gmol->add_line(vals+0, vals+3, line_style, width)); 00290 Tcl_SetResult(interp, tmpstring, TCL_VOLATILE); 00291 return TCL_OK; 00292 } 00293 00294 // turn them on or off 00295 static int tcl_graphics_materials(MoleculeGraphics *gmol, 00296 int argc, const char *argv[], 00297 Tcl_Interp *interp) 00298 { 00299 MUST_HAVE(1, "materials"); 00300 int val; 00301 if (Tcl_GetBoolean(interp, argv[0], &val) != TCL_OK) { 00302 return TCL_ERROR; 00303 } 00304 00305 // enable/disable materials 00306 char tmpstring[64]; 00307 sprintf(tmpstring, "%d", gmol->use_materials(val)); 00308 Tcl_SetResult(interp, tmpstring, TCL_VOLATILE); 00309 return TCL_OK; 00310 } 00311 00312 // set material for this graphics molecule 00313 static int tcl_graphics_material(MoleculeGraphics *gmol, 00314 int argc, const char *argv[], 00315 Tcl_Interp *interp, MaterialList *mlist) 00316 { 00317 MUST_HAVE(1, "material"); 00318 int val = mlist->material_index(argv[0]); 00319 if (val < 0) { 00320 char tmpstring[1024]; 00321 sprintf(tmpstring, "graphics: invalid material: %s", argv[0]); 00322 Tcl_SetResult(interp, tmpstring, TCL_VOLATILE); 00323 return TCL_ERROR; 00324 } 00325 const Material *mat = mlist->material(val); 00326 char tmpstring[64]; 00327 sprintf(tmpstring, "%d", gmol->use_material(mat)); 00328 Tcl_SetResult(interp, tmpstring, TCL_VOLATILE); 00329 return TCL_OK; 00330 } 00331 00332 // takes: 00333 // a color index 00334 // a color name (like "red") 00335 static int tcl_graphics_color(VMDApp *app, MoleculeGraphics *gmol, 00336 int argc, const char *argv[], 00337 Tcl_Interp *interp) 00338 { 00339 MUST_HAVE(1, "color"); 00340 // is it a valid number? 00341 int id; 00342 Tcl_ResetResult(interp); 00343 if (Tcl_GetInt(interp, argv[0], &id) == TCL_OK) { 00344 // is it valid? 00345 if (id >=0 && id < MAXCOLORS) { 00346 char tmpstring[64]; 00347 sprintf(tmpstring, "%d", gmol->use_color(id)); 00348 Tcl_SetResult(interp, tmpstring, TCL_VOLATILE); 00349 return TCL_OK; 00350 } else { 00351 char tmpstring[64]; 00352 sprintf(tmpstring, "graphics: color index value '%d' out of range", id); 00353 Tcl_SetResult(interp, tmpstring, TCL_VOLATILE); 00354 return TCL_ERROR; 00355 } 00356 } 00357 // is it a color name? 00358 Tcl_ResetResult(interp); 00359 id = app->color_index(argv[0]); 00360 if (id >= 0) { 00361 char tmpstring[64]; 00362 sprintf(tmpstring, "%d", gmol->use_color(id)); 00363 Tcl_SetResult(interp, tmpstring, TCL_VOLATILE); 00364 return TCL_OK; 00365 } 00366 // Otherwise there is a problem 00367 Tcl_AppendResult(interp, "graphics: unknown color: ", argv[0], NULL); 00368 return TCL_ERROR; 00369 } 00370 00371 // cone has base and tip coordinates, width at the base, width at the tip and resolution 00372 static int tcl_graphics_cone(MoleculeGraphics *gmol, 00373 int argc, const char *argv[], 00374 Tcl_Interp *interp) 00375 { 00376 // the first two are {x, y, z} 00377 AT_LEAST(2, "cone"); 00378 float vals[6]; 00379 if (tcl_get_vector(argv[0], vals+0, interp) != TCL_OK || 00380 tcl_get_vector(argv[1], vals+3, interp) != TCL_OK) { 00381 return TCL_ERROR; 00382 } 00383 00384 // get the optional values 00385 double radius = 1.0; 00386 double radius2 = 0.0; 00387 int resolution = 6; 00388 argc -= 2; 00389 argv += 2; 00390 if (argc %2) { 00391 Tcl_SetResult(interp, (char *) "graphics: cone has wrong number of options", TCL_STATIC); 00392 return TCL_ERROR; 00393 } 00394 while (argc) { 00395 if (!strcmp(argv[0], "radius2")) { 00396 if (Tcl_GetDouble(interp, argv[1], &radius2) != TCL_OK) { 00397 return TCL_ERROR; 00398 } 00399 if (radius2 <0) radius2 = 0; 00400 argc -= 2; 00401 argv += 2; 00402 continue; 00403 } 00404 if (!strcmp(argv[0], "radius")) { 00405 if (Tcl_GetDouble(interp, argv[1], &radius) != TCL_OK) { 00406 return TCL_ERROR; 00407 } 00408 if (radius <0) radius = 0; 00409 argc -= 2; 00410 argv += 2; 00411 continue; 00412 } 00413 if (!strcmp(argv[0], "resolution")) { 00414 if (Tcl_GetInt(interp, argv[1], &resolution) != TCL_OK) { 00415 return TCL_ERROR; 00416 } 00417 if (resolution < 0) resolution = 0; 00418 if (resolution > 300) resolution = 300; 00419 argc -= 2; 00420 argv += 2; 00421 continue; 00422 } 00423 00424 // reaching here is an error 00425 Tcl_AppendResult(interp, "graphics: unknown option for cone: ", 00426 argv[0], NULL); 00427 return TCL_ERROR; 00428 } 00429 00430 // I have a cone, so add it 00431 char tmpstring[64]; 00432 sprintf(tmpstring, "%d", 00433 gmol->add_cone(vals+0, vals+3, (float) radius, (float) radius2, resolution)); 00434 Tcl_SetResult(interp, tmpstring, TCL_VOLATILE); 00435 return TCL_OK; 00436 } 00437 00438 00439 // sphere has a center, radius, and resolution 00440 static int tcl_graphics_sphere(MoleculeGraphics *gmol, 00441 int argc, const char *argv[], 00442 Tcl_Interp *interp) 00443 { 00444 // only really need the coordinates 00445 AT_LEAST(1, "sphere"); 00446 float vals[3]; 00447 if (tcl_get_vector(argv[0], vals+0, interp) != TCL_OK) { 00448 return TCL_ERROR; 00449 } 00450 00451 // get the optional values 00452 double radius = 1.0; 00453 int resolution = 6; 00454 argc -= 1; 00455 argv += 1; 00456 if (argc %2) { 00457 Tcl_SetResult(interp, (char *) "graphics: sphere has wrong number of options", TCL_STATIC); 00458 return TCL_ERROR; 00459 } 00460 while (argc) { 00461 if (!strcmp(argv[0], "radius")) { 00462 if (Tcl_GetDouble(interp, argv[1], &radius) != TCL_OK) { 00463 return TCL_ERROR; 00464 } 00465 if (radius <0) radius = 0; 00466 argc -= 2; 00467 argv += 2; 00468 continue; 00469 } 00470 if (!strcmp(argv[0], "resolution")) { 00471 if (Tcl_GetInt(interp, argv[1], &resolution) != TCL_OK) { 00472 return TCL_ERROR; 00473 } 00474 if (resolution < 0) resolution = 0; 00475 if (resolution > 30) resolution = 30; 00476 argc -= 2; 00477 argv += 2; 00478 continue; 00479 } 00480 // reaching here is an error 00481 Tcl_AppendResult(interp, "graphics: unknown option for sphere: ", 00482 argv[0], NULL); 00483 return TCL_ERROR; 00484 } 00485 00486 // I have a sphere, so add it 00487 char tmpstring[64]; 00488 sprintf(tmpstring, "%d", 00489 gmol->add_sphere(vals+0, (float) radius, resolution)); 00490 Tcl_SetResult(interp, tmpstring, TCL_VOLATILE); 00491 return TCL_OK; 00492 } 00493 00494 00495 // text has a start point and a string to display 00496 static int tcl_graphics_text(MoleculeGraphics *gmol, int argc, const char *argv[], 00497 Tcl_Interp *interp) { 00498 // have a vector and some text 00499 AT_LEAST(2, "text"); 00500 float vals[3]; 00501 if (tcl_get_vector(argv[0], vals+0, interp) != TCL_OK) { 00502 return TCL_ERROR; 00503 } 00504 00505 // get the optional size values 00506 const char* string = argv[1]; 00507 double size = 1.0; 00508 double thickness = 1.0; 00509 argc -= 2; 00510 argv += 2; 00511 00512 if (argc % 2) { 00513 Tcl_SetResult(interp, (char *) "graphics: text has wrong number of options", TCL_STATIC); 00514 return TCL_ERROR; 00515 } 00516 00517 while (argc) { 00518 if (!strcmp(argv[0], "size")) { 00519 if (Tcl_GetDouble(interp, argv[1], &size) != TCL_OK) { 00520 return TCL_ERROR; 00521 } 00522 if (size <0) size = 0; 00523 argc -= 2; 00524 argv += 2; 00525 continue; 00526 } 00527 00528 if (!strcmp(argv[0], "thickness")) { 00529 if (Tcl_GetDouble(interp, argv[1], &thickness) != TCL_OK) { 00530 return TCL_ERROR; 00531 } 00532 if (thickness <0) thickness = 0; 00533 argc -= 2; 00534 argv += 2; 00535 continue; 00536 } 00537 00538 // reaching here is an error 00539 Tcl_AppendResult(interp, "graphics: unknown option for text: ", 00540 argv[0], NULL); 00541 return TCL_ERROR; 00542 } 00543 00544 // add the text 00545 char tmpstring[64]; 00546 sprintf(tmpstring, "%d", gmol->add_text(vals+0, string, (float) size, (float) thickness)); 00547 Tcl_SetResult(interp, tmpstring, TCL_VOLATILE); 00548 return TCL_OK; 00549 } 00550 00551 00552 static int tcl_graphics_spheretube(MoleculeGraphics *gmol, int argc, const char *argv[], Tcl_Interp *interp) { 00553 // have a vector and some text 00554 AT_LEAST(2, "spheretube"); 00555 float *coords = NULL; 00556 float *radii = NULL; 00557 float radius = 0.0f; 00558 float *rgb3fv = NULL; 00559 int *colorids = NULL; 00560 int numcoords = 0, numcolors = 0, numcolorids = 0; 00561 int radset = 0, numradii = 0; 00562 int drawtubes = 0; 00563 int res = 8; 00564 00565 if (tcl_get_vecarray(argv[0], numcoords, coords, interp) != TCL_OK) { 00566 delete [] coords; 00567 return TCL_ERROR; 00568 } 00569 00570 // advance to process remaining command arguments 00571 argc -= 1; 00572 argv += 1; 00573 00574 while (argc) { 00575 if (!strcmp(argv[0], "colors")) { 00576 if (tcl_get_vecarray(argv[1], numcolors, rgb3fv, interp) != TCL_OK) { 00577 delete [] coords; 00578 delete [] rgb3fv; 00579 delete [] colorids; 00580 delete [] radii; 00581 return TCL_ERROR; 00582 } 00583 00584 argc -= 2; 00585 argv += 2; 00586 continue; 00587 } 00588 00589 if (!strcmp(argv[0], "colorids")) { 00590 if (tcl_get_intarray(argv[1], numcolorids, colorids, interp) != TCL_OK) { 00591 delete [] coords; 00592 delete [] rgb3fv; 00593 delete [] colorids; 00594 delete [] radii; 00595 return TCL_ERROR; 00596 } 00597 00598 rgb3fv = new float[numcolorids * 3]; 00599 for (int idx=0; idx<numcolorids; idx++) { 00600 int id = colorids[idx]; 00601 // is it valid? 00602 if (id <0 && id >= MAXCOLORS) { 00603 char tmpstring[64]; 00604 sprintf(tmpstring, "graphics spheretubes: color index value '%d' out of range", id); 00605 Tcl_SetResult(interp, tmpstring, TCL_VOLATILE); 00606 return TCL_ERROR; 00607 } 00608 } 00609 00610 argc -= 2; 00611 argv += 2; 00612 continue; 00613 } 00614 00615 if (!strcmp(argv[0], "radii")) { 00616 if (tcl_get_array(argv[1], numradii, radii, interp) != TCL_OK) { 00617 delete [] coords; 00618 delete [] rgb3fv; 00619 delete [] colorids; 00620 delete [] radii; 00621 return TCL_ERROR; 00622 } 00623 radset = 1; // we got some radius information 00624 radius = float(radii[0]); // must set to first radius in case of 1 radii 00625 00626 argc -= 2; 00627 argv += 2; 00628 continue; 00629 } 00630 00631 if (!strcmp(argv[0], "radius")) { 00632 double trad = 0.0; 00633 if (Tcl_GetDouble(interp, argv[1], &trad) != TCL_OK) { 00634 delete [] coords; 00635 delete [] rgb3fv; 00636 delete [] colorids; 00637 delete [] radii; 00638 return TCL_ERROR; 00639 } 00640 if (trad < 0) trad = 0; 00641 numradii = 1; 00642 radset = 1; // we got some radius information 00643 radius = float(trad); 00644 00645 argc -= 2; 00646 argv += 2; 00647 continue; 00648 } 00649 00650 if (!strcmp(argv[0], "drawtubes")) { 00651 if (Tcl_GetInt(interp, argv[1], &drawtubes) != TCL_OK) { 00652 delete [] coords; 00653 delete [] rgb3fv; 00654 delete [] colorids; 00655 delete [] radii; 00656 return TCL_ERROR; 00657 } 00658 argc -= 2; 00659 argv += 2; 00660 continue; 00661 } 00662 00663 if (!strcmp(argv[0], "resolution")) { 00664 if (Tcl_GetInt(interp, argv[1], &res) != TCL_OK) { 00665 delete [] coords; 00666 delete [] rgb3fv; 00667 delete [] colorids; 00668 delete [] radii; 00669 return TCL_ERROR; 00670 } 00671 if (res < 8) res = 8; 00672 argc -= 2; 00673 argv += 2; 00674 continue; 00675 } 00676 00677 // reaching here is an error 00678 Tcl_AppendResult(interp, "graphics: unknown option for spheretube: ", 00679 argv[0], NULL); 00680 00681 delete [] coords; 00682 delete [] rgb3fv; 00683 delete [] colorids; 00684 delete [] radii; 00685 return TCL_ERROR; 00686 } 00687 00688 #if 0 00689 printf("***spheretube: coords %d radii %d drawtubes: %d res %d\n", 00690 numcoords/3, numradii, drawtubes, res); 00691 #endif 00692 00693 if ((numcoords % 3)) { 00694 Tcl_SetResult(interp, (char *) "graphics: illegal spheretube coordinate vector length", TCL_STATIC); 00695 printf("total coordinate components not divible by 3!\n"); 00696 delete [] coords; 00697 delete [] rgb3fv; 00698 delete [] colorids; 00699 delete [] radii; 00700 return TCL_ERROR; 00701 } 00702 if ((numradii > 1) && (numradii != (numcoords/3))) { 00703 Tcl_SetResult(interp, (char *) "graphics: spheretube requires matching count of coords and radii", TCL_STATIC); 00704 delete [] coords; 00705 delete [] rgb3fv; 00706 delete [] colorids; 00707 delete [] radii; 00708 return TCL_ERROR; 00709 } 00710 if ((numcolors > 0 || numcolorids > 0) && 00711 (((numcolors != 0) && (numcolors != numcoords)) || 00712 ((numcolorids != 0) && ((3*numcolorids) != numcoords)))) { 00713 Tcl_SetResult(interp, (char *) "graphics: spheretube requires matching count of coords and colors", TCL_STATIC); 00714 delete [] coords; 00715 delete [] rgb3fv; 00716 delete [] colorids; 00717 delete [] radii; 00718 return TCL_ERROR; 00719 } 00720 if ((!radset)) { 00721 Tcl_SetResult(interp, (char *) "graphics: spheretube requires either radius or radii parameter be set", TCL_STATIC); 00722 delete [] coords; 00723 delete [] rgb3fv; 00724 delete [] colorids; 00725 delete [] radii; 00726 return TCL_ERROR; 00727 } 00728 00729 int colorcnt = 0; 00730 if (numcolors > 0) 00731 colorcnt = numcolors / 3; 00732 if (numcolorids > 0) 00733 colorcnt = numcolorids; 00734 00735 char tmpstring[64]; 00736 int gid = gmol->add_spheretube(numcoords/3, coords, numradii, 00737 (numradii > 1) ? radii : &radius, 00738 colorcnt, rgb3fv, colorids, 00739 drawtubes, res); 00740 sprintf(tmpstring, "%d", gid); 00741 Tcl_SetResult(interp, tmpstring, TCL_VOLATILE); 00742 return TCL_OK; 00743 } 00744 00745 00747 // delete the given id 00748 static int tcl_graphics_delete(MoleculeGraphics *gmol, int argc, const char *argv[], 00749 Tcl_Interp *interp) { 00750 if (argc != 1) { 00751 Tcl_SetResult(interp, (char *) "graphics: delete takes one parameter (either an index or 'all')", TCL_STATIC); 00752 return TCL_ERROR; 00753 } 00754 if (!strcmp(argv[0], "all")) { 00755 gmol->delete_all(); 00756 return TCL_OK; 00757 } 00758 int id; 00759 if (Tcl_GetInt(interp, argv[0], &id) != TCL_OK) { 00760 return TCL_ERROR; 00761 } 00762 gmol->delete_id(id); 00763 return TCL_OK; 00764 } 00765 00766 // delete the given id and have the next element replace this one 00767 static int tcl_graphics_replace(MoleculeGraphics *gmol, int argc, const char *argv[], 00768 Tcl_Interp *interp) { 00769 if (argc != 1) { 00770 Tcl_SetResult(interp, (char *) "graphics: replace takes one parameter, the index", TCL_STATIC); 00771 return TCL_ERROR; 00772 } 00773 int id; 00774 if (Tcl_GetInt(interp, argv[0], &id) != TCL_OK) { 00775 return TCL_ERROR; 00776 } 00777 gmol->replace_id(id); 00778 return TCL_OK; 00779 } 00780 00781 // does a given id exist? 00782 static int tcl_graphics_exists(MoleculeGraphics *gmol, int argc, const char *argv[], 00783 Tcl_Interp *interp) { 00784 if (argc != 1) { 00785 Tcl_SetResult(interp, (char *) "graphics: exists takes one parameter, the index", TCL_STATIC); 00786 return TCL_ERROR; 00787 } 00788 int id; 00789 if (Tcl_GetInt(interp, argv[0], &id) != TCL_OK) { 00790 return TCL_ERROR; 00791 } 00792 00793 char tmpstring[64]; 00794 sprintf(tmpstring, "%d", gmol->index_id(id) != -1); 00795 Tcl_SetResult(interp, tmpstring, TCL_VOLATILE); 00796 return TCL_OK; 00797 } 00798 00799 // return info about the graphics with a given id 00800 static int tcl_graphics_info(MoleculeGraphics *gmol, 00801 int argc, const char *argv[], 00802 Tcl_Interp *interp) 00803 { 00804 if (argc != 1) { 00805 Tcl_SetResult(interp, (char *) "graphics: info takes one parameter, the index", TCL_STATIC); 00806 return TCL_ERROR; 00807 } 00808 int id; 00809 if (Tcl_GetInt(interp, argv[0], &id) != TCL_OK) { 00810 return TCL_ERROR; 00811 } 00812 // since either NULL or a static char * is returned, this will work 00813 Tcl_AppendResult(interp, gmol->info_id(id), NULL); 00814 return TCL_OK; 00815 } 00816 00817 00818 // already parsed the "graphics" and "number" terms, what remains are 00819 // add, delete, info, and list 00820 static int tcl_graphics(VMDApp *app, int molid, int argc, const char *argv[], 00821 Tcl_Interp *interp) 00822 { 00823 // Is this a graphics molecule? 00824 Molecule *mol = app->moleculeList->mol_from_id(molid); 00825 if (mol == NULL) { 00826 Tcl_SetResult(interp, (char *) "graphics: invalid graphics molecule", TCL_STATIC); 00827 return TCL_ERROR; 00828 } 00829 if (argc < 1) { 00830 Tcl_SetResult(interp, (char *) "graphics: not enough parameters", TCL_STATIC); 00831 return TCL_ERROR; 00832 } 00833 MoleculeGraphics *gmol = mol->moleculeGraphics(); 00834 // what am I to do? 00835 if (!strcmp(argv[0], "list")) { 00836 if (argc != 1) { 00837 Tcl_SetResult(interp, (char *) "graphics: list takes no parameters", TCL_STATIC); 00838 return TCL_ERROR; 00839 } 00840 int num = gmol->num_elements(); 00841 for (int i=0; i<num; i++) { 00842 int id = gmol->element_id(i); 00843 if (id >=0) { 00844 char s[16]; 00845 sprintf(s, "%d", id); 00846 Tcl_AppendElement(interp, s); 00847 } 00848 } 00849 return TCL_OK; 00850 } 00851 // all the rest take more than one parameter 00852 if (argc < 2) { 00853 Tcl_SetResult(interp, (char *) "graphics: not enough parameters", TCL_STATIC); 00854 return TCL_ERROR; 00855 } 00856 if (!strcmp(argv[0], "triangle")) { 00857 return tcl_graphics_triangle(gmol, argc-1, argv+1, interp); 00858 } 00859 if (!strcmp(argv[0], "trinorm")) { 00860 return tcl_graphics_trinorm(gmol, argc-1, argv+1, interp); 00861 } 00862 if (!strcmp(argv[0], "tricolor")) { 00863 return tcl_graphics_tricolor(gmol, argc-1, argv+1, interp); 00864 } 00865 if (!strcmp(argv[0], "point")) { 00866 return tcl_graphics_point(gmol, argc-1, argv+1, interp); 00867 } 00868 if (!strcmp(argv[0], "pickpoint")) { 00869 return tcl_graphics_pickpoint(gmol, argc-1, argv+1, interp); 00870 } 00871 if (!strcmp(argv[0], "line")) { 00872 return tcl_graphics_line(gmol, argc-1, argv+1, interp); 00873 } 00874 if (!strcmp(argv[0], "cylinder")) { 00875 return tcl_graphics_cylinder(gmol, argc-1, argv+1, interp); 00876 } 00877 if (!strcmp(argv[0], "cone")) { 00878 return tcl_graphics_cone(gmol, argc-1, argv+1, interp); 00879 } 00880 if (!strcmp(argv[0], "sphere")) { 00881 return tcl_graphics_sphere(gmol, argc-1, argv+1, interp); 00882 } 00883 if (!strcmp(argv[0], "text")) { 00884 return tcl_graphics_text(gmol, argc-1, argv+1, interp); 00885 } 00886 if (!strcmp(argv[0], "spheretube")) { 00887 return tcl_graphics_spheretube(gmol, argc-1, argv+1, interp); 00888 } 00889 if (!strcmp(argv[0], "materials")) { 00890 return tcl_graphics_materials(gmol, argc-1, argv+1, interp); 00891 } 00892 if (!strcmp(argv[0], "material")) { 00893 return tcl_graphics_material(gmol, argc-1, argv+1, interp, 00894 app->materialList); 00895 } 00896 if (!strcmp(argv[0], "color") || !strcmp(argv[1], "colour")) { 00897 return tcl_graphics_color(app, gmol, argc-1, argv+1, interp); 00898 } 00899 if (!strcmp(argv[0], "delete")) { 00900 return tcl_graphics_delete(gmol, argc-1, argv+1, interp); 00901 } 00902 if (!strcmp(argv[0], "exists")) { 00903 return tcl_graphics_exists(gmol, argc-1, argv+1, interp); 00904 } 00905 if (!strcmp(argv[0], "replace")) { 00906 return tcl_graphics_replace(gmol, argc-1, argv+1, interp); 00907 } 00908 if (!strcmp(argv[0], "info")) { 00909 return tcl_graphics_info(gmol, argc-1, argv+1, interp); 00910 } 00911 Tcl_AppendResult(interp, "graphics: don't understand the command: ", 00912 argv[0], NULL); 00913 return TCL_ERROR; 00914 } 00915 00916 00917 // interface to the 3d graphics 00918 int graphics_tcl(ClientData cd, Tcl_Interp *interp, int argc, const char *argv[]) { 00919 // need at least two arguments 00920 if (argc < 2) { 00921 Tcl_SetResult(interp, (char *) "graphics: not enough parameters", TCL_STATIC); 00922 return TCL_ERROR; 00923 } 00924 00925 VMDApp *app = (VMDApp *)cd; 00926 // get the molid 00927 int mol = -1; 00928 if (!strcmp(argv[1], "top")) { 00929 if (app->moleculeList->top()) { 00930 mol = app->moleculeList->top()->id(); 00931 } 00932 } else { 00933 if (Tcl_GetInt(interp, argv[1], &mol) != TCL_OK) { 00934 return TCL_ERROR; 00935 } 00936 } 00937 // and call the "real" function 00938 return tcl_graphics(app, mol, argc-2, argv+2, interp); 00939 } 00940 00941