Changeset 2542 for branches/blt4


Ignore:
Timestamp:
Sep 21, 2011, 2:27:44 PM (13 years ago)
Author:
gah
Message:

update from trunk

Location:
branches/blt4/packages/vizservers
Files:
49 edited

Legend:

Unmodified
Added
Removed
  • branches/blt4/packages/vizservers/configure.in

    r2409 r2542  
    11AC_PREREQ([2.60])
    22AC_INIT(vizservers, 0.1, rappture@nanohub.org)
    3 AC_CONFIG_HEADER(nanovis/nvconf.h nanoscale/config.h)
    4 
    5 with_vtk="yes"
    6 with_vtk_libs=""
    7 with_vtk_includes=""
    8 with_rappture=""
    9 with_tcllib=""
    10 with_rappture="yes"
     3AC_CONFIG_HEADERS([nanovis/nvconf.h nanoscale/config.h])
    114
    125AC_ARG_WITH(
     
    2922        [VTK include files are in DIR])],
    3023    [with_vtk_includes=$withval],
    31     [with_vtk_includes=/usr/include/vtk-5.6])
     24    [with_vtk_includes=""])
    3225
    3326AC_ARG_WITH(
     
    3629        [VTK libraries are in DIR])],
    3730    [with_vtk_libs=$withval],
    38     [with_vtk_libs=/usr/lib/vtk-5.6])
     31    [with_vtk_libs=""])
    3932
    4033AC_ARG_WITH(
     
    154147  done
    155148else
    156   if test -d "$with_rappture" ; then
     149  if test ! -d "$with_rappture" ; then
    157150    AC_MSG_ERROR([--with-rappture: no such directory $with_rappture])
    158151  fi
     
    193186if test "x$with_vtk_libs" != "x"; then
    194187   VTK_LIB_DIR=$with_vtk_libs
     188   VTK_LIB_SPEC="-L$with_vtk_libs"
    195189fi
    196190
     
    290284    AC_CHECK_LIB([avformat], [av_alloc_format_context], [],
    291285        [AC_MSG_WARN([libavformat not usable])]))
     286AC_CHECK_FUNCS([avformat_alloc_context])
    292287AC_CHECK_LIB([avutil], [av_free])
    293288AC_CHECK_FUNCS([img_convert])
     
    311306CG_LIB_DIR="$dir/lib"
    312307
    313 echo CGDIR=$CG_DIR
    314308save_CPPFLAGS=$CPPFLAGS
    315309CPPFLAGS="-I${CG_INC_DIR} $CPPFLAGS"
  • branches/blt4/packages/vizservers/nanoscale/config.h.in

    r1353 r2542  
    33/* Define if building universal (internal helper macro) */
    44#undef AC_APPLE_UNIVERSAL_BUILD
     5
     6/* Define to 1 if you have the `accept4' function. */
     7#undef HAVE_ACCEPT4
    58
    69/* Define to 1 if you have the <arpa/inet.h> header file. */
     
    912/* Define to 1 if you have the `avformat_alloc_context' function. */
    1013#undef HAVE_AVFORMAT_ALLOC_CONTEXT
     14
     15/* Define to 1 if you have the <Cg/cgGL.h> header file. */
     16#undef HAVE_CG_CGGL_H
    1117
    1218/* Define to 1 if you have the <ffmpeg/avcodec.h> header file. */
     
    2531#undef HAVE_INTTYPES_H
    2632
     33/* Define to 1 if you have the `avcodec' library (-lavcodec). */
     34#undef HAVE_LIBAVCODEC
     35
    2736/* Define to 1 if you have the <libavcodec/avcodec.h> header file. */
    2837#undef HAVE_LIBAVCODEC_AVCODEC_H
     38
     39/* Define to 1 if you have the `avformat' library (-lavformat). */
     40#undef HAVE_LIBAVFORMAT
    2941
    3042/* Define to 1 if you have the <libavformat/avformat.h> header file. */
    3143#undef HAVE_LIBAVFORMAT_AVFORMAT_H
    3244
     45/* Define to 1 if you have the `avutil' library (-lavutil). */
     46#undef HAVE_LIBAVUTIL
     47
    3348/* Define to 1 if you have the <libavutil/avutil.h> header file. */
    3449#undef HAVE_LIBAVUTIL_AVUTIL_H
     50
     51/* Define to 1 if you have the `highgui' library (-lhighgui). */
     52#undef HAVE_LIBHIGHGUI
    3553
    3654/* Define to 1 if you have the <memory.h> header file. */
     
    4361#undef HAVE_NETINET_IN_H
    4462
    45 /* Define to 1 if you have the <rappture.h> header file. */
    46 #undef HAVE_RAPPTURE_H
     63/* Define to 1 if you have the <opencv/cv.h> header file. */
     64#undef HAVE_OPENCV_CV_H
     65
     66/* Define to 1 if you have the <opencv/highgui.h> header file. */
     67#undef HAVE_OPENCV_HIGHGUI_H
    4768
    4869/* Define to 1 if you have the <stdint.h> header file. */
     
    7697#undef HAVE_UNISTD_H
    7798
     99/* Define to 1 if you have the <vtkSmartPointer.h> header file. */
     100#undef HAVE_VTKSMARTPOINTER_H
     101
    78102/* Define to the address where bug reports for this package should be sent. */
    79103#undef PACKAGE_BUGREPORT
     
    91115#undef PACKAGE_VERSION
    92116
     117/* The size of `float', as computed by sizeof. */
     118#undef SIZEOF_FLOAT
     119
     120/* The size of `int', as computed by sizeof. */
     121#undef SIZEOF_INT
     122
     123/* The size of `long', as computed by sizeof. */
     124#undef SIZEOF_LONG
     125
     126/* The size of `long long', as computed by sizeof. */
     127#undef SIZEOF_LONG_LONG
     128
     129/* The size of `void *', as computed by sizeof. */
     130#undef SIZEOF_VOID_P
     131
    93132/* Define to 1 if you have the ANSI C header files. */
    94133#undef STDC_HEADERS
  • branches/blt4/packages/vizservers/nanoscale/renderservers.tcl.in

    r2410 r2542  
    1010    ${bindir}/nanovis -p ${libdir}/shaders:${libdir}/resources
    1111} {
    12   LD_LIBRARY_PATH ${libdir}
     12    LD_LIBRARY_PATH ${libdir}
    1313}
    1414
     
    1818    ${bindir}/nanovis -p ${libdir}/shaders:${libdir}/resources
    1919} {
    20   LD_LIBRARY_PATH ${libdir}
     20    LD_LIBRARY_PATH ${libdir}
    2121}
    2222
     
    2727    ${bindir}/vtkvis
    2828} {
    29   LD_LIBRARY_PATH ${libdir}:${vtkdir}
     29    LD_LIBRARY_PATH ${libdir}:${vtkdir}
    3030}
    3131
     
    3636    ${bindir}/pymolproxy ${bindir}/pymol -p -q -i -x -X 0 -Y 0
    3737} {
    38    PYMOL_PATH ${libdir}/pymol
     38    LD_LIBRARY_PATH ${libdir}
     39    PYMOL_PATH ${libdir}/pymol
    3940}
  • branches/blt4/packages/vizservers/nanoscale/server2.c

    r2409 r2542  
     1
     2#define _GNU_SOURCE
     3#include <sys/socket.h>
    14
    25#include <stdio.h>
     
    1215#include <syslog.h>
    1316#include <unistd.h>
     17#include <fcntl.h>
    1418
    1519#include <tcl.h>
     20
     21#include "config.h"
    1622
    1723#define TRUE    1
     
    378384            /* Accept the new connection. */
    379385            length = sizeof(newaddr);
     386#ifdef HAVE_ACCEPT4
     387            f = accept4(serverPtr->listenerFd, (struct sockaddr *)&newaddr,
     388                        &length, SOCK_CLOEXEC);
     389#else
    380390            f = accept(serverPtr->listenerFd, (struct sockaddr *)&newaddr,
    381391                       &length);
     392#endif
    382393            if (f < 0) {
    383394                ERROR("Can't accept server \"%s\": %s", serverPtr->name,
     
    385396                exit(1);
    386397            }
     398#ifndef HAVE_ACCEPT4
     399            int flags = fcntl(f, F_GETFD);
     400            flags |= FD_CLOEXEC;
     401            if (fcntl(f, F_SETFD, flags) < 0) {
     402                ERROR("Can't set FD_CLOEXEC on socket \"%s\": %s", serverPtr->name,
     403                      strerror(errno));
     404                exit(1);
     405            }
     406#endif
    387407            INFO("Connecting \"%s\" to %s\n", serverPtr->name,
    388408                 inet_ntoa(newaddr.sin_addr));
     
    413433                /* Dup the descriptors and start the server.  */
    414434
    415                 dup2(f, 0);             /* Stdin */
    416                 dup2(f, 1);             /* Stdout */
     435                if (dup2(f, 0) < 0)  {  /* Stdin */
     436                    ERROR("%s: can't dup stdin: %s", serverPtr->name,
     437                        strerror(errno));
     438                    exit(1);
     439                }
     440                if (dup2(f, 1) < 0) {   /* Stdout */
     441                    ERROR("%s: can't dup stdout: %s", serverPtr->name,
     442                          strerror(errno));
     443                    exit(1);
     444                }
    417445                errFd = open("/dev/null", O_WRONLY, 0600);
    418                 dup2(errFd, 2);         /* Stderr */
     446                if (errFd < 0) {
     447                    ERROR("%s: can't open /dev/null for read/write: %s",
     448                          serverPtr->name, strerror(errno));
     449                    exit(1);
     450                }
     451                if (dup2(errFd, 2) < 0) { /* Stderr */
     452                    ERROR("%s: can't change to root directory for \"%s\": %s",
     453                          serverPtr->name, strerror(errno));
     454                    exit(1);
     455                }
    419456                for(i = 3; i <= FD_SETSIZE; i++) {
    420457                    close(i);           /* Close all the other descriptors. */
  • branches/blt4/packages/vizservers/nanovis/Makefile.in

    r2120 r2542  
    11
    22SHELL = /bin/sh
    3 
    4 #.SUFFIX:
    5 #SUFFIX: .c .o .cpp
    6 
    7 .PHONY: all install clean distclean
    83
    94bindir          = @bindir@
     
    2318
    2419#Why are these files installed owner writable?
    25 INSTALL_PROGRAM = ${INSTALL} -m 555
    26 INSTALL_DATA    = ${INSTALL} -m 444
    27 INSTALL_SCRIPT  = ${INSTALL} -m 444
     20INSTALL_PROGRAM = ${INSTALL} -m 0555
     21INSTALL_DATA    = ${INSTALL} -m 0444
     22INSTALL_SCRIPT  = ${INSTALL} -m 0444
    2823RM              = rm -f
    2924
     
    3328CG_INC_SPEC     = -I$(CG_DIR)/include
    3429CG_LIB_SPEC     = -L$(CG_DIR)/lib -lCg -lCgGL
    35 DX_INC_SPEC      = @DX_INC_SPEC@
    36 DX_LIB_SPEC      = @DX_LIB_SPEC@ -lDXcallm
     30DX_INC_SPEC     = @DX_INC_SPEC@
     31DX_LIB_SPEC     = @DX_LIB_SPEC@ -lDXcallm
    3732FF_LIB_SPEC     = @LIBS@
    3833FF_INC_SPEC     = @FF_INC_SPEC@
     
    7368TCL_INC_SPEC    = @TCL_INC_SPEC@
    7469
    75 LD_RUN_PATH     = @LD_RPATH@
     70LD_RUN_PATH     = $(libdir):@LD_RPATH@
    7671
    7772LIBS            = \
     
    10499                $(CG_INC_SPEC) \
    105100                $(GL_INC_SPEC) \
    106                 $(RP_INC_SPEC) \
     101                $(RP_INC_SPEC)
    107102
    108103CC              = @CC@
     
    111106EXTRA_CFLAGS    = -Wall
    112107DEFINES         =
    113 CXX_SWITCHES     = $(CFLAGS) $(EXTRA_CFLAGS) $(DEFINES) $(INCLUDES)
     108CXX_SWITCHES    = $(CFLAGS) $(EXTRA_CFLAGS) $(DEFINES) $(INCLUDES)
    114109
    115110OBJS            = \
     
    124119                DataLoader.o \
    125120                Event.o \
    126                 Unirect.o \
    127121                FlowCmd.o \
    128                 Switch.o \
    129122                GradientFilter.o \
    130123                Grid.o \
     
    137130                NvDefaultTFData.o \
    138131                NvEventLog.o \
     132                NvFlowVisRenderer.o \
    139133                NvLIC.o \
    140134                NvLoadFile.o \
    141135                NvParticleAdvectionShader.o \
    142136                NvParticleRenderer.o \
    143                 NvFlowVisRenderer.o \
    144                 NvVectorField.o \
    145137                NvRegularVolumeShader.o \
    146138                NvShader.o \
    147139                NvStdVertexShader.o \
     140                NvVectorField.o \
    148141                NvVolumeShader.o \
    149142                NvZincBlendeReconstructor.o \
    150143                NvZincBlendeVolumeShader.o \
     144                ParticleEmitter.o \
    151145                ParticleSystem.o \
    152                 ParticleEmitter.o \
    153146                ParticleSystemFactory.o \
    154147                PCASplit.o \
     
    159152                PointSetRenderer.o \
    160153                PointShader.o \
     154                Renderable.o \
    161155                RenderContext.o \
    162156                RenderVertexArray.o \
    163                 Renderable.o \
    164157                RpAVTranslate.o \
    165158                RpDX.o \
    166159                ScreenSnapper.o \
    167160                Sphere.o \
     161                Switch.o \
    168162                Texture1D.o \
    169163                Texture2D.o \
     
    171165                Trace.o \
    172166                TransferFunction.o \
     167                Unirect.o \
    173168                Util.o \
    174                 VelocityArrowsSlice.o \
     169                VelocityArrowsSlice.o \
    175170                Volume.o \
    176171                VolumeInterpolator.o \
     
    220215                $(srcdir)/shaders/velocity.cg
    221216
    222 .PHONY: newmat11 R2 imgloaders vrmath vrutil vr3d transfer-function
     217.PHONY: all install install-resources install-shaders install-nanovis clean distclean newmat11 R2 imgloaders vrmath vrutil vr3d transfer-function
    223218
    224219all: newmat11 R2 imgloaders vrmath vrutil vr3d transfer-function nanovis
     
    258253
    259254dxReader2.o: $(srcdir)/dxReader2.cpp
    260         $(CXX) -c $(CXX_SWITCHES) $(DX_INC_SPEC) $?
     255        $(CXX) -c $(CXX_SWITCHES) $(DX_INC_SPEC) $<
    261256RpDX.o: $(srcdir)/RpDX.cpp
    262         $(CXX) -c $(CXX_SWITCHES) $(DX_INC_SPEC) $?
     257        $(CXX) -c $(CXX_SWITCHES) $(DX_INC_SPEC) $<
    263258RpAVTranslate.o: $(srcdir)/RpAVTranslate.cpp
    264         $(CXX) -c $(CXX_SWITCHES) $(FF_INC_SPEC) $?
     259        $(CXX) -c $(CXX_SWITCHES) $(FF_INC_SPEC) $<
    265260
    266261client: Socket.o ClientSocket.o RenderClient.o Event.o
     
    278273        @for i in $(resources) ; do \
    279274            echo "installing $$i..." ; \
    280             $(INSTALL_DATA) -m 0444 $$i $(libdir)/resources ; \
     275            $(INSTALL_DATA) $$i $(libdir)/resources ; \
    281276        done
    282277
     
    285280        @for i in $(shaders) ; do \
    286281            echo "installing $$i..." ; \
    287             $(INSTALL_DATA) -m 0444 $$i $(libdir)/shaders ; \
     282            $(INSTALL_DATA) $$i $(libdir)/shaders ; \
    288283        done
    289284
    290285install-nanovis: nanovis
    291         $(INSTALL) -m 0555 nanovis $(bindir)
     286        $(INSTALL_PROGRAM) nanovis $(bindir)
    292287
    293288clean:
     
    301296
    302297distclean: clean
    303         $(RM) Makefile *~
    304 
    305 NvStdVertexShader.o: NvStdVertexShader.cpp NvStdVertexShader.h
     298        $(MAKE) -C $(MAT_DIR) distclean
     299        $(MAKE) -C $(VRMATH_DIR) distclean
     300        $(MAKE) -C $(VRUTIL_DIR) distclean
     301        $(MAKE) -C $(VR3D_DIR) distclean
     302        $(MAKE) -C $(R2_DIR)/src distclean
     303        $(MAKE) -C $(IMG_DIR) distclean
     304        $(RM) Makefile nvconf.h *~
     305
     306Axis.o: Axis.cpp Axis.h Chain.h
     307BucketSort.o: BucketSort.cpp BucketSort.h Vector3.h Vector4.h Mat4x4.h PCASplit.h
     308Chain.o: Chain.cpp Chain.h
     309CmdProc.o: CmdProc.cpp CmdProc.h
     310Color.o: Color.cpp Color.h
     311Command.o: Command.cpp Command.h
    306312ContourLineFilter.o: ContourLineFilter.cpp ContourLineFilter.h
     313ConvexPolygon.o: ConvexPolygon.cpp ConvexPolygon.h
    307314DataLoader.o: DataLoader.cpp
     315Event.o: Event.cpp Event.h
     316FlowCmd.o: FlowCmd.cpp FlowCmd.h Switch.h Trace.h TransferFunction.h nanovis.h Command.h CmdProc.h Nv.h NvLIC.h Unirect.h
     317GradientFilter.o: GradientFilter.cpp GradientFilter.h
     318Grid.o: Grid.cpp Grid.h
    308319HeightMap.o: HeightMap.cpp HeightMap.h
    309 Grid.o: Grid.cpp Grid.h
     320Mat4x4.o: Mat4x4.cpp Mat4x4.h
     321Nv.o: Nv.cpp Nv.h NvShader.h NvParticleRenderer.h NvColorTableRenderer.h NvEventLog.h VolumeRenderer.h PointSetRenderer.h
     322NvCamera.o: NvCamera.cpp NvCamera.h
     323NvColorTableRenderer.o: NvColorTableRenderer.cpp NvColorTableRenderer.h
     324NvColorTableShader.o: NvColorTableShader.cpp NvColorTableShader.h
     325NvDefaultTFData.o: NvDefaultTFData.cpp
     326NvEventLog.o: NvEventLog.cpp NvEventLog.h
     327NvFlowVisRenderer.o: NvFlowVisRenderer.cpp NvFlowVisRenderer.h
     328NvLIC.o: NvLIC.cpp NvLIC.h
    310329NvLoadFile.o: NvLoadFile.cpp NvLoadFile.h
    311330NvParticleAdvectionShader.o: NvParticleAdvectionShader.cpp NvParticleAdvectionShader.h
    312 NvFlowVisRenderer.o: NvFlowVisRenderer.cpp NvFlowVisRenderer.h
     331NvParticleRenderer.o: NvParticleRenderer.cpp NvParticleRenderer.h
     332NvRegularVolumeShader.o: NvRegularVolumeShader.cpp NvRegularVolumeShader.h
     333NvShader.o: NvShader.cpp NvShader.h
     334NvStdVertexShader.o: NvStdVertexShader.cpp NvStdVertexShader.h
    313335NvVectorField.o: NvVectorField.cpp NvVectorField.h
    314 NvParticleRenderer.o: NvParticleRenderer.cpp NvParticleRenderer.h
    315 NvColorTableShader.o: NvColorTableShader.cpp NvColorTableShader.h
    316 NvLIC.o: NvLIC.cpp NvLIC.h
    317 NvColorTableRenderer.o: NvColorTableRenderer.cpp NvColorTableRenderer.h
    318 NvEventLog.o: NvEventLog.cpp NvEventLog.h
    319 NvShader.o: NvShader.cpp NvShader.h
    320336NvVolumeShader.o: NvVolumeShader.cpp NvVolumeShader.h
    321 NvDefaultTFData.o: NvDefaultTFData.cpp
    322 NvRegularVolumeShader.o: NvRegularVolumeShader.cpp NvRegularVolumeShader.h
     337NvZincBlendeReconstructor.o: NvZincBlendeReconstructor.cpp NvZincBlendeReconstructor.h ZincBlendeVolume.h Volume.h Vector3.h
    323338NvZincBlendeVolumeShader.o: NvZincBlendeVolumeShader.cpp NvZincBlendeVolumeShader.h
     339ParticleEmitter.o: ParticleEmitter.cpp ParticleEmitter.h
    324340ParticleSystem.o: ParticleSystem.cpp ParticleSystem.h
    325341ParticleSystemFactory.o: ParticleSystemFactory.cpp ParticleSystemFactory.h
    326 ParticleEmitter.o: ParticleEmitter.cpp ParticleEmitter.h
     342PCASplit.o: PCASplit.cpp PCASplit.h
     343PerfQuery.o: PerfQuery.cpp PerfQuery.h
     344Plane.o: Plane.cpp Plane.h
     345PlaneRenderer.o: PlaneRenderer.cpp PlaneRenderer.h
     346PointSet.o: PointSet.cpp PointSet.h
     347PointSetRenderer.o: PointSetRenderer.cpp PointSetRenderer.h
     348PointShader.o: PointShader.cpp PointShader.h
     349Renderable.o: Renderable.cpp Renderable.h
     350RenderContext.o: RenderContext.cpp RenderContext.h
    327351RenderVertexArray.o: RenderVertexArray.cpp RenderVertexArray.h
    328 Color.o: Color.cpp Color.h
    329 Event.o: Event.cpp Event.h
     352RpAVTranslate.o: RpAVTranslate.cpp RpAVTranslate.h nvconf.h
     353RpDX.o: RpDX.cpp RpDX.h Trace.h
     354ScreenSnapper.o: ScreenSnapper.cpp ScreenSnapper.h define.h
    330355Sphere.o: Sphere.cpp Sphere.h
    331 TransferFunction.o: TransferFunction.cpp
     356Switch.o: Switch.cpp Switch.h
    332357Texture1D.o: Texture1D.cpp Texture1D.h
    333358Texture2D.o: Texture2D.cpp Texture2D.h $(AUXSRC)
    334359Texture3D.o: Texture3D.cpp Texture3D.h $(AUXSRC)
    335 Renderable.o: Renderable.cpp Renderable.h
    336 NvCamera.o: NvCamera.cpp NvCamera.h
    337 ScreenSnapper.o: ScreenSnapper.cpp ScreenSnapper.h define.h
     360Trace.o: Trace.cpp Trace.h
     361TransferFunction.o: TransferFunction.cpp
     362Unirect.o: Unirect.cpp Unirect.h Trace.h
     363Util.o: Util.cpp Util.h
     364VelocityArrowsSlice.o: VelocityArrowsSlice.cpp VelocityArrowsSlice.h
    338365Volume.o: Volume.cpp Volume.h $(AUXSRC)
     366VolumeInterpolator.o: VolumeInterpolator.cpp VolumeInterpolator.h
     367VolumeRenderer.o: VolumeRenderer.cpp VolumeRenderer.h
    339368ZincBlendeVolume.o: ZincBlendeVolume.cpp ZincBlendeVolume.h $(AUXSRC)
    340 VolumeRenderer.o: VolumeRenderer.cpp VolumeRenderer.h
    341 PlaneRenderer.o: PlaneRenderer.cpp PlaneRenderer.h
    342 Mat4x4.o: Mat4x4.cpp Mat4x4.h
    343 Plane.o: Plane.cpp Plane.h
    344 ConvexPolygon.o: ConvexPolygon.cpp ConvexPolygon.h
    345 PerfQuery.o: PerfQuery.cpp PerfQuery.h
    346 PointShader.o: PointShader.cpp PointShader.h
    347 PCASplit.o: PCASplit.cpp PCASplit.h
    348 BucketSort.o: BucketSort.cpp BucketSort.h
    349 PointSetRenderer.o: PointSetRenderer.cpp PointSetRenderer.h
    350 PointSet.o: PointSet.cpp PointSet.h
    351 RenderContext.o: RenderContext.cpp RenderContext.h
    352 VolumeInterpolator.o: VolumeInterpolator.cpp VolumeInterpolator.h
    353 GradientFilter.o: GradientFilter.cpp GradientFilter.h
    354 VelocityArrowsSlice.o: VelocityArrowsSlice.cpp VelocityArrowsSlice.h
    355 
    356 Util.o: Util.cpp Util.h
    357 Command.o: Command.cpp Command.h
    358 Trace.o: Trace.cpp Trace.h
    359 
     369dxReader.o: dxReader.cpp dxReaderCommon.h Nv.h nanovis.h Unirect.h ZincBlendeVolume.h NvZincBlendeReconstructor.h
     370dxReader2.o: dxReader2.cpp dxReaderCommon.h RpDX.h Nv.h nanovis.h
     371dxReaderCommon.o: dxReaderCommon.cpp dxReaderCommon.h GradientFilter.h Vector3.h
    360372nanovis.o: nanovis.cpp nanovis.h $(AUXSRC)
  • branches/blt4/packages/vizservers/nanovis/nvconf.h.in

    r2120 r2542  
    44#undef AC_APPLE_UNIVERSAL_BUILD
    55
     6/* Define to 1 if you have the `accept4' function. */
     7#undef HAVE_ACCEPT4
     8
    69/* Define to 1 if you have the <arpa/inet.h> header file. */
    710#undef HAVE_ARPA_INET_H
     11
     12/* Define to 1 if you have the `avformat_alloc_context' function. */
     13#undef HAVE_AVFORMAT_ALLOC_CONTEXT
     14
     15/* Define to 1 if you have the <Cg/cgGL.h> header file. */
     16#undef HAVE_CG_CGGL_H
    817
    918/* Define to 1 if you have the <ffmpeg/avcodec.h> header file. */
     
    4049#undef HAVE_LIBAVUTIL_AVUTIL_H
    4150
    42 /* Define to 1 if you have the `cv' library (-lcv). */
    43 #undef HAVE_LIBCV
     51/* Define to 1 if you have the `highgui' library (-lhighgui). */
     52#undef HAVE_LIBHIGHGUI
    4453
    4554/* Define to 1 if you have the <memory.h> header file. */
     
    5766/* Define to 1 if you have the <opencv/highgui.h> header file. */
    5867#undef HAVE_OPENCV_HIGHGUI_H
    59 
    60 /* Define to 1 if you have the <rappture.h> header file. */
    61 #undef HAVE_RAPPTURE_H
    6268
    6369/* Define to 1 if you have the <stdint.h> header file. */
     
    9197#undef HAVE_UNISTD_H
    9298
     99/* Define to 1 if you have the <vtkSmartPointer.h> header file. */
     100#undef HAVE_VTKSMARTPOINTER_H
     101
    93102/* Define to the address where bug reports for this package should be sent. */
    94103#undef PACKAGE_BUGREPORT
     
    102111/* Define to the one symbol short name of this package. */
    103112#undef PACKAGE_TARNAME
    104 
    105 /* Define to the home page for this package. */
    106 #undef PACKAGE_URL
    107113
    108114/* Define to the version of this package. */
  • branches/blt4/packages/vizservers/pymolproxy/Makefile.in

    r1948 r2542  
    22TARGETS         = pymolproxy
    33
     4CC              = @CC@
     5CC_SWITCHES     = $(CFLAGS) $(EXTRA_CFLAGS) $(DEFINES) $(INCLUDES)
     6CFLAGS          = @CFLAGS@
     7DEFINES         = -DSTANDALONE
     8EXTRA_CFLAGS    = -Wall
     9INCLUDES        = $(TCL_INC_SPEC)
    410TCL_INC_SPEC    = @TCL_INC_SPEC@
    511TCL_LIB_SPEC    = @TCL_LIB_SPEC@
    6 CC              = @CC@
    7 INCLUDES        = $(TCL_INC_SPEC)
    8 CFLAGS          = @CFLAGS@
    9 EXTRA_CFLAGS    = -Wall
    10 DEFINES         = -DSTANDALONE
    11 CC_SWITCHES     = $(CFLAGS) $(EXTRA_CFLAGS) $(DEFINES) $(INCLUDES)
     12RP_LIB_DIR      = @RP_LIB_DIR@
    1213
    1314bindir          = @bindir@
     
    2930
    3031OBJS            = pymolproxy.o
    31 LIBS            = $(TCL_LIB_SPEC)
     32LIBS            = $(TCL_LIB_SPEC) \
     33                  -Wl,-rpath,$(RP_LIB_DIR)
    3234
    3335SCRIPTS         = $(srcdir)/scripts/box.py
  • branches/blt4/packages/vizservers/pymolproxy/pymolproxy.c

    r2409 r2542  
    107107
    108108typedef struct Image {
    109     struct Image *nextPtr;      /* Next image in chain of images. The list is
    110                                  * ordered by the most recently received image
    111                                  * from the pymol server to the least. */
    112     struct Image *prevPtr;      /* Previous image in chain of images. The list
    113                                  * is ordered by the most recently received
    114                                  * image from the pymol server to the
    115                                  * least. */
    116     ssize_t nWritten;           /* Number of bytes of image data already
    117                                  * delivered.*/
    118     size_t bytesLeft;           /* Number of bytes of image data left to
    119                                  * delivered to the client. */
    120     char data[1];               /* Start of image data. We allocate the size
    121                                  * of the Image structure plus the size of the
    122                                  * image data. */
     109    struct Image *nextPtr;              /* Next image in chain of images. The
     110                                         * list is ordered by the most
     111                                         * recently received image from the
     112                                         * pymol server to the least. */
     113    struct Image *prevPtr;              /* Previous image in chain of
     114                                         * images. The list is ordered by the
     115                                         * most recently received image from
     116                                         * the pymol server to the least. */
     117    ssize_t nWritten;                   /* Number of bytes of image data
     118                                         * already delivered.*/
     119    size_t bytesLeft;                   /* Number of bytes of image data left
     120                                         * to delivered to the client. */
     121    char data[1];                       /* Start of image data. We allocate
     122                                         * the size of the Image structure
     123                                         * plus the size of the image data. */
    123124} Image;
    124125
     
    126127
    127128typedef struct {
     129    const char *ident;
    128130    char bytes[BUFFER_SIZE];
    129131    int fill;
     
    135137#define BUFFER_ERROR            -1
    136138#define BUFFER_CONTINUE         -2
    137 #define BUFFER_SHORT_READ       -3
    138139
    139140#define FORCE_UPDATE            (1<<0)
     
    155156                                         * are in the front of the list. */
    156157
    157     int sin, sout, serr;                /* Server file descriptors. */
     158    int sin, sout;                      /* Server file descriptors. */
    158159    int cin, cout;                      /* Client file descriptors. */
    159160    ReadBuffer client;                  /* Read buffer for client input. */
     
    247248
    248249static void
    249 InitBuffer(ReadBuffer *readPtr, int f)
    250 {
     250InitBuffer(ReadBuffer *readPtr, const char *ident, int f)
     251{
     252    readPtr->ident = ident;
    251253    readPtr->fd = f;
    252254    readPtr->fill = 0;
     
    261263}
    262264
     265/* 
     266 * FillBuffer --
     267 *
     268 *      Fills the buffer with available data.  Any existing data
     269 *      in the buffer is slide to the front of the buffer, then
     270 *      the channel is read to fill the rest of the buffer.
     271 *
     272 *      If EOF or an error occur when reading the channel, then
     273 *      BUFFER_ERROR is returned. If the buffer can't be filled,
     274 *      then BUFFER_CONTINUE is returned. 
     275 *
     276 */
    263277static int
    264278FillBuffer(ReadBuffer *readPtr)
     
    272286#endif
    273287    if (readPtr->mark >= readPtr->fill) {
     288        INFO("tossing full buffer mark=%d, fill=%d", readPtr->mark,
     289             readPtr->fill);
    274290        readPtr->mark = readPtr->fill = 0;
    275291    }
     
    277293        size_t i, j;
    278294
     295        /* Some data has been consumed. Move the unconsumed data to the front
     296         * of the buffer. */
    279297        for (i = 0, j = readPtr->mark; j < readPtr->fill; i++, j++) {
    280298            readPtr->bytes[i] = readPtr->bytes[j];
     
    286304    nRead = read(readPtr->fd, readPtr->bytes + readPtr->fill, bytesLeft);
    287305    if (nRead == 0) {
    288         return BUFFER_ERROR;
    289     }
    290     if (nRead <= 0) {
     306        INFO("EOF found reading \"%s\" buffer", readPtr->ident);
     307        return BUFFER_ERROR;            /* EOF, treat as an error. */
     308    }
     309    if (nRead < 0) {
    291310        if (errno != EAGAIN) {
    292311#if READTRACE
     
    295314                  nRead, readPtr->mark, readPtr->fill);
    296315#endif
     316            ERROR("error reading \"%s\" buffer: %s", readPtr->ident,
     317                  strerror(errno));
    297318            return BUFFER_ERROR;
    298319        }
    299         return BUFFER_SHORT_READ;
     320        INFO("Short read for \"%s\" buffer", readPtr->ident);
     321        return BUFFER_CONTINUE;
    300322    }
    301323    readPtr->fill += nRead;
     
    304326          nRead, readPtr->mark, readPtr->fill);
    305327#endif
    306     return (nRead == bytesLeft) ? BUFFER_OK : BUFFER_SHORT_READ;
    307 }
    308 
     328    return (nRead == bytesLeft) ? BUFFER_OK : BUFFER_CONTINUE;
     329}
     330
     331/*
     332 * NextLine --
     333 *
     334 *      Returns the next available line (terminated by a newline).
     335 *      If insufficient data is in the buffer, then the channel is
     336 *      read for more data.  If reading the channel results in a
     337 *      short read, NULL is returned and *nBytesPtr is set to
     338 *      BUFFER_CONTINUE.
     339 */
    309340static char *
    310 GetLine(ReadBuffer *readPtr, int *nBytesPtr)
     341NextLine(ReadBuffer *readPtr, int *nBytesPtr)
    311342{
    312343    int i;
     
    314345
    315346#if READTRACE
    316     Debug("Entering GetLine (mark=%d, fill=%d)\n",readPtr->mark, readPtr->fill);
     347    Debug("Entering NextLine (mark=%d, fill=%d)\n",readPtr->mark, readPtr->fill);
    317348#endif
    318349    status = BUFFER_OK;
    319350    for (;;) {
    320         /* Look for the next newline (the next full line). */
    321351#if READTRACE
    322         Debug("in GetLine: mark=%d fill=%d\n", readPtr->mark, readPtr->fill);
     352        Debug("in NextLine: mark=%d fill=%d\n", readPtr->mark, readPtr->fill);
    323353#endif
     354        /* Check for a newline in the current buffer (it's the next
     355         * full line). */
    324356        for (i = readPtr->mark; i < readPtr->fill; i++) {
    325357            if (readPtr->bytes[i] == '\n') {
     
    328360                /* Save the start of the line. */
    329361                p = readPtr->bytes + readPtr->mark;
    330                 i++;
     362                i++;                    /* Include the newline. */
    331363                *nBytesPtr = i - readPtr->mark;
    332364                readPtr->mark = i;
    333365#if READTRACE
    334                 Debug("Leaving GetLine(%.*s)\n", *nBytesPtr, p);
     366                Debug("Leaving NextLine(%.*s)\n", *nBytesPtr, p);
    335367#endif
    336368                return p;
     
    339371        /* Couldn't find a newline, so it may be that we need to read some
    340372         * more. Check first that last read wasn't a short read. */
    341         if (status == BUFFER_SHORT_READ) {
    342             break;
    343         }
     373        if (status == BUFFER_CONTINUE) {
     374            *nBytesPtr = BUFFER_CONTINUE;  /* No complete line just yet. */
     375            return NULL;
     376        }
     377        /* Try to add more data to the buffer. */
    344378        status = FillBuffer(readPtr);
    345379        if (status == BUFFER_ERROR) {
     
    347381            return NULL;        /* EOF or error on read. */
    348382        }
     383        /* BUFFER_OK or BUFFER_CONTINUE */
    349384    }
    350385#if READTRACE
    351     Debug("Leaving GetLine failed to read line\n");
     386    Debug("Leaving NextLine failed to read line\n");
    352387#endif
    353388    *nBytesPtr = BUFFER_CONTINUE;
     
    355390}
    356391
     392/*
     393 * ReadFollowingData --
     394 *
     395 *      Read the requested number of bytes from the buffer.  Fails if
     396 *      the requested number of bytes are not immediately available.
     397 *      Never should be short.
     398 */
    357399static int
    358 GetBytes(ReadBuffer *readPtr, char *out, int nBytes)
     400ReadFollowingData(ReadBuffer *readPtr, char *out, int nBytes)
    359401{
    360402#if READTRACE
    361     Debug("Entering GetBytes(%d)\n", nBytes);
     403    Debug("Entering ReadFollowingData(%d)\n", nBytes);
    362404#endif
    363405    while (nBytes > 0) {
     
    369411            int size;
    370412
     413            /* Pull bytes out of the buffer, updating the mark. */
    371414            size = (bytesLeft >  nBytes) ? nBytes : bytesLeft;
    372415            memcpy(out, readPtr->bytes + readPtr->mark, size);
     
    378421            /* Received requested # bytes. */
    379422#if READTRACE
    380             Debug("Leaving GetBytes(%d)\n", nBytes);
     423            Debug("Leaving ReadFollowingData(%d)\n", nBytes);
    381424#endif
    382425            return BUFFER_OK;
     
    388431        }
    389432#if READTRACE
    390         Debug("in GetBytes: mark=%d fill=%d\n", readPtr->mark, readPtr->fill);
     433        Debug("in ReadFollowingData: after fill: mark=%d fill=%d status=%d\n",
     434              readPtr->mark, readPtr->fill, status);
    391435#endif
    392436    }
    393437#if READTRACE
    394     Debug("Leaving GetBytes(%d)\n", nBytes);
     438    Debug("Leaving ReadFollowingData(%d)\n", nBytes);
    395439#endif
    396440    return BUFFER_OK;
     
    435479
    436480    if (proxyPtr->status != TCL_OK) {
    437         return proxyPtr->status;
     481        return TCL_ERROR;
    438482    }
    439483#if EXPECTTRACE
     
    446490        char *line;
    447491
    448         line = GetLine(&proxyPtr->server, &nBytes);
     492        line = NextLine(&proxyPtr->server, &nBytes);
    449493        if (line != NULL) {
    450494#if EXPECTTRACE
     
    460504                Debug("Leaving Expect: got (%.*s)\n", nBytes, out);
    461505#endif
    462                 return BUFFER_OK;
     506                return TCL_OK;
    463507            }
    464508            continue;
    465509        }
    466         if (nBytes != BUFFER_CONTINUE) {
    467             return BUFFER_ERROR;
    468         }
    469     }
    470     ERROR("Leaving Expect: failed to find (%s)\n", match);
     510        if (nBytes == BUFFER_ERROR) {
     511            Tcl_AppendResult(proxyPtr->interp,
     512                "error reading server to find match for \"", match, "\": ",
     513                Tcl_PosixError(proxyPtr->interp), (char *)NULL);
     514            return TCL_ERROR;
     515        }
     516    }
     517    Tcl_AppendResult(proxyPtr->interp, "failed to find match for \"", match,
     518        "\"", (char *)NULL);
    471519    proxyPtr->error = 2;
    472520    proxyPtr->status = TCL_ERROR;
    473     return BUFFER_ERROR;
     521    return TCL_ERROR;
    474522}
    475523
     
    674722#endif
    675723            if (nWritten < 0) {
    676                 ERROR("Error writing fd(%d), %d/%s.", fd, errno,
    677                       strerror(errno));
     724                ERROR("Error writing fd=%d, %s", fd, strerror(errno));
    678725                return;
    679726            }
     
    724771    nWritten = write(proxyPtr->sin, buffer, length);
    725772    if (nWritten != length) {
    726         ERROR("short write to pymol (wrote=%d, should have been %d)",
    727               nWritten, length);
     773        ERROR("short write to pymol (wrote=%d, should have been %d): %s",
     774              nWritten, length, strerror(errno));
    728775    }
    729776    for (p = buffer; *p != '\0'; p++) {
     
    735782    sprintf(expect, "PyMOL>%s", buffer);
    736783    /* Now wait for the "PyMOL>" prompt. */
    737     result = Expect(proxyPtr, expect, buffer, BUFSIZ);
    738     if (result == BUFFER_ERROR) {
    739         ERROR("timeout reading data (buffer=%s)", buffer);
     784    if (Expect(proxyPtr, expect, buffer, BUFSIZ) != TCL_OK) {
    740785        proxyPtr->error = 1;
    741786        proxyPtr->status = TCL_ERROR;
    742         return proxyPtr->status;
     787        return TCL_ERROR;
    743788    }
    744789    return  proxyPtr->status;
     
    848893    Pymol(proxyPtr, "refresh\n");
    849894    Pymol(proxyPtr, "bmp -\n");
    850     if (Expect(proxyPtr, "bmp image follows: ", buffer, BUFSIZ) != BUFFER_OK) {
    851         ERROR("can't find image follows line (%s)", buffer);
     895    if (Expect(proxyPtr, "bmp image follows: ", buffer, BUFSIZ) != TCL_OK) {
     896        return TCL_ERROR;
    852897    }
    853898    if (sscanf(buffer, "bmp image follows: %d\n", &nBytes) != 1) {
     
    862907    imgPtr = NewImage(proxyPtr, nBytes + length);
    863908    strcpy(imgPtr->data, buffer);
    864     if (GetBytes(&proxyPtr->server, imgPtr->data + length, nBytes)!=BUFFER_OK){
    865         ERROR("can't read %d bytes for \"image follows\" buffer", nBytes);
     909    if (ReadFollowingData(&proxyPtr->server, imgPtr->data + length, nBytes)
     910        != BUFFER_OK) {
     911        ERROR("can't read %d bytes for \"image follows\" buffer: %s", nBytes,
     912              strerror(errno));
    866913        return  TCL_ERROR;
    867914    }
     
    11861233            return TCL_ERROR;
    11871234        }
    1188         if (GetBytes(&proxyPtr->client, allocated, nBytes) != BUFFER_OK) {
     1235        if (ReadFollowingData(&proxyPtr->client, allocated, nBytes)
     1236            != BUFFER_OK) {
    11891237            Tcl_AppendResult(interp, "can't read pdbdata from client.",
    11901238                             (char *)NULL);
     
    13181366PngCmd(ClientData clientData, Tcl_Interp *interp, int argc, const char *argv[])
    13191367{
    1320     char buffer[800];
     1368    char buffer[BUFSIZ];
    13211369    int nBytes=0;
    13221370    PymolProxy *proxyPtr = clientData;
     
    13301378    Pymol(proxyPtr, "png -\n");
    13311379
    1332     Expect(proxyPtr, "png image follows: ", buffer, 800);
    1333 
     1380    if (Expect(proxyPtr, "png image follows: ", buffer, BUFSIZ-1) != TCL_OK) {
     1381        return TCL_ERROR;
     1382    }
    13341383    if (sscanf(buffer, "png image follows: %d\n", &nBytes) != 1) {
    13351384        Tcl_AppendResult(interp, "can't get # bytes from \"", buffer, "\"",
     
    13421391    imgPtr = NewImage(proxyPtr, nBytes + length);
    13431392    strcpy(imgPtr->data, buffer);
    1344     if (GetBytes(&proxyPtr->server, imgPtr->data + length, nBytes)!=BUFFER_OK){
    1345         ERROR("can't read %d bytes for \"image follows\" buffer", nBytes);
     1393    if (ReadFollowingData(&proxyPtr->server, imgPtr->data + length, nBytes)
     1394        != BUFFER_OK) {
     1395        ERROR("can't read %d bytes for \"image follows\" buffer: %s", nBytes,
     1396              strerror(errno));
    13461397        return  TCL_ERROR;
    13471398    }
    1348     Expect(proxyPtr, " ScenePNG", buffer, 800);
    1349 
     1399    if (Expect(proxyPtr, " ScenePNG", buffer, BUFSIZ-1) != TCL_OK) {
     1400        return TCL_ERROR;
     1401    }
    13501402    stats.nFrames++;
    13511403    stats.nBytes += nBytes;
     
    13901442    }
    13911443    Pymol(proxyPtr, "ray %d,%d\n", width, height);
    1392     Expect(proxyPtr, " Ray:", buffer, 800);
     1444    if (Expect(proxyPtr, " Ray:", buffer, BUFSIZ-1) != TCL_OK) {
     1445        return TCL_ERROR;
     1446    }
    13931447
    13941448    Pymol(proxyPtr, "png -,dpi=300\nbg_color black\n");
    1395     Expect(proxyPtr, "png image follows: ", buffer, 800);
     1449    if (Expect(proxyPtr, "png image follows: ", buffer, BUFSIZ-1) != TCL_OK) {
     1450        return TCL_ERROR;
     1451    }
    13961452
    13971453    if (sscanf(buffer, "png image follows: %d\n", &nBytes) != 1) {
     
    14061462    imgPtr = NewImage(proxyPtr, nBytes + length);
    14071463    strcpy(imgPtr->data, buffer);
    1408     if (GetBytes(&proxyPtr->server, imgPtr->data + length, nBytes)!=BUFFER_OK){
    1409         ERROR("can't read %d bytes for \"image follows\" buffer", nBytes);
     1464    if (ReadFollowingData(&proxyPtr->server, imgPtr->data + length, nBytes)
     1465        != BUFFER_OK) {
     1466        ERROR("can't read %d bytes for \"image follows\" buffer: %s", nBytes,
     1467              strerror(errno));
    14101468        return  TCL_ERROR;
    14111469    }
    1412     Expect(proxyPtr, " ScenePNG", buffer, 800);
     1470    if (Expect(proxyPtr, " ScenePNG", buffer, BUFSIZ-1) != TCL_OK) {
     1471        return TCL_ERROR;
     1472    }
    14131473
    14141474    stats.nFrames++;
     
    19361996
    19371997       
     1998static void
     1999ChildHandler(int sigNum)
     2000{
     2001    ERROR("pymol (%d) died unexpectedly", stats.child);
     2002    exit(1);
     2003}
     2004
    19382005static int
    19392006ProxyInit(int cin, int cout, char *const *argv)
     
    19422009    int sin[2];
    19432010    int sout[2];
    1944     int serr[2];
    19452011    Tcl_Interp *interp;
    1946     int child;
     2012    pid_t child, parent;
    19472013    PymolProxy proxy;
    19482014    struct timeval end;
     
    19602026    }
    19612027
    1962     if (pipe(serr) == -1) {
    1963         close(sin[0]);
    1964         close(sin[1]);
    1965         close(sout[0]);
    1966         close(sout[1]);
    1967         return -1;
    1968     }
    1969 
    1970     /* Fork the new process.  Connect i/o to the new socket.  */
     2028    parent = getpid();
     2029
     2030    /* Fork the new process.  Connect I/O to the new socket.  */
    19712031
    19722032    child = fork();
     
    19752035        return -3;
    19762036    }
     2037
     2038    interp = Tcl_CreateInterp();
     2039    if (CreateTmpDir(interp) != TCL_OK) {
     2040        ERROR(Tcl_GetStringResult(interp));
     2041    }
     2042    Tcl_MakeSafe(interp);
     2043
    19772044    if (child == 0) {
    19782045        int f;
     2046        char path[200];
    19792047
    19802048        /* Child process */
     
    19892057        /* Redirect stdin, stdout, and stderr to pipes before execing */
    19902058
    1991         dup2(sin[0], 0);  // stdin
    1992         dup2(sout[1],1);  // stdout
    1993         dup2(serr[1],2);  // stderr
     2059        dup2(sin[0],  0);               // stdin
     2060        dup2(sout[1], 1);               // stdout
     2061        sprintf(path, "/tmp/pymol%d/stderr", parent);
     2062        f = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0600);
     2063        if (f < 0) {
     2064            ERROR("can't open server error file `%s': %s", path,
     2065                  strerror(errno));
     2066            exit(1);
     2067        }
     2068        dup2(f, 2);                     /* Redirect stderr to a file */
    19942069       
    19952070        /* Close all other descriptors  */       
     
    19972072            close(f);
    19982073        }
     2074        INFO("attempting to start \"%s\"", argv[0]);
    19992075       
    20002076        execvp(argv[0], argv);
    2001         ERROR("Failed to start pymol `%s'", argv[0]);
     2077        ERROR("can't exec `%s': %s", argv[0], strerror(errno));
    20022078        exit(-1);
     2079    } else {
     2080        signal(SIGCHLD, ChildHandler);
    20032081    }
    20042082    stats.child = child;
     
    20092087    close(sin[0]);
    20102088    close(sout[1]);
    2011     close(serr[1]);
    2012 
    2013 #ifdef notdef
    2014     signal(SIGPIPE, SIG_IGN); /* ignore SIGPIPE (e.g. nanoscale terminates)*/
    2015 #endif
    20162089
    20172090    memset(&proxy, 0, sizeof(PymolProxy));
    20182091    proxy.sin  = sin[1];
    20192092    proxy.sout = sout[0];
    2020     proxy.serr = serr[0];
    20212093    proxy.cin  = cin;
    20222094    proxy.cout = cout;
    20232095    proxy.flags = CAN_UPDATE;
    20242096    proxy.frame = 1;
    2025     interp = Tcl_CreateInterp();
    2026     if (CreateTmpDir(interp) != TCL_OK) {
    2027         ERROR(Tcl_GetStringResult(interp));
    2028     }
    2029     Tcl_MakeSafe(interp);
    20302097    proxy.interp = interp;
    20312098
     
    20592126    stats.start = end;
    20602127
    2061     if (write(cout, "PyMol 1.0\n", 10) != 10) {
    2062         ERROR("short write of signature");
    2063     }
    2064    
    20652128    // Main Proxy Loop
    20662129    //  accept tcl commands from socket
    20672130    //  translate them into pyMol commands, and issue them to child proccess
    20682131    //  send images back
     2132
    20692133    PollForEvents(&proxy);
    20702134
    20712135    close(proxy.cout);
    20722136    close(proxy.sout);
    2073     close(proxy.serr);
    20742137    close(proxy.cin);
    20752138    close(proxy.sin);
    20762139
    2077     status = waitpid(child, &result, WNOHANG);
    2078     if (status == -1) {
     2140    if (waitpid(child, &result, 0) < 0) {
    20792141        ERROR("error waiting on pymol server to exit: %s", strerror(errno));
    2080     } else if (status == 0) {
    2081         ERROR("attempting to signal (SIGTERM) pymol server.");
    2082         kill(-child, SIGTERM);          // Kill process group
    2083         alarm(5);
    2084         status = waitpid(child, &result, 0);
    2085         alarm(0);
    2086        
    2087         while ((status == -1) && (errno == EINTR)) {
    2088             ERROR("Attempting to signal (SIGKILL) pymol server.");
    2089             kill(-child, SIGKILL);      // Kill process group
    2090             alarm(10);
    2091             status = waitpid(child, &result, 0);
    2092             alarm(0);
    2093         }
    2094     }
     2142    }
     2143    INFO("attempting to signal (SIGTERM) pymol server.");
     2144    kill(-child, SIGTERM);              // Kill process group
     2145    alarm(5);
    20952146   
    2096     ERROR("pymol server process ended (result=%d)", result);
     2147    if (waitpid(child, &result, 0) < 0) {
     2148        ERROR("error waiting on pymol server to exit after SIGTERM: %s",
     2149              strerror(errno));
     2150    }
     2151    status = -1;
     2152    while ((status == -1) && (errno == EINTR)) {
     2153        ERROR("Attempting to signal (SIGKILL) pymol server.");
     2154        kill(-child, SIGKILL);  // Kill process group
     2155        alarm(10);
     2156        status = waitpid(child, &result, 0);
     2157        alarm(0);
     2158    }
     2159    INFO("pymol server process ended (result=%d)", result);
     2160
    20972161    DestroyTmpDir();
    2098 
    20992162    Tcl_DeleteInterp(interp);
    21002163   
     
    21112174{
    21122175    Tcl_DString clientCmds;
    2113     struct pollfd pollResults[4];
     2176    struct pollfd pollFd[3];
    21142177    int flags;
     2178
     2179    if (write(proxyPtr->cout, "PyMol 1.0\n", 10) != 10) {
     2180        ERROR("short write of signature");
     2181    }
    21152182
    21162183    flags = fcntl(proxyPtr->cin, F_GETFL);
    21172184    fcntl(proxyPtr->cin, F_SETFL, flags|O_NONBLOCK);
    21182185
    2119     pollResults[0].fd = proxyPtr->cout;
    2120     pollResults[1].fd = proxyPtr->sout;
    2121     pollResults[2].fd = proxyPtr->serr;
    2122     pollResults[0].events = pollResults[1].events =
    2123         pollResults[2].events = POLLIN;
    2124 
    2125     pollResults[3].fd = proxyPtr->cin;
    2126     pollResults[3].events = POLLOUT;
    2127 
    2128     InitBuffer(&proxyPtr->client, proxyPtr->cout);
    2129     InitBuffer(&proxyPtr->server, proxyPtr->sout);
     2186#ifdef notdef
     2187    flags = fcntl(proxyPtr->sout, F_GETFL);
     2188    fcntl(proxyPtr->sout, F_SETFL, flags|O_NONBLOCK);
     2189
     2190    flags = fcntl(proxyPtr->cout, F_GETFL);
     2191    fcntl(proxyPtr->cout, F_SETFL, flags|O_NONBLOCK);
     2192#endif
     2193
     2194    /* Read file descriptors. */
     2195    pollFd[0].fd = proxyPtr->cout;      /* Client standard output  */
     2196    pollFd[1].fd = proxyPtr->sout;      /* Server standard error.  */
     2197    pollFd[0].events = pollFd[1].events = POLLIN;
     2198
     2199    /* Write file descriptors. */
     2200    pollFd[2].fd = proxyPtr->cin;       /* Client standard input. */
     2201    pollFd[2].events = POLLOUT;
     2202
     2203    InitBuffer(&proxyPtr->client, "client", proxyPtr->cout);
     2204    InitBuffer(&proxyPtr->server, "server", proxyPtr->sout);
    21302205
    21312206    Tcl_DStringInit(&clientCmds);
     
    21332208        int timeout, nChannels;
    21342209
    2135         nChannels =  (proxyPtr->headPtr != NULL) ? 4 : 3;
    2136 
     2210        nChannels =  (proxyPtr->headPtr != NULL) ? 3 : 2;
    21372211#define PENDING_TIMEOUT         10  /* milliseconds. */
    21382212        timeout = (proxyPtr->flags & UPDATE_PENDING) ? PENDING_TIMEOUT : -1;
    2139         nChannels = poll(pollResults, nChannels, timeout);
     2213        nChannels = poll(pollFd, nChannels, timeout);
    21402214        if (nChannels < 0) {
    21412215            ERROR("POLL ERROR: %s", strerror(errno));
     
    21482222         * the pymol server to block writing to stderr or stdout.
    21492223         */
    2150         if (pollResults[1].revents & POLLIN) {
     2224        if (pollFd[1].revents & POLLIN) { /* Server stdout */
    21512225            int nBytes;
    21522226            char *line;
     
    21552229            /* Don't care what's in the server output buffer. */
    21562230            FlushBuffer(&proxyPtr->server);
    2157             line = GetLine(&proxyPtr->server, &nBytes);
     2231            line = NextLine(&proxyPtr->server, &nBytes);
    21582232            if (line != NULL) {
    21592233                Debug("STDOUT>%.*s", nBytes, line);
     
    21612235            } else if (nBytes == BUFFER_CONTINUE) {
    21622236                Debug("Done with pymol stdout\n");
     2237                goto error;             /* Pymol server died unexpectedly. */
    21632238            } else {
    2164                 ERROR("Failed reading pymol stdout (nBytes=%d)\n", nBytes);
    2165                 goto error;     /* Get out on EOF or error. */
     2239                ERROR("can't read pymol stdout (nBytes=%d): %s\n", nBytes,
     2240                      strerror(errno));
     2241                goto error;             /* Get out on EOF or error. */
    21662242            }
    21672243        }
    21682244
    2169         if (pollResults[2].revents & POLLIN) {
    2170             ssize_t nRead;
    2171             char buf[BUFSIZ];
    2172            
    2173             Debug("Reading pymol stderr\n");
    2174             /* pyMol Stderr Connection: pymol standard error output */
    2175            
    2176             nRead = read(pollResults[2].fd, buf, BUFSIZ-1);
    2177             if (nRead <= 0) {
    2178                 ERROR("unexpected read error from server (stderr): %s",
    2179                       strerror(errno));
    2180                 if (errno != EINTR) {
    2181                     ERROR("lost connection (stderr) to pymol server.");
    2182                     return;
    2183                 }
    2184             }
    2185             buf[nRead] = '\0';
    2186             Debug("stderr>%s", buf);
    2187             Debug("Done reading pymol stderr\n");
    2188         }
    2189 
    21902245        /* We have some descriptors ready. */
    2191         if (pollResults[0].revents & POLLIN) {
     2246        if (pollFd[0].revents & POLLIN) { /* Client stdout */
    21922247            Debug("Reading client stdout\n");
    21932248            for (;;) {
     
    21952250                char *line;
    21962251               
    2197                 line = GetLine(&proxyPtr->client, &nBytes);
     2252                line = NextLine(&proxyPtr->client, &nBytes);
    21982253                if (line != NULL) {
    21992254                    const char *cmd;
     
    22022257                    cmd = Tcl_DStringValue(&clientCmds);
    22032258                    if (Tcl_CommandComplete(cmd)) {
     2259                        int result;
     2260
    22042261                        /* May execute more than one command. */
    2205                         ExecuteCommand(proxyPtr->interp, cmd);
     2262                        result = ExecuteCommand(proxyPtr->interp, cmd);
     2263                        if (result != TCL_OK) {
     2264                            Tcl_Obj *objPtr;
     2265
     2266                            objPtr = Tcl_GetObjResult(proxyPtr->interp);
     2267                            ERROR(Tcl_GetString(objPtr));
     2268                            goto error;
     2269                        }
    22062270                        Tcl_DStringSetLength(&clientCmds, 0);
    22072271                    }
     
    22112275                    break;
    22122276                }
    2213                 ERROR("Failed reading client stdout (nBytes=%d)\n", nBytes);
     2277                ERROR("can't read client stdout (nBytes=%d): %s\n", nBytes,
     2278                      strerror(errno));
    22142279                goto error;             /* Get out on EOF or error. */
    22152280            }
     
    22432308            }
    22442309        }
    2245         if ((proxyPtr->headPtr != NULL) &&
    2246             (pollResults[3].revents & POLLOUT)) {
    2247             WriteImage(proxyPtr, pollResults[3].fd);
     2310        if ((proxyPtr->headPtr != NULL) && (pollFd[2].revents & POLLOUT)) {
     2311            WriteImage(proxyPtr, pollFd[2].fd);
    22482312        }
    22492313    }
  • branches/blt4/packages/vizservers/vtkvis/CmdProc.cpp

    r2170 r2542  
    33 * Copyright (C) 2011, Purdue Research Foundation
    44 *
    5  * Author: ?
     5 * Author: George A. Howlett <gah@purdue.edu>
    66 */
    77
     
    1010
    1111#include "CmdProc.h"
     12
     13using namespace Rappture;
    1214
    1315/**
     
    2224 */
    2325static int
    24 BinaryOpSearch(Rappture::CmdSpec *specs,
     26BinaryOpSearch(CmdSpec *specs,
    2527               int nSpecs,
    2628               char *string)       /* Name of minor operation to search for */
     
    3537    length = strlen(string);
    3638    while (low <= high) {
    37         Rappture::CmdSpec *specPtr;
     39        CmdSpec *specPtr;
    3840        int compare;
    3941        int median;
     
    7678 */
    7779static int
    78 LinearOpSearch(Rappture::CmdSpec *specs,
     80LinearOpSearch(CmdSpec *specs,
    7981               int nSpecs,
    8082               char *string)       /* Name of minor operation to search for */
    8183{
    82     Rappture::CmdSpec *specPtr;
     84    CmdSpec *specPtr;
    8385    char c;
    8486    size_t length;
     
    120122 */
    121123Tcl_ObjCmdProc *
    122 Rappture::GetOpFromObj(Tcl_Interp *interp,              /* Interpreter to report errors to */
    123                        int nSpecs,                      /* Number of specifications in array */
    124                        Rappture::CmdSpec *specs,        /* Op specification array */
    125                        int operPos,                     /* Position of operation in argument
    126                                                          * list. */
    127                        int objc,                        /* Number of arguments in the argument
    128                                                          * vector.  This includes any prefixed
    129                                                          * arguments */
    130                        Tcl_Obj *const *objv,            /* Argument vector */
     124Rappture::GetOpFromObj(Tcl_Interp *interp,      /* Interpreter to report errors to */
     125                       int nSpecs,              /* Number of specifications in array */
     126                       CmdSpec *specs,          /* Op specification array */
     127                       int operPos,             /* Position of operation in argument
     128                                                 * list. */
     129                       int objc,                /* Number of arguments in the argument
     130                                                 * vector.  This includes any prefixed
     131                                                 * arguments */
     132                       Tcl_Obj *const *objv,    /* Argument vector */
    131133                       int flags)
    132134{
  • branches/blt4/packages/vizservers/vtkvis/CmdProc.h

    r2170 r2542  
    33 * Copyright (C) 2011, Purdue Research Foundation
    44 *
    5  * Author: ?
     5 * Author: George A. Howlett <gah@purdue.edu>
    66 */
    77
     
    1919 * for a function pointer associated with the operation name.
    2020 */
    21 typedef struct {
     21struct CmdSpec {
    2222    const char *name;           /**< Name of operation */
    2323    int minChars;               /**< Minimum # characters to disambiguate */
     
    2626    int maxArgs;                /**< Maximum # args required */
    2727    const char *usage;          /**< Usage message */
    28 } CmdSpec;
     28};
    2929
    30 typedef enum {
     30enum CmdSpecIndex {
    3131    CMDSPEC_ARG0,               /**< Op is the first argument. */
    3232    CMDSPEC_ARG1,               /**< Op is the second argument. */
     
    3434    CMDSPEC_ARG3,               /**< Op is the fourth argument. */
    3535    CMDSPEC_ARG4                /**< Op is the fifth argument. */
    36 } CmdSpecIndex;
     36};
    3737
    3838#define CMDSPEC_LINEAR_SEARCH   1
  • branches/blt4/packages/vizservers/vtkvis/ColorMap.cpp

    r2409 r2542  
    2121
    2222ColorMap *ColorMap::_default = NULL;
     23ColorMap *ColorMap::_grayDefault = NULL;
    2324ColorMap *ColorMap::_volumeDefault = NULL;
    2425ColorMap *ColorMap::_elementDefault = NULL;
     
    219220        }
    220221        if (itr2 == _controlPoints.end()) {
     222#ifdef DEBUG
    221223            TRACE("val: %g Range: %g - 1 Color: %g %g %g", value, itr->value,
    222224                  itr->color[0], itr->color[1], itr->color[2]);
     225#endif
    223226            memcpy(color, itr->color, sizeof(double)*3);
    224227        } else {
     
    226229            assert(value >= itr->value && value <= itr2->value);
    227230            lerp(color, *itr, *itr2, value);
     231#ifdef DEBUG
    228232            TRACE("val: %g Range: %g - %g Color: %g %g %g", value, itr->value, itr2->value,
    229233                  color[0], color[1], color[2]);
     234#endif
    230235        }
    231236        if (oitr2 == _opacityControlPoints.end()) {
     237#ifdef DEBUG
    232238            TRACE("val: %g Range: %g - 1 Alpha %g", value, oitr->value,
    233239                  oitr->alpha);
     240#endif
    234241            color[3] = oitr->alpha;
    235242        } else {
     
    237244            assert(value >= oitr->value && value <= oitr2->value);
    238245            lerp(&color[3], *oitr, *oitr2, value);
     246#ifdef DEBUG
    239247            TRACE("val: %g Range: %g - %g Alpha: %g", value, oitr->value, oitr2->value,
    240248                  color[3]);
     249#endif
    241250        }
    242251        _lookupTable->SetTableValue(i, color);
     
    329338
    330339/**
     340 * \brief Create a default ColorMap with a black-white grayscale ramp
     341 */
     342ColorMap *ColorMap::getGrayDefault()
     343{
     344    if (_grayDefault != NULL) {
     345        return _grayDefault;
     346    }
     347
     348    _grayDefault = new ColorMap("grayDefault");
     349    ControlPoint cp[2];
     350    cp[0].value = 0.0;
     351    cp[0].color[0] = 0.0;
     352    cp[0].color[1] = 0.0;
     353    cp[0].color[2] = 0.0;
     354    _grayDefault->addControlPoint(cp[0]);
     355    cp[1].value = 1.0;
     356    cp[1].color[0] = 1.0;
     357    cp[1].color[1] = 1.0;
     358    cp[1].color[2] = 1.0;
     359    _grayDefault->addControlPoint(cp[1]);
     360    OpacityControlPoint ocp[2];
     361    ocp[0].value = 0.0;
     362    ocp[0].alpha = 1.0;
     363    ocp[1].value = 1.0;
     364    ocp[1].alpha = 1.0;
     365    _grayDefault->addOpacityControlPoint(ocp[0]);
     366    _grayDefault->addOpacityControlPoint(ocp[1]);
     367    _grayDefault->build();
     368    return _grayDefault;
     369}
     370
     371/**
    331372 * \brief Create a default ColorMap with a blue-cyan-green-yellow-red ramp
    332373 * and transparent to opaque ramp
  • branches/blt4/packages/vizservers/vtkvis/ColorMap.h

    r2322 r2542  
    104104
    105105    static ColorMap *getDefault();
     106    static ColorMap *getGrayDefault();
    106107    static ColorMap *getVolumeDefault();
    107108    static ColorMap *getElementDefault();
     
    109110private:
    110111    static ColorMap *_default;
     112    static ColorMap *_grayDefault;
    111113    static ColorMap *_volumeDefault;
    112114    static ColorMap *_elementDefault;
  • branches/blt4/packages/vizservers/vtkvis/Makefile.in

    r2413 r2542  
    4747DEBUG                   = #yes
    4848TRACE                   = #yes
    49 USE_CUSTOM_AXES         = #yes
     49USE_CUSTOM_AXES         = yes
    5050USE_GPU_RAYCASTING      = yes
    51 USE_OFFSCREEN_RENDERING = #yes
     51USE_OFFSCREEN_RENDERING = yes
     52USE_THREADS             = yes
    5253
    5354#vtk uses deprecated strstream header (instead of sstream)
     
    6970ifdef USE_GPU_RAYCASTING
    7071DEFINES         += -DUSE_GPU_RAYCAST_MAPPER
     72endif
     73ifdef USE_THREADS
     74DEFINES         += -DUSE_THREADS
    7175endif
    7276CXX_SWITCHES    = $(CXXFLAGS) $(EXTRA_CFLAGS) $(DEFINES) $(INCLUDES)
     
    9599ifdef USE_CUSTOM_AXES
    96100SERVER_SRCS+=vtkRpCubeAxesActor2D.cpp
     101endif
     102ifdef USE_THREADS
     103SERVER_SRCS+=ResponseQueue.cpp
    97104endif
    98105
     
    129136CmdProc.o: CmdProc.h
    130137ColorMap.o: ColorMap.h RpMolecule.h Trace.h
    131 PPMWriter.o: PPMWriter.h Trace.h
     138PPMWriter.o: PPMWriter.h ResponseQueue.h Trace.h
     139ResponseQueue.o: ResponseQueue.h Trace.h
    132140RpContour2D.o: RpContour2D.h RpVtkGraphicsObject.h RpVtkDataSet.h Trace.h
    133 RpContour3D.o: RpContour3D.h RpVtkGraphicsObject.h RpVtkDataSet.h Trace.h
     141RpContour3D.o: RpContour3D.h RpVtkGraphicsObject.h RpVtkDataSet.h ColorMap.h Trace.h
    134142RpGlyphs.o: RpGlyphs.h RpVtkGraphicsObject.h RpVtkDataSet.h ColorMap.h Trace.h
    135 RpHeightMap.o: RpHeightMap.h RpVtkGraphicsObject.h RpVtkDataSet.h Trace.h
    136 RpLIC.o: RpLIC.h RpVtkGraphicsObject.h RpVtkDataSet.h Trace.h RpVtkRenderServer.h
     143RpHeightMap.o: RpHeightMap.h RpVtkGraphicsObject.h RpVtkDataSet.h ColorMap.h Trace.h
     144RpLIC.o: RpLIC.h RpVtkGraphicsObject.h RpVtkDataSet.h ColorMap.h Trace.h RpVtkRenderServer.h
    137145RpMolecule.o: RpMolecule.h RpMoleculeData.h RpVtkGraphicsObject.h RpVtkDataSet.h ColorMap.h Trace.h
    138146RpPolyData.o: RpPolyData.h RpVtkGraphicsObject.h RpVtkDataSet.h Trace.h
    139 RpPseudoColor.o: RpPseudoColor.h RpVtkGraphicsObject.h RpVtkDataSet.h Trace.h
    140 RpStreamlines.o: RpStreamlines.h RpVtkGraphicsObject.h RpVtkDataSet.h Trace.h
     147RpPseudoColor.o: RpPseudoColor.h RpVtkGraphicsObject.h RpVtkDataSet.h ColorMap.h Trace.h
     148RpStreamlines.o: RpStreamlines.h RpVtkGraphicsObject.h RpVtkDataSet.h ColorMap.h Trace.h
    141149RpVolume.o: RpVolume.h RpVtkGraphicsObject.h RpVtkDataSet.h ColorMap.h Trace.h
    142150RpVtkDataSet.o: RpVtkDataSet.h Trace.h
    143151RpVtkRenderer.o: RpVtkRenderer.h RpVtkDataSet.h RpContour2D.h RpContour3D.h RpGlyphs.h RpHeightMap.h RpLIC.h RpMolecule.h RpPolyData.h RpPseudoColor.h RpStreamlines.h RpVolume.h ColorMap.h Trace.h
    144 RpVtkRendererCmd.o: RpVtkRenderer.h RpVtkDataSet.h RpContour2D.h RpContour3D.h RpGlyphs.h RpHeightMap.h RpLIC.h RpMolecule.h RpPolyData.h RpPseudoColor.h RpStreamlines.h RpVolume.h ColorMap.h Trace.h CmdProc.h PPMWriter.h TGAWriter.h
    145 RpVtkRenderServer.o: RpVtkRenderServer.h RpVtkRendererCmd.h RpVtkRenderer.h Trace.h PPMWriter.h TGAWriter.h
     152RpVtkRendererCmd.o: RpVtkRenderer.h RpVtkDataSet.h RpContour2D.h RpContour3D.h RpGlyphs.h RpHeightMap.h RpLIC.h RpMolecule.h RpPolyData.h RpPseudoColor.h RpStreamlines.h RpVolume.h ColorMap.h ResponseQueue.h Trace.h CmdProc.h PPMWriter.h TGAWriter.h
     153RpVtkRenderServer.o: RpVtkRenderServer.h RpVtkRendererCmd.h RpVtkRenderer.h ResponseQueue.h Trace.h PPMWriter.h TGAWriter.h
    146154Trace.o: Trace.h
    147 TGAWriter.o: TGAWriter.h Trace.h
     155TGAWriter.o: TGAWriter.h ResponseQueue.h Trace.h
    148156vtkRpCubeAxesActor2D.o: vtkRpCubeAxesActor2D.h
  • branches/blt4/packages/vizservers/vtkvis/PPMWriter.cpp

    r2302 r2542  
    33 * Copyright (C) 2011, Purdue Research Foundation
    44 *
    5  * Author: ?
     5 * Author: George A. Howlett <gah@purdue.edu>
    66 */
    77
     
    1212#include <sys/uio.h>
    1313
     14#include "Trace.h"
    1415#include "PPMWriter.h"
    15 #include "Trace.h"
     16#ifdef USE_THREADS
     17#include "ResponseQueue.h"
     18#endif
    1619
    1720using namespace Rappture::VtkVis;
     21
     22#ifdef USE_THREADS
     23
     24/**
     25 * \brief Writes image data as PPM binary data to the client.
     26 *
     27 * The PPM binary format is very simple.
     28 *
     29 *     P6 w h 255\n
     30 *     3-byte RGB pixel data.
     31 *
     32 * The client (using the TkImg library) will do less work to unpack this
     33 * format, as opposed to BMP or PNG.
     34 *
     35 * Note that currently the image data has bottom to top scanlines.  This
     36 * routine could be made even simpler (faster) if the image data had top
     37 * to bottom scanlines.
     38 *
     39 * \param[in] queue Pointer to ResponseQueue to write to
     40 * \param[in] cmdName Command name to send (byte length will be appended)
     41 * \param[in] data Image data
     42 * \param[in] width Width of image in pixels
     43 * \param[in] height Height of image in pixels
     44 */
     45void
     46Rappture::VtkVis::queuePPM(ResponseQueue *queue, const char *cmdName,
     47                           const unsigned char *data, int width, int height)
     48{
     49#define PPM_MAXVAL 255
     50    char header[200];
     51
     52    TRACE("Entering (%dx%d)\n", width, height);
     53    // Generate the PPM binary file header
     54    snprintf(header, sizeof(header), "P6 %d %d %d\n", width, height,
     55             PPM_MAXVAL);
     56
     57    size_t headerLength = strlen(header);
     58    size_t dataLength = width * height * 3;
     59
     60    char command[200];
     61    snprintf(command, sizeof(command), "%s %lu\n", cmdName,
     62             (unsigned long)headerLength + dataLength);
     63
     64    size_t cmdLength;
     65    cmdLength = strlen(command);
     66
     67    size_t length;
     68    unsigned char *mesg;
     69
     70    length = headerLength + dataLength + cmdLength;
     71    mesg = (unsigned char *)malloc(length);
     72    if (mesg == NULL) {
     73        ERROR("can't allocate %ld bytes for the image message", length);
     74        return;
     75    }
     76    memcpy(mesg, command, cmdLength);
     77    memcpy(mesg + cmdLength, header, headerLength);
     78
     79    size_t bytesPerRow = width * 3;
     80    unsigned char *destRowPtr = mesg + length - bytesPerRow;
     81    int y;
     82    unsigned char *srcRowPtr = const_cast<unsigned char *>(data);
     83    for (y = 0; y < height; y++) {
     84        memcpy(destRowPtr, srcRowPtr, bytesPerRow);
     85        srcRowPtr += bytesPerRow;
     86        destRowPtr -= bytesPerRow;
     87    }
     88
     89    Response *response;
     90    if (strncmp(cmdName, "nv>legend", 9) == 0) {
     91        response = new Response(Response::LEGEND);
     92    } else {
     93        response = new Response(Response::IMAGE);
     94    }
     95    response->setMessage(mesg, length, Response::DYNAMIC);
     96    queue->enqueue(response);
     97    TRACE("Leaving (%dx%d)\n", width, height);
     98}
     99#else
    18100
    19101/**
     
    39121 */
    40122void
    41 Rappture::VtkVis::writePPM(int fd, const char *cmdName, const unsigned char *data,
    42                            int width, int height)
     123Rappture::VtkVis::writePPM(int fd, const char *cmdName,
     124                           const unsigned char *data, int width, int height)
    43125{
    44126#define PPM_MAXVAL 255
     
    47129    TRACE("Entering (%dx%d)\n", width, height);
    48130    // Generate the PPM binary file header
    49     snprintf(header, sizeof(header), "P6 %d %d %d\n", width, height, PPM_MAXVAL);
     131    snprintf(header, sizeof(header), "P6 %d %d %d\n", width, height,
     132             PPM_MAXVAL);
    50133
    51134    size_t headerLength = strlen(header);
     
    79162    }
    80163    if (writev(fd, iov, nRecs) < 0) {
    81         ERROR("write failed: %s\n", strerror(errno));
     164        ERROR("write failed: %s\n", strerror(errno));
    82165    }
    83166    free(iov);
     
    85168    TRACE("Leaving (%dx%d)\n", width, height);
    86169}
     170
     171#endif /*USE_THREADS*/
  • branches/blt4/packages/vizservers/vtkvis/PPMWriter.h

    r2120 r2542  
    33 * Copyright (C) 2011, Purdue Research Foundation
    44 *
    5  * Author: ?
     5 * Author: George A. Howlett <gah@purdue.edu>
    66 */
    77
     
    99#define __RAPPTURE_VTKVIS_PPMWRITER_H__
    1010
     11#ifdef USE_THREADS
     12#include "ResponseQueue.h"
     13#endif
     14
    1115namespace Rappture {
    1216namespace VtkVis {
    13 
     17#ifdef USE_THREADS
    1418extern
    15 void writePPM(int fd, const char *cmdName, const unsigned char *data, int width, int height);
    16 
     19void queuePPM(ResponseQueue *queue, const char *cmdName,
     20              const unsigned char *data, int width, int height);
     21#else
     22extern
     23void writePPM(int fd, const char *cmdName,
     24              const unsigned char *data, int width, int height);
     25#endif
    1726}
    1827}
    19 
    2028#endif
  • branches/blt4/packages/vizservers/vtkvis/RpContour2D.cpp

    r2409 r2542  
    1313#include <vtkCellDataToPointData.h>
    1414#include <vtkContourFilter.h>
     15#include <vtkStripper.h>
    1516#include <vtkPolyDataMapper.h>
    1617#include <vtkUnstructuredGrid.h>
    1718#include <vtkProperty.h>
     19#include <vtkTransform.h>
    1820#include <vtkDelaunay2D.h>
    1921#include <vtkDelaunay3D.h>
     
    2527using namespace Rappture::VtkVis;
    2628
    27 Contour2D::Contour2D() :
     29Contour2D::Contour2D(int numContours) :
    2830    VtkGraphicsObject(),
    29     _numContours(0)
    30 {
    31     _dataRange[0] = 0;
    32     _dataRange[1] = 1;
     31    _numContours(numContours)
     32{
     33    _edgeColor[0] = _color[0];
     34    _edgeColor[1] = _color[0];
     35    _edgeColor[2] = _color[0];
     36    _lighting = false;
     37}
     38
     39Contour2D::Contour2D(const std::vector<double>& contours) :
     40    VtkGraphicsObject(),
     41    _numContours(contours.size()),
     42    _contours(contours)
     43{
     44    _edgeColor[0] = _color[0];
     45    _edgeColor[1] = _color[0];
     46    _edgeColor[2] = _color[0];
     47    _lighting = false;
    3348}
    3449
     
    4156        TRACE("Deleting Contour2D with NULL DataSet");
    4257#endif
    43 }
    44 
    45 /**
    46  * \brief Specify input DataSet used to extract contours
    47  */
    48 void Contour2D::setDataSet(DataSet *dataSet)
    49 {
    50     if (_dataSet != dataSet) {
    51         _dataSet = dataSet;
    52 
    53         if (_dataSet != NULL) {
    54             double dataRange[2];
    55             _dataSet->getDataRange(dataRange);
    56             _dataRange[0] = dataRange[0];
    57             _dataRange[1] = dataRange[1];
    58         }
    59 
    60         update();
    61     }
    62 }
    63 
    64 /**
    65  * \brief Create and initialize a VTK Prop to render isolines
    66  */
    67 void Contour2D::initProp()
    68 {
    69     if (_prop == NULL) {
    70         _prop = vtkSmartPointer<vtkActor>::New();
    71         vtkProperty *property = getActor()->GetProperty();
    72         property->EdgeVisibilityOn();
    73         property->SetEdgeColor(_edgeColor[0], _edgeColor[1], _edgeColor[2]);
    74         property->SetLineWidth(_edgeWidth);
    75         property->SetOpacity(_opacity);
    76         property->SetAmbient(.2);
    77         property->LightingOff();
    78     }
    7958}
    8059
     
    121100            pd->GetNumberOfStrips() == 0) {
    122101            // DataSet is a point cloud
    123             if (_dataSet->is2D()) {
     102            DataSet::PrincipalPlane plane;
     103            double offset;
     104            if (_dataSet->is2D(&plane, &offset)) {
    124105                vtkSmartPointer<vtkDelaunay2D> mesher = vtkSmartPointer<vtkDelaunay2D>::New();
     106                if (plane == DataSet::PLANE_ZY) {
     107                    vtkSmartPointer<vtkTransform> trans = vtkSmartPointer<vtkTransform>::New();
     108                    trans->RotateWXYZ(90, 0, 1, 0);
     109                    if (offset != 0.0) {
     110                        trans->Translate(-offset, 0, 0);
     111                    }
     112                    mesher->SetTransform(trans);
     113                } else if (plane == DataSet::PLANE_XZ) {
     114                    vtkSmartPointer<vtkTransform> trans = vtkSmartPointer<vtkTransform>::New();
     115                    trans->RotateWXYZ(-90, 1, 0, 0);
     116                    if (offset != 0.0) {
     117                        trans->Translate(0, -offset, 0);
     118                    }
     119                    mesher->SetTransform(trans);
     120                } else if (offset != 0.0) {
     121                    // XY with Z offset
     122                    vtkSmartPointer<vtkTransform> trans = vtkSmartPointer<vtkTransform>::New();
     123                    trans->Translate(0, 0, -offset);
     124                    mesher->SetTransform(trans);
     125                }
    125126                mesher->SetInput(pd);
    126127                _contourFilter->SetInputConnection(mesher->GetOutputPort());
     
    168169        _contourMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
    169170        _contourMapper->SetResolveCoincidentTopologyToPolygonOffset();
    170         _contourMapper->SetInputConnection(_contourFilter->GetOutputPort());
     171        _contourMapper->ScalarVisibilityOff();
     172        vtkSmartPointer<vtkStripper> stripper = vtkSmartPointer<vtkStripper>::New();
     173        stripper->SetInputConnection(_contourFilter->GetOutputPort());
     174        _contourMapper->SetInputConnection(stripper->GetOutputPort());
    171175        getActor()->SetMapper(_contourMapper);
    172176    }
    173177
    174178    _contourMapper->Update();
     179}
     180
     181void Contour2D::updateRanges(bool useCumulative,
     182                             double scalarRange[2],
     183                             double vectorMagnitudeRange[2],
     184                             double vectorComponentRange[3][2])
     185{
     186    if (useCumulative) {
     187        _dataRange[0] = scalarRange[0];
     188        _dataRange[1] = scalarRange[1];
     189    } else if (_dataSet != NULL) {
     190        _dataSet->getScalarRange(_dataRange);
     191    } else {
     192        WARN("updateRanges called before setDataSet");
     193    }
     194
     195    if (_contours.empty() && _numContours > 0) {
     196        // Contour isovalues need to be recomputed
     197        update();
     198    }
    175199}
    176200
     
    185209    _numContours = numContours;
    186210
    187     if (_dataSet != NULL) {
    188         double dataRange[2];
    189         _dataSet->getDataRange(dataRange);
    190         _dataRange[0] = dataRange[0];
    191         _dataRange[1] = dataRange[1];
    192     }
    193 
    194     update();
    195 }
    196 
    197 /**
    198  * \brief Specify number of evenly spaced contour lines to render
    199  * between the given range (including range endpoints)
    200  *
    201  * Will override any existing contours
    202  */
    203 void Contour2D::setContours(int numContours, double range[2])
    204 {
    205     _contours.clear();
    206     _numContours = numContours;
    207 
    208     _dataRange[0] = range[0];
    209     _dataRange[1] = range[1];
    210 
    211211    update();
    212212}
  • branches/blt4/packages/vizservers/vtkvis/RpContour2D.h

    r2409 r2542  
    2727class Contour2D : public VtkGraphicsObject {
    2828public:
    29     Contour2D();
     29    Contour2D(int numContours);
     30
     31    Contour2D(const std::vector<double>& contours);
     32
    3033    virtual ~Contour2D();
    3134
     
    3538    }
    3639
    37     virtual void setDataSet(DataSet *dataset);
    38 
    3940    virtual void setClippingPlanes(vtkPlaneCollection *planes);
    4041
    4142    void setContours(int numContours);
    42 
    43     void setContours(int numContours, double range[2]);
    4443
    4544    void setContourList(const std::vector<double>& contours);
     
    4948    const std::vector<double>& getContourList() const;
    5049
     50    virtual void updateRanges(bool useCumulative,
     51                              double scalarRange[2],
     52                              double vectorMagnitudeRange[2],
     53                              double vectorComponentRange[3][2]);
     54
     55    virtual void setColor(float color[3])
     56    {
     57        VtkGraphicsObject::setColor(color);
     58        VtkGraphicsObject::setEdgeColor(color);
     59    }
     60
     61    virtual void setEdgeColor(float color[3])
     62    {
     63        setColor(color);
     64    }
     65
    5166private:
    52     virtual void initProp();
     67    Contour2D();
     68
    5369    virtual void update();
    5470
    5571    int _numContours;
    5672    std::vector<double> _contours;
    57     double _dataRange[2];
    5873
    5974    vtkSmartPointer<vtkContourFilter> _contourFilter;
  • branches/blt4/packages/vizservers/vtkvis/RpContour3D.cpp

    r2409 r2542  
    2525using namespace Rappture::VtkVis;
    2626
    27 Contour3D::Contour3D() :
     27Contour3D::Contour3D(int numContours) :
    2828    VtkGraphicsObject(),
    29     _numContours(0)
    30 {
    31     _dataRange[0] = 0;
    32     _dataRange[1] = 1;
     29    _numContours(numContours),
     30    _colorMap(NULL)
     31{
     32    _color[0] = 0.0f;
     33    _color[1] = 0.0f;
     34    _color[2] = 1.0f;
     35}
     36
     37Contour3D::Contour3D(const std::vector<double>& contours) :
     38    VtkGraphicsObject(),
     39    _numContours(contours.size()),
     40    _contours(contours),
     41    _colorMap(NULL)
     42{
    3343    _color[0] = 0.0f;
    3444    _color[1] = 0.0f;
     
    4757
    4858/**
    49  * \brief Specify input DataSet used to extract contours
    50  */
    51 void Contour3D::setDataSet(DataSet *dataSet)
    52 {
    53     if (_dataSet != dataSet) {
    54         _dataSet = dataSet;
    55 
    56         if (_dataSet != NULL) {
    57             double dataRange[2];
    58             _dataSet->getDataRange(dataRange);
    59             _dataRange[0] = dataRange[0];
    60             _dataRange[1] = dataRange[1];
    61         }
    62 
    63         update();
    64     }
    65 }
    66 
    67 /**
    68  * \brief Create and initialize a VTK Prop to render isosurfaces
    69  */
    70 void Contour3D::initProp()
    71 {
    72     if (_prop == NULL) {
    73         _prop = vtkSmartPointer<vtkActor>::New();
    74         vtkProperty *property = getActor()->GetProperty();
    75         property->EdgeVisibilityOff();
    76         property->SetColor(_color[0], _color[1], _color[2]);
    77         property->SetEdgeColor(_edgeColor[0], _edgeColor[1], _edgeColor[2]);
    78         property->SetLineWidth(_edgeWidth);
    79         property->SetOpacity(_opacity);
    80         property->SetAmbient(.2);
    81         if (!_lighting)
    82             property->LightingOff();
    83     }
    84 }
    85 
    86 /**
    87  * \brief Get the VTK colormap lookup table in use
    88  */
    89 vtkLookupTable *Contour3D::getLookupTable()
    90 {
    91     return _lut;
     59 * \brief Called when the color map has been edited
     60 */
     61void Contour3D::updateColorMap()
     62{
     63    setColorMap(_colorMap);
    9264}
    9365
     
    9567 * \brief Associate a colormap lookup table with the DataSet
    9668 */
    97 void Contour3D::setLookupTable(vtkLookupTable *lut)
    98 {
    99     if (lut == NULL) {
     69void Contour3D::setColorMap(ColorMap *cmap)
     70{
     71    if (cmap == NULL)
     72        return;
     73
     74    _colorMap = cmap;
     75 
     76    if (_lut == NULL) {
    10077        _lut = vtkSmartPointer<vtkLookupTable>::New();
    101     } else {
    102         _lut = lut;
    103     }
    104 
    105     if (_contourMapper != NULL) {
    106         _contourMapper->UseLookupTableScalarRangeOn();
    107         _contourMapper->SetLookupTable(_lut);
    108     }
     78        if (_contourMapper != NULL) {
     79            _contourMapper->UseLookupTableScalarRangeOn();
     80            _contourMapper->SetLookupTable(_lut);
     81        }
     82    }
     83
     84    _lut->DeepCopy(cmap->getLookupTable());
     85    _lut->SetRange(_dataRange);
    10986}
    11087
     
    198175    }
    199176
    200     if (ds->GetPointData() == NULL ||
    201         ds->GetPointData()->GetScalars() == NULL) {
    202         if (_lut == NULL) {
    203             _lut = vtkSmartPointer<vtkLookupTable>::New();
    204         }
    205     } else {
    206         vtkLookupTable *lut = ds->GetPointData()->GetScalars()->GetLookupTable();
    207         TRACE("Data set scalars lookup table: %p\n", lut);
    208         if (_lut == NULL) {
    209             if (lut)
    210                 _lut = lut;
    211             else
    212                 _lut = vtkSmartPointer<vtkLookupTable>::New();
    213         }
    214     }
    215 
    216     if (_lut != NULL) {
    217         _lut->SetRange(_dataRange);
    218 
    219         _contourMapper->SetColorModeToMapScalars();
    220         _contourMapper->UseLookupTableScalarRangeOn();
    221         _contourMapper->SetLookupTable(_lut);
     177    if (_lut == NULL) {
     178        setColorMap(ColorMap::getDefault());
    222179    }
    223180
     
    228185}
    229186
     187void Contour3D::updateRanges(bool useCumulative,
     188                             double scalarRange[2],
     189                             double vectorMagnitudeRange[2],
     190                             double vectorComponentRange[3][2])
     191{
     192    if (useCumulative) {
     193        _dataRange[0] = scalarRange[0];
     194        _dataRange[1] = scalarRange[1];
     195    } else if (_dataSet != NULL) {
     196        _dataSet->getScalarRange(_dataRange);
     197    }
     198
     199    if (_lut != NULL) {
     200        _lut->SetRange(_dataRange);
     201    }
     202
     203    if (_contours.empty() && _numContours > 0) {
     204        // Need to recompute isovalues
     205        update();
     206    }
     207}
     208
    230209/**
    231210 * \brief Specify number of evenly spaced isosurfaces to render
     
    238217    _numContours = numContours;
    239218
    240     if (_dataSet != NULL) {
    241         double dataRange[2];
    242         _dataSet->getDataRange(dataRange);
    243         _dataRange[0] = dataRange[0];
    244         _dataRange[1] = dataRange[1];
    245     }
    246 
    247     update();
    248 }
    249 
    250 /**
    251  * \brief Specify number of evenly spaced isosurfaces to render
    252  * between the given range (including range endpoints)
    253  *
    254  * Will override any existing contours
    255  */
    256 void Contour3D::setContours(int numContours, double range[2])
    257 {
    258     _contours.clear();
    259     _numContours = numContours;
    260 
    261     _dataRange[0] = range[0];
    262     _dataRange[1] = range[1];
    263 
    264219    update();
    265220}
  • branches/blt4/packages/vizservers/vtkvis/RpContour3D.h

    r2409 r2542  
    1818#include <vector>
    1919
     20#include "ColorMap.h"
    2021#include "RpVtkGraphicsObject.h"
    2122
     
    2829class Contour3D : public VtkGraphicsObject {
    2930public:
    30     Contour3D();
     31    Contour3D(int numContours);
     32
     33    Contour3D(const std::vector<double>& contours);
     34
    3135    virtual ~Contour3D();
    3236
     
    3640    }
    3741
    38     virtual void setDataSet(DataSet *dataset);
    39 
    4042    virtual void setClippingPlanes(vtkPlaneCollection *planes);
    4143
    4244    void setContours(int numContours);
    43 
    44     void setContours(int numContours, double range[2]);
    4545
    4646    void setContourList(const std::vector<double>& contours);
     
    5050    const std::vector<double>& getContourList() const;
    5151
    52     void setLookupTable(vtkLookupTable *lut);
     52    void setColorMap(ColorMap *colorMap);
    5353
    54     vtkLookupTable *getLookupTable();
     54    /**
     55     * \brief Return the ColorMap in use
     56     */
     57    ColorMap *getColorMap()
     58    {
     59        return _colorMap;
     60    }
     61
     62    void updateColorMap();
     63
     64    virtual void updateRanges(bool useCumulative,
     65                              double scalarRange[2],
     66                              double vectorMagnitudeRange[2],
     67                              double vectorComponentRange[3][2]);
    5568
    5669private:
    57     virtual void initProp();
     70    Contour3D();
     71
    5872    virtual void update();
    5973
    6074    int _numContours;
    6175    std::vector<double> _contours;
    62     double _dataRange[2];
     76    ColorMap *_colorMap;
    6377
    6478    vtkSmartPointer<vtkContourFilter> _contourFilter;
  • branches/blt4/packages/vizservers/vtkvis/RpGlyphs.cpp

    r2409 r2542  
    1414#include <vtkProperty.h>
    1515#include <vtkGlyph3D.h>
     16#include <vtkLineSource.h>
    1617#include <vtkArrowSource.h>
    1718#include <vtkConeSource.h>
     
    1920#include <vtkPlatonicSolidSource.h>
    2021#include <vtkSphereSource.h>
     22#include <vtkTransform.h>
    2123#include <vtkPolyDataMapper.h>
     24#include <vtkTransformPolyDataFilter.h>
    2225
    2326#include "RpGlyphs.h"
     
    2629using namespace Rappture::VtkVis;
    2730
    28 Glyphs::Glyphs() :
     31Glyphs::Glyphs(GlyphShape shape) :
    2932    VtkGraphicsObject(),
    30     _glyphShape(ARROW),
     33    _glyphShape(shape),
     34    _scalingMode(SCALE_BY_VECTOR_MAGNITUDE),
     35    _dataScale(1.0),
    3136    _scaleFactor(1.0),
    32     _colorMode(COLOR_BY_SCALAR)
     37    _normalizeScale(true),
     38    _colorMode(COLOR_BY_SCALAR),
     39    _colorMap(NULL)
    3340{
    3441    _faceCulling = true;
     
    3946}
    4047
     48void Glyphs::setDataSet(DataSet *dataSet,
     49                        bool useCumulative,
     50                        double scalarRange[2],
     51                        double vectorMagnitudeRange[2],
     52                        double vectorComponentRange[3][2])
     53{
     54    if (_dataSet != dataSet) {
     55        _dataSet = dataSet;
     56
     57        if (useCumulative) {
     58            _dataRange[0] = scalarRange[0];
     59            _dataRange[1] = scalarRange[1];
     60            _vectorMagnitudeRange[0] = vectorMagnitudeRange[0];
     61            _vectorMagnitudeRange[1] = vectorMagnitudeRange[1];
     62            for (int i = 0; i < 3; i++) {
     63                _vectorComponentRange[i][0] = vectorComponentRange[i][0];
     64                _vectorComponentRange[i][1] = vectorComponentRange[i][1];
     65            }
     66        } else {
     67            _dataSet->getScalarRange(_dataRange);
     68            _dataSet->getVectorRange(_vectorMagnitudeRange);
     69            for (int i = 0; i < 3; i++) {
     70                _dataSet->getVectorRange(_vectorComponentRange[i], i);
     71            }
     72        }
     73
     74        update();
     75    }
     76}
     77
    4178/**
    4279 * \brief Set the shape of the glyphs
     
    4582{
    4683    _glyphShape = shape;
     84
     85    // Note: using vtkTransformPolyDataFilter instead of the vtkGlyph3D's
     86    // SourceTransform because of a bug: vtkGlyph3D doesn't transform normals
     87    // by the SourceTransform, so the lighting would be wrong
     88
    4789    switch (_glyphShape) {
     90    case LINE:
     91        _glyphSource = vtkSmartPointer<vtkLineSource>::New();
     92        break;
    4893    case ARROW:
    49         _glyphSource = vtkSmartPointer<vtkArrowSource>::New();
    50         break;
     94        _glyphSource = vtkSmartPointer<vtkArrowSource>::New();
     95        break;
    5196    case CONE:
    52         _glyphSource = vtkSmartPointer<vtkConeSource>::New();
    53         break;
     97        _glyphSource = vtkSmartPointer<vtkConeSource>::New();
     98        break;
    5499    case CUBE:
    55         _glyphSource = vtkSmartPointer<vtkPlatonicSolidSource>::New();
    56         vtkPlatonicSolidSource::SafeDownCast(_glyphSource)->SetSolidTypeToCube();
    57         break;
    58     case CYLINDER:
    59         _glyphSource = vtkSmartPointer<vtkCylinderSource>::New();
    60         break;
     100        _glyphSource = vtkSmartPointer<vtkPlatonicSolidSource>::New();
     101        vtkPlatonicSolidSource::SafeDownCast(_glyphSource)->SetSolidTypeToCube();
     102        break;
     103    case CYLINDER: {
     104        vtkSmartPointer<vtkCylinderSource> csource = vtkSmartPointer<vtkCylinderSource>::New();
     105        vtkCylinderSource::SafeDownCast(csource)->SetResolution(6);
     106        _glyphSource = vtkSmartPointer<vtkTransformPolyDataFilter>::New();
     107        _glyphSource->SetInputConnection(csource->GetOutputPort());
     108        vtkSmartPointer<vtkTransform> trans = vtkSmartPointer<vtkTransform>::New();
     109        trans->RotateZ(-90.0);
     110        vtkTransformPolyDataFilter::SafeDownCast(_glyphSource)->SetTransform(trans);
     111      }
     112        break;
    61113    case DODECAHEDRON:
    62         _glyphSource = vtkSmartPointer<vtkPlatonicSolidSource>::New();
    63         vtkPlatonicSolidSource::SafeDownCast(_glyphSource)->SetSolidTypeToDodecahedron();
    64         break;
     114        _glyphSource = vtkSmartPointer<vtkPlatonicSolidSource>::New();
     115        vtkPlatonicSolidSource::SafeDownCast(_glyphSource)->SetSolidTypeToDodecahedron();
     116        break;
    65117    case ICOSAHEDRON:
    66         _glyphSource = vtkSmartPointer<vtkPlatonicSolidSource>::New();
    67         vtkPlatonicSolidSource::SafeDownCast(_glyphSource)->SetSolidTypeToIcosahedron();
    68         break;
     118        _glyphSource = vtkSmartPointer<vtkPlatonicSolidSource>::New();
     119        vtkPlatonicSolidSource::SafeDownCast(_glyphSource)->SetSolidTypeToIcosahedron();
     120        break;
    69121    case OCTAHEDRON:
    70         _glyphSource = vtkSmartPointer<vtkPlatonicSolidSource>::New();
    71         vtkPlatonicSolidSource::SafeDownCast(_glyphSource)->SetSolidTypeToOctahedron();
    72         break;
     122        _glyphSource = vtkSmartPointer<vtkPlatonicSolidSource>::New();
     123        vtkPlatonicSolidSource::SafeDownCast(_glyphSource)->SetSolidTypeToOctahedron();
     124        break;
    73125    case SPHERE:
    74         _glyphSource = vtkSmartPointer<vtkSphereSource>::New();
    75         break;
     126        _glyphSource = vtkSmartPointer<vtkSphereSource>::New();
     127        break;
    76128    case TETRAHEDRON:
    77         _glyphSource = vtkSmartPointer<vtkPlatonicSolidSource>::New();
    78         vtkPlatonicSolidSource::SafeDownCast(_glyphSource)->SetSolidTypeToTetrahedron();
    79         break;
     129        // FIXME: need to rotate inital orientation
     130        _glyphSource = vtkSmartPointer<vtkPlatonicSolidSource>::New();
     131        vtkPlatonicSolidSource::SafeDownCast(_glyphSource)->SetSolidTypeToTetrahedron();
     132        break;
    80133    default:
    81         ERROR("Unknown glyph shape: %d", _glyphShape);
    82         return;
     134        ERROR("Unknown glyph shape: %d", _glyphShape);
     135        return;
    83136    }
    84137
     
    91144    }
    92145
     146#ifdef HAVE_GLYPH3D_MAPPER
     147    if (_glyphMapper != NULL) {
     148        _glyphMapper->SetSourceConnection(_glyphSource->GetOutputPort());
     149    }
     150#else
    93151    if (_glyphGenerator != NULL) {
    94         _glyphGenerator->SetSourceConnection(_glyphSource->GetOutputPort());
    95     }
     152        _glyphGenerator->SetSourceConnection(_glyphSource->GetOutputPort());
     153    }
     154#endif
    96155}
    97156
     
    107166    vtkDataSet *ds = _dataSet->getVtkDataSet();
    108167
     168#ifdef HAVE_GLYPH3D_MAPPER
     169    if (_glyphMapper == NULL) {
     170        _glyphMapper = vtkSmartPointer<vtkGlyph3DMapper>::New();
     171        _glyphMapper->SetResolveCoincidentTopologyToPolygonOffset();
     172        _glyphMapper->ScalarVisibilityOn();
     173    }
     174#else
    109175    if (_glyphGenerator == NULL) {
    110         _glyphGenerator = vtkSmartPointer<vtkGlyph3D>::New();
    111     }
     176        _glyphGenerator = vtkSmartPointer<vtkGlyph3D>::New();
     177    }
     178    if (_pdMapper == NULL) {
     179        _pdMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
     180        _pdMapper->SetResolveCoincidentTopologyToPolygonOffset();
     181        _pdMapper->ScalarVisibilityOn();
     182        _pdMapper->SetInputConnection(_glyphGenerator->GetOutputPort());
     183    }
     184#endif
    112185
    113186    initProp();
     
    133206    }
    134207
     208#ifdef HAVE_GLYPH3D_MAPPER
     209    _glyphMapper->SetInputConnection(ds->GetProducerPort());
     210#else
    135211    _glyphGenerator->SetInput(ds);
     212#endif
    136213
    137214    if (ds->GetPointData()->GetVectors() != NULL) {
    138         _glyphGenerator->SetScaleModeToScaleByVector();
     215        TRACE("Setting scale mode to vector magnitude");
     216        setScalingMode(SCALE_BY_VECTOR_MAGNITUDE);
    139217    } else {
    140         _glyphGenerator->SetScaleModeToScaleByScalar();
    141     }
    142     _glyphGenerator->SetScaleFactor(_scaleFactor);
     218        TRACE("Setting scale mode to scalar");
     219        setScalingMode(SCALE_BY_SCALAR);
     220    }
     221
     222    double cellSizeRange[2];
     223    double avgSize;
     224    _dataSet->getCellSizeRange(cellSizeRange, &avgSize);
     225    //_dataScale = cellSizeRange[0] + (cellSizeRange[1] - cellSizeRange[0])/2.;
     226    _dataScale = avgSize;
     227
     228    TRACE("Cell size range: %g,%g, Data scale factor: %g",
     229          cellSizeRange[0], cellSizeRange[1], _dataScale);
     230
     231    // Normalize sizes to [0,1] * ScaleFactor
     232#ifdef HAVE_GLYPH3D_MAPPER
     233    _glyphMapper->SetClamping(_normalizeScale ? 1 : 0);
     234    _glyphMapper->SetScaleFactor(_scaleFactor * _dataScale);
     235    _glyphMapper->ScalingOn();
     236#else
     237    _glyphGenerator->SetClamping(_normalizeScale ? 1 : 0);
     238    _glyphGenerator->SetScaleFactor(_scaleFactor * _dataScale);
    143239    _glyphGenerator->ScalingOn();
     240#endif
    144241
    145242    if (ds->GetPointData()->GetScalars() == NULL) {
    146243        TRACE("Setting color mode to vector magnitude");
    147         _glyphGenerator->SetColorModeToColorByVector();
    148         _colorMode = COLOR_BY_VECTOR;
     244        setColorMode(COLOR_BY_VECTOR_MAGNITUDE);
    149245    } else {
    150246        TRACE("Setting color mode to scalar");
    151         _glyphGenerator->SetColorModeToColorByScalar();
    152         _colorMode = COLOR_BY_SCALAR;
    153     }
    154     if (_glyphShape == SPHERE) {
    155         _glyphGenerator->OrientOff();
    156     }
    157 
    158     if (_pdMapper == NULL) {
    159         _pdMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
    160         _pdMapper->SetResolveCoincidentTopologyToPolygonOffset();
    161         _pdMapper->ScalarVisibilityOn();
    162     }
    163     _pdMapper->SetInputConnection(_glyphGenerator->GetOutputPort());
    164 
    165     if (ds->GetPointData() == NULL ||
    166         ds->GetPointData()->GetScalars() == NULL) {
    167         if (_lut == NULL) {
    168             _lut = vtkSmartPointer<vtkLookupTable>::New();
    169         }
    170     } else {
    171         vtkLookupTable *lut = ds->GetPointData()->GetScalars()->GetLookupTable();
    172         TRACE("Data set scalars lookup table: %p\n", lut);
    173         if (_lut == NULL) {
    174             if (lut)
    175                 _lut = lut;
    176             else
    177                 _lut = vtkSmartPointer<vtkLookupTable>::New();
    178         }
    179     }
    180 
    181     if (ds->GetPointData()->GetScalars() == NULL) {
    182         double dataRange[2];
    183         _dataSet->getVectorMagnitudeRange(dataRange);
    184         _lut->SetRange(dataRange);
    185         //_pdMapper->SetScalarModeToUsePointFieldData();
    186         //_pdMapper->SelectColorArray(ds->GetPointData()->GetVectors()->GetName());
    187     } else {
    188         double dataRange[2];
    189         _dataSet->getDataRange(dataRange);
    190         _lut->SetRange(dataRange);
    191         //_pdMapper->SetScalarModeToDefault();
    192     }
    193 
    194     //_lut->SetVectorModeToMagnitude();
    195     _pdMapper->SetLookupTable(_lut);
    196     _pdMapper->UseLookupTableScalarRangeOn();
    197 
     247        setColorMode(COLOR_BY_SCALAR);
     248    }
     249
     250    if (_lut == NULL) {
     251        setColorMap(ColorMap::getDefault());
     252    }
     253
     254#ifdef HAVE_GLYPH3D_MAPPER
     255    getActor()->SetMapper(_glyphMapper);
     256    _glyphMapper->Update();
     257#else
    198258    getActor()->SetMapper(_pdMapper);
    199259    _pdMapper->Update();
     260#endif
     261}
     262
     263/**
     264 * \brief Control if field data range is normalized to [0,1] before
     265 * applying scale factor
     266 */
     267void Glyphs::setNormalizeScale(bool normalize)
     268{
     269    if (_normalizeScale != normalize) {
     270        _normalizeScale = normalize;
     271#ifdef HAVE_GLYPH3D_MAPPER
     272        if (_glyphMapper != NULL) {
     273            _glyphMapper->SetClamping(_normalizeScale ? 1 : 0);
     274        }
     275#else
     276        if (_glyphGenerator != NULL) {
     277            _glyphGenerator->SetClamping(_normalizeScale ? 1 : 0);
     278        }
     279#endif
     280    }
    200281}
    201282
     
    205286void Glyphs::setScalingMode(ScalingMode mode)
    206287{
     288    _scalingMode = mode;
     289#ifdef HAVE_GLYPH3D_MAPPER
     290    if (_glyphMapper != NULL) {
     291#else
    207292    if (_glyphGenerator != NULL) {
     293#endif
    208294        switch (mode) {
    209         case SCALE_BY_SCALAR:
     295        case SCALE_BY_SCALAR: {
     296#ifdef HAVE_GLYPH3D_MAPPER
     297            _glyphMapper->SetRange(_dataRange);
     298            _glyphMapper->SetScaleModeToScaleByMagnitude();
     299            _glyphMapper->SetScaleArray(vtkDataSetAttributes::SCALARS);
     300#else
     301            _glyphGenerator->SetRange(_dataRange);
    210302            _glyphGenerator->SetScaleModeToScaleByScalar();
    211             _glyphGenerator->ScalingOn();
     303#endif
     304        }
    212305            break;
    213         case SCALE_BY_VECTOR:
     306        case SCALE_BY_VECTOR_MAGNITUDE: {
     307#ifdef HAVE_GLYPH3D_MAPPER
     308            _glyphMapper->SetRange(_dataRange);
     309            _glyphMapper->SetScaleModeToScaleByMagnitude();
     310            _glyphMapper->SetScaleArray(vtkDataSetAttributes::VECTORS);
     311#else
     312            _glyphGenerator->SetRange(_vectorMagnitudeRange);
    214313            _glyphGenerator->SetScaleModeToScaleByVector();
    215             _glyphGenerator->ScalingOn();
     314#endif
     315        }
    216316            break;
    217         case SCALE_BY_VECTOR_COMPONENTS:
     317        case SCALE_BY_VECTOR_COMPONENTS: {
     318            double sizeRange[2];
     319            sizeRange[0] = _vectorComponentRange[0][0];
     320            sizeRange[1] = _vectorComponentRange[0][1];
     321            sizeRange[0] = min2(sizeRange[0], _vectorComponentRange[1][0]);
     322            sizeRange[1] = max2(sizeRange[1], _vectorComponentRange[1][1]);
     323            sizeRange[0] = min2(sizeRange[0], _vectorComponentRange[2][0]);
     324            sizeRange[1] = max2(sizeRange[1], _vectorComponentRange[2][1]);
     325#ifdef HAVE_GLYPH3D_MAPPER
     326            _glyphMapper->SetRange(sizeRange);
     327            _glyphMapper->SetScaleModeToScaleByVectorComponents();
     328            _glyphMapper->SetScaleArray(vtkDataSetAttributes::VECTORS);
     329#else
     330            _glyphGenerator->SetRange(sizeRange);
    218331            _glyphGenerator->SetScaleModeToScaleByVectorComponents();
    219             _glyphGenerator->ScalingOn();
     332#endif
     333        }
    220334            break;
    221335        case SCALING_OFF:
    222336        default:
     337#ifdef HAVE_GLYPH3D_MAPPER
     338            _glyphMapper->SetScaleModeToNoDataScaling();
     339#else
    223340            _glyphGenerator->SetScaleModeToDataScalingOff();
    224             _glyphGenerator->ScalingOff();
    225         }
    226         _pdMapper->Update();
     341#endif
     342        }
    227343    }
    228344}
     
    234350{
    235351    _colorMode = mode;
     352#ifdef HAVE_GLYPH3D_MAPPER
     353    if (_glyphMapper != NULL) {
     354#else
    236355    if (_glyphGenerator != NULL) {
     356#endif
    237357        switch (mode) {
    238         case COLOR_BY_SCALE:
    239             _glyphGenerator->SetColorModeToColorByScale();
     358        case COLOR_BY_VECTOR_MAGNITUDE: {
     359#ifdef HAVE_GLYPH3D_MAPPER
     360            _glyphMapper->ScalarVisibilityOn();
     361            _glyphMapper->SetScalarModeToUsePointFieldData();
     362            vtkDataSet *ds = _dataSet->getVtkDataSet();
     363            if (ds->GetPointData() != NULL &&
     364                ds->GetPointData()->GetVectors() != NULL) {
     365                _glyphMapper->SelectColorArray(ds->GetPointData()->GetVectors()->GetName());
     366            }
     367#else
     368            _glyphGenerator->SetColorModeToColorByVector();
    240369            _pdMapper->ScalarVisibilityOn();
    241             break;
    242         case COLOR_BY_VECTOR: {
    243             _glyphGenerator->SetColorModeToColorByVector();
    244            _pdMapper->ScalarVisibilityOn();
    245             double dataRange[2];
    246             _dataSet->getVectorMagnitudeRange(dataRange);
    247             _lut->SetRange(dataRange);
     370#endif
     371            if (_lut != NULL) {
     372                _lut->SetVectorModeToMagnitude();
     373                _lut->SetRange(_vectorMagnitudeRange);
     374            }
    248375        }
    249376            break;
    250377        case COLOR_BY_SCALAR: {
     378#ifdef HAVE_GLYPH3D_MAPPER
     379            _glyphMapper->ScalarVisibilityOn();
     380            _glyphMapper->SetScalarModeToDefault();
     381#else
    251382            _glyphGenerator->SetColorModeToColorByScalar();
    252            _pdMapper->ScalarVisibilityOn();
    253             double dataRange[2];
    254             _dataSet->getDataRange(dataRange);
    255             _lut->SetRange(dataRange);
     383            _pdMapper->ScalarVisibilityOn();
     384#endif
     385            if (_lut != NULL) {
     386                _lut->SetRange(_dataRange);
     387            }
    256388        }
    257389            break;
    258390        case COLOR_CONSTANT:
    259391        default:
     392#ifdef HAVE_GLYPH3D_MAPPER
     393            _glyphMapper->ScalarVisibilityOff();
     394#else
    260395            _pdMapper->ScalarVisibilityOff();
    261         }
    262         _pdMapper->Update();
    263     }
     396#endif
     397        }
     398     }
    264399}
    265400
     
    270405{
    271406    _scaleFactor = scale;
     407#ifdef HAVE_GLYPH3D_MAPPER
     408    if (_glyphMapper != NULL) {
     409        _glyphMapper->SetScaleFactor(_scaleFactor * _dataScale);
     410    }
     411#else
    272412    if (_glyphGenerator != NULL) {
    273         _glyphGenerator->SetScaleFactor(scale);
    274         _pdMapper->Update();
    275     }
    276 }
    277 
    278 /**
    279  * \brief Get the VTK colormap lookup table in use
    280  */
    281 vtkLookupTable *Glyphs::getLookupTable()
    282 {
    283     return _lut;
     413        _glyphGenerator->SetScaleFactor(_scaleFactor * _dataScale);
     414    }
     415#endif
     416}
     417
     418void Glyphs::updateRanges(bool useCumulative,
     419                          double scalarRange[2],
     420                          double vectorMagnitudeRange[2],
     421                          double vectorComponentRange[3][2])
     422{
     423    if (useCumulative) {
     424        _dataRange[0] = scalarRange[0];
     425        _dataRange[1] = scalarRange[1];
     426        _vectorMagnitudeRange[0] = vectorMagnitudeRange[0];
     427        _vectorMagnitudeRange[1] = vectorMagnitudeRange[1];
     428        for (int i = 0; i < 3; i++) {
     429            _vectorComponentRange[i][0] = vectorComponentRange[i][0];
     430            _vectorComponentRange[i][1] = vectorComponentRange[i][1];
     431        }
     432    } else {
     433        _dataSet->getScalarRange(_dataRange);
     434        _dataSet->getVectorRange(_vectorMagnitudeRange);
     435        for (int i = 0; i < 3; i++) {
     436            _dataSet->getVectorRange(_vectorComponentRange[i], i);
     437        }
     438    }
     439
     440    // Need to update color map ranges and/or active vector field
     441    setColorMode(_colorMode);
     442    setScalingMode(_scalingMode);
     443}
     444
     445/**
     446 * \brief Called when the color map has been edited
     447 */
     448void Glyphs::updateColorMap()
     449{
     450    setColorMap(_colorMap);
    284451}
    285452
     
    287454 * \brief Associate a colormap lookup table with the DataSet
    288455 */
    289 void Glyphs::setLookupTable(vtkLookupTable *lut)
    290 {
    291     if (lut == NULL) {
     456void Glyphs::setColorMap(ColorMap *cmap)
     457{
     458    if (cmap == NULL)
     459        return;
     460
     461    _colorMap = cmap;
     462 
     463    if (_lut == NULL) {
    292464        _lut = vtkSmartPointer<vtkLookupTable>::New();
    293     } else {
    294         _lut = lut;
    295     }
     465#ifdef HAVE_GLYPH3D_MAPPER
     466        if (_glyphMapper != NULL) {
     467            _glyphMapper->UseLookupTableScalarRangeOn();
     468            _glyphMapper->SetLookupTable(_lut);
     469        }
     470#else
     471        if (_pdMapper != NULL) {
     472            _pdMapper->UseLookupTableScalarRangeOn();
     473            _pdMapper->SetLookupTable(_lut);
     474        }
     475#endif
     476    }
     477
     478    _lut->DeepCopy(cmap->getLookupTable());
    296479
    297480    switch (_colorMode) {
    298     case COLOR_BY_VECTOR: {
    299         double dataRange[2];
    300         _dataSet->getVectorMagnitudeRange(dataRange);
    301         _lut->SetRange(dataRange);
    302     }
     481    case COLOR_BY_VECTOR_MAGNITUDE:
     482        _lut->SetRange(_vectorMagnitudeRange);
     483        _lut->SetVectorModeToMagnitude();
    303484        break;
    304485    case COLOR_BY_SCALAR:
    305     default: {
    306         double dataRange[2];
    307         _dataSet->getDataRange(dataRange);
    308         _lut->SetRange(dataRange);
    309     }
    310         break;
    311     }
    312 
    313     if (_pdMapper != NULL) {
    314         _pdMapper->SetLookupTable(_lut);
     486    default:
     487        _lut->SetRange(_dataRange);
     488        break;
    315489    }
    316490}
     
    323497void Glyphs::setClippingPlanes(vtkPlaneCollection *planes)
    324498{
     499#ifdef HAVE_GLYPH3D_MAPPER
     500    if (_glyphMapper != NULL) {
     501        _glyphMapper->SetClippingPlanes(planes);
     502    }
     503#else
    325504    if (_pdMapper != NULL) {
    326505        _pdMapper->SetClippingPlanes(planes);
    327506    }
    328 }
     507#endif
     508}
  • branches/blt4/packages/vizservers/vtkvis/RpGlyphs.h

    r2409 r2542  
    1414#include <vtkProp.h>
    1515#include <vtkActor.h>
     16#ifdef HAVE_GLYPH3D_MAPPER
     17#include <vtkGlyph3DMapper.h>
     18#else
    1619#include <vtkGlyph3D.h>
     20#endif
    1721#include <vtkLookupTable.h>
    1822#include <vtkPlaneCollection.h>
     
    2731 * \brief Oriented and scaled 3D glyph shapes
    2832 *
    29  * The DataSet must be a PolyData point set
    30  * with vectors and/or scalars
     33 * The DataSet must have vectors and/or scalars
    3134 */
    3235class Glyphs : public VtkGraphicsObject {
     
    3942        DODECAHEDRON,
    4043        ICOSAHEDRON,
     44        LINE,
    4145        OCTAHEDRON,
    4246        SPHERE,
     
    4549    enum ScalingMode {
    4650        SCALE_BY_SCALAR,
    47         SCALE_BY_VECTOR,
     51        SCALE_BY_VECTOR_MAGNITUDE,
    4852        SCALE_BY_VECTOR_COMPONENTS,
    4953        SCALING_OFF
    5054    };
    5155    enum ColorMode {
    52         COLOR_BY_SCALE,
    5356        COLOR_BY_SCALAR,
    54         COLOR_BY_VECTOR,
     57        COLOR_BY_VECTOR_MAGNITUDE,
    5558        COLOR_CONSTANT
    5659    };
    5760
    58     Glyphs();
     61    Glyphs(GlyphShape shape);
    5962    virtual ~Glyphs();
    6063
     
    6467    }
    6568
     69    virtual void setDataSet(DataSet *dataSet,
     70                            bool useCumulative,
     71                            double scalarRange[2],
     72                            double vectorMagnitudeRange[2],
     73                            double vectorComponentRange[3][2]);
     74
    6675    virtual void setClippingPlanes(vtkPlaneCollection *planes);
    6776
    6877    void setScalingMode(ScalingMode mode);
     78
     79    void setNormalizeScale(bool normalize);
    6980
    7081    void setColorMode(ColorMode mode);
     
    7485    void setScaleFactor(double scale);
    7586
    76     void setLookupTable(vtkLookupTable *lut);
     87    void setColorMap(ColorMap *colorMap);
    7788
    78     vtkLookupTable *getLookupTable();
     89    /**
     90     * \brief Return the ColorMap in use
     91     */
     92    ColorMap *getColorMap()
     93    {
     94        return _colorMap;
     95    }
     96
     97    void updateColorMap();
     98
     99    virtual void updateRanges(bool useCumulative,
     100                              double scalarRange[2],
     101                              double vectorMagnitudeRange[2],
     102                              double vectorComponentRange[3][2]);
    79103
    80104private:
     105    Glyphs();
    81106    virtual void update();
     107    static inline double min2(double a, double b)
     108    {
     109        return ((a < b) ? a : b);
     110    }
     111    static inline double max2(double a, double b)
     112    {
     113        return ((a > b) ? a : b);
     114    }
    82115
    83116    GlyphShape _glyphShape;
     117    ScalingMode _scalingMode;
     118    double _dataScale;
    84119    double _scaleFactor;
     120    bool _normalizeScale;
    85121    ColorMode _colorMode;
     122    ColorMap *_colorMap;
     123    double _vectorMagnitudeRange[2];
     124    double _vectorComponentRange[3][2];
    86125
    87126    vtkSmartPointer<vtkLookupTable> _lut;
     127    vtkSmartPointer<vtkPolyDataAlgorithm> _glyphSource;
     128#ifdef HAVE_GLYPH3D_MAPPER
     129    vtkSmartPointer<vtkGlyph3DMapper> _glyphMapper;
     130#else
    88131    vtkSmartPointer<vtkGlyph3D> _glyphGenerator;
    89     vtkSmartPointer<vtkPolyDataAlgorithm> _glyphSource;
    90132    vtkSmartPointer<vtkPolyDataMapper> _pdMapper;
     133#endif
    91134};
    92135
  • branches/blt4/packages/vizservers/vtkvis/RpHeightMap.cpp

    r2409 r2542  
    1818#include <vtkImageData.h>
    1919#include <vtkLookupTable.h>
     20#include <vtkTransform.h>
    2021#include <vtkDelaunay2D.h>
    2122#include <vtkDelaunay3D.h>
    22 #include <vtkProbeFilter.h>
    2323#include <vtkGaussianSplatter.h>
    2424#include <vtkExtractVOI.h>
    2525#include <vtkDataSetSurfaceFilter.h>
    2626#include <vtkContourFilter.h>
     27#include <vtkStripper.h>
    2728#include <vtkWarpScalar.h>
    2829#include <vtkPropAssembly.h>
     30#include <vtkCutter.h>
     31#include <vtkPlane.h>
    2932
    3033#include "RpHeightMap.h"
     
    3538#define MESH_POINT_CLOUDS
    3639
    37 HeightMap::HeightMap() :
     40HeightMap::HeightMap(int numContours, double heightScale) :
    3841    VtkGraphicsObject(),
    39     _numContours(0),
     42    _numContours(numContours),
     43    _colorMap(NULL),
    4044    _contourEdgeWidth(1.0),
    41     _warpScale(1.0),
     45    _warpScale(heightScale),
    4246    _sliceAxis(Z_AXIS),
    4347    _pipelineInitialized(false)
    4448{
    45     _dataRange[0] = 0.0;
    46     _dataRange[1] = 1.0;
     49    _contourEdgeColor[0] = 1.0f;
     50    _contourEdgeColor[1] = 0.0f;
     51    _contourEdgeColor[2] = 0.0f;
     52}
     53
     54HeightMap::HeightMap(const std::vector<double>& contours, double heightScale) :
     55    VtkGraphicsObject(),
     56    _numContours(contours.size()),
     57    _contours(contours),
     58    _colorMap(NULL),
     59    _contourEdgeWidth(1.0),
     60    _warpScale(heightScale),
     61    _sliceAxis(Z_AXIS),
     62    _pipelineInitialized(false)
     63{
    4764    _contourEdgeColor[0] = 1.0f;
    4865    _contourEdgeColor[1] = 0.0f;
     
    6077}
    6178
    62 /**
    63  * \brief Specify input DataSet with scalars to colormap
    64  *
    65  * Currently the DataSet must be image data (2D uniform grid)
    66  */
    67 void HeightMap::setDataSet(DataSet *dataSet)
     79void HeightMap::setDataSet(DataSet *dataSet,
     80                           bool useCumulative,
     81                           double scalarRange[2],
     82                           double vectorMagnitudeRange[2],
     83                           double vectorComponentRange[3][2])
    6884{
    6985    if (_dataSet != dataSet) {
     
    7187
    7288        if (_dataSet != NULL) {
    73             double dataRange[2];
    74             _dataSet->getDataRange(dataRange);
    75             _dataRange[0] = dataRange[0];
    76             _dataRange[1] = dataRange[1];
     89            if (useCumulative) {
     90                _dataRange[0] = scalarRange[0];
     91                _dataRange[1] = scalarRange[1];
     92            } else {
     93                dataSet->getScalarRange(_dataRange);
     94            }
    7795
    7896            // Compute a data scaling factor to make maximum
     
    120138        _contourActor = vtkSmartPointer<vtkActor>::New();
    121139        _contourActor->GetProperty()->SetOpacity(_opacity);
     140        _contourActor->GetProperty()->SetColor(_contourEdgeColor[0],
     141                                               _contourEdgeColor[1],
     142                                               _contourEdgeColor[2]);
    122143        _contourActor->GetProperty()->SetEdgeColor(_contourEdgeColor[0],
    123144                                                   _contourEdgeColor[1],
    124145                                                   _contourEdgeColor[2]);
    125146        _contourActor->GetProperty()->SetLineWidth(_contourEdgeWidth);
    126         _contourActor->GetProperty()->EdgeVisibilityOn();
     147        _contourActor->GetProperty()->EdgeVisibilityOff();
    127148        _contourActor->GetProperty()->SetAmbient(.2);
    128149        _contourActor->GetProperty()->LightingOff();
     150    }
     151    if (_prop == NULL) {
     152        _prop = vtkSmartPointer<vtkAssembly>::New();
     153        getAssembly()->AddPart(_dsActor);
     154        getAssembly()->AddPart(_contourActor);
    129155    }
    130156}
     
    150176    if (_dsMapper == NULL) {
    151177        _dsMapper = vtkSmartPointer<vtkDataSetMapper>::New();
     178        // Map scalars through lookup table regardless of type
     179        _dsMapper->SetColorModeToMapScalars();
    152180    }
    153181
     
    179207                pd->GetNumberOfStrips() == 0) {
    180208                // DataSet is a point cloud
    181                 if (_dataSet->is2D()) {
     209                DataSet::PrincipalPlane plane;
     210                double offset;
     211                if (_dataSet->is2D(&plane, &offset)) {
    182212#ifdef MESH_POINT_CLOUDS
    183213                    // Result of Delaunay2D is a PolyData
    184214                    vtkSmartPointer<vtkDelaunay2D> mesher = vtkSmartPointer<vtkDelaunay2D>::New();
     215                    if (plane == DataSet::PLANE_ZY) {
     216                        vtkSmartPointer<vtkTransform> trans = vtkSmartPointer<vtkTransform>::New();
     217                        trans->RotateWXYZ(90, 0, 1, 0);
     218                        if (offset != 0.0) {
     219                            trans->Translate(-offset, 0, 0);
     220                        }
     221                        mesher->SetTransform(trans);
     222                        _sliceAxis = X_AXIS;
     223                    } else if (plane == DataSet::PLANE_XZ) {
     224                        vtkSmartPointer<vtkTransform> trans = vtkSmartPointer<vtkTransform>::New();
     225                        trans->RotateWXYZ(-90, 1, 0, 0);
     226                        if (offset != 0.0) {
     227                            trans->Translate(0, -offset, 0);
     228                        }
     229                        mesher->SetTransform(trans);
     230                        _sliceAxis = Y_AXIS;
     231                    } else if (offset != 0.0) {
     232                        // XY with Z offset
     233                        vtkSmartPointer<vtkTransform> trans = vtkSmartPointer<vtkTransform>::New();
     234                        trans->Translate(0, 0, -offset);
     235                        mesher->SetTransform(trans);
     236                    }
    185237                    mesher->SetInput(pd);
    186238                    vtkAlgorithmOutput *warpOutput = initWarp(mesher->GetOutputPort());
     
    190242                    if (_pointSplatter == NULL)
    191243                        _pointSplatter = vtkSmartPointer<vtkGaussianSplatter>::New();
     244                    if (_volumeSlicer == NULL)
     245                        _volumeSlicer = vtkSmartPointer<vtkExtractVOI>::New();
    192246                    _pointSplatter->SetInput(pd);
    193247                    int dims[3];
    194248                    _pointSplatter->GetSampleDimensions(dims);
    195249                    TRACE("Sample dims: %d %d %d", dims[0], dims[1], dims[2]);
    196                     dims[2] = 3;
     250                    if (plane == DataSet::PLANE_ZY) {
     251                        dims[0] = 3;
     252                        _volumeSlicer->SetVOI(1, 1, 0, dims[1]-1, 0, dims[1]-1);
     253                        _sliceAxis = X_AXIS;
     254                    } else if (plane == DataSet::PLANE_XZ) {
     255                        dims[1] = 3;
     256                        _volumeSlicer->SetVOI(0, dims[0]-1, 1, 1, 0, dims[2]-1);
     257                        _sliceAxis = Y_AXIS;
     258                    } else {
     259                        dims[2] = 3;
     260                        _volumeSlicer->SetVOI(0, dims[0]-1, 0, dims[1]-1, 1, 1);
     261                    }
    197262                    _pointSplatter->SetSampleDimensions(dims);
    198263                    double bounds[6];
     
    203268                          bounds[2], bounds[3],
    204269                          bounds[4], bounds[5]);
    205                     if (_volumeSlicer == NULL)
    206                         _volumeSlicer = vtkSmartPointer<vtkExtractVOI>::New();
    207270                    _volumeSlicer->SetInputConnection(_pointSplatter->GetOutputPort());
    208                     _volumeSlicer->SetVOI(0, dims[0]-1, 0, dims[1]-1, 1, 1);
    209271                    _volumeSlicer->SetSampleRate(1, 1, 1);
    210272                    vtkSmartPointer<vtkDataSetSurfaceFilter> gf = vtkSmartPointer<vtkDataSetSurfaceFilter>::New();
     
    227289                    mesher->GetOutput()->GetBounds(bounds);
    228290                    // Sample a plane within the grid bounding box
    229                     if (_probeFilter == NULL)
    230                         _probeFilter = vtkSmartPointer<vtkProbeFilter>::New();
    231                     _probeFilter->SetSourceConnection(mesher->GetOutputPort());
    232                     vtkSmartPointer<vtkImageData> imageData = vtkSmartPointer<vtkImageData>::New();
    233                     int xdim = 256;
    234                     int ydim = 256;
    235                     int zdim = 1;
    236                     imageData->SetDimensions(xdim, ydim, zdim);
    237                     imageData->SetOrigin(bounds[0], bounds[2], bounds[4] + (bounds[5]-bounds[4])/2.);
    238                     imageData->SetSpacing((bounds[1]-bounds[0])/((double)(xdim-1)),
    239                                           (bounds[3]-bounds[2])/((double)(ydim-1)),
    240                                           0);
    241                     _probeFilter->SetInput(imageData);
     291                    vtkSmartPointer<vtkCutter> cutter = vtkSmartPointer<vtkCutter>::New();
     292                    cutter->SetInputConnection(mesher->GetOutputPort());
     293                    if (_cutPlane == NULL) {
     294                        _cutPlane = vtkSmartPointer<vtkPlane>::New();
     295                    }
     296                    _cutPlane->SetNormal(0, 0, 1);
     297                    _cutPlane->SetOrigin(0,
     298                                         0,
     299                                         bounds[4] + (bounds[5]-bounds[4])/2.);
     300                    cutter->SetCutFunction(_cutPlane);
    242301                    vtkSmartPointer<vtkDataSetSurfaceFilter> gf = vtkSmartPointer<vtkDataSetSurfaceFilter>::New();
    243302                    gf->UseStripsOn();
    244                     gf->SetInputConnection(_probeFilter->GetOutputPort());
     303                    gf->SetInputConnection(cutter->GetOutputPort());
    245304#else
    246305                    if (_pointSplatter == NULL)
     
    300359                _volumeSlicer->SetSampleRate(1, 1, 1);
    301360                gf->SetInputConnection(_volumeSlicer->GetOutputPort());
    302             } else if (imageData == NULL) {
    303                 // structured grid, unstructured grid, or rectilinear grid
     361            } else if (!_dataSet->is2D() && imageData == NULL) {
     362                // 3D structured grid, unstructured grid, or rectilinear grid
    304363                double bounds[6];
    305364                ds->GetBounds(bounds);
    306365                // Sample a plane within the grid bounding box
    307                 if (_probeFilter == NULL)
    308                     _probeFilter = vtkSmartPointer<vtkProbeFilter>::New();
    309                 _probeFilter->SetSource(ds);
    310                 vtkSmartPointer<vtkImageData> imageData = vtkSmartPointer<vtkImageData>::New();
    311                 int xdim = 256;
    312                 int ydim = 256;
    313                 int zdim = 1;
    314                 imageData->SetDimensions(xdim, ydim, zdim);
    315                 imageData->SetOrigin(bounds[0], bounds[2], bounds[4] + (bounds[5]-bounds[4])/2.);
    316                 imageData->SetSpacing((bounds[1]-bounds[0])/((double)(xdim-1)),
    317                                       (bounds[3]-bounds[2])/((double)(ydim-1)),
    318                                       0);
    319                 _probeFilter->SetInput(imageData);
    320                 gf->SetInputConnection(_probeFilter->GetOutputPort());
     366                vtkSmartPointer<vtkCutter> cutter = vtkSmartPointer<vtkCutter>::New();
     367                cutter->SetInput(ds);
     368                if (_cutPlane == NULL) {
     369                    _cutPlane = vtkSmartPointer<vtkPlane>::New();
     370                }
     371                _cutPlane->SetNormal(0, 0, 1);
     372                _cutPlane->SetOrigin(0,
     373                                     0,
     374                                     bounds[4] + (bounds[5]-bounds[4])/2.);
     375                cutter->SetCutFunction(_cutPlane);
     376                gf->SetInputConnection(cutter->GetOutputPort());
    321377            } else {
    322                 // 2D image data
     378                // 2D data
    323379                gf->SetInput(ds);
    324380            }
     
    331387    _pipelineInitialized = true;
    332388
    333     if (ds->GetPointData() == NULL ||
    334         ds->GetPointData()->GetScalars() == NULL) {
    335         ERROR("No scalar point data in dataset %s", _dataSet->getName().c_str());
    336         if (_lut == NULL) {
    337             _lut = vtkSmartPointer<vtkLookupTable>::New();
    338         }
    339     } else {
    340         vtkLookupTable *lut = ds->GetPointData()->GetScalars()->GetLookupTable();
    341         TRACE("Data set scalars lookup table: %p\n", lut);
    342         if (_lut == NULL) {
    343             if (lut)
    344                 _lut = lut;
    345             else {
    346                 _lut = vtkSmartPointer<vtkLookupTable>::New();
    347             }
    348         }
    349     }
    350 
    351     _lut->SetRange(_dataRange);
     389    if (_lut == NULL) {
     390        setColorMap(ColorMap::getDefault());
     391    }
     392    //_dsMapper->InterpolateScalarsBeforeMappingOn();
    352393
    353394    initProp();
    354 
    355     _dsMapper->SetColorModeToMapScalars();
    356     _dsMapper->UseLookupTableScalarRangeOn();
    357     _dsMapper->SetLookupTable(_lut);
    358     //_dsMapper->InterpolateScalarsBeforeMappingOn();
    359395
    360396    _contourFilter->ComputeNormalsOff();
     
    381417    if (_contourMapper == NULL) {
    382418        _contourMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
     419        _contourMapper->ScalarVisibilityOff();
    383420        _contourMapper->SetResolveCoincidentTopologyToPolygonOffset();
    384         _contourMapper->SetInputConnection(_contourFilter->GetOutputPort());
     421        vtkSmartPointer<vtkStripper> stripper = vtkSmartPointer<vtkStripper>::New();
     422        stripper->SetInputConnection(_contourFilter->GetOutputPort());
     423        _contourMapper->SetInputConnection(stripper->GetOutputPort());
    385424        _contourActor->SetMapper(_contourMapper);
    386425    }
    387426
    388427    _dsActor->SetMapper(_dsMapper);
    389 
    390     if (_prop == NULL) {
    391         _prop = vtkSmartPointer<vtkAssembly>::New();
    392         getAssembly()->AddPart(_dsActor);
    393         getAssembly()->AddPart(_contourActor);
    394     }
    395428
    396429    _dsMapper->Update();
     
    498531
    499532    if (_volumeSlicer == NULL &&
    500         _probeFilter == NULL) {
     533        _cutPlane == NULL) {
    501534        WARN("Called before update() or DataSet is not a volume");
    502535        return;
    503     }
    504 
    505     int dims[3];
    506 
    507     if (_pointSplatter != NULL) {
    508         _pointSplatter->GetSampleDimensions(dims);
    509     } else {
    510         vtkImageData *imageData = vtkImageData::SafeDownCast(_dataSet->getVtkDataSet());
    511         if (imageData == NULL) {
    512             if (_probeFilter != NULL) {
    513                 imageData = vtkImageData::SafeDownCast(_probeFilter->GetInput());
    514                 if (imageData == NULL) {
    515                     ERROR("Couldn't get probe filter input image");
    516                     return;
    517                 }
    518             } else {
    519                 ERROR("Not a volume data set");
    520                 return;
    521             }
    522         }
    523         imageData->GetDimensions(dims);
    524536    }
    525537
     
    542554    }
    543555
    544     if (_probeFilter != NULL) {
    545         vtkImageData *imageData = vtkImageData::SafeDownCast(_probeFilter->GetInput());
     556    if (_cutPlane != NULL) {
    546557        double bounds[6];
    547         assert(vtkDataSet::SafeDownCast(_probeFilter->GetSource()) != NULL);
    548         vtkDataSet::SafeDownCast(_probeFilter->GetSource())->GetBounds(bounds);
    549         int dim = 256;
    550 
     558        _dataSet->getBounds(bounds);
    551559        switch (axis) {
    552560        case X_AXIS:
    553             imageData->SetDimensions(1, dim, dim);
    554             imageData->SetOrigin(bounds[0] + (bounds[1]-bounds[0])*ratio, bounds[2], bounds[4]);
    555             imageData->SetSpacing(0,
    556                                   (bounds[3]-bounds[2])/((double)(dim-1)),
    557                                   (bounds[5]-bounds[4])/((double)(dim-1)));
     561            _cutPlane->SetNormal(1, 0, 0);
     562            _cutPlane->SetOrigin(bounds[0] + (bounds[1]-bounds[0]) * ratio,
     563                                 0,
     564                                 0);
    558565            break;
    559566        case Y_AXIS:
    560             imageData->SetDimensions(dim, 1, dim);
    561             imageData->SetOrigin(bounds[0], bounds[2] + (bounds[3]-bounds[2])*ratio, bounds[4]);
    562             imageData->SetSpacing((bounds[1]-bounds[0])/((double)(dim-1)),
    563                                   0,
    564                                   (bounds[5]-bounds[4])/((double)(dim-1)));
     567            _cutPlane->SetNormal(0, 1, 0);
     568            _cutPlane->SetOrigin(0,
     569                                 bounds[2] + (bounds[3]-bounds[2]) * ratio,
     570                                 0);
    565571            break;
    566572        case Z_AXIS:
    567             imageData->SetDimensions(dim, dim, 1);
    568             imageData->SetOrigin(bounds[0], bounds[2], bounds[4] + (bounds[5]-bounds[4])*ratio);
    569             imageData->SetSpacing((bounds[1]-bounds[0])/((double)(dim-1)),
    570                                   (bounds[3]-bounds[2])/((double)(dim-1)),
    571                                   0);
     573            _cutPlane->SetNormal(0, 0, 1);
     574            _cutPlane->SetOrigin(0,
     575                                 0,
     576                                 bounds[4] + (bounds[5]-bounds[4]) * ratio);
    572577            break;
    573578        default:
     
    576581        }
    577582    } else {
     583        int dims[3];
     584        if (_pointSplatter != NULL) {
     585            _pointSplatter->GetSampleDimensions(dims);
     586        } else {
     587            vtkImageData *imageData = vtkImageData::SafeDownCast(_dataSet->getVtkDataSet());
     588            if (imageData == NULL) {
     589                ERROR("Not a volume data set");
     590                return;
     591            }
     592            imageData->GetDimensions(dims);
     593        }
    578594        int voi[6];
    579595
     
    587603            break;
    588604        case Y_AXIS:
    589             voi[2] = voi[3] = (int)((dims[1]-1) * ratio);
    590605            voi[0] = 0;
    591606            voi[1] = dims[0]-1;
     607            voi[2] = voi[3] = (int)((dims[1]-1) * ratio);
    592608            voi[4] = 0;
    593609            voi[5] = dims[2]-1;
    594610            break;
    595611        case Z_AXIS:
    596             voi[4] = voi[5] = (int)((dims[2]-1) * ratio);
    597612            voi[0] = 0;
    598613            voi[1] = dims[0]-1;
    599614            voi[2] = 0;
    600615            voi[3] = dims[1]-1;
     616            voi[4] = voi[5] = (int)((dims[2]-1) * ratio);
    601617            break;
    602618        default:
     
    615631
    616632/**
    617  * \brief Get the VTK colormap lookup table in use
    618  */
    619 vtkLookupTable *HeightMap::getLookupTable()
    620 { 
    621     return _lut;
     633 * \brief Called when the color map has been edited
     634 */
     635void HeightMap::updateColorMap()
     636{
     637    setColorMap(_colorMap);
    622638}
    623639
     
    625641 * \brief Associate a colormap lookup table with the DataSet
    626642 */
    627 void HeightMap::setLookupTable(vtkLookupTable *lut)
    628 {
    629     if (lut == NULL) {
     643void HeightMap::setColorMap(ColorMap *cmap)
     644{
     645    if (cmap == NULL)
     646        return;
     647
     648    _colorMap = cmap;
     649 
     650    if (_lut == NULL) {
    630651        _lut = vtkSmartPointer<vtkLookupTable>::New();
    631     } else {
    632         _lut = lut;
    633     }
    634 
    635     if (_dsMapper != NULL) {
    636         _dsMapper->UseLookupTableScalarRangeOn();
    637         _dsMapper->SetLookupTable(_lut);
     652        if (_dsMapper != NULL) {
     653            _dsMapper->UseLookupTableScalarRangeOn();
     654            _dsMapper->SetLookupTable(_lut);
     655        }
     656    }
     657
     658    _lut->DeepCopy(cmap->getLookupTable());
     659    _lut->SetRange(_dataRange);
     660}
     661
     662void HeightMap::updateRanges(bool useCumulative,
     663                             double scalarRange[2],
     664                             double vectorMagnitudeRange[2],
     665                             double vectorComponentRange[3][2])
     666{
     667    if (useCumulative) {
     668        _dataRange[0] = scalarRange[0];
     669        _dataRange[1] = scalarRange[1];
     670    } else if (_dataSet != NULL) {
     671        _dataSet->getScalarRange(_dataRange);
     672    }
     673
     674    if (_lut != NULL) {
     675        _lut->SetRange(_dataRange);
     676    }
     677
     678    if (_contours.empty() && _numContours > 0) {
     679        // Need to recompute isovalues
     680        update();
    638681    }
    639682}
     
    644687 * Will override any existing contours
    645688 */
    646 void  HeightMap::setContours(int numContours)
     689void HeightMap::setNumContours(int numContours)
    647690{
    648691    _contours.clear();
    649692    _numContours = numContours;
    650 
    651     if (_dataSet != NULL) {
    652         double dataRange[2];
    653         _dataSet->getDataRange(dataRange);
    654         _dataRange[0] = dataRange[0];
    655         _dataRange[1] = dataRange[1];
    656     }
    657 
    658     update();
    659 }
    660 
    661 /**
    662  * \brief Specify number of evenly spaced contour lines to render
    663  * between the given range (including range endpoints)
    664  *
    665  * Will override any existing contours
    666  */
    667 void  HeightMap::setContours(int numContours, double range[2])
    668 {
    669     _contours.clear();
    670     _numContours = numContours;
    671 
    672     _dataRange[0] = range[0];
    673     _dataRange[1] = range[1];
    674693
    675694    update();
     
    681700 * Will override any existing contours
    682701 */
    683 void  HeightMap::setContourList(const std::vector<double>& contours)
     702void HeightMap::setContourList(const std::vector<double>& contours)
    684703{
    685704    _contours = contours;
     
    692711 * \brief Get the number of contours
    693712 */
    694 int  HeightMap::getNumContours() const
     713int HeightMap::getNumContours() const
    695714{
    696715    return _numContours;
     
    701720 * was specified in place of a list)
    702721 */
    703 const std::vector<double>&  HeightMap::getContourList() const
     722const std::vector<double>& HeightMap::getContourList() const
    704723{
    705724    return _contours;
     
    726745
    727746/**
     747 * \brief Turn on/off rendering of colormaped surface
     748 */
     749void HeightMap::setContourSurfaceVisibility(bool state)
     750{
     751    if (_dsActor != NULL) {
     752        _dsActor->SetVisibility((state ? 1 : 0));
     753    }
     754}
     755
     756/**
    728757 * \brief Turn on/off rendering of contour isolines
    729758 */
    730 void HeightMap::setContourVisibility(bool state)
     759void HeightMap::setContourLineVisibility(bool state)
    731760{
    732761    if (_contourActor != NULL) {
     
    765794    _contourEdgeColor[1] = color[1];
    766795    _contourEdgeColor[2] = color[2];
    767     if (_contourActor != NULL)
     796    if (_contourActor != NULL) {
     797        _contourActor->GetProperty()->SetColor(_contourEdgeColor[0],
     798                                               _contourEdgeColor[1],
     799                                               _contourEdgeColor[2]);
    768800        _contourActor->GetProperty()->SetEdgeColor(_contourEdgeColor[0],
    769801                                                   _contourEdgeColor[1],
    770802                                                   _contourEdgeColor[2]);
     803    }
    771804}
    772805
  • branches/blt4/packages/vizservers/vtkvis/RpHeightMap.h

    r2409 r2542  
    1212#include <vtkAlgorithmOutput.h>
    1313#include <vtkContourFilter.h>
    14 #include <vtkProbeFilter.h>
    1514#include <vtkLookupTable.h>
    1615#include <vtkDataSetMapper.h>
     
    2221#include <vtkAssembly.h>
    2322#include <vtkPolyData.h>
     23#include <vtkPlane.h>
    2424
    2525#include <vector>
    2626
     27#include "ColorMap.h"
    2728#include "RpVtkGraphicsObject.h"
    2829
     
    4142    };
    4243
    43     HeightMap();
     44    HeightMap(int numContours, double heightScale = 1.0);
     45
     46    HeightMap(const std::vector<double>& contours, double heightScale = 1.0);
     47
    4448    virtual ~HeightMap();
    4549
     
    4953    }
    5054
    51     virtual void setDataSet(DataSet *dataset);
     55    virtual void setDataSet(DataSet *dataset,
     56                            bool useCumulative,
     57                            double scalarRange[2],
     58                            double vectorMagnitudeRange[2],
     59                            double vectorComponentRange[3][2]);
    5260
    5361    virtual void setLighting(bool state);
     
    6573    void setHeightScale(double scale);
    6674
    67     void setContours(int numContours);
    68 
    69     void setContours(int numContours, double range[2]);
     75    void setNumContours(int numContours);
    7076
    7177    void setContourList(const std::vector<double>& contours);
     
    7581    const std::vector<double>& getContourList() const;
    7682
    77     void setLookupTable(vtkLookupTable *lut);
     83    void setColorMap(ColorMap *colorMap);
    7884
    79     vtkLookupTable *getLookupTable();
     85    /**
     86     * \brief Return the ColorMap in use
     87     */
     88    ColorMap *getColorMap()
     89    {
     90        return _colorMap;
     91    }
    8092
    81     void setContourVisibility(bool state);
     93    void updateColorMap();
     94
     95    virtual void updateRanges(bool useCumulative,
     96                              double scalarRange[2],
     97                              double vectorMagnitudeRange[2],
     98                              double vectorComponentRange[3][2]);
     99
     100    void setContourLineVisibility(bool state);
     101
     102    void setContourSurfaceVisibility(bool state);
    82103
    83104    void setContourEdgeColor(float color[3]);
     
    86107
    87108private:
     109    HeightMap();
     110
    88111    virtual void initProp();
    89112    virtual void update();
     
    94117    int _numContours;
    95118    std::vector<double> _contours;
    96     double _dataRange[2];
     119    ColorMap *_colorMap;
    97120
    98     float _edgeColor[3];
    99121    float _contourEdgeColor[3];
    100     float _edgeWidth;
    101122    float _contourEdgeWidth;
    102123    double _warpScale;
     
    110131    vtkSmartPointer<vtkPolyDataMapper> _contourMapper;
    111132    vtkSmartPointer<vtkGaussianSplatter> _pointSplatter;
    112     vtkSmartPointer<vtkProbeFilter> _probeFilter;
    113133    vtkSmartPointer<vtkExtractVOI> _volumeSlicer;
     134    vtkSmartPointer<vtkPlane> _cutPlane;
    114135    vtkSmartPointer<vtkWarpScalar> _warp;
    115136    vtkSmartPointer<vtkActor> _dsActor;
  • branches/blt4/packages/vizservers/vtkvis/RpLIC.cpp

    r2409 r2542  
    1818#include <vtkPainterPolyDataMapper.h>
    1919#include <vtkDataSetSurfaceFilter.h>
     20#include <vtkCutter.h>
     21#include <vtkImageMask.h>
     22#include <vtkImageCast.h>
    2023
    2124#include "RpLIC.h"
     
    2730LIC::LIC() :
    2831    VtkGraphicsObject(),
    29     _sliceAxis(Z_AXIS)
     32    _sliceAxis(Z_AXIS),
     33    _colorMap(NULL)
    3034{
    3135}
     
    5660
    5761    vtkDataSet *ds = _dataSet->getVtkDataSet();
    58 
    59     double dataRange[2];
    60     _dataSet->getDataRange(dataRange);
    61 
    62     TRACE("DataSet type: %s, range: %g - %g", _dataSet->getVtkType(),
    63           dataRange[0], dataRange[1]);
    6462
    6563    vtkSmartPointer<vtkCellDataToPointData> cellToPtData;
     
    111109        }
    112110
     111        // Need to convert to vtkImageData
    113112        double bounds[6];
    114113        ds->GetBounds(bounds);
     
    121120        if (ySize < xSize && ySize < zSize)
    122121            minDir = 1;
    123         // Sample a plane within the grid bounding box
    124122        if (_probeFilter == NULL)
    125123            _probeFilter = vtkSmartPointer<vtkProbeFilter>::New();
    126         _probeFilter->SetSource(ds);
     124
     125        if (!_dataSet->is2D()) {
     126            // Sample a plane within the grid bounding box
     127            vtkSmartPointer<vtkCutter> cutter = vtkSmartPointer<vtkCutter>::New();
     128            if (_cutPlane == NULL) {
     129                _cutPlane = vtkSmartPointer<vtkPlane>::New();
     130            }
     131            if (minDir == 0) {
     132                _cutPlane->SetNormal(1, 0, 0);
     133                _cutPlane->SetOrigin(bounds[0] + (bounds[1]-bounds[0])/2.,
     134                                     0,
     135                                     0);
     136            } else if (minDir == 1) {
     137                _cutPlane->SetNormal(0, 1, 0);
     138                _cutPlane->SetOrigin(0,
     139                                     bounds[2] + (bounds[3]-bounds[2])/2.,
     140                                     0);
     141            } else {
     142                _cutPlane->SetNormal(0, 0, 1);
     143                _cutPlane->SetOrigin(0,
     144                                     0,
     145                                     bounds[4] + (bounds[5]-bounds[4])/2.);
     146            }
     147            cutter->SetInput(ds);
     148            cutter->SetCutFunction(_cutPlane);
     149            _probeFilter->SetSourceConnection(cutter->GetOutputPort());
     150        } else {
     151            _probeFilter->SetSource(ds);
     152        }
     153
    127154        vtkSmartPointer<vtkImageData> imageData = vtkSmartPointer<vtkImageData>::New();
    128155        int xdim, ydim, zdim;
     
    170197        if (_mapper == NULL) {
    171198            _mapper = vtkSmartPointer<vtkDataSetMapper>::New();
    172         }
    173         _mapper->SetInputConnection(_lic->GetOutputPort());
     199            _mapper->SetColorModeToMapScalars();
     200        }
     201        _lic->Update();
     202        vtkSmartPointer<vtkImageCast> cast = vtkSmartPointer<vtkImageCast>::New();
     203        cast->SetInputConnection(_probeFilter->GetOutputPort());
     204        cast->SetInputArrayToProcess(0, 0, 0, vtkDataObject::FIELD_ASSOCIATION_POINTS,
     205                                     _probeFilter->GetValidPointMaskArrayName());
     206        cast->SetOutputScalarTypeToUnsignedChar();
     207        vtkSmartPointer<vtkImageMask> mask = vtkSmartPointer<vtkImageMask>::New();
     208        mask->SetInputConnection(0, _lic->GetOutputPort());
     209        mask->SetInputConnection(1, cast->GetOutputPort());
     210        _mapper->SetInputConnection(mask->GetOutputPort());
    174211    } else {
    175212        // DataSet is a PolyData
     
    189226    }
    190227
     228    if (_lut == NULL) {
     229        setColorMap(ColorMap::getGrayDefault());
     230    }
     231
    191232    initProp();
    192233    getActor()->SetMapper(_mapper);
     
    244285        double bounds[6];
    245286        assert(vtkDataSet::SafeDownCast(_probeFilter->GetSource()) != NULL);
    246         vtkDataSet::SafeDownCast(_probeFilter->GetSource())->GetBounds(bounds);
     287        _dataSet->getBounds(bounds);
    247288        int dim = 128;
    248289
     
    254295                                  (bounds[3]-bounds[2])/((double)(dim-1)),
    255296                                  (bounds[5]-bounds[4])/((double)(dim-1)));
     297            if (_cutPlane != NULL) {
     298                _cutPlane->SetNormal(1, 0, 0);
     299                _cutPlane->SetOrigin(bounds[0] + (bounds[1]-bounds[0])*ratio, 0, 0);
     300            }
    256301            break;
    257302        case Y_AXIS:
     
    261306                                  0,
    262307                                  (bounds[5]-bounds[4])/((double)(dim-1)));
     308            if (_cutPlane != NULL) {
     309                _cutPlane->SetNormal(0, 1, 0);
     310                _cutPlane->SetOrigin(0, bounds[2] + (bounds[3]-bounds[2])*ratio, 0);
     311            }
    263312            break;
    264313        case Z_AXIS:
     
    268317                                  (bounds[3]-bounds[2])/((double)(dim-1)),
    269318                                  0);
     319            if (_cutPlane != NULL) {
     320                _cutPlane->SetNormal(0, 0, 1);
     321                _cutPlane->SetOrigin(0, 0, bounds[4] + (bounds[5]-bounds[4])*ratio);
     322            }
    270323            break;
    271324        default:
     
    306359    }
    307360
     361    if (_lic != NULL)
     362        _lic->Update();
     363
    308364    if (_mapper != NULL)
    309365        _mapper->Update();
     
    311367
    312368/**
    313  * \brief Get the VTK colormap lookup table in use
     369 * \brief Called when the color map has been edited
    314370 */
    315 vtkLookupTable *LIC::getLookupTable()
    316 { 
    317     return _lut;
     371void LIC::updateColorMap()
     372{
     373    setColorMap(_colorMap);
    318374}
    319375
     
    321377 * \brief Associate a colormap lookup table with the DataSet
    322378 */
    323 void LIC::setLookupTable(vtkLookupTable *lut)
    324 {
    325     if (lut == NULL) {
     379void LIC::setColorMap(ColorMap *cmap)
     380{
     381    if (cmap == NULL)
     382        return;
     383
     384    _colorMap = cmap;
     385 
     386    if (_lut == NULL) {
    326387        _lut = vtkSmartPointer<vtkLookupTable>::New();
    327     } else {
    328         _lut = lut;
    329     }
    330 
    331     if (_mapper != NULL) {
    332         _mapper->SetLookupTable(_lut);
     388        if (_mapper != NULL) {
     389            _mapper->UseLookupTableScalarRangeOff();
     390            _mapper->SetLookupTable(_lut);
     391        }
     392    }
     393
     394    _lut->DeepCopy(cmap->getLookupTable());
     395    _lut->SetRange(_dataRange);
     396}
     397
     398void LIC::updateRanges(bool useCumulative,
     399                       double scalarRange[2],
     400                       double vectorMagnitudeRange[2],
     401                       double vectorComponentRange[3][2])
     402{
     403    if (useCumulative) {
     404        _dataRange[0] = scalarRange[0];
     405        _dataRange[1] = scalarRange[1];
     406    } else if (_dataSet != NULL) {
     407        _dataSet->getScalarRange(_dataRange);
     408    }
     409
     410    if (_lut != NULL) {
     411        _lut->SetRange(_dataRange);
    333412    }
    334413}
  • branches/blt4/packages/vizservers/vtkvis/RpLIC.h

    r2409 r2542  
    1818#include <vtkMapper.h>
    1919#include <vtkLookupTable.h>
     20#include <vtkPlane.h>
    2021
     22#include "ColorMap.h"
    2123#include "RpVtkGraphicsObject.h"
    2224
     
    4951    void selectVolumeSlice(Axis axis, double ratio);
    5052
    51     void setLookupTable(vtkLookupTable *lut);
     53    void setColorMap(ColorMap *colorMap);
    5254
    53     vtkLookupTable *getLookupTable();
     55    /**
     56     * \brief Return the ColorMap in use
     57     */
     58    ColorMap *getColorMap()
     59    {
     60        return _colorMap;
     61    }
     62
     63    void updateColorMap();
     64
     65    virtual void updateRanges(bool useCumulative,
     66                              double scalarRange[2],
     67                              double vectorMagnitudeRange[2],
     68                              double vectorComponentRange[3][2]);
    5469
    5570private:
     
    5873
    5974    Axis _sliceAxis;
     75    ColorMap *_colorMap;
    6076
    6177    vtkSmartPointer<vtkLookupTable> _lut;
    6278    vtkSmartPointer<vtkExtractVOI> _volumeSlicer;
    6379    vtkSmartPointer<vtkProbeFilter> _probeFilter;
     80    vtkSmartPointer<vtkPlane> _cutPlane;
    6481    vtkSmartPointer<vtkImageDataLIC2D> _lic;
    6582    vtkSmartPointer<vtkSurfaceLICPainter> _painter;
  • branches/blt4/packages/vizservers/vtkvis/RpMolecule.cpp

    r2409 r2542  
    2727Molecule::Molecule() :
    2828    VtkGraphicsObject(),
    29     _atomScaling(NO_ATOM_SCALING)
     29    _atomScaling(NO_ATOM_SCALING),
     30    _colorMap(NULL)
    3031{
    3132    _faceCulling = true;
     
    8687    vtkDataSet *ds = _dataSet->getVtkDataSet();
    8788
    88     double dataRange[2];
    89     _dataSet->getDataRange(dataRange);
    90 
    91     if (ds->GetPointData() == NULL ||
    92         ds->GetPointData()->GetScalars() == NULL) {
    93         WARN("No scalar point data in dataset %s", _dataSet->getName().c_str());
    94         if (_lut == NULL) {
    95             _lut = vtkSmartPointer<vtkLookupTable>::New();
    96             _lut->DeepCopy(ColorMap::getDefault()->getLookupTable());
    97             _lut->SetRange(dataRange);
    98         }
    99     } else {
    100         vtkLookupTable *lut = ds->GetPointData()->GetScalars()->GetLookupTable();
    101         TRACE("Data set scalars lookup table: %p\n", lut);
    102         if (_lut == NULL) {
    103             if (lut) {
    104                 _lut = lut;
    105                 if (strcmp(ds->GetPointData()->GetScalars()->GetName(), "element") == 0) {
    106                     double range[2];
    107                     range[0] = 0;
    108                     range[1] = NUM_ELEMENTS+1;
    109                     _lut->SetRange(range);
    110                 } else {
    111                     _lut->SetRange(dataRange);
    112                 }
    113             } else {
    114                 if (strcmp(ds->GetPointData()->GetScalars()->GetName(), "element") == 0) {
    115                     _lut = ColorMap::getElementDefault()->getLookupTable();
    116                 } else {
    117                     _lut = vtkSmartPointer<vtkLookupTable>::New();
    118                     _lut->DeepCopy(ColorMap::getDefault()->getLookupTable());
    119                     _lut->SetRange(dataRange);
    120                 }
    121             }
    122         }
    123     }
    124 
    12589    if (_atomMapper == NULL) {
    12690        _atomMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
    12791        _atomMapper->SetResolveCoincidentTopologyToPolygonOffset();
    12892        _atomMapper->ScalarVisibilityOn();
    129         _atomMapper->SetColorModeToMapScalars();
    130         _atomMapper->UseLookupTableScalarRangeOn();
    131         _atomMapper->SetLookupTable(_lut);
    13293    }
    13394    if (_bondMapper == NULL) {
     
    13596        _bondMapper->SetResolveCoincidentTopologyToPolygonOffset();
    13697        _bondMapper->ScalarVisibilityOn();
    137         _bondMapper->SetColorModeToMapScalars();
    138         _bondMapper->UseLookupTableScalarRangeOn();
    139         _bondMapper->SetLookupTable(_lut);
     98    }
     99
     100    if (_lut == NULL) {
     101        if (ds->GetPointData() == NULL ||
     102            ds->GetPointData()->GetScalars() == NULL ||
     103            strcmp(ds->GetPointData()->GetScalars()->GetName(), "element") != 0) {
     104            WARN("No element array in dataset %s", _dataSet->getName().c_str());
     105            setColorMap(ColorMap::getDefault());
     106        } else {
     107            TRACE("Using element default colormap");
     108            setColorMap(ColorMap::getElementDefault());
     109        }
    140110    }
    141111
     
    197167}
    198168
    199 /**
    200  * \brief Get the VTK colormap lookup table in use
    201  */
    202 vtkLookupTable *Molecule::getLookupTable()
    203 {
    204     return _lut;
     169void Molecule::updateRanges(bool useCumulative,
     170                            double scalarRange[2],
     171                            double vectorMagnitudeRange[2],
     172                            double vectorComponentRange[3][2])
     173{
     174    if (useCumulative) {
     175        _dataRange[0] = scalarRange[0];
     176        _dataRange[1] = scalarRange[1];
     177    } else if (_dataSet != NULL) {
     178        _dataSet->getScalarRange(_dataRange);
     179    }
     180
     181    if (_lut != NULL) {
     182        vtkDataSet *ds = _dataSet->getVtkDataSet();
     183        if (ds == NULL)
     184            return;
     185        if (ds->GetPointData() == NULL ||
     186            ds->GetPointData()->GetScalars() == NULL ||
     187            strcmp(ds->GetPointData()->GetScalars()->GetName(), "element") != 0) {
     188            _lut->SetRange(_dataRange);
     189        }
     190    }
     191}
     192
     193/**
     194 * \brief Called when the color map has been edited
     195 */
     196void Molecule::updateColorMap()
     197{
     198    setColorMap(_colorMap);
    205199}
    206200
     
    208202 * \brief Associate a colormap lookup table with the DataSet
    209203 */
    210 void Molecule::setLookupTable(vtkLookupTable *lut)
    211 {
    212     if (lut == NULL) {
     204void Molecule::setColorMap(ColorMap *cmap)
     205{
     206    if (cmap == NULL)
     207        return;
     208
     209    _colorMap = cmap;
     210 
     211    if (_lut == NULL) {
    213212        _lut = vtkSmartPointer<vtkLookupTable>::New();
    214     } else {
    215         _lut = lut;
    216     }
    217 
    218     if (_atomMapper != NULL) {
    219         _atomMapper->UseLookupTableScalarRangeOn();
    220         _atomMapper->SetLookupTable(_lut);
    221     }
    222     if (_bondMapper != NULL) {
    223         _bondMapper->UseLookupTableScalarRangeOn();
    224         _bondMapper->SetLookupTable(_lut);
     213        if (_atomMapper != NULL) {
     214            _atomMapper->UseLookupTableScalarRangeOn();
     215            _atomMapper->SetLookupTable(_lut);
     216        }
     217        if (_bondMapper != NULL) {
     218            _bondMapper->UseLookupTableScalarRangeOn();
     219            _bondMapper->SetLookupTable(_lut);
     220        }
     221    }
     222
     223    _lut->DeepCopy(cmap->getLookupTable());
     224    _lut->Modified();
     225
     226    // Element color maps need to retain their range
     227    // Only set LUT range if we are not coloring by element
     228    vtkDataSet *ds = _dataSet->getVtkDataSet();
     229    if (ds == NULL)
     230        return;
     231    if (ds->GetPointData() == NULL ||
     232        ds->GetPointData()->GetScalars() == NULL ||
     233        strcmp(ds->GetPointData()->GetScalars()->GetName(), "element") != 0) {
     234        _lut->SetRange(_dataRange);
    225235    }
    226236}
     
    284294}
    285295
     296/**
     297 * \brief Add a scalar array to dataSet with sizes for the elements
     298 * specified in the "element" scalar array
     299 */
    286300void Molecule::addRadiusArray(vtkDataSet *dataSet, AtomScaling scaling)
    287301{
     
    323337}
    324338
     339/**
     340 * \brief Create a color map to map atomic numbers to element colors
     341 */
    325342ColorMap *Molecule::createElementColorMap()
    326343{
    327     ColorMap *elementLUT = new ColorMap("elementDefault");
     344    ColorMap *elementCmap = new ColorMap("elementDefault");
    328345    ColorMap::ControlPoint cp[NUM_ELEMENTS+1];
    329346
    330     elementLUT->setNumberOfTableEntries(NUM_ELEMENTS+1);
     347    elementCmap->setNumberOfTableEntries(NUM_ELEMENTS+1);
    331348    for (int i = 0; i <= NUM_ELEMENTS; i++) {
    332349        cp[i].value = i/((double)(NUM_ELEMENTS+1));
     
    334351            cp[i].color[c] = ((double)g_elementColors[i][c])/255.;
    335352        }
    336         elementLUT->addControlPoint(cp[i]);
     353        elementCmap->addControlPoint(cp[i]);
    337354    }
    338355    ColorMap::OpacityControlPoint ocp[2];
     
    341358    ocp[1].value = 1.0;
    342359    ocp[1].alpha = 1.0;
    343     elementLUT->addOpacityControlPoint(ocp[0]);
    344     elementLUT->addOpacityControlPoint(ocp[1]);
    345     elementLUT->build();
     360    elementCmap->addOpacityControlPoint(ocp[0]);
     361    elementCmap->addOpacityControlPoint(ocp[1]);
     362    elementCmap->build();
    346363    double range[2];
    347364    range[0] = 0;
    348365    range[1] = NUM_ELEMENTS+1;
    349     elementLUT->getLookupTable()->SetRange(range);
    350 
    351     return elementLUT;
    352 }
     366    elementCmap->getLookupTable()->SetRange(range);
     367
     368    return elementCmap;
     369}
  • branches/blt4/packages/vizservers/vtkvis/RpMolecule.h

    r2409 r2542  
    5252    virtual void setClippingPlanes(vtkPlaneCollection *planes);
    5353
    54     void setLookupTable(vtkLookupTable *lut);
     54    void setColorMap(ColorMap *colorMap);
    5555
    56     vtkLookupTable *getLookupTable();
     56    /**
     57     * \brief Return the ColorMap in use
     58     */
     59    ColorMap *getColorMap()
     60    {
     61        return _colorMap;
     62    }
     63
     64    void updateColorMap();
     65
     66    virtual void updateRanges(bool useCumulative,
     67                              double scalarRange[2],
     68                              double vectorMagnitudeRange[2],
     69                              double vectorComponentRange[3][2]);
    5770
    5871    void setAtomScaling(AtomScaling state);
     
    7184
    7285    AtomScaling _atomScaling;
     86    ColorMap *_colorMap;
    7387
    7488    vtkSmartPointer<vtkLookupTable> _lut;
  • branches/blt4/packages/vizservers/vtkvis/RpPolyData.cpp

    r2409 r2542  
    1414#include <vtkActor.h>
    1515#include <vtkProperty.h>
     16#include <vtkTransform.h>
    1617#include <vtkDelaunay2D.h>
    1718#include <vtkDelaunay3D.h>
     
    4647void PolyData::initProp()
    4748{
    48     if (_prop == NULL) {
    49         _prop = vtkSmartPointer<vtkActor>::New();
    50         vtkProperty *property = getActor()->GetProperty();
    51         property->EdgeVisibilityOn();
    52         property->SetColor(_color[0], _color[1], _color[2]);
    53         property->SetEdgeColor(_edgeColor[0], _edgeColor[1], _edgeColor[2]);
    54         property->SetLineWidth(_edgeWidth);
    55         property->SetOpacity(_opacity);
    56         property->SetAmbient(.2);
    57         if (!_lighting)
    58             property->LightingOff();
    59     }
     49    VtkGraphicsObject::initProp();
     50    getActor()->GetProperty()->EdgeVisibilityOn();
    6051}
    6152
     
    7869    vtkPolyData *pd = vtkPolyData::SafeDownCast(ds);
    7970    if (pd) {
    80         TRACE("Verts: %d Lines: %d Polys: %d Strips: %d",
    81                   pd->GetNumberOfVerts(),
    82                   pd->GetNumberOfLines(),
    83                   pd->GetNumberOfPolys(),
    84                   pd->GetNumberOfStrips());
     71        TRACE("Points: %d Verts: %d Lines: %d Polys: %d Strips: %d",
     72              pd->GetNumberOfPoints(),
     73              pd->GetNumberOfVerts(),
     74              pd->GetNumberOfLines(),
     75              pd->GetNumberOfPolys(),
     76              pd->GetNumberOfStrips());
    8577        // DataSet is a vtkPolyData
    8678        if (pd->GetNumberOfLines() == 0 &&
     
    8880            pd->GetNumberOfStrips() == 0) {
    8981            // DataSet is a point cloud
    90             if (_dataSet->is2D()) {
     82            DataSet::PrincipalPlane plane;
     83            double offset;
     84            if (_dataSet->numDimensions() < 2 || pd->GetNumberOfPoints() < 3) {
     85                // 0D or 1D or not enough points to mesh
     86                _pdMapper->SetInput(pd);
     87            } else if (_dataSet->is2D(&plane, &offset)) {
    9188                vtkSmartPointer<vtkDelaunay2D> mesher = vtkSmartPointer<vtkDelaunay2D>::New();
     89                if (plane == DataSet::PLANE_ZY) {
     90                    vtkSmartPointer<vtkTransform> trans = vtkSmartPointer<vtkTransform>::New();
     91                    trans->RotateWXYZ(90, 0, 1, 0);
     92                    if (offset != 0.0) {
     93                        trans->Translate(-offset, 0, 0);
     94                    }
     95                    mesher->SetTransform(trans);
     96                } else if (plane == DataSet::PLANE_XZ) {
     97                     vtkSmartPointer<vtkTransform> trans = vtkSmartPointer<vtkTransform>::New();
     98                    trans->RotateWXYZ(-90, 1, 0, 0);
     99                    if (offset != 0.0) {
     100                        trans->Translate(0, -offset, 0);
     101                    }
     102                    mesher->SetTransform(trans);
     103                } else if (offset != 0.0) {
     104                    // XY with Z offset
     105                    vtkSmartPointer<vtkTransform> trans = vtkSmartPointer<vtkTransform>::New();
     106                    trans->Translate(0, 0, -offset);
     107                    mesher->SetTransform(trans);
     108                }
    92109                mesher->SetInput(pd);
    93110                mesher->ReleaseDataFlagOn();
    94                 _pdMapper->SetInputConnection(mesher->GetOutputPort());
    95 #if defined(DEBUG) && defined(WANT_TRACE)
    96111                mesher->Update();
    97112                vtkPolyData *outpd = mesher->GetOutput();
     
    101116                      outpd->GetNumberOfPolys(),
    102117                      outpd->GetNumberOfStrips());
    103 #endif
     118                if (outpd->GetNumberOfPolys() == 0) {
     119                    WARN("Delaunay2D mesher failed");
     120                    _pdMapper->SetInput(pd);
     121                } else {
     122                    _pdMapper->SetInputConnection(mesher->GetOutputPort());
     123                }
    104124            } else {
    105125                vtkSmartPointer<vtkDelaunay3D> mesher = vtkSmartPointer<vtkDelaunay3D>::New();
    106126                mesher->SetInput(pd);
    107127                mesher->ReleaseDataFlagOn();
    108                 // Delaunay3D returns an UnstructuredGrid, so feed it through a surface filter
    109                 // to get the grid boundary as a PolyData
    110                 vtkSmartPointer<vtkDataSetSurfaceFilter> gf = vtkSmartPointer<vtkDataSetSurfaceFilter>::New();
    111                 gf->SetInputConnection(mesher->GetOutputPort());
    112                 gf->ReleaseDataFlagOn();
    113                 _pdMapper->SetInputConnection(gf->GetOutputPort());
    114             }
     128                mesher->Update();
     129                vtkUnstructuredGrid *grid = mesher->GetOutput();
     130                TRACE("Delaunay3D Cells: %d",
     131                      grid->GetNumberOfCells());
     132                if (grid->GetNumberOfCells() == 0) {
     133                    WARN("Delaunay3D mesher failed");
     134                    _pdMapper->SetInput(pd);
     135                } else {
     136                    // Delaunay3D returns an UnstructuredGrid, so feed it
     137                    // through a surface filter to get the grid boundary
     138                    // as a PolyData
     139                    vtkSmartPointer<vtkDataSetSurfaceFilter> gf = vtkSmartPointer<vtkDataSetSurfaceFilter>::New();
     140                    gf->UseStripsOn();
     141                    gf->SetInputConnection(mesher->GetOutputPort());
     142                    gf->ReleaseDataFlagOn();
     143                    _pdMapper->SetInputConnection(gf->GetOutputPort());
     144                }
     145             }
    115146        } else {
    116147            // DataSet is a vtkPolyData with lines and/or polygons
     
    121152        TRACE("DataSet is not a PolyData");
    122153        vtkSmartPointer<vtkDataSetSurfaceFilter> gf = vtkSmartPointer<vtkDataSetSurfaceFilter>::New();
     154        gf->UseStripsOn();
    123155        gf->SetInput(ds);
    124156        gf->ReleaseDataFlagOn();
  • branches/blt4/packages/vizservers/vtkvis/RpPolyData.h

    r2409 r2542  
    2222 * \brief VTK Mesh (Polygon data)
    2323 *
    24  * The DataSet must be a PolyData object
     24 * This class creates a boundary mesh of a DataSet
    2525 */
    2626class PolyData : public VtkGraphicsObject {
  • branches/blt4/packages/vizservers/vtkvis/RpPseudoColor.cpp

    r2409 r2542  
    1515#include <vtkImageData.h>
    1616#include <vtkLookupTable.h>
     17#include <vtkTransform.h>
    1718#include <vtkDelaunay2D.h>
    1819#include <vtkDelaunay3D.h>
     
    2930
    3031PseudoColor::PseudoColor() :
    31     VtkGraphicsObject()
     32    VtkGraphicsObject(),
     33    _colorMode(COLOR_BY_SCALAR),
     34    _colorMap(NULL)
    3235{
    3336}
     
    4346}
    4447
    45 /**
    46  * \brief Create and initialize a VTK Prop to render the colormapped dataset
    47  */
    48 void PseudoColor::initProp()
    49 {
    50     if (_prop == NULL) {
    51         _prop = vtkSmartPointer<vtkActor>::New();
    52         vtkProperty *property = getActor()->GetProperty();
    53         property->SetOpacity(_opacity);
    54         property->SetEdgeColor(_edgeColor[0], _edgeColor[1], _edgeColor[2]);
    55         property->SetLineWidth(_edgeWidth);
    56         property->EdgeVisibilityOff();
    57         property->SetAmbient(.2);
    58         if (!_lighting)
    59             property->LightingOff();
     48void PseudoColor::setDataSet(DataSet *dataSet,
     49                             bool useCumulative,
     50                             double scalarRange[2],
     51                             double vectorMagnitudeRange[2],
     52                             double vectorComponentRange[3][2])
     53{
     54    if (_dataSet != dataSet) {
     55        _dataSet = dataSet;
     56
     57        if (useCumulative) {
     58            _dataRange[0] = scalarRange[0];
     59            _dataRange[1] = scalarRange[1];
     60            _vectorMagnitudeRange[0] = vectorMagnitudeRange[0];
     61            _vectorMagnitudeRange[1] = vectorMagnitudeRange[1];
     62            for (int i = 0; i < 3; i++) {
     63                _vectorComponentRange[i][0] = vectorComponentRange[i][0];
     64                _vectorComponentRange[i][1] = vectorComponentRange[i][1];
     65            }
     66        } else {
     67            _dataSet->getScalarRange(_dataRange);
     68            _dataSet->getVectorRange(_vectorMagnitudeRange);
     69            for (int i = 0; i < 3; i++) {
     70                _dataSet->getVectorRange(_vectorComponentRange[i], i);
     71            }
     72        }
     73
     74        update();
    6075    }
    6176}
     
    7085
    7186    vtkDataSet *ds = _dataSet->getVtkDataSet();
    72 
    73     double dataRange[2];
    74     _dataSet->getDataRange(dataRange);
    7587
    7688    // Mapper, actor to render color-mapped data set
    7789    if (_dsMapper == NULL) {
    7890        _dsMapper = vtkSmartPointer<vtkDataSetMapper>::New();
     91        // Map scalars through lookup table regardless of type
     92        _dsMapper->SetColorModeToMapScalars();
     93        //_dsMapper->InterpolateScalarsBeforeMappingOn();
    7994    }
    8095
     
    86101            pd->GetNumberOfStrips() == 0) {
    87102            // DataSet is a point cloud
    88             if (_dataSet->is2D()) {
     103            DataSet::PrincipalPlane plane;
     104            double offset;
     105            if (_dataSet->is2D(&plane, &offset)) {
    89106#ifdef MESH_POINT_CLOUDS
    90107                vtkSmartPointer<vtkDelaunay2D> mesher = vtkSmartPointer<vtkDelaunay2D>::New();
     108                if (plane == DataSet::PLANE_ZY) {
     109                    vtkSmartPointer<vtkTransform> trans = vtkSmartPointer<vtkTransform>::New();
     110                    trans->RotateWXYZ(90, 0, 1, 0);
     111                    if (offset != 0.0) {
     112                        trans->Translate(-offset, 0, 0);
     113                    }
     114                    mesher->SetTransform(trans);
     115                } else if (plane == DataSet::PLANE_XZ) {
     116                    vtkSmartPointer<vtkTransform> trans = vtkSmartPointer<vtkTransform>::New();
     117                    trans->RotateWXYZ(-90, 1, 0, 0);
     118                    if (offset != 0.0) {
     119                        trans->Translate(0, -offset, 0);
     120                    }
     121                    mesher->SetTransform(trans);
     122                } else if (offset != 0.0) {
     123                    // XY with Z offset
     124                    vtkSmartPointer<vtkTransform> trans = vtkSmartPointer<vtkTransform>::New();
     125                    trans->Translate(0, 0, -offset);
     126                    mesher->SetTransform(trans);
     127                }
    91128                mesher->SetInput(pd);
    92                 vtkSmartPointer<vtkDataSetSurfaceFilter> gf = vtkSmartPointer<vtkDataSetSurfaceFilter>::New();
    93                 gf->SetInputConnection(mesher->GetOutputPort());
    94                 _dsMapper->SetInputConnection(gf->GetOutputPort());
     129                _dsMapper->SetInputConnection(mesher->GetOutputPort());
    95130#else
    96131                vtkSmartPointer<vtkGaussianSplatter> splatter = vtkSmartPointer<vtkGaussianSplatter>::New();
     132                vtkSmartPointer<vtkExtractVOI> slicer = vtkSmartPointer<vtkExtractVOI>::New();
    97133                splatter->SetInput(pd);
    98134                int dims[3];
    99135                splatter->GetSampleDimensions(dims);
    100136                TRACE("Sample dims: %d %d %d", dims[0], dims[1], dims[2]);
    101                 dims[2] = 3;
     137                if (plane == DataSet::PLANE_ZY) {
     138                    dims[0] = 3;
     139                    slicer->SetVOI(1, 1, 0, dims[1]-1, 0, dims[1]-1);
     140                } else if (plane == DataSet::PLANE_XZ) {
     141                    dims[1] = 3;
     142                    slicer->SetVOI(0, dims[0]-1, 1, 1, 0, dims[2]-1);
     143                } else {
     144                    dims[2] = 3;
     145                    slicer->SetVOI(0, dims[0]-1, 0, dims[1]-1, 1, 1);
     146                }
    102147                splatter->SetSampleDimensions(dims);
    103148                double bounds[6];
     
    108153                      bounds[2], bounds[3],
    109154                      bounds[4], bounds[5]);
    110                 vtkSmartPointer<vtkExtractVOI> slicer = vtkSmartPointer<vtkExtractVOI>::New();
    111155                slicer->SetInputConnection(splatter->GetOutputPort());
    112                 slicer->SetVOI(0, dims[0]-1, 0, dims[1]-1, 1, 1);
    113156                slicer->SetSampleRate(1, 1, 1);
    114157                vtkSmartPointer<vtkDataSetSurfaceFilter> gf = vtkSmartPointer<vtkDataSetSurfaceFilter>::New();
     
    136179    }
    137180
    138     if (ds->GetPointData() == NULL ||
    139         ds->GetPointData()->GetScalars() == NULL) {
    140         WARN("No scalar point data in dataset %s", _dataSet->getName().c_str());
    141         if (_lut == NULL) {
    142             _lut = vtkSmartPointer<vtkLookupTable>::New();
    143         }
    144     } else {
    145         vtkLookupTable *lut = ds->GetPointData()->GetScalars()->GetLookupTable();
    146         TRACE("Data set scalars lookup table: %p\n", lut);
    147         if (_lut == NULL) {
    148             if (lut)
    149                 _lut = lut;
    150             else
    151                 _lut = vtkSmartPointer<vtkLookupTable>::New();
    152         }
    153     }
    154 
    155     _lut->SetRange(dataRange);
    156 
    157     _dsMapper->SetColorModeToMapScalars();
    158     _dsMapper->UseLookupTableScalarRangeOn();
    159     _dsMapper->SetLookupTable(_lut);
    160     //_dsMapper->InterpolateScalarsBeforeMappingOn();
     181    if (_lut == NULL) {
     182        setColorMap(ColorMap::getDefault());
     183    }
     184
     185    setColorMode(_colorMode);
    161186
    162187    initProp();
     
    165190}
    166191
     192void PseudoColor::updateRanges(bool useCumulative,
     193                               double scalarRange[2],
     194                               double vectorMagnitudeRange[2],
     195                               double vectorComponentRange[3][2])
     196{
     197    if (useCumulative) {
     198        _dataRange[0] = scalarRange[0];
     199        _dataRange[1] = scalarRange[1];
     200        _vectorMagnitudeRange[0] = vectorMagnitudeRange[0];
     201        _vectorMagnitudeRange[1] = vectorMagnitudeRange[1];
     202        for (int i = 0; i < 3; i++) {
     203            _vectorComponentRange[i][0] = vectorComponentRange[i][0];
     204            _vectorComponentRange[i][1] = vectorComponentRange[i][1];
     205        }
     206    } else if (_dataSet != NULL) {
     207        _dataSet->getScalarRange(_dataRange);
     208        _dataSet->getVectorRange(_vectorMagnitudeRange);
     209        for (int i = 0; i < 3; i++) {
     210            _dataSet->getVectorRange(_vectorComponentRange[i], i);
     211        }
     212    }
     213
     214    // Need to update color map ranges and/or active vector field
     215    setColorMode(_colorMode);
     216}
     217
     218void PseudoColor::setColorMode(ColorMode mode)
     219{
     220    _colorMode = mode;
     221    if (_dataSet == NULL || _dsMapper == NULL)
     222        return;
     223
     224    vtkDataSet *ds = _dataSet->getVtkDataSet();
     225
     226    switch (mode) {
     227    case COLOR_BY_SCALAR: {
     228        _dsMapper->ScalarVisibilityOn();
     229        _dsMapper->SetScalarModeToDefault();
     230        if (_lut != NULL) {
     231            _lut->SetRange(_dataRange);
     232        }
     233    }
     234        break;
     235    case COLOR_BY_VECTOR_MAGNITUDE: {
     236        _dsMapper->ScalarVisibilityOn();
     237        _dsMapper->SetScalarModeToUsePointFieldData();
     238        if (ds->GetPointData() != NULL &&
     239            ds->GetPointData()->GetVectors() != NULL) {
     240            _dsMapper->SelectColorArray(ds->GetPointData()->GetVectors()->GetName());
     241        }
     242        if (_lut != NULL) {
     243            _lut->SetRange(_vectorMagnitudeRange);
     244            _lut->SetVectorModeToMagnitude();
     245        }
     246    }
     247        break;
     248    case COLOR_BY_VECTOR_X:
     249        _dsMapper->ScalarVisibilityOn();
     250        _dsMapper->SetScalarModeToUsePointFieldData();
     251        if (ds->GetPointData() != NULL &&
     252            ds->GetPointData()->GetVectors() != NULL) {
     253            _dsMapper->SelectColorArray(ds->GetPointData()->GetVectors()->GetName());
     254        }
     255        if (_lut != NULL) {
     256            _lut->SetRange(_vectorComponentRange[0]);
     257            _lut->SetVectorModeToComponent();
     258            _lut->SetVectorComponent(0);
     259        }
     260        break;
     261    case COLOR_BY_VECTOR_Y:
     262        _dsMapper->ScalarVisibilityOn();
     263        _dsMapper->SetScalarModeToUsePointFieldData();
     264        if (ds->GetPointData() != NULL &&
     265            ds->GetPointData()->GetVectors() != NULL) {
     266            _dsMapper->SelectColorArray(ds->GetPointData()->GetVectors()->GetName());
     267        }
     268        if (_lut != NULL) {
     269            _lut->SetRange(_vectorComponentRange[1]);
     270            _lut->SetVectorModeToComponent();
     271            _lut->SetVectorComponent(1);
     272        }
     273        break;
     274    case COLOR_BY_VECTOR_Z:
     275        _dsMapper->ScalarVisibilityOn();
     276        _dsMapper->SetScalarModeToUsePointFieldData();
     277        if (ds->GetPointData() != NULL &&
     278            ds->GetPointData()->GetVectors() != NULL) {
     279            _dsMapper->SelectColorArray(ds->GetPointData()->GetVectors()->GetName());
     280        }
     281        if (_lut != NULL) {
     282            _lut->SetRange(_vectorComponentRange[2]);
     283            _lut->SetVectorModeToComponent();
     284            _lut->SetVectorComponent(2);
     285        }
     286        break;
     287    case COLOR_CONSTANT:
     288    default:
     289        _dsMapper->ScalarVisibilityOff();
     290        break;
     291    }
     292}
     293
    167294/**
    168  * \brief Get the VTK colormap lookup table in use
    169  */
    170 vtkLookupTable *PseudoColor::getLookupTable()
    171 { 
    172     return _lut;
     295 * \brief Called when the color map has been edited
     296 */
     297void PseudoColor::updateColorMap()
     298{
     299    setColorMap(_colorMap);
    173300}
    174301
     
    176303 * \brief Associate a colormap lookup table with the DataSet
    177304 */
    178 void PseudoColor::setLookupTable(vtkLookupTable *lut)
    179 {
    180     if (lut == NULL) {
     305void PseudoColor::setColorMap(ColorMap *cmap)
     306{
     307    if (cmap == NULL)
     308        return;
     309
     310    _colorMap = cmap;
     311 
     312    if (_lut == NULL) {
    181313        _lut = vtkSmartPointer<vtkLookupTable>::New();
    182     } else {
    183         _lut = lut;
    184     }
    185 
    186     if (_dsMapper != NULL) {
    187         _dsMapper->UseLookupTableScalarRangeOn();
    188         _dsMapper->SetLookupTable(_lut);
     314        if (_dsMapper != NULL) {
     315            _dsMapper->UseLookupTableScalarRangeOn();
     316            _dsMapper->SetLookupTable(_lut);
     317        }
     318    }
     319
     320    _lut->DeepCopy(cmap->getLookupTable());
     321
     322    switch (_colorMode) {
     323    case COLOR_CONSTANT:
     324    case COLOR_BY_SCALAR:
     325        _lut->SetRange(_dataRange);
     326        break;
     327    case COLOR_BY_VECTOR_MAGNITUDE:
     328        _lut->SetVectorModeToMagnitude();
     329        _lut->SetRange(_vectorMagnitudeRange);
     330        break;
     331    case COLOR_BY_VECTOR_X:
     332        _lut->SetVectorModeToComponent();
     333        _lut->SetVectorComponent(0);
     334        _lut->SetRange(_vectorComponentRange[0]);
     335        break;
     336    case COLOR_BY_VECTOR_Y:
     337        _lut->SetVectorModeToComponent();
     338        _lut->SetVectorComponent(1);
     339        _lut->SetRange(_vectorComponentRange[1]);
     340        break;
     341    case COLOR_BY_VECTOR_Z:
     342        _lut->SetVectorModeToComponent();
     343        _lut->SetVectorComponent(2);
     344        _lut->SetRange(_vectorComponentRange[2]);
     345        break;
     346    default:
     347         break;
    189348    }
    190349}
  • branches/blt4/packages/vizservers/vtkvis/RpPseudoColor.h

    r2409 r2542  
    1515#include <vtkPlaneCollection.h>
    1616
     17#include "ColorMap.h"
    1718#include "RpVtkGraphicsObject.h"
    18 #include "RpVtkDataSet.h"
    1919
    2020namespace Rappture {
     
    2323/**
    2424 * \brief Color-mapped plot of data set
    25  *
    26  * Currently the DataSet must be image data (2D uniform grid)
    2725 */
    2826class PseudoColor : public VtkGraphicsObject {
    2927public:
     28    enum ColorMode {
     29        COLOR_BY_SCALAR,
     30        COLOR_BY_VECTOR_MAGNITUDE,
     31        COLOR_BY_VECTOR_X,
     32        COLOR_BY_VECTOR_Y,
     33        COLOR_BY_VECTOR_Z,
     34        COLOR_CONSTANT
     35    };
     36
    3037    PseudoColor();
    3138    virtual ~PseudoColor();
     
    3643    }
    3744
     45    virtual void setDataSet(DataSet *dataSet,
     46                            bool useCumulative,
     47                            double scalarRange[2],
     48                            double vectorMagnitudeRange[2],
     49                            double vectorComponentRange[3][2]);
     50
    3851    virtual void setClippingPlanes(vtkPlaneCollection *planes);
    3952
    40     void setLookupTable(vtkLookupTable *lut);
     53    void setColorMode(ColorMode mode);
    4154
    42     vtkLookupTable *getLookupTable();
     55    void setColorMap(ColorMap *colorMap);
     56
     57    /**
     58     * \brief Return the ColorMap in use
     59     */
     60    ColorMap *getColorMap()
     61    {
     62        return _colorMap;
     63    }
     64
     65    void updateColorMap();
     66
     67    virtual void updateRanges(bool useCumulative,
     68                              double scalarRange[2],
     69                              double vectorMagnitudeRange[2],
     70                              double vectorComponentRange[3][2]);
    4371
    4472private:
    45     virtual void initProp();
    4673    virtual void update();
     74
     75    ColorMode _colorMode;
     76    ColorMap *_colorMap;
     77    double _vectorMagnitudeRange[2];
     78    double _vectorComponentRange[3][2];
    4779
    4880    vtkSmartPointer<vtkLookupTable> _lut;
  • branches/blt4/packages/vizservers/vtkvis/RpStreamlines.cpp

    r2409 r2542  
    3636    _lineType(LINES),
    3737    _colorMode(COLOR_BY_VECTOR_MAGNITUDE),
    38     _seedVisible(true)
     38    _colorMap(NULL),
     39    _seedVisible(true),
     40    _dataScale(1)
    3941{
    4042    _faceCulling = true;
     
    5153Streamlines::~Streamlines()
    5254{
     55}
     56
     57void Streamlines::setDataSet(DataSet *dataSet,
     58                             bool useCumulative,
     59                             double scalarRange[2],
     60                             double vectorMagnitudeRange[2],
     61                             double vectorComponentRange[3][2])
     62{
     63    if (_dataSet != dataSet) {
     64        _dataSet = dataSet;
     65
     66        if (useCumulative) {
     67            _dataRange[0] = scalarRange[0];
     68            _dataRange[1] = scalarRange[1];
     69            _vectorMagnitudeRange[0] = vectorMagnitudeRange[0];
     70            _vectorMagnitudeRange[1] = vectorMagnitudeRange[1];
     71            for (int i = 0; i < 3; i++) {
     72                _vectorComponentRange[i][0] = vectorComponentRange[i][0];
     73                _vectorComponentRange[i][1] = vectorComponentRange[i][1];
     74            }
     75        } else {
     76            _dataSet->getScalarRange(_dataRange);
     77            _dataSet->getVectorRange(_vectorMagnitudeRange);
     78            for (int i = 0; i < 3; i++) {
     79                _dataSet->getVectorRange(_vectorComponentRange[i], i);
     80            }
     81        }
     82
     83        update();
     84    }
    5385}
    5486
     
    96128        _seedActor->GetProperty()->SetRepresentationToWireframe();
    97129        _seedActor->GetProperty()->LightingOff();
     130        setSeedVisibility(_seedVisible);
    98131    }
    99132    if (_prop == NULL) {
     
    201234
    202235    vtkDataSet *ds = _dataSet->getVtkDataSet();
    203     double dataRange[2];
    204     _dataSet->getVectorMagnitudeRange(dataRange);
     236
    205237    double bounds[6];
    206238    _dataSet->getBounds(bounds);
     
    215247        maxBound = bounds[5] - bounds[4];
    216248    }
     249
     250    double cellSizeRange[2];
     251    double avgSize;
     252    _dataSet->getCellSizeRange(cellSizeRange, &avgSize);
     253    _dataScale = avgSize / 8.;
    217254
    218255    vtkSmartPointer<vtkCellDataToPointData> cellToPtData;
     
    294331    _seedActor->SetMapper(_seedMapper);
    295332
    296     _lut = vtkSmartPointer<vtkLookupTable>::New();
    297     _lut->SetRange(dataRange);
    298     _lut->SetVectorModeToMagnitude();
    299 
    300     _pdMapper->SetScalarModeToUsePointFieldData();
    301     if (ds->GetPointData() != NULL &&
    302         ds->GetPointData()->GetVectors() != NULL) {
    303         TRACE("Vector name: '%s'", ds->GetPointData()->GetVectors()->GetName());
    304         _pdMapper->SelectColorArray(ds->GetPointData()->GetVectors()->GetName());
    305     }
    306     _pdMapper->SetColorModeToMapScalars();
    307     _pdMapper->UseLookupTableScalarRangeOn();
    308     _pdMapper->SetLookupTable(_lut);
     333    if (_lut == NULL) {
     334        setColorMap(ColorMap::getDefault());
     335    }
     336
     337    setColorMode(_colorMode);
    309338
    310339    _linesActor->SetMapper(_pdMapper);
     
    724753            numSides = 3;
    725754        tubeFilter->SetNumberOfSides(numSides);
    726         tubeFilter->SetRadius(radius);
     755        tubeFilter->SetRadius(_dataScale * radius);
    727756        _pdMapper->SetInputConnection(_lineFilter->GetOutputPort());
    728757        if (_faceCulling && _opacity == 1.0)
     
    749778        }
    750779        vtkRibbonFilter *ribbonFilter = vtkRibbonFilter::SafeDownCast(_lineFilter);
    751         ribbonFilter->SetWidth(width);
     780        ribbonFilter->SetWidth(_dataScale * width);
    752781        ribbonFilter->SetAngle(angle);
    753782        ribbonFilter->UseDefaultNormalOn();
     
    759788}
    760789
     790void Streamlines::updateRanges(bool useCumulative,
     791                               double scalarRange[2],
     792                               double vectorMagnitudeRange[2],
     793                               double vectorComponentRange[3][2])
     794{
     795    if (useCumulative) {
     796        _dataRange[0] = scalarRange[0];
     797        _dataRange[1] = scalarRange[1];
     798        _vectorMagnitudeRange[0] = vectorMagnitudeRange[0];
     799        _vectorMagnitudeRange[1] = vectorMagnitudeRange[1];
     800        for (int i = 0; i < 3; i++) {
     801            _vectorComponentRange[i][0] = vectorComponentRange[i][0];
     802            _vectorComponentRange[i][1] = vectorComponentRange[i][1];
     803        }
     804    } else {
     805        _dataSet->getScalarRange(_dataRange);
     806        _dataSet->getVectorRange(_vectorMagnitudeRange);
     807        for (int i = 0; i < 3; i++) {
     808            _dataSet->getVectorRange(_vectorComponentRange[i], i);
     809        }
     810    }
     811
     812    // Need to update color map ranges and/or active vector field
     813    setColorMode(_colorMode);
     814}
     815
    761816void Streamlines::setColorMode(ColorMode mode)
    762817{
     
    772827        _pdMapper->SetScalarModeToDefault();
    773828        if (_lut != NULL) {
    774             double dataRange[2];
    775             _dataSet->getDataRange(dataRange);
    776             _lut->SetRange(dataRange);
     829            _lut->SetRange(_dataRange);
    777830        }
    778831    }
     
    786839        }
    787840        if (_lut != NULL) {
    788             double dataRange[2];
    789             _dataSet->getVectorMagnitudeRange(dataRange);
    790             TRACE("vmag range: %g %g", dataRange[0], dataRange[1]);
    791             _lut->SetRange(dataRange);
     841            _lut->SetRange(_vectorMagnitudeRange);
    792842            _lut->SetVectorModeToMagnitude();
    793843        }
     
    802852        }
    803853        if (_lut != NULL) {
    804             double dataRange[2];
    805             _dataSet->getVectorComponentRange(dataRange, 0);
    806             _lut->SetRange(dataRange);
     854            _lut->SetRange(_vectorComponentRange[0]);
    807855            _lut->SetVectorModeToComponent();
    808856            _lut->SetVectorComponent(0);
     
    817865        }
    818866        if (_lut != NULL) {
    819             double dataRange[2];
    820             _dataSet->getVectorComponentRange(dataRange, 1);
    821             _lut->SetRange(dataRange);
     867            _lut->SetRange(_vectorComponentRange[1]);
    822868            _lut->SetVectorModeToComponent();
    823869            _lut->SetVectorComponent(1);
     
    832878        }
    833879        if (_lut != NULL) {
    834             double dataRange[2];
    835             _dataSet->getVectorComponentRange(dataRange, 2);
    836             TRACE("vz range: %g %g", dataRange[0], dataRange[1]);
    837             _lut->SetRange(dataRange);
     880            _lut->SetRange(_vectorComponentRange[2]);
    838881            _lut->SetVectorModeToComponent();
    839882            _lut->SetVectorComponent(2);
     
    848891
    849892/**
    850  * \brief Get the VTK colormap lookup table in use
    851  */
    852 vtkLookupTable *Streamlines::getLookupTable()
    853 { 
    854     return _lut;
     893 * \brief Called when the color map has been edited
     894 */
     895void Streamlines::updateColorMap()
     896{
     897    setColorMap(_colorMap);
    855898}
    856899
     
    858901 * \brief Associate a colormap lookup table with the DataSet
    859902 */
    860 void Streamlines::setLookupTable(vtkLookupTable *lut)
    861 {
    862     if (lut == NULL) {
     903void Streamlines::setColorMap(ColorMap *cmap)
     904{
     905    if (cmap == NULL)
     906        return;
     907
     908    _colorMap = cmap;
     909 
     910    if (_lut == NULL) {
    863911        _lut = vtkSmartPointer<vtkLookupTable>::New();
    864     } else {
    865         _lut = lut;
    866     }
     912        if (_pdMapper != NULL) {
     913            _pdMapper->UseLookupTableScalarRangeOn();
     914            _pdMapper->SetLookupTable(_lut);
     915        }
     916    }
     917
     918    _lut->DeepCopy(cmap->getLookupTable());
    867919
    868920    switch (_colorMode) {
    869     case COLOR_BY_VECTOR_MAGNITUDE: {
    870         double dataRange[2];
    871         _dataSet->getVectorMagnitudeRange(dataRange);
     921    case COLOR_CONSTANT:
     922    case COLOR_BY_SCALAR:
     923        _lut->SetRange(_dataRange);
     924        break;
     925    case COLOR_BY_VECTOR_MAGNITUDE:
    872926        _lut->SetVectorModeToMagnitude();
    873         _lut->SetRange(dataRange);
    874     }
    875         break;
    876     case COLOR_BY_VECTOR_X: {
    877         double dataRange[2];
    878         _dataSet->getVectorComponentRange(dataRange, 0);
     927        _lut->SetRange(_vectorMagnitudeRange);
     928        break;
     929    case COLOR_BY_VECTOR_X:
    879930        _lut->SetVectorModeToComponent();
    880931        _lut->SetVectorComponent(0);
    881         _lut->SetRange(dataRange);
    882     }
    883         break;
    884     case COLOR_BY_VECTOR_Y: {
    885         double dataRange[2];
    886         _dataSet->getVectorComponentRange(dataRange, 1);
     932        _lut->SetRange(_vectorComponentRange[0]);
     933        break;
     934    case COLOR_BY_VECTOR_Y:
    887935        _lut->SetVectorModeToComponent();
    888936        _lut->SetVectorComponent(1);
    889         _lut->SetRange(dataRange);
    890     }
    891         break;
    892     case COLOR_BY_VECTOR_Z: {
    893         double dataRange[2];
    894         _dataSet->getVectorComponentRange(dataRange, 2);
     937        _lut->SetRange(_vectorComponentRange[1]);
     938        break;
     939    case COLOR_BY_VECTOR_Z:
    895940        _lut->SetVectorModeToComponent();
    896941        _lut->SetVectorComponent(2);
    897         _lut->SetRange(dataRange);
    898     }
     942        _lut->SetRange(_vectorComponentRange[2]);
    899943        break;
    900944    default:
    901945         break;
    902     }
    903 
    904     if (_pdMapper != NULL) {
    905         _pdMapper->SetLookupTable(_lut);
    906946    }
    907947}
  • branches/blt4/packages/vizservers/vtkvis/RpStreamlines.h

    r2409 r2542  
    1818#include <vtkAssembly.h>
    1919
     20#include "ColorMap.h"
    2021#include "RpVtkGraphicsObject.h"
    2122
     
    5152        return "Streamlines";
    5253    }
     54
     55    virtual void setDataSet(DataSet *dataSet,
     56                            bool useCumulative,
     57                            double scalarRange[2],
     58                            double vectorMagnitudeRange[2],
     59                            double vectorComponentRange[3][2]);
    5360
    5461    virtual void setLighting(bool state);
     
    95102    void setColorMode(ColorMode mode);
    96103
    97     void setLookupTable(vtkLookupTable *lut);
     104    void setColorMap(ColorMap *colorMap);
    98105
    99     vtkLookupTable *getLookupTable();
     106    /**
     107     * \brief Return the ColorMap in use
     108     */
     109    ColorMap *getColorMap()
     110    {
     111        return _colorMap;
     112    }
     113
     114    void updateColorMap();
     115
     116    virtual void updateRanges(bool useCumulative,
     117                              double scalarRange[2],
     118                              double vectorMagnitudeRange[2],
     119                              double vectorComponentRange[3][2]);
    100120
    101121    void setSeedVisibility(bool state);
     
    120140    LineType _lineType;
    121141    ColorMode _colorMode;
    122     float _color[3];
     142    ColorMap *_colorMap;
    123143    float _seedColor[3];
    124144    bool _seedVisible;
     145    double _vectorMagnitudeRange[2];
     146    double _vectorComponentRange[3][2];
     147    double _dataScale;
    125148
    126149    vtkSmartPointer<vtkLookupTable> _lut;
  • branches/blt4/packages/vizservers/vtkvis/RpVolume.cpp

    r2409 r2542  
    6363    vtkDataSet *ds = _dataSet->getVtkDataSet();
    6464
    65     double dataRange[2];
    66     _dataSet->getDataRange(dataRange);
    67 
    68     TRACE("DataSet type: %s, range: %g - %g", _dataSet->getVtkType(),
    69           dataRange[0], dataRange[1]);
    70 
    7165    if (vtkImageData::SafeDownCast(ds) != NULL) {
    7266        // Image data required for these mappers
     
    113107        WARN("No scalar point data in dataset %s", _dataSet->getName().c_str());
    114108    }
     109
    115110    if (_colorMap == NULL) {
    116         _colorMap = ColorMap::getVolumeDefault();
     111        setColorMap(ColorMap::getVolumeDefault());
    117112    }
    118 
    119     vtkVolumeProperty *volProperty = getVolume()->GetProperty();
    120     volProperty->SetColor(_colorMap->getColorTransferFunction(dataRange));
    121     volProperty->SetScalarOpacity(_colorMap->getOpacityTransferFunction(dataRange));
    122113
    123114    getVolume()->SetMapper(_volumeMapper);
    124115    _volumeMapper->Update();
     116}
     117
     118void Volume::updateRanges(bool useCumulative,
     119                          double scalarRange[2],
     120                          double vectorMagnitudeRange[2],
     121                          double vectorComponentRange[3][2])
     122{
     123    if (useCumulative) {
     124        _dataRange[0] = scalarRange[0];
     125        _dataRange[1] = scalarRange[1];
     126    } else if (_dataSet != NULL) {
     127        _dataSet->getScalarRange(_dataRange);
     128    }
     129
     130    if (getVolume() != NULL) {
     131        getVolume()->GetProperty()->SetColor(_colorMap->getColorTransferFunction(_dataRange));
     132        getVolume()->GetProperty()->SetScalarOpacity(_colorMap->getOpacityTransferFunction(_dataRange));
     133    }
     134}
     135void Volume::updateColorMap()
     136{
     137    setColorMap(_colorMap);
    125138}
    126139
     
    131144{
    132145    _colorMap = cmap;
     146
    133147    if (getVolume() != NULL) {
    134         double dataRange[2];
    135         _dataSet->getDataRange(dataRange);
    136         getVolume()->GetProperty()->SetColor(_colorMap->getColorTransferFunction(dataRange));
    137         getVolume()->GetProperty()->SetScalarOpacity(_colorMap->getOpacityTransferFunction(dataRange));
    138     }
    139 }
    140 
    141 /**
    142  * \brief Assign a color map (transfer function) to use in rendering the Volume and
    143  * specify a scalar range for the map
    144  */
    145 void Volume::setColorMap(ColorMap *cmap, double dataRange[2])
    146 {
    147     _colorMap = cmap;
    148     if (getVolume() != NULL) {
    149         getVolume()->GetProperty()->SetColor(_colorMap->getColorTransferFunction(dataRange));
    150         getVolume()->GetProperty()->SetScalarOpacity(_colorMap->getOpacityTransferFunction(dataRange));
     148        getVolume()->GetProperty()->SetColor(_colorMap->getColorTransferFunction(_dataRange));
     149        getVolume()->GetProperty()->SetScalarOpacity(_colorMap->getOpacityTransferFunction(_dataRange));
    151150    }
    152151}
  • branches/blt4/packages/vizservers/vtkvis/RpVolume.h

    r2409 r2542  
    4949    void setColorMap(ColorMap *cmap);
    5050
    51     void setColorMap(ColorMap *cmap, double dataRange[2]);
     51    ColorMap *getColorMap();
    5252
    53     ColorMap *getColorMap();
     53    void updateColorMap();
     54
     55    virtual void updateRanges(bool useCumulative,
     56                              double scalarRange[2],
     57                              double vectorMagnitudeRange[2],
     58                              double vectorComponentRange[3][2]);
    5459
    5560private:
  • branches/blt4/packages/vizservers/vtkvis/RpVtkDataSet.cpp

    r2409 r2542  
    66 */
    77
     8#include <cassert>
    89#include <cstring>
     10#include <cfloat>
     11#include <cmath>
    912
    1013#include <vtkCharArray.h>
     
    1821#include <vtkPointData.h>
    1922#include <vtkCellData.h>
     23#include <vtkCell.h>
    2024#include <vtkLookupTable.h>
    2125
     
    2731DataSet::DataSet(const std::string& name) :
    2832    _name(name),
    29     _visible(true)
    30 {
     33    _visible(true),
     34    _opacity(1),
     35    _cellSizeAverage(0)
     36{
     37    _cellSizeRange[0] = -1;
     38    _cellSizeRange[1] = -1;
    3139}
    3240
     
    3644
    3745/**
     46 * \brief Create and initialize a VTK Prop to render the outline
     47 */
     48void DataSet::initProp()
     49{
     50    if (_prop == NULL) {
     51        _prop = vtkSmartPointer<vtkActor>::New();
     52        vtkProperty *property = _prop->GetProperty();
     53        property->EdgeVisibilityOff();
     54        property->SetOpacity(_opacity);
     55        property->SetAmbient(.2);
     56        property->LightingOff();
     57        _prop->SetVisibility((_visible ? 1 : 0));
     58    }
     59}
     60
     61/**
     62 * \brief Create and initialize a wireframe outline
     63 */
     64void DataSet::showOutline(bool state)
     65{
     66    if (state) {
     67        if (_outlineFilter == NULL) {
     68            _outlineFilter = vtkSmartPointer<vtkOutlineFilter>::New();
     69            _outlineFilter->SetInput(_dataSet);
     70        }
     71        if (_outlineMapper == NULL) {
     72            _outlineMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
     73            _outlineMapper->SetInputConnection(_outlineFilter->GetOutputPort());
     74        }
     75        initProp();
     76        _prop->SetMapper(_outlineMapper);
     77    } else {
     78        if (_prop != NULL) {
     79            _prop->SetMapper(NULL);
     80        }
     81        if (_outlineMapper != NULL) {
     82            _outlineMapper = NULL;
     83        }
     84        if (_outlineFilter != NULL) {
     85            _outlineFilter = NULL;
     86        }
     87    }
     88}
     89
     90/**
     91 * \brief Set color of outline bounding box
     92 */
     93void DataSet::setOutlineColor(float color[3])
     94{
     95    if (_prop == NULL) {
     96        initProp();
     97    }
     98    _prop->GetProperty()->SetColor(color[0], color[1], color[2]);
     99}
     100
     101/**
     102 * \brief Set opacity of DataSet outline
     103 *
     104 * This method is used for record-keeping and opacity of the
     105 * DataSet bounds outline.  The renderer controls opacity
     106 * of other related graphics objects.
     107 */
     108void DataSet::setOpacity(double opacity)
     109{
     110    _opacity = opacity;
     111    if (_prop != NULL) {
     112        _prop->GetProperty()->SetOpacity(opacity);
     113    }
     114}
     115
     116/**
    38117 * \brief Set visibility flag in DataSet
    39118 *
    40  * This method is used for record-keeping.  The renderer controls
    41  * the visibility of related graphics objects.
     119 * This method is used for record-keeping and visibility of the
     120 * DataSet bounds outline.  The renderer controls visibility
     121 * of other related graphics objects.
    42122 */
    43123void DataSet::setVisibility(bool state)
    44124{
    45125    _visible = state;
     126    if (_prop != NULL) {
     127        _prop->SetVisibility((state ? 1 : 0));
     128    }
    46129}
    47130
     
    69152
    70153    reader->SetFileName(filename);
     154    reader->ReadAllNormalsOn();
     155    //reader->ReadAllTCoordsOn();
    71156    reader->ReadAllScalarsOn();
     157    //reader->ReadAllColorScalarsOn();
    72158    reader->ReadAllVectorsOn();
     159    //reader->ReadAllTensorsOn();
    73160    reader->ReadAllFieldsOn();
     161
    74162    return setData(reader);
    75163}
     
    80168bool DataSet::setData(char *data, int nbytes)
    81169{
    82     TRACE("Entering");
    83 
    84170    vtkSmartPointer<vtkDataSetReader> reader = vtkSmartPointer<vtkDataSetReader>::New();
    85171    vtkSmartPointer<vtkCharArray> dataSetString = vtkSmartPointer<vtkCharArray>::New();
     
    93179    reader->SetInputArray(dataSetString);
    94180    reader->ReadFromInputStringOn();
     181    reader->ReadAllNormalsOn();
     182    //reader->ReadAllTCoordsOn();
    95183    reader->ReadAllScalarsOn();
     184    //reader->ReadAllColorScalarsOn();
    96185    reader->ReadAllVectorsOn();
     186    //reader->ReadAllTensorsOn();
    97187    reader->ReadAllFieldsOn();
    98188
    99     bool status = setData(reader);
    100 
    101     TRACE("Leaving");
    102     return status;
    103 }
    104 
    105 /**
    106  * \brief Read dataset using supplied reader
    107  *
    108  * Pipeline information is removed from the resulting
    109  * vtkDataSet, so that the reader and its data can be
    110  * released
    111  */
    112 bool DataSet::setData(vtkDataSetReader *reader)
    113 {
    114     // Force reading data set
    115     reader->SetLookupTableName("");
    116     reader->Update();
    117 
    118     _dataSet = reader->GetOutput();
    119     _dataSet->SetPipelineInformation(NULL);
    120 
     189    return setData(reader);
     190}
     191
     192void DataSet::print() const
     193{
    121194    TRACE("DataSet class: %s", _dataSet->GetClassName());
    122 #ifdef WANT_TRACE
    123     double dataRange[2];
    124     getDataRange(dataRange);
     195
     196    TRACE("DataSet memory: %g MiB", _dataSet->GetActualMemorySize()/1024.);
     197
    125198    double bounds[6];
    126199    getBounds(bounds);
    127 #endif
    128     TRACE("Scalar Range: %.12e, %.12e", dataRange[0], dataRange[1]);
     200
     201    // Topology
    129202    TRACE("DataSet bounds: %g %g %g %g %g %g",
    130203          bounds[0], bounds[1],
     
    132205          bounds[4], bounds[5]);
    133206    TRACE("Points: %d Cells: %d", _dataSet->GetNumberOfPoints(), _dataSet->GetNumberOfCells());
     207
     208    double dataRange[2];
     209    if (_dataSet->GetPointData() != NULL) {
     210        TRACE("PointData arrays: %d", _dataSet->GetPointData()->GetNumberOfArrays());
     211        for (int i = 0; i < _dataSet->GetPointData()->GetNumberOfArrays(); i++) {
     212            _dataSet->GetPointData()->GetArray(i)->GetRange(dataRange, -1);
     213            TRACE("PointData[%d]: '%s' comp:%d, (%g,%g)", i,
     214                  _dataSet->GetPointData()->GetArrayName(i),
     215                  _dataSet->GetPointData()->GetArray(i)->GetNumberOfComponents(),
     216                  dataRange[0], dataRange[1]);
     217        }
     218    }
     219    if (_dataSet->GetCellData() != NULL) {
     220        TRACE("CellData arrays: %d", _dataSet->GetCellData()->GetNumberOfArrays());
     221        for (int i = 0; i < _dataSet->GetCellData()->GetNumberOfArrays(); i++) {
     222            _dataSet->GetCellData()->GetArray(i)->GetRange(dataRange, -1);
     223            TRACE("CellData[%d]: '%s' comp:%d, (%g,%g)", i,
     224                  _dataSet->GetCellData()->GetArrayName(i),
     225                  _dataSet->GetCellData()->GetArray(i)->GetNumberOfComponents(),
     226                  dataRange[0], dataRange[1]);
     227        }
     228    }
     229    if (_dataSet->GetFieldData() != NULL) {
     230        TRACE("FieldData arrays: %d", _dataSet->GetFieldData()->GetNumberOfArrays());
     231        for (int i = 0; i < _dataSet->GetFieldData()->GetNumberOfArrays(); i++) {
     232            _dataSet->GetFieldData()->GetArray(i)->GetRange(dataRange, -1);
     233            TRACE("FieldData[%d]: '%s' comp:%d, tuples:%d (%g,%g)", i,
     234                  _dataSet->GetFieldData()->GetArrayName(i),
     235                  _dataSet->GetFieldData()->GetArray(i)->GetNumberOfComponents(),
     236                  _dataSet->GetFieldData()->GetArray(i)->GetNumberOfTuples(),
     237                  dataRange[0], dataRange[1]);
     238        }
     239    }
     240}
     241
     242void DataSet::setDefaultArrays()
     243{
     244    if (_dataSet->GetPointData() != NULL &&
     245        _dataSet->GetPointData()->GetScalars() == NULL &&
     246        _dataSet->GetPointData()->GetNumberOfArrays() > 0) {
     247        for (int i = 0; i < _dataSet->GetPointData()->GetNumberOfArrays(); i++) {
     248            if (_dataSet->GetPointData()->GetArray(i)->GetNumberOfComponents() == 1) {
     249                TRACE("Setting point scalars to '%s'", _dataSet->GetPointData()->GetArrayName(i));
     250                _dataSet->GetPointData()->SetActiveScalars(_dataSet->GetPointData()->GetArrayName(i));
     251                break;
     252            }
     253        }
     254    }
     255    if (_dataSet->GetPointData() != NULL &&
     256        _dataSet->GetPointData()->GetVectors() == NULL &&
     257        _dataSet->GetPointData()->GetNumberOfArrays() > 0) {
     258        for (int i = 0; i < _dataSet->GetPointData()->GetNumberOfArrays(); i++) {
     259            if (_dataSet->GetPointData()->GetArray(i)->GetNumberOfComponents() == 3) {
     260                TRACE("Setting point vectors to '%s'", _dataSet->GetPointData()->GetArrayName(i));
     261                _dataSet->GetPointData()->SetActiveVectors(_dataSet->GetPointData()->GetArrayName(i));
     262                break;
     263            }
     264        }
     265    }
     266    if (_dataSet->GetCellData() != NULL &&
     267        _dataSet->GetCellData()->GetScalars() == NULL &&
     268        _dataSet->GetCellData()->GetNumberOfArrays() > 0) {
     269        for (int i = 0; i < _dataSet->GetCellData()->GetNumberOfArrays(); i++) {
     270            if (_dataSet->GetCellData()->GetArray(i)->GetNumberOfComponents() == 1) {
     271                TRACE("Setting cell scalars to '%s'", _dataSet->GetCellData()->GetArrayName(i));
     272                _dataSet->GetCellData()->SetActiveScalars(_dataSet->GetCellData()->GetArrayName(i));
     273                break;
     274            }
     275        }
     276    }
     277    if (_dataSet->GetCellData() != NULL &&
     278        _dataSet->GetCellData()->GetVectors() == NULL &&
     279        _dataSet->GetCellData()->GetNumberOfArrays() > 0) {
     280        for (int i = 0; i < _dataSet->GetCellData()->GetNumberOfArrays(); i++) {
     281            if (_dataSet->GetCellData()->GetArray(i)->GetNumberOfComponents() == 3) {
     282                TRACE("Setting cell vectors to '%s'", _dataSet->GetCellData()->GetArrayName(i));
     283                _dataSet->GetCellData()->SetActiveVectors(_dataSet->GetCellData()->GetArrayName(i));
     284                break;
     285            }
     286        }
     287    }
     288}
     289
     290/**
     291 * \brief Read dataset using supplied reader
     292 *
     293 * Pipeline information is removed from the resulting
     294 * vtkDataSet, so that the reader and its data can be
     295 * released
     296 */
     297bool DataSet::setData(vtkDataSetReader *reader)
     298{
     299    TRACE("Enter");
     300    // Force reading data set
     301    reader->SetLookupTableName("");
     302    reader->Update();
     303
     304    _dataSet = reader->GetOutput();
     305    _dataSet->SetPipelineInformation(NULL);
     306
     307    if (_dataSet->GetPointData() != NULL &&
     308        _dataSet->GetPointData()->GetScalars() != NULL &&
     309        _dataSet->GetPointData()->GetScalars()->GetLookupTable() != NULL) {
     310        ERROR("No lookup table should be specified in DataSets");
     311    }
     312
     313    setDefaultArrays();
     314
     315#ifdef WANT_TRACE
     316    print();
     317#endif
     318    TRACE("Leave");
    134319    return true;
    135320}
     
    145330    _dataSet->SetPipelineInformation(NULL);
    146331
    147     TRACE("DataSet class: %s", _dataSet->GetClassName());
     332    if (_dataSet->GetPointData() != NULL &&
     333        _dataSet->GetPointData()->GetScalars() != NULL &&
     334        _dataSet->GetPointData()->GetScalars()->GetLookupTable() != NULL) {
     335        ERROR("No lookup table should be specified in DataSets");
     336    }
     337
     338    setDefaultArrays();
     339
    148340#ifdef WANT_TRACE
    149     double dataRange[2];
    150     getDataRange(dataRange);
    151     double bounds[6];
    152     getBounds(bounds);
     341    print();
    153342#endif
    154     TRACE("Scalar Range: %.12e, %.12e", dataRange[0], dataRange[1]);
    155     TRACE("DataSet bounds: %g %g %g %g %g %g",
    156           bounds[0], bounds[1],
    157           bounds[2], bounds[3],
    158           bounds[4], bounds[5]);
    159     TRACE("Points: %d Cells: %d", _dataSet->GetNumberOfPoints(), _dataSet->GetNumberOfCells());
    160343    return true;
    161344}
     
    190373    }
    191374
    192     TRACE("DataSet class: %s", _dataSet->GetClassName());
    193375#ifdef WANT_TRACE
    194     double dataRange[2];
    195     getDataRange(dataRange);
    196     double bounds[6];
    197     getBounds(bounds);
     376    print();
    198377#endif   
    199     TRACE("Scalar Range: %.12e, %.12e", dataRange[0], dataRange[1]);
    200     TRACE("DataSet bounds: %g %g %g %g %g %g",
    201           bounds[0], bounds[1],
    202           bounds[2], bounds[3],
    203           bounds[4], bounds[5]);
    204378    return _dataSet;
    205379}
     
    208382 * \brief Does DataSet lie in the XY plane (z = 0)
    209383 */
    210 bool DataSet::is2D() const
     384bool DataSet::isXY() const
    211385{
    212386    double bounds[6];
     
    216390
    217391/**
     392 * \brief Returns the dimensionality of the AABB
     393 */
     394int DataSet::numDimensions() const
     395{
     396    double bounds[6];
     397    getBounds(bounds);
     398    int numDims = 0;
     399    if (bounds[0] != bounds[1])
     400        numDims++;
     401    if (bounds[2] != bounds[3])
     402        numDims++;
     403    if (bounds[4] != bounds[5])
     404        numDims++;
     405
     406    return numDims;
     407}
     408
     409/**
     410 * \brief Determines if DataSet lies in a principal axis plane
     411 * and if so, returns the plane normal and offset from origin
     412 */
     413bool DataSet::is2D(DataSet::PrincipalPlane *plane, double *offset) const
     414{
     415    double bounds[6];
     416    getBounds(bounds);
     417    if (bounds[4] == bounds[5]) {
     418        // Z = 0, XY plane
     419        if (plane != NULL) {
     420            *plane = PLANE_XY;
     421        }
     422        if (offset != NULL)
     423            *offset = bounds[4];
     424        return true;
     425    } else if (bounds[0] == bounds[1]) {
     426        // X = 0, ZY plane
     427        if (plane != NULL) {
     428            *plane = PLANE_ZY;
     429        }
     430        if (offset != NULL)
     431            *offset = bounds[0];
     432        return true;
     433    } else if (bounds[2] == bounds[3]) {
     434        // Y = 0, XZ plane
     435        if (plane != NULL) {
     436            *plane = PLANE_XZ;
     437         }
     438        if (offset != NULL)
     439            *offset = bounds[2];
     440        return true;
     441    }
     442    return false;
     443}
     444
     445/**
     446 * \brief Determines a principal plane with the
     447 * largest two dimensions of the AABB
     448 */
     449DataSet::PrincipalPlane DataSet::principalPlane() const
     450{
     451    double bounds[6];
     452    getBounds(bounds);
     453    double xlen = bounds[1] - bounds[0];
     454    double ylen = bounds[3] - bounds[2];
     455    double zlen = bounds[5] - bounds[4];
     456    if (zlen <= xlen && zlen <= ylen) {
     457        return PLANE_XY;
     458    } else if (xlen <= ylen && xlen <= zlen) {
     459        return PLANE_ZY;
     460    } else {
     461        return PLANE_XZ;
     462    }
     463}
     464
     465/**
    218466 * \brief Get the name/id of this dataset
    219467 */
     
    247495    if (_dataSet != NULL) {
    248496        if (_dataSet->GetPointData() != NULL) {
    249             if (_dataSet->GetPointData()->SetActiveScalars(name) >= 0)
     497            if (_dataSet->GetPointData()->SetActiveScalars(name) >= 0) {
     498                TRACE("Set active point data scalars to %s", name);
    250499                found = true;
     500            }
    251501        }
    252502        if (_dataSet->GetCellData() != NULL) {
    253             if (_dataSet->GetCellData()->SetActiveScalars(name) >= 0)
     503            if (_dataSet->GetCellData()->SetActiveScalars(name) >= 0) {
     504                TRACE("Set active cell data scalars to %s", name);
    254505                found = true;
    255         }
    256     }
     506            }
     507        }
     508    }
     509#ifdef WANT_TRACE
     510    if (_dataSet->GetPointData() != NULL) {
     511        if (_dataSet->GetPointData()->GetScalars() != NULL) {
     512            TRACE("Point data scalars: %s", _dataSet->GetPointData()->GetScalars()->GetName());
     513        } else {
     514            TRACE("NULL point data scalars");
     515        }
     516    }
     517    if (_dataSet->GetCellData() != NULL) {
     518        if (_dataSet->GetCellData()->GetScalars() != NULL) {
     519            TRACE("Cell data scalars: %s", _dataSet->GetCellData()->GetScalars()->GetName());
     520        } else {
     521            TRACE("NULL cell data scalars");
     522        }
     523    }
     524#endif
    257525    return found;
     526}
     527
     528/**
     529 * \brief Get the active scalar array field name
     530 */
     531const char *DataSet::getActiveScalarsName()
     532{
     533    if (_dataSet != NULL) {
     534         if (_dataSet->GetPointData() != NULL &&
     535             _dataSet->GetPointData()->GetScalars() != NULL) {
     536            return _dataSet->GetPointData()->GetScalars()->GetName();
     537        }
     538        TRACE("No point scalars");
     539        if (_dataSet->GetCellData() != NULL &&
     540            _dataSet->GetCellData()->GetScalars() != NULL) {
     541            return _dataSet->GetCellData()->GetScalars()->GetName();
     542        }
     543        TRACE("No cell scalars");
     544    }
     545    return NULL;
    258546}
    259547
     
    266554    if (_dataSet != NULL) {
    267555        if (_dataSet->GetPointData() != NULL) {
    268             if (_dataSet->GetPointData()->SetActiveVectors(name) >= 0)
     556            if (_dataSet->GetPointData()->SetActiveVectors(name) >= 0) {
     557                TRACE("Set active point data vectors to %s", name);
    269558                found = true;
     559            }
    270560        }
    271561        if (_dataSet->GetCellData() != NULL) {
    272             if (_dataSet->GetCellData()->SetActiveVectors(name) >= 0)
     562            if (_dataSet->GetCellData()->SetActiveVectors(name) >= 0) {
     563                TRACE("Set active cell data vectors to %s", name);
    273564                found = true;
    274         }
    275     }
     565            }
     566        }
     567    }
     568
    276569    return found;
    277570}
    278571
    279572/**
     573 * \brief Get the active vector array field name
     574 */
     575const char *DataSet::getActiveVectorsName()
     576{
     577    if (_dataSet != NULL) {
     578        if (_dataSet->GetPointData() != NULL &&
     579            _dataSet->GetPointData()->GetVectors() != NULL) {
     580            return _dataSet->GetPointData()->GetVectors()->GetName();
     581        }
     582        TRACE("No point vectors");
     583        if (_dataSet->GetCellData() != NULL &&
     584            _dataSet->GetCellData()->GetVectors() != NULL) {
     585            return _dataSet->GetCellData()->GetVectors()->GetName();
     586        }
     587        TRACE("No cell vectors");
     588    }
     589    return NULL;
     590}
     591
     592/**
    280593 * \brief Get the range of scalar values in the DataSet
    281594 */
    282 void DataSet::getDataRange(double minmax[2]) const
    283 {
    284     _dataSet->GetScalarRange(minmax);
    285 }
    286 
    287 /**
    288  * \brief Get the range of scalar values (or vector magnitudes) for
    289  * the named field in the DataSet
    290  */
    291 void DataSet::getDataRange(double minmax[2], const char *fieldName) const
     595void DataSet::getScalarRange(double minmax[2]) const
    292596{
    293597    if (_dataSet == NULL)
    294598        return;
    295599    if (_dataSet->GetPointData() != NULL &&
    296         _dataSet->GetPointData()->GetArray(fieldName) != NULL) {
    297         _dataSet->GetPointData()->GetArray(fieldName)->GetRange(minmax, -1);
     600        _dataSet->GetPointData()->GetScalars() != NULL) {
     601        _dataSet->GetPointData()->GetScalars()->GetRange(minmax, -1);
    298602    } else if (_dataSet->GetCellData() != NULL &&
    299         _dataSet->GetCellData()->GetArray(fieldName) != NULL) {
    300         _dataSet->GetCellData()->GetArray(fieldName)->GetRange(minmax, -1);
    301     } else if (_dataSet->GetFieldData() != NULL &&
    302         _dataSet->GetFieldData()->GetArray(fieldName) != NULL) {
    303         _dataSet->GetFieldData()->GetArray(fieldName)->GetRange(minmax, -1);
    304     }
    305 }
    306 
    307 /**
    308  * \brief Get the range of vector magnitudes in the DataSet
    309  */
    310 void DataSet::getVectorMagnitudeRange(double minmax[2]) const
    311 {
    312     if (_dataSet == NULL)
    313         return;
    314     if (_dataSet->GetPointData() != NULL &&
    315         _dataSet->GetPointData()->GetVectors() != NULL) {
    316         _dataSet->GetPointData()->GetVectors()->GetRange(minmax, -1);
    317     } else if (_dataSet->GetCellData() != NULL &&
    318                _dataSet->GetCellData()->GetVectors() != NULL) {
    319         _dataSet->GetCellData()->GetVectors()->GetRange(minmax, -1);
     603               _dataSet->GetCellData()->GetScalars() != NULL) {
     604        _dataSet->GetCellData()->GetScalars()->GetRange(minmax, -1);
    320605    }
    321606}
     
    323608/**
    324609 * \brief Get the range of a vector component in the DataSet
    325  */
    326 void DataSet::getVectorComponentRange(double minmax[2], int component) const
     610 *
     611 * \param[out] minmax The data range
     612 * \param[in] component The field component, -1 means magnitude
     613 */
     614void DataSet::getVectorRange(double minmax[2], int component) const
    327615{
    328616    if (_dataSet == NULL)
     
    338626
    339627/**
     628 * \brief Get the range of values for the named field in the DataSet
     629 *
     630 * \param[out] minmax The data range
     631 * \param[in] fieldName The array name
     632 * \param[in] component The field component, -1 means magnitude
     633 */
     634void DataSet::getDataRange(double minmax[2], const char *fieldName, int component) const
     635{
     636    if (_dataSet == NULL)
     637        return;
     638    if (_dataSet->GetPointData() != NULL &&
     639        _dataSet->GetPointData()->GetArray(fieldName) != NULL) {
     640        _dataSet->GetPointData()->GetArray(fieldName)->GetRange(minmax, component);
     641    } else if (_dataSet->GetCellData() != NULL &&
     642        _dataSet->GetCellData()->GetArray(fieldName) != NULL) {
     643        _dataSet->GetCellData()->GetArray(fieldName)->GetRange(minmax, component);
     644    } else if (_dataSet->GetFieldData() != NULL &&
     645        _dataSet->GetFieldData()->GetArray(fieldName) != NULL) {
     646        _dataSet->GetFieldData()->GetArray(fieldName)->GetRange(minmax, component);
     647    }
     648}
     649
     650/**
    340651 * \brief Get the bounds the DataSet
    341652 */
     
    346657
    347658/**
     659 * \brief Get the range of cell AABB diagonal lengths in the DataSet
     660 */
     661void DataSet::getCellSizeRange(double minmax[2], double *average)
     662{
     663    if (_dataSet == NULL ||
     664        _dataSet->GetNumberOfCells() < 1) {
     665        minmax[0] = 1;
     666        minmax[1] = 1;
     667        *average = 1;
     668        return;
     669    }
     670
     671    if (_cellSizeRange[0] >= 0.0) {
     672        minmax[0] = _cellSizeRange[0];
     673        minmax[1] = _cellSizeRange[1];
     674        *average = _cellSizeAverage;
     675        return;
     676    }
     677
     678    minmax[0] = DBL_MAX;
     679    minmax[1] = -DBL_MAX;
     680
     681    *average = 0;
     682    for (int i = 0; i < _dataSet->GetNumberOfCells(); i++) {
     683        double length2 = _dataSet->GetCell(i)->GetLength2();
     684        if (length2 < minmax[0])
     685            minmax[0] = length2;
     686        if (length2 > minmax[1])
     687            minmax[1] = length2;
     688        *average += length2;
     689    }
     690    if (minmax[0] == DBL_MAX)
     691        minmax[0] = 1;
     692    if (minmax[1] == -DBL_MAX)
     693        minmax[1] = 1;
     694
     695    minmax[0] = sqrt(minmax[0]);
     696    minmax[1] = sqrt(minmax[1]);
     697    *average = sqrt(*average/((double)_dataSet->GetNumberOfCells()));
     698    _cellSizeRange[0] = minmax[0];
     699    _cellSizeRange[1] = minmax[1];
     700    _cellSizeAverage = *average;
     701}
     702
     703/**
    348704 * \brief Get nearest data value given world coordinates x,y,z
    349705 *
     
    352708 * \return the value of the nearest point or 0 if no scalar data available
    353709 */
    354 double DataSet::getDataValue(double x, double y, double z) const
     710bool DataSet::getScalarValue(double x, double y, double z, double *value) const
    355711{
    356712    if (_dataSet == NULL)
    357         return 0;
     713        return false;
    358714    if (_dataSet->GetPointData() == NULL ||
    359715        _dataSet->GetPointData()->GetScalars() == NULL) {
    360         return 0.0;
     716        return false;
    361717    }
    362718    vtkIdType pt = _dataSet->FindPoint(x, y, z);
    363     return _dataSet->GetPointData()->GetScalars()->GetComponent(pt, 0);
    364 }
     719    if (pt < 0)
     720        return false;
     721    *value = _dataSet->GetPointData()->GetScalars()->GetComponent(pt, 0);
     722    return true;
     723}
     724
     725/**
     726 * \brief Get nearest vector data value given world coordinates x,y,z
     727 *
     728 * Note: no interpolation is performed on data
     729 *
     730 * \param[in] x World x coordinate to probe
     731 * \param[in] y World y coordinate to probe
     732 * \param[in] z World z coordinate to probe
     733 * \param[out] vector On success, contains the data values
     734 * \return boolean indicating success or failure
     735 */
     736bool DataSet::getVectorValue(double x, double y, double z, double vector[3]) const
     737{
     738    if (_dataSet == NULL)
     739        return false;
     740    if (_dataSet->GetPointData() == NULL ||
     741        _dataSet->GetPointData()->GetVectors() == NULL) {
     742        return false;
     743    }
     744    vtkIdType pt = _dataSet->FindPoint(x, y, z);
     745    if (pt < 0)
     746        return false;
     747    assert(_dataSet->GetPointData()->GetVectors()->GetNumberOfComponents() == 3);
     748    _dataSet->GetPointData()->GetVectors()->GetTuple(pt, vector);
     749    return true;
     750}
  • branches/blt4/packages/vizservers/vtkvis/RpVtkDataSet.h

    r2409 r2542  
    1212#include <vtkDataSet.h>
    1313#include <vtkDataSetReader.h>
     14#include <vtkProp.h>
     15#include <vtkActor.h>
     16#include <vtkOutlineFilter.h>
     17#include <vtkPolyDataMapper.h>
    1418
    1519#include <string>
     
    2428class DataSet {
    2529public:
     30    enum PrincipalPlane {
     31        PLANE_XY,
     32        PLANE_ZY,
     33        PLANE_XZ
     34    };
    2635    DataSet(const std::string& name);
    2736    virtual ~DataSet();
     
    3746    vtkDataSet *copyData(vtkDataSet *ds);
    3847
    39     bool is2D() const;
     48    bool isXY() const;
     49
     50    int numDimensions() const;
     51
     52    bool is2D(PrincipalPlane *plane = NULL, double *offset = NULL) const;
     53
     54    PrincipalPlane principalPlane() const;
    4055
    4156    const std::string& getName() const;
     
    4762    bool setActiveScalars(const char *name);
    4863
     64    const char *getActiveScalarsName();
     65
    4966    bool setActiveVectors(const char *name);
    5067
    51     void getDataRange(double minmax[2]) const;
     68    const char *getActiveVectorsName();
    5269
    53     void getDataRange(double minmax[2], const char *fieldName) const;
     70    void getScalarRange(double minmax[2]) const;
    5471
    55     void getVectorMagnitudeRange(double minmax[2]) const;
     72    void getDataRange(double minmax[2], const char *fieldName, int component = -1) const;
    5673
    57     void getVectorComponentRange(double minmax[2], int component) const;
     74    void getVectorRange(double minmax[2], int component = -1) const;
    5875
    5976    void getBounds(double bounds[6]) const;
    6077
    61     double getDataValue(double x, double y, double z) const;
     78    void getCellSizeRange(double minmax[2], double *average);
     79
     80    bool getScalarValue(double x, double y, double z, double *value) const;
     81
     82    bool getVectorValue(double x, double y, double z, double vector[3]) const;
     83
     84    void setOpacity(double opacity);
     85
     86    /**
     87     * \brief Get the opacity setting for the DataSet
     88     *
     89     * This method is used for record-keeping.  The renderer controls
     90     * the visibility of related graphics objects.
     91     */
     92    inline double getOpacity()
     93    {
     94        return _opacity;
     95    }
    6296
    6397    void setVisibility(bool state);
     
    6599    bool getVisibility() const;
    66100
     101    void showOutline(bool state);
     102
     103    void setOutlineColor(float color[3]);
     104
     105    /**
     106     * \brief Return the VTK prop object for the outline
     107     */
     108    inline vtkProp *getProp()
     109    {
     110        return _prop;
     111    }
     112
    67113private:
    68114    DataSet();
     115
     116    void setDefaultArrays();
     117    void print() const;
     118
     119    void initProp();
    69120
    70121    std::string _name;
    71122    vtkSmartPointer<vtkDataSet> _dataSet;
    72123    bool _visible;
     124    double _opacity;
     125    double _cellSizeRange[2];
     126    double _cellSizeAverage;
     127    vtkSmartPointer<vtkOutlineFilter> _outlineFilter;
     128    vtkSmartPointer<vtkActor> _prop;
     129    vtkSmartPointer<vtkPolyDataMapper> _outlineMapper;
    73130};
    74131
  • branches/blt4/packages/vizservers/vtkvis/RpVtkGraphicsObject.h

    r2410 r2542  
    4646        _opacity(1.0),
    4747        _edgeWidth(1.0f),
     48        _pointSize(1.0f),
    4849        _lighting(true),
    4950        _cullFace(CULL_BACK),
    5051        _faceCulling(false)
    5152    {
     53        _dataRange[0] = 0;
     54        _dataRange[1] = 1;
    5255        _color[0] = 1.0f;
    5356        _color[1] = 1.0f;
     
    7073     *
    7174     * Default implementation calls update()
     75     *
     76     * \param[in] dataSet DataSet to use in rendering
    7277     */
    7378    virtual void setDataSet(DataSet *dataSet)
     
    7580        if (_dataSet != dataSet) {
    7681            _dataSet = dataSet;
     82
    7783            update();
     84        }
     85    }
     86
     87    /**
     88     * \brief Specify input DataSet and information on cumulative data ranges
     89     *
     90     * Default implementation calls update() and stores scalarRange to
     91     * _dataRange based on cumulative range settings
     92     *
     93     * \param[in] dataSet DataSet to use in rendering
     94     * \param[in] useCumulative Whether the cumulative data ranges should be
     95     * used in place of the dataSet's ranges
     96     * \param[in] scalarRange Current cumulative scalar data range
     97     * \param[in] vectorMagnitudeRange Current cumulative vector magnitude data range
     98     * \param[in] vectorComponentRange Current cumulative vector component data ranges
     99     */
     100    virtual void setDataSet(DataSet *dataSet,
     101                            bool useCumulative,
     102                            double scalarRange[2],
     103                            double vectorMagnitudeRange[2],
     104                            double vectorComponentRange[3][2])
     105    {
     106        if (_dataSet != dataSet) {
     107            _dataSet = dataSet;
     108
     109            if (useCumulative) {
     110                _dataRange[0] = scalarRange[0];
     111                _dataRange[1] = scalarRange[1];
     112            } else {
     113                _dataSet->getScalarRange(_dataRange);
     114            }
     115
     116            update();
     117        }
     118    }
     119
     120    /**
     121     * \brief Called when scalar or vector field changes (e.g. active field) or
     122     * cumulative ranges or settings change
     123     *
     124     * \param[in] useCumulative Whether the cumulative data ranges should be
     125     * used in place of the dataSet's ranges
     126     * \param[in] scalarRange Current cumulative scalar data range
     127     * \param[in] vectorMagnitudeRange Current cumulative vector magnitude data range
     128     * \param[in] vectorComponentRange Current cumulative vector component data ranges
     129     */
     130    virtual void updateRanges(bool useCumulative,
     131                              double scalarRange[2],
     132                              double vectorMagnitudeRange[2],
     133                              double vectorComponentRange[3][2])
     134    {
     135        if (useCumulative) {
     136            _dataRange[0] = scalarRange[0];
     137            _dataRange[1] = scalarRange[1];
     138        } else {
     139            _dataSet->getScalarRange(_dataRange);
    78140        }
    79141    }
     
    171233            double angle = vtkMath::DegreesFromRadians(2.0 * acos(quat[0]));
    172234            double axis[3];
    173             double denom = sqrt(1. - quat[0] * quat[0]);
    174             axis[0] = quat[1] / denom;
    175             axis[1] = quat[2] / denom;
    176             axis[2] = quat[3] / denom;
     235            if (angle < 1.0e-6) {
     236                axis[0] = 1;
     237                axis[1] = 0;
     238                axis[2] = 0;
     239            } else {
     240                double denom = sqrt(1. - quat[0] * quat[0]);
     241                axis[0] = quat[1] / denom;
     242                axis[1] = quat[2] / denom;
     243                axis[2] = quat[3] / denom;
     244             }
    177245            setOrientation(angle, axis);
    178246        }
     
    522590    {
    523591        for (int i = 0; i < 3; i++)
    524             _color[i] = color[i];
     592            _edgeColor[i] = color[i];
    525593        if (getActor() != NULL) {
    526594            getActor()->GetProperty()->SetEdgeColor(color[0], color[1], color[2]);
     
    540608     * \brief Set pixel width of edges
    541609     *
    542      * NOTE: May be a no-op if OpenGL implementation doesn't support fat lines
     610     * NOTE: May be a no-op if OpenGL implementation doesn't support wide lines
    543611     */
    544612    virtual void setEdgeWidth(float width)
     
    554622                if (vtkActor::SafeDownCast(prop) != NULL) {
    555623                    vtkActor::SafeDownCast(prop)->GetProperty()->SetLineWidth(width);
     624                }
     625            }
     626        }
     627    }
     628
     629    /**
     630     * \brief Set point size
     631     *
     632     * NOTE: May be a no-op if OpenGL implementation doesn't support wide points
     633     */
     634    virtual void setPointSize(float size)
     635    {
     636        _pointSize = size;
     637        if (getActor() != NULL) {
     638            getActor()->GetProperty()->SetPointSize(size);
     639        } else if (getAssembly() != NULL) {
     640            vtkProp3DCollection *props = getAssembly()->GetParts();
     641            vtkProp3D *prop;
     642            props->InitTraversal();
     643            while ((prop = props->GetNextProp3D()) != NULL) {
     644                if (vtkActor::SafeDownCast(prop) != NULL) {
     645                    vtkActor::SafeDownCast(prop)->GetProperty()->SetPointSize(size);
    556646                }
    557647            }
     
    589679        }
    590680    }
     681
     682    /**
     683     * \brief Toggle culling of selected CullFace
     684     */
     685    virtual void setCulling(bool state)
     686    {
     687        _faceCulling = state;
     688        if (state && _opacity < 1.0)
     689            return;
     690        if (getActor() != NULL) {
     691            setCulling(getActor()->GetProperty(), state);
     692         } else if (getAssembly() != NULL) {
     693            vtkProp3DCollection *props = getAssembly()->GetParts();
     694            vtkProp3D *prop;
     695            props->InitTraversal();
     696            while ((prop = props->GetNextProp3D()) != NULL) {
     697                if (vtkActor::SafeDownCast(prop) != NULL) {
     698                    setCulling(vtkActor::SafeDownCast(prop)->GetProperty(), state);
     699                }
     700            }
     701        }
     702    }
     703
     704    /**
     705     * \brief Specify which face(s) to cull when culling is enabled
     706     */
     707    virtual void setCullFace(CullFace cull)
     708    {
     709        _cullFace = cull;
     710        setCulling(_faceCulling);
     711    }
     712
     713    /**
     714     * \brief Subclasses need to implement setting clipping planes in their mappers
     715     */
     716    virtual void setClippingPlanes(vtkPlaneCollection *planes) = 0;
     717
     718protected:
     719    /**
     720     * \brief Create and initialize a VTK Prop to render the object
     721     */
     722    virtual void initProp()
     723    {
     724        if (_prop == NULL) {
     725            _prop = vtkSmartPointer<vtkActor>::New();
     726            vtkProperty *property = getActor()->GetProperty();
     727            property->SetColor(_color[0], _color[1], _color[2]);
     728            property->SetEdgeColor(_edgeColor[0], _edgeColor[1], _edgeColor[2]);
     729            property->SetLineWidth(_edgeWidth);
     730            property->SetPointSize(_pointSize);
     731            property->EdgeVisibilityOff();
     732            property->SetOpacity(_opacity);
     733            property->SetAmbient(.2);
     734            if (!_lighting)
     735                property->LightingOff();
     736            if (_faceCulling && _opacity == 1.0) {
     737                setCulling(property, true);
     738            }
     739        }
     740    }
     741
     742    /**
     743     * \brief Subclasses implement this to create the VTK pipeline
     744     * on a state change (e.g. new DataSet)
     745     */
     746    virtual void update() = 0;
    591747
    592748    /**
     
    613769    }
    614770
    615     /**
    616      * \brief Toggle culling of selected CullFace
    617      */
    618     virtual void setCulling(bool state)
    619     {
    620         _faceCulling = state;
    621         if (state && _opacity < 1.0)
    622             return;
    623         if (getActor() != NULL) {
    624             setCulling(getActor()->GetProperty(), state);
    625          } else if (getAssembly() != NULL) {
    626             vtkProp3DCollection *props = getAssembly()->GetParts();
    627             vtkProp3D *prop;
    628             props->InitTraversal();
    629             while ((prop = props->GetNextProp3D()) != NULL) {
    630                 if (vtkActor::SafeDownCast(prop) != NULL) {
    631                     setCulling(vtkActor::SafeDownCast(prop)->GetProperty(), state);
    632                 }
    633             }
    634         }
    635     }
    636 
    637     virtual void setCullFace(CullFace cull)
    638     {
    639         _cullFace = cull;
    640         setCulling(_faceCulling);
    641     }
    642 
    643     /**
    644      * \brief Subclasses need to implement setting clipping planes in their mappers
    645      */
    646     virtual void setClippingPlanes(vtkPlaneCollection *planes) = 0;
    647 
    648 protected:
    649     /**
    650      * \brief Create and initialize a VTK Prop to render the object
    651      */
    652     virtual void initProp()
    653     {
    654         if (_prop == NULL) {
    655             _prop = vtkSmartPointer<vtkActor>::New();
    656             vtkProperty *property = getActor()->GetProperty();
    657             property->EdgeVisibilityOff();
    658             property->SetOpacity(_opacity);
    659             property->SetAmbient(.2);
    660             if (!_lighting)
    661                 property->LightingOff();
    662             if (_faceCulling && _opacity == 1.0) {
    663                 setCulling(property, true);
    664             }
    665         }
    666     }
    667 
    668     /**
    669      * \brief Subclasses implement this to create the VTK pipeline
    670      * on a state change (e.g. new DataSet)
    671      */
    672     virtual void update() = 0;
    673 
    674771    DataSet *_dataSet;
     772    double _dataRange[2];
    675773    double _opacity;
    676774    float _color[3];
    677775    float _edgeColor[3];
    678776    float _edgeWidth;
     777    float _pointSize;
    679778    bool _lighting;
    680779    CullFace _cullFace;
  • branches/blt4/packages/vizservers/vtkvis/RpVtkRenderServer.cpp

    r2409 r2542  
     1
    12/* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
    23/*
     
    910#include <cstring>
    1011#include <cstdlib>
    11 #include <string>
    12 #include <sstream>
     12#include <cerrno>
    1313#include <unistd.h>
    1414#include <signal.h>
     
    1717#include <sys/time.h>
    1818#endif
     19
     20#include <string>
     21#include <sstream>
    1922
    2023#include "Trace.h"
     
    2427#include "PPMWriter.h"
    2528#include "TGAWriter.h"
     29#ifdef USE_THREADS
     30#include <pthread.h>
     31#include "ResponseQueue.h"
     32#endif
    2633
    2734using namespace Rappture::VtkVis;
     
    3845     (((t2).tv_sec - (t1).tv_sec))*1.0e+3f + (float)((t2).tv_usec - (t1).tv_usec)/1.0e+3f)
    3946
     47#ifdef USE_THREADS
    4048static void
    41 writeFrame(int fd, vtkUnsignedCharArray *imgData)
     49queueFrame(ResponseQueue *queue, vtkUnsignedCharArray *imgData)
    4250{
    4351#ifdef DEBUG
     
    6573                 TARGA_BYTES_PER_PIXEL,
    6674                 true);
    67 #endif
     75#endif  /*RENDER_TARGA*/
    6876
    6977#else
    7078    if (g_renderer->getCameraMode() == Renderer::IMAGE) {
    7179        double xywh[4];
    72         g_renderer->getScreenWorldCoords(xywh);
     80        g_renderer->getCameraZoomRegion(xywh);
    7381        std::ostringstream oss;
    7482        oss.precision(12);
     
    7785            << std::scientific
    7886            << xywh[0] << " "
    79             << (xywh[1] + xywh[3]) << " "
    80             << (xywh[0] + xywh[2]) << " "
    81             << xywh[1] << "} -bytes";
     87            << xywh[1] << " "
     88            << xywh[2] << " "
     89            << xywh[3] << "} -bytes";
     90
     91#ifdef RENDER_TARGA
     92        queueTGA(queue, oss.str().c_str(),
     93                 imgData->GetPointer(0),
     94                 g_renderer->getWindowWidth(),
     95                 g_renderer->getWindowHeight(),
     96                 TARGA_BYTES_PER_PIXEL);
     97#else
     98        queuePPM(queue, oss.str().c_str(),
     99                 imgData->GetPointer(0),
     100                 g_renderer->getWindowWidth(),
     101                 g_renderer->getWindowHeight());
     102#endif  /*RENDER_TARGA*/
     103    } else {
     104#ifdef RENDER_TARGA
     105        queueTGA(queue, "nv>image -type image -bytes",
     106                 imgData->GetPointer(0),
     107                 g_renderer->getWindowWidth(),
     108                 g_renderer->getWindowHeight(),
     109                 TARGA_BYTES_PER_PIXEL);
     110#else
     111        queuePPM(queue, "nv>image -type image -bytes",
     112                 imgData->GetPointer(0),
     113                 g_renderer->getWindowWidth(),
     114                 g_renderer->getWindowHeight());
     115#endif  /*RENDER_TARGA*/
     116    }
     117#endif  /*DEBUG*/
     118}
     119
     120#else
     121
     122static void
     123writeFrame(int fd, vtkUnsignedCharArray *imgData)
     124{
     125#ifdef DEBUG
     126    if (g_renderer->getCameraMode() == Renderer::IMAGE) {
     127        double xywh[4];
     128        g_renderer->getScreenWorldCoords(xywh);
     129        TRACE("Image bbox: %g %g %g %g",
     130              xywh[0],
     131              (xywh[1] + xywh[3]),
     132              (xywh[0] + xywh[2]),
     133              xywh[1]);
     134    }
     135
     136#ifdef RENDER_TARGA
     137    writeTGAFile("/tmp/frame.tga",
     138                 imgData->GetPointer(0),
     139                 g_renderer->getWindowWidth(),
     140                 g_renderer->getWindowHeight(),
     141                 TARGA_BYTES_PER_PIXEL);
     142#else
     143    writeTGAFile("/tmp/frame.tga",
     144                 imgData->GetPointer(0),
     145                 g_renderer->getWindowWidth(),
     146                 g_renderer->getWindowHeight(),
     147                 TARGA_BYTES_PER_PIXEL,
     148                 true);
     149#endif  /*RENDER_TARGA*/
     150
     151#else
     152    if (g_renderer->getCameraMode() == Renderer::IMAGE) {
     153        double xywh[4];
     154        g_renderer->getCameraZoomRegion(xywh);
     155        std::ostringstream oss;
     156        oss.precision(12);
     157        // Send upper left and lower right corners as bbox
     158        oss << "nv>image -type image -bbox {"
     159            << std::scientific
     160            << xywh[0] << " "
     161            << xywh[1] << " "
     162            << xywh[2] << " "
     163            << xywh[3] << "} -bytes";
    82164
    83165#ifdef RENDER_TARGA
     
    92174                 g_renderer->getWindowWidth(),
    93175                 g_renderer->getWindowHeight());
    94 #endif
     176#endif  /*RENDER_TARGA*/
    95177    } else {
    96178#ifdef RENDER_TARGA
     
    105187                 g_renderer->getWindowWidth(),
    106188                 g_renderer->getWindowHeight());
    107 #endif
    108     }
    109 #endif
    110 }
     189#endif  /*RENDER_TARGA*/
     190    }
     191#endif  /*DEBUG*/
     192}
     193#endif /*USE_THREADS*/
    111194
    112195static void
     
    153236}
    154237
     238#ifdef USE_THREADS
     239static void *
     240readerThread(void *clientData)
     241{
     242    ResponseQueue *queue = (ResponseQueue *)clientData;
     243    Tcl_Interp *interp;
     244
     245    TRACE("starting reader thread");
     246    interp = (Tcl_Interp *)queue->clientData();
     247    vtkSmartPointer<vtkUnsignedCharArray> imgData =
     248        vtkSmartPointer<vtkUnsignedCharArray>::New();
     249    for (;;) {
     250        int ret;
     251
     252        ret = processCommands(interp, g_fIn, g_fOut);
     253        if (ret < 0)
     254            break;
     255        if (g_renderer->render()) {
     256            TRACE("Rendering new frame");
     257            g_renderer->getRenderedFrame(imgData);
     258            queueFrame(queue, imgData);
     259        } else {
     260            TRACE("No render required");
     261        }
     262        if (feof(g_fIn))
     263            break;
     264    }   
     265    return NULL;
     266}
     267
     268static void *
     269writerThread(void *clientData)
     270{
     271    ResponseQueue *queue = (ResponseQueue *)clientData;
     272
     273    TRACE("starting writer thread");
     274    for (;;) {
     275        Response *response;
     276
     277        response = queue->dequeue();
     278        if (fwrite(response->message(), sizeof(char), response->length(),
     279                   g_fOut) != response->length()) {
     280            ERROR("short write while trying to write %ld bytes",
     281                  response->length());
     282        }
     283        fflush(g_fOut);
     284        delete response;
     285        if (feof(g_fOut))
     286            break;
     287    }   
     288    return NULL;
     289}
     290
     291#endif  /*USE_THREADS*/
     292
    155293int
    156294main(int argc, char *argv[])
     
    159297    signal(SIGPIPE, SIG_IGN);
    160298    initService();
    161     InitLog();
     299    initLog();
    162300
    163301    TRACE("Starting VTKVis Server");
     
    176314
    177315    g_renderer = new Renderer();
     316
     317    Tcl_Interp *interp = Tcl_CreateInterp();
     318
     319#ifdef USE_THREADS
     320    ResponseQueue queue((void *)interp);
     321    initTcl(interp, (ClientData)&queue);
     322
     323    pthread_t readerThreadId, writerThreadId;
     324    if (pthread_create(&readerThreadId, NULL, &readerThread, &queue) < 0) {
     325        ERROR("can't create reader thread: %s", strerror(errno));
     326    }
     327    if (pthread_create(&writerThreadId, NULL, &writerThread, &queue) < 0) {
     328        ERROR("can't create writer thread: %s", strerror(errno));
     329    }
     330    if (pthread_join(readerThreadId, NULL) < 0) {
     331        ERROR("can't join reader thread: %s", strerror(errno));
     332    }
     333    if (pthread_join(writerThreadId, NULL) < 0) {
     334        ERROR("can't join writer thread: %s", strerror(errno));
     335    }
     336#else
     337    initTcl(interp, (ClientData)NULL);
     338    int ret = 0;
     339
    178340    vtkSmartPointer<vtkUnsignedCharArray> imgData =
    179341        vtkSmartPointer<vtkUnsignedCharArray>::New();
    180 
    181     Tcl_Interp *interp = initTcl();
    182 
    183     int ret = 0;
    184 
    185342    while (1) {
    186343        ret = processCommands(interp, g_fIn, g_fOut);
     
    199356            break;
    200357    }
    201 
     358#endif
     359    INFO("exiting vtkvis");
    202360    exitTcl(interp);
    203361    interp = NULL;
     
    208366    TRACE("Exiting VTKVis Server");
    209367
    210     CloseLog();
     368    closeLog();
    211369    exitService();
    212370
    213     return ret;
    214 }
    215 
     371    return 0;
     372}
     373
  • branches/blt4/packages/vizservers/vtkvis/RpVtkRenderer.cpp

    r2409 r2542  
    2424#include <vtkCharArray.h>
    2525#include <vtkAxisActor2D.h>
     26#include <vtkCubeAxesActor.h>
    2627#ifdef USE_CUSTOM_AXES
    27 #include <vtkRpCubeAxesActor2D.h>
     28#include "vtkRpCubeAxesActor2D.h"
    2829#else
    29 #include <vtkCubeAxesActor.h>
    3030#include <vtkCubeAxesActor2D.h>
    3131#endif
     
    5353Renderer::Renderer() :
    5454    _needsRedraw(true),
    55     _windowWidth(320),
    56     _windowHeight(320),
     55    _windowWidth(500),
     56    _windowHeight(500),
     57    _imgCameraPlane(PLANE_XY),
     58    _imgCameraOffset(0),
    5759    _cameraZoomRatio(1),
    5860    _useCumulativeRange(true),
     
    6971    _cameraOrientation[2] = 0.0;
    7072    _cameraOrientation[3] = 0.0;
    71     _cumulativeDataRange[0] = 0.0;
    72     _cumulativeDataRange[1] = 1.0;
     73    _cumulativeScalarRange[0] = 0.0;
     74    _cumulativeScalarRange[1] = 1.0;
     75    _cumulativeVectorMagnitudeRange[0] = 0.0;
     76    _cumulativeVectorMagnitudeRange[1] = 1.0;
     77    for (int i = 0; i < 3; i++) {
     78        _cumulativeVectorComponentRange[i][0] = 0.0;
     79        _cumulativeVectorComponentRange[i][1] = 1.0;
     80    }
    7381    // clipping planes to prevent overdrawing axes
    7482    _activeClipPlanes = vtkSmartPointer<vtkPlaneCollection>::New();
     
    130138    initCamera();
    131139    addColorMap("default", ColorMap::getDefault());
     140    addColorMap("grayDefault", ColorMap::getGrayDefault());
    132141    addColorMap("volumeDefault", ColorMap::getVolumeDefault());
    133142    addColorMap("elementDefault", ColorMap::getElementDefault());
     
    263272    } while (doAll && itr != _contour2Ds.end());
    264273
     274    initCamera();
    265275    _needsRedraw = true;
    266276}
     
    299309    } while (doAll && itr != _contour3Ds.end());
    300310
     311    initCamera();
    301312    _needsRedraw = true;
    302313}
     
    335346    } while (doAll && itr != _glyphs.end());
    336347
     348    initCamera();
    337349    _needsRedraw = true;
    338350}
     
    371383    } while (doAll && itr != _heightMaps.end());
    372384
     385    initCamera();
    373386    _needsRedraw = true;
    374387}
     
    407420    } while (doAll && itr != _lics.end());
    408421
     422    initCamera();
    409423    _needsRedraw = true;
    410424}
     
    443457    } while (doAll && itr != _molecules.end());
    444458
     459    initCamera();
    445460    _needsRedraw = true;
    446461}
     
    479494    } while (doAll && itr != _polyDatas.end());
    480495
     496    initCamera();
    481497    _needsRedraw = true;
    482498}
     
    515531    } while (doAll && itr != _pseudoColors.end());
    516532
     533    initCamera();
    517534    _needsRedraw = true;
    518535}
     
    551568    } while (doAll && itr != _streamlines.end());
    552569
     570    initCamera();
    553571    _needsRedraw = true;
    554572}
     
    587605    } while (doAll && itr != _volumes.end());
    588606
     607    initCamera();
    589608    _needsRedraw = true;
    590609}
     
    627646        deleteVolume(itr->second->getName());
    628647 
     648        if (itr->second->getProp() != NULL) {
     649            _renderer->RemoveViewProp(itr->second->getProp());
     650        }
     651
    629652        TRACE("After deleting graphics objects");
    630653
     
    634657
    635658    // Update cumulative data range
    636     collectDataRanges(_cumulativeDataRange, _cumulativeRangeOnlyVisible);
    637     updateRanges(_useCumulativeRange);
    638 
    639     _needsRedraw = true;
     659    updateRanges();
     660
     661    initCamera();
     662    _needsRedraw = true;
     663}
     664
     665void Renderer::getDataSetNames(std::vector<std::string>& names)
     666{
     667    names.clear();
     668    for (DataSetHashmap::iterator itr = _dataSets.begin();
     669         itr != _dataSets.end(); ++itr) {
     670        names.push_back(itr->second->getName());
     671    }
    640672}
    641673
     
    649681    DataSetHashmap::iterator itr = _dataSets.find(id);
    650682    if (itr == _dataSets.end()) {
     683#ifdef DEBUG
    651684        TRACE("DataSet not found: %s", id.c_str());
     685#endif
    652686        return NULL;
    653687    } else
     
    663697    if (ds) {
    664698        bool ret = ds->setDataFile(filename);
    665         collectDataRanges(_cumulativeDataRange, _cumulativeRangeOnlyVisible);
    666         updateRanges(_useCumulativeRange);
     699        updateRanges();
    667700        _needsRedraw = true;
    668701        return ret;
     
    679712    if (ds) {
    680713        bool ret = ds->setData(data, nbytes);
    681         collectDataRanges(_cumulativeDataRange, _cumulativeRangeOnlyVisible);
    682         updateRanges(_useCumulativeRange);
     714        updateRanges();
    683715        _needsRedraw = true;
    684716        return ret;
     
    712744
    713745    if (ret) {
    714         collectDataRanges(_cumulativeDataRange, _cumulativeRangeOnlyVisible);
    715         updateRanges(_useCumulativeRange);
     746         updateRanges();
    716747        _needsRedraw = true;
    717748    }
     
    745776
    746777    if (ret) {
    747         collectDataRanges(_cumulativeDataRange, _cumulativeRangeOnlyVisible);
    748         updateRanges(_useCumulativeRange);
     778        updateRanges();
    749779        _needsRedraw = true;
    750780    }
     
    762792        _useCumulativeRange = state;
    763793        _cumulativeRangeOnlyVisible = onlyVisible;
    764         collectDataRanges(_cumulativeDataRange, _cumulativeRangeOnlyVisible);
    765         updateRanges(_useCumulativeRange);
     794        updateRanges();
    766795        _needsRedraw = true;
    767796    }
    768797}
    769798
    770 void Renderer::resetAxes()
     799void Renderer::resetAxes(double bounds[6])
    771800{
    772801    TRACE("Resetting axes");
     
    793822            _renderer->AddViewProp(_cubeAxesActor);
    794823        }
    795         double bounds[6];
    796         collectBounds(bounds, false);
    797         _cubeAxesActor->SetBounds(bounds);
     824        if (bounds == NULL) {
     825            double newBounds[6];
     826            collectBounds(newBounds, false);
     827            _cubeAxesActor->SetBounds(newBounds);
     828            TRACE("Bounds (computed): %g %g %g %g %g %g",
     829                  newBounds[0],
     830                  newBounds[1],
     831                  newBounds[2],
     832                  newBounds[3],
     833                  newBounds[4],
     834                  newBounds[5]);
     835        } else {
     836            _cubeAxesActor->SetBounds(bounds);
     837            TRACE("Bounds (supplied): %g %g %g %g %g %g",
     838                  bounds[0],
     839                  bounds[1],
     840                  bounds[2],
     841                  bounds[3],
     842                  bounds[4],
     843                  bounds[5]);
     844        }
    798845    }
    799846}
     
    832879    _cubeAxesActor2D->GetXAxisActor2D()->AdjustLabelsOn();
    833880    _cubeAxesActor2D->GetYAxisActor2D()->AdjustLabelsOn();
     881    _cubeAxesActor2D->GetZAxisActor2D()->AdjustLabelsOn();
    834882
    835883#ifdef USE_CUSTOM_AXES
     
    851899    _cubeAxesActor2D->GetYAxisActor2D()->GetLabelTextProperty()->ItalicOff();
    852900    _cubeAxesActor2D->GetYAxisActor2D()->GetLabelTextProperty()->ShadowOff();
     901
     902    //_cubeAxesActor2D->GetZAxisActor2D()->SizeFontRelativeToAxisOn();
     903    _cubeAxesActor2D->GetZAxisActor2D()->GetTitleTextProperty()->BoldOn();
     904    _cubeAxesActor2D->GetZAxisActor2D()->GetTitleTextProperty()->ItalicOff();
     905    _cubeAxesActor2D->GetZAxisActor2D()->GetTitleTextProperty()->ShadowOn();
     906    _cubeAxesActor2D->GetZAxisActor2D()->GetLabelTextProperty()->BoldOff();
     907    _cubeAxesActor2D->GetZAxisActor2D()->GetLabelTextProperty()->ItalicOff();
     908    _cubeAxesActor2D->GetZAxisActor2D()->GetLabelTextProperty()->ShadowOff();
    853909#else
    854910    _cubeAxesActor2D->GetAxisTitleTextProperty()->BoldOn();
     
    913969        _cubeAxesActor2D->GetYAxisActor2D()->GetTitleTextProperty()->SetColor(color);
    914970        _cubeAxesActor2D->GetYAxisActor2D()->GetLabelTextProperty()->SetColor(color);
     971        _cubeAxesActor2D->GetZAxisActor2D()->GetTitleTextProperty()->SetColor(color);
     972        _cubeAxesActor2D->GetZAxisActor2D()->GetLabelTextProperty()->SetColor(color);
    915973#else
    916974        _cubeAxesActor2D->GetAxisTitleTextProperty()->SetColor(color);
     
    922980
    923981/**
    924  * \brief Turn on/off rendering of all axes
     982 * \brief Turn on/off rendering of all enabled axes
    925983 */
    926984void Renderer::setAxesVisibility(bool state)
     
    934992        _needsRedraw = true;
    935993    }
    936     setAxisVisibility(X_AXIS, state);
    937     setAxisVisibility(Y_AXIS, state);
    938     setAxisVisibility(Z_AXIS, state);
    939994}
    940995
     
    10121067        } else if (axis == Y_AXIS) {
    10131068            _cubeAxesActor2D->SetYAxisVisibility((state ? 1 : 0));
     1069        } else if (axis == Z_AXIS) {
     1070            _cubeAxesActor2D->SetZAxisVisibility((state ? 1 : 0));
    10141071        }
    10151072        _needsRedraw = true;
     
    10541111        } else if (axis == Y_AXIS) {
    10551112            _cubeAxesActor2D->GetYAxisActor2D()->SetLabelVisibility((state ? 1 : 0));
     1113        } else if (axis == Z_AXIS) {
     1114            _cubeAxesActor2D->GetZAxisActor2D()->SetLabelVisibility((state ? 1 : 0));
    10561115        }
    10571116        _needsRedraw = true;
     
    10791138        } else if (axis == Y_AXIS) {
    10801139            _cubeAxesActor2D->GetYAxisActor2D()->SetTickVisibility((state ? 1 : 0));
     1140        } else if (axis == Z_AXIS) {
     1141            _cubeAxesActor2D->GetZAxisActor2D()->SetTickVisibility((state ? 1 : 0));
    10811142        }
    10821143        _needsRedraw = true;
     
    11041165        } else if (axis == Y_AXIS) {
    11051166            _cubeAxesActor2D->SetYLabel(title);
     1167        } else if (axis == Z_AXIS) {
     1168            _cubeAxesActor2D->SetZLabel(title);
    11061169        }
    11071170        _needsRedraw = true;
     
    11301193        } else if (axis == Y_AXIS) {
    11311194            _cubeAxesActor2D->SetYUnits(units);
     1195        } else if (axis == Z_AXIS) {
     1196            _cubeAxesActor2D->SetZUnits(units);
    11321197        }
    11331198        _needsRedraw = true;
     
    11371202
    11381203/**
    1139  * \brief Add a color map for use in the Renderer
     1204 * \brief Notify graphics objects that color map has changed
     1205 */
     1206void Renderer::updateColorMap(ColorMap *cmap)
     1207{
     1208    for (Contour3DHashmap::iterator itr = _contour3Ds.begin();
     1209         itr != _contour3Ds.end(); ++itr) {
     1210        if (itr->second->getColorMap() == cmap) {
     1211            itr->second->updateColorMap();
     1212            _needsRedraw = true;
     1213        }
     1214    }
     1215    for (GlyphsHashmap::iterator itr = _glyphs.begin();
     1216         itr != _glyphs.end(); ++itr) {
     1217        if (itr->second->getColorMap() == cmap) {
     1218            itr->second->updateColorMap();
     1219            _needsRedraw = true;
     1220        }
     1221    }
     1222    for (HeightMapHashmap::iterator itr = _heightMaps.begin();
     1223         itr != _heightMaps.end(); ++itr) {
     1224        if (itr->second->getColorMap() == cmap) {
     1225            itr->second->updateColorMap();
     1226            _needsRedraw = true;
     1227        }
     1228    }
     1229    for (LICHashmap::iterator itr = _lics.begin();
     1230         itr != _lics.end(); ++itr) {
     1231        if (itr->second->getColorMap() == cmap) {
     1232            itr->second->updateColorMap();
     1233            _needsRedraw = true;
     1234        }
     1235    }
     1236    for (MoleculeHashmap::iterator itr = _molecules.begin();
     1237         itr != _molecules.end(); ++itr) {
     1238        if (itr->second->getColorMap() == cmap) {
     1239            itr->second->updateColorMap();
     1240            _needsRedraw = true;
     1241        }
     1242    }
     1243    for (PseudoColorHashmap::iterator itr = _pseudoColors.begin();
     1244         itr != _pseudoColors.end(); ++itr) {
     1245        if (itr->second->getColorMap() == cmap) {
     1246            itr->second->updateColorMap();
     1247            _needsRedraw = true;
     1248        }
     1249    }
     1250    for (StreamlinesHashmap::iterator itr = _streamlines.begin();
     1251         itr != _streamlines.end(); ++itr) {
     1252        if (itr->second->getColorMap() == cmap) {
     1253            itr->second->updateColorMap();
     1254            _needsRedraw = true;
     1255        }
     1256    }
     1257    for (VolumeHashmap::iterator itr = _volumes.begin();
     1258         itr != _volumes.end(); ++itr) {
     1259        if (itr->second->getColorMap() == cmap) {
     1260            itr->second->updateColorMap();
     1261            _needsRedraw = true;
     1262        }
     1263    }
     1264}
     1265
     1266/**
     1267 * \brief Check if a ColorMap is in use by graphics objects
     1268 */
     1269bool Renderer::colorMapUsed(ColorMap *cmap)
     1270{
     1271    for (Contour3DHashmap::iterator itr = _contour3Ds.begin();
     1272         itr != _contour3Ds.end(); ++itr) {
     1273        if (itr->second->getColorMap() == cmap)
     1274            return true;
     1275    }
     1276    for (GlyphsHashmap::iterator itr = _glyphs.begin();
     1277         itr != _glyphs.end(); ++itr) {
     1278        if (itr->second->getColorMap() == cmap)
     1279            return true;
     1280    }
     1281    for (HeightMapHashmap::iterator itr = _heightMaps.begin();
     1282         itr != _heightMaps.end(); ++itr) {
     1283        if (itr->second->getColorMap() == cmap)
     1284            return true;
     1285    }
     1286    for (LICHashmap::iterator itr = _lics.begin();
     1287         itr != _lics.end(); ++itr) {
     1288        if (itr->second->getColorMap() == cmap)
     1289            return true;
     1290    }
     1291    for (MoleculeHashmap::iterator itr = _molecules.begin();
     1292         itr != _molecules.end(); ++itr) {
     1293        if (itr->second->getColorMap() == cmap)
     1294            return true;
     1295    }
     1296    for (PseudoColorHashmap::iterator itr = _pseudoColors.begin();
     1297         itr != _pseudoColors.end(); ++itr) {
     1298        if (itr->second->getColorMap() == cmap)
     1299            return true;
     1300    }
     1301    for (StreamlinesHashmap::iterator itr = _streamlines.begin();
     1302         itr != _streamlines.end(); ++itr) {
     1303        if (itr->second->getColorMap() == cmap)
     1304            return true;
     1305    }
     1306    for (VolumeHashmap::iterator itr = _volumes.begin();
     1307         itr != _volumes.end(); ++itr) {
     1308        if (itr->second->getColorMap() == cmap)
     1309            return true;
     1310    }
     1311    return false;
     1312}
     1313
     1314/**
     1315 * \brief Add/replace a ColorMap for use in the Renderer
    11401316 */
    11411317void Renderer::addColorMap(const ColorMapId& id, ColorMap *colorMap)
     
    11441320        colorMap->build();
    11451321        if (getColorMap(id) != NULL) {
    1146             WARN("Replacing existing ColorMap %s", id.c_str());
    1147             deleteColorMap(id);
    1148         }
    1149         _colorMaps[id] = colorMap;
     1322            TRACE("Replacing existing ColorMap %s", id.c_str());
     1323            // Copy to current colormap to avoid invalidating
     1324            // pointers in graphics objects using the color map
     1325            *_colorMaps[id] = *colorMap;
     1326            delete colorMap;
     1327            // Notify graphics objects of change
     1328            updateColorMap(_colorMaps[id]);
     1329        } else
     1330            _colorMaps[id] = colorMap;
    11501331    } else {
    11511332        ERROR("NULL ColorMap");
     
    11911372
    11921373    do {
     1374        if (itr->second->getName().compare("default") == 0 ||
     1375            itr->second->getName().compare("grayDefault") == 0 ||
     1376            itr->second->getName().compare("volumeDefault") == 0 ||
     1377            itr->second->getName().compare("elementDefault") == 0) {
     1378            if (id.compare("all") != 0) {
     1379                WARN("Cannot delete a default color map");
     1380            }
     1381            continue;
     1382        } else if (colorMapUsed(itr->second)) {
     1383            WARN("Cannot delete color map '%s', it is in use", itr->second->getName().c_str());
     1384            continue;
     1385        }
     1386
    11931387        TRACE("Deleting ColorMap %s", itr->second->getName().c_str());
    11941388
    1195         // TODO: Check if color map is used in PseudoColors?
    11961389        delete itr->second;
    11971390        itr = _colorMaps.erase(itr);
     
    12021395 * \brief Render a labelled legend image for the given colormap
    12031396 *
     1397 * \param[in] id ColorMap name
     1398 * \param[in] dataSetID DataSet name
     1399 * \param[in] legendType scalar or vector field legend
     1400 * \param[in,out] title If supplied, draw title ("#auto" means to
     1401 * fill in field name and draw).  If blank, do not draw title. 
     1402 * If title was blank or "#auto", will be filled with field name on
     1403 * return
     1404 * \param[out] range Filled with min and max values
     1405 * \param[in] width Pixel width of legend (aspect controls orientation)
     1406 * \param[in] height Pixel height of legend (aspect controls orientation)
     1407 * \param[in] numLabels Number of labels to render (includes min/max)
     1408 * \param[in,out] imgData Pointer to array to fill with image bytes. Array
     1409 * will be resized if needed.
    12041410 * \return The image is rendered into the supplied array, false is
    12051411 * returned if the color map is not found
     
    12071413bool Renderer::renderColorMap(const ColorMapId& id,
    12081414                              const DataSetId& dataSetID,
    1209                               const char *title,
     1415                              Renderer::LegendType legendType,
     1416                              std::string& title,
     1417                              double range[2],
    12101418                              int width, int height,
     1419                              int numLabels,
    12111420                              vtkUnsignedCharArray *imgData)
    12121421{
     1422    TRACE("Enter");
    12131423    ColorMap *colorMap = getColorMap(id);
    12141424    if (colorMap == NULL)
     
    12201430        _legendRenderWindow->DoubleBufferOff();
    12211431        _legendRenderWindow->OffScreenRenderingOn();
     1432#else
     1433        _legendRenderWindow->DoubleBufferOn();
     1434        _legendRenderWindow->SwapBuffersOff();
    12221435#endif
    12231436    }
     
    12371450    }
    12381451
     1452    if (width > height) {
     1453        _scalarBarActor->SetOrientationToHorizontal();
     1454    } else {
     1455        _scalarBarActor->SetOrientationToVertical();
     1456    }
     1457
     1458    // Set viewport-relative width/height/pos
     1459    if (title.empty() && numLabels == 0) {
     1460        _scalarBarActor->SetPosition(0, 0);
     1461        if (width > height) {
     1462            // horizontal
     1463            _scalarBarActor->SetHeight(2.5); // VTK: floor(actorHeight * .4)
     1464            _scalarBarActor->SetWidth(1);
     1465        } else {
     1466            // vertical
     1467            _scalarBarActor->SetHeight((double)height/(.86*height)); // VTK: floor(actorHeight * .86)
     1468            _scalarBarActor->SetWidth(((double)(width+5))/((double)width)); // VTK: actorWidth - 4 pixels
     1469        }
     1470    } else {
     1471        if (width > height) {
     1472            // horizontal
     1473            _scalarBarActor->SetPosition(.075, .1);
     1474            _scalarBarActor->SetHeight(0.8);
     1475            _scalarBarActor->SetWidth(0.85);
     1476        } else {
     1477            // vertical
     1478            _scalarBarActor->SetPosition(.1, .05);
     1479            _scalarBarActor->SetHeight(0.9);
     1480            _scalarBarActor->SetWidth(0.8);
     1481        }
     1482    }
     1483
    12391484    vtkSmartPointer<vtkLookupTable> lut = colorMap->getLookupTable();
     1485    DataSet *dataSet = NULL;
     1486    bool cumulative = _useCumulativeRange;
    12401487    if (dataSetID.compare("all") == 0) {
    1241         lut->SetRange(_cumulativeDataRange);
    1242     } else {
    1243         DataSet *dataSet = getDataSet(dataSetID);
     1488        if (_dataSets.empty()) {
     1489            WARN("No DataSets exist, can't fill title or range");
     1490        } else {
     1491            dataSet = _dataSets.begin()->second;
     1492        }
     1493        cumulative = true;
     1494    } else {
     1495        dataSet = getDataSet(dataSetID);
    12441496        if (dataSet == NULL) {
    1245             lut->SetRange(_cumulativeDataRange);
    1246         } else {
    1247             double range[2];
    1248             dataSet->getDataRange(range);
     1497            ERROR("DataSet '%s' not found", dataSetID.c_str());
     1498            return false;
     1499        }
     1500    }
     1501
     1502    bool drawTitle = false;
     1503    if (!title.empty()) {
     1504        drawTitle = true;
     1505        if (title.compare("#auto") == 0) {
     1506            title.clear();
     1507        }
     1508    }
     1509
     1510    range[0] = 0.0;
     1511    range[1] = 1.0;
     1512
     1513    switch (legendType) {
     1514    case ACTIVE_VECTOR_MAGNITUDE:
     1515        if (cumulative) {
     1516            lut->SetRange(_cumulativeVectorMagnitudeRange);
     1517            range[0] = _cumulativeVectorMagnitudeRange[0];
     1518            range[1] = _cumulativeVectorMagnitudeRange[1];
     1519        } else if (dataSet != NULL) {
     1520            dataSet->getVectorRange(range);
    12491521            lut->SetRange(range);
    12501522        }
    1251     }
     1523        if (title.empty() && dataSet != NULL) {
     1524            const char *name = dataSet->getActiveVectorsName();
     1525            if (name != NULL) {
     1526                title = name;
     1527                title.append("(mag)");
     1528            }
     1529        }
     1530        break;
     1531    case ACTIVE_VECTOR_X:
     1532        if (cumulative) {
     1533            lut->SetRange(_cumulativeVectorComponentRange[0]);
     1534            range[0] = _cumulativeVectorComponentRange[0][0];
     1535            range[1] = _cumulativeVectorComponentRange[0][1];
     1536        } else if (dataSet != NULL) {
     1537            dataSet->getVectorRange(range, 0);
     1538            lut->SetRange(range);
     1539        }
     1540        if (title.empty() && dataSet != NULL) {
     1541            const char *name = dataSet->getActiveVectorsName();
     1542            if (name != NULL) {
     1543                title = name;
     1544                title.append("(x)");
     1545            }
     1546        }
     1547        break;
     1548    case ACTIVE_VECTOR_Y:
     1549        if (cumulative) {
     1550            lut->SetRange(_cumulativeVectorComponentRange[1]);
     1551            range[0] = _cumulativeVectorComponentRange[1][0];
     1552            range[1] = _cumulativeVectorComponentRange[1][1];
     1553        } else if (dataSet != NULL) {
     1554            dataSet->getVectorRange(range, 1);
     1555            lut->SetRange(range);
     1556        }
     1557        if (title.empty() && dataSet != NULL) {
     1558            const char *name = dataSet->getActiveVectorsName();
     1559            if (name != NULL) {
     1560                title = name;
     1561                title.append("(y)");
     1562            }
     1563        }
     1564        break;
     1565    case ACTIVE_VECTOR_Z:
     1566        if (cumulative) {
     1567            lut->SetRange(_cumulativeVectorComponentRange[2]);
     1568            range[0] = _cumulativeVectorComponentRange[2][0];
     1569            range[1] = _cumulativeVectorComponentRange[2][1];
     1570        } else if (dataSet != NULL) {
     1571            dataSet->getVectorRange(range, 1);
     1572            lut->SetRange(range);
     1573        }
     1574        if (title.empty() && dataSet != NULL) {
     1575            const char *name = dataSet->getActiveVectorsName();
     1576            if (name != NULL) {
     1577                title = name;
     1578                title.append("(z)");
     1579            }
     1580        }
     1581        break;
     1582    case ACTIVE_SCALAR:
     1583    default:
     1584        if (cumulative) {
     1585            lut->SetRange(_cumulativeScalarRange);
     1586            range[0] = _cumulativeScalarRange[0];
     1587            range[1] = _cumulativeScalarRange[1];
     1588        } else if (dataSet != NULL) {
     1589            dataSet->getScalarRange(range);
     1590            lut->SetRange(range);
     1591        }
     1592        if (title.empty() && dataSet != NULL) {
     1593            const char *name = dataSet->getActiveScalarsName();
     1594            if (name != NULL)
     1595                title = name;
     1596        }
     1597        break;
     1598    }
     1599
    12521600    _scalarBarActor->SetLookupTable(lut);
    12531601
    1254     // Set viewport-relative width/height/pos
    1255     if (width > height) {
    1256         _scalarBarActor->SetOrientationToHorizontal();
    1257         _scalarBarActor->SetHeight(0.8);
    1258         _scalarBarActor->SetWidth(0.85);
    1259         _scalarBarActor->SetPosition(.075, .1);
    1260     } else {
    1261         _scalarBarActor->SetOrientationToVertical();
    1262         _scalarBarActor->SetHeight(0.9);
    1263         _scalarBarActor->SetWidth(0.8);
    1264         _scalarBarActor->SetPosition(.1, .05);
    1265     }
    1266     _scalarBarActor->SetTitle(title);
     1602    if (drawTitle) {
     1603        _scalarBarActor->SetTitle(title.c_str());
     1604    } else {
     1605        _scalarBarActor->SetTitle("");
     1606    }
    12671607    _scalarBarActor->GetTitleTextProperty()->ItalicOff();
     1608    _scalarBarActor->SetNumberOfLabels(numLabels);
    12681609    _scalarBarActor->GetLabelTextProperty()->BoldOff();
    12691610    _scalarBarActor->GetLabelTextProperty()->ItalicOff();
     
    13041645                                      imgData);
    13051646#endif
     1647    TRACE("Leave");
    13061648    return true;
    13071649}
     
    13101652 * \brief Create a new Contour2D and associate it with the named DataSet
    13111653 */
    1312 void Renderer::addContour2D(const DataSetId& id)
     1654bool Renderer::addContour2D(const DataSetId& id, int numContours)
    13131655{
    13141656    DataSetHashmap::iterator itr;
     
    13231665    if (itr == _dataSets.end()) {
    13241666        ERROR("Unknown dataset %s", id.c_str());
    1325         return;
     1667        return false;
    13261668    }
    13271669
     
    13351677        }
    13361678
    1337         Contour2D *contour = new Contour2D();
     1679        Contour2D *contour = new Contour2D(numContours);
     1680 
     1681        contour->setDataSet(ds,
     1682                            _useCumulativeRange,
     1683                            _cumulativeScalarRange,
     1684                            _cumulativeVectorMagnitudeRange,
     1685                            _cumulativeVectorComponentRange);
     1686
     1687        if (contour->getProp() == NULL) {
     1688            delete contour;
     1689            return false;
     1690        } else {
     1691            _renderer->AddViewProp(contour->getProp());
     1692        }
     1693
    13381694        _contour2Ds[dsID] = contour;
    1339 
    1340         contour->setDataSet(ds);
    1341 
    1342         _renderer->AddViewProp(contour->getProp());
    13431695    } while (doAll && ++itr != _dataSets.end());
    13441696
    13451697    initCamera();
    13461698    _needsRedraw = true;
     1699    return true;
     1700}
     1701
     1702/**
     1703 * \brief Create a new Contour2D and associate it with the named DataSet
     1704 */
     1705bool Renderer::addContour2D(const DataSetId& id, const std::vector<double>& contours)
     1706{
     1707    DataSetHashmap::iterator itr;
     1708
     1709    bool doAll = false;
     1710
     1711    if (id.compare("all") == 0) {
     1712        itr = _dataSets.begin();
     1713    } else {
     1714        itr = _dataSets.find(id);
     1715    }
     1716    if (itr == _dataSets.end()) {
     1717        ERROR("Unknown dataset %s", id.c_str());
     1718        return false;
     1719    }
     1720
     1721    do {
     1722        DataSet *ds = itr->second;
     1723        const DataSetId& dsID = ds->getName();
     1724
     1725        if (getContour2D(dsID)) {
     1726            WARN("Replacing existing Contour2D %s", dsID.c_str());
     1727            deleteContour2D(dsID);
     1728        }
     1729
     1730        Contour2D *contour = new Contour2D(contours);
     1731
     1732        contour->setDataSet(ds,
     1733                            _useCumulativeRange,
     1734                            _cumulativeScalarRange,
     1735                            _cumulativeVectorMagnitudeRange,
     1736                            _cumulativeVectorComponentRange);
     1737
     1738        if (contour->getProp() == NULL) {
     1739            delete contour;
     1740            return false;
     1741        } else {
     1742            _renderer->AddViewProp(contour->getProp());
     1743        }
     1744
     1745        _contour2Ds[dsID] = contour;
     1746    } while (doAll && ++itr != _dataSets.end());
     1747
     1748    initCamera();
     1749    _needsRedraw = true;
     1750    return true;
    13471751}
    13481752
     
    13551759
    13561760    if (itr == _contour2Ds.end()) {
     1761#ifdef DEBUG
    13571762        TRACE("Contour2D not found: %s", id.c_str());
     1763#endif
    13581764        return NULL;
    13591765    } else
     
    15221928
    15231929    do {
    1524         if (_useCumulativeRange) {
    1525             itr->second->setContours(numContours, _cumulativeDataRange);
    1526         } else {
    1527             itr->second->setContours(numContours);
    1528         }
     1930        itr->second->setContours(numContours);
    15291931    } while (doAll && ++itr != _contour2Ds.end());
    15301932
     
    16162018 * \brief Set the RGB isoline color for the specified DataSet
    16172019 */
    1618 void Renderer::setContour2DEdgeColor(const DataSetId& id, float color[3])
     2020void Renderer::setContour2DColor(const DataSetId& id, float color[3])
    16192021{
    16202022    Contour2DHashmap::iterator itr;
     
    16342036
    16352037    do {
    1636         itr->second->setEdgeColor(color);
     2038        itr->second->setColor(color);
    16372039    } while (doAll && ++itr != _contour2Ds.end());
    16382040
     
    16992101 * \brief Create a new Contour3D and associate it with the named DataSet
    17002102 */
    1701 void Renderer::addContour3D(const DataSetId& id)
     2103bool Renderer::addContour3D(const DataSetId& id, int numContours)
    17022104{
    17032105    DataSetHashmap::iterator itr;
     
    17122114    if (itr == _dataSets.end()) {
    17132115        ERROR("Unknown dataset %s", id.c_str());
    1714         return;
     2116        return false;
    17152117    }
    17162118
     
    17242126        }
    17252127
    1726         Contour3D *contour = new Contour3D();
     2128        Contour3D *contour = new Contour3D(numContours);
     2129
     2130        contour->setDataSet(ds,
     2131                            _useCumulativeRange,
     2132                            _cumulativeScalarRange,
     2133                            _cumulativeVectorMagnitudeRange,
     2134                            _cumulativeVectorComponentRange);
     2135
     2136        if (contour->getProp() == NULL) {
     2137            delete contour;
     2138            return false;
     2139        } else {
     2140            _renderer->AddViewProp(contour->getProp());
     2141        }
     2142
    17272143        _contour3Ds[dsID] = contour;
    1728 
    1729         contour->setDataSet(ds);
    1730 
    1731         // Use the default color map
    1732         vtkSmartPointer<vtkLookupTable> lut = vtkSmartPointer<vtkLookupTable>::New();
    1733         ColorMap *cmap = getColorMap("default");
    1734         lut->DeepCopy(cmap->getLookupTable());
    1735         if (_useCumulativeRange) {
    1736             lut->SetRange(_cumulativeDataRange);
    1737         } else {
    1738             double range[2];
    1739             ds->getDataRange(range);
    1740             lut->SetRange(range);
    1741         }
    1742 
    1743         contour->setLookupTable(lut);
    1744 
    1745         _renderer->AddViewProp(contour->getProp());
    17462144    } while (doAll && ++itr != _dataSets.end());
    17472145
     
    17502148    initCamera();
    17512149    _needsRedraw = true;
     2150    return true;
     2151}
     2152
     2153/**
     2154 * \brief Create a new Contour3D and associate it with the named DataSet
     2155 */
     2156bool Renderer::addContour3D(const DataSetId& id,const std::vector<double>& contours)
     2157{
     2158    DataSetHashmap::iterator itr;
     2159
     2160    bool doAll = false;
     2161
     2162    if (id.compare("all") == 0) {
     2163        itr = _dataSets.begin();
     2164    } else {
     2165        itr = _dataSets.find(id);
     2166    }
     2167    if (itr == _dataSets.end()) {
     2168        ERROR("Unknown dataset %s", id.c_str());
     2169        return false;
     2170    }
     2171
     2172    do {
     2173        DataSet *ds = itr->second;
     2174        const DataSetId& dsID = ds->getName();
     2175
     2176        if (getContour3D(dsID)) {
     2177            WARN("Replacing existing Contour3D %s", dsID.c_str());
     2178            deleteContour3D(dsID);
     2179        }
     2180
     2181        Contour3D *contour = new Contour3D(contours);
     2182
     2183        contour->setDataSet(ds,
     2184                            _useCumulativeRange,
     2185                            _cumulativeScalarRange,
     2186                            _cumulativeVectorMagnitudeRange,
     2187                            _cumulativeVectorComponentRange);
     2188
     2189        if (contour->getProp() == NULL) {
     2190            delete contour;
     2191            return false;
     2192        } else {
     2193            _renderer->AddViewProp(contour->getProp());
     2194        }
     2195
     2196        _contour3Ds[dsID] = contour;
     2197    } while (doAll && ++itr != _dataSets.end());
     2198
     2199    if (_cameraMode == IMAGE)
     2200        setCameraMode(PERSPECTIVE);
     2201    initCamera();
     2202    _needsRedraw = true;
     2203    return true;
    17522204}
    17532205
     
    17602212
    17612213    if (itr == _contour3Ds.end()) {
     2214#ifdef DEBUG
    17622215        TRACE("Contour3D not found: %s", id.c_str());
     2216#endif
    17632217        return NULL;
    17642218    } else
     
    19272381
    19282382    do {
    1929         if (_useCumulativeRange) {
    1930             itr->second->setContours(numContours, _cumulativeDataRange);
    1931         } else {
    1932             itr->second->setContours(numContours);
    1933         }
    1934     } while (doAll && ++itr != _contour3Ds.end());
     2383        itr->second->setContours(numContours);
     2384     } while (doAll && ++itr != _contour3Ds.end());
    19352385
    19362386    initCamera();
     
    20522502              itr->second->getDataSet()->getName().c_str());
    20532503
    2054         // Make a copy of the generic colormap lookup table, so
    2055         // data range can be set in the copy table to match the
    2056         // dataset being plotted
    2057         vtkSmartPointer<vtkLookupTable> lut = vtkSmartPointer<vtkLookupTable>::New();
    2058         lut->DeepCopy(cmap->getLookupTable());
    2059 
    2060         if (_useCumulativeRange) {
    2061             lut->SetRange(_cumulativeDataRange);
    2062         } else {
    2063             if (itr->second->getDataSet() != NULL) {
    2064                 double range[2];
    2065                 itr->second->getDataSet()->getDataRange(range);
    2066                 lut->SetRange(range);
    2067             }
    2068         }
    2069 
    2070         itr->second->setLookupTable(lut);
     2504        itr->second->setColorMap(cmap);
    20712505    } while (doAll && ++itr != _contour3Ds.end());
    20722506
     
    22402674 * \brief Create a new Glyphs and associate it with the named DataSet
    22412675 */
    2242 void Renderer::addGlyphs(const DataSetId& id)
     2676bool Renderer::addGlyphs(const DataSetId& id, Glyphs::GlyphShape shape)
    22432677{
    22442678    DataSetHashmap::iterator itr;
     
    22532687    if (itr == _dataSets.end()) {
    22542688        ERROR("Unknown dataset %s", id.c_str());
    2255         return;
     2689        return false;
    22562690    }
    22572691
     
    22652699        }
    22662700
    2267         Glyphs *glyphs = new Glyphs();
     2701        Glyphs *glyphs = new Glyphs(shape);
     2702
     2703        glyphs->setDataSet(ds,
     2704                           _useCumulativeRange,
     2705                           _cumulativeScalarRange,
     2706                           _cumulativeVectorMagnitudeRange,
     2707                           _cumulativeVectorComponentRange);
     2708
     2709        if (glyphs->getProp() == NULL) {
     2710            delete glyphs;
     2711            return false;
     2712        } else {
     2713            _renderer->AddViewProp(glyphs->getProp());
     2714        }
     2715
    22682716        _glyphs[dsID] = glyphs;
    2269 
    2270         glyphs->setDataSet(ds);
    2271 
    2272         // Use the default color map
    2273         vtkSmartPointer<vtkLookupTable> lut = vtkSmartPointer<vtkLookupTable>::New();
    2274         ColorMap *cmap = getColorMap("default");
    2275         lut->DeepCopy(cmap->getLookupTable());
    2276         if (_useCumulativeRange) {
    2277             lut->SetRange(_cumulativeDataRange);
    2278         } else {
    2279             double range[2];
    2280             ds->getDataRange(range);
    2281             lut->SetRange(range);
    2282         }
    2283 
    2284         glyphs->setLookupTable(lut);
    2285 
    2286         _renderer->AddViewProp(glyphs->getProp());
    22872717    } while (doAll && ++itr != _dataSets.end());
    22882718
     
    22922722
    22932723    _needsRedraw = true;
     2724    return true;
    22942725}
    22952726
     
    23022733
    23032734    if (itr == _glyphs.end()) {
     2735#ifdef DEBUG
    23042736        TRACE("Glyphs not found: %s", id.c_str());
     2737#endif
    23052738        return NULL;
    23062739    } else
     
    25062939              itr->second->getDataSet()->getName().c_str());
    25072940
    2508         // Make a copy of the generic colormap lookup table, so
    2509         // data range can be set in the copy table to match the
    2510         // dataset being plotted
    2511         vtkSmartPointer<vtkLookupTable> lut = vtkSmartPointer<vtkLookupTable>::New();
    2512         lut->DeepCopy(cmap->getLookupTable());
    2513 
    2514         if (_useCumulativeRange) {
    2515             lut->SetRange(_cumulativeDataRange);
    2516         } else {
    2517             if (itr->second->getDataSet() != NULL) {
    2518                 double range[2];
    2519                 itr->second->getDataSet()->getDataRange(range);
    2520                 lut->SetRange(range);
    2521             }
    2522         }
    2523 
    2524         itr->second->setLookupTable(lut);
     2941        itr->second->setColorMap(cmap);
    25252942    } while (doAll && ++itr != _glyphs.end());
    25262943
     
    25772994    do {
    25782995        itr->second->setScalingMode(mode);
     2996    } while (doAll && ++itr != _glyphs.end());
     2997
     2998    _renderer->ResetCameraClippingRange();
     2999    _needsRedraw = true;
     3000}
     3001
     3002/**
     3003 * \brief Controls if field data range is normalized to [0,1] before
     3004 * applying scale factor for the given DataSet
     3005 */
     3006void Renderer::setGlyphsNormalizeScale(const DataSetId& id, bool normalize)
     3007{
     3008    GlyphsHashmap::iterator itr;
     3009
     3010    bool doAll = false;
     3011
     3012    if (id.compare("all") == 0) {
     3013        itr = _glyphs.begin();
     3014        doAll = true;
     3015    } else {
     3016        itr = _glyphs.find(id);
     3017    }
     3018    if (itr == _glyphs.end()) {
     3019        ERROR("Glyphs not found: %s", id.c_str());
     3020        return;
     3021    }
     3022
     3023    do {
     3024        itr->second->setNormalizeScale(normalize);
    25793025    } while (doAll && ++itr != _glyphs.end());
    25803026
     
    28333279 * \brief Create a new HeightMap and associate it with the named DataSet
    28343280 */
    2835 void Renderer::addHeightMap(const DataSetId& id)
     3281bool Renderer::addHeightMap(const DataSetId& id, int numContours, double heightScale)
    28363282{
    28373283    DataSetHashmap::iterator itr;
     
    28463292    if (itr == _dataSets.end()) {
    28473293        ERROR("Unknown dataset %s", id.c_str());
    2848         return;
     3294        return false;
    28493295    }
    28503296
     
    28583304        }
    28593305
    2860         HeightMap *hmap = new HeightMap();
     3306        HeightMap *hmap = new HeightMap(numContours, heightScale);
     3307
     3308        hmap->setDataSet(ds,
     3309                         _useCumulativeRange,
     3310                         _cumulativeScalarRange,
     3311                         _cumulativeVectorMagnitudeRange,
     3312                         _cumulativeVectorComponentRange);
     3313
     3314        if (hmap->getProp() == NULL) {
     3315            delete hmap;
     3316            return false;
     3317        } else {
     3318            _renderer->AddViewProp(hmap->getProp());
     3319        }
     3320
    28613321        _heightMaps[dsID] = hmap;
    2862 
    2863         hmap->setDataSet(ds);
    2864 
    2865         // Use the default color map
    2866         vtkSmartPointer<vtkLookupTable> lut = vtkSmartPointer<vtkLookupTable>::New();
    2867         ColorMap *cmap = getColorMap("default");
    2868         lut->DeepCopy(cmap->getLookupTable());
    2869         if (_useCumulativeRange) {
    2870             lut->SetRange(_cumulativeDataRange);
    2871         } else {
    2872             double range[2];
    2873             ds->getDataRange(range);
    2874             lut->SetRange(range);
    2875         }
    2876 
    2877         hmap->setLookupTable(lut);
    2878 
    2879         _renderer->AddViewProp(hmap->getProp());
    28803322    } while (doAll && ++itr != _dataSets.end());
    28813323
     
    28853327
    28863328    _needsRedraw = true;
     3329    return true;
     3330}
     3331
     3332/**
     3333 * \brief Create a new HeightMap and associate it with the named DataSet
     3334 */
     3335bool Renderer::addHeightMap(const DataSetId& id, const std::vector<double>& contours, double heightScale)
     3336{
     3337    DataSetHashmap::iterator itr;
     3338
     3339    bool doAll = false;
     3340
     3341    if (id.compare("all") == 0) {
     3342        itr = _dataSets.begin();
     3343    } else {
     3344        itr = _dataSets.find(id);
     3345    }
     3346    if (itr == _dataSets.end()) {
     3347        ERROR("Unknown dataset %s", id.c_str());
     3348        return false;
     3349    }
     3350
     3351    do {
     3352        DataSet *ds = itr->second;
     3353        const DataSetId& dsID = ds->getName();
     3354
     3355        if (getHeightMap(dsID)) {
     3356            WARN("Replacing existing HeightMap %s", dsID.c_str());
     3357            deleteHeightMap(dsID);
     3358        }
     3359
     3360        HeightMap *hmap = new HeightMap(contours, heightScale);
     3361
     3362        hmap->setDataSet(ds,
     3363                         _useCumulativeRange,
     3364                         _cumulativeScalarRange,
     3365                         _cumulativeVectorMagnitudeRange,
     3366                         _cumulativeVectorComponentRange);
     3367
     3368        if (hmap->getProp() == NULL) {
     3369            delete hmap;
     3370            return false;
     3371        } else {
     3372            _renderer->AddViewProp(hmap->getProp());
     3373        }
     3374
     3375        _heightMaps[dsID] = hmap;
     3376    } while (doAll && ++itr != _dataSets.end());
     3377
     3378    if (_cameraMode == IMAGE)
     3379        setCameraMode(PERSPECTIVE);
     3380    initCamera();
     3381
     3382    _needsRedraw = true;
     3383    return true;
    28873384}
    28883385
     
    28953392
    28963393    if (itr == _heightMaps.end()) {
     3394#ifdef DEBUG
    28973395        TRACE("HeightMap not found: %s", id.c_str());
     3396#endif
    28983397        return NULL;
    28993398    } else
     
    31313630              itr->second->getDataSet()->getName().c_str());
    31323631
    3133         // Make a copy of the generic colormap lookup table, so
    3134         // data range can be set in the copy table to match the
    3135         // dataset being plotted
    3136         vtkSmartPointer<vtkLookupTable> lut = vtkSmartPointer<vtkLookupTable>::New();
    3137         lut->DeepCopy(cmap->getLookupTable());
    3138 
    3139         if (_useCumulativeRange) {
    3140             lut->SetRange(_cumulativeDataRange);
    3141         } else {
    3142             if (itr->second->getDataSet() != NULL) {
    3143                 double range[2];
    3144                 itr->second->getDataSet()->getDataRange(range);
    3145                 lut->SetRange(range);
    3146             }
    3147         }
    3148 
    3149         itr->second->setLookupTable(lut);
     3632        itr->second->setColorMap(cmap);
    31503633    } while (doAll && ++itr != _heightMaps.end());
    31513634
     
    31563639 * \brief Set the number of equally spaced contour isolines for the given DataSet
    31573640 */
    3158 void Renderer::setHeightMapContours(const DataSetId& id, int numContours)
     3641void Renderer::setHeightMapNumContours(const DataSetId& id, int numContours)
    31593642{
    31603643    HeightMapHashmap::iterator itr;
     
    31743657
    31753658    do {
    3176         if (_useCumulativeRange) {
    3177             itr->second->setContours(numContours, _cumulativeDataRange);
    3178         } else {
    3179             itr->second->setContours(numContours);
    3180         }
     3659        itr->second->setNumContours(numContours);
    31813660    } while (doAll && ++itr != _heightMaps.end());
    31823661
     
    32603739    do {
    32613740        itr->second->setVisibility(state);
     3741    } while (doAll && ++itr != _heightMaps.end());
     3742
     3743    _needsRedraw = true;
     3744}
     3745
     3746/**
     3747 * \brief Set wireframe rendering for the specified DataSet
     3748 */
     3749void Renderer::setHeightMapWireframe(const DataSetId& id, bool state)
     3750{
     3751    HeightMapHashmap::iterator itr;
     3752
     3753    bool doAll = false;
     3754
     3755    if (id.compare("all") == 0) {
     3756        itr = _heightMaps.begin();
     3757        doAll = true;
     3758    } else {
     3759        itr = _heightMaps.find(id);
     3760    }
     3761    if (itr == _heightMaps.end()) {
     3762        ERROR("HeightMap not found: %s", id.c_str());
     3763        return;
     3764    }
     3765
     3766    do {
     3767        itr->second->setWireframe(state);
    32623768    } while (doAll && ++itr != _heightMaps.end());
    32633769
     
    33523858 * \brief Turn on/off rendering height map contour lines for the given DataSet
    33533859 */
    3354 void Renderer::setHeightMapContourVisibility(const DataSetId& id, bool state)
     3860void Renderer::setHeightMapContourLineVisibility(const DataSetId& id, bool state)
    33553861{
    33563862    HeightMapHashmap::iterator itr;
     
    33703876
    33713877    do {
    3372         itr->second->setContourVisibility(state);
     3878        itr->second->setContourLineVisibility(state);
     3879    } while (doAll && ++itr != _heightMaps.end());
     3880
     3881    _needsRedraw = true;
     3882}
     3883
     3884/**
     3885 * \brief Turn on/off rendering height map colormap surface for the given DataSet
     3886 */
     3887void Renderer::setHeightMapContourSurfaceVisibility(const DataSetId& id, bool state)
     3888{
     3889    HeightMapHashmap::iterator itr;
     3890
     3891    bool doAll = false;
     3892
     3893    if (id.compare("all") == 0) {
     3894        itr = _heightMaps.begin();
     3895        doAll = true;
     3896    } else {
     3897        itr = _heightMaps.find(id);
     3898    }
     3899    if (itr == _heightMaps.end()) {
     3900        ERROR("HeightMap not found: %s", id.c_str());
     3901        return;
     3902    }
     3903
     3904    do {
     3905        itr->second->setContourSurfaceVisibility(state);
    33733906    } while (doAll && ++itr != _heightMaps.end());
    33743907
     
    34623995 * \brief Create a new LIC and associate it with the named DataSet
    34633996 */
    3464 void Renderer::addLIC(const DataSetId& id)
     3997bool Renderer::addLIC(const DataSetId& id)
    34653998{
    34663999    DataSetHashmap::iterator itr;
     
    34754008    if (itr == _dataSets.end()) {
    34764009        ERROR("Unknown dataset %s", id.c_str());
    3477         return;
     4010        return false;
    34784011    }
    34794012
     
    34904023        _lics[dsID] = lic;
    34914024
    3492         lic->setDataSet(ds);
     4025        lic->setDataSet(ds,
     4026                        _useCumulativeRange,
     4027                        _cumulativeScalarRange,
     4028                        _cumulativeVectorMagnitudeRange,
     4029                        _cumulativeVectorComponentRange);
    34934030
    34944031        _renderer->AddViewProp(lic->getProp());
     
    34994036    initCamera();
    35004037    _needsRedraw = true;
     4038    return true;
    35014039}
    35024040
     
    35094047
    35104048    if (itr == _lics.end()) {
     4049#ifdef DEBUG
    35114050        TRACE("LIC not found: %s", id.c_str());
     4051#endif
    35124052        return NULL;
    35134053    } else
     
    37154255              itr->second->getDataSet()->getName().c_str());
    37164256
    3717         // Make a copy of the generic colormap lookup table, so
    3718         // data range can be set in the copy table to match the
    3719         // dataset being plotted
    3720         vtkSmartPointer<vtkLookupTable> lut = vtkSmartPointer<vtkLookupTable>::New();
    3721         lut->DeepCopy(cmap->getLookupTable());
    3722 
    3723         if (_useCumulativeRange) {
    3724             lut->SetRange(_cumulativeDataRange);
    3725         } else {
    3726             if (itr->second->getDataSet() != NULL) {
    3727                 double range[2];
    3728                 itr->second->getDataSet()->getDataRange(range);
    3729                 lut->SetRange(range);
    3730             }
    3731         }
    3732 
    3733         itr->second->setLookupTable(lut);
     4257        itr->second->setColorMap(cmap);
    37344258    } while (doAll && ++itr != _lics.end());
    37354259
     
    39054429 * \brief Create a new Molecule and associate it with the named DataSet
    39064430 */
    3907 void Renderer::addMolecule(const DataSetId& id)
     4431bool Renderer::addMolecule(const DataSetId& id)
    39084432{
    39094433    DataSetHashmap::iterator itr;
     
    39184442    if (itr == _dataSets.end()) {
    39194443        ERROR("Unknown dataset %s", id.c_str());
    3920         return;
     4444        return false;
    39214445    }
    39224446
     
    39424466    initCamera();
    39434467    _needsRedraw = true;
     4468    return true;
    39444469}
    39454470
     
    39524477
    39534478    if (itr == _molecules.end()) {
     4479#ifdef DEBUG
    39544480        TRACE("Molecule not found: %s", id.c_str());
     4481#endif
    39554482        return NULL;
    39564483    } else
     
    41294656              itr->second->getDataSet()->getName().c_str());
    41304657
    4131         // Make a copy of the generic colormap lookup table, so
    4132         // data range can be set in the copy table to match the
    4133         // dataset being plotted
    4134         vtkSmartPointer<vtkLookupTable> lut = vtkSmartPointer<vtkLookupTable>::New();
    4135         lut->DeepCopy(cmap->getLookupTable());
    4136 
    4137         if (_useCumulativeRange) {
    4138             lut->SetRange(_cumulativeDataRange);
    4139         } else {
    4140             if (itr->second->getDataSet() != NULL) {
    4141                 double range[2];
    4142                 itr->second->getDataSet()->getDataRange(range);
    4143                 lut->SetRange(range);
    4144             }
    4145         }
    4146 
    4147         itr->second->setLookupTable(lut);
     4658        itr->second->setColorMap(cmap);
    41484659    } while (doAll && ++itr != _molecules.end());
    41494660
     
    44274938 * \brief Create a new PolyData and associate it with the named DataSet
    44284939 */
    4429 void Renderer::addPolyData(const DataSetId& id)
     4940bool Renderer::addPolyData(const DataSetId& id)
    44304941{
    44314942    DataSetHashmap::iterator itr;
     
    44404951    if (itr == _dataSets.end()) {
    44414952        ERROR("Unknown dataset %s", id.c_str());
    4442         return;
     4953        return false;
    44434954    }
    44444955
     
    44644975    initCamera();
    44654976    _needsRedraw = true;
     4977    return true;
    44664978}
    44674979
     
    44744986
    44754987    if (itr == _polyDatas.end()) {
     4988#ifdef DEBUG
    44764989        TRACE("PolyData not found: %s", id.c_str());
     4990#endif
    44774991        return NULL;
    44784992    } else
     
    47855299
    47865300/**
    4787  * \brief Set wireframe rendering for the specified DataSet
    4788  */
    4789 void Renderer::setPolyDataWireframe(const DataSetId& id, bool state)
     5301 * \brief Set the point size for the specified DataSet (may be a no-op)
     5302 *
     5303 * If the OpenGL implementation/hardware does not support wide points,
     5304 * this function may not have an effect.
     5305 */
     5306void Renderer::setPolyDataPointSize(const DataSetId& id, float size)
    47905307{
    47915308    PolyDataHashmap::iterator itr;
     
    48055322
    48065323    do {
     5324        itr->second->setPointSize(size);
     5325    } while (doAll && ++itr != _polyDatas.end());
     5326
     5327    _needsRedraw = true;
     5328}
     5329
     5330/**
     5331 * \brief Set wireframe rendering for the specified DataSet
     5332 */
     5333void Renderer::setPolyDataWireframe(const DataSetId& id, bool state)
     5334{
     5335    PolyDataHashmap::iterator itr;
     5336
     5337    bool doAll = false;
     5338
     5339    if (id.compare("all") == 0) {
     5340        itr = _polyDatas.begin();
     5341        doAll = true;
     5342    } else {
     5343        itr = _polyDatas.find(id);
     5344    }
     5345    if (itr == _polyDatas.end()) {
     5346        ERROR("PolyData not found: %s", id.c_str());
     5347        return;
     5348    }
     5349
     5350    do {
    48075351        itr->second->setWireframe(state);
    48085352    } while (doAll && ++itr != _polyDatas.end());
     
    48415385 * \brief Create a new PseudoColor rendering for the specified DataSet
    48425386 */
    4843 void Renderer::addPseudoColor(const DataSetId& id)
     5387bool Renderer::addPseudoColor(const DataSetId& id)
    48445388{
    48455389    DataSetHashmap::iterator itr;
     
    48545398    if (itr == _dataSets.end()) {
    48555399        ERROR("Unknown dataset %s", id.c_str());
    4856         return;
     5400        return false;
    48575401    }
    48585402
     
    48685412        _pseudoColors[dsID] = pc;
    48695413
    4870         pc->setDataSet(ds);
    4871 
    4872         // Use the default color map
    4873         vtkSmartPointer<vtkLookupTable> lut = vtkSmartPointer<vtkLookupTable>::New();
    4874         ColorMap *cmap = getColorMap("default");
    4875         lut->DeepCopy(cmap->getLookupTable());
    4876         if (_useCumulativeRange) {
    4877             lut->SetRange(_cumulativeDataRange);
    4878         } else {
    4879             double range[2];
    4880             ds->getDataRange(range);
    4881             lut->SetRange(range);
    4882         }
    4883 
    4884         pc->setLookupTable(lut);
     5414        pc->setDataSet(ds,
     5415                       _useCumulativeRange,
     5416                       _cumulativeScalarRange,
     5417                       _cumulativeVectorMagnitudeRange,
     5418                       _cumulativeVectorComponentRange);
    48855419
    48865420        _renderer->AddViewProp(pc->getProp());
     
    48895423    initCamera();
    48905424    _needsRedraw = true;
     5425    return true;
    48915426}
    48925427
     
    48995434
    49005435    if (itr == _pseudoColors.end()) {
     5436#ifdef DEBUG
    49015437        TRACE("PseudoColor not found: %s", id.c_str());
     5438#endif
    49025439        return NULL;
    49035440    } else
     
    50465583
    50475584/**
     5585 * \brief Set the RGB color for the specified DataSet
     5586 */
     5587void Renderer::setPseudoColorColor(const DataSetId& id, float color[3])
     5588{
     5589    PseudoColorHashmap::iterator itr;
     5590
     5591    bool doAll = false;
     5592
     5593    if (id.compare("all") == 0) {
     5594        itr = _pseudoColors.begin();
     5595        doAll = true;
     5596    } else {
     5597        itr = _pseudoColors.find(id);
     5598    }
     5599    if (itr == _pseudoColors.end()) {
     5600        ERROR("PseudoColor not found: %s", id.c_str());
     5601        return;
     5602    }
     5603
     5604    do {
     5605        itr->second->setColor(color);
     5606    } while (doAll && ++itr != _pseudoColors.end());
     5607
     5608    _needsRedraw = true;
     5609}
     5610
     5611/**
    50485612 * \brief Associate an existing named color map with a PseudoColor for the given DataSet
    50495613 */
     
    50765640              itr->second->getDataSet()->getName().c_str());
    50775641
    5078         // Make a copy of the generic colormap lookup table, so
    5079         // data range can be set in the copy table to match the
    5080         // dataset being plotted
    5081         vtkSmartPointer<vtkLookupTable> lut = vtkSmartPointer<vtkLookupTable>::New();
    5082         lut->DeepCopy(cmap->getLookupTable());
    5083 
    5084         if (_useCumulativeRange) {
    5085             lut->SetRange(_cumulativeDataRange);
    5086         } else {
    5087             if (itr->second->getDataSet() != NULL) {
    5088                 double range[2];
    5089                 itr->second->getDataSet()->getDataRange(range);
    5090                 lut->SetRange(range);
    5091             }
    5092         }
    5093 
    5094         itr->second->setLookupTable(lut);
     5642        itr->second->setColorMap(cmap);
     5643    } while (doAll && ++itr != _pseudoColors.end());
     5644
     5645    _needsRedraw = true;
     5646}
     5647
     5648/**
     5649 * \brief Set the color mode for the specified DataSet
     5650 */
     5651void Renderer::setPseudoColorColorMode(const DataSetId& id, PseudoColor::ColorMode mode)
     5652{
     5653    PseudoColorHashmap::iterator itr;
     5654
     5655    bool doAll = false;
     5656
     5657    if (id.compare("all") == 0) {
     5658        itr = _pseudoColors.begin();
     5659        doAll = true;
     5660    } else {
     5661        itr = _pseudoColors.find(id);
     5662    }
     5663    if (itr == _pseudoColors.end()) {
     5664        ERROR("PseudoColor not found: %s", id.c_str());
     5665        return;
     5666    }
     5667
     5668    do {
     5669        itr->second->setColorMode(mode);
    50955670    } while (doAll && ++itr != _pseudoColors.end());
    50965671
     
    52995874 * \brief Create a new Streamlines and associate it with the named DataSet
    53005875 */
    5301 void Renderer::addStreamlines(const DataSetId& id)
     5876bool Renderer::addStreamlines(const DataSetId& id)
    53025877{
    53035878    DataSetHashmap::iterator itr;
     
    53125887    if (itr == _dataSets.end()) {
    53135888        ERROR("Unknown dataset %s", id.c_str());
    5314         return;
     5889        return false;
    53155890    }
    53165891
     
    53275902        _streamlines[dsID] = streamlines;
    53285903
    5329         streamlines->setDataSet(ds);
    5330 
    5331         // Use the default color map
    5332         vtkSmartPointer<vtkLookupTable> lut = vtkSmartPointer<vtkLookupTable>::New();
    5333         ColorMap *cmap = getColorMap("default");
    5334         lut->DeepCopy(cmap->getLookupTable());
    5335 
    5336         if (_useCumulativeRange) {
    5337             lut->SetRange(_cumulativeDataRange);
    5338         } else {
    5339             double range[2];
    5340             ds->getDataRange(range);
    5341             lut->SetRange(range);
    5342         }
    5343         streamlines->setLookupTable(lut);
     5904        streamlines->setDataSet(ds,
     5905                                _useCumulativeRange,
     5906                                _cumulativeScalarRange,
     5907                                _cumulativeVectorMagnitudeRange,
     5908                                _cumulativeVectorComponentRange);
    53445909
    53455910        _renderer->AddViewProp(streamlines->getProp());
     
    53485913    initCamera();
    53495914    _needsRedraw = true;
     5915    return true;
    53505916}
    53515917
     
    53585924
    53595925    if (itr == _streamlines.end()) {
     5926#ifdef DEBUG
    53605927        TRACE("Streamlines not found: %s", id.c_str());
     5928#endif
    53615929        return NULL;
    53625930    } else
     
    59016469              itr->second->getDataSet()->getName().c_str());
    59026470
    5903         // Make a copy of the generic colormap lookup table, so
    5904         // data range can be set in the copy table to match the
    5905         // dataset being plotted
    5906         vtkSmartPointer<vtkLookupTable> lut = vtkSmartPointer<vtkLookupTable>::New();
    5907         lut->DeepCopy(cmap->getLookupTable());
    5908 
    5909         if (_useCumulativeRange) {
    5910             lut->SetRange(_cumulativeDataRange);
    5911         } else {
    5912             if (itr->second->getDataSet() != NULL) {
    5913                 double range[2];
    5914                 itr->second->getDataSet()->getDataRange(range);
    5915                 lut->SetRange(range);
    5916             }
    5917         }
    5918 
    5919         itr->second->setLookupTable(lut);
     6471        itr->second->setColorMap(cmap);
    59206472    } while (doAll && ++itr != _streamlines.end());
    59216473
     
    60926644 * \brief Create a new Volume and associate it with the named DataSet
    60936645 */
    6094 void Renderer::addVolume(const DataSetId& id)
     6646bool Renderer::addVolume(const DataSetId& id)
    60956647{
    60966648    DataSetHashmap::iterator itr;
     
    61056657    if (itr == _dataSets.end()) {
    61066658        ERROR("Unknown dataset %s", id.c_str());
    6107         return;
     6659        return false;
    61086660    }
    61096661
     
    61206672        _volumes[dsID] = volume;
    61216673
    6122         volume->setDataSet(ds);
    6123 
    6124         if (_useCumulativeRange) {
    6125             ColorMap *cmap = volume->getColorMap();
    6126             volume->setColorMap(cmap, _cumulativeDataRange);
    6127         }
     6674        volume->setDataSet(ds,
     6675                           _useCumulativeRange,
     6676                           _cumulativeScalarRange,
     6677                           _cumulativeVectorMagnitudeRange,
     6678                           _cumulativeVectorComponentRange );
    61286679
    61296680        _renderer->AddViewProp(volume->getProp());
     
    61346685    initCamera();
    61356686    _needsRedraw = true;
     6687    return true;
    61366688}
    61376689
     
    61446696
    61456697    if (itr == _volumes.end()) {
     6698#ifdef DEBUG
    61466699        TRACE("Volume not found: %s", id.c_str());
     6700#endif
    61476701        return NULL;
    61486702    } else
     
    63216875              itr->second->getDataSet()->getName().c_str());
    63226876
    6323         if (_useCumulativeRange) {
    6324             itr->second->setColorMap(cmap, _cumulativeDataRange);
    6325         } else {
    6326             itr->second->setColorMap(cmap);
    6327         }
     6877        itr->second->setColorMap(cmap);
    63286878    } while (doAll && ++itr != _volumes.end());
    63296879
     
    65177067void Renderer::setWindowSize(int width, int height)
    65187068{
    6519     setViewAngle(height);
     7069    if (_windowWidth == width &&
     7070        _windowHeight == height)
     7071        return;
     7072
     7073    //setViewAngle(height);
    65207074
    65217075    // FIXME: Fix up panning on aspect change
     
    65567110    CameraMode origMode = _cameraMode;
    65577111    _cameraMode = mode;
     7112    resetAxes();
     7113
    65587114    vtkSmartPointer<vtkCamera> camera = _renderer->GetActiveCamera();
    65597115    switch (mode) {
     
    65847140        ERROR("Unkown camera mode: %d", mode);
    65857141    }
    6586     resetAxes();
    6587 
    65887142    _needsRedraw = true;
    65897143}
     
    70387592        setCameraZoomRegion(_imgWorldOrigin[0], _imgWorldOrigin[1],
    70397593                            _imgWorldDims[0], _imgWorldDims[1]);
    7040     } else if (_cameraMode == ORTHO) {
    7041         camera->Zoom(z); // Change ortho parallel scale (Dolly has no effect in ortho)
    7042         _renderer->ResetCameraClippingRange();
    7043     } else {
    7044         camera->Dolly(z); // Move camera forward/back
     7594    } else {
     7595        // Keep ortho and perspective modes in sync
     7596        // Move camera forward/back for perspective camera
     7597        camera->Dolly(z);
     7598        // Change ortho parallel scale
     7599        camera->SetParallelScale(camera->GetParallelScale()/z);
    70457600        _renderer->ResetCameraClippingRange();
    70467601        //computeScreenWorldCoords();
     
    70517606
    70527607    _needsRedraw = true;
     7608}
     7609
     7610/**
     7611 * \brief Set the pan/zoom using a corner and dimensions in pixel coordinates
     7612 *
     7613 * \param[in] x left pixel coordinate
     7614 * \param[in] y bottom  pixel coordinate (with y=0 at top of window)
     7615 * \param[in] width Width of zoom region in pixel coordinates
     7616 * \param[in] height Height of zoom region in pixel coordinates
     7617 */
     7618void Renderer::setCameraZoomRegionPixels(int x, int y, int width, int height)
     7619{
     7620    double wx, wy, ww, wh;
     7621
     7622    y = _windowHeight - y;
     7623    double pxToWorldX = _screenWorldCoords[2] / (double)_windowWidth;
     7624    double pxToWorldY = _screenWorldCoords[3] / (double)_windowHeight;
     7625
     7626    wx = _screenWorldCoords[0] + x * pxToWorldX;
     7627    wy = _screenWorldCoords[1] + y * pxToWorldY;
     7628    ww = abs(width) *  pxToWorldX;
     7629    wh = abs(height) * pxToWorldY;
     7630    setCameraZoomRegion(wx, wy, ww, wh);
     7631
     7632    TRACE("\npx: %d %d %d %d\nworld: %g %g %g %g",
     7633          x, y, width, height,
     7634          wx, wy, ww, wh);
    70537635}
    70547636
     
    70657647    double camPos[2];
    70667648
    7067     int pxOffsetX = 85;
    7068     int pxOffsetY = 75;
    7069     int outerGutter = 15;
     7649    int pxOffsetX = (int)(0.17 * (double)_windowWidth);
     7650    pxOffsetX = (pxOffsetX > 100 ? 100 : pxOffsetX);
     7651    int pxOffsetY = (int)(0.15 * (double)_windowHeight);
     7652    pxOffsetY = (pxOffsetY > 75 ? 75 : pxOffsetY);
     7653    int outerGutter = (int)(0.03 * (double)_windowWidth);
     7654    outerGutter = (outerGutter > 15 ? 15 : outerGutter);
    70707655
    70717656    int imgHeightPx = _windowHeight - pxOffsetY - outerGutter;
     
    71037688    vtkSmartPointer<vtkCamera> camera = _renderer->GetActiveCamera();
    71047689    camera->ParallelProjectionOn();
    7105     camera->SetPosition(camPos[0], camPos[1], 1);
    7106     camera->SetFocalPoint(camPos[0], camPos[1], 0);
    7107     camera->SetViewUp(0, 1, 0);
    71087690    camera->SetClippingRange(1, 2);
    71097691    // Half of world coordinate height of viewport (Documentation is wrong)
    71107692    camera->SetParallelScale(_windowHeight * pxToWorld / 2.0);
    71117693
    7112     // bottom
    7113     _cameraClipPlanes[0]->SetOrigin(0, _imgWorldOrigin[1], 0);
    7114     // left
    7115     _cameraClipPlanes[1]->SetOrigin(_imgWorldOrigin[0], 0, 0);
    7116     // top
    7117     _cameraClipPlanes[2]->SetOrigin(0, _imgWorldOrigin[1] + _imgWorldDims[1], 0);
    7118     // right
    7119     _cameraClipPlanes[3]->SetOrigin(_imgWorldOrigin[0] + _imgWorldDims[0], 0, 0);
    7120 
    7121     _cubeAxesActor2D->SetBounds(_imgWorldOrigin[0], _imgWorldOrigin[0] + _imgWorldDims[0],
    7122                                 _imgWorldOrigin[1], _imgWorldOrigin[1] + _imgWorldDims[1], 0, 0);
     7694    if (_imgCameraPlane == PLANE_XY) {
     7695        // XY plane
     7696        camera->SetPosition(camPos[0], camPos[1], _imgCameraOffset + 1.);
     7697        camera->SetFocalPoint(camPos[0], camPos[1], _imgCameraOffset);
     7698        camera->SetViewUp(0, 1, 0);
     7699        // bottom
     7700        _cameraClipPlanes[0]->SetOrigin(0, _imgWorldOrigin[1], 0);
     7701        _cameraClipPlanes[0]->SetNormal(0, 1, 0);
     7702        // left
     7703        _cameraClipPlanes[1]->SetOrigin(_imgWorldOrigin[0], 0, 0);
     7704        _cameraClipPlanes[1]->SetNormal(1, 0, 0);
     7705        // top
     7706        _cameraClipPlanes[2]->SetOrigin(0, _imgWorldOrigin[1] + _imgWorldDims[1], 0);
     7707        _cameraClipPlanes[2]->SetNormal(0, -1, 0);
     7708        // right
     7709        _cameraClipPlanes[3]->SetOrigin(_imgWorldOrigin[0] + _imgWorldDims[0], 0, 0);
     7710        _cameraClipPlanes[3]->SetNormal(-1, 0, 0);
     7711        _cubeAxesActor2D->SetBounds(_imgWorldOrigin[0], _imgWorldOrigin[0] + _imgWorldDims[0],
     7712                                    _imgWorldOrigin[1], _imgWorldOrigin[1] + _imgWorldDims[1],
     7713                                    _imgCameraOffset, _imgCameraOffset);
     7714        _cubeAxesActor2D->XAxisVisibilityOn();
     7715        _cubeAxesActor2D->YAxisVisibilityOn();
     7716        _cubeAxesActor2D->ZAxisVisibilityOff();
     7717    } else if (_imgCameraPlane == PLANE_ZY) {
     7718        // ZY plane
     7719        camera->SetPosition(_imgCameraOffset - 1., camPos[1], camPos[0]);
     7720        camera->SetFocalPoint(_imgCameraOffset, camPos[1], camPos[0]);
     7721        camera->SetViewUp(0, 1, 0);
     7722        // bottom
     7723        _cameraClipPlanes[0]->SetOrigin(0, _imgWorldOrigin[1], 0);
     7724        _cameraClipPlanes[0]->SetNormal(0, 1, 0);
     7725        // left
     7726        _cameraClipPlanes[1]->SetOrigin(0, 0, _imgWorldOrigin[0]);
     7727        _cameraClipPlanes[1]->SetNormal(0, 0, 1);
     7728        // top
     7729        _cameraClipPlanes[2]->SetOrigin(0, _imgWorldOrigin[1] + _imgWorldDims[1], 0);
     7730        _cameraClipPlanes[2]->SetNormal(0, -1, 0);
     7731        // right
     7732        _cameraClipPlanes[3]->SetOrigin(0, 0, _imgWorldOrigin[0] + _imgWorldDims[0]);
     7733        _cameraClipPlanes[3]->SetNormal(0, 0, -1);
     7734        _cubeAxesActor2D->SetBounds(_imgCameraOffset, _imgCameraOffset,
     7735                                    _imgWorldOrigin[1], _imgWorldOrigin[1] + _imgWorldDims[1],
     7736                                    _imgWorldOrigin[0], _imgWorldOrigin[0] + _imgWorldDims[0]);
     7737        _cubeAxesActor2D->XAxisVisibilityOff();
     7738        _cubeAxesActor2D->YAxisVisibilityOn();
     7739        _cubeAxesActor2D->ZAxisVisibilityOn();
     7740    } else {
     7741        // XZ plane
     7742        camera->SetPosition(camPos[0], _imgCameraOffset - 1., camPos[1]);
     7743        camera->SetFocalPoint(camPos[0], _imgCameraOffset, camPos[1]);
     7744        camera->SetViewUp(0, 0, 1);
     7745        // bottom
     7746        _cameraClipPlanes[0]->SetOrigin(0, 0, _imgWorldOrigin[1]);
     7747        _cameraClipPlanes[0]->SetNormal(0, 0, 1);
     7748        // left
     7749        _cameraClipPlanes[1]->SetOrigin(_imgWorldOrigin[0], 0, 0);
     7750        _cameraClipPlanes[1]->SetNormal(1, 0, 0);
     7751        // top
     7752        _cameraClipPlanes[2]->SetOrigin(0, 0, _imgWorldOrigin[1] + _imgWorldDims[1]);
     7753        _cameraClipPlanes[2]->SetNormal(0, 0, -1);
     7754        // right
     7755        _cameraClipPlanes[3]->SetOrigin(_imgWorldOrigin[0] + _imgWorldDims[0], 0, 0);
     7756        _cameraClipPlanes[3]->SetNormal(-1, 0, 0);
     7757        _cubeAxesActor2D->SetBounds(_imgWorldOrigin[0], _imgWorldOrigin[0] + _imgWorldDims[0],
     7758                                    _imgCameraOffset, _imgCameraOffset,
     7759                                    _imgWorldOrigin[1], _imgWorldOrigin[1] + _imgWorldDims[1]);
     7760        _cubeAxesActor2D->XAxisVisibilityOn();
     7761        _cubeAxesActor2D->YAxisVisibilityOff();
     7762        _cubeAxesActor2D->ZAxisVisibilityOn();
     7763    }
    71237764
    71247765    // Compute screen world coordinates
     
    72127853    mat->Delete();
    72137854
    7214     _screenWorldCoords[0] = x0;
    7215     _screenWorldCoords[1] = y0;
    7216     _screenWorldCoords[2] = x1 - x0;
    7217     _screenWorldCoords[3] = y1 - y0;
     7855    if (_imgCameraPlane == PLANE_XZ) {
     7856        _screenWorldCoords[0] = x0;
     7857        _screenWorldCoords[1] = z0;
     7858        _screenWorldCoords[2] = x1 - x0;
     7859        _screenWorldCoords[3] = z1 - z0;
     7860    } else if (_imgCameraPlane == PLANE_ZY) {
     7861        _screenWorldCoords[0] = z0;
     7862        _screenWorldCoords[1] = y0;
     7863        _screenWorldCoords[2] = z1 - z0;
     7864        _screenWorldCoords[3] = y1 - y0;
     7865    } else {
     7866        // XY
     7867        _screenWorldCoords[0] = x0;
     7868        _screenWorldCoords[1] = y0;
     7869        _screenWorldCoords[2] = x1 - x0;
     7870        _screenWorldCoords[3] = y1 - y0;
     7871    }
    72187872}
    72197873
     
    72807934    bounds[5] = -DBL_MAX;
    72817935
     7936    for (DataSetHashmap::iterator itr = _dataSets.begin();
     7937             itr != _dataSets.end(); ++itr) {
     7938        if ((!onlyVisible || itr->second->getVisibility()) &&
     7939            itr->second->getProp() != NULL)
     7940            mergeBounds(bounds, bounds, itr->second->getProp()->GetBounds());
     7941    }
    72827942    for (Contour2DHashmap::iterator itr = _contour2Ds.begin();
    72837943             itr != _contour2Ds.end(); ++itr) {
    7284         if (!onlyVisible || itr->second->getVisibility())
     7944        if ((!onlyVisible || itr->second->getVisibility()) &&
     7945            itr->second->getProp() != NULL)
    72857946            mergeBounds(bounds, bounds, itr->second->getProp()->GetBounds());
    72867947    }
    72877948    for (Contour3DHashmap::iterator itr = _contour3Ds.begin();
    72887949             itr != _contour3Ds.end(); ++itr) {
    7289         if (!onlyVisible || itr->second->getVisibility())
     7950        if ((!onlyVisible || itr->second->getVisibility()) &&
     7951            itr->second->getProp() != NULL)
    72907952            mergeBounds(bounds, bounds, itr->second->getProp()->GetBounds());
    72917953    }
    72927954    for (GlyphsHashmap::iterator itr = _glyphs.begin();
    72937955             itr != _glyphs.end(); ++itr) {
    7294         if (!onlyVisible || itr->second->getVisibility())
     7956        if ((!onlyVisible || itr->second->getVisibility()) &&
     7957            itr->second->getProp() != NULL)
    72957958            mergeBounds(bounds, bounds, itr->second->getProp()->GetBounds());
    72967959    }
    72977960    for (HeightMapHashmap::iterator itr = _heightMaps.begin();
    72987961             itr != _heightMaps.end(); ++itr) {
    7299         if (!onlyVisible || itr->second->getVisibility())
     7962        if ((!onlyVisible || itr->second->getVisibility()) &&
     7963            itr->second->getProp() != NULL)
    73007964            mergeBounds(bounds, bounds, itr->second->getProp()->GetBounds());
    73017965    }
    73027966    for (LICHashmap::iterator itr = _lics.begin();
    73037967             itr != _lics.end(); ++itr) {
    7304         if (!onlyVisible || itr->second->getVisibility())
     7968        if ((!onlyVisible || itr->second->getVisibility()) &&
     7969            itr->second->getProp() != NULL)
    73057970            mergeBounds(bounds, bounds, itr->second->getProp()->GetBounds());
    73067971    }
    73077972    for (MoleculeHashmap::iterator itr = _molecules.begin();
    73087973             itr != _molecules.end(); ++itr) {
    7309         if (!onlyVisible || itr->second->getVisibility())
     7974        if ((!onlyVisible || itr->second->getVisibility()) &&
     7975            itr->second->getProp() != NULL)
    73107976            mergeBounds(bounds, bounds, itr->second->getProp()->GetBounds());
    73117977    }
    73127978    for (PolyDataHashmap::iterator itr = _polyDatas.begin();
    73137979             itr != _polyDatas.end(); ++itr) {
    7314         if (!onlyVisible || itr->second->getVisibility())
     7980        if ((!onlyVisible || itr->second->getVisibility()) &&
     7981            itr->second->getProp() != NULL)
    73157982            mergeBounds(bounds, bounds, itr->second->getProp()->GetBounds());
    73167983    }
    73177984    for (PseudoColorHashmap::iterator itr = _pseudoColors.begin();
    73187985             itr != _pseudoColors.end(); ++itr) {
    7319         if (!onlyVisible || itr->second->getVisibility())
     7986        if ((!onlyVisible || itr->second->getVisibility()) &&
     7987            itr->second->getProp() != NULL)
    73207988            mergeBounds(bounds, bounds, itr->second->getProp()->GetBounds());
    73217989    }
    73227990    for (StreamlinesHashmap::iterator itr = _streamlines.begin();
    73237991             itr != _streamlines.end(); ++itr) {
    7324         if (!onlyVisible || itr->second->getVisibility())
     7992        if ((!onlyVisible || itr->second->getVisibility()) &&
     7993            itr->second->getProp() != NULL)
    73257994            mergeBounds(bounds, bounds, itr->second->getProp()->GetBounds());
    73267995    }
    73277996    for (VolumeHashmap::iterator itr = _volumes.begin();
    73287997             itr != _volumes.end(); ++itr) {
    7329         if (!onlyVisible || itr->second->getVisibility())
     7998        if ((!onlyVisible || itr->second->getVisibility()) &&
     7999            itr->second->getProp() != NULL)
    73308000            mergeBounds(bounds, bounds, itr->second->getProp()->GetBounds());
    73318001    }
    7332     for (int i = 0; i < 6; i++) {
    7333         if (i % 2 == 0) {
    7334             if (bounds[i] == DBL_MAX)
    7335                 bounds[i] = 0;
    7336         } else {
    7337             if (bounds[i] == -DBL_MAX)
    7338                 bounds[i] = 1;
     8002
     8003    for (int i = 0; i < 6; i += 2) {
     8004        if (bounds[i+1] < bounds[i]) {
     8005            bounds[i] = -0.5;
     8006            bounds[i+1] = 0.5;
    73398007        }
    73408008    }
     8009
     8010    int numDims = 0;
     8011    if (bounds[0] != bounds[1])
     8012        numDims++;
     8013    if (bounds[2] != bounds[3])
     8014        numDims++;
     8015    if (bounds[4] != bounds[5])
     8016        numDims++;
     8017
     8018    if (numDims == 0) {
     8019        bounds[0] -= .5;
     8020        bounds[1] += .5;
     8021        bounds[2] -= .5;
     8022        bounds[3] += .5;
     8023    }
     8024
    73418025    TRACE("Bounds: %g %g %g %g %g %g",
    73428026          bounds[0],
     
    73508034/**
    73518035 * \brief Update data ranges for color-mapping and contours
    7352  *
    7353  * \param[in] useCumulative Use cumulative range of all DataSets
    7354  */
    7355 void Renderer::updateRanges(bool useCumulative)
    7356 {
     8036 */
     8037void Renderer::updateRanges()
     8038{
     8039    collectDataRanges();
     8040
    73578041    for (Contour2DHashmap::iterator itr = _contour2Ds.begin();
    73588042         itr != _contour2Ds.end(); ++itr) {
    7359         // Only need to update range if using evenly spaced contours
    7360         if (itr->second->getContourList().empty()) {
    7361             if (useCumulative) {
    7362                 itr->second->setContours(itr->second->getNumContours(), _cumulativeDataRange);
    7363             } else {
    7364                 itr->second->setContours(itr->second->getNumContours());
    7365             }
    7366         }
     8043        itr->second->updateRanges(_useCumulativeRange,
     8044                                  _cumulativeScalarRange,
     8045                                  _cumulativeVectorMagnitudeRange,
     8046                                  _cumulativeVectorComponentRange);
    73678047    }
    73688048    for (Contour3DHashmap::iterator itr = _contour3Ds.begin();
    73698049         itr != _contour3Ds.end(); ++itr) {
    7370         // Only need to update range if using evenly spaced contours
    7371         if (itr->second->getContourList().empty()) {
    7372             if (useCumulative) {
    7373                 itr->second->setContours(itr->second->getNumContours(), _cumulativeDataRange);
    7374             } else {
    7375                 itr->second->setContours(itr->second->getNumContours());
    7376             }
    7377         }
     8050        itr->second->updateRanges(_useCumulativeRange,
     8051                                  _cumulativeScalarRange,
     8052                                  _cumulativeVectorMagnitudeRange,
     8053                                  _cumulativeVectorComponentRange);
    73788054    }
    73798055    for (GlyphsHashmap::iterator itr = _glyphs.begin();
    73808056         itr != _glyphs.end(); ++itr) {
    7381         vtkLookupTable *lut = itr->second->getLookupTable();
    7382         if (lut) {
    7383             if (useCumulative) {
    7384                 lut->SetRange(_cumulativeDataRange);
    7385             } else {
    7386                 double range[2];
    7387                 if (itr->second->getDataSet()) {
    7388                     itr->second->getDataSet()->getDataRange(range);
    7389                     lut->SetRange(range);
    7390                 }
    7391             }
    7392         }
     8057        itr->second->updateRanges(_useCumulativeRange,
     8058                                  _cumulativeScalarRange,
     8059                                  _cumulativeVectorMagnitudeRange,
     8060                                  _cumulativeVectorComponentRange);
    73938061    }
    73948062    for (HeightMapHashmap::iterator itr = _heightMaps.begin();
    73958063         itr != _heightMaps.end(); ++itr) {
    7396         vtkLookupTable *lut = itr->second->getLookupTable();
    7397         if (lut) {
    7398             if (useCumulative) {
    7399                 lut->SetRange(_cumulativeDataRange);
    7400             } else {
    7401                 double range[2];
    7402                 if (itr->second->getDataSet()) {
    7403                     itr->second->getDataSet()->getDataRange(range);
    7404                     lut->SetRange(range);
    7405                 }
    7406             }
    7407         }
    7408         // Only need to update contour range if using evenly spaced contours
    7409         if (itr->second->getContourList().empty()) {
    7410             if (useCumulative) {
    7411                 itr->second->setContours(itr->second->getNumContours(), _cumulativeDataRange);
    7412             } else {
    7413                 itr->second->setContours(itr->second->getNumContours());
    7414             }
    7415         }
     8064        itr->second->updateRanges(_useCumulativeRange,
     8065                                  _cumulativeScalarRange,
     8066                                  _cumulativeVectorMagnitudeRange,
     8067                                  _cumulativeVectorComponentRange);
    74168068    }
    74178069    for (LICHashmap::iterator itr = _lics.begin();
    74188070         itr != _lics.end(); ++itr) {
    7419         vtkLookupTable *lut = itr->second->getLookupTable();
    7420         if (lut) {
    7421             if (useCumulative) {
    7422                 lut->SetRange(_cumulativeDataRange);
    7423             } else {
    7424                 double range[2];
    7425                 if (itr->second->getDataSet()) {
    7426                     itr->second->getDataSet()->getDataRange(range);
    7427                     lut->SetRange(range);
    7428                 }
    7429             }
    7430         }
     8071        itr->second->updateRanges(_useCumulativeRange,
     8072                                  _cumulativeScalarRange,
     8073                                  _cumulativeVectorMagnitudeRange,
     8074                                  _cumulativeVectorComponentRange);
     8075    }
     8076    for (MoleculeHashmap::iterator itr = _molecules.begin();
     8077         itr != _molecules.end(); ++itr) {
     8078        itr->second->updateRanges(_useCumulativeRange,
     8079                                  _cumulativeScalarRange,
     8080                                  _cumulativeVectorMagnitudeRange,
     8081                                  _cumulativeVectorComponentRange);
    74318082    }
    74328083    for (PseudoColorHashmap::iterator itr = _pseudoColors.begin();
    74338084         itr != _pseudoColors.end(); ++itr) {
    7434         vtkLookupTable *lut = itr->second->getLookupTable();
    7435         if (lut) {
    7436             if (useCumulative) {
    7437                 lut->SetRange(_cumulativeDataRange);
    7438             } else {
    7439                 double range[2];
    7440                 if (itr->second->getDataSet()) {
    7441                     itr->second->getDataSet()->getDataRange(range);
    7442                     lut->SetRange(range);
    7443                 }
    7444             }
    7445         }
     8085        itr->second->updateRanges(_useCumulativeRange,
     8086                                  _cumulativeScalarRange,
     8087                                  _cumulativeVectorMagnitudeRange,
     8088                                  _cumulativeVectorComponentRange);
    74468089    }
    74478090    for (StreamlinesHashmap::iterator itr = _streamlines.begin();
    74488091         itr != _streamlines.end(); ++itr) {
    7449         vtkLookupTable *lut = itr->second->getLookupTable();
    7450         if (lut) {
    7451             if (useCumulative) {
    7452                 lut->SetRange(_cumulativeDataRange);
    7453             } else {
    7454                 double range[2];
    7455                 if (itr->second->getDataSet()) {
    7456                     itr->second->getDataSet()->getDataRange(range);
    7457                     lut->SetRange(range);
    7458                 }
    7459             }
    7460         }
     8092        itr->second->updateRanges(_useCumulativeRange,
     8093                                  _cumulativeScalarRange,
     8094                                  _cumulativeVectorMagnitudeRange,
     8095                                  _cumulativeVectorComponentRange);
    74618096    }
    74628097    for (VolumeHashmap::iterator itr = _volumes.begin();
    74638098         itr != _volumes.end(); ++itr) {
    7464         ColorMap *cmap = itr->second->getColorMap();
    7465         if (cmap) {
    7466             if (useCumulative) {
    7467                 itr->second->setColorMap(cmap, _cumulativeDataRange);
    7468             } else {
    7469                 itr->second->setColorMap(cmap);
    7470             }
    7471         }
     8099        itr->second->updateRanges(_useCumulativeRange,
     8100                                  _cumulativeScalarRange,
     8101                                  _cumulativeVectorMagnitudeRange,
     8102                                  _cumulativeVectorComponentRange);
     8103    }
     8104}
     8105
     8106void Renderer::collectDataRanges()
     8107{
     8108    collectScalarRanges(_cumulativeScalarRange,
     8109                        _cumulativeRangeOnlyVisible);
     8110    collectVectorMagnitudeRanges(_cumulativeVectorMagnitudeRange,
     8111                                 _cumulativeRangeOnlyVisible);
     8112    for (int i = 0; i < 3; i++) {
     8113        collectVectorComponentRanges(_cumulativeVectorComponentRange[i], i,
     8114                                     _cumulativeRangeOnlyVisible);
     8115    }
     8116
     8117    TRACE("Cumulative scalar range: %g, %g",
     8118          _cumulativeScalarRange[0],
     8119          _cumulativeScalarRange[1]);
     8120    TRACE("Cumulative vmag range: %g, %g",
     8121          _cumulativeVectorMagnitudeRange[0],
     8122          _cumulativeVectorMagnitudeRange[1]);
     8123    for (int i = 0; i < 3; i++) {
     8124        TRACE("Cumulative v[%d] range: %g, %g", i,
     8125              _cumulativeVectorComponentRange[i][0],
     8126              _cumulativeVectorComponentRange[i][1]);
    74728127    }
    74738128}
     
    74768131 * \brief Collect cumulative data range of all DataSets
    74778132 *
    7478  * \param[inout] range Data range of all DataSets
     8133 * \param[in,out] range Data range of all DataSets
    74798134 * \param[in] onlyVisible Only collect range of visible DataSets
    74808135 */
    7481 void Renderer::collectDataRanges(double *range, bool onlyVisible)
     8136void Renderer::collectScalarRanges(double *range, bool onlyVisible)
    74828137{
    74838138    range[0] = DBL_MAX;
     
    74888143        if (!onlyVisible || itr->second->getVisibility()) {
    74898144            double r[2];
    7490             itr->second->getDataRange(r);
     8145            itr->second->getScalarRange(r);
    74918146            range[0] = min2(range[0], r[0]);
    74928147            range[1] = max2(range[1], r[1]);
     
    74978152    if (range[1] == -DBL_MAX)
    74988153        range[1] = 1;
     8154}
     8155
     8156/**
     8157 * \brief Collect cumulative data range of all DataSets
     8158 *
     8159 * \param[in,out] range Data range of all DataSets
     8160 * \param[in] onlyVisible Only collect range of visible DataSets
     8161 */
     8162void Renderer::collectVectorMagnitudeRanges(double *range, bool onlyVisible)
     8163{
     8164    range[0] = DBL_MAX;
     8165    range[1] = -DBL_MAX;
     8166
     8167    for (DataSetHashmap::iterator itr = _dataSets.begin();
     8168         itr != _dataSets.end(); ++itr) {
     8169        if (!onlyVisible || itr->second->getVisibility()) {
     8170            double r[2];
     8171            itr->second->getVectorRange(r);
     8172            range[0] = min2(range[0], r[0]);
     8173            range[1] = max2(range[1], r[1]);
     8174        }
     8175    }
     8176    if (range[0] == DBL_MAX)
     8177        range[0] = 0;
     8178    if (range[1] == -DBL_MAX)
     8179        range[1] = 1;
     8180}
     8181
     8182/**
     8183 * \brief Collect cumulative data range of all DataSets
     8184 *
     8185 * \param[in,out] range Data range of all DataSets
     8186 * \param[in] onlyVisible Only collect range of visible DataSets
     8187 */
     8188void Renderer::collectVectorComponentRanges(double *range, int component, bool onlyVisible)
     8189{
     8190    range[0] = DBL_MAX;
     8191    range[1] = -DBL_MAX;
     8192
     8193    for (DataSetHashmap::iterator itr = _dataSets.begin();
     8194         itr != _dataSets.end(); ++itr) {
     8195        if (!onlyVisible || itr->second->getVisibility()) {
     8196            double r[2];
     8197            itr->second->getVectorRange(r, component);
     8198            range[0] = min2(range[0], r[0]);
     8199            range[1] = max2(range[1], r[1]);
     8200        }
     8201    }
     8202    if (range[0] == DBL_MAX)
     8203        range[0] = 0;
     8204    if (range[1] == -DBL_MAX)
     8205        range[1] = 1;
     8206 }
     8207
     8208/**
     8209 * \brief Determines if AABB lies in a principal axis plane
     8210 * and if so, returns the plane normal
     8211 */
     8212bool Renderer::is2D(const double bounds[6],
     8213                    Renderer::PrincipalPlane *plane,
     8214                    double *offset) const
     8215{
     8216    if (bounds[4] == bounds[5]) {
     8217        // Z = 0, XY plane
     8218        if (plane)
     8219            *plane = PLANE_XY;
     8220        if (offset)
     8221            *offset = bounds[4];
     8222        return true;
     8223    } else if (bounds[0] == bounds[1]) {
     8224        // X = 0, ZY plane
     8225        if (plane)
     8226            *plane = PLANE_ZY;
     8227        if (offset)
     8228            *offset = bounds[0];
     8229        return true;
     8230    } else if (bounds[2] == bounds[3]) {
     8231        // Y = 0, XZ plane
     8232        if (plane)
     8233            *plane = PLANE_XZ;
     8234        if (offset)
     8235            *offset = bounds[2];
     8236        return true;
     8237    }
     8238    *plane = PLANE_XY;
     8239    *offset = 0;
     8240    return false;
    74998241}
    75008242
     
    75218263    double bounds[6];
    75228264    collectBounds(bounds, false);
    7523     _imgWorldOrigin[0] = bounds[0];
    7524     _imgWorldOrigin[1] = bounds[2];
    7525     _imgWorldDims[0] = bounds[1] - bounds[0];
    7526     _imgWorldDims[1] = bounds[3] - bounds[2];
     8265    bool twod = is2D(bounds, &_imgCameraPlane, &_imgCameraOffset);
     8266    if (twod) {
     8267        _cameraMode = IMAGE;
     8268        if (_imgCameraPlane == PLANE_ZY) {
     8269            _imgWorldOrigin[0] = bounds[4];
     8270            _imgWorldOrigin[1] = bounds[2];
     8271            _imgWorldDims[0] = bounds[5] - bounds[4];
     8272            _imgWorldDims[1] = bounds[3] - bounds[2];
     8273        } else if (_imgCameraPlane == PLANE_XZ) {
     8274            _imgWorldOrigin[0] = bounds[0];
     8275            _imgWorldOrigin[1] = bounds[4];
     8276            _imgWorldDims[0] = bounds[1] - bounds[0];
     8277            _imgWorldDims[1] = bounds[5] - bounds[4];
     8278        } else {
     8279            _imgWorldOrigin[0] = bounds[0];
     8280            _imgWorldOrigin[1] = bounds[2];
     8281            _imgWorldDims[0] = bounds[1] - bounds[0];
     8282            _imgWorldDims[1] = bounds[3] - bounds[2];
     8283        }
     8284    } else {
     8285        _imgWorldOrigin[0] = bounds[0];
     8286        _imgWorldOrigin[1] = bounds[2];
     8287        _imgWorldDims[0] = bounds[1] - bounds[0];
     8288        _imgWorldDims[1] = bounds[3] - bounds[2];
     8289    }
     8290
    75278291    _cameraPan[0] = 0;
    75288292    _cameraPan[1] = 0;
     
    75388302    case ORTHO:
    75398303        _renderer->GetActiveCamera()->ParallelProjectionOn();
    7540         resetAxes();
     8304        resetAxes(bounds);
    75418305        _renderer->ResetCamera(bounds);
    75428306        //computeScreenWorldCoords();
     
    75448308    case PERSPECTIVE:
    75458309        _renderer->GetActiveCamera()->ParallelProjectionOff();
    7546         resetAxes();
     8310        resetAxes(bounds);
    75478311        _renderer->ResetCamera(bounds);
    75488312        //computeScreenWorldCoords();
     
    75518315        ERROR("Unknown camera mode");
    75528316    }
     8317
    75538318#ifdef WANT_TRACE
    75548319    printCameraInfo(_renderer->GetActiveCamera());
     
    75618326void Renderer::printCameraInfo(vtkCamera *camera)
    75628327{
    7563     TRACE("Parallel Scale: %g, View angle: %g, Cam pos: %g %g %g, focal pt: %g %g %g, view up: %g %g %g, Clipping range: %g %g",
     8328    TRACE("pscale: %g, angle: %g, d: %g pos: %g %g %g, fpt: %g %g %g, vup: %g %g %g, clip: %g %g",
    75648329          camera->GetParallelScale(),
    75658330          camera->GetViewAngle(),
     8331          camera->GetDistance(),
    75668332          camera->GetPosition()[0],
    75678333          camera->GetPosition()[1],
     
    75928358 * \brief Set the opacity of the specified DataSet's associated graphics objects
    75938359 */
    7594 void Renderer::setOpacity(const DataSetId& id, double opacity)
    7595 {
     8360void Renderer::setDataSetOpacity(const DataSetId& id, double opacity)
     8361{
     8362    DataSetHashmap::iterator itr;
     8363
     8364    bool doAll = false;
     8365
     8366    if (id.compare("all") == 0) {
     8367        itr = _dataSets.begin();
     8368        doAll = true;
     8369    } else {
     8370        itr = _dataSets.find(id);
     8371    }
     8372    if (itr == _dataSets.end()) {
     8373        ERROR("Unknown dataset %s", id.c_str());
     8374        return;
     8375    }
     8376
     8377    do {
     8378        itr->second->setOpacity(opacity);
     8379    } while (doAll && ++itr != _dataSets.end());
     8380
    75968381    if (id.compare("all") == 0 || getContour2D(id) != NULL)
    75978382        setContour2DOpacity(id, opacity);
     
    76148399    if (id.compare("all") == 0 || getVolume(id) != NULL)
    76158400        setVolumeOpacity(id, opacity);
     8401
     8402    _needsRedraw = true;
    76168403}
    76178404
     
    76198406 * \brief Turn on/off rendering of the specified DataSet's associated graphics objects
    76208407 */
    7621 void Renderer::setVisibility(const DataSetId& id, bool state)
     8408void Renderer::setDataSetVisibility(const DataSetId& id, bool state)
    76228409{
    76238410    DataSetHashmap::iterator itr;
     
    76608447    if (id.compare("all") == 0 || getVolume(id) != NULL)
    76618448        setVolumeVisibility(id, state);
     8449
     8450    _needsRedraw = true;
    76628451}
    76638452
     
    76658454 * \brief Toggle rendering of actors' bounding box
    76668455 */
    7667 void Renderer::showBounds(bool state)
    7668 {
    7669     if (state) {
    7670         ; // TODO: Add bounding box actor/mapper
    7671     } else {
    7672         ; // TODO: Remove bounding box actor/mapper
    7673     }
     8456void Renderer::setDataSetShowBounds(const DataSetId& id, bool state)
     8457{
     8458    DataSetHashmap::iterator itr;
     8459
     8460    bool doAll = false;
     8461
     8462    if (id.compare("all") == 0) {
     8463        itr = _dataSets.begin();
     8464        doAll = true;
     8465    } else {
     8466        itr = _dataSets.find(id);
     8467    }
     8468    if (itr == _dataSets.end()) {
     8469        ERROR("Unknown dataset %s", id.c_str());
     8470        return;
     8471    }
     8472
     8473    do {
     8474        if (!state && itr->second->getProp()) {
     8475            _renderer->RemoveViewProp(itr->second->getProp());
     8476        }
     8477
     8478        itr->second->showOutline(state);
     8479
     8480        if (state && !_renderer->HasViewProp(itr->second->getProp())) {
     8481            _renderer->AddViewProp(itr->second->getProp());
     8482        }
     8483    } while (doAll && ++itr != _dataSets.end());
     8484
     8485    initCamera();
     8486    _needsRedraw = true;
     8487}
     8488
     8489/**
     8490 * \brief Set color of outline bounding box
     8491 */
     8492void Renderer::setDataSetOutlineColor(const DataSetId& id, float color[3])
     8493{
     8494    DataSetHashmap::iterator itr;
     8495
     8496    bool doAll = false;
     8497
     8498    if (id.compare("all") == 0) {
     8499        itr = _dataSets.begin();
     8500        doAll = true;
     8501    } else {
     8502        itr = _dataSets.find(id);
     8503    }
     8504    if (itr == _dataSets.end()) {
     8505        ERROR("Unknown dataset %s", id.c_str());
     8506        return;
     8507    }
     8508
     8509    do {
     8510        itr->second->setOutlineColor(color);
     8511    } while (doAll && ++itr != _dataSets.end());
     8512
     8513    _needsRedraw = true;
    76748514}
    76758515
     
    79508790 * Note: no interpolation is performed on data
    79518791 */
    7952 double Renderer::getDataValueAtPixel(const DataSetId& id, int x, int y)
     8792bool Renderer::getScalarValueAtPixel(const DataSetId& id, int x, int y, double *value)
    79538793{
    79548794    vtkSmartPointer<vtkCoordinate> coord = vtkSmartPointer<vtkCoordinate>::New();
    79558795    coord->SetCoordinateSystemToDisplay();
    7956     coord->SetValue(x, y, 0);
     8796    coord->SetValue(x, _windowHeight - y, 0);
    79578797    double *worldCoords = coord->GetComputedWorldValue(_renderer);
    79588798
    7959     TRACE("Pixel coords: %d, %d\nWorld coords: %.12e, %.12e, %12e", x, y,
     8799    TRACE("Pixel coords: %d, %d\nWorld coords: %g, %g, %g", x, y,
    79608800          worldCoords[0],
    79618801          worldCoords[1],
    79628802          worldCoords[2]);
    79638803
    7964     return getDataValue(id, worldCoords[0], worldCoords[1], worldCoords[2]);
     8804    return getScalarValue(id, worldCoords[0], worldCoords[1], worldCoords[2], value);
    79658805}
    79668806
     
    79708810 * Note: no interpolation is performed on data
    79718811 */
    7972 double Renderer::getDataValue(const DataSetId& id, double x, double y, double z)
     8812bool Renderer::getScalarValue(const DataSetId& id, double x, double y, double z, double *value)
    79738813{
    79748814    DataSet *ds = getDataSet(id);
    79758815    if (ds == NULL)
    7976         return 0;
    7977     vtkDataSet *vtkds = ds->getVtkDataSet();
    7978     vtkIdType pt = vtkds->FindPoint(x, y, z);
    7979     return vtkds->GetPointData()->GetScalars()->GetComponent(pt, 0);
    7980 }
     8816        return false;
     8817
     8818    return ds->getScalarValue(x, y, z, value);
     8819}
     8820
     8821/**
     8822 * \brief Get nearest data value given display coordinates x,y
     8823 *
     8824 * Note: no interpolation is performed on data
     8825 */
     8826bool Renderer::getVectorValueAtPixel(const DataSetId& id, int x, int y, double vector[3])
     8827{
     8828    vtkSmartPointer<vtkCoordinate> coord = vtkSmartPointer<vtkCoordinate>::New();
     8829    coord->SetCoordinateSystemToDisplay();
     8830    coord->SetValue(x, _windowHeight - y, 0);
     8831    double *worldCoords = coord->GetComputedWorldValue(_renderer);
     8832
     8833    TRACE("Pixel coords: %d, %d\nWorld coords: %g, %g, %g", x, y,
     8834          worldCoords[0],
     8835          worldCoords[1],
     8836          worldCoords[2]);
     8837
     8838    return getVectorValue(id, worldCoords[0], worldCoords[1], worldCoords[2], vector);
     8839}
     8840
     8841/**
     8842 * \brief Get nearest data value given world coordinates x,y,z
     8843 *
     8844 * Note: no interpolation is performed on data
     8845 */
     8846bool Renderer::getVectorValue(const DataSetId& id, double x, double y, double z, double vector[3])
     8847{
     8848    DataSet *ds = getDataSet(id);
     8849    if (ds == NULL)
     8850        return false;
     8851
     8852    return ds->getVectorValue(x, y, z, vector);
     8853}
  • branches/blt4/packages/vizservers/vtkvis/RpVtkRenderer.h

    r2409 r2542  
    1212#include <vtkCubeAxesActor.h>
    1313#ifdef USE_CUSTOM_AXES
    14 #include <vtkRpCubeAxesActor2D.h>
     14#include "vtkRpCubeAxesActor2D.h"
    1515#else
    1616#include <vtkCubeAxesActor2D.h>
     
    6161    };
    6262
     63    enum PrincipalPlane {
     64        PLANE_XY,
     65        PLANE_ZY,
     66        PLANE_XZ
     67    };
     68
    6369    enum AxesFlyMode {
    6470        FLY_OUTER_EDGES = 0,
     
    7985        ORTHO,
    8086        IMAGE
     87    };
     88
     89    enum LegendType {
     90        ACTIVE_SCALAR,
     91        ACTIVE_VECTOR_MAGNITUDE,
     92        ACTIVE_VECTOR_X,
     93        ACTIVE_VECTOR_Y,
     94        ACTIVE_VECTOR_Z
    8195    };
    8296
     
    104118    DataSet *getDataSet(const DataSetId& id);
    105119
     120    void getDataSetNames(std::vector<std::string>& names);
     121
    106122    bool setData(const DataSetId& id, char *data, int nbytes);
    107123
     
    112128    bool setDataSetActiveVectors(const DataSetId& id, const char *vectorName);
    113129
    114     double getDataValueAtPixel(const DataSetId& id, int x, int y);
    115 
    116     double getDataValue(const DataSetId& id, double x, double y, double z);
    117 
    118     void setOpacity(const DataSetId& id, double opacity);
    119 
    120     void setVisibility(const DataSetId& id, bool state);
     130    bool getScalarValueAtPixel(const DataSetId& id, int x, int y, double *value);
     131
     132    bool getScalarValue(const DataSetId& id, double x, double y, double z, double *value);
     133
     134    bool getVectorValueAtPixel(const DataSetId& id, int x, int y, double vector[3]);
     135
     136    bool getVectorValue(const DataSetId& id, double x, double y, double z, double vector[3]);
     137
     138    void setDataSetShowBounds(const DataSetId& id, bool state);
     139
     140    void setDataSetOutlineColor(const DataSetId& id, float color[3]);
     141
     142    void setDataSetOpacity(const DataSetId& id, double opacity);
     143
     144    void setDataSetVisibility(const DataSetId& id, bool state);
    121145
    122146    void setUseCumulativeDataRange(bool state, bool onlyVisible = false);
     
    148172    void resetCameraClippingRange();
    149173
     174    void setCameraZoomRegionPixels(int x, int y, int width, int height);
     175
    150176    void setCameraZoomRegion(double x, double y, double width, double height);
    151177
     
    174200    void setBackgroundColor(float color[3]);
    175201
    176     void showBounds(bool state);
    177 
    178202    void setClipPlane(Axis axis, double ratio, int direction);
    179203
     
    226250    bool renderColorMap(const ColorMapId& id,
    227251                        const DataSetId& dataSetID,
    228                         const char *title,
     252                        LegendType legendType,
     253                        std::string& title,
     254                        double range[2],
    229255                        int width, int height,
     256                        int numLabels,
    230257                        vtkUnsignedCharArray *imgData);
    231258
    232259    // 2D Contour plots
    233260
    234     void addContour2D(const DataSetId& id);
     261    bool addContour2D(const DataSetId& id, int numContours);
     262
     263    bool addContour2D(const DataSetId& id, const std::vector<double>& contours);
    235264
    236265    void deleteContour2D(const DataSetId& id);
     
    248277    void setContour2DScale(const DataSetId& id, double scale[3]);
    249278
    250     void setContour2DEdgeColor(const DataSetId& id, float color[3]);
     279    void setContour2DColor(const DataSetId& id, float color[3]);
    251280
    252281    void setContour2DEdgeWidth(const DataSetId& id, float edgeWidth);
     
    264293    // 3D Contour (isosurface) plots
    265294
    266     void addContour3D(const DataSetId& id);
     295    bool addContour3D(const DataSetId& id, int numContours);
     296
     297    bool addContour3D(const DataSetId& id, const std::vector<double>& contours);
    267298
    268299    void deleteContour3D(const DataSetId& id);
     
    304335    // Glyphs
    305336
    306     void addGlyphs(const DataSetId& id);
     337    bool addGlyphs(const DataSetId& id, Glyphs::GlyphShape shape);
    307338
    308339    void deleteGlyphs(const DataSetId& id);
     
    344375    void setGlyphsScalingMode(const DataSetId& id, Glyphs::ScalingMode mode);
    345376
     377    void setGlyphsNormalizeScale(const DataSetId& id, bool normalize);
     378
    346379    void setGlyphsScaleFactor(const DataSetId& id, double scale);
    347380
    348381    // Height maps
    349382
    350     void addHeightMap(const DataSetId& id);
     383    bool addHeightMap(const DataSetId& id, int numContours, double heightScale);
     384
     385    bool addHeightMap(const DataSetId& id, const std::vector<double>& contours, double heightScale);
    351386
    352387    void deleteHeightMap(const DataSetId& id);
     
    376411    void setHeightMapVisibility(const DataSetId& id, bool state);
    377412
     413    void setHeightMapWireframe(const DataSetId& id, bool state);
     414
    378415    void setHeightMapVolumeSlice(const DataSetId& id, HeightMap::Axis axis, double ratio);
    379416
     
    382419    void setHeightMapColorMap(const DataSetId& id, const ColorMapId& colorMapId);
    383420
    384     void setHeightMapContours(const DataSetId& id, int numContours);
     421    void setHeightMapNumContours(const DataSetId& id, int numContours);
    385422
    386423    void setHeightMapContourList(const DataSetId& id, const std::vector<double>& contours);
    387424
    388     void setHeightMapContourVisibility(const DataSetId& id, bool state);
     425    void setHeightMapContourSurfaceVisibility(const DataSetId& id, bool state);
     426
     427    void setHeightMapContourLineVisibility(const DataSetId& id, bool state);
    389428
    390429    void setHeightMapContourEdgeColor(const DataSetId& id, float color[3]);
     
    394433    // LIC plots
    395434
    396     void addLIC(const DataSetId& id);
     435    bool addLIC(const DataSetId& id);
    397436   
    398437    void deleteLIC(const DataSetId& id);
     
    428467    // Molecules
    429468
    430     void addMolecule(const DataSetId& id);
     469    bool addMolecule(const DataSetId& id);
    431470   
    432471    void deleteMolecule(const DataSetId& id);
     
    468507    // PolyData Meshes
    469508
    470     void addPolyData(const DataSetId& id);
     509    bool addPolyData(const DataSetId& id);
    471510   
    472511    void deletePolyData(const DataSetId& id);
     
    492531    void setPolyDataEdgeWidth(const DataSetId& id, float edgeWidth);
    493532
     533    void setPolyDataPointSize(const DataSetId& id, float size);
     534
    494535    void setPolyDataLighting(const DataSetId& id, bool state);
    495536
     
    500541    void setPolyDataWireframe(const DataSetId& id, bool state);
    501542
    502 
    503543    // Color-mapped surfaces
    504544
    505     void addPseudoColor(const DataSetId& id);
     545    bool addPseudoColor(const DataSetId& id);
    506546
    507547    void deletePseudoColor(const DataSetId& id);
     
    519559    void setPseudoColorScale(const DataSetId& id, double scale[3]);
    520560
     561    void setPseudoColorColor(const DataSetId& id, float color[3]);
     562
    521563    void setPseudoColorEdgeVisibility(const DataSetId& id, bool state);
    522564
     
    535577    void setPseudoColorColorMap(const DataSetId& id, const ColorMapId& colorMapId);
    536578
     579    void setPseudoColorColorMode(const DataSetId& id, PseudoColor::ColorMode mode);
     580
    537581    // Streamlines
    538582
    539     void addStreamlines(const DataSetId& id);
     583    bool addStreamlines(const DataSetId& id);
    540584
    541585    void deleteStreamlines(const DataSetId& id);
     
    606650    // Volumes
    607651
    608     void addVolume(const DataSetId& id);
     652    bool addVolume(const DataSetId& id);
    609653
    610654    void deleteVolume(const DataSetId& id);
     
    650694    void collectBounds(double *bounds, bool onlyVisible);
    651695
    652     void collectDataRanges(double *range, bool onlyVisible);
    653 
    654     void updateRanges(bool useCumulative);
     696    void collectDataRanges();
     697
     698    void collectScalarRanges(double *range, bool onlyVisible);
     699
     700    void collectVectorMagnitudeRanges(double *range, bool onlyVisible);
     701
     702    void collectVectorComponentRanges(double *range, int component, bool onlyVisible);
     703
     704    void updateRanges();
     705
     706    void updateColorMap(ColorMap *cmap);
     707
     708    bool colorMapUsed(ColorMap *cmap);
    655709
    656710    void setCameraFromMatrix(vtkCamera *camera, vtkMatrix4x4 &mat);
     
    662716    void computeScreenWorldCoords();
    663717
     718    bool is2D(const double bounds[6],
     719              PrincipalPlane *plane,
     720              double *offset) const;
    664721    void initCamera();
    665722    void initAxes();
    666     void resetAxes();
     723    void resetAxes(double bounds[6] = NULL);
    667724    void setCameraClippingPlanes();
    668725
     
    671728    double _imgWorldOrigin[2];
    672729    double _imgWorldDims[2];
     730    PrincipalPlane _imgCameraPlane;
     731    double _imgCameraOffset;
    673732    double _screenWorldCoords[4];
    674733    double _cameraOrientation[4];
     
    678737    bool _useCumulativeRange;
    679738    bool _cumulativeRangeOnlyVisible;
    680     double _cumulativeDataRange[2];
     739    double _cumulativeScalarRange[2];
     740    double _cumulativeVectorMagnitudeRange[2];
     741    double _cumulativeVectorComponentRange[3][2];
    681742
    682743    ColorMapHashmap _colorMaps;
  • branches/blt4/packages/vizservers/vtkvis/RpVtkRendererCmd.cpp

    r2409 r2542  
    1010#include <cstring>
    1111#include <cerrno>
     12#include <string>
     13#include <sstream>
    1214#include <unistd.h>
    1315#include <sys/uio.h>
     
    2123#include "PPMWriter.h"
    2224#include "TGAWriter.h"
     25#ifdef USE_THREADS
     26#include "ResponseQueue.h"
     27#endif
    2328
    2429using namespace Rappture::VtkVis;
    2530
     31static int lastCmdStatus;
     32
     33#ifdef USE_THREADS
     34static void
     35QueueResponse(ClientData clientData, const void *bytes, size_t len,
     36              Response::AllocationType allocType)
     37{
     38    ResponseQueue *queue = (ResponseQueue *)clientData;
     39
     40    Response *response;
     41
     42    response = new Response(Response::DATA);
     43    response->setMessage((unsigned char *)bytes, len, allocType);
     44    queue->enqueue(response);
     45}
     46#else
     47
     48static ssize_t
     49SocketWrite(const void *bytes, size_t len)
     50{
     51    size_t ofs = 0;
     52    ssize_t bytesWritten;
     53    while ((bytesWritten = write(g_fdOut, (const char *)bytes + ofs, len - ofs)) > 0) {
     54        ofs += bytesWritten;
     55        if (ofs == len)
     56            break;
     57    }
     58    if (bytesWritten < 0) {
     59        ERROR("write: %s", strerror(errno));
     60    }
     61    return bytesWritten;
     62}
     63
     64#endif  /*USE_THREADS*/
     65
    2666static int
    2767ExecuteCommand(Tcl_Interp *interp, Tcl_DString *dsPtr)
     
    2969    int result;
    3070
    31     result = Tcl_Eval(interp, Tcl_DStringValue(dsPtr));
     71    TRACE("command: '%s'", Tcl_DStringValue(dsPtr));
     72    lastCmdStatus = TCL_OK;
     73    result = Tcl_EvalEx(interp, Tcl_DStringValue(dsPtr),
     74                        Tcl_DStringLength(dsPtr),
     75                        TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL);
    3276    Tcl_DStringSetLength(dsPtr, 0);
    33 
     77    if (lastCmdStatus == TCL_BREAK) {
     78        return TCL_BREAK;
     79    }
     80    lastCmdStatus = result;
    3481    return result;
    3582}
    3683
    37 static bool
     84static int
    3885GetBooleanFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, bool *boolPtr)
    3986{
     
    4794}
    4895
    49 int
     96static int
    5097GetFloatFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, float *valuePtr)
    5198{
     
    324371
    325372    char buf[256];
    326     snprintf(buf, sizeof(buf), "nv>camera set %.12e %.12e %.12e %.12e %.12e %.12e %.12e %.12e %.12e",
     373    snprintf(buf, sizeof(buf), "nv>camera set %.12e %.12e %.12e %.12e %.12e %.12e %.12e %.12e %.12e\n",
    327374             pos[0], pos[1], pos[2], focalPt[0], focalPt[1], focalPt[2], viewUp[0], viewUp[1], viewUp[2]);
    328     ssize_t bytesWritten;
    329     size_t len = strlen(buf);
    330     size_t ofs = 0;
    331     while ((bytesWritten = write(g_fdOut, buf + ofs, len - ofs)) > 0) {
    332         ofs += bytesWritten;
    333         if (ofs == len)
    334             break;
    335     }
     375
     376#ifdef USE_THREADS
     377    QueueResponse(clientData, buf, strlen(buf), Response::VOLATILE);
     378#else
     379    ssize_t bytesWritten = SocketWrite(buf, strlen(buf));
    336380    if (bytesWritten < 0) {
    337381        return TCL_ERROR;
    338382    }
     383#endif
    339384    return TCL_OK;
    340385}
     
    361406              Tcl_Obj *const *objv)
    362407{
    363     double x, y, width, height;
    364 
    365     if (Tcl_GetDoubleFromObj(interp, objv[2], &x) != TCL_OK ||
    366         Tcl_GetDoubleFromObj(interp, objv[3], &y) != TCL_OK ||
    367         Tcl_GetDoubleFromObj(interp, objv[4], &width) != TCL_OK ||
    368         Tcl_GetDoubleFromObj(interp, objv[5], &height) != TCL_OK) {
    369         return TCL_ERROR;
    370     }
    371 
    372     g_renderer->setCameraZoomRegion(x, y, width, height);
     408    const char *string = Tcl_GetString(objv[2]);
     409
     410    if (string[0] == 'p' && strcmp(string, "pixel") == 0) {
     411        int x, y, width, height;
     412        if (Tcl_GetIntFromObj(interp, objv[3], &x) != TCL_OK ||
     413            Tcl_GetIntFromObj(interp, objv[4], &y) != TCL_OK ||
     414            Tcl_GetIntFromObj(interp, objv[5], &width) != TCL_OK ||
     415            Tcl_GetIntFromObj(interp, objv[6], &height) != TCL_OK) {
     416            return TCL_ERROR;
     417        }
     418        g_renderer->setCameraZoomRegionPixels(x, y, width, height);
     419    } else if (string[0] == 'w' && strcmp(string, "world") == 0) {
     420        double x, y, width, height;
     421        if (Tcl_GetDoubleFromObj(interp, objv[3], &x) != TCL_OK ||
     422            Tcl_GetDoubleFromObj(interp, objv[4], &y) != TCL_OK ||
     423            Tcl_GetDoubleFromObj(interp, objv[5], &width) != TCL_OK ||
     424            Tcl_GetDoubleFromObj(interp, objv[6], &height) != TCL_OK) {
     425            return TCL_ERROR;
     426        }
     427        g_renderer->setCameraZoomRegion(x, y, width, height);
     428    } else {
     429        Tcl_AppendResult(interp, "bad camera ortho option \"", string,
     430                         "\": should be pixel or world", (char*)NULL);
     431        return TCL_ERROR;
     432    }
     433
    373434    return TCL_OK;
    374435}
     
    466527    {"mode", 1, CameraModeOp, 3, 3, "mode"},
    467528    {"orient", 3, CameraOrientOp, 6, 6, "qw qx qy qz"},
    468     {"ortho", 1, CameraOrthoOp, 6, 6, "x y width height"},
     529    {"ortho", 1, CameraOrthoOp, 7, 7, "coordMode x y width height"},
    469530    {"pan", 1, CameraPanOp, 4, 4, "panX panY"},
    470531    {"reset", 2, CameraResetOp, 2, 3, "?all?"},
     
    625686    if (objc == 5) {
    626687        const char *name = Tcl_GetString(objv[4]);
    627         g_renderer->addContour2D(name);
    628         g_renderer->setContour2DContourList(name, contourList);
    629     } else {
    630         g_renderer->addContour2D("all");
    631         g_renderer->setContour2DContourList("all", contourList);
     688        if (!g_renderer->addContour2D(name, contourList)) {
     689            Tcl_AppendResult(interp, "Failed to create contour2d", (char*)NULL);
     690            return TCL_ERROR;
     691        }
     692    } else {
     693        if (!g_renderer->addContour2D("all", contourList)) {
     694            Tcl_AppendResult(interp, "Failed to create contour2d for one or more data sets", (char*)NULL);
     695            return TCL_ERROR;
     696        }
    632697    }
    633698    return TCL_OK;
     
    644709    if (objc == 5) {
    645710        const char *name = Tcl_GetString(objv[4]);
    646         g_renderer->addContour2D(name);
    647         g_renderer->setContour2DContours(name, numContours);
    648     } else {
    649         g_renderer->addContour2D("all");
    650         g_renderer->setContour2DContours("all", numContours);
     711        if (!g_renderer->addContour2D(name, numContours)) {
     712            Tcl_AppendResult(interp, "Failed to create contour2d", (char*)NULL);
     713            return TCL_ERROR;
     714        }
     715    } else {
     716       if (!g_renderer->addContour2D("all", numContours)) {
     717            Tcl_AppendResult(interp, "Failed to create contour2d for one or more data sets", (char*)NULL);
     718            return TCL_ERROR;
     719       }
    651720    }
    652721    return TCL_OK;
     
    715784    if (objc == 6) {
    716785        const char *name = Tcl_GetString(objv[5]);
    717         g_renderer->setContour2DEdgeColor(name, color);
    718     } else {
    719         g_renderer->setContour2DEdgeColor("all", color);
     786        g_renderer->setContour2DColor(name, color);
     787    } else {
     788        g_renderer->setContour2DColor("all", color);
    720789    }
    721790    return TCL_OK;
     
    833902static Rappture::CmdSpec contour2dOps[] = {
    834903    {"add",       1, Contour2DAddOp, 4, 5, "oper value ?dataSetName?"},
     904    {"color",     1, Contour2DLineColorOp, 5, 6, "r g b ?dataSetName?"},
    835905    {"delete",    1, Contour2DDeleteOp, 2, 3, "?dataSetName?"},
    836906    {"lighting",  3, Contour2DLightingOp, 3, 4, "bool ?dataSetName?"},
     
    882952    if (objc == 5) {
    883953        const char *name = Tcl_GetString(objv[4]);
    884         g_renderer->addContour3D(name);
    885         g_renderer->setContour3DContourList(name, contourList);
    886     } else {
    887         g_renderer->addContour3D("all");
    888         g_renderer->setContour3DContourList("all", contourList);
     954        if (!g_renderer->addContour3D(name, contourList)) {
     955            Tcl_AppendResult(interp, "Failed to create contour3d", (char*)NULL);
     956            return TCL_ERROR;
     957        }
     958    } else {
     959        if (!g_renderer->addContour3D("all", contourList)) {
     960            Tcl_AppendResult(interp, "Failed to create contour3d for one or more data sets", (char*)NULL);
     961            return TCL_ERROR;
     962        }
    889963    }
    890964    return TCL_OK;
     
    901975    if (objc == 5) {
    902976        const char *name = Tcl_GetString(objv[4]);
    903         g_renderer->addContour3D(name);
    904         g_renderer->setContour3DContours(name, numContours);
    905     } else {
    906         g_renderer->addContour3D("all");
    907         g_renderer->setContour3DContours("all", numContours);
     977        if (!g_renderer->addContour3D(name, numContours)) {
     978            Tcl_AppendResult(interp, "Failed to create contour3d", (char*)NULL);
     979            return TCL_ERROR;
     980        }
     981    } else {
     982        if (!g_renderer->addContour3D("all", numContours)) {
     983            Tcl_AppendResult(interp, "Failed to create contour3d for one or more data sets", (char*)NULL);
     984            return TCL_ERROR;
     985        }
    908986    }
    909987    return TCL_OK;
     
    12561334    }
    12571335    char *data = (char *)malloc(nbytes);
    1258 #ifdef notdef
    1259     size_t ofs = 0;
    1260     ssize_t bytesRead = 0;
    1261     while ((bytesRead = read(g_fdIn, data + ofs, nbytes - ofs)) > 0) {
    1262         ofs += bytesRead;
    1263         if (ofs == nbytes)
    1264             break;
    1265     }
    1266     TRACE("bytesRead: %d", ofs);
    1267     if (bytesRead < 0) {
    1268         free(data);
    1269         return TCL_ERROR;
    1270     }
    1271 #else
    12721336    size_t bytesRead = fread(data, 1, nbytes, g_fIn);
    1273     TRACE("bytesRead: %d '%c'", bytesRead, data[0]);
     1337    TRACE("bytesRead: %d", bytesRead);
    12741338    if (bytesRead < (size_t)nbytes) {
    12751339        free(data);
    12761340        return TCL_ERROR;
    12771341    }
    1278 #endif
    12791342    g_renderer->addDataSet(name);
    12801343    g_renderer->setData(name, data, nbytes);
     
    12981361
    12991362static int
    1300 DataSetGetValuePixelOp(ClientData clientData, Tcl_Interp *interp, int objc,
    1301                        Tcl_Obj *const *objv)
     1363DataSetGetScalarPixelOp(ClientData clientData, Tcl_Interp *interp, int objc,
     1364                        Tcl_Obj *const *objv)
    13021365{
    13031366    const char *name = Tcl_GetString(objv[5]);
     
    13071370        return TCL_ERROR;
    13081371    }
    1309     double value = g_renderer->getDataValueAtPixel(name, x, y);
    1310     char buf[128];
    1311     snprintf(buf, sizeof(buf), "nv>dataset value pixel %d %d %.12e", x, y, value);
    1312     ssize_t bytesWritten;
    1313     size_t len = strlen(buf);
    1314     size_t ofs = 0;
    1315     while ((bytesWritten = write(g_fdOut, buf + ofs, len - ofs)) > 0) {
    1316         ofs += bytesWritten;
    1317         if (ofs == len)
    1318             break;
    1319     }
     1372    double value;
     1373    if (!g_renderer->getScalarValueAtPixel(name, x, y, &value)) {
     1374        Tcl_AppendResult(interp, "Pixel out of dataset bounds or no scalar data available", (char*)NULL);
     1375        return TCL_ERROR;
     1376    }
     1377
     1378    char buf[256];
     1379    int length;
     1380
     1381    length = snprintf(buf, sizeof(buf), "nv>dataset scalar pixel %d %d %g %s\n",
     1382        x, y, value, name);
     1383
     1384#ifdef USE_THREADS
     1385    QueueResponse(clientData, buf, length, Response::VOLATILE);
     1386#else
     1387    ssize_t bytesWritten = SocketWrite(buf, length);
     1388
    13201389    if (bytesWritten < 0) {
    13211390        return TCL_ERROR;
    13221391    }
    1323     return TCL_OK;
    1324 }
    1325 
    1326 static int
    1327 DataSetGetValueWorldOp(ClientData clientData, Tcl_Interp *interp, int objc,
    1328                        Tcl_Obj *const *objv)
     1392#endif
     1393    return TCL_OK;
     1394}
     1395
     1396static int
     1397DataSetGetScalarWorldOp(ClientData clientData, Tcl_Interp *interp, int objc,
     1398                        Tcl_Obj *const *objv)
    13291399{
    13301400    const char *name = Tcl_GetString(objv[6]);
     
    13351405        return TCL_ERROR;
    13361406    }
    1337     double value = g_renderer->getDataValue(name, x, y, z);
    1338     char buf[128];
    1339     snprintf(buf, sizeof(buf), "nv>dataset value world %.12e %.12e %.12e %.12e", x, y, z, value);
    1340     ssize_t bytesWritten;
    1341     size_t len = strlen(buf);
    1342     size_t ofs = 0;
    1343     while ((bytesWritten = write(g_fdOut, buf + ofs, len - ofs)) > 0) {
    1344         ofs += bytesWritten;
    1345         if (ofs == len)
    1346             break;
    1347     }
     1407    double value;
     1408    if (!g_renderer->getScalarValue(name, x, y, z, &value)) {
     1409        Tcl_AppendResult(interp, "Coordinate out of dataset bounds or no scalar data available", (char*)NULL);
     1410        return TCL_ERROR;
     1411    }
     1412
     1413    char buf[256];
     1414    int length;
     1415
     1416    length = snprintf(buf, sizeof(buf),
     1417        "nv>dataset scalar world %g %g %g %g %s\n", x, y, z, value, name);
     1418
     1419#ifdef USE_THREADS
     1420    QueueResponse(clientData, buf, length, Response::VOLATILE);
     1421#else
     1422    ssize_t bytesWritten = SocketWrite(buf, length);
    13481423    if (bytesWritten < 0) {
    13491424        return TCL_ERROR;
    13501425    }
    1351     return TCL_OK;
    1352 }
    1353 
    1354 static Rappture::CmdSpec dataSetGetValueOps[] = {
    1355     {"pixel", 1, DataSetGetValuePixelOp, 6, 6, "x y dataSetName"},
    1356     {"world", 1, DataSetGetValueWorldOp, 7, 7, "x y z dataSetName"}
     1426#endif
     1427    return TCL_OK;
     1428}
     1429
     1430static Rappture::CmdSpec dataSetGetScalarOps[] = {
     1431    {"pixel", 1, DataSetGetScalarPixelOp, 6, 6, "x y dataSetName"},
     1432    {"world", 1, DataSetGetScalarWorldOp, 7, 7, "x y z dataSetName"}
    13571433};
    1358 static int nDataSetGetValueOps = NumCmdSpecs(dataSetGetValueOps);
    1359 
    1360 static int
    1361 DataSetGetValueOp(ClientData clientData, Tcl_Interp *interp, int objc,
    1362                   Tcl_Obj *const *objv)
     1434static int nDataSetGetScalarOps = NumCmdSpecs(dataSetGetScalarOps);
     1435
     1436static int
     1437DataSetGetScalarOp(ClientData clientData, Tcl_Interp *interp, int objc,
     1438                   Tcl_Obj *const *objv)
    13631439{
    13641440    Tcl_ObjCmdProc *proc;
    13651441
    1366     proc = Rappture::GetOpFromObj(interp, nDataSetGetValueOps, dataSetGetValueOps,
     1442    proc = Rappture::GetOpFromObj(interp, nDataSetGetScalarOps, dataSetGetScalarOps,
    13671443                                  Rappture::CMDSPEC_ARG2, objc, objv, 0);
    13681444    if (proc == NULL) {
     
    13731449
    13741450static int
    1375 DataSetOpacityOp(ClientData clientData, Tcl_Interp *interp, int objc,
    1376                  Tcl_Obj *const *objv)
    1377 {
    1378     double opacity;
    1379     if (Tcl_GetDoubleFromObj(interp, objv[2], &opacity) != TCL_OK) {
    1380         return TCL_ERROR;
    1381     }
    1382     if (objc == 4) {
    1383         const char *name = Tcl_GetString(objv[3]);
    1384         g_renderer->setOpacity(name, opacity);
    1385     } else {
    1386         g_renderer->setOpacity("all", opacity);
    1387     }
    1388     return TCL_OK;
     1451DataSetGetVectorPixelOp(ClientData clientData, Tcl_Interp *interp, int objc,
     1452                        Tcl_Obj *const *objv)
     1453{
     1454    const char *name = Tcl_GetString(objv[5]);
     1455    int x, y;
     1456    if (Tcl_GetIntFromObj(interp, objv[3], &x) != TCL_OK ||
     1457        Tcl_GetIntFromObj(interp, objv[4], &y) != TCL_OK) {
     1458        return TCL_ERROR;
     1459    }
     1460    double value[3];
     1461    if (!g_renderer->getVectorValueAtPixel(name, x, y, value)) {
     1462        Tcl_AppendResult(interp, "Pixel out of dataset bounds or no vector data available", (char*)NULL);
     1463        return TCL_ERROR;
     1464    }
     1465
     1466    char buf[256];
     1467    int length;
     1468    length = snprintf(buf, sizeof(buf),
     1469        "nv>dataset vector pixel %d %d %g %g %g %s\n", x, y, value[0],
     1470        value[1], value[2], name);
     1471
     1472#ifdef USE_THREADS
     1473    QueueResponse(clientData, buf, length, Response::VOLATILE);
     1474#else
     1475    ssize_t bytesWritten = SocketWrite(buf, length);
     1476
     1477    if (bytesWritten < 0) {
     1478        return TCL_ERROR;
     1479    }
     1480#endif /*USE_THREADS*/
     1481    return TCL_OK;
     1482}
     1483
     1484static int
     1485DataSetGetVectorWorldOp(ClientData clientData, Tcl_Interp *interp, int objc,
     1486                        Tcl_Obj *const *objv)
     1487{
     1488    const char *name = Tcl_GetString(objv[6]);
     1489    double x, y, z;
     1490    if (Tcl_GetDoubleFromObj(interp, objv[3], &x) != TCL_OK ||
     1491        Tcl_GetDoubleFromObj(interp, objv[4], &y) != TCL_OK ||
     1492        Tcl_GetDoubleFromObj(interp, objv[5], &z) != TCL_OK) {
     1493        return TCL_ERROR;
     1494    }
     1495    double value[3];
     1496    if (!g_renderer->getVectorValue(name, x, y, z, value)) {
     1497        Tcl_AppendResult(interp, "Coordinate out of dataset bounds or no vector data available", (char*)NULL);
     1498        return TCL_ERROR;
     1499    }
     1500
     1501    char buf[256];
     1502    int length;
     1503    length = snprintf(buf, sizeof(buf),
     1504        "nv>dataset vector world %g %g %g %g %g %g %s\n", x, y, z,
     1505        value[0], value[1], value[2], name);
     1506#ifdef USE_THREADS
     1507    QueueResponse(clientData, buf, length, Response::VOLATILE);
     1508#else
     1509    ssize_t bytesWritten = SocketWrite(buf, length);
     1510
     1511    if (bytesWritten < 0) {
     1512        return TCL_ERROR;
     1513    }
     1514#endif /*USE_THREADS*/
     1515    return TCL_OK;
     1516}
     1517
     1518static Rappture::CmdSpec dataSetGetVectorOps[] = {
     1519    {"pixel", 1, DataSetGetVectorPixelOp, 6, 6, "x y dataSetName"},
     1520    {"world", 1, DataSetGetVectorWorldOp, 7, 7, "x y z dataSetName"}
     1521};
     1522static int nDataSetGetVectorOps = NumCmdSpecs(dataSetGetVectorOps);
     1523
     1524static int
     1525DataSetGetVectorOp(ClientData clientData, Tcl_Interp *interp, int objc,
     1526                   Tcl_Obj *const *objv)
     1527{
     1528    Tcl_ObjCmdProc *proc;
     1529
     1530    proc = Rappture::GetOpFromObj(interp, nDataSetGetVectorOps, dataSetGetVectorOps,
     1531                                  Rappture::CMDSPEC_ARG2, objc, objv, 0);
     1532    if (proc == NULL) {
     1533        return TCL_ERROR;
     1534    }
     1535    return (*proc) (clientData, interp, objc, objv);
    13891536}
    13901537
     
    14011548        g_renderer->setUseCumulativeDataRange(false);
    14021549    } else {
    1403         return TCL_ERROR;
     1550        Tcl_AppendResult(interp, "bad maprange option \"", value,
     1551                         "\": should be all, visible, or separate", (char*)NULL);
     1552        return TCL_ERROR;
     1553    }
     1554    return TCL_OK;
     1555}
     1556
     1557static int
     1558DataSetNamesOp(ClientData clientData, Tcl_Interp *interp, int objc,
     1559               Tcl_Obj *const *objv)
     1560{
     1561    std::vector<std::string> dataSets;
     1562    g_renderer->getDataSetNames(dataSets);
     1563    std::ostringstream oss;
     1564    size_t len = 0;
     1565    oss << "nv>dataset names {";
     1566    len += 18;
     1567    for (size_t i = 0; i < dataSets.size(); i++) {
     1568        oss << "\"" << dataSets[i] << "\"";
     1569        len += 2 + dataSets[i].length();
     1570        if (i < dataSets.size() - 1) {
     1571            oss << " ";
     1572            len++;
     1573        }
     1574    }
     1575    oss << "}\n";
     1576    len += 2;
     1577#ifdef USE_THREADS
     1578    QueueResponse(clientData, oss.str().c_str(), len, Response::VOLATILE);
     1579#else
     1580    ssize_t bytesWritten = SocketWrite(oss.str().c_str(), len);
     1581
     1582    if (bytesWritten < 0) {
     1583        return TCL_ERROR;
     1584    }
     1585#endif /*USE_THREADS*/
     1586    return TCL_OK;
     1587}
     1588
     1589static int
     1590DataSetOpacityOp(ClientData clientData, Tcl_Interp *interp, int objc,
     1591                 Tcl_Obj *const *objv)
     1592{
     1593    double opacity;
     1594    if (Tcl_GetDoubleFromObj(interp, objv[2], &opacity) != TCL_OK) {
     1595        return TCL_ERROR;
     1596    }
     1597    if (objc == 4) {
     1598        const char *name = Tcl_GetString(objv[3]);
     1599        g_renderer->setDataSetOpacity(name, opacity);
     1600    } else {
     1601        g_renderer->setDataSetOpacity("all", opacity);
     1602    }
     1603    return TCL_OK;
     1604}
     1605
     1606static int
     1607DataSetOutlineOp(ClientData clientData, Tcl_Interp *interp, int objc,
     1608                 Tcl_Obj *const *objv)
     1609{
     1610    bool state;
     1611    if (GetBooleanFromObj(interp, objv[2], &state) != TCL_OK) {
     1612        return TCL_ERROR;
     1613    }
     1614    if (objc == 4) {
     1615        const char *name = Tcl_GetString(objv[3]);
     1616        g_renderer->setDataSetShowBounds(name, state);
     1617    } else {
     1618        g_renderer->setDataSetShowBounds("all", state);
     1619    }
     1620    return TCL_OK;
     1621}
     1622
     1623static int
     1624DataSetOutlineColorOp(ClientData clientData, Tcl_Interp *interp, int objc,
     1625                      Tcl_Obj *const *objv)
     1626{
     1627    float color[3];
     1628    if (GetFloatFromObj(interp, objv[2], &color[0]) != TCL_OK ||
     1629        GetFloatFromObj(interp, objv[3], &color[1]) != TCL_OK ||
     1630        GetFloatFromObj(interp, objv[4], &color[2]) != TCL_OK) {
     1631        return TCL_ERROR;
     1632    }
     1633    if (objc == 6) {
     1634        const char *name = Tcl_GetString(objv[5]);
     1635        g_renderer->setDataSetOutlineColor(name, color);
     1636    } else {
     1637        g_renderer->setDataSetOutlineColor("all", color);
    14041638    }
    14051639    return TCL_OK;
     
    14161650    if (objc == 4) {
    14171651        const char *name = Tcl_GetString(objv[3]);
    1418         g_renderer->setVisibility(name, state);
    1419     } else {
    1420         g_renderer->setVisibility("all", state);
     1652        g_renderer->setDataSetVisibility(name, state);
     1653    } else {
     1654        g_renderer->setDataSetVisibility("all", state);
    14211655    }
    14221656    return TCL_OK;
     
    14241658
    14251659static Rappture::CmdSpec dataSetOps[] = {
    1426     {"add",      1, DataSetAddOp, 6, 6, "name data follows nBytes"},
    1427     {"delete",   1, DataSetDeleteOp, 2, 3, "?name?"},
    1428     {"getvalue", 1, DataSetGetValueOp, 6, 7, "oper x y ?z? name"},
    1429     {"maprange", 1, DataSetMapRangeOp, 3, 3, "value"},
    1430     {"opacity",  1, DataSetOpacityOp, 3, 4, "value ?name?"},
    1431     {"scalar",   1, DataSetActiveScalarsOp, 3, 4, "scalarName ?name?"},
    1432     {"vector",   2, DataSetActiveVectorsOp, 3, 4, "vectorName ?name?"},
    1433     {"visible",  2, DataSetVisibleOp, 3, 4, "bool ?name?"}
     1660    {"add",       1, DataSetAddOp, 6, 6, "name data follows nBytes"},
     1661    {"color",     1, DataSetOutlineColorOp, 5, 6, "r g b ?name?"},
     1662    {"delete",    1, DataSetDeleteOp, 2, 3, "?name?"},
     1663    {"getscalar", 4, DataSetGetScalarOp, 6, 7, "oper x y ?z? name"},
     1664    {"getvector", 4, DataSetGetVectorOp, 6, 7, "oper x y ?z? name"},
     1665    {"maprange",  1, DataSetMapRangeOp, 3, 3, "value"},
     1666    {"names",     1, DataSetNamesOp, 2, 2, ""},
     1667    {"opacity",   2, DataSetOpacityOp, 3, 4, "value ?name?"},
     1668    {"outline",   2, DataSetOutlineOp, 3, 4, "bool ?name?"},
     1669    {"scalar",    1, DataSetActiveScalarsOp, 3, 4, "scalarName ?name?"},
     1670    {"vector",    2, DataSetActiveVectorsOp, 3, 4, "vectorName ?name?"},
     1671    {"visible",   2, DataSetVisibleOp, 3, 4, "bool ?name?"}
    14341672};
    14351673static int nDataSetOps = NumCmdSpecs(dataSetOps);
     
    14681706    } else if (shapeOpt[0] == 'i' && strcmp(shapeOpt, "icosahedron") == 0) {
    14691707        shape = Glyphs::ICOSAHEDRON;
     1708    } else if (shapeOpt[0] == 'l' && strcmp(shapeOpt, "line") == 0) {
     1709        shape = Glyphs::LINE;
    14701710    } else if (shapeOpt[0] == 'o' && strcmp(shapeOpt, "octahedron") == 0) {
    14711711        shape = Glyphs::OCTAHEDRON;
     
    14821722    if (objc == 4) {
    14831723        const char *name = Tcl_GetString(objv[3]);
    1484         g_renderer->addGlyphs(name);
    1485         g_renderer->setGlyphsShape(name, shape);
    1486     } else {
    1487         g_renderer->addGlyphs("all");
    1488         g_renderer->setGlyphsShape("all", shape);
     1724        if (!g_renderer->addGlyphs(name, shape)) {
     1725            Tcl_AppendResult(interp, "Failed to create glyphs", (char*)NULL);
     1726            return TCL_ERROR;
     1727        }
     1728    } else {
     1729        if (!g_renderer->addGlyphs("all", shape)) {
     1730            Tcl_AppendResult(interp, "Failed to create glyphs for one or more data sets", (char*)NULL);
     1731            return TCL_ERROR;
     1732        }
    14891733    }
    14901734    return TCL_OK;
     
    15321776    if (str[0] == 'c' && strcmp(str, "ccolor") == 0) {
    15331777        mode = Glyphs::COLOR_CONSTANT;
    1534     } else if (str[0] == 's' && strcmp(str, "scale") == 0) {
    1535         mode = Glyphs::COLOR_BY_SCALE;
    15361778    } else if (str[0] == 's' && strcmp(str, "scalar") == 0) {
    15371779        mode = Glyphs::COLOR_BY_SCALAR;
    1538     } else if (str[0] == 'v' && strcmp(str, "vector") == 0) {
    1539         mode = Glyphs::COLOR_BY_VECTOR;
     1780    } else if (str[0] == 'v' && strcmp(str, "vmag") == 0) {
     1781        mode = Glyphs::COLOR_BY_VECTOR_MAGNITUDE;
    15401782    } else {
    15411783        Tcl_AppendResult(interp, "bad color mode option \"", str,
    1542                          "\": should be one of: 'scale', 'scalar', 'vector', 'ccolor'", (char*)NULL);
     1784                         "\": should be one of: 'scalar', 'vmag', 'ccolor'", (char*)NULL);
    15431785        return TCL_ERROR;
    15441786    }
     
    16311873    } else {
    16321874        g_renderer->setGlyphsEdgeWidth("all", width);
     1875    }
     1876    return TCL_OK;
     1877}
     1878
     1879static int
     1880GlyphsNormalizeScaleOp(ClientData clientData, Tcl_Interp *interp, int objc,
     1881                       Tcl_Obj *const *objv)
     1882{
     1883    bool normalize;
     1884    if (GetBooleanFromObj(interp, objv[2], &normalize) != TCL_OK) {
     1885        return TCL_ERROR;
     1886    }
     1887    if (objc == 4) {
     1888        const char *name = Tcl_GetString(objv[3]);
     1889        g_renderer->setGlyphsNormalizeScale(name, normalize);
     1890    } else {
     1891        g_renderer->setGlyphsNormalizeScale("all", normalize);
    16331892    }
    16341893    return TCL_OK;
     
    17351994    if (str[0] == 's' && strcmp(str, "scalar") == 0) {
    17361995        mode = Glyphs::SCALE_BY_SCALAR;
    1737     } else if (str[0] == 'v' && strcmp(str, "vector") == 0) {
    1738         mode = Glyphs::SCALE_BY_VECTOR;
    1739     } else if (str[0] == 'v' && strcmp(str, "vector_comp") == 0) {
     1996    } else if (str[0] == 'v' && strcmp(str, "vmag") == 0) {
     1997        mode = Glyphs::SCALE_BY_VECTOR_MAGNITUDE;
     1998    } else if (str[0] == 'v' && strcmp(str, "vcomp") == 0) {
    17401999        mode = Glyphs::SCALE_BY_VECTOR_COMPONENTS;
    17412000    } else if (str[0] == 'o' && strcmp(str, "off") == 0) {
     
    17432002    } else {
    17442003        Tcl_AppendResult(interp, "bad scaling mode option \"", str,
    1745                          "\": should be one of: 'scalar', 'vector', 'vector_comp', 'off'", (char*)NULL);
     2004                         "\": should be one of: 'scalar', 'vmag', 'vcomp', 'off'", (char*)NULL);
    17462005        return TCL_ERROR;
    17472006    }
     
    17742033    } else if (shapeOpt[0] == 'i' && strcmp(shapeOpt, "icosahedron") == 0) {
    17752034        shape = Glyphs::ICOSAHEDRON;
     2035    } else if (shapeOpt[0] == 'l' && strcmp(shapeOpt, "line") == 0) {
     2036        shape = Glyphs::LINE;
    17762037    } else if (shapeOpt[0] == 'o' && strcmp(shapeOpt, "octahedron") == 0) {
    17772038        shape = Glyphs::OCTAHEDRON;
     
    17822043    } else {
    17832044        Tcl_AppendResult(interp, "bad shape option \"", shapeOpt,
    1784                          "\": should be one of: 'arrow', 'cone', 'cube', 'cylinder', 'dodecahedron', 'icosahedron', 'octahedron', 'sphere', 'tetrahedron'", (char*)NULL);
     2045                         "\": should be one of: 'arrow', 'cone', 'cube', 'cylinder', 'dodecahedron', 'icosahedron', 'line', 'octahedron', 'sphere', 'tetrahedron'", (char*)NULL);
    17852046        return TCL_ERROR;
    17862047    }
     
    18402101    {"linecolor", 5, GlyphsLineColorOp, 5, 6, "r g b ?dataSetName?"},
    18412102    {"linewidth", 5, GlyphsLineWidthOp, 3, 4, "width ?dataSetName?"},
     2103    {"normscale", 1, GlyphsNormalizeScaleOp, 3, 4, "bool ?dataSetName?"},
    18422104    {"opacity",   2, GlyphsOpacityOp, 3, 4, "value ?dataSetName?"},
    18432105    {"orient",    2, GlyphsOrientOp, 6, 7, "qw qx qy qz ?dataSetName?"},
     
    18702132{
    18712133    std::vector<double> contourList;
     2134    double heightScale;
    18722135
    18732136    int clistc;
     
    18862149    }
    18872150
    1888     if (objc == 5) {
    1889         const char *name = Tcl_GetString(objv[4]);
    1890         g_renderer->addHeightMap(name);
    1891         g_renderer->setHeightMapContourList(name, contourList);
    1892     } else {
    1893         g_renderer->addHeightMap("all");
    1894         g_renderer->setHeightMapContourList("all", contourList);
     2151    if (Tcl_GetDoubleFromObj(interp, objv[4], &heightScale) != TCL_OK) {
     2152        return TCL_ERROR;
     2153    }
     2154
     2155    if (objc == 6) {
     2156        const char *name = Tcl_GetString(objv[5]);
     2157        if (!g_renderer->addHeightMap(name, contourList, heightScale)) {
     2158            Tcl_AppendResult(interp, "Failed to create heightmap", (char*)NULL);
     2159            return TCL_ERROR;
     2160        }
     2161    } else {
     2162        if (!g_renderer->addHeightMap("all", contourList, heightScale)) {
     2163            Tcl_AppendResult(interp, "Failed to create heightmap for one or more data sets", (char*)NULL);
     2164            return TCL_ERROR;
     2165        }
    18952166    }
    18962167    return TCL_OK;
     
    19022173{
    19032174    int numContours;
     2175    double heightScale;
    19042176    if (Tcl_GetIntFromObj(interp, objv[3], &numContours) != TCL_OK) {
    19052177        return TCL_ERROR;
    19062178    }
    1907     if (objc == 5) {
    1908         const char *name = Tcl_GetString(objv[4]);
    1909         g_renderer->addHeightMap(name);
    1910         g_renderer->setHeightMapContours(name, numContours);
    1911     } else {
    1912         g_renderer->addHeightMap("all");
    1913         g_renderer->setHeightMapContours("all", numContours);
     2179    if (Tcl_GetDoubleFromObj(interp, objv[4], &heightScale) != TCL_OK) {
     2180        return TCL_ERROR;
     2181    }
     2182    if (objc == 6) {
     2183        const char *name = Tcl_GetString(objv[5]);
     2184        if (!g_renderer->addHeightMap(name, numContours, heightScale)) {
     2185            Tcl_AppendResult(interp, "Failed to create heightmap", (char*)NULL);
     2186            return TCL_ERROR;
     2187        }
     2188    } else {
     2189        if (!g_renderer->addHeightMap("all", numContours, heightScale)) {
     2190            Tcl_AppendResult(interp, "Failed to create heightmap for one or more data sets", (char*)NULL);
     2191            return TCL_ERROR;
     2192        }
    19142193    }
    19152194    return TCL_OK;
     
    19172196
    19182197static Rappture::CmdSpec heightmapAddOps[] = {
    1919     {"contourlist", 1, HeightMapAddContourListOp, 4, 5, "contourList ?dataSetName?"},
    1920     {"numcontours", 1, HeightMapAddNumContoursOp, 4, 5, "numContours ?dataSetName?"}
     2198    {"contourlist", 1, HeightMapAddContourListOp, 5, 6, "contourList heightscale ?dataSetName?"},
     2199    {"numcontours", 1, HeightMapAddNumContoursOp, 5, 6, "numContours heightscale ?dataSetName?"}
    19212200};
    19222201static int nHeightmapAddOps = NumCmdSpecs(heightmapAddOps);
     
    19872266
    19882267static int
    1989 HeightMapContourVisibleOp(ClientData clientData, Tcl_Interp *interp, int objc,
    1990                           Tcl_Obj *const *objv)
     2268HeightMapContourListOp(ClientData clientData, Tcl_Interp *interp, int objc,
     2269                       Tcl_Obj *const *objv)
     2270{
     2271    std::vector<double> contourList;
     2272
     2273    int clistc;
     2274    Tcl_Obj **clistv;
     2275
     2276    if (Tcl_ListObjGetElements(interp, objv[2], &clistc, &clistv) != TCL_OK) {
     2277        return TCL_ERROR;
     2278    }
     2279
     2280    for (int i = 0; i < clistc; i++) {
     2281        double val;
     2282        if (Tcl_GetDoubleFromObj(interp, clistv[i], &val) != TCL_OK) {
     2283            return TCL_ERROR;
     2284        }
     2285        contourList.push_back(val);
     2286    }
     2287
     2288    if (objc == 4) {
     2289        const char *name = Tcl_GetString(objv[3]);
     2290        g_renderer->setHeightMapContourList(name, contourList);
     2291    } else {
     2292        g_renderer->setHeightMapContourList("all", contourList);
     2293    }
     2294    return TCL_OK;
     2295}
     2296
     2297static int
     2298HeightMapContourLineVisibleOp(ClientData clientData, Tcl_Interp *interp, int objc,
     2299                              Tcl_Obj *const *objv)
    19912300{
    19922301    bool state;
     
    19962305    if (objc == 4) {
    19972306        const char *name = Tcl_GetString(objv[3]);
    1998         g_renderer->setHeightMapContourVisibility(name, state);
    1999     } else {
    2000         g_renderer->setHeightMapContourVisibility("all", state);
     2307        g_renderer->setHeightMapContourLineVisibility(name, state);
     2308    } else {
     2309        g_renderer->setHeightMapContourLineVisibility("all", state);
     2310    }
     2311    return TCL_OK;
     2312}
     2313
     2314static int
     2315HeightMapContourSurfaceVisibleOp(ClientData clientData, Tcl_Interp *interp, int objc,
     2316                                 Tcl_Obj *const *objv)
     2317{
     2318    bool state;
     2319    if (GetBooleanFromObj(interp, objv[2], &state) != TCL_OK) {
     2320        return TCL_ERROR;
     2321    }
     2322    if (objc == 4) {
     2323        const char *name = Tcl_GetString(objv[3]);
     2324        g_renderer->setHeightMapContourSurfaceVisibility(name, state);
     2325    } else {
     2326        g_renderer->setHeightMapContourSurfaceVisibility("all", state);
    20012327    }
    20022328    return TCL_OK;
     
    20992425    } else {
    21002426        g_renderer->setHeightMapEdgeWidth("all", width);
     2427    }
     2428    return TCL_OK;
     2429}
     2430
     2431static int
     2432HeightMapNumContoursOp(ClientData clientData, Tcl_Interp *interp, int objc,
     2433                       Tcl_Obj *const *objv)
     2434{
     2435    int numContours;
     2436
     2437    if (Tcl_GetIntFromObj(interp, objv[2], &numContours) != TCL_OK) {
     2438        return TCL_ERROR;
     2439    }
     2440    if (objc == 4) {
     2441        const char *name = Tcl_GetString(objv[3]);
     2442        g_renderer->setHeightMapNumContours(name, numContours);
     2443    } else {
     2444        g_renderer->setHeightMapNumContours("all", numContours);
    21012445    }
    21022446    return TCL_OK;
     
    22262570}
    22272571
     2572static int
     2573HeightMapWireframeOp(ClientData clientData, Tcl_Interp *interp, int objc,
     2574                     Tcl_Obj *const *objv)
     2575{
     2576    bool state;
     2577    if (GetBooleanFromObj(interp, objv[2], &state) != TCL_OK) {
     2578        return TCL_ERROR;
     2579    }
     2580    if (objc == 4) {
     2581        const char *name = Tcl_GetString(objv[3]);
     2582        g_renderer->setHeightMapWireframe(name, state);
     2583    } else {
     2584        g_renderer->setHeightMapWireframe("all", state);
     2585    }
     2586    return TCL_OK;
     2587}
     2588
    22282589static Rappture::CmdSpec heightmapOps[] = {
    2229     {"add",          1, HeightMapAddOp, 4, 5, "oper value ?dataSetName?"},
    2230     {"colormap",     1, HeightMapColorMapOp, 3, 4, "colorMapName ?dataSetName?"},
     2590    {"add",          1, HeightMapAddOp, 5, 6, "oper value ?dataSetName?"},
     2591    {"colormap",     2, HeightMapColorMapOp, 3, 4, "colorMapName ?dataSetName?"},
     2592    {"contourlist",  2, HeightMapContourListOp, 3, 4, "contourList ?dataSetName?"},
    22312593    {"delete",       1, HeightMapDeleteOp, 2, 3, "?dataSetName?"},
    22322594    {"edges",        1, HeightMapEdgeVisibilityOp, 3, 4, "bool ?dataSetName?"},
    22332595    {"heightscale",  1, HeightMapHeightScaleOp, 3, 4, "value ?dataSetName?"},
    22342596    {"isolinecolor", 8, HeightMapContourLineColorOp, 5, 6, "r g b ?dataSetName?"},
    2235     {"isolines",     8, HeightMapContourVisibleOp, 3, 4, "bool ?dataSetName?"},
     2597    {"isolines",     8, HeightMapContourLineVisibleOp, 3, 4, "bool ?dataSetName?"},
    22362598    {"isolinewidth", 8, HeightMapContourLineWidthOp, 3, 4, "width ?dataSetName?"},
    22372599    {"lighting",     3, HeightMapLightingOp, 3, 4, "bool ?dataSetName?"},
    22382600    {"linecolor",    5, HeightMapLineColorOp, 5, 6, "r g b ?dataSetName?"},
    22392601    {"linewidth",    5, HeightMapLineWidthOp, 3, 4, "width ?dataSetName?"},
     2602    {"numcontours",  1, HeightMapNumContoursOp, 3, 4, "numContours ?dataSetName?"},
    22402603    {"opacity",      2, HeightMapOpacityOp, 3, 4, "value ?dataSetName?"},
    22412604    {"orient",       2, HeightMapOrientOp, 6, 7, "qw qx qy qz ?dataSetName?"},
    22422605    {"pos",          1, HeightMapPositionOp, 5, 6, "x y z ?dataSetName?"},
    22432606    {"scale",        1, HeightMapScaleOp, 5, 6, "sx sy sz ?dataSetName?"},
     2607    {"surface",      2, HeightMapContourSurfaceVisibleOp, 3, 4, "bool ?dataSetName?"},
    22442608    {"visible",      2, HeightMapVisibleOp, 3, 4, "bool ?dataSetName?"},
    2245     {"volumeslice",  2, HeightMapVolumeSliceOp, 4, 5, "axis ratio ?dataSetName?"}
     2609    {"volumeslice",  2, HeightMapVolumeSliceOp, 4, 5, "axis ratio ?dataSetName?"},
     2610    {"wireframe",    1, HeightMapWireframeOp, 3, 4, "bool ?dataSetName?"}
    22462611};
    22472612static int nHeightmapOps = NumCmdSpecs(heightmapOps);
     
    22622627
    22632628static int
     2629ImageFlushCmd(ClientData clientData, Tcl_Interp *interp, int objc,
     2630             Tcl_Obj *const *objv)
     2631{
     2632    lastCmdStatus = TCL_BREAK;
     2633    return TCL_OK;
     2634}
     2635
     2636static int
    22642637LegendCmd(ClientData clientData, Tcl_Interp *interp, int objc,
    22652638          Tcl_Obj *const *objv)
    22662639{
    2267     if (objc < 4) {
     2640    if (objc < 7) {
    22682641        Tcl_AppendResult(interp, "wrong # args: should be \"",
    2269                 Tcl_GetString(objv[0]), " colormapName title width height ?dataSetName?\"", (char*)NULL);
    2270         return TCL_ERROR;
    2271     }
    2272     const char *name = Tcl_GetString(objv[1]);
    2273     const char *title = Tcl_GetString(objv[2]);
    2274     int width, height;
    2275 
    2276     if (Tcl_GetIntFromObj(interp, objv[3], &width) != TCL_OK ||
    2277         Tcl_GetIntFromObj(interp, objv[4], &height) != TCL_OK) {
     2642                Tcl_GetString(objv[0]), " colormapName legendType title width height numLabels ?dataSetName?\"", (char*)NULL);
     2643        return TCL_ERROR;
     2644    }
     2645    const char *colorMapName = Tcl_GetString(objv[1]);
     2646    const char *typeStr = Tcl_GetString(objv[2]);
     2647    Renderer::LegendType type;
     2648    if (typeStr[0] == 's' && strcmp(typeStr, "scalar") == 0) {
     2649        type = Renderer::ACTIVE_SCALAR;
     2650    } else if (typeStr[0] == 'v' && strcmp(typeStr, "vmag") == 0) {
     2651        type = Renderer::ACTIVE_VECTOR_MAGNITUDE;
     2652    } else if (typeStr[0] == 'v' && strcmp(typeStr, "vx") == 0) {
     2653        type = Renderer::ACTIVE_VECTOR_X;
     2654    } else if (typeStr[0] == 'v' && strcmp(typeStr, "vy") == 0) {
     2655        type = Renderer::ACTIVE_VECTOR_Y;
     2656    } else if (typeStr[0] == 'v' && strcmp(typeStr, "vz") == 0) {
     2657        type = Renderer::ACTIVE_VECTOR_Z;
     2658    } else {
     2659        Tcl_AppendResult(interp, "Bad legendType option \"",
     2660                         typeStr, "\", should be one of 'scalar', 'vmag', 'vx', 'vy', 'vz'", (char*)NULL);
     2661        return TCL_ERROR;
     2662    }
     2663
     2664    std::string title(Tcl_GetString(objv[3]));
     2665    int width, height, numLabels;
     2666
     2667    if (Tcl_GetIntFromObj(interp, objv[4], &width) != TCL_OK ||
     2668        Tcl_GetIntFromObj(interp, objv[5], &height) != TCL_OK ||
     2669        Tcl_GetIntFromObj(interp, objv[6], &numLabels) != TCL_OK) {
    22782670        return TCL_ERROR;
    22792671    }
     
    22822674        vtkSmartPointer<vtkUnsignedCharArray>::New();
    22832675
    2284     if (objc == 6) {
    2285         const char *dataSetName = Tcl_GetString(objv[5]);
    2286         if (!g_renderer->renderColorMap(name, dataSetName, title, width, height, imgData)) {
     2676    double range[2];
     2677
     2678    if (objc == 8) {
     2679        const char *dataSetName = Tcl_GetString(objv[7]);
     2680        if (!g_renderer->renderColorMap(colorMapName, dataSetName, type, title,
     2681                                        range, width, height, numLabels, imgData)) {
    22872682            Tcl_AppendResult(interp, "Color map \"",
    2288                              name, "\" was not found", (char*)NULL);
     2683                             colorMapName, "\" or dataset \"",
     2684                             dataSetName, "\" was not found", (char*)NULL);
    22892685            return TCL_ERROR;
    22902686        }
    22912687    } else {
    2292         if (!g_renderer->renderColorMap(name, "all", title, width, height, imgData)) {
     2688        if (!g_renderer->renderColorMap(colorMapName, "all", type, title,
     2689                                        range, width, height, numLabels, imgData)) {
    22932690            Tcl_AppendResult(interp, "Color map \"",
    2294                              name, "\" was not found", (char*)NULL);
     2691                             colorMapName, "\" was not found", (char*)NULL);
    22952692            return TCL_ERROR;
    22962693        }
     
    22982695
    22992696#ifdef DEBUG
     2697# ifdef RENDER_TARGA
    23002698    writeTGAFile("/tmp/legend.tga", imgData->GetPointer(0), width, height,
    23012699                 TARGA_BYTES_PER_PIXEL);
     2700# else
     2701    writeTGAFile("/tmp/legend.tga", imgData->GetPointer(0), width, height,
     2702                 TARGA_BYTES_PER_PIXEL, true);
     2703# endif
    23022704#else
    23032705    char cmd[256];
    2304     snprintf(cmd, sizeof(cmd), "nv>legend %s", name);
    2305 #ifdef RENDER_TARGA
     2706    snprintf(cmd, sizeof(cmd), "nv>legend {%s} {%s} %g %g",
     2707             colorMapName, title.c_str(), range[0], range[1]);
     2708
     2709# ifdef USE_THREADS
     2710#  ifdef RENDER_TARGA
     2711    ResponseQueue *queue = (ResponseQueue *)clientData;
     2712    queueTGA(queue, cmd, imgData->GetPointer(0), width, height,
     2713             TARGA_BYTES_PER_PIXEL);
     2714#  else
     2715    ResponseQueue *queue = (ResponseQueue *)clientData;
     2716    queuePPM(queue, cmd, imgData->GetPointer(0), width, height);
     2717#  endif
     2718# else
     2719#  ifdef RENDER_TARGA
    23062720    writeTGA(g_fdOut, cmd, imgData->GetPointer(0), width, height,
    2307                  TARGA_BYTES_PER_PIXEL);
    2308 #else
     2721             TARGA_BYTES_PER_PIXEL);
     2722#  else
    23092723    writePPM(g_fdOut, cmd, imgData->GetPointer(0), width, height);
    2310 #endif
    2311 #endif
    2312 
     2724#  endif
     2725# endif // USE_THREADS
     2726#endif // DEBUG
    23132727    return TCL_OK;
    23142728}
     
    23202734    if (objc == 3) {
    23212735        const char *name = Tcl_GetString(objv[2]);
    2322         g_renderer->addLIC(name);
    2323     } else {
    2324         g_renderer->addLIC("all");
     2736        if (!g_renderer->addLIC(name)) {
     2737            Tcl_AppendResult(interp, "Failed to create lic", (char*)NULL);
     2738            return TCL_ERROR;
     2739        }
     2740    } else {
     2741        if (!g_renderer->addLIC("all")) {
     2742            Tcl_AppendResult(interp, "Failed to create lic for one or more data sets", (char*)NULL);
     2743            return TCL_ERROR;
     2744        }
    23252745    }
    23262746    return TCL_OK;
     
    25843004    if (objc == 3) {
    25853005        const char *name = Tcl_GetString(objv[2]);
    2586         g_renderer->addMolecule(name);
    2587     } else {
    2588         g_renderer->addMolecule("all");
     3006        if (!g_renderer->addMolecule(name)) {
     3007            Tcl_AppendResult(interp, "Failed to create molecule", (char*)NULL);
     3008            return TCL_ERROR;
     3009        }
     3010    } else {
     3011        if (!g_renderer->addMolecule("all")) {
     3012            Tcl_AppendResult(interp, "Failed to create molecule for one or more data sets", (char*)NULL);
     3013            return TCL_ERROR;
     3014        }
    25893015    }
    25903016    return TCL_OK;
     
    28993325    if (objc == 3) {
    29003326        const char *name = Tcl_GetString(objv[2]);
    2901         g_renderer->addPolyData(name);
    2902     } else {
    2903         g_renderer->addPolyData("all");
     3327        if (!g_renderer->addPolyData(name)) {
     3328            Tcl_AppendResult(interp, "Failed to create polydata", (char*)NULL);
     3329            return TCL_ERROR;
     3330        }
     3331    } else {
     3332        if (!g_renderer->addPolyData("all")) {
     3333            Tcl_AppendResult(interp, "Failed to create polydata for one or more data sets", (char*)NULL);
     3334            return TCL_ERROR;
     3335        }
    29043336    }
    29053337    return TCL_OK;
     
    30413473    } else {
    30423474        g_renderer->setPolyDataOrientation("all", quat);
     3475    }
     3476    return TCL_OK;
     3477}
     3478
     3479static int
     3480PolyDataPointSizeOp(ClientData clientData, Tcl_Interp *interp, int objc,
     3481                    Tcl_Obj *const *objv)
     3482{
     3483    float size;
     3484    if (GetFloatFromObj(interp, objv[2], &size) != TCL_OK) {
     3485        return TCL_ERROR;
     3486    }
     3487    if (objc == 4) {
     3488        const char *name = Tcl_GetString(objv[3]);
     3489        g_renderer->setPolyDataPointSize(name, size);
     3490    } else {
     3491        g_renderer->setPolyDataPointSize("all", size);
    30433492    }
    30443493    return TCL_OK;
     
    31273576    {"opacity",   2, PolyDataOpacityOp, 3, 4, "value ?dataSetName?"},
    31283577    {"orient",    2, PolyDataOrientOp, 6, 7, "qw qx qy qz ?dataSetName?"},
    3129     {"pos",       1, PolyDataPositionOp, 5, 6, "x y z ?dataSetName?"},
     3578    {"pos",       2, PolyDataPositionOp, 5, 6, "x y z ?dataSetName?"},
     3579    {"ptsize",    2, PolyDataPointSizeOp, 3, 4, "size ?dataSetName?"},
    31303580    {"scale",     1, PolyDataScaleOp, 5, 6, "sx sy sz ?dataSetName?"},
    31313581    {"visible",   1, PolyDataVisibleOp, 3, 4, "bool ?dataSetName?"},
     
    31543604    if (objc == 3) {
    31553605        const char *name = Tcl_GetString(objv[2]);
    3156         g_renderer->addPseudoColor(name);
    3157     } else {
    3158         g_renderer->addPseudoColor("all");
     3606        if (!g_renderer->addPseudoColor(name)) {
     3607            Tcl_AppendResult(interp, "Failed to create pseudocolor", (char*)NULL);
     3608            return TCL_ERROR;
     3609        }
     3610    } else {
     3611        if (!g_renderer->addPseudoColor("all")) {
     3612            Tcl_AppendResult(interp, "Failed to create pseudocolor for one or more data sets", (char*)NULL);
     3613            return TCL_ERROR;
     3614        }
     3615    }
     3616    return TCL_OK;
     3617}
     3618
     3619static int
     3620PseudoColorColorOp(ClientData clientData, Tcl_Interp *interp, int objc,
     3621                   Tcl_Obj *const *objv)
     3622{
     3623    float color[3];
     3624    if (GetFloatFromObj(interp, objv[2], &color[0]) != TCL_OK ||
     3625        GetFloatFromObj(interp, objv[3], &color[1]) != TCL_OK ||
     3626        GetFloatFromObj(interp, objv[4], &color[2]) != TCL_OK) {
     3627        return TCL_ERROR;
     3628    }
     3629    if (objc == 6) {
     3630        const char *name = Tcl_GetString(objv[5]);
     3631        g_renderer->setPseudoColorColor(name, color);
     3632    } else {
     3633        g_renderer->setPseudoColorColor("all", color);
    31593634    }
    31603635    return TCL_OK;
     
    31713646    } else {
    31723647        g_renderer->setPseudoColorColorMap("all", colorMapName);
     3648    }
     3649    return TCL_OK;
     3650}
     3651
     3652static int
     3653PseudoColorColorModeOp(ClientData clientData, Tcl_Interp *interp, int objc,
     3654                       Tcl_Obj *const *objv)
     3655{
     3656    PseudoColor::ColorMode mode;
     3657    const char *str = Tcl_GetString(objv[2]);
     3658    if (str[0] == 'c' && strcmp(str, "ccolor") == 0) {
     3659        mode = PseudoColor::COLOR_CONSTANT;
     3660    } else if (str[0] == 's' && strcmp(str, "scalar") == 0) {
     3661        mode = PseudoColor::COLOR_BY_SCALAR;
     3662    } else if (str[0] == 'v' && strcmp(str, "vmag") == 0) {
     3663        mode = PseudoColor::COLOR_BY_VECTOR_MAGNITUDE;
     3664    } else if (str[0] == 'v' && strcmp(str, "vx") == 0) {
     3665        mode = PseudoColor::COLOR_BY_VECTOR_X;
     3666    } else if (str[0] == 'v' && strcmp(str, "vy") == 0) {
     3667        mode = PseudoColor::COLOR_BY_VECTOR_Y;
     3668    } else if (str[0] == 'v' && strcmp(str, "vz") == 0) {
     3669        mode = PseudoColor::COLOR_BY_VECTOR_Z;
     3670    } else {
     3671        Tcl_AppendResult(interp, "bad color mode option \"", str,
     3672                         "\": should be one of: 'scalar', 'vmag', 'vx', 'vy', 'vz', 'ccolor'", (char*)NULL);
     3673        return TCL_ERROR;
     3674    }
     3675    if (objc == 4) {
     3676        const char *name = Tcl_GetString(objv[3]);
     3677        g_renderer->setPseudoColorColorMode(name, mode);
     3678    } else {
     3679        g_renderer->setPseudoColorColorMode("all", mode);
    31733680    }
    31743681    return TCL_OK;
     
    33693876static Rappture::CmdSpec pseudoColorOps[] = {
    33703877    {"add",       1, PseudoColorAddOp, 2, 3, "?dataSetName?"},
    3371     {"colormap",  1, PseudoColorColorMapOp, 3, 4, "colorMapName ?dataSetName?"},
     3878    {"ccolor",    2, PseudoColorColorOp, 5, 6, "r g b ?dataSetName?"},
     3879    {"colormap",  7, PseudoColorColorMapOp, 3, 4, "colorMapName ?dataSetNme?"},
     3880    {"colormode", 7, PseudoColorColorModeOp, 3, 4, "mode ?dataSetNme?"},
    33723881    {"delete",    1, PseudoColorDeleteOp, 2, 3, "?dataSetName?"},
    33733882    {"edges",     1, PseudoColorEdgeVisibilityOp, 3, 4, "bool ?dataSetName?"},
     
    35394048    if (objc == 3) {
    35404049        const char *name = Tcl_GetString(objv[2]);
    3541         g_renderer->addStreamlines(name);
    3542     } else {
    3543         g_renderer->addStreamlines("all");
     4050        if (!g_renderer->addStreamlines(name)) {
     4051            Tcl_AppendResult(interp, "Failed to create streamlines", (char*)NULL);
     4052            return TCL_ERROR;
     4053        }
     4054    } else {
     4055        if (!g_renderer->addStreamlines("all")) {
     4056            Tcl_AppendResult(interp, "Failed to create streamlines for one or more data sets", (char*)NULL);
     4057            return TCL_ERROR;
     4058        }
    35444059    }
    35454060    return TCL_OK;
     
    40714586
    40724587static Rappture::CmdSpec streamlinesOps[] = {
    4073     {"add",       1, StreamlinesAddOp, 2, 3, "?dataSetName?"},
    4074     {"ccolor",    1, StreamlinesColorOp, 5, 6, "r g b ?dataSetName?"},
    4075     {"colormap",  7, StreamlinesColorMapOp, 3, 4, "colorMapName ?dataSetName?"},
     4588    {"add",       1, StreamlinesAddOp,       2, 3, "?dataSetName?"},
     4589    {"ccolor",    1, StreamlinesColorOp,     5, 6, "r g b ?dataSetName?"},
     4590    {"colormap",  7, StreamlinesColorMapOp,  3, 4, "colorMapName ?dataSetName?"},
    40764591    {"colormode", 7, StreamlinesColorModeOp, 3, 4, "mode ?dataSetNme?"},
    4077     {"delete",    1, StreamlinesDeleteOp, 2, 3, "?dataSetName?"},
     4592    {"delete",    1, StreamlinesDeleteOp,    2, 3, "?dataSetName?"},
    40784593    {"edges",     1, StreamlinesEdgeVisibilityOp, 3, 4, "bool ?dataSetName?"},
    4079     {"length",    2, StreamlinesLengthOp, 3, 4, "length ?dataSetName?"},
    4080     {"lighting",  3, StreamlinesLightingOp, 3, 4, "bool ?dataSetName?"},
     4594    {"length",    2, StreamlinesLengthOp,    3, 4, "length ?dataSetName?"},
     4595    {"lighting",  3, StreamlinesLightingOp,  3, 4, "bool ?dataSetName?"},
    40814596    {"linecolor", 5, StreamlinesLineColorOp, 5, 6, "r g b ?dataSetName?"},
    4082     {"lines",     5, StreamlinesLinesOp, 2, 3, "?dataSetName?"},
     4597    {"lines",     5, StreamlinesLinesOp,     2, 3, "?dataSetName?"},
    40834598    {"linewidth", 5, StreamlinesLineWidthOp, 3, 4, "width ?dataSetName?"},
    4084     {"opacity",   2, StreamlinesOpacityOp, 3, 4, "val ?dataSetName?"},
    4085     {"orient",    2, StreamlinesOrientOp, 6, 7, "qw qx qy qz ?dataSetName?"},
    4086     {"pos",       1, StreamlinesPositionOp, 5, 6, "x y z ?dataSetName?"},
    4087     {"ribbons",   1, StreamlinesRibbonsOp, 4, 5, "width angle ?dataSetName?"},
    4088     {"scale",     2, StreamlinesScaleOp, 5, 6, "sx sy sz ?dataSetName?"},
    4089     {"seed",      2, StreamlinesSeedOp, 4, 14, "op params... ?dataSetName?"},
     4599    {"opacity",   2, StreamlinesOpacityOp,   3, 4, "val ?dataSetName?"},
     4600    {"orient",    2, StreamlinesOrientOp,    6, 7, "qw qx qy qz ?dataSetName?"},
     4601    {"pos",       1, StreamlinesPositionOp,  5, 6, "x y z ?dataSetName?"},
     4602    {"ribbons",   1, StreamlinesRibbonsOp,   4, 5, "width angle ?dataSetName?"},
     4603    {"scale",     2, StreamlinesScaleOp,     5, 6, "sx sy sz ?dataSetName?"},
     4604    {"seed",      2, StreamlinesSeedOp,  4, 14, "op params... ?dataSetName?"},
    40904605    {"tubes",     1, StreamlinesTubesOp, 4, 5, "numSides radius ?dataSetName?"},
    40914606    {"visible",   1, StreamlinesVisibleOp, 3, 4, "bool ?dataSetName?"}
     
    41134628    if (objc == 3) {
    41144629        const char *name = Tcl_GetString(objv[2]);
    4115         g_renderer->addVolume(name);
    4116     } else {
    4117         g_renderer->addVolume("all");
     4630        if (!g_renderer->addVolume(name)) {
     4631            Tcl_AppendResult(interp, "Failed to create volume", (char*)NULL);
     4632            return TCL_ERROR;
     4633        }
     4634    } else {
     4635        if (!g_renderer->addVolume("all")) {
     4636            Tcl_AppendResult(interp, "Failed to create volume for one or more data sets", (char*)NULL);
     4637            return TCL_ERROR;
     4638        }
    41184639    }
    41194640    return TCL_OK;
     
    42954816
    42964817static Rappture::CmdSpec volumeShadingOps[] = {
    4297     {"ambient",  1, VolumeShadingAmbientOp, 4, 5, "coeff ?dataSetName?"},
    4298     {"diffuse",  1, VolumeShadingDiffuseOp, 4, 5, "coeff ?dataSetName?"},
     4818    {"ambient",  1, VolumeShadingAmbientOp,  4, 5, "coeff ?dataSetName?"},
     4819    {"diffuse",  1, VolumeShadingDiffuseOp,  4, 5, "coeff ?dataSetName?"},
    42994820    {"specular", 1, VolumeShadingSpecularOp, 5, 6, "coeff power ?dataSetName?"}
    43004821};
     
    43334854
    43344855static Rappture::CmdSpec volumeOps[] = {
    4335     {"add",      1, VolumeAddOp, 2, 3, "?dataSetName?"},
     4856    {"add",      1, VolumeAddOp,      2, 3, "?dataSetName?"},
    43364857    {"colormap", 1, VolumeColorMapOp, 3, 4, "colorMapName ?dataSetName?"},
    4337     {"delete",   1, VolumeDeleteOp, 2, 3, "?dataSetName?"},
     4858    {"delete",   1, VolumeDeleteOp,   2, 3, "?dataSetName?"},
    43384859    {"lighting", 1, VolumeLightingOp, 3, 4, "bool ?dataSetName?"},
    4339     {"opacity",  2, VolumeOpacityOp, 3, 4, "val ?dataSetName?"},
    4340     {"orient",   2, VolumeOrientOp, 6, 7, "qw qx qy qz ?dataSetName?"},
     4860    {"opacity",  2, VolumeOpacityOp,  3, 4, "val ?dataSetName?"},
     4861    {"orient",   2, VolumeOrientOp,   6, 7, "qw qx qy qz ?dataSetName?"},
    43414862    {"pos",      1, VolumePositionOp, 5, 6, "x y z ?dataSetName?"},
    4342     {"scale",    2, VolumeScaleOp, 5, 6, "sx sy sz ?dataSetName?"},
    4343     {"shading",  2, VolumeShadingOp, 4, 6, "oper val ?dataSetName?"},
    4344     {"visible",  1, VolumeVisibleOp, 3, 4, "bool ?dataSetName?"}
     4863    {"scale",    2, VolumeScaleOp,    5, 6, "sx sy sz ?dataSetName?"},
     4864    {"shading",  2, VolumeShadingOp,  4, 6, "oper val ?dataSetName?"},
     4865    {"visible",  1, VolumeVisibleOp,  3, 4, "bool ?dataSetName?"}
    43454866};
    43464867static int nVolumeOps = NumCmdSpecs(volumeOps);
     
    43624883/**
    43634884 * \brief Execute commands from client in Tcl interpreter
     4885 *
     4886 * In this threaded model, the select call is for event compression.  We
     4887 * want to execute render server commands as long as they keep coming. 
     4888 * This lets us execute a stream of many commands but render once.  This
     4889 * benefits camera movements, screen resizing, and opacity changes
     4890 * (using a slider on the client).  The down side is you don't render
     4891 * until there's a lull in the command stream.  If the client needs an
     4892 * image, it can issue an "imgflush" command.  That breaks us out of the
     4893 * read loop.
    43644894 */
    43654895int
    43664896Rappture::VtkVis::processCommands(Tcl_Interp *interp, FILE *fin, FILE *fout)
    43674897{
    4368     Tcl_DString cmdbuffer;
    4369     Tcl_DStringInit(&cmdbuffer);
    4370 
    4371     int fdIn = fileno(fin);
    4372     int fdOut = fileno(fout);
    4373     int flags = fcntl(fdIn, F_GETFL, 0);
    4374     fcntl(fdIn, F_SETFL, flags & ~O_NONBLOCK);
    4375 
    43764898    int status = TCL_OK;
    4377     int nCommands = 0;
    4378     bool isComplete = false;
    4379     while ((!feof(fin)) && (status == TCL_OK)) {
    4380         while (!feof(fin)) {
    4381             int c = fgetc(fin);
    4382             if (c <= 0) {
    4383                 if (errno == EWOULDBLOCK) {
    4384                     break;
    4385                 }
    4386                 if (feof(fin))
    4387                     return 1;
    4388                 else
    4389                     return c;
     4899
     4900#define BUFFERSIZE   ((1<<16)-1)
     4901    char buffer[BUFFERSIZE+1];
     4902
     4903    Tcl_DString command;
     4904    Tcl_DStringInit(&command);
     4905
     4906    fd_set readFds;
     4907    struct timeval tv, *tvPtr;
     4908
     4909    FD_ZERO(&readFds);
     4910    FD_SET(fileno(fin), &readFds);
     4911    tvPtr = NULL;                       /* Initially there is no timeout. */
     4912    while (select(1, &readFds, NULL, NULL, tvPtr) > 0) {
     4913        if (fgets(buffer, BUFFERSIZE, fin) == NULL) {
     4914            /* Terminate the server if we can't
     4915             * communicate with the client
     4916             * anymore. */
     4917            if (feof(fin)) {
     4918                INFO("Exiting server on EOF from client");
     4919                exit(0);
     4920            } else {
     4921                ERROR("Exiting server, failed to read from client: %s",
     4922                      strerror(errno));
     4923                exit(1);
    43904924            }
    4391             char ch = (char)c;
    4392             Tcl_DStringAppend(&cmdbuffer, &ch, 1);
    4393             if (ch == '\n') {
    4394                 isComplete = Tcl_CommandComplete(Tcl_DStringValue(&cmdbuffer));
    4395                 if (isComplete) {
    4396                     break;
    4397                 }
     4925        }
     4926        buffer[BUFFERSIZE] = '\0';
     4927        Tcl_DStringAppend(&command, buffer, -1);
     4928        if (Tcl_CommandComplete(Tcl_DStringValue(&command))) {
     4929            status = ExecuteCommand(interp, &command);
     4930            if (status == TCL_BREAK) {
     4931                return 1;               /* This was caused by a "imgflush"
     4932                                         * command. Break out of the read loop
     4933                                         * and allow a new image to be
     4934                                         * rendered. */
    43984935            }
    43994936        }
    4400         // no command? then we're done for now
    4401         if (Tcl_DStringLength(&cmdbuffer) == 0) {
    4402             break;
    4403         }
    4404         if (isComplete) {
    4405             // back to original flags during command evaluation...
    4406             fcntl(fdIn, F_SETFL, flags & ~O_NONBLOCK);
    4407             TRACE("command: '%s'", Tcl_DStringValue(&cmdbuffer));
    4408             status = ExecuteCommand(interp, &cmdbuffer);
    4409             // non-blocking for next read -- we might not get anything
    4410             fcntl(fdIn, F_SETFL, flags | O_NONBLOCK);
    4411             isComplete = false;
    4412             nCommands++;
    4413         }
    4414     }
    4415     fcntl(fdIn, F_SETFL, flags);
     4937        tv.tv_sec = tv.tv_usec = 0L;
     4938        FD_SET(fileno(fin), &readFds);
     4939        tvPtr = &tv;
     4940    }
    44164941
    44174942    if (status != TCL_OK) {
     
    44214946        string = Tcl_GetVar(interp, "errorInfo", TCL_GLOBAL_ONLY);
    44224947        TRACE("ERROR errorInfo=(%s)", string);
    4423 
     4948        INFO("%s: status=%d ERROR errorInfo=(%s)", Tcl_DStringValue(&command),
     4949             status, string);
    44244950        nBytes = strlen(string);
    44254951        struct iovec iov[3];
     
    44294955        iov[1].iov_len = nBytes;
    44304956        iov[2].iov_base = (char *)"\n";
    4431         iov[2].iov_len = 1;
     4957        iov[2].iov_len = strlen((char *)iov[2].iov_base);
     4958        int fdOut = fileno(fout);
    44324959        if (writev(fdOut, iov, 3) < 0) {
    44334960            ERROR("write failed: %s", strerror(errno));
     
    44444971 * \return The initialized Tcl interpreter
    44454972 */
    4446 Tcl_Interp *
    4447 Rappture::VtkVis::initTcl()
    4448 {
    4449     Tcl_Interp *interp;
    4450     interp = Tcl_CreateInterp();
    4451 
     4973void
     4974Rappture::VtkVis::initTcl(Tcl_Interp *interp, ClientData clientData)
     4975{
    44524976    Tcl_MakeSafe(interp);
    4453 
    4454     Tcl_CreateObjCommand(interp, "axis",        AxisCmd,        NULL, NULL);
    4455     Tcl_CreateObjCommand(interp, "camera",      CameraCmd,      NULL, NULL);
    4456     Tcl_CreateObjCommand(interp, "colormap",    ColorMapCmd,    NULL, NULL);
    4457     Tcl_CreateObjCommand(interp, "contour2d",   Contour2DCmd,   NULL, NULL);
    4458     Tcl_CreateObjCommand(interp, "contour3d",   Contour3DCmd,   NULL, NULL);
    4459     Tcl_CreateObjCommand(interp, "dataset",     DataSetCmd,     NULL, NULL);
    4460     Tcl_CreateObjCommand(interp, "glyphs",      GlyphsCmd,      NULL, NULL);
    4461     Tcl_CreateObjCommand(interp, "heightmap",   HeightMapCmd,   NULL, NULL);
    4462     Tcl_CreateObjCommand(interp, "legend",      LegendCmd,      NULL, NULL);
    4463     Tcl_CreateObjCommand(interp, "lic",         LICCmd,         NULL, NULL);
    4464     Tcl_CreateObjCommand(interp, "molecule",    MoleculeCmd,    NULL, NULL);
    4465     Tcl_CreateObjCommand(interp, "polydata",    PolyDataCmd,    NULL, NULL);
    4466     Tcl_CreateObjCommand(interp, "pseudocolor", PseudoColorCmd, NULL, NULL);
    4467     Tcl_CreateObjCommand(interp, "renderer",    RendererCmd,    NULL, NULL);
    4468     Tcl_CreateObjCommand(interp, "screen",      ScreenCmd,      NULL, NULL);
    4469     Tcl_CreateObjCommand(interp, "streamlines", StreamlinesCmd, NULL, NULL);
    4470     Tcl_CreateObjCommand(interp, "volume",      VolumeCmd,      NULL, NULL);
    4471     return interp;
     4977    Tcl_CreateObjCommand(interp, "axis",        AxisCmd,        clientData, NULL);
     4978    Tcl_CreateObjCommand(interp, "camera",      CameraCmd,      clientData, NULL);
     4979    Tcl_CreateObjCommand(interp, "colormap",    ColorMapCmd,    clientData, NULL);
     4980    Tcl_CreateObjCommand(interp, "contour2d",   Contour2DCmd,   clientData, NULL);
     4981    Tcl_CreateObjCommand(interp, "contour3d",   Contour3DCmd,   clientData, NULL);
     4982    Tcl_CreateObjCommand(interp, "dataset",     DataSetCmd,     clientData, NULL);
     4983    Tcl_CreateObjCommand(interp, "glyphs",      GlyphsCmd,      clientData, NULL);
     4984    Tcl_CreateObjCommand(interp, "heightmap",   HeightMapCmd,   clientData, NULL);
     4985    Tcl_CreateObjCommand(interp, "imgflush",    ImageFlushCmd,  clientData, NULL);
     4986    Tcl_CreateObjCommand(interp, "legend",      LegendCmd,      clientData, NULL);
     4987    Tcl_CreateObjCommand(interp, "lic",         LICCmd,         clientData, NULL);
     4988    Tcl_CreateObjCommand(interp, "molecule",    MoleculeCmd,    clientData, NULL);
     4989    Tcl_CreateObjCommand(interp, "polydata",    PolyDataCmd,    clientData, NULL);
     4990    Tcl_CreateObjCommand(interp, "pseudocolor", PseudoColorCmd, clientData, NULL);
     4991    Tcl_CreateObjCommand(interp, "renderer",    RendererCmd,    clientData, NULL);
     4992    Tcl_CreateObjCommand(interp, "screen",      ScreenCmd,      clientData, NULL);
     4993    Tcl_CreateObjCommand(interp, "streamlines", StreamlinesCmd, clientData, NULL);
     4994    Tcl_CreateObjCommand(interp, "volume",      VolumeCmd,      clientData, NULL);
    44724995}
    44734996
    44744997/**
    44754998 * \brief Delete Tcl commands and interpreter
    4476  *
    44774999 */
    44785000void Rappture::VtkVis::exitTcl(Tcl_Interp *interp)
     
    44875009    Tcl_DeleteCommand(interp, "glyphs");
    44885010    Tcl_DeleteCommand(interp, "heightmap");
     5011    Tcl_DeleteCommand(interp, "imgflush");
    44895012    Tcl_DeleteCommand(interp, "legend");
    44905013    Tcl_DeleteCommand(interp, "lic");
  • branches/blt4/packages/vizservers/vtkvis/RpVtkRendererCmd.h

    r2302 r2542  
    1616
    1717extern int processCommands(Tcl_Interp *interp, FILE *fin, FILE *fout);
    18 extern Tcl_Interp *initTcl();
     18extern void initTcl(Tcl_Interp *interp, ClientData clientData);
    1919extern void exitTcl(Tcl_Interp *interp);
    2020
  • branches/blt4/packages/vizservers/vtkvis/TGAWriter.cpp

    r2302 r2542  
    1717#include "TGAWriter.h"
    1818#include "Trace.h"
     19#ifdef USE_THREADS
     20#include "ResponseQueue.h"
     21#endif
     22
     23#ifdef USE_THREADS
     24
     25/**
     26 * \brief Writes image command + data to supplied file descriptor.
     27 *
     28 * The image data must be supplied in BGR(A) order with bottom to
     29 * top scanline ordering.
     30 *
     31 * \param[in] queue Pointer to ResponseQueue to write to
     32 * \param[in] cmdName Command name to send (byte length will be appended)
     33 * \param[in] data Image data
     34 * \param[in] width Width of image in pixels
     35 * \param[in] height Height of image in pixels
     36 * \param[in] bytesPerPixel Should be 3 or 4, depending on alpha
     37 */
     38void
     39Rappture::VtkVis::queueTGA(ResponseQueue *queue, const char *cmdName,
     40                           const unsigned char *data,
     41                           int width, int height,
     42                           int bytesPerPixel)
     43{
     44    TRACE("(%dx%d)\n", width, height);
     45
     46    size_t headerLength = 18;
     47
     48    char header[headerLength];
     49    memset(header, 0, headerLength);
     50    header[2] = (char)2;  // image type (2 = uncompressed true-color)
     51    header[12] = (char)width;
     52    header[13] = (char)(width >> 8);
     53    header[14] = (char)height;
     54    header[15] = (char)(height >> 8);
     55    header[16] = (char)(bytesPerPixel*8); // bits per pixel
     56
     57    size_t dataLength = width * height * bytesPerPixel;
     58    size_t cmdLength;
     59
     60    char command[200];
     61    cmdLength = snprintf(command, sizeof(command), "%s %lu\n", cmdName,
     62                         (unsigned long)headerLength + dataLength);
     63
     64    size_t length;
     65    unsigned char *mesg = NULL;
     66
     67    length = headerLength + dataLength + cmdLength;
     68    mesg = (unsigned char *)malloc(length);
     69    if (mesg == NULL) {
     70        ERROR("can't allocate %ld bytes for the image message", length);
     71        return;
     72    }
     73    memcpy(mesg, command, cmdLength);
     74    memcpy(mesg + cmdLength, header, headerLength);
     75    memcpy(mesg + cmdLength + headerLength,
     76           const_cast<unsigned char *>(data), dataLength);
     77
     78    Response *response = NULL;
     79    if (strncmp(cmdName, "nv>legend", 9) == 0) {
     80        response = new Response(Response::LEGEND);
     81    } else {
     82        response = new Response(Response::IMAGE);
     83    }
     84    response->setMessage(mesg, length, Response::DYNAMIC);
     85    queue->enqueue(response);
     86    TRACE("Leaving (%dx%d)\n", width, height);
     87}
     88#else
    1989
    2090/**
     
    79149    TRACE("Leaving (%dx%d)\n", width, height);
    80150}
     151#endif  /*USE_THREADS*/
    81152
    82153/**
  • branches/blt4/packages/vizservers/vtkvis/TGAWriter.h

    r2302 r2542  
    99#define __RAPPTURE_VTKVIS_TGAWRITER_H__
    1010
     11#ifdef USE_THREADS
     12#include "ResponseQueue.h"
     13#endif
     14
    1115namespace Rappture {
    1216namespace VtkVis {
    13 
     17#ifdef USE_THREADS
    1418extern
    15 void writeTGA(int fd, const char *cmdName, const unsigned char *data,
    16               int width, int height, int bytesPerPixel);
    17 
     19void queueTGA(ResponseQueue *queue, const char *cmdName,
     20              const unsigned char *data, int width, int height,
     21              int bytesPerPixel);
     22#else
    1823extern
    19 void writeTGAFile(const char *filename, const unsigned char *data,
    20                   int width, int height, int bytesPerPixel,
    21                   bool srcIsRGB = false);
    22 
     24void writeTGA(int fd, const char *cmdName,
     25              const unsigned char *data, int width, int height,
     26              int bytesPerPixel);
     27#endif
     28extern
     29void writeTGAFile(const char *filename,
     30                  const unsigned char *data, int width, int height,
     31                  int bytesPerPixel, bool srcIsRGB = false);
    2332}
    2433}
  • branches/blt4/packages/vizservers/vtkvis/Trace.cpp

    r2120 r2542  
    2121 */
    2222void
    23 Rappture::VtkVis::InitLog()
     23Rappture::VtkVis::initLog()
    2424{
    2525    openlog("vtkvis", LOG_CONS | LOG_PERROR | LOG_PID,  LOG_USER);
     
    3030 */
    3131void
    32 Rappture::VtkVis::CloseLog()
     32Rappture::VtkVis::closeLog()
    3333{
    3434    closelog();
     
    3939 */
    4040void
    41 Rappture::VtkVis::LogMessage(int priority, const char *funcname,
     41Rappture::VtkVis::logMessage(int priority, const char *funcname,
    4242                             const char *path, int lineNum, const char* fmt, ...)
    4343{
  • branches/blt4/packages/vizservers/vtkvis/Trace.h

    r2120 r2542  
    1414namespace VtkVis {
    1515
    16 extern void InitLog();
     16extern void initLog();
    1717
    18 extern void CloseLog();
     18extern void closeLog();
    1919
    20 extern void LogMessage(int priority, const char *funcname, const char *fileName, int lineNum,
    21                        const char* format, ...);
     20extern void logMessage(int priority, const char *funcname, const char *fileName,
     21                       int lineNum, const char* format, ...);
    2222
    23 #define ERROR(...)      LogMessage(LOG_ERR, __FUNCTION__, __FILE__, __LINE__, __VA_ARGS__)
     23#define ERROR(...)      Rappture::VtkVis::logMessage(LOG_ERR, __FUNCTION__, __FILE__, __LINE__, __VA_ARGS__)
    2424#ifdef WANT_TRACE
    25 #define TRACE(...)      LogMessage(LOG_DEBUG, __FUNCTION__, __FILE__, __LINE__, __VA_ARGS__)
     25#define TRACE(...)      Rappture::VtkVis::logMessage(LOG_DEBUG, __FUNCTION__, __FILE__, __LINE__, __VA_ARGS__)
    2626#else
    2727#define TRACE(...)
    28 #endif
    29 #define WARN(...)       LogMessage(LOG_WARNING, __FUNCTION__, __FILE__, __LINE__, __VA_ARGS__)
    30 #define INFO(...)       LogMessage(LOG_INFO, __FUNCTION__, __FILE__, __LINE__, __VA_ARGS__)
     28#endif  /*WANT_TRACE*/
     29#define WARN(...)       Rappture::VtkVis::logMessage(LOG_WARNING, __FUNCTION__, __FILE__, __LINE__, __VA_ARGS__)
     30#define INFO(...)       Rappture::VtkVis::logMessage(LOG_INFO, __FUNCTION__, __FILE__, __LINE__, __VA_ARGS__)
    3131
    3232}
  • branches/blt4/packages/vizservers/vtkvis/protocol.txt

    r2409 r2542  
    4040axis visible <axis> <bool>
    4141     <axis> = x|y|z|all
     42     Note: 'all' means all enabled axes.  To force all axes on, set each axis on
     43     individually -- however, it is best to let the server determine which of
     44     the individual axes are enabled based on the dataset bounds.
    4245
    4346camera get
     
    4750camera orient <quatW> <quatX> <quatY> <quatZ>
    4851       Set scene orientation using a quaternion
    49 camera ortho <x> <y> <width> <height>
    50        Supply world coordinate bounds of plot area for image camera mode
    51        Data is assumed to lie in XY plane (z = 0)
     52camera ortho <coordMode> <x> <y> <width> <height>
     53       <coordMode> = pixel|world
     54       Supply bounds of plot area for image camera mode
    5255camera pan <x> <y>
    5356       <x,y> viewport coordinates (window center at 0,0).  Positive x pan
     
    7073colormap delete <?colorMapName?>
    7174
    72 legend <colormapName> <legendTitle> <width> <height> <?datasetName?>
     75legend <colormapName> <legendType> <legendTitle> <width> <height> <numLabels> <?datasetName?>
    7376       Causes legend to be rendered and written back with labels and title
     77       (title may be left blank)
     78       <legendType> = scalar|vmag|vx|vy|vz
     79       <numLabels> Can be zero or more 'tick' value labels
     80       If datasetName is omitted, the cumulative data range of all data sets
     81       will be used to label the legend -- otherwise, the current setting of
     82       'dataset maprange' will be used to determine if the individual dataset
     83       range or cumulative range will be used.
    7484
    7585dataset add <datasetName> data follows <nbytes>
     86dataset color <r> <g> <b> <?datasetName?>
     87        Set color of outline bounding box
    7688dataset delete <?datasetName?>
    77 dataset getvalue world <x> <y> <z> <datasetName>
    78 dataset getvalue pixel <x> <y> <datasetName>
     89dataset getscalar world <x> <y> <z> <datasetName>
     90dataset getscalar pixel <x> <y> <datasetName>
     91dataset getvector world <x> <y> <z> <datasetName>
     92dataset getvector pixel <x> <y> <datasetName>
    7993        Use pixel for image camera mode
    8094dataset maprange <val>
     
    8599        "all"
    86100dataset opacity <val> <?datasetName?>
     101dataset outline <bool> <?datasetName?>
     102        Toggle wireframe outline of dataset's bounding box
    87103dataset scalar <scalarName> <?datasetName?>
    88104        Set the active scalar field to plot
     
    96112contour2d add contourlist <list> <?datasetName?>
    97113          list = {isoval1 isoval2 isoval3...}
     114contour2d color <r> <g> <b> <?datasetName?>
     115          synonym for linecolor
    98116contour2d delete <?datasetName?>
    99117contour2d lighting <bool> <?datasetName?>
    100118contour2d linecolor <r> <g> <b> <?datasetName?>
     119          synonym for color
    101120contour2d linewidth <val> <?datasetName?>
    102121contour2d opacity <val> <?datasetName?>
     
    128147glyphs ccolor r g b <?datasetName?>
    129148glyphs colormap <colorMapName> <?dataSetName?>
    130 glyphs colormode <scale|scalar|vector|ccolor> <?dataSetName?>
    131        Set the color mode: color by scale, scalar field or
    132        vector magnitude -- uses the current color map
     149glyphs colormode <scalar|vmag|ccolor> <?dataSetName?>
     150       Set the color mode: color by scalar field or
     151       vector magnitude -- uses the current color map,
     152       or ccolor for constant color
    133153glyphs delete <?dataSetName?>
    134154glyphs edges <bool> <?datasetName?>
     
    138158glyphs linecolor <r> <g> <b> <?datasetName?>
    139159glyphs linewidth <val> <?datasetName?>
     160glyphs normscale <bool> <?datasetName?>
     161       Control if data values are normalized to [0,1] range before applying
     162       glyph scaling factor (gscale)
    140163glyphs opacity <val> <?datasetName?>
    141164glyphs orient <qw> <qx> <qy> <qz> <?dataSetName?>
    142165glyphs pos <x> <y> <z> <?dataSetName?>
    143166glyphs scale <sx> <sy> <sz> <?dataSetName?>
    144 glyphs shape <arrow|cone|cube|cylinder|dodecahedron|icosahedron|octahedron|sphere|tetrahedron> <?datasetName?>
    145 glyphs smode <scalar|vector|vector_comp|off> <?dataSetName?>
     167glyphs shape <arrow|cone|cube|cylinder|dodecahedron|icosahedron|line|octahedron|sphere|tetrahedron> <?datasetName?>
     168glyphs smode <scalar|vmag|vcomp|off> <?dataSetName?>
    146169       Set the scaling mode: use the scalar field, vector magnitude
    147170       (uniform scale), vector components, or disable scaling
     
    149172glyphs wireframe <bool> <?datasetName?>
    150173
    151 heightmap add numcontours <n> <?dataSetName?>
     174heightmap add numcontours <n> <heightScale> <?dataSetName?>
    152175          Generate evenly spaced contours including range endpoints.  See also
    153176          'dataset maprange' command.
    154 heightmap add contourlist <list> <?dataSetName?>
     177heightmap add contourlist <list> <heightScale> <?dataSetName?>
    155178          list = {isoval1 isoval2 isoval3...}
    156179heightmap colormap <colorMapName> <?dataSetName?>
     180heightmap contourlist <list> <?dataSetName?>
    157181heightmap delete <?dataSetName?>
    158182heightmap edges <bool> <?dataSetName?>
     
    164188heightmap linecolor <r> <g> <b> <?dataSetName?>
    165189heightmap linewidth <width> <?dataSetName?>
     190heightmap numcontours <n> <?dataSetName?>
    166191heightmap opacity <value> <?dataSetName?>
    167192heightmap orient <qw> <qx> <qy> <qz> <?dataSetName?>
    168193heightmap pos <x> <y> <z> <?dataSetName?>
    169194heightmap scale <sx> <sy> <sz> <?dataSetName?>
     195heightmap surface <bool> <?dataSetName?>
     196          Toggle rendering of colormapped surface (mountain plot or cutplane)
    170197heightmap visible <bool> <?dataSetName?>
    171198heightmap volumeslice axis ratio <?dataSetName?>
    172199          For 3D data, select a slice along a principle axis of the volume. The
    173200          ratio is [0,1]
     201heightmap wireframe <bool> <?datasetName?>
    174202
    175203lic add <?datasetName?>
     
    218246polydata orient <qw> <qx> <qy> <qz> <?dataSetName?>
    219247polydata pos <x> <y> <z> <?dataSetName?>
     248polydata ptsize <size> <?dataSetName?>
    220249polydata scale <sx> <sy> <sz> <?dataSetName?>
    221250polydata visible <bool> <?datasetName?>
     
    223252
    224253pseudocolor add <?datasetName?>
     254pseudocolor ccolor r g b <?datasetName?>
    225255pseudocolor colormap <colormapName> <?datasetName?>
     256pseudocolor colormode <scalar|vmag|vx|vy|vz|ccolor> <?datasetName?>
     257            Set the field used to color the object.  'ccolor' means to use
     258            the constant color defined by the ccolor subcommand.  'scalar' uses
     259            the active scalar field.  'vmag' uses the magnitude of the current
     260            vector field, and 'vx','vy','vz' use the corresponding component of
     261            the active vector field.
    226262pseudocolor delete <?datasetName?>
    227263pseudocolor edges <bool> <?datasetName?>
     
    301337nv>image -type image -bytes <nbytes>
    302338  <binary RGB data>
    303 nv>image -type image -bbox {x1 y1 x2 y2} -bytes <nbytes>
     339nv>image -type image -bbox {x y w h} -bytes <nbytes>
    304340  <binary RGB data>
    305   Note: in this form, the bbox is the upper left and lower right screen corners
    306   in world coordinates.  This form is currently used only if the camera mode is
    307   set to 'image'.
    308 nv>legend <colormapName> <nbytes>
     341  The bounding box of the 2D image camera zoom region is supplied
     342  Note: The bbox coordinates are in the form used by 'camera ortho world ...':
     343  x,y - world coordinate of lower left corner, w,h - width height in world coords
     344  This form is currently used only if the camera mode is set to 'image'.
     345nv>legend <colormapName> <title> <rmin> <rmax> <nbytes>
    309346  <binary RGB data>
    310 nv>dataset value world <x> <y> <z> <value>
    311 nv>dataset value pixel <x> <y> <value>
     347nv>dataset scalar world <x> <y> <z> <value> <dataSetName>
     348nv>dataset scalar pixel <x> <y> <value> <dataSetName>
     349nv>dataset vector world <x> <y> <z> <valueX> <valueY> <valueZ> <dataSetName>
     350nv>dataset vector pixel <x> <y> <valueX> <valueY> <valueZ> <dataSetName>
    312351
    313352================================================================================
  • branches/blt4/packages/vizservers/vtkvis/vtkRpCubeAxesActor2D.cpp

    r2120 r2542  
    22
    33  Program:   Visualization Toolkit
    4   Module:    vtkCubeAxesActor2D.cxx
     4  Module:    vtkCubeAxesActor2D.cpp
    55
    66  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
     
    419419  this->YAxis->SetFontFactor(AxisFontFactor);
    420420  this->YAxis->SetProperty(this->GetProperty());
    421 
    422   this->ZAxis->GetPositionCoordinate()->SetValue(zCoords[0], zCoords[1]);
    423   this->ZAxis->GetPosition2Coordinate()->SetValue(zCoords[2], zCoords[3]);
    424   this->ZAxis->SetRange(zRange[0], zRange[1]);
     421  if ( this->YAxisVisibility ) {
     422      this->ZAxis->GetPositionCoordinate()->SetValue(zCoords[0], zCoords[1]);
     423      this->ZAxis->GetPosition2Coordinate()->SetValue(zCoords[2], zCoords[3]);
     424      this->ZAxis->SetRange(zRange[0], zRange[1]);
     425  } else {
     426      this->ZAxis->GetPositionCoordinate()->SetValue(zCoords[2], zCoords[3]);
     427      this->ZAxis->GetPosition2Coordinate()->SetValue(zCoords[0], zCoords[1]);
     428      this->ZAxis->SetRange(zRange[1], zRange[0]);
     429  }
    425430  this->ZAxis->SetTitle(this->Labels[zAxes]);
    426431  this->ZAxis->SetNumberOfLabels(this->NumberOfLabels);
Note: See TracChangeset for help on using the changeset viewer.