Changeset 915 for trunk/vizservers/nanovis/Command.cpp
- Timestamp:
- Mar 4, 2008 4:34:30 PM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/vizservers/nanovis/Command.cpp
r913 r915 24 24 /* 25 25 * TODO: In no particular order... 26 * oConvert to Tcl_CmdObj interface. (done)26 * x Convert to Tcl_CmdObj interface. (done) 27 27 * o Use Tcl command option parser to reduce size of procedures, remove 28 * lots of extra error checking code. 28 * lots of extra error checking code. (almost there) 29 29 * o Convert GetVolumeIndices to GetVolumes. Goal is to remove 30 30 * all references of Nanovis::volume[] from this file. Don't 31 * want to know how volumes are stored. Same for heightmaps. 31 * want to know how volumes are stored. Same for heightmaps. 32 32 * o Rationalize volume id scheme. Right now it's the index in 33 33 * the vector. 1) Use a list instead of a vector. 2) carry 34 34 * an id field that's a number that gets incremented each new volume. 35 * o Create R2, matrix, etc. libraries. 35 * x Create R2, matrix, etc. libraries. (done) 36 * o Add bookkeeping for volumes, heightmaps, flows, etc. to track 37 * 1) id # 2) simulation # 3) include/exclude. The include/exclude 38 * is to indicate whether the item should contribute to the overall 39 * limits of the axes. 36 40 */ 37 41 38 42 #define ISO_TEST 1 39 #define PLANE_CMD S043 #define PLANE_CMD 0 40 44 #define __TEST_CODE__ 0 41 45 // FOR testing new functions … … 135 139 static Tcl_ObjCmdProc GridCmd; 136 140 static Tcl_ObjCmdProc LegendCmd; 137 #if PLANE_CMDS 138 static Tcl_ObjCmdProc PlaneEnableCmd; 139 static Tcl_ObjCmdProc PlaneLinkCmd; 140 static Tcl_ObjCmdProc PlaneNewCmd; 141 #if PLANE_CMD 142 static Tcl_ObjCmdProc PlaneCmd; 141 143 #endif 142 144 static Tcl_ObjCmdProc ScreenCmd; … … 272 274 } 273 275 276 277 /* 278 * ----------------------------------------------------------------------- 279 * 280 * CreateHeightMap -- 281 * 282 * Creates a heightmap from the given the data. The format of the data 283 * should be as follows: 284 * 285 * xMin, xMax, xNum, yMin, yMax, yNum, heights... 286 * 287 * xNum and yNum must be integer values, all others are real numbers. 288 * The number of heights must be xNum * yNum; 289 * 290 * ----------------------------------------------------------------------- 291 */ 292 static HeightMap * 293 CreateHeightMap(ClientData clientData, Tcl_Interp *interp, int objc, 294 Tcl_Obj *CONST *objv) 295 { 296 float xMin, yMin, xMax, yMax; 297 int xNum, yNum; 298 299 if (objc != 7) { 300 Tcl_AppendResult(interp, 301 "wrong # of values: should be xMin yMin xMax yMax xNum yNum heights", 302 (char *)NULL); 303 return NULL; 304 } 305 if ((GetFloatFromObj(interp, objv[0], &xMin) != TCL_OK) || 306 (GetFloatFromObj(interp, objv[1], &yMin) != TCL_OK) || 307 (GetFloatFromObj(interp, objv[2], &xMax) != TCL_OK) || 308 (GetFloatFromObj(interp, objv[3], &yMax) != TCL_OK) || 309 (Tcl_GetIntFromObj(interp, objv[4], &xNum) != TCL_OK) || 310 (Tcl_GetIntFromObj(interp, objv[5], &yNum) != TCL_OK)) { 311 return NULL; 312 } 313 int nValues; 314 Tcl_Obj **elem; 315 if (Tcl_ListObjGetElements(interp, objv[6], &nValues, &elem) != TCL_OK) { 316 return NULL; 317 } 318 if ((xNum <= 0) || (yNum <= 0)) { 319 Tcl_AppendResult(interp, "bad number of x or y values", (char *)NULL); 320 return NULL; 321 } 322 if (nValues != (xNum * yNum)) { 323 Tcl_AppendResult(interp, "wrong # of heights", (char *)NULL); 324 return NULL; 325 } 326 327 float *heights; 328 heights = new float[nValues]; 329 if (heights == NULL) { 330 Tcl_AppendResult(interp, "can't allocate array of heights", 331 (char *)NULL); 332 return NULL; 333 } 334 335 int i; 336 for (i = 0; i < nValues; i++) { 337 if (GetFloatFromObj(interp, elem[i], heights + i) != TCL_OK) { 338 delete [] heights; 339 return NULL; 340 } 341 } 342 HeightMap* hMap; 343 hMap = new HeightMap(); 344 hMap->setHeight(xMin, yMin, xMax, yMax, xNum, yNum, heights); 345 hMap->setColorMap(NanoVis::get_transfunc("default")); 346 hMap->setVisible(true); 347 hMap->setLineContourVisible(true); 348 delete [] heights; 349 return hMap; 350 } 351 352 /* 353 * ---------------------------------------------------------------------- 354 * FUNCTION: GetHeightMap 355 * 356 * Used internally to decode a series of volume index values and 357 * store then in the specified vector. If there are no volume index 358 * arguments, this means "all volumes" to most commands, so all 359 * active volume indices are stored in the vector. 360 * 361 * Updates pushes index values into the vector. Returns TCL_OK or 362 * TCL_ERROR to indicate an error. 363 * ---------------------------------------------------------------------- 364 */ 365 static int 366 GetHeightMap(Tcl_Interp *interp, Tcl_Obj *objPtr, HeightMap **hmPtrPtr) 367 { 368 int mapIndex; 369 if (Tcl_GetIntFromObj(interp, objPtr, &mapIndex) != TCL_OK) { 370 return TCL_ERROR; 371 } 372 if ((mapIndex < 0) || (mapIndex >= (int)NanoVis::heightMap.size()) || 373 (NanoVis::heightMap[mapIndex] == NULL)) { 374 Tcl_AppendResult(interp, "invalid heightmap index \"", 375 Tcl_GetString(objPtr), "\"", (char *)NULL); 376 return TCL_ERROR; 377 } 378 *hmPtrPtr = NanoVis::heightMap[mapIndex]; 379 return TCL_OK; 380 } 381 382 /* 383 * ---------------------------------------------------------------------- 384 * FUNCTION: GetVolumeIndex 385 * 386 * Used internally to decode a series of volume index values and 387 * store then in the specified vector. If there are no volume index 388 * arguments, this means "all volumes" to most commands, so all 389 * active volume indices are stored in the vector. 390 * 391 * Updates pushes index values into the vector. Returns TCL_OK or 392 * TCL_ERROR to indicate an error. 393 * ---------------------------------------------------------------------- 394 */ 395 static int 396 GetVolumeIndex(Tcl_Interp *interp, Tcl_Obj *objPtr, unsigned int *indexPtr) 397 { 398 int index; 399 if (Tcl_GetIntFromObj(interp, objPtr, &index) != TCL_OK) { 400 return TCL_ERROR; 401 } 402 if (index < 0) { 403 Tcl_AppendResult(interp, "can't have negative index \"", 404 Tcl_GetString(objPtr), "\"", (char*)NULL); 405 return TCL_ERROR; 406 } 407 if (index >= (int)NanoVis::volume.size()) { 408 Tcl_AppendResult(interp, "index \"", Tcl_GetString(objPtr), 409 "\" is out of range", (char*)NULL); 410 return TCL_ERROR; 411 } 412 *indexPtr = (unsigned int)index; 413 return TCL_OK; 414 } 415 416 /* 417 * ---------------------------------------------------------------------- 418 * FUNCTION: GetVolumeFromObj 419 * 420 * Used internally to decode a series of volume index values and 421 * store then in the specified vector. If there are no volume index 422 * arguments, this means "all volumes" to most commands, so all 423 * active volume indices are stored in the vector. 424 * 425 * Updates pushes index values into the vector. Returns TCL_OK or 426 * TCL_ERROR to indicate an error. 427 * ---------------------------------------------------------------------- 428 */ 429 static int 430 GetVolumeFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, Volume **volPtrPtr) 431 { 432 unsigned int index; 433 if (GetVolumeIndex(interp, objPtr, &index) != TCL_OK) { 434 return TCL_ERROR; 435 } 436 Volume *vol; 437 vol = NanoVis::volume[index]; 438 if (vol == NULL) { 439 Tcl_AppendResult(interp, "no volume defined for index \"", 440 Tcl_GetString(objPtr), "\"", (char*)NULL); 441 return TCL_ERROR; 442 } 443 *volPtrPtr = vol; 444 return TCL_OK; 445 } 446 447 /* 448 * ---------------------------------------------------------------------- 449 * FUNCTION: GetVolumeIndices() 450 * 451 * Used internally to decode a series of volume index values and 452 * store then in the specified vector. If there are no volume index 453 * arguments, this means "all volumes" to most commands, so all 454 * active volume indices are stored in the vector. 455 * 456 * Updates pushes index values into the vector. Returns TCL_OK or 457 * TCL_ERROR to indicate an error. 458 * ---------------------------------------------------------------------- 459 */ 460 static int 461 GetVolumeIndices(Tcl_Interp *interp, int objc, Tcl_Obj *CONST *objv, 462 vector<unsigned int>* vectorPtr) 463 { 464 if (objc == 0) { 465 for (unsigned int n = 0; n < NanoVis::volume.size(); n++) { 466 if (NanoVis::volume[n] != NULL) { 467 vectorPtr->push_back(n); 468 } 469 } 470 } else { 471 for (int n = 0; n < objc; n++) { 472 unsigned int index; 473 474 if (GetVolumeIndex(interp, objv[n], &index) != TCL_OK) { 475 return TCL_ERROR; 476 } 477 if (index < NanoVis::volume.size() && NanoVis::volume[index] != NULL) { 478 vectorPtr->push_back(index); 479 } 480 } 481 } 482 return TCL_OK; 483 } 484 485 static int 486 GetIndices(Tcl_Interp *interp, int objc, Tcl_Obj *CONST *objv, 487 vector<unsigned int>* vectorPtr) 488 { 489 for (int n = 0; n < objc; n++) { 490 int index; 491 492 if (Tcl_GetIntFromObj(interp, objv[n], &index) != TCL_OK) { 493 return TCL_ERROR; 494 } 495 if (index < 0) { 496 Tcl_AppendResult(interp, "can't have negative index \"", 497 Tcl_GetString(objv[n]), "\"", (char *)NULL); 498 return TCL_ERROR; 499 } 500 vectorPtr->push_back((unsigned int)index); 501 } 502 return TCL_OK; 503 } 504 505 506 /* 507 * ---------------------------------------------------------------------- 508 * FUNCTION: GetVolumes() 509 * 510 * Used internally to decode a series of volume index values and 511 * store then in the specified vector. If there are no volume index 512 * arguments, this means "all volumes" to most commands, so all 513 * active volume indices are stored in the vector. 514 * 515 * Updates pushes index values into the vector. Returns TCL_OK or 516 * TCL_ERROR to indicate an error. 517 * ---------------------------------------------------------------------- 518 */ 519 static int 520 GetVolumes(Tcl_Interp *interp, int objc, Tcl_Obj *CONST *objv, 521 vector<Volume *>* vectorPtr) 522 { 523 if (objc == 0) { 524 for (unsigned int n = 0; n < NanoVis::volume.size(); n++) { 525 if (NanoVis::volume[n] != NULL) { 526 vectorPtr->push_back(NanoVis::volume[n]); 527 } 528 } 529 } else { 530 for (int n = 0; n < objc; n++) { 531 Volume *volPtr; 532 533 if (GetVolumeFromObj(interp, objv[n], &volPtr) != TCL_OK) { 534 return TCL_ERROR; 535 } 536 if (volPtr != NULL) { 537 vectorPtr->push_back(volPtr); 538 } 539 } 540 } 541 return TCL_OK; 542 } 543 544 545 /* 546 * ---------------------------------------------------------------------- 547 * FUNCTION: GetAxis() 548 * 549 * Used internally to decode an axis value from a string ("x", "y", 550 * or "z") to its index (0, 1, or 2). Returns TCL_OK if successful, 551 * along with a value in valPtr. Otherwise, it returns TCL_ERROR 552 * and an error message in the interpreter. 553 * ---------------------------------------------------------------------- 554 */ 555 static int 556 GetAxis(Tcl_Interp *interp, const char *string, int *indexPtr) 557 { 558 if (string[1] == '\0') { 559 char c; 560 561 c = tolower((unsigned char)string[0]); 562 if (c == 'x') { 563 *indexPtr = 0; 564 return TCL_OK; 565 } else if (c == 'y') { 566 *indexPtr = 1; 567 return TCL_OK; 568 } else if (c == 'z') { 569 *indexPtr = 2; 570 return TCL_OK; 571 } 572 /*FALLTHRU*/ 573 } 574 Tcl_AppendResult(interp, "bad axis \"", string, 575 "\": should be x, y, or z", (char*)NULL); 576 return TCL_ERROR; 577 } 578 579 /* 580 * ---------------------------------------------------------------------- 581 * FUNCTION: GetAxisFromObj() 582 * 583 * Used internally to decode an axis value from a string ("x", "y", 584 * or "z") to its index (0, 1, or 2). Returns TCL_OK if successful, 585 * along with a value in indexPtr. Otherwise, it returns TCL_ERROR 586 * and an error message in the interpreter. 587 * ---------------------------------------------------------------------- 588 */ 589 static int 590 GetAxisFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, int *indexPtr) 591 { 592 return GetAxis(interp, Tcl_GetString(objPtr), indexPtr); 593 } 594 595 /* 596 * ---------------------------------------------------------------------- 597 * FUNCTION: GetAxisDirFromObj() 598 * 599 * Used internally to decode an axis value from a string ("x", "y", 600 * or "z") to its index (0, 1, or 2). Returns TCL_OK if successful, 601 * along with a value in indexPtr. Otherwise, it returns TCL_ERROR 602 * and an error message in the interpreter. 603 * ---------------------------------------------------------------------- 604 */ 605 static int 606 GetAxisDirFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, int *indexPtr, int *dirPtr) 607 { 608 char *string = Tcl_GetString(objPtr); 609 610 int sign = 1; 611 if (*string == '-') { 612 sign = -1; 613 string++; 614 } 615 if (GetAxis(interp, string, indexPtr) != TCL_OK) { 616 return TCL_ERROR; 617 } 618 if (dirPtr != NULL) { 619 *dirPtr = sign; 620 } 621 return TCL_OK; 622 } 623 624 /* 625 * ---------------------------------------------------------------------- 626 * FUNCTION: GetColor() 627 * 628 * Used internally to decode a color value from a string ("R G B") 629 * as a list of three numbers 0-1. Returns TCL_OK if successful, 630 * along with RGB values in rgbPtr. Otherwise, it returns TCL_ERROR 631 * and an error message in the interpreter. 632 * ---------------------------------------------------------------------- 633 */ 634 static int 635 GetColor(Tcl_Interp *interp, int objc, Tcl_Obj *CONST *objv, float *rgbPtr) 636 { 637 if (objc < 3) { 638 Tcl_AppendResult(interp, "missing color values\": ", 639 "should list of R G B values 0.0 - 1.0", (char*)NULL); 640 return TCL_ERROR; 641 } 642 if ((GetFloatFromObj(interp, objv[0], rgbPtr + 0) != TCL_OK) || 643 (GetFloatFromObj(interp, objv[1], rgbPtr + 1) != TCL_OK) || 644 (GetFloatFromObj(interp, objv[2], rgbPtr + 2) != TCL_OK)) { 645 return TCL_ERROR; 646 } 647 return TCL_OK; 648 } 649 650 651 /* 652 * ----------------------------------------------------------------------- 653 * 654 * GetDataStream -- 655 * 656 * Read the requested number of bytes from standard input into the given 657 * buffer. The buffer is then decompressed and decoded. 658 * 659 * ----------------------------------------------------------------------- 660 */ 661 static int 662 GetDataStream(Tcl_Interp *interp, Rappture::Buffer &buf, int nBytes) 663 { 664 char buffer[8096]; 665 666 clearerr(stdin); 667 while (nBytes > 0) { 668 unsigned int chunk; 669 int nRead; 670 671 chunk = (sizeof(buffer) < (unsigned int) nBytes) ? 672 sizeof(buffer) : nBytes; 673 nRead = fread(buffer, sizeof(char), chunk, stdin); 674 if (ferror(stdin)) { 675 Tcl_AppendResult(interp, "while reading data stream: ", 676 Tcl_PosixError(interp), (char*)NULL); 677 return TCL_ERROR; 678 } 679 if (feof(stdin)) { 680 Tcl_AppendResult(interp, "premature EOF while reading data stream", 681 (char*)NULL); 682 return TCL_ERROR; 683 } 684 buf.append(buffer, nRead); 685 nBytes -= nRead; 686 } 687 { 688 Rappture::Outcome err; 689 690 err = Rappture::encoding::decode(buf, RPENC_Z|RPENC_B64|RPENC_HDR); 691 if (err) { 692 printf("ERROR -- DECODING\n"); 693 fflush(stdout); 694 Tcl_AppendResult(interp, err.remark().c_str(), (char*)NULL); 695 return TCL_ERROR; 696 } 697 } 698 return TCL_OK; 699 } 700 701 static int 702 CameraAimOp(ClientData cdata, Tcl_Interp *interp, int objc, Tcl_Obj *CONST *objv) 703 { 704 double x0, y0, z0; 705 if ((Tcl_GetDoubleFromObj(interp, objv[2], &x0) != TCL_OK) || 706 (Tcl_GetDoubleFromObj(interp, objv[3], &y0) != TCL_OK) || 707 (Tcl_GetDoubleFromObj(interp, objv[4], &z0) != TCL_OK)) { 708 return TCL_ERROR; 709 } 710 NanoVis::cam->aim(x0, y0, z0); 711 return TCL_OK; 712 } 713 714 static int 715 CameraAngleOp(ClientData cdata, Tcl_Interp *interp, int objc, Tcl_Obj *CONST *objv) 716 { 717 double xangle, yangle, zangle; 718 if ((Tcl_GetDoubleFromObj(interp, objv[2], &xangle) != TCL_OK) || 719 (Tcl_GetDoubleFromObj(interp, objv[3], &yangle) != TCL_OK) || 720 (Tcl_GetDoubleFromObj(interp, objv[4], &zangle) != TCL_OK)) { 721 return TCL_ERROR; 722 } 723 NanoVis::cam->rotate(xangle, yangle, zangle); 724 return TCL_OK; 725 } 726 727 static int 728 CameraZoomOp(ClientData cdata, Tcl_Interp *interp, int objc, Tcl_Obj *CONST *objv) 729 { 730 double zoom; 731 if (Tcl_GetDoubleFromObj(interp, objv[2], &zoom) != TCL_OK) { 732 return TCL_ERROR; 733 } 734 NanoVis::zoom(zoom); 735 return TCL_OK; 736 } 737 738 static Rappture::CmdSpec cameraOps[] = 739 { 740 {"aim", 2, CameraAimOp, 5, 5, "x y z",}, 741 {"angle", 2, CameraAngleOp, 5, 5, "xAngle yAngle zAngle",}, 742 {"zoom", 1, CameraZoomOp, 3, 3, "factor",}, 743 }; 744 static int nCameraOps = NumCmdSpecs(cameraOps); 745 274 746 /* 275 747 * ---------------------------------------------------------------------- … … 288 760 CameraCmd(ClientData cdata, Tcl_Interp *interp, int objc, Tcl_Obj *CONST *objv) 289 761 { 290 if (objc < 2) { 291 Tcl_AppendResult(interp, "wrong # args: should be \"", 292 Tcl_GetString(objv[0]), " option arg arg...\"", (char*)NULL); 293 return TCL_ERROR; 294 } 295 296 char *string = Tcl_GetString(objv[1]); 297 char c = string[0]; 298 if ((c == 'a') && (strcmp(string, "angle") == 0)) { 299 if (objc != 5) { 300 Tcl_AppendResult(interp, "wrong # args: should be \"", 301 Tcl_GetString(objv[0]), " angle xangle yangle zangle\"", 302 (char*)NULL); 303 return TCL_ERROR; 304 } 305 double xangle, yangle, zangle; 306 if ((Tcl_GetDoubleFromObj(interp, objv[2], &xangle) != TCL_OK) || 307 (Tcl_GetDoubleFromObj(interp, objv[3], &yangle) != TCL_OK) || 308 (Tcl_GetDoubleFromObj(interp, objv[4], &zangle) != TCL_OK)) { 309 return TCL_ERROR; 310 } 311 NanoVis::cam->rotate(xangle, yangle, zangle); 312 } else if ((c == 'a') && (strcmp(string, "aim") == 0)) { 313 if (objc != 5) { 314 Tcl_AppendResult(interp, "wrong # args: should be \"", 315 Tcl_GetString(objv[0]), " aim x y z\"", (char*)NULL); 316 return TCL_ERROR; 317 } 318 double x0, y0, z0; 319 if ((Tcl_GetDoubleFromObj(interp, objv[2], &x0) != TCL_OK) || 320 (Tcl_GetDoubleFromObj(interp, objv[3], &y0) != TCL_OK) || 321 (Tcl_GetDoubleFromObj(interp, objv[4], &z0) != TCL_OK)) { 322 return TCL_ERROR; 323 } 324 NanoVis::cam->aim(x0, y0, z0); 325 } else if ((c == 'z') && (strcmp(string, "zoom") == 0)) { 326 if (objc != 3) { 327 Tcl_AppendResult(interp, "wrong # args: should be \"", 328 Tcl_GetString(objv[0]), " zoom factor\"", (char*)NULL); 329 return TCL_ERROR; 330 } 331 332 double zoom; 333 if (Tcl_GetDoubleFromObj(interp, objv[2], &zoom) != TCL_OK) { 334 return TCL_ERROR; 335 } 336 NanoVis::zoom(zoom); 337 } else { 338 Tcl_AppendResult(interp, "bad camera option \"", string, 339 "\": should be aim, angle, or zoom", (char*)NULL); 340 return TCL_ERROR; 341 } 342 343 /* 344 Trace("Camera pos(%f %f %f), rot(%f %f %f), aim(%f %f %f)\n", 345 NanoVis::cam->location.x, NanoVis::cam->location.y, NanoVis::cam->location.z, 346 NanoVis::cam->angle.x, NanoVis::cam->angle.y, NanoVis::cam->angle.z, 347 NanoVis::cam->target.x, NanoVis::cam->target.y, NanoVis::cam->target.z); 348 349 NanoVis::cam->aim(0, 0, 100); 350 NanoVis::cam->rotate(-51.868206, 88.637497, 0.000000); 351 NanoVis::cam->move(-0.000000, -0.000000, -0.819200); 352 */ 353 354 return TCL_OK; 762 Tcl_ObjCmdProc *proc; 763 764 proc = Rappture::GetOpFromObj(interp, nCameraOps, cameraOps, 765 Rappture::CMDSPEC_ARG1, objc, objv, 0); 766 if (proc == NULL) { 767 return TCL_ERROR; 768 } 769 return (*proc) (cdata, interp, objc, objv); 355 770 } 356 771 … … 390 805 } 391 806 807 static int 808 CutplanePositionOp(ClientData cdata, Tcl_Interp *interp, int objc, 809 Tcl_Obj *CONST *objv) 810 { 811 float relval; 812 if (GetFloatFromObj(interp, objv[2], &relval) != TCL_OK) { 813 return TCL_ERROR; 814 } 815 816 // keep this just inside the volume so it doesn't disappear 817 if (relval < 0.01f) { 818 relval = 0.01f; 819 } else if (relval > 0.99f) { 820 relval = 0.99f; 821 } 822 823 int axis; 824 if (GetAxisFromObj(interp, objv[3], &axis) != TCL_OK) { 825 return TCL_ERROR; 826 } 827 828 vector<Volume *> ivol; 829 if (GetVolumes(interp, objc-4, objv+4, &ivol) != TCL_OK) { 830 return TCL_ERROR; 831 } 832 vector<Volume *>::iterator iter; 833 for (iter = ivol.begin(); iter != ivol.end(); iter++) { 834 (*iter)->move_cutplane(axis, relval); 835 } 836 return TCL_OK; 837 } 838 839 static int 840 CutplaneStateOp(ClientData cdata, Tcl_Interp *interp, int objc, 841 Tcl_Obj *CONST *objv) 842 { 843 int state; 844 if (Tcl_GetBooleanFromObj(interp, objv[2], &state) != TCL_OK) { 845 return TCL_ERROR; 846 } 847 848 int axis; 849 if (GetAxisFromObj(interp, objv[3], &axis) != TCL_OK) { 850 return TCL_ERROR; 851 } 852 853 vector<Volume *> ivol; 854 if (GetVolumes(interp, objc - 4, objv + 4, &ivol) != TCL_OK) { 855 return TCL_ERROR; 856 } 857 if (state) { 858 vector<Volume *>::iterator iter; 859 for (iter = ivol.begin(); iter != ivol.end(); iter++) { 860 (*iter)->enable_cutplane(axis); 861 } 862 } else { 863 vector<Volume *>::iterator iter; 864 for (iter = ivol.begin(); iter != ivol.end(); iter++) { 865 (*iter)->disable_cutplane(axis); 866 } 867 } 868 return TCL_OK; 869 } 870 871 static Rappture::CmdSpec cutplaneOps[] = 872 { 873 {"position", 1, CutplanePositionOp, 4, 4, "bool axis ?indices?",}, 874 {"state", 1, CutplaneStateOp, 4, 0, "relval axis ?indices?",}, 875 }; 876 static int nCutplaneOps = NumCmdSpecs(cutplaneOps); 877 392 878 /* 393 879 * ---------------------------------------------------------------------- … … 408 894 CutplaneCmd(ClientData cdata, Tcl_Interp *interp, int objc, Tcl_Obj *CONST *objv) 409 895 { 410 if (objc < 2) { 411 Tcl_AppendResult(interp, "wrong # args: should be \"", 412 Tcl_GetString(objv[0]), " option ?arg arg...?\"", (char*)NULL); 413 return TCL_ERROR; 414 } 415 416 char *string = Tcl_GetString(objv[1]); 417 char c = string[0]; 418 if ((c == 's') && (strcmp(string, "state") == 0)) { 419 if (objc < 4) { 420 Tcl_AppendResult(interp, "wrong # args: should be \"", 421 Tcl_GetString(objv[0]), " state on|off axis ?volume ...? \"", 422 (char*)NULL); 423 return TCL_ERROR; 424 } 425 426 int state; 427 if (Tcl_GetBooleanFromObj(interp, objv[2], &state) != TCL_OK) { 428 return TCL_ERROR; 429 } 430 431 int axis; 432 if (GetAxisFromObj(interp, objv[3], &axis) != TCL_OK) { 433 return TCL_ERROR; 434 } 435 436 vector<Volume *> ivol; 437 if (GetVolumes(interp, objc - 4, objv + 4, &ivol) != TCL_OK) { 438 return TCL_ERROR; 439 } 440 if (state) { 441 vector<Volume *>::iterator iter; 442 for (iter = ivol.begin(); iter != ivol.end(); iter++) { 443 (*iter)->enable_cutplane(axis); 444 } 445 } else { 446 vector<Volume *>::iterator iter; 447 for (iter = ivol.begin(); iter != ivol.end(); iter++) { 448 (*iter)->disable_cutplane(axis); 449 } 450 } 451 } else if ((c == 'p') && (strcmp(string, "position") == 0)) { 452 if (objc < 4) { 453 Tcl_AppendResult(interp, "wrong # args: should be \"", 454 Tcl_GetString(objv[0]), " position relval axis ?volume ...? \"", 455 (char*)NULL); 456 return TCL_ERROR; 457 } 458 459 float relval; 460 if (GetFloatFromObj(interp, objv[2], &relval) != TCL_OK) { 461 return TCL_ERROR; 462 } 463 464 // keep this just inside the volume so it doesn't disappear 465 if (relval < 0.01f) { 466 relval = 0.01f; 467 } else if (relval > 0.99f) { 468 relval = 0.99f; 469 } 470 471 int axis; 472 if (GetAxisFromObj(interp, objv[3], &axis) != TCL_OK) { 473 return TCL_ERROR; 474 } 475 476 vector<Volume *> ivol; 477 if (GetVolumes(interp, objc-4, objv+4, &ivol) != TCL_OK) { 478 return TCL_ERROR; 479 } 480 vector<Volume *>::iterator iter; 481 for (iter = ivol.begin(); iter != ivol.end(); iter++) { 482 (*iter)->move_cutplane(axis, relval); 483 } 484 } else { 485 Tcl_AppendResult(interp, "bad option \"", string, 486 "\": should be position or state", (char*)NULL); 487 return TCL_ERROR; 488 } 489 return TCL_OK; 896 Tcl_ObjCmdProc *proc; 897 898 proc = Rappture::GetOpFromObj(interp, nCutplaneOps, cutplaneOps, 899 Rappture::CMDSPEC_ARG1, objc, objv, 0); 900 if (proc == NULL) { 901 return TCL_ERROR; 902 } 903 return (*proc) (cdata, interp, objc, objv); 490 904 } 491 905 … … 506 920 if (objc != 4) { 507 921 Tcl_AppendResult(interp, "wrong # args: should be \"", 508 Tcl_GetString(objv[0]), " transfuncwidth height\"", (char*)NULL);922 Tcl_GetString(objv[0]), " volIndex width height\"", (char*)NULL); 509 923 return TCL_ERROR; 510 924 } … … 1783 2197 } 1784 2198 2199 static int 2200 GridAxisColorOp(ClientData cdata, Tcl_Interp *interp, int objc, 2201 Tcl_Obj *CONST *objv) 2202 { 2203 float r, g, b, a; 2204 if ((GetFloatFromObj(interp, objv[2], &r) != TCL_OK) || 2205 (GetFloatFromObj(interp, objv[3], &g) != TCL_OK) || 2206 (GetFloatFromObj(interp, objv[4], &b) != TCL_OK)) { 2207 return TCL_ERROR; 2208 } 2209 a = 1.0f; 2210 if ((objc == 6) && (GetFloatFromObj(interp, objv[5], &a) != TCL_OK)) { 2211 return TCL_ERROR; 2212 } 2213 if (NanoVis::grid) { 2214 NanoVis::grid->setAxisColor(r, g, b, a); 2215 } 2216 return TCL_OK; 2217 } 2218 2219 static int 2220 GridAxisNameOp(ClientData cdata, Tcl_Interp *interp, int objc, 2221 Tcl_Obj *CONST *objv) 2222 { 2223 int axisId; 2224 if (GetAxisFromObj(interp, objv[2], &axisId) != TCL_OK) { 2225 return TCL_ERROR; 2226 } 2227 if (NanoVis::grid) { 2228 NanoVis::grid->setAxisName(axisId, Tcl_GetString(objv[3])); 2229 } 2230 return TCL_OK; 2231 } 2232 2233 static int 2234 GridLineColorOp(ClientData cdata, Tcl_Interp *interp, int objc, 2235 Tcl_Obj *CONST *objv) 2236 { 2237 float r, g, b, a; 2238 if ((GetFloatFromObj(interp, objv[2], &r) != TCL_OK) || 2239 (GetFloatFromObj(interp, objv[3], &g) != TCL_OK) || 2240 (GetFloatFromObj(interp, objv[4], &b) != TCL_OK)) { 2241 return TCL_ERROR; 2242 } 2243 a = 1.0f; 2244 if ((objc == 6) && (GetFloatFromObj(interp, objv[5], &a) != TCL_OK)) { 2245 return TCL_ERROR; 2246 } 2247 if (NanoVis::grid) { 2248 NanoVis::grid->setGridLineColor(r, g, b, a); 2249 } 2250 return TCL_OK; 2251 } 2252 2253 static int 2254 GridLineCountOp(ClientData cdata, Tcl_Interp *interp, int objc, 2255 Tcl_Obj *CONST *objv) 2256 { 2257 int x, y, z; 2258 2259 if ((Tcl_GetIntFromObj(interp, objv[2], &x) != TCL_OK) || 2260 (Tcl_GetIntFromObj(interp, objv[3], &y) != TCL_OK) || 2261 (Tcl_GetIntFromObj(interp, objv[4], &z) != TCL_OK)) { 2262 return TCL_ERROR; 2263 } 2264 if (NanoVis::grid) { 2265 NanoVis::grid->setGridLineCount(x, y, z); 2266 } 2267 return TCL_OK; 2268 } 2269 2270 static int 2271 GridMinMaxOp(ClientData cdata, Tcl_Interp *interp, int objc, 2272 Tcl_Obj *CONST *objv) 2273 { 2274 double x1, y1, z1, x2, y2, z2; 2275 if ((Tcl_GetDoubleFromObj(interp, objv[2], &x1) != TCL_OK) || 2276 (Tcl_GetDoubleFromObj(interp, objv[3], &y1) != TCL_OK) || 2277 (Tcl_GetDoubleFromObj(interp, objv[4], &z1) != TCL_OK) || 2278 (Tcl_GetDoubleFromObj(interp, objv[5], &x2) != TCL_OK) || 2279 (Tcl_GetDoubleFromObj(interp, objv[6], &y2) != TCL_OK) || 2280 (Tcl_GetDoubleFromObj(interp, objv[7], &z2) != TCL_OK)) { 2281 return TCL_ERROR; 2282 } 2283 if (NanoVis::grid) { 2284 NanoVis::grid->setMinMax(Vector3(x1, y1, z1), Vector3(x2, y2, z2)); 2285 } 2286 return TCL_OK; 2287 } 2288 2289 static int 2290 GridVisibleOp(ClientData cdata, Tcl_Interp *interp, int objc, 2291 Tcl_Obj *CONST *objv) 2292 { 2293 int ivisible; 2294 2295 if (Tcl_GetBooleanFromObj(interp, objv[2], &ivisible) != TCL_OK) { 2296 return TCL_ERROR; 2297 } 2298 NanoVis::grid->setVisible((bool)ivisible); 2299 return TCL_OK; 2300 } 2301 2302 static Rappture::CmdSpec gridOps[] = 2303 { 2304 {"axiscolor", 5, GridAxisColorOp, 5, 6, "r g b ?a?",}, 2305 {"axisname", 5, GridAxisNameOp, 5, 5, "index width height",}, 2306 {"linecolor", 7, GridLineColorOp, 5, 6, "r g b ?a?",}, 2307 {"linecount", 7, GridLineCountOp, 5, 5, "xCount yCount zCount",}, 2308 {"minmax", 1, GridMinMaxOp, 8, 8, "xMin yMin zMin xMax yMax zMax",}, 2309 {"visible", 1, GridVisibleOp, 3, 3, "bool",}, 2310 }; 2311 static int nGridOps = NumCmdSpecs(gridOps); 2312 1785 2313 static int 1786 2314 GridCmd(ClientData cdata, Tcl_Interp *interp, int objc, Tcl_Obj *CONST *objv) 1787 { 1788 if (objc < 2) { 1789 Tcl_AppendResult(interp, "wrong # args: should be \"", 1790 Tcl_GetString(objv[0]), " option ?args?", (char *)NULL); 1791 return TCL_ERROR; 1792 } 1793 char *string = Tcl_GetString(objv[1]); 1794 char c = string[0]; 1795 if ((c == 'v') && (strcmp(string,"visible") == 0)) { 1796 int ivisible; 1797 1798 if (Tcl_GetBooleanFromObj(interp, objv[2], &ivisible) != TCL_OK) { 1799 return TCL_ERROR; 1800 } 1801 NanoVis::grid->setVisible((bool)ivisible); 1802 } else if ((c == 'l') && (strcmp(string, "linecount") == 0)) { 1803 int x, y, z; 1804 1805 if ((Tcl_GetIntFromObj(interp, objv[2], &x) != TCL_OK) || 1806 (Tcl_GetIntFromObj(interp, objv[3], &y) != TCL_OK) || 1807 (Tcl_GetIntFromObj(interp, objv[4], &z) != TCL_OK)) { 1808 return TCL_ERROR; 1809 } 1810 if (NanoVis::grid) { 1811 NanoVis::grid->setGridLineCount(x, y, z); 1812 } 1813 } else if ((c == 'a') && (strcmp(string, "axiscolor") == 0)) { 1814 float r, g, b, a; 1815 if ((GetFloatFromObj(interp, objv[2], &r) != TCL_OK) || 1816 (GetFloatFromObj(interp, objv[3], &g) != TCL_OK) || 1817 (GetFloatFromObj(interp, objv[4], &b) != TCL_OK)) { 1818 return TCL_ERROR; 1819 } 1820 a = 1.0f; 1821 if ((objc == 6) && (GetFloatFromObj(interp, objv[5], &a) != TCL_OK)) { 1822 return TCL_ERROR; 1823 } 1824 if (NanoVis::grid) { 1825 NanoVis::grid->setAxisColor(r, g, b, a); 1826 } 1827 } else if ((c == 'l') && (strcmp(string, "linecolor") == 0)) { 1828 float r, g, b, a; 1829 if ((GetFloatFromObj(interp, objv[2], &r) != TCL_OK) || 1830 (GetFloatFromObj(interp, objv[3], &g) != TCL_OK) || 1831 (GetFloatFromObj(interp, objv[4], &b) != TCL_OK)) { 1832 return TCL_ERROR; 1833 } 1834 a = 1.0f; 1835 if ((objc == 6) && (GetFloatFromObj(interp, objv[5], &a) != TCL_OK)) { 1836 return TCL_ERROR; 1837 } 1838 if (NanoVis::grid) { 1839 NanoVis::grid->setGridLineColor(r, g, b, a); 1840 } 1841 } else if ((c == 'm') && (strcmp(string, "minmax") == 0)) { 1842 double x1, y1, z1, x2, y2, z2; 1843 if ((Tcl_GetDoubleFromObj(interp, objv[2], &x1) != TCL_OK) || 1844 (Tcl_GetDoubleFromObj(interp, objv[3], &y1) != TCL_OK) || 1845 (Tcl_GetDoubleFromObj(interp, objv[4], &z1) != TCL_OK) || 1846 (Tcl_GetDoubleFromObj(interp, objv[5], &x2) != TCL_OK) || 1847 (Tcl_GetDoubleFromObj(interp, objv[6], &y2) != TCL_OK) || 1848 (Tcl_GetDoubleFromObj(interp, objv[7], &z2) != TCL_OK)) { 1849 return TCL_ERROR; 1850 } 1851 if (NanoVis::grid) { 1852 NanoVis::grid->setMinMax(Vector3(x1, y1, z1), Vector3(x2, y2, z2)); 1853 } 1854 } else if ((c == 'a') && (strcmp(string, "axisname") == 0)) { 1855 int axisId; 1856 if (GetAxisFromObj(interp, objv[2], &axisId) != TCL_OK) { 1857 return TCL_ERROR; 1858 } 1859 if (NanoVis::grid) { 1860 NanoVis::grid->setAxisName(axisId, Tcl_GetString(objv[3])); 1861 } 1862 } else { 1863 Tcl_AppendResult(interp, "bad option \"", Tcl_GetString(objv[1]), 1864 "\": should be data, outline, shading, or state", 1865 (char*)NULL); 1866 return TCL_ERROR; 1867 } 1868 return TCL_OK; 2315 { 2316 Tcl_ObjCmdProc *proc; 2317 2318 proc = Rappture::GetOpFromObj(interp, nGridOps, gridOps, 2319 Rappture::CMDSPEC_ARG1, objc, objv, 0); 2320 if (proc == NULL) { 2321 return TCL_ERROR; 2322 } 2323 return (*proc) (cdata, interp, objc, objv); 1869 2324 } 1870 2325 … … 1894 2349 } 1895 2350 1896 /* 1897 * ---------------------------------------------------------------------- 1898 * FUNCTION: GetHeightMap 1899 * 1900 * Used internally to decode a series of volume index values and 1901 * store then in the specified vector. If there are no volume index 1902 * arguments, this means "all volumes" to most commands, so all 1903 * active volume indices are stored in the vector. 1904 * 1905 * Updates pushes index values into the vector. Returns TCL_OK or 1906 * TCL_ERROR to indicate an error. 1907 * ---------------------------------------------------------------------- 1908 */ 1909 static int 1910 GetHeightMap(Tcl_Interp *interp, Tcl_Obj *objPtr, HeightMap **hmPtrPtr) 1911 { 1912 int mapIndex; 1913 if (Tcl_GetIntFromObj(interp, objPtr, &mapIndex) != TCL_OK) { 1914 return TCL_ERROR; 1915 } 1916 if ((mapIndex < 0) || (mapIndex >= (int)NanoVis::heightMap.size()) || 1917 (NanoVis::heightMap[mapIndex] == NULL)) { 1918 Tcl_AppendResult(interp, "invalid heightmap index \"", 1919 Tcl_GetString(objPtr), "\"", (char *)NULL); 1920 return TCL_ERROR; 1921 } 1922 *hmPtrPtr = NanoVis::heightMap[mapIndex]; 1923 return TCL_OK; 1924 } 1925 1926 /* 1927 * ---------------------------------------------------------------------- 1928 * FUNCTION: GetVolumeIndex 1929 * 1930 * Used internally to decode a series of volume index values and 1931 * store then in the specified vector. If there are no volume index 1932 * arguments, this means "all volumes" to most commands, so all 1933 * active volume indices are stored in the vector. 1934 * 1935 * Updates pushes index values into the vector. Returns TCL_OK or 1936 * TCL_ERROR to indicate an error. 1937 * ---------------------------------------------------------------------- 1938 */ 1939 static int 1940 GetVolumeIndex(Tcl_Interp *interp, Tcl_Obj *objPtr, unsigned int *indexPtr) 1941 { 1942 int index; 1943 if (Tcl_GetIntFromObj(interp, objPtr, &index) != TCL_OK) { 1944 return TCL_ERROR; 1945 } 1946 if (index < 0) { 1947 Tcl_AppendResult(interp, "can't have negative index \"", 1948 Tcl_GetString(objPtr), "\"", (char*)NULL); 1949 return TCL_ERROR; 1950 } 1951 if (index >= (int)NanoVis::volume.size()) { 1952 Tcl_AppendResult(interp, "index \"", Tcl_GetString(objPtr), 1953 "\" is out of range", (char*)NULL); 1954 return TCL_ERROR; 1955 } 1956 *indexPtr = (unsigned int)index; 1957 return TCL_OK; 1958 } 1959 1960 /* 1961 * ---------------------------------------------------------------------- 1962 * FUNCTION: GetVolumeFromObj 1963 * 1964 * Used internally to decode a series of volume index values and 1965 * store then in the specified vector. If there are no volume index 1966 * arguments, this means "all volumes" to most commands, so all 1967 * active volume indices are stored in the vector. 1968 * 1969 * Updates pushes index values into the vector. Returns TCL_OK or 1970 * TCL_ERROR to indicate an error. 1971 * ---------------------------------------------------------------------- 1972 */ 1973 static int 1974 GetVolumeFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, Volume **volPtrPtr) 1975 { 1976 unsigned int index; 1977 if (GetVolumeIndex(interp, objPtr, &index) != TCL_OK) { 1978 return TCL_ERROR; 1979 } 1980 Volume *vol; 1981 vol = NanoVis::volume[index]; 1982 if (vol == NULL) { 1983 Tcl_AppendResult(interp, "no volume defined for index \"", 1984 Tcl_GetString(objPtr), "\"", (char*)NULL); 1985 return TCL_ERROR; 1986 } 1987 *volPtrPtr = vol; 1988 return TCL_OK; 1989 } 1990 1991 /* 1992 * ---------------------------------------------------------------------- 1993 * FUNCTION: GetVolumeIndices() 1994 * 1995 * Used internally to decode a series of volume index values and 1996 * store then in the specified vector. If there are no volume index 1997 * arguments, this means "all volumes" to most commands, so all 1998 * active volume indices are stored in the vector. 1999 * 2000 * Updates pushes index values into the vector. Returns TCL_OK or 2001 * TCL_ERROR to indicate an error. 2002 * ---------------------------------------------------------------------- 2003 */ 2004 static int 2005 GetVolumeIndices(Tcl_Interp *interp, int objc, Tcl_Obj *CONST *objv, 2006 vector<unsigned int>* vectorPtr) 2007 { 2008 if (objc == 0) { 2009 for (unsigned int n = 0; n < NanoVis::volume.size(); n++) { 2010 if (NanoVis::volume[n] != NULL) { 2011 vectorPtr->push_back(n); 2012 } 2013 } 2014 } else { 2015 for (int n = 0; n < objc; n++) { 2016 unsigned int index; 2017 2018 if (GetVolumeIndex(interp, objv[n], &index) != TCL_OK) { 2019 return TCL_ERROR; 2020 } 2021 if (index < NanoVis::volume.size() && NanoVis::volume[index] != NULL) { 2022 vectorPtr->push_back(index); 2023 } 2024 } 2025 } 2026 return TCL_OK; 2027 } 2028 2029 static int 2030 GetIndices(Tcl_Interp *interp, int objc, Tcl_Obj *CONST *objv, 2031 vector<unsigned int>* vectorPtr) 2032 { 2033 for (int n = 0; n < objc; n++) { 2034 int index; 2035 2036 if (Tcl_GetIntFromObj(interp, objv[n], &index) != TCL_OK) { 2037 return TCL_ERROR; 2038 } 2039 if (index < 0) { 2040 Tcl_AppendResult(interp, "can't have negative index \"", 2041 Tcl_GetString(objv[n]), "\"", (char *)NULL); 2042 return TCL_ERROR; 2043 } 2044 vectorPtr->push_back((unsigned int)index); 2045 } 2046 return TCL_OK; 2047 } 2048 2049 2050 /* 2051 * ---------------------------------------------------------------------- 2052 * FUNCTION: GetVolumes() 2053 * 2054 * Used internally to decode a series of volume index values and 2055 * store then in the specified vector. If there are no volume index 2056 * arguments, this means "all volumes" to most commands, so all 2057 * active volume indices are stored in the vector. 2058 * 2059 * Updates pushes index values into the vector. Returns TCL_OK or 2060 * TCL_ERROR to indicate an error. 2061 * ---------------------------------------------------------------------- 2062 */ 2063 static int 2064 GetVolumes(Tcl_Interp *interp, int objc, Tcl_Obj *CONST *objv, 2065 vector<Volume *>* vectorPtr) 2066 { 2067 if (objc == 0) { 2068 for (unsigned int n = 0; n < NanoVis::volume.size(); n++) { 2069 if (NanoVis::volume[n] != NULL) { 2070 vectorPtr->push_back(NanoVis::volume[n]); 2071 } 2072 } 2073 } else { 2074 for (int n = 0; n < objc; n++) { 2075 Volume *volPtr; 2076 2077 if (GetVolumeFromObj(interp, objv[n], &volPtr) != TCL_OK) { 2078 return TCL_ERROR; 2079 } 2080 if (volPtr != NULL) { 2081 vectorPtr->push_back(volPtr); 2082 } 2083 } 2084 } 2085 return TCL_OK; 2086 } 2087 2088 2089 /* 2090 * ---------------------------------------------------------------------- 2091 * FUNCTION: GetAxis() 2092 * 2093 * Used internally to decode an axis value from a string ("x", "y", 2094 * or "z") to its index (0, 1, or 2). Returns TCL_OK if successful, 2095 * along with a value in valPtr. Otherwise, it returns TCL_ERROR 2096 * and an error message in the interpreter. 2097 * ---------------------------------------------------------------------- 2098 */ 2099 static int 2100 GetAxis(Tcl_Interp *interp, const char *string, int *indexPtr) 2101 { 2102 if (string[1] == '\0') { 2103 char c; 2104 2105 c = tolower((unsigned char)string[0]); 2106 if (c == 'x') { 2107 *indexPtr = 0; 2108 return TCL_OK; 2109 } else if (c == 'y') { 2110 *indexPtr = 1; 2111 return TCL_OK; 2112 } else if (c == 'z') { 2113 *indexPtr = 2; 2114 return TCL_OK; 2115 } 2116 /*FALLTHRU*/ 2117 } 2118 Tcl_AppendResult(interp, "bad axis \"", string, 2119 "\": should be x, y, or z", (char*)NULL); 2120 return TCL_ERROR; 2121 } 2122 2123 2124 /* 2125 * ---------------------------------------------------------------------- 2126 * FUNCTION: GetAxisFromObj() 2127 * 2128 * Used internally to decode an axis value from a string ("x", "y", 2129 * or "z") to its index (0, 1, or 2). Returns TCL_OK if successful, 2130 * along with a value in indexPtr. Otherwise, it returns TCL_ERROR 2131 * and an error message in the interpreter. 2132 * ---------------------------------------------------------------------- 2133 */ 2134 static int 2135 GetAxisFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, int *indexPtr) 2136 { 2137 return GetAxis(interp, Tcl_GetString(objPtr), indexPtr); 2138 } 2139 2140 /* 2141 * ---------------------------------------------------------------------- 2142 * FUNCTION: GetAxisDirFromObj() 2143 * 2144 * Used internally to decode an axis value from a string ("x", "y", 2145 * or "z") to its index (0, 1, or 2). Returns TCL_OK if successful, 2146 * along with a value in indexPtr. Otherwise, it returns TCL_ERROR 2147 * and an error message in the interpreter. 2148 * ---------------------------------------------------------------------- 2149 */ 2150 static int 2151 GetAxisDirFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, int *indexPtr, int *dirPtr) 2152 { 2153 char *string = Tcl_GetString(objPtr); 2154 2155 int sign = 1; 2156 if (*string == '-') { 2157 sign = -1; 2158 string++; 2159 } 2160 if (GetAxis(interp, string, indexPtr) != TCL_OK) { 2161 return TCL_ERROR; 2162 } 2163 if (dirPtr != NULL) { 2164 *dirPtr = sign; 2165 } 2166 return TCL_OK; 2167 } 2168 2169 /* 2170 * ---------------------------------------------------------------------- 2171 * FUNCTION: GetColor() 2172 * 2173 * Used internally to decode a color value from a string ("R G B") 2174 * as a list of three numbers 0-1. Returns TCL_OK if successful, 2175 * along with RGB values in rgbPtr. Otherwise, it returns TCL_ERROR 2176 * and an error message in the interpreter. 2177 * ---------------------------------------------------------------------- 2178 */ 2179 static int 2180 GetColor(Tcl_Interp *interp, int objc, Tcl_Obj *CONST *objv, float *rgbPtr) 2181 { 2182 if (objc < 3) { 2183 Tcl_AppendResult(interp, "missing color values\": ", 2184 "should list of R G B values 0.0 - 1.0", (char*)NULL); 2185 return TCL_ERROR; 2186 } 2187 if ((GetFloatFromObj(interp, objv[0], rgbPtr + 0) != TCL_OK) || 2188 (GetFloatFromObj(interp, objv[1], rgbPtr + 1) != TCL_OK) || 2189 (GetFloatFromObj(interp, objv[2], rgbPtr + 2) != TCL_OK)) { 2190 return TCL_ERROR; 2191 } 2192 return TCL_OK; 2193 } 2194 2195 2196 #if PLANE_CMDS 2351 #if PLANE_CMD 2197 2352 static int 2198 PlaneNew Cmd(ClientData cdata, Tcl_Interp *interp, int objc,2353 PlaneNewOp(ClientData cdata, Tcl_Interp *interp, int objc, 2199 2354 Tcl_Obj *CONST *objv) 2200 2355 { … … 2235 2390 2236 2391 static int 2237 PlaneLink Cmd(ClientData cdata, Tcl_Interp *interp, int objc,2392 PlaneLinkOp(ClientData cdata, Tcl_Interp *interp, int objc, 2238 2393 Tcl_Obj *CONST *objv) 2239 2394 { … … 2260 2415 //The plane_index is the index mantained in the 2D plane renderer 2261 2416 static int 2262 PlaneEnable Cmd(ClientData cdata, Tcl_Interp *interp, int objc,2263 Tcl_Obj *CONST *objv)2417 PlaneEnableOp(ClientData cdata, Tcl_Interp *interp, int objc, 2418 Tcl_Obj *CONST *objv) 2264 2419 { 2265 2420 fprintf(stderr,"enable a plane so the 2D renderer can render it command\n"); … … 2284 2439 return TCL_OK; 2285 2440 } 2286 #endif /*PLANE_CMDS*/ 2441 2442 static Rappture::CmdSpec planeOps[] = 2443 { 2444 {"enable", 1, PlaneEnableOp, 4, 4, "planeIdx mode",}, 2445 {"link", 1, PlaneLinkOp, 4, 4, "planeIdx transfuncIdx",}, 2446 {"new", 1, PlaneNewOp, 5, 5, "planeIdx width height",}, 2447 }; 2448 static int nPlaneOps = NumCmdSpecs(planeOps); 2449 2450 static int 2451 PlaneCmd(ClientData cdata, Tcl_Interp *interp, int objc, Tcl_Obj *CONST *objv) 2452 { 2453 Tcl_ObjCmdProc *proc; 2454 2455 proc = Rappture::GetOpFromObj(interp, nPlaneOps, planeOps, 2456 Rappture::CMDSPEC_ARG1, objc, objv, 0); 2457 if (proc == NULL) { 2458 return TCL_ERROR; 2459 } 2460 return (*proc) (cdata, interp, objc, objv); 2461 } 2462 2463 #endif /*PLANE_CMD*/ 2464 2465 /* 2466 * This command should be Tcl procedure instead of a C command. The reason 2467 * for this that 1) we are using a safe interpreter so we would need a master 2468 * interpreter to load the Tcl environment properly (including our "unirect2d" 2469 * procedure). And 2) the way nanovis is currently deployed doesn't make it 2470 * easy to add new directories for procedures, since it's loaded into /tmp. 2471 * 2472 * Ideally, the "unirect2d" proc would do a rundimentary parsing of the data 2473 * to verify the structure and then pass it to the appropiate Tcl command 2474 * (heightmap, volume, etc). Our C command always creates a heightmap. 2475 */ 2476 static int 2477 UniRect2dCmd(ClientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST *objv) 2478 { 2479 int xNum, yNum, zNum; 2480 float xMin, yMin, xMax, yMax; 2481 float *zValues; 2482 2483 if ((objc & 0x01) == 0) { 2484 Tcl_AppendResult(interp, Tcl_GetString(objv[0]), ": ", 2485 "wrong number of arguments: should be key-value pairs", 2486 (char *)NULL); 2487 return TCL_ERROR; 2488 } 2489 zValues = NULL; 2490 xNum = yNum = zNum = 0; 2491 xMin = yMin = xMax = yMax = 0.0f; 2492 int i; 2493 for (i = 1; i < objc; i += 2) { 2494 char *string; 2495 2496 string = Tcl_GetString(objv[i]); 2497 if (strcmp(string, "xmin") == 0) { 2498 if (GetFloatFromObj(interp, objv[i+1], &xMin) != TCL_OK) { 2499 return TCL_ERROR; 2500 } 2501 } else if (strcmp(string, "xmax") == 0) { 2502 if (GetFloatFromObj(interp, objv[i+1], &xMax) != TCL_OK) { 2503 return TCL_ERROR; 2504 } 2505 } else if (strcmp(string, "xnum") == 0) { 2506 if (Tcl_GetIntFromObj(interp, objv[i+1], &xNum) != TCL_OK) { 2507 return TCL_ERROR; 2508 } 2509 if (xNum <= 0) { 2510 Tcl_AppendResult(interp, "bad xnum value: must be > 0", 2511 (char *)NULL); 2512 return TCL_ERROR; 2513 } 2514 } else if (strcmp(string, "ymin") == 0) { 2515 if (GetFloatFromObj(interp, objv[i+1], &yMin) != TCL_OK) { 2516 return TCL_ERROR; 2517 } 2518 } else if (strcmp(string, "ymax") == 0) { 2519 if (GetFloatFromObj(interp, objv[i+1], &yMax) != TCL_OK) { 2520 return TCL_ERROR; 2521 } 2522 } else if (strcmp(string, "ynum") == 0) { 2523 if (Tcl_GetIntFromObj(interp, objv[i+1], &yNum) != TCL_OK) { 2524 return TCL_ERROR; 2525 } 2526 if (yNum <= 0) { 2527 Tcl_AppendResult(interp, "bad ynum value: must be > 0", 2528 (char *)NULL); 2529 return TCL_ERROR; 2530 } 2531 } else if (strcmp(string, "zvalues") == 0) { 2532 Tcl_Obj **zObj; 2533 2534 if (Tcl_ListObjGetElements(interp, objv[i+1], &zNum, &zObj)!= TCL_OK) { 2535 return TCL_ERROR; 2536 } 2537 int j; 2538 zValues = new float[zNum]; 2539 for (j = 0; j < zNum; j++) { 2540 if (GetFloatFromObj(interp, zObj[j], zValues + j) != TCL_OK) { 2541 return TCL_ERROR; 2542 } 2543 } 2544 } else { 2545 Tcl_AppendResult(interp, "unknown key \"", string, 2546 "\": should be xmin, xmax, xnum, ymin, ymax, ynum, or zvalues", 2547 (char *)NULL); 2548 return TCL_ERROR; 2549 } 2550 } 2551 if (zValues == NULL) { 2552 Tcl_AppendResult(interp, "missing \"zvalues\" key", (char *)NULL); 2553 return TCL_ERROR; 2554 } 2555 if (zNum != (xNum * yNum)) { 2556 Tcl_AppendResult(interp, "wrong number of z values must be xnum*ynum", 2557 (char *)NULL); 2558 return TCL_ERROR; 2559 } 2560 HeightMap* hMap; 2561 hMap = new HeightMap(); 2562 hMap->setHeight(xMin, yMin, xMax, yMax, xNum, yNum, zValues); 2563 hMap->setColorMap(NanoVis::get_transfunc("default")); 2564 hMap->setVisible(true); 2565 hMap->setLineContourVisible(true); 2566 NanoVis::heightMap.push_back(hMap); 2567 delete [] zValues; 2568 return TCL_OK; 2569 } 2570 2287 2571 2288 2572 void … … 2294 2578 Tcl_DStringInit(&cmdbuffer); 2295 2579 2296 // manipulate the viewpoint 2297 Tcl_CreateObjCommand(interp, "camera", CameraCmd, 2298 NULL, (Tcl_CmdDeleteProc*)NULL); 2299 2300 // turn on/off cut planes in x/y/z directions 2301 Tcl_CreateObjCommand(interp, "cutplane", CutplaneCmd, 2302 NULL, (Tcl_CmdDeleteProc*)NULL); 2303 2304 // request the legend for a plot (transfer function) 2305 Tcl_CreateObjCommand(interp, "legend", LegendCmd, 2306 NULL, (Tcl_CmdDeleteProc*)NULL); 2307 2308 // change the size of the screen (size of picture generated) 2309 Tcl_CreateObjCommand(interp, "screen", ScreenCmd, 2310 NULL, (Tcl_CmdDeleteProc*)NULL); 2311 2312 // manipulate transfer functions 2313 Tcl_CreateObjCommand(interp, "transfunc", TransfuncCmd, 2314 NULL, (Tcl_CmdDeleteProc*)NULL); 2315 2316 // set the "up" direction for volumes 2317 Tcl_CreateObjCommand(interp, "up", UpCmd, 2318 NULL, (Tcl_CmdDeleteProc*)NULL); 2319 2320 // manipulate volume data 2321 Tcl_CreateObjCommand(interp, "volume", VolumeCmd, 2322 NULL, (Tcl_CmdDeleteProc*)NULL); 2323 2324 Tcl_CreateObjCommand(interp, "flow", FlowCmd, 2325 NULL, (Tcl_CmdDeleteProc*)NULL); 2326 2327 Tcl_CreateObjCommand(interp, "axis", AxisCmd, 2328 NULL, (Tcl_CmdDeleteProc*)NULL); 2329 2330 Tcl_CreateObjCommand(interp, "grid", GridCmd, 2331 NULL, (Tcl_CmdDeleteProc*)NULL); 2332 2333 Tcl_CreateObjCommand(interp, "heightmap", HeightMapCmd, 2334 NULL, (Tcl_CmdDeleteProc*)NULL); 2335 2336 // get screenshot 2337 Tcl_CreateObjCommand(interp, "screenshot", ScreenShotCmd, 2338 NULL, (Tcl_CmdDeleteProc*)NULL); 2339 2340 Tcl_CreateObjCommand(interp, "unirect2d", UniRect2dCmd, 2341 NULL, (Tcl_CmdDeleteProc*)NULL); 2342 2343 Tcl_CreateObjCommand(interp, "axis", AxisCmd, 2344 NULL, (Tcl_CmdDeleteProc*)NULL); 2345 2346 Tcl_CreateObjCommand(interp, "grid", GridCmd, 2347 NULL, (Tcl_CmdDeleteProc*)NULL); 2348 2349 Tcl_CreateObjCommand(interp, "heightmap", HeightMapCmd, 2350 NULL, (Tcl_CmdDeleteProc*)NULL); 2351 2352 // get screenshot 2353 Tcl_CreateObjCommand(interp, "screenshot", ScreenShotCmd, 2354 NULL, (Tcl_CmdDeleteProc*)NULL); 2355 2356 Tcl_CreateObjCommand(interp, "unirect2d", UniRect2dCmd, 2357 NULL, (Tcl_CmdDeleteProc*)NULL); 2358 2580 Tcl_CreateObjCommand(interp, "axis", AxisCmd, NULL, NULL); 2581 Tcl_CreateObjCommand(interp, "camera", CameraCmd, NULL, NULL); 2582 Tcl_CreateObjCommand(interp, "cutplane", CutplaneCmd, NULL, NULL); 2583 Tcl_CreateObjCommand(interp, "flow", FlowCmd, NULL, NULL); 2584 Tcl_CreateObjCommand(interp, "grid", GridCmd, NULL, NULL); 2585 Tcl_CreateObjCommand(interp, "heightmap", HeightMapCmd, NULL, NULL); 2586 Tcl_CreateObjCommand(interp, "legend", LegendCmd, NULL, NULL); 2587 Tcl_CreateObjCommand(interp, "screen", ScreenCmd, NULL, NULL); 2588 Tcl_CreateObjCommand(interp, "screenshot", ScreenShotCmd, NULL, NULL); 2589 Tcl_CreateObjCommand(interp, "transfunc", TransfuncCmd, NULL, NULL); 2590 Tcl_CreateObjCommand(interp, "unirect2d", UniRect2dCmd, NULL, NULL); 2591 Tcl_CreateObjCommand(interp, "up", UpCmd, NULL, NULL); 2592 Tcl_CreateObjCommand(interp, "volume", VolumeCmd, NULL, NULL); 2359 2593 #if __TEST_CODE__ 2360 Tcl_CreateObjCommand(interp, "test", TestCmd, 2361 NULL, (Tcl_CmdDeleteProc*)NULL); 2362 2363 2364 // Tcl_CreateObjCommand(interp, "flow", FlowCmd, 2365 // NULL, (Tcl_CmdDeleteProc*)NULL); 2594 Tcl_CreateObjCommand(interp, "test", TestCmd, NULL, NULL); 2366 2595 #endif 2367 2596 … … 2388 2617 while (status == TCL_OK) { 2389 2618 // 2390 // Read the next command from the buffer. First time through 2391 // weblock here and wait if necessary until a command comes in.2619 // Read the next command from the buffer. First time through we 2620 // block here and wait if necessary until a command comes in. 2392 2621 // 2393 // BE CAREFUL: Read only one command, up to a newline.2394 // The "volume data follows" command needs to be able to read2395 // the data immediately following the command, and we shouldn't2396 // consume ithere.2622 // BE CAREFUL: Read only one command, up to a newline. The "volume 2623 // data follows" command needs to be able to read the data 2624 // immediately following the command, and we shouldn't consume it 2625 // here. 2397 2626 // 2398 2627 while (1) { … … 2478 2707 #endif 2479 2708 } 2480 2481 2482 /*2483 * -----------------------------------------------------------------------2484 *2485 * GetDataStream --2486 *2487 * Read the requested number of bytes from standard input into the given2488 * buffer. The buffer is then decompressed and decoded.2489 *2490 * -----------------------------------------------------------------------2491 */2492 static int2493 GetDataStream(Tcl_Interp *interp, Rappture::Buffer &buf, int nBytes)2494 {2495 char buffer[8096];2496 2497 clearerr(stdin);2498 while (nBytes > 0) {2499 unsigned int chunk;2500 int nRead;2501 2502 chunk = (sizeof(buffer) < (unsigned int) nBytes) ?2503 sizeof(buffer) : nBytes;2504 nRead = fread(buffer, sizeof(char), chunk, stdin);2505 if (ferror(stdin)) {2506 Tcl_AppendResult(interp, "while reading data stream: ",2507 Tcl_PosixError(interp), (char*)NULL);2508 return TCL_ERROR;2509 }2510 if (feof(stdin)) {2511 Tcl_AppendResult(interp, "premature EOF while reading data stream",2512 (char*)NULL);2513 return TCL_ERROR;2514 }2515 buf.append(buffer, nRead);2516 nBytes -= nRead;2517 }2518 {2519 Rappture::Outcome err;2520 2521 err = Rappture::encoding::decode(buf, RPENC_Z|RPENC_B64|RPENC_HDR);2522 if (err) {2523 printf("ERROR -- DECODING\n");2524 fflush(stdout);2525 Tcl_AppendResult(interp, err.remark().c_str(), (char*)NULL);2526 return TCL_ERROR;2527 }2528 }2529 return TCL_OK;2530 }2531 2532 /*2533 * -----------------------------------------------------------------------2534 *2535 * CreateHeightMap --2536 *2537 * Creates a heightmap from the given the data. The format of the data2538 * should be as follows:2539 *2540 * xMin, xMax, xNum, yMin, yMax, yNum, heights...2541 *2542 * xNum and yNum must be integer values, all others are real numbers.2543 * The number of heights must be xNum * yNum;2544 *2545 * -----------------------------------------------------------------------2546 */2547 static HeightMap *2548 CreateHeightMap(ClientData clientData, Tcl_Interp *interp, int objc,2549 Tcl_Obj *CONST *objv)2550 {2551 float xMin, yMin, xMax, yMax;2552 int xNum, yNum;2553 2554 if (objc != 7) {2555 Tcl_AppendResult(interp,2556 "wrong # of values: should be xMin yMin xMax yMax xNum yNum heights",2557 (char *)NULL);2558 return NULL;2559 }2560 if ((GetFloatFromObj(interp, objv[0], &xMin) != TCL_OK) ||2561 (GetFloatFromObj(interp, objv[1], &yMin) != TCL_OK) ||2562 (GetFloatFromObj(interp, objv[2], &xMax) != TCL_OK) ||2563 (GetFloatFromObj(interp, objv[3], &yMax) != TCL_OK) ||2564 (Tcl_GetIntFromObj(interp, objv[4], &xNum) != TCL_OK) ||2565 (Tcl_GetIntFromObj(interp, objv[5], &yNum) != TCL_OK)) {2566 return NULL;2567 }2568 int nValues;2569 Tcl_Obj **elem;2570 if (Tcl_ListObjGetElements(interp, objv[6], &nValues, &elem) != TCL_OK) {2571 return NULL;2572 }2573 if ((xNum <= 0) || (yNum <= 0)) {2574 Tcl_AppendResult(interp, "bad number of x or y values", (char *)NULL);2575 return NULL;2576 }2577 if (nValues != (xNum * yNum)) {2578 Tcl_AppendResult(interp, "wrong # of heights", (char *)NULL);2579 return NULL;2580 }2581 2582 float *heights;2583 heights = new float[nValues];2584 if (heights == NULL) {2585 Tcl_AppendResult(interp, "can't allocate array of heights",2586 (char *)NULL);2587 return NULL;2588 }2589 2590 int i;2591 for (i = 0; i < nValues; i++) {2592 if (GetFloatFromObj(interp, elem[i], heights + i) != TCL_OK) {2593 delete [] heights;2594 return NULL;2595 }2596 }2597 HeightMap* hMap;2598 hMap = new HeightMap();2599 hMap->setHeight(xMin, yMin, xMax, yMax, xNum, yNum, heights);2600 hMap->setColorMap(NanoVis::get_transfunc("default"));2601 hMap->setVisible(true);2602 hMap->setLineContourVisible(true);2603 delete [] heights;2604 return hMap;2605 }2606 2607 /*2608 * This command should be Tcl procedure instead of a C command. The reason2609 * for this that 1) we are using a safe interpreter so we would need a master2610 * interpreter to load the Tcl environment properly (including our "unirect2d"2611 * procedure). And 2) the way nanovis is currently deployed, doesn't make it2612 * easy to add new directories for procedures, since it's loaded into /tmp.2613 *2614 * Ideally, the "unirect2d" proc would do a rundimentary parsing of the data2615 * to verify the structure and then pass it to the appropiate Tcl command2616 * (heightmap, volume, etc). Our C command always creates a heightmap.2617 */2618 static int2619 UniRect2dCmd(ClientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST *objv)2620 {2621 int xNum, yNum, zNum;2622 float xMin, yMin, xMax, yMax;2623 float *zValues;2624 2625 if ((objc & 0x01) == 0) {2626 Tcl_AppendResult(interp, Tcl_GetString(objv[0]), ": ",2627 "wrong number of arguments: should be key-value pairs",2628 (char *)NULL);2629 return TCL_ERROR;2630 }2631 zValues = NULL;2632 xNum = yNum = zNum = 0;2633 xMin = yMin = xMax = yMax = 0.0f;2634 int i;2635 for (i = 1; i < objc; i += 2) {2636 char *string;2637 2638 string = Tcl_GetString(objv[i]);2639 if (strcmp(string, "xmin") == 0) {2640 if (GetFloatFromObj(interp, objv[i+1], &xMin) != TCL_OK) {2641 return TCL_ERROR;2642 }2643 } else if (strcmp(string, "xmax") == 0) {2644 if (GetFloatFromObj(interp, objv[i+1], &xMax) != TCL_OK) {2645 return TCL_ERROR;2646 }2647 } else if (strcmp(string, "xnum") == 0) {2648 if (Tcl_GetIntFromObj(interp, objv[i+1], &xNum) != TCL_OK) {2649 return TCL_ERROR;2650 }2651 if (xNum <= 0) {2652 Tcl_AppendResult(interp, "bad xnum value: must be > 0",2653 (char *)NULL);2654 return TCL_ERROR;2655 }2656 } else if (strcmp(string, "ymin") == 0) {2657 if (GetFloatFromObj(interp, objv[i+1], &yMin) != TCL_OK) {2658 return TCL_ERROR;2659 }2660 } else if (strcmp(string, "ymax") == 0) {2661 if (GetFloatFromObj(interp, objv[i+1], &yMax) != TCL_OK) {2662 return TCL_ERROR;2663 }2664 } else if (strcmp(string, "ynum") == 0) {2665 if (Tcl_GetIntFromObj(interp, objv[i+1], &yNum) != TCL_OK) {2666 return TCL_ERROR;2667 }2668 if (yNum <= 0) {2669 Tcl_AppendResult(interp, "bad ynum value: must be > 0",2670 (char *)NULL);2671 return TCL_ERROR;2672 }2673 } else if (strcmp(string, "zvalues") == 0) {2674 Tcl_Obj **zObj;2675 2676 if (Tcl_ListObjGetElements(interp, objv[i+1], &zNum, &zObj)!= TCL_OK) {2677 return TCL_ERROR;2678 }2679 int j;2680 zValues = new float[zNum];2681 for (j = 0; j < zNum; j++) {2682 if (GetFloatFromObj(interp, zObj[j], zValues + j) != TCL_OK) {2683 return TCL_ERROR;2684 }2685 }2686 } else {2687 Tcl_AppendResult(interp, "unknown key \"", string,2688 "\": should be xmin, xmax, xnum, ymin, ymax, ynum, or zvalues",2689 (char *)NULL);2690 return TCL_ERROR;2691 }2692 }2693 if (zValues == NULL) {2694 Tcl_AppendResult(interp, "missing \"zvalues\" key", (char *)NULL);2695 return TCL_ERROR;2696 }2697 if (zNum != (xNum * yNum)) {2698 Tcl_AppendResult(interp, "wrong number of z values must be xnum*ynum",2699 (char *)NULL);2700 return TCL_ERROR;2701 }2702 HeightMap* hMap;2703 hMap = new HeightMap();2704 hMap->setHeight(xMin, yMin, xMax, yMax, xNum, yNum, zValues);2705 hMap->setColorMap(NanoVis::get_transfunc("default"));2706 hMap->setVisible(true);2707 hMap->setLineContourVisible(true);2708 NanoVis::heightMap.push_back(hMap);2709 delete [] zValues;2710 return TCL_OK;2711 }
Note: See TracChangeset
for help on using the changeset viewer.