source: branches/1.3/packages/vizservers/vtkvis/RendererGraphicsObjs.cpp @ 3844

Last change on this file since 3844 was 3844, checked in by ldelgass, 11 years ago

Sync with trunk. Branch now differs only from trunk by r3722 (branch is version
1.3, trunk is version 1.4)

  • Property svn:eol-style set to native
File size: 102.0 KB
Line 
1/* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2/*
3 * Copyright (C) 2004-2012  HUBzero Foundation, LLC
4 *
5 * Author: Leif Delgass <ldelgass@purdue.edu>
6 */
7
8#include <cstring>
9#include <typeinfo>
10#include <vector>
11
12#include <vtkVersion.h>
13#include <vtkSmartPointer.h>
14#include <vtkDataSet.h>
15#include <vtkCharArray.h>
16#include <vtkDataSetReader.h>
17
18#include "RendererGraphicsObjs.h"
19#include "Renderer.h"
20#include "DataSet.h"
21#include "Box.h"
22#include "Contour2D.h"
23#include "Contour3D.h"
24#include "Cutplane.h"
25#include "Glyphs.h"
26#include "HeightMap.h"
27#include "LIC.h"
28#include "Line.h"
29#include "Molecule.h"
30#include "PolyData.h"
31#include "PseudoColor.h"
32#include "Sphere.h"
33#include "Streamlines.h"
34#include "Volume.h"
35#include "ColorMap.h"
36#include "Trace.h"
37
38// Template specializations
39namespace VtkVis {
40
41template<>
42Renderer::ArcHashmap &
43Renderer::getGraphicsObjectHashmap<Arc>()
44{ return _arcs; }
45
46template<>
47Renderer::ArrowHashmap &
48Renderer::getGraphicsObjectHashmap<Arrow>()
49{ return _arrows; }
50
51template<>
52Renderer::BoxHashmap &
53Renderer::getGraphicsObjectHashmap<Box>()
54{ return _boxes; }
55
56template<>
57Renderer::ConeHashmap &
58Renderer::getGraphicsObjectHashmap<Cone>()
59{ return _cones; }
60
61template<>
62Renderer::Contour2DHashmap &
63Renderer::getGraphicsObjectHashmap<Contour2D>()
64{ return _contour2Ds; }
65
66template<>
67Renderer::Contour3DHashmap &
68Renderer::getGraphicsObjectHashmap<Contour3D>()
69{ return _contour3Ds; }
70
71template<>
72Renderer::CutplaneHashmap &
73Renderer::getGraphicsObjectHashmap<Cutplane>()
74{ return _cutplanes; }
75
76template<>
77Renderer::CylinderHashmap &
78Renderer::getGraphicsObjectHashmap<Cylinder>()
79{ return _cylinders; }
80
81template<>
82Renderer::DiskHashmap &
83Renderer::getGraphicsObjectHashmap<Disk>()
84{ return _disks; }
85
86template<>
87Renderer::GlyphsHashmap &
88Renderer::getGraphicsObjectHashmap<Glyphs>()
89{ return _glyphs; }
90
91template<>
92Renderer::GroupHashmap &
93Renderer::getGraphicsObjectHashmap<Group>()
94{ return _groups; }
95
96template<>
97Renderer::HeightMapHashmap &
98Renderer::getGraphicsObjectHashmap<HeightMap>()
99{ return _heightMaps; }
100
101template<>
102Renderer::ImageHashmap &
103Renderer::getGraphicsObjectHashmap<Image>()
104{ return _images; }
105
106template<>
107Renderer::LICHashmap &
108Renderer::getGraphicsObjectHashmap<LIC>()
109{ return _lics; }
110
111template<>
112Renderer::LineHashmap &
113Renderer::getGraphicsObjectHashmap<Line>()
114{ return _lines; }
115
116template<>
117Renderer::MoleculeHashmap &
118Renderer::getGraphicsObjectHashmap<Molecule>()
119{ return _molecules; }
120
121template<>
122Renderer::OutlineHashmap &
123Renderer::getGraphicsObjectHashmap<Outline>()
124{ return _outlines; }
125
126template<>
127Renderer::PolyDataHashmap &
128Renderer::getGraphicsObjectHashmap<PolyData>()
129{ return _polyDatas; }
130
131template<>
132Renderer::PolygonHashmap &
133Renderer::getGraphicsObjectHashmap<Polygon>()
134{ return _polygons; }
135
136template<>
137Renderer::PseudoColorHashmap &
138Renderer::getGraphicsObjectHashmap<PseudoColor>()
139{ return _pseudoColors; }
140
141template<>
142Renderer::SphereHashmap &
143Renderer::getGraphicsObjectHashmap<Sphere>()
144{ return _spheres; }
145
146template<>
147Renderer::StreamlinesHashmap &
148Renderer::getGraphicsObjectHashmap<Streamlines>()
149{ return _streamlines; }
150
151template<>
152Renderer::Text3DHashmap &
153Renderer::getGraphicsObjectHashmap<Text3D>()
154{ return _text3Ds; }
155
156template<>
157Renderer::VolumeHashmap &
158Renderer::getGraphicsObjectHashmap<Volume>()
159{ return _volumes; }
160
161template<>
162Renderer::WarpHashmap &
163Renderer::getGraphicsObjectHashmap<Warp>()
164{ return _warps; }
165
166#if 0
167template Arc *Renderer::getGraphicsObject(const DataSetId&);
168template Arrow *Renderer::getGraphicsObject(const DataSetId&);
169template Box *Renderer::getGraphicsObject(const DataSetId&);
170template Cone *Renderer::getGraphicsObject(const DataSetId&);
171template Cylinder *Renderer::getGraphicsObject(const DataSetId&);
172template Disk *Renderer::getGraphicsObject(const DataSetId&);
173template Group *Renderer::getGraphicsObject(const DataSetId&);
174template Line *Renderer::getGraphicsObject(const DataSetId&);
175template Polygon *Renderer::getGraphicsObject(const DataSetId&);
176template Sphere *Renderer::getGraphicsObject(const DataSetId&);
177template Text3D *Renderer::getGraphicsObject(const DataSetId&);
178#endif
179
180template <>
181void Renderer::deleteGraphicsObject<Group>(const DataSetId& id)
182{
183    GroupHashmap& hashmap = getGraphicsObjectHashmap<Group>();
184    GroupHashmap::iterator itr;
185
186    bool doAll = false;
187
188    if (id.compare("all") == 0) {
189        itr = hashmap.begin();
190        doAll = true;
191    } else {
192        itr = hashmap.find(id);
193    }
194    if (itr == hashmap.end()) {
195        ERROR("Group not found: %s", id.c_str());
196        return;
197    }
198
199    TRACE("Deleting Group: %s", id.c_str());
200
201    do {
202        Group *gobj = itr->second;
203        if (gobj->getProp())
204            _renderer->RemoveViewProp(gobj->getProp());
205        if (gobj->getOverlayProp())
206            _renderer->RemoveViewProp(gobj->getOverlayProp());
207
208        std::vector<GraphicsObject *> children;
209        gobj->getChildren(children);
210
211        // Un-grouping children
212        for (std::vector<GraphicsObject *>::iterator citr = children.begin();
213             citr != children.end(); ++citr) {
214            if ((*citr)->getProp())
215                _renderer->AddViewProp((*citr)->getProp());
216            if ((*citr)->getOverlayProp())
217                _renderer->AddViewProp((*citr)->getOverlayProp());
218        }
219
220        delete gobj;
221
222        itr = hashmap.erase(itr);
223    } while (doAll && itr != hashmap.end());
224
225    sceneBoundsChanged();
226    _needsRedraw = true;
227}
228
229/**
230 * \brief Set the volume slice used for mapping volumetric data
231 */
232template <>
233void Renderer::setGraphicsObjectVolumeSlice<HeightMap>(const DataSetId& id, Axis axis, double ratio)
234{
235    HeightMapHashmap::iterator itr;
236
237    bool doAll = false;
238
239    if (id.compare("all") == 0) {
240        itr = _heightMaps.begin();
241        if (itr == _heightMaps.end())
242            return;
243        doAll = true;
244    } else {
245        itr = _heightMaps.find(id);
246    }
247
248    if (itr == _heightMaps.end()) {
249        ERROR("HeightMap not found: %s", id.c_str());
250        return;
251    }
252
253    do {
254        itr->second->selectVolumeSlice(axis, ratio);
255     } while (doAll && ++itr != _heightMaps.end());
256
257    sceneBoundsChanged();
258    _needsRedraw = true;
259}
260
261}
262
263using namespace VtkVis;
264
265GraphicsObject *
266Renderer::getGenericGraphicsObject(const DataSetId& id)
267{
268    GraphicsObject *gobj = NULL;
269
270    if ((gobj = getGraphicsObject<Arc>(id)) != NULL) {
271        return gobj;
272    }
273    if ((gobj = getGraphicsObject<Arrow>(id)) != NULL) {
274        return gobj;
275    }
276    if ((gobj = getGraphicsObject<Box>(id)) != NULL) {
277        return gobj;
278    }
279    if ((gobj = getGraphicsObject<Cone>(id)) != NULL) {
280        return gobj;
281    }
282    if ((gobj = getGraphicsObject<Cylinder>(id)) != NULL) {
283        return gobj;
284    }
285    if ((gobj = getGraphicsObject<Disk>(id)) != NULL) {
286        return gobj;
287    }
288    if ((gobj = getGraphicsObject<Line>(id)) != NULL) {
289        return gobj;
290    }
291    if ((gobj = getGraphicsObject<Polygon>(id)) != NULL) {
292        return gobj;
293    }
294    if ((gobj = getGraphicsObject<Sphere>(id)) != NULL) {
295        return gobj;
296    }
297    if ((gobj = getGraphicsObject<Text3D>(id)) != NULL) {
298        return gobj;
299    }
300    //
301    if ((gobj = getGraphicsObject<Contour2D>(id)) != NULL) {
302        return gobj;
303    }
304    if ((gobj = getGraphicsObject<Contour3D>(id)) != NULL) {
305        return gobj;
306    }
307    if ((gobj = getGraphicsObject<Cutplane>(id)) != NULL) {
308        return gobj;
309    }
310    if ((gobj = getGraphicsObject<Glyphs>(id)) != NULL) {
311        return gobj;
312    }
313    if ((gobj = getGraphicsObject<HeightMap>(id)) != NULL) {
314        return gobj;
315    }
316    if ((gobj = getGraphicsObject<Image>(id)) != NULL) {
317        return gobj;
318    }
319    if ((gobj = getGraphicsObject<LIC>(id)) != NULL) {
320        return gobj;
321    }
322    if ((gobj = getGraphicsObject<Molecule>(id)) != NULL) {
323        return gobj;
324    }
325    if ((gobj = getGraphicsObject<Outline>(id)) != NULL) {
326        return gobj;
327    }
328    if ((gobj = getGraphicsObject<PolyData>(id)) != NULL) {
329        return gobj;
330    }
331    if ((gobj = getGraphicsObject<PseudoColor>(id)) != NULL) {
332        return gobj;
333    }
334    if ((gobj = getGraphicsObject<Streamlines>(id)) != NULL) {
335        return gobj;
336    }
337    if ((gobj = getGraphicsObject<Volume>(id)) != NULL) {
338        return gobj;
339    }
340    if ((gobj = getGraphicsObject<Warp>(id)) != NULL) {
341        return gobj;
342    }
343    //
344    if ((gobj = getGraphicsObject<Group>(id)) != NULL) {
345        return gobj;
346    }
347
348    return NULL;
349}
350
351/**
352 * \brief Create a new Arc and associate it with an ID
353 */
354bool Renderer::addArc(const DataSetId& id,
355                      double center[3],
356                      double pt1[3],
357                      double normal[3],
358                      double angle)
359{
360    Arc *gobj;
361    if ((gobj = getGraphicsObject<Arc>(id)) != NULL) {
362        WARN("Replacing existing %s %s", gobj->getClassName(), id.c_str());
363        deleteGraphicsObject<Arc>(id);
364    }
365
366    gobj = new Arc();
367 
368    gobj->setDataSet(NULL, this);
369
370    if (gobj->getProp() == NULL &&
371        gobj->getOverlayProp() == NULL) {
372        delete gobj;
373        return false;
374    } else {
375        if (gobj->getProp())
376            _renderer->AddViewProp(gobj->getProp());
377        if (gobj->getOverlayProp())
378            _renderer->AddViewProp(gobj->getOverlayProp());
379    }
380
381    gobj->setCenter(center);
382    gobj->setStartPoint(pt1);
383    gobj->setNormal(normal);
384    gobj->setAngle(angle);
385
386    getGraphicsObjectHashmap<Arc>()[id] = gobj;
387
388    sceneBoundsChanged();
389    _needsRedraw = true;
390    return true;
391}
392
393/**
394 * \brief Set Arc resolution
395 */
396void Renderer::setArcResolution(const DataSetId& id, int res)
397{
398    ArcHashmap::iterator itr;
399
400    bool doAll = false;
401
402    if (id.compare("all") == 0) {
403        itr = _arcs.begin();
404        if (itr == _arcs.end())
405            return;
406        doAll = true;
407    } else {
408        itr = _arcs.find(id);
409    }
410    if (itr == _arcs.end()) {
411        ERROR("Arc not found: %s", id.c_str());
412        return;
413    }
414
415    do {
416        itr->second->setResolution(res);
417    } while (doAll && ++itr != _arcs.end());
418
419    sceneBoundsChanged();
420    _needsRedraw = true;
421}
422
423/**
424 * \brief Create a new Arrow and associate it with an ID
425 */
426bool Renderer::addArrow(const DataSetId& id, double tipRadius,
427                        double shaftRadius, double tipLength,
428                        bool flipNormals)
429{
430    Arrow *gobj;
431    if ((gobj = getGraphicsObject<Arrow>(id)) != NULL) {
432        WARN("Replacing existing %s %s", gobj->getClassName(), id.c_str());
433        deleteGraphicsObject<Arrow>(id);
434    }
435
436    gobj = new Arrow();
437 
438    gobj->setDataSet(NULL, this);
439
440    if (gobj->getProp() == NULL &&
441        gobj->getOverlayProp() == NULL) {
442        delete gobj;
443        return false;
444    } else {
445        if (gobj->getProp())
446            _renderer->AddViewProp(gobj->getProp());
447        if (gobj->getOverlayProp())
448            _renderer->AddViewProp(gobj->getOverlayProp());
449    }
450
451    gobj->setRadii(tipRadius, shaftRadius);
452    gobj->setTipLength(tipLength);
453    if (flipNormals)
454        gobj->flipNormals(flipNormals);
455
456    getGraphicsObjectHashmap<Arrow>()[id] = gobj;
457
458    sceneBoundsChanged();
459    _needsRedraw = true;
460    return true;
461}
462
463/**
464 * \brief Set Arrow resolution
465 */
466void Renderer::setArrowResolution(const DataSetId& id, int tipRes, int shaftRes)
467{
468    ArrowHashmap::iterator itr;
469
470    bool doAll = false;
471
472    if (id.compare("all") == 0) {
473        itr = _arrows.begin();
474        if (itr == _arrows.end())
475            return;
476        doAll = true;
477    } else {
478        itr = _arrows.find(id);
479    }
480    if (itr == _arrows.end()) {
481        ERROR("Arrow not found: %s", id.c_str());
482        return;
483    }
484
485    do {
486        itr->second->setResolution(tipRes, shaftRes);
487    } while (doAll && ++itr != _arrows.end());
488
489    sceneBoundsChanged();
490    _needsRedraw = true;
491}
492
493/**
494 * \brief Create a new Box and associate it with an ID
495 */
496bool Renderer::addBox(const DataSetId& id,
497                      double xLen, double yLen, double zLen,
498                      bool flipNormals)
499{
500    Box *gobj;
501    if ((gobj = getGraphicsObject<Box>(id)) != NULL) {
502        WARN("Replacing existing %s %s", gobj->getClassName(), id.c_str());
503        deleteGraphicsObject<Box>(id);
504    }
505
506    gobj = new Box();
507 
508    gobj->setDataSet(NULL, this);
509
510    if (gobj->getProp() == NULL &&
511        gobj->getOverlayProp() == NULL) {
512        delete gobj;
513        return false;
514    } else {
515        if (gobj->getProp())
516            _renderer->AddViewProp(gobj->getProp());
517        if (gobj->getOverlayProp())
518            _renderer->AddViewProp(gobj->getOverlayProp());
519    }
520
521    gobj->setSize(xLen, yLen, zLen);
522    if (flipNormals)
523        gobj->flipNormals(flipNormals);
524
525    getGraphicsObjectHashmap<Box>()[id] = gobj;
526
527    sceneBoundsChanged();
528    _needsRedraw = true;
529    return true;
530}
531
532/**
533 * \brief Create a new Cone and associate it with an ID
534 */
535bool Renderer::addCone(const DataSetId& id, double radius, double height,
536                       bool cap, bool flipNormals)
537{
538    Cone *gobj;
539    if ((gobj = getGraphicsObject<Cone>(id)) != NULL) {
540        WARN("Replacing existing %s %s", gobj->getClassName(), id.c_str());
541        deleteGraphicsObject<Cone>(id);
542    }
543
544    gobj = new Cone();
545 
546    gobj->setDataSet(NULL, this);
547
548    if (gobj->getProp() == NULL &&
549        gobj->getOverlayProp() == NULL) {
550        delete gobj;
551        return false;
552    } else {
553        if (gobj->getProp())
554            _renderer->AddViewProp(gobj->getProp());
555        if (gobj->getOverlayProp())
556            _renderer->AddViewProp(gobj->getOverlayProp());
557    }
558
559    gobj->setRadius(radius);
560    gobj->setHeight(height);
561    gobj->setCapping(cap);
562    if (flipNormals)
563        gobj->flipNormals(flipNormals);
564
565    getGraphicsObjectHashmap<Cone>()[id] = gobj;
566
567    sceneBoundsChanged();
568    _needsRedraw = true;
569    return true;
570}
571
572/**
573 * \brief Set Cone resolution
574 */
575void Renderer::setConeResolution(const DataSetId& id, int res)
576{
577    ConeHashmap::iterator itr;
578
579    bool doAll = false;
580
581    if (id.compare("all") == 0) {
582        itr = _cones.begin();
583        if (itr == _cones.end())
584            return;
585        doAll = true;
586    } else {
587        itr = _cones.find(id);
588    }
589    if (itr == _cones.end()) {
590        ERROR("Cone not found: %s", id.c_str());
591        return;
592    }
593
594    do {
595        itr->second->setResolution(res);
596    } while (doAll && ++itr != _cones.end());
597
598    sceneBoundsChanged();
599    _needsRedraw = true;
600}
601
602/**
603 * \brief Create a new Contour2D and associate it with the named DataSet
604 */
605bool Renderer::addContour2D(const DataSetId& id, int numContours)
606{
607    DataSetHashmap::iterator itr;
608
609    bool doAll = false;
610
611    if (id.compare("all") == 0) {
612        itr = _dataSets.begin();
613    } else {
614        itr = _dataSets.find(id);
615    }
616    if (itr == _dataSets.end()) {
617        ERROR("Unknown dataset %s", id.c_str());
618        return false;
619    }
620
621    do {
622        DataSet *ds = itr->second;
623        const DataSetId& dsID = ds->getName();
624
625        if (getGraphicsObject<Contour2D>(dsID)) {
626            WARN("Replacing existing Contour2D %s", dsID.c_str());
627            deleteGraphicsObject<Contour2D>(dsID);
628        }
629
630        Contour2D *contour = new Contour2D(numContours);
631 
632        contour->setDataSet(ds, this);
633
634        if (contour->getProp() == NULL) {
635            delete contour;
636            return false;
637        } else {
638            _renderer->AddViewProp(contour->getProp());
639        }
640
641        _contour2Ds[dsID] = contour;
642    } while (doAll && ++itr != _dataSets.end());
643
644    sceneBoundsChanged();
645    _needsRedraw = true;
646    return true;
647}
648
649/**
650 * \brief Create a new Contour2D and associate it with the named DataSet
651 */
652bool Renderer::addContour2D(const DataSetId& id, const std::vector<double>& contours)
653{
654    DataSetHashmap::iterator itr;
655
656    bool doAll = false;
657
658    if (id.compare("all") == 0) {
659        itr = _dataSets.begin();
660    } else {
661        itr = _dataSets.find(id);
662    }
663    if (itr == _dataSets.end()) {
664        ERROR("Unknown dataset %s", id.c_str());
665        return false;
666    }
667
668    do {
669        DataSet *ds = itr->second;
670        const DataSetId& dsID = ds->getName();
671
672        if (getGraphicsObject<Contour2D>(dsID)) {
673            WARN("Replacing existing Contour2D %s", dsID.c_str());
674            deleteGraphicsObject<Contour2D>(dsID);
675        }
676
677        Contour2D *contour = new Contour2D(contours);
678
679        contour->setDataSet(ds, this);
680
681        if (contour->getProp() == NULL) {
682            delete contour;
683            return false;
684        } else {
685            _renderer->AddViewProp(contour->getProp());
686        }
687
688        _contour2Ds[dsID] = contour;
689    } while (doAll && ++itr != _dataSets.end());
690
691    sceneBoundsChanged();
692    _needsRedraw = true;
693    return true;
694}
695
696/**
697 * \brief Set the number of equally spaced contour isolines for the given DataSet
698 */
699void Renderer::setContour2DNumContours(const DataSetId& id, int numContours)
700{
701    Contour2DHashmap::iterator itr;
702
703    bool doAll = false;
704
705    if (id.compare("all") == 0) {
706        itr = _contour2Ds.begin();
707        doAll = true;
708    } else {
709        itr = _contour2Ds.find(id);
710    }
711    if (itr == _contour2Ds.end()) {
712        ERROR("Contour2D not found: %s", id.c_str());
713        return;
714    }
715
716    do {
717        itr->second->setNumContours(numContours);
718    } while (doAll && ++itr != _contour2Ds.end());
719
720    sceneBoundsChanged();
721    _needsRedraw = true;
722}
723
724/**
725 * \brief Set the number of equally spaced isosurfaces for the given DataSet
726 */
727void Renderer::setContour2DContourField(const DataSetId& id, const char *fieldName)
728{
729    Contour2DHashmap::iterator itr;
730
731    bool doAll = false;
732
733    if (id.compare("all") == 0) {
734        itr = _contour2Ds.begin();
735        doAll = true;
736    } else {
737        itr = _contour2Ds.find(id);
738    }
739    if (itr == _contour2Ds.end()) {
740        ERROR("Contour2D not found: %s", id.c_str());
741        return;
742    }
743
744    do {
745        itr->second->setContourField(fieldName);
746     } while (doAll && ++itr != _contour2Ds.end());
747
748    sceneBoundsChanged();
749    _needsRedraw = true;
750}
751
752/**
753 * \brief Set a list of isovalues for the given DataSet
754 */
755void Renderer::setContour2DContourList(const DataSetId& id, const std::vector<double>& contours)
756{
757    Contour2DHashmap::iterator itr;
758
759    bool doAll = false;
760
761    if (id.compare("all") == 0) {
762        itr = _contour2Ds.begin();
763        doAll = true;
764    } else {
765        itr = _contour2Ds.find(id);
766    }
767    if (itr == _contour2Ds.end()) {
768        ERROR("Contour2D not found: %s", id.c_str());
769        return;
770    }
771
772    do {
773        itr->second->setContourList(contours);
774    } while (doAll && ++itr != _contour2Ds.end());
775
776    sceneBoundsChanged();
777     _needsRedraw = true;
778}
779
780/**
781 * \brief Set the color mode for the specified DataSet
782 */
783void Renderer::setContour2DColorMode(const DataSetId& id,
784                                     Contour2D::ColorMode mode,
785                                     DataSet::DataAttributeType type,
786                                     const char *name, double range[2])
787{
788    Contour2DHashmap::iterator itr;
789
790    bool doAll = false;
791
792    if (id.compare("all") == 0) {
793        itr = _contour2Ds.begin();
794        if (itr == _contour2Ds.end())
795            return;
796        doAll = true;
797    } else {
798        itr = _contour2Ds.find(id);
799    }
800    if (itr == _contour2Ds.end()) {
801        ERROR("Contour2D not found: %s", id.c_str());
802        return;
803    }
804
805    do {
806        itr->second->setColorMode(mode, type, name, range);
807    } while (doAll && ++itr != _contour2Ds.end());
808
809    _needsRedraw = true;
810}
811
812/**
813 * \brief Set the color mode for the specified DataSet
814 */
815void Renderer::setContour2DColorMode(const DataSetId& id,
816                                     Contour2D::ColorMode mode,
817                                     const char *name, double range[2])
818{
819    Contour2DHashmap::iterator itr;
820
821    bool doAll = false;
822
823    if (id.compare("all") == 0) {
824        itr = _contour2Ds.begin();
825        if (itr == _contour2Ds.end())
826            return;
827        doAll = true;
828    } else {
829        itr = _contour2Ds.find(id);
830    }
831    if (itr == _contour2Ds.end()) {
832        ERROR("Contour2D not found: %s", id.c_str());
833        return;
834    }
835
836    do {
837        itr->second->setColorMode(mode, name, range);
838    } while (doAll && ++itr != _contour2Ds.end());
839
840    _needsRedraw = true;
841}
842
843/**
844 * \brief Create a new Contour3D and associate it with the named DataSet
845 */
846bool Renderer::addContour3D(const DataSetId& id, int numContours)
847{
848    DataSetHashmap::iterator itr;
849
850    bool doAll = false;
851
852    if (id.compare("all") == 0) {
853        itr = _dataSets.begin();
854    } else {
855        itr = _dataSets.find(id);
856    }
857    if (itr == _dataSets.end()) {
858        ERROR("Unknown dataset %s", id.c_str());
859        return false;
860    }
861
862    do {
863        DataSet *ds = itr->second;
864        const DataSetId& dsID = ds->getName();
865
866        if (getGraphicsObject<Contour3D>(dsID)) {
867            WARN("Replacing existing Contour3D %s", dsID.c_str());
868            deleteGraphicsObject<Contour3D>(dsID);
869        }
870
871        Contour3D *contour = new Contour3D(numContours);
872
873        contour->setDataSet(ds, this);
874
875        if (contour->getProp() == NULL) {
876            delete contour;
877            return false;
878        } else {
879            _renderer->AddViewProp(contour->getProp());
880        }
881
882        _contour3Ds[dsID] = contour;
883    } while (doAll && ++itr != _dataSets.end());
884
885    sceneBoundsChanged();
886    _needsRedraw = true;
887    return true;
888}
889
890/**
891 * \brief Create a new Contour3D and associate it with the named DataSet
892 */
893bool Renderer::addContour3D(const DataSetId& id,const std::vector<double>& contours)
894{
895    DataSetHashmap::iterator itr;
896
897    bool doAll = false;
898
899    if (id.compare("all") == 0) {
900        itr = _dataSets.begin();
901    } else {
902        itr = _dataSets.find(id);
903    }
904    if (itr == _dataSets.end()) {
905        ERROR("Unknown dataset %s", id.c_str());
906        return false;
907    }
908
909    do {
910        DataSet *ds = itr->second;
911        const DataSetId& dsID = ds->getName();
912
913        if (getGraphicsObject<Contour3D>(dsID)) {
914            WARN("Replacing existing Contour3D %s", dsID.c_str());
915            deleteGraphicsObject<Contour3D>(dsID);
916        }
917
918        Contour3D *contour = new Contour3D(contours);
919
920        contour->setDataSet(ds, this);
921
922        if (contour->getProp() == NULL) {
923            delete contour;
924            return false;
925        } else {
926            _renderer->AddViewProp(contour->getProp());
927        }
928
929        _contour3Ds[dsID] = contour;
930    } while (doAll && ++itr != _dataSets.end());
931
932    sceneBoundsChanged();
933    _needsRedraw = true;
934    return true;
935}
936
937/**
938 * \brief Set the number of equally spaced isosurfaces for the given DataSet
939 */
940void Renderer::setContour3DContourField(const DataSetId& id, const char *fieldName)
941{
942    Contour3DHashmap::iterator itr;
943
944    bool doAll = false;
945
946    if (id.compare("all") == 0) {
947        itr = _contour3Ds.begin();
948        doAll = true;
949    } else {
950        itr = _contour3Ds.find(id);
951    }
952    if (itr == _contour3Ds.end()) {
953        ERROR("Contour3D not found: %s", id.c_str());
954        return;
955    }
956
957    do {
958        itr->second->setContourField(fieldName);
959     } while (doAll && ++itr != _contour3Ds.end());
960
961    sceneBoundsChanged();
962    _needsRedraw = true;
963}
964
965/**
966 * \brief Set the number of equally spaced isosurfaces for the given DataSet
967 */
968void Renderer::setContour3DNumContours(const DataSetId& id, int numContours)
969{
970    Contour3DHashmap::iterator itr;
971
972    bool doAll = false;
973
974    if (id.compare("all") == 0) {
975        itr = _contour3Ds.begin();
976        doAll = true;
977    } else {
978        itr = _contour3Ds.find(id);
979    }
980    if (itr == _contour3Ds.end()) {
981        ERROR("Contour3D not found: %s", id.c_str());
982        return;
983    }
984
985    do {
986        itr->second->setNumContours(numContours);
987     } while (doAll && ++itr != _contour3Ds.end());
988
989    sceneBoundsChanged();
990    _needsRedraw = true;
991}
992
993/**
994 * \brief Set a list of isovalues for the given DataSet
995 */
996void Renderer::setContour3DContourList(const DataSetId& id, const std::vector<double>& contours)
997{
998    Contour3DHashmap::iterator itr;
999
1000    bool doAll = false;
1001
1002    if (id.compare("all") == 0) {
1003        itr = _contour3Ds.begin();
1004        doAll = true;
1005    } else {
1006        itr = _contour3Ds.find(id);
1007    }
1008    if (itr == _contour3Ds.end()) {
1009        ERROR("Contour3D not found: %s", id.c_str());
1010        return;
1011    }
1012
1013    do {
1014        itr->second->setContourList(contours);
1015    } while (doAll && ++itr != _contour3Ds.end());
1016
1017    sceneBoundsChanged();
1018    _needsRedraw = true;
1019}
1020
1021/**
1022 * \brief Set the color mode for the specified DataSet
1023 */
1024void Renderer::setContour3DColorMode(const DataSetId& id,
1025                                     Contour3D::ColorMode mode,
1026                                     DataSet::DataAttributeType type,
1027                                     const char *name, double range[2])
1028{
1029    Contour3DHashmap::iterator itr;
1030
1031    bool doAll = false;
1032
1033    if (id.compare("all") == 0) {
1034        itr = _contour3Ds.begin();
1035        if (itr == _contour3Ds.end())
1036            return;
1037        doAll = true;
1038    } else {
1039        itr = _contour3Ds.find(id);
1040    }
1041    if (itr == _contour3Ds.end()) {
1042        ERROR("Contour3D not found: %s", id.c_str());
1043        return;
1044    }
1045
1046    do {
1047        itr->second->setColorMode(mode, type, name, range);
1048    } while (doAll && ++itr != _contour3Ds.end());
1049
1050    _needsRedraw = true;
1051}
1052
1053/**
1054 * \brief Set the color mode for the specified DataSet
1055 */
1056void Renderer::setContour3DColorMode(const DataSetId& id,
1057                                     Contour3D::ColorMode mode,
1058                                     const char *name, double range[2])
1059{
1060    Contour3DHashmap::iterator itr;
1061
1062    bool doAll = false;
1063
1064    if (id.compare("all") == 0) {
1065        itr = _contour3Ds.begin();
1066        if (itr == _contour3Ds.end())
1067            return;
1068        doAll = true;
1069    } else {
1070        itr = _contour3Ds.find(id);
1071    }
1072    if (itr == _contour3Ds.end()) {
1073        ERROR("Contour3D not found: %s", id.c_str());
1074        return;
1075    }
1076
1077    do {
1078        itr->second->setColorMode(mode, name, range);
1079    } while (doAll && ++itr != _contour3Ds.end());
1080
1081    _needsRedraw = true;
1082}
1083
1084/**
1085 * \brief Set the visibility of cutplane outlines
1086 */
1087void Renderer::setCutplaneOutlineVisibility(const DataSetId& id, bool state)
1088{
1089    CutplaneHashmap::iterator itr;
1090
1091    bool doAll = false;
1092
1093    if (id.compare("all") == 0) {
1094        itr = _cutplanes.begin();
1095        if (itr == _cutplanes.end())
1096            return;
1097        doAll = true;
1098    } else {
1099        itr = _cutplanes.find(id);
1100    }
1101
1102    if (itr == _cutplanes.end()) {
1103        ERROR("Cutplane not found: %s", id.c_str());
1104        return;
1105    }
1106
1107    do {
1108        itr->second->setOutlineVisibility(state);
1109     } while (doAll && ++itr != _cutplanes.end());
1110
1111    sceneBoundsChanged();
1112    _needsRedraw = true;
1113}
1114
1115/**
1116 * \brief Set the visibility of slices in one of the three axes
1117 */
1118void Renderer::setCutplaneSliceVisibility(const DataSetId& id, Axis axis, bool state)
1119{
1120    CutplaneHashmap::iterator itr;
1121
1122    bool doAll = false;
1123
1124    if (id.compare("all") == 0) {
1125        itr = _cutplanes.begin();
1126        if (itr == _cutplanes.end())
1127            return;
1128        doAll = true;
1129    } else {
1130        itr = _cutplanes.find(id);
1131    }
1132
1133    if (itr == _cutplanes.end()) {
1134        ERROR("Cutplane not found: %s", id.c_str());
1135        return;
1136    }
1137
1138    do {
1139        itr->second->setSliceVisibility(axis, state);
1140     } while (doAll && ++itr != _cutplanes.end());
1141
1142    sceneBoundsChanged();
1143    _needsRedraw = true;
1144}
1145
1146/**
1147 * \brief Set the point cloud render style for the specified DataSet
1148 */
1149void Renderer::setCutplaneCloudStyle(const DataSetId& id,
1150                                     Cutplane::CloudStyle style)
1151{
1152    CutplaneHashmap::iterator itr;
1153
1154    bool doAll = false;
1155
1156    if (id.compare("all") == 0) {
1157        itr = _cutplanes.begin();
1158        if (itr == _cutplanes.end())
1159            return;
1160        doAll = true;
1161    } else {
1162        itr = _cutplanes.find(id);
1163    }
1164    if (itr == _cutplanes.end()) {
1165        ERROR("Cutplane not found: %s", id.c_str());
1166        return;
1167    }
1168
1169    do {
1170        itr->second->setCloudStyle(style);
1171    } while (doAll && ++itr != _cutplanes.end());
1172
1173    _needsRedraw = true;
1174}
1175
1176/**
1177 * \brief Set the color mode for the specified DataSet
1178 */
1179void Renderer::setCutplaneColorMode(const DataSetId& id,
1180                                    Cutplane::ColorMode mode,
1181                                    DataSet::DataAttributeType type,
1182                                    const char *name, double range[2])
1183{
1184    CutplaneHashmap::iterator itr;
1185
1186    bool doAll = false;
1187
1188    if (id.compare("all") == 0) {
1189        itr = _cutplanes.begin();
1190        if (itr == _cutplanes.end())
1191            return;
1192        doAll = true;
1193    } else {
1194        itr = _cutplanes.find(id);
1195    }
1196    if (itr == _cutplanes.end()) {
1197        ERROR("Cutplane not found: %s", id.c_str());
1198        return;
1199    }
1200
1201    do {
1202        itr->second->setColorMode(mode, type, name, range);
1203    } while (doAll && ++itr != _cutplanes.end());
1204
1205    _needsRedraw = true;
1206}
1207
1208/**
1209 * \brief Set the color mode for the specified DataSet
1210 */
1211void Renderer::setCutplaneColorMode(const DataSetId& id,
1212                                    Cutplane::ColorMode mode,
1213                                    const char *name, double range[2])
1214{
1215    CutplaneHashmap::iterator itr;
1216
1217    bool doAll = false;
1218
1219    if (id.compare("all") == 0) {
1220        itr = _cutplanes.begin();
1221        if (itr == _cutplanes.end())
1222            return;
1223        doAll = true;
1224    } else {
1225        itr = _cutplanes.find(id);
1226    }
1227    if (itr == _cutplanes.end()) {
1228        ERROR("Cutplane not found: %s", id.c_str());
1229        return;
1230    }
1231
1232    do {
1233        itr->second->setColorMode(mode, name, range);
1234    } while (doAll && ++itr != _cutplanes.end());
1235
1236    _needsRedraw = true;
1237}
1238
1239/**
1240 * \brief Create a new Cylinder and associate it with an ID
1241 */
1242bool Renderer::addCylinder(const DataSetId& id, double radius, double height,
1243                           bool cap, bool flipNormals)
1244{
1245    Cylinder *gobj;
1246    if ((gobj = getGraphicsObject<Cylinder>(id)) != NULL) {
1247        WARN("Replacing existing %s %s", gobj->getClassName(), id.c_str());
1248        deleteGraphicsObject<Cylinder>(id);
1249    }
1250
1251    gobj = new Cylinder();
1252 
1253    gobj->setDataSet(NULL, this);
1254
1255    if (gobj->getProp() == NULL &&
1256        gobj->getOverlayProp() == NULL) {
1257        delete gobj;
1258        return false;
1259    } else {
1260        if (gobj->getProp())
1261            _renderer->AddViewProp(gobj->getProp());
1262        if (gobj->getOverlayProp())
1263            _renderer->AddViewProp(gobj->getOverlayProp());
1264    }
1265
1266    gobj->setRadius(radius);
1267    gobj->setHeight(height);
1268    gobj->setCapping(cap);
1269    if (flipNormals)
1270        gobj->flipNormals(flipNormals);
1271
1272    getGraphicsObjectHashmap<Cylinder>()[id] = gobj;
1273
1274    sceneBoundsChanged();
1275    _needsRedraw = true;
1276    return true;
1277}
1278
1279/**
1280 * \brief Set Cylinder capping
1281 */
1282void Renderer::setCylinderCapping(const DataSetId& id, bool state)
1283{
1284    CylinderHashmap::iterator itr;
1285
1286    bool doAll = false;
1287
1288    if (id.compare("all") == 0) {
1289        itr = _cylinders.begin();
1290        if (itr == _cylinders.end())
1291            return;
1292        doAll = true;
1293    } else {
1294        itr = _cylinders.find(id);
1295    }
1296    if (itr == _cylinders.end()) {
1297        ERROR("Cylinder not found: %s", id.c_str());
1298        return;
1299    }
1300
1301    do {
1302        itr->second->setCapping(state);
1303    } while (doAll && ++itr != _cylinders.end());
1304
1305    sceneBoundsChanged();
1306    _needsRedraw = true;
1307}
1308
1309/**
1310 * \brief Set Cylinder resolution
1311 */
1312void Renderer::setCylinderResolution(const DataSetId& id, int res)
1313{
1314    CylinderHashmap::iterator itr;
1315
1316    bool doAll = false;
1317
1318    if (id.compare("all") == 0) {
1319        itr = _cylinders.begin();
1320        if (itr == _cylinders.end())
1321            return;
1322        doAll = true;
1323    } else {
1324        itr = _cylinders.find(id);
1325    }
1326    if (itr == _cylinders.end()) {
1327        ERROR("Cylinder not found: %s", id.c_str());
1328        return;
1329    }
1330
1331    do {
1332        itr->second->setResolution(res);
1333    } while (doAll && ++itr != _cylinders.end());
1334
1335    sceneBoundsChanged();
1336    _needsRedraw = true;
1337}
1338
1339/**
1340 * \brief Create a new Disk and associate it with an ID
1341 */
1342bool Renderer::addDisk(const DataSetId& id,
1343                       double innerRadius,
1344                       double outerRadius,
1345                       bool flipNormals)
1346{
1347    Disk *gobj;
1348    if ((gobj = getGraphicsObject<Disk>(id)) != NULL) {
1349        WARN("Replacing existing %s %s", gobj->getClassName(), id.c_str());
1350        deleteGraphicsObject<Disk>(id);
1351    }
1352
1353    gobj = new Disk();
1354 
1355    gobj->setDataSet(NULL, this);
1356
1357    if (gobj->getProp() == NULL &&
1358        gobj->getOverlayProp() == NULL) {
1359        delete gobj;
1360        return false;
1361    } else {
1362        if (gobj->getProp())
1363            _renderer->AddViewProp(gobj->getProp());
1364        if (gobj->getOverlayProp())
1365            _renderer->AddViewProp(gobj->getOverlayProp());
1366    }
1367
1368    gobj->setRadii(innerRadius, outerRadius);
1369    if (flipNormals)
1370        gobj->flipNormals(flipNormals);
1371
1372    getGraphicsObjectHashmap<Disk>()[id] = gobj;
1373
1374    sceneBoundsChanged();
1375    _needsRedraw = true;
1376    return true;
1377}
1378
1379/**
1380 * \brief Set Disk resolution
1381 */
1382void Renderer::setDiskResolution(const DataSetId& id, int resRadial, int resCircum)
1383{
1384    DiskHashmap::iterator itr;
1385
1386    bool doAll = false;
1387
1388    if (id.compare("all") == 0) {
1389        itr = _disks.begin();
1390        if (itr == _disks.end())
1391            return;
1392        doAll = true;
1393    } else {
1394        itr = _disks.find(id);
1395    }
1396    if (itr == _disks.end()) {
1397        ERROR("Disk not found: %s", id.c_str());
1398        return;
1399    }
1400
1401    do {
1402        itr->second->setResolution(resRadial, resCircum);
1403    } while (doAll && ++itr != _disks.end());
1404
1405    sceneBoundsChanged();
1406    _needsRedraw = true;
1407}
1408
1409/**
1410 * \brief Create a new Glyphs and associate it with the named DataSet
1411 */
1412bool Renderer::addGlyphs(const DataSetId& id, Glyphs::GlyphShape shape)
1413{
1414    DataSetHashmap::iterator itr;
1415
1416    bool doAll = false;
1417
1418    if (id.compare("all") == 0) {
1419        itr = _dataSets.begin();
1420    } else {
1421        itr = _dataSets.find(id);
1422    }
1423    if (itr == _dataSets.end()) {
1424        ERROR("Unknown dataset %s", id.c_str());
1425        return false;
1426    }
1427
1428    do {
1429        DataSet *ds = itr->second;
1430        const DataSetId& dsID = ds->getName();
1431
1432        if (getGraphicsObject<Glyphs>(dsID)) {
1433            WARN("Replacing existing Glyphs %s", dsID.c_str());
1434            deleteGraphicsObject<Glyphs>(dsID);
1435        }
1436
1437        Glyphs *glyphs = new Glyphs(shape);
1438
1439        glyphs->setDataSet(ds, this);
1440
1441        if (glyphs->getProp() == NULL) {
1442            delete glyphs;
1443            return false;
1444        } else {
1445            _renderer->AddViewProp(glyphs->getProp());
1446        }
1447
1448        _glyphs[dsID] = glyphs;
1449    } while (doAll && ++itr != _dataSets.end());
1450
1451    sceneBoundsChanged();
1452    _needsRedraw = true;
1453    return true;
1454}
1455
1456/**
1457 * \brief Set the color mode for the specified DataSet
1458 */
1459void Renderer::setGlyphsColorMode(const DataSetId& id,
1460                                  Glyphs::ColorMode mode,
1461                                  const char *name, double range[2])
1462{
1463    GlyphsHashmap::iterator itr;
1464
1465    bool doAll = false;
1466
1467    if (id.compare("all") == 0) {
1468        itr = _glyphs.begin();
1469        if (itr == _glyphs.end())
1470            return;
1471        doAll = true;
1472    } else {
1473        itr = _glyphs.find(id);
1474    }
1475    if (itr == _glyphs.end()) {
1476        ERROR("Glyphs not found: %s", id.c_str());
1477        return;
1478    }
1479
1480    do {
1481        itr->second->setColorMode(mode, name, range);
1482    } while (doAll && ++itr != _glyphs.end());
1483
1484    _needsRedraw = true;
1485}
1486
1487/**
1488 * \brief Controls the array used to scale glyphs for the given DataSet
1489 */
1490void Renderer::setGlyphsScalingMode(const DataSetId& id,
1491                                    Glyphs::ScalingMode mode,
1492                                    const char *name, double range[2])
1493{
1494    GlyphsHashmap::iterator itr;
1495
1496    bool doAll = false;
1497
1498    if (id.compare("all") == 0) {
1499        itr = _glyphs.begin();
1500        if (itr == _glyphs.end())
1501            return;
1502        doAll = true;
1503    } else {
1504        itr = _glyphs.find(id);
1505    }
1506    if (itr == _glyphs.end()) {
1507        ERROR("Glyphs not found: %s", id.c_str());
1508        return;
1509    }
1510
1511    do {
1512        itr->second->setScalingMode(mode, name, range);
1513    } while (doAll && ++itr != _glyphs.end());
1514
1515    sceneBoundsChanged();
1516    _needsRedraw = true;
1517}
1518
1519/**
1520 * \brief Limit the number of glyphs displayed
1521 *
1522 * The choice of glyphs to display can be based on sampling every
1523 * n-th point (ratio) or by random sample
1524 *
1525 * \param max Maximum number of glyphs to display, negative means display all
1526 * \param random Flag to enable/disable random sampling
1527 * \param offset If random is false, this controls the first sample point
1528 * \param ratio If random is false, this ratio controls every n-th point sampling
1529 */
1530void Renderer::setGlyphsMaximumNumberOfGlyphs(const DataSetId& id, int max,
1531                                              bool random, int offset, int ratio)
1532{
1533    GlyphsHashmap::iterator itr;
1534
1535    bool doAll = false;
1536
1537    if (id.compare("all") == 0) {
1538        itr = _glyphs.begin();
1539        if (itr == _glyphs.end())
1540            return;
1541        doAll = true;
1542    } else {
1543        itr = _glyphs.find(id);
1544    }
1545    if (itr == _glyphs.end()) {
1546        ERROR("Glyphs not found: %s", id.c_str());
1547        return;
1548    }
1549
1550    do {
1551        itr->second->setMaximumNumberOfGlyphs(max, random, offset, ratio);
1552    } while (doAll && ++itr != _glyphs.end());
1553
1554    sceneBoundsChanged();
1555    _needsRedraw = true;
1556}
1557
1558/**
1559 * \brief Controls if field data range is normalized to [0,1] before
1560 * applying scale factor for the given DataSet
1561 */
1562void Renderer::setGlyphsNormalizeScale(const DataSetId& id, bool normalize)
1563{
1564    GlyphsHashmap::iterator itr;
1565
1566    bool doAll = false;
1567
1568    if (id.compare("all") == 0) {
1569        itr = _glyphs.begin();
1570        if (itr == _glyphs.end())
1571            return;
1572        doAll = true;
1573    } else {
1574        itr = _glyphs.find(id);
1575    }
1576    if (itr == _glyphs.end()) {
1577        ERROR("Glyphs not found: %s", id.c_str());
1578        return;
1579    }
1580
1581    do {
1582        itr->second->setNormalizeScale(normalize);
1583    } while (doAll && ++itr != _glyphs.end());
1584
1585    sceneBoundsChanged();
1586    _needsRedraw = true;
1587}
1588
1589/**
1590 * \brief Controls if glyphs are oriented from a vector field for the
1591 * given DataSet
1592 */
1593void Renderer::setGlyphsOrientMode(const DataSetId& id, bool state,
1594                                   const char *name)
1595{
1596    GlyphsHashmap::iterator itr;
1597
1598    bool doAll = false;
1599
1600    if (id.compare("all") == 0) {
1601        itr = _glyphs.begin();
1602        if (itr == _glyphs.end())
1603            return;
1604        doAll = true;
1605    } else {
1606        itr = _glyphs.find(id);
1607    }
1608    if (itr == _glyphs.end()) {
1609        ERROR("Glyphs not found: %s", id.c_str());
1610        return;
1611    }
1612
1613    do {
1614        itr->second->setOrientMode(state, name);
1615    } while (doAll && ++itr != _glyphs.end());
1616
1617    sceneBoundsChanged();
1618    _needsRedraw = true;
1619}
1620
1621/**
1622 * \brief Set glyph shape resolution
1623 */
1624void Renderer::setGlyphsQuality(const DataSetId& id, double quality)
1625{
1626    GlyphsHashmap::iterator itr;
1627
1628    bool doAll = false;
1629
1630    if (id.compare("all") == 0) {
1631        itr = _glyphs.begin();
1632        if (itr == _glyphs.end())
1633            return;
1634        doAll = true;
1635    } else {
1636        itr = _glyphs.find(id);
1637    }
1638    if (itr == _glyphs.end()) {
1639        ERROR("Glyphs not found: %s", id.c_str());
1640        return;
1641    }
1642
1643    do {
1644        itr->second->setQuality(quality);
1645    } while (doAll && ++itr != _glyphs.end());
1646
1647    sceneBoundsChanged();
1648    _needsRedraw = true;
1649}
1650
1651/**
1652 * \brief Set the shape of Glyphs for the given DataSet
1653 */
1654void Renderer::setGlyphsShape(const DataSetId& id, Glyphs::GlyphShape shape)
1655{
1656    GlyphsHashmap::iterator itr;
1657
1658    bool doAll = false;
1659
1660    if (id.compare("all") == 0) {
1661        itr = _glyphs.begin();
1662        if (itr == _glyphs.end())
1663            return;
1664        doAll = true;
1665    } else {
1666        itr = _glyphs.find(id);
1667    }
1668    if (itr == _glyphs.end()) {
1669        ERROR("Glyphs not found: %s", id.c_str());
1670        return;
1671    }
1672
1673    do {
1674        itr->second->setGlyphShape(shape);
1675    } while (doAll && ++itr != _glyphs.end());
1676
1677    sceneBoundsChanged();
1678    _needsRedraw = true;
1679}
1680
1681/**
1682 * \brief Set the glyph scaling factor for the given DataSet
1683 */
1684void Renderer::setGlyphsScaleFactor(const DataSetId& id, double scale)
1685{
1686    GlyphsHashmap::iterator itr;
1687
1688    bool doAll = false;
1689
1690    if (id.compare("all") == 0) {
1691        itr = _glyphs.begin();
1692        if (itr == _glyphs.end())
1693            return;
1694        doAll = true;
1695    } else {
1696        itr = _glyphs.find(id);
1697    }
1698    if (itr == _glyphs.end()) {
1699        ERROR("Glyphs not found: %s", id.c_str());
1700        return;
1701    }
1702
1703    do {
1704        itr->second->setScaleFactor(scale);
1705    } while (doAll && ++itr != _glyphs.end());
1706
1707    sceneBoundsChanged();
1708    _needsRedraw = true;
1709}
1710
1711bool Renderer::addGroup(const DataSetId& id, const std::vector<Group::NodeId>& nodeList)
1712{
1713    if (id.compare("all") == 0) {
1714        addChildrenToGroup(id, nodeList);
1715        return true;
1716    }
1717
1718    Group *gobj;
1719    if ((gobj = getGraphicsObject<Group>(id)) != NULL) {
1720        // Group exists, so add nodes to it
1721        addChildrenToGroup(id, nodeList);
1722        return true;
1723    }
1724
1725    gobj = new Group();
1726 
1727    gobj->setDataSet(NULL, this);
1728
1729    if (gobj->getProp() == NULL &&
1730        gobj->getOverlayProp() == NULL) {
1731        delete gobj;
1732        return false;
1733    } else {
1734        if (gobj->getProp())
1735            _renderer->AddViewProp(gobj->getProp());
1736        if (gobj->getOverlayProp())
1737            _renderer->AddViewProp(gobj->getOverlayProp());
1738    }
1739
1740    for (std::vector<Group::NodeId>::const_iterator itr = nodeList.begin();
1741         itr != nodeList.end(); ++itr) {
1742        GraphicsObject *node = getGenericGraphicsObject(*itr);
1743        if (node != NULL) {
1744            if (node->getProp())
1745                _renderer->RemoveViewProp(node->getProp());
1746            if (node->getOverlayProp())
1747                _renderer->RemoveViewProp(node->getOverlayProp());
1748            gobj->addChild(*itr, node);
1749        } else {
1750            ERROR("Can't find node: %s", itr->c_str());
1751        }
1752    }
1753
1754    getGraphicsObjectHashmap<Group>()[id] = gobj;
1755
1756    sceneBoundsChanged();
1757    _needsRedraw = true;
1758    return true;
1759}
1760
1761void Renderer::addChildrenToGroup(const DataSetId& id, const std::vector<Group::NodeId>& nodeList)
1762{
1763    GroupHashmap::iterator itr;
1764
1765    bool doAll = false;
1766
1767    if (id.compare("all") == 0) {
1768        itr = _groups.begin();
1769        if (itr == _groups.end())
1770            return;
1771        doAll = true;
1772    } else {
1773        itr = _groups.find(id);
1774    }
1775
1776    if (itr == _groups.end()) {
1777        ERROR("Group not found: %s", id.c_str());
1778        return;
1779    }
1780
1781    do {
1782        for (std::vector<Group::NodeId>::const_iterator citr = nodeList.begin();
1783             citr != nodeList.end(); ++citr) {
1784            GraphicsObject *node = getGenericGraphicsObject(*citr);
1785            if (node != NULL) {
1786                if (node->getProp())
1787                    _renderer->RemoveViewProp(node->getProp());
1788                if (node->getOverlayProp())
1789                    _renderer->RemoveViewProp(node->getOverlayProp());
1790                itr->second->addChild(*citr, node);
1791            } else {
1792                ERROR("Can't find node: %s", citr->c_str());
1793            }
1794        }
1795     } while (doAll && ++itr != _groups.end());
1796
1797    sceneBoundsChanged();
1798    _needsRedraw = true;
1799}
1800
1801void Renderer::removeChildrenFromGroup(const DataSetId& id, const std::vector<Group::NodeId>& nodeList)
1802{
1803    GroupHashmap::iterator itr;
1804
1805    bool doAll = false;
1806
1807    if (id.compare("all") == 0) {
1808        itr = _groups.begin();
1809        if (itr == _groups.end())
1810            return;
1811        doAll = true;
1812    } else {
1813        itr = _groups.find(id);
1814    }
1815
1816    if (itr == _groups.end()) {
1817        ERROR("Group not found: %s", id.c_str());
1818        return;
1819    }
1820
1821    do {
1822        for (std::vector<Group::NodeId>::const_iterator citr = nodeList.begin();
1823             citr != nodeList.end(); ++citr) {
1824            GraphicsObject *node = getGenericGraphicsObject(*citr);
1825            if (node != NULL) {
1826                if (node->getProp())
1827                    _renderer->AddViewProp(node->getProp());
1828                if (node->getOverlayProp())
1829                    _renderer->AddViewProp(node->getOverlayProp());
1830                assert(node == itr->second->removeChild(*citr));
1831            } else {
1832                ERROR("Can't find node: %s", citr->c_str());
1833            }
1834        }
1835     } while (doAll && ++itr != _groups.end());
1836
1837    sceneBoundsChanged();
1838    _needsRedraw = true;
1839}
1840
1841/**
1842 * \brief Create a new HeightMap and associate it with the named DataSet
1843 */
1844bool Renderer::addHeightMap(const DataSetId& id, int numContours, double heightScale)
1845{
1846    DataSetHashmap::iterator itr;
1847
1848    bool doAll = false;
1849
1850    if (id.compare("all") == 0) {
1851        itr = _dataSets.begin();
1852    } else {
1853        itr = _dataSets.find(id);
1854    }
1855    if (itr == _dataSets.end()) {
1856        ERROR("Unknown dataset %s", id.c_str());
1857        return false;
1858    }
1859
1860    do {
1861        DataSet *ds = itr->second;
1862        const DataSetId& dsID = ds->getName();
1863
1864        if (getGraphicsObject<HeightMap>(dsID)) {
1865            WARN("Replacing existing HeightMap %s", dsID.c_str());
1866            deleteGraphicsObject<HeightMap>(dsID);
1867        }
1868
1869        HeightMap *hmap = new HeightMap(numContours, heightScale);
1870
1871        hmap->setDataSet(ds, this);
1872
1873        if (hmap->getProp() == NULL) {
1874            delete hmap;
1875            return false;
1876        } else {
1877            _renderer->AddViewProp(hmap->getProp());
1878        }
1879
1880        _heightMaps[dsID] = hmap;
1881    } while (doAll && ++itr != _dataSets.end());
1882
1883    sceneBoundsChanged();
1884    _needsRedraw = true;
1885    return true;
1886}
1887
1888/**
1889 * \brief Create a new HeightMap and associate it with the named DataSet
1890 */
1891bool Renderer::addHeightMap(const DataSetId& id, const std::vector<double>& contours, double heightScale)
1892{
1893    DataSetHashmap::iterator itr;
1894
1895    bool doAll = false;
1896
1897    if (id.compare("all") == 0) {
1898        itr = _dataSets.begin();
1899    } else {
1900        itr = _dataSets.find(id);
1901    }
1902    if (itr == _dataSets.end()) {
1903        ERROR("Unknown dataset %s", id.c_str());
1904        return false;
1905    }
1906
1907    do {
1908        DataSet *ds = itr->second;
1909        const DataSetId& dsID = ds->getName();
1910
1911        if (getGraphicsObject<HeightMap>(dsID)) {
1912            WARN("Replacing existing HeightMap %s", dsID.c_str());
1913            deleteGraphicsObject<HeightMap>(dsID);
1914        }
1915
1916        HeightMap *hmap = new HeightMap(contours, heightScale);
1917
1918        hmap->setDataSet(ds, this);
1919
1920        if (hmap->getProp() == NULL) {
1921            delete hmap;
1922            return false;
1923        } else {
1924            _renderer->AddViewProp(hmap->getProp());
1925        }
1926
1927        _heightMaps[dsID] = hmap;
1928    } while (doAll && ++itr != _dataSets.end());
1929
1930    sceneBoundsChanged();
1931    _needsRedraw = true;
1932    return true;
1933}
1934
1935/**
1936 * \brief Set amount to scale scalar values when creating elevations
1937 * in the height map
1938 */
1939void Renderer::setHeightMapHeightScale(const DataSetId& id, double scale)
1940{
1941    HeightMapHashmap::iterator itr;
1942
1943    bool doAll = false;
1944
1945    if (id.compare("all") == 0) {
1946        itr = _heightMaps.begin();
1947        if (itr == _heightMaps.end())
1948            return;
1949        doAll = true;
1950    } else {
1951        itr = _heightMaps.find(id);
1952    }
1953
1954    if (itr == _heightMaps.end()) {
1955        ERROR("HeightMap not found: %s", id.c_str());
1956        return;
1957    }
1958
1959    do {
1960        itr->second->setHeightScale(scale);
1961     } while (doAll && ++itr != _heightMaps.end());
1962
1963    sceneBoundsChanged();
1964    _needsRedraw = true;
1965}
1966
1967/**
1968 * \brief Set the point cloud render style for the specified DataSet
1969 */
1970void Renderer::setHeightMapCloudStyle(const DataSetId& id,
1971                                      HeightMap::CloudStyle style)
1972{
1973    HeightMapHashmap::iterator itr;
1974
1975    bool doAll = false;
1976
1977    if (id.compare("all") == 0) {
1978        itr = _heightMaps.begin();
1979        if (itr == _heightMaps.end())
1980            return;
1981        doAll = true;
1982    } else {
1983        itr = _heightMaps.find(id);
1984    }
1985    if (itr == _heightMaps.end()) {
1986        ERROR("HeightMap not found: %s", id.c_str());
1987        return;
1988    }
1989
1990    do {
1991        itr->second->setCloudStyle(style);
1992    } while (doAll && ++itr != _heightMaps.end());
1993
1994    _needsRedraw = true;
1995}
1996
1997/**
1998 * \brief Set the number of equally spaced contour isolines for the given DataSet
1999 */
2000void Renderer::setHeightMapNumContours(const DataSetId& id, int numContours)
2001{
2002    HeightMapHashmap::iterator itr;
2003
2004    bool doAll = false;
2005
2006    if (id.compare("all") == 0) {
2007        itr = _heightMaps.begin();
2008        doAll = true;
2009    } else {
2010        itr = _heightMaps.find(id);
2011    }
2012    if (itr == _heightMaps.end()) {
2013        ERROR("HeightMap not found: %s", id.c_str());
2014        return;
2015    }
2016
2017    do {
2018        itr->second->setNumContours(numContours);
2019    } while (doAll && ++itr != _heightMaps.end());
2020
2021    sceneBoundsChanged();
2022    _needsRedraw = true;
2023}
2024
2025/**
2026 * \brief Set a list of height map contour isovalues for the given DataSet
2027 */
2028void Renderer::setHeightMapContourList(const DataSetId& id, const std::vector<double>& contours)
2029{
2030    HeightMapHashmap::iterator itr;
2031
2032    bool doAll = false;
2033
2034    if (id.compare("all") == 0) {
2035        itr = _heightMaps.begin();
2036        doAll = true;
2037    } else {
2038        itr = _heightMaps.find(id);
2039    }
2040    if (itr == _heightMaps.end()) {
2041        ERROR("HeightMap not found: %s", id.c_str());
2042        return;
2043    }
2044
2045    do {
2046        itr->second->setContourList(contours);
2047    } while (doAll && ++itr != _heightMaps.end());
2048
2049    sceneBoundsChanged();
2050     _needsRedraw = true;
2051}
2052
2053/**
2054 * \brief Turn on/off rendering height map contour lines for the given DataSet
2055 */
2056void Renderer::setHeightMapContourLineVisibility(const DataSetId& id, bool state)
2057{
2058    HeightMapHashmap::iterator itr;
2059
2060    bool doAll = false;
2061
2062    if (id.compare("all") == 0) {
2063        itr = _heightMaps.begin();
2064        if (itr == _heightMaps.end())
2065            return;
2066        doAll = true;
2067    } else {
2068        itr = _heightMaps.find(id);
2069    }
2070    if (itr == _heightMaps.end()) {
2071        ERROR("HeightMap not found: %s", id.c_str());
2072        return;
2073    }
2074
2075    do {
2076        itr->second->setContourLineVisibility(state);
2077    } while (doAll && ++itr != _heightMaps.end());
2078
2079    sceneBoundsChanged();
2080    _needsRedraw = true;
2081}
2082
2083/**
2084 * \brief Turn on/off rendering height map colormap surface for the given DataSet
2085 */
2086void Renderer::setHeightMapContourSurfaceVisibility(const DataSetId& id, bool state)
2087{
2088    HeightMapHashmap::iterator itr;
2089
2090    bool doAll = false;
2091
2092    if (id.compare("all") == 0) {
2093        itr = _heightMaps.begin();
2094        if (itr == _heightMaps.end())
2095            return;
2096        doAll = true;
2097    } else {
2098        itr = _heightMaps.find(id);
2099    }
2100    if (itr == _heightMaps.end()) {
2101        ERROR("HeightMap not found: %s", id.c_str());
2102        return;
2103    }
2104
2105    do {
2106        itr->second->setContourSurfaceVisibility(state);
2107    } while (doAll && ++itr != _heightMaps.end());
2108
2109    sceneBoundsChanged();
2110    _needsRedraw = true;
2111}
2112
2113/**
2114 * \brief Set the RGB height map isoline color for the specified DataSet
2115 */
2116void Renderer::setHeightMapContourEdgeColor(const DataSetId& id, float color[3])
2117{
2118    HeightMapHashmap::iterator itr;
2119
2120    bool doAll = false;
2121
2122    if (id.compare("all") == 0) {
2123        itr = _heightMaps.begin();
2124        if (itr == _heightMaps.end())
2125            return;
2126        doAll = true;
2127    } else {
2128        itr = _heightMaps.find(id);
2129    }
2130    if (itr == _heightMaps.end()) {
2131        ERROR("HeightMap not found: %s", id.c_str());
2132        return;
2133    }
2134
2135    do {
2136        itr->second->setContourEdgeColor(color);
2137    } while (doAll && ++itr != _heightMaps.end());
2138
2139    _needsRedraw = true;
2140}
2141
2142/**
2143 * \brief Set the height map isoline width for the specified DataSet (may be a no-op)
2144 *
2145 * If the OpenGL implementation/hardware does not support wide lines,
2146 * this function may not have an effect.
2147 */
2148void Renderer::setHeightMapContourEdgeWidth(const DataSetId& id, float edgeWidth)
2149{
2150    HeightMapHashmap::iterator itr;
2151
2152    bool doAll = false;
2153
2154    if (id.compare("all") == 0) {
2155        itr = _heightMaps.begin();
2156        if (itr == _heightMaps.end())
2157            return;
2158        doAll = true;
2159    } else {
2160        itr = _heightMaps.find(id);
2161    }
2162    if (itr == _heightMaps.end()) {
2163        ERROR("HeightMap not found: %s", id.c_str());
2164        return;
2165    }
2166
2167    do {
2168        itr->second->setContourEdgeWidth(edgeWidth);
2169    } while (doAll && ++itr != _heightMaps.end());
2170
2171    sceneBoundsChanged();
2172    _needsRedraw = true;
2173}
2174
2175/**
2176 * \brief Toggle colormapping of contour lines
2177 */
2178void Renderer::setHeightMapContourLineColorMapEnabled(const DataSetId& id, bool mode)
2179{
2180    HeightMapHashmap::iterator itr;
2181
2182    bool doAll = false;
2183
2184    if (id.compare("all") == 0) {
2185        itr = _heightMaps.begin();
2186        if (itr == _heightMaps.end())
2187            return;
2188        doAll = true;
2189    } else {
2190        itr = _heightMaps.find(id);
2191    }
2192    if (itr == _heightMaps.end()) {
2193        ERROR("HeightMap not found: %s", id.c_str());
2194        return;
2195    }
2196
2197    do {
2198        itr->second->setContourLineColorMapEnabled(mode);
2199    } while (doAll && ++itr != _heightMaps.end());
2200
2201    _needsRedraw = true;   
2202}
2203
2204/**
2205 * \brief Set the color mode for the specified DataSet
2206 */
2207void Renderer::setHeightMapColorMode(const DataSetId& id,
2208                                     HeightMap::ColorMode mode,
2209                                     DataSet::DataAttributeType type,
2210                                     const char *name, double range[2])
2211{
2212    HeightMapHashmap::iterator itr;
2213
2214    bool doAll = false;
2215
2216    if (id.compare("all") == 0) {
2217        itr = _heightMaps.begin();
2218        if (itr == _heightMaps.end())
2219            return;
2220        doAll = true;
2221    } else {
2222        itr = _heightMaps.find(id);
2223    }
2224    if (itr == _heightMaps.end()) {
2225        ERROR("HeightMap not found: %s", id.c_str());
2226        return;
2227    }
2228
2229    do {
2230        itr->second->setColorMode(mode, type, name, range);
2231    } while (doAll && ++itr != _heightMaps.end());
2232
2233    _needsRedraw = true;
2234}
2235
2236/**
2237 * \brief Set the color mode for the specified DataSet
2238 */
2239void Renderer::setHeightMapColorMode(const DataSetId& id,
2240                                     HeightMap::ColorMode mode,
2241                                     const char *name, double range[2])
2242{
2243    HeightMapHashmap::iterator itr;
2244
2245    bool doAll = false;
2246
2247    if (id.compare("all") == 0) {
2248        itr = _heightMaps.begin();
2249        if (itr == _heightMaps.end())
2250            return;
2251        doAll = true;
2252    } else {
2253        itr = _heightMaps.find(id);
2254    }
2255    if (itr == _heightMaps.end()) {
2256        ERROR("HeightMap not found: %s", id.c_str());
2257        return;
2258    }
2259
2260    do {
2261        itr->second->setColorMode(mode, name, range);
2262    } while (doAll && ++itr != _heightMaps.end());
2263
2264    _needsRedraw = true;
2265}
2266
2267void Renderer::setImageBackground(const DataSetId& id, bool state)
2268{
2269    ImageHashmap::iterator itr;
2270
2271    bool doAll = false;
2272
2273    if (id.compare("all") == 0) {
2274        itr = _images.begin();
2275        if (itr == _images.end())
2276            return;
2277        doAll = true;
2278    } else {
2279        itr = _images.find(id);
2280    }
2281    if (itr == _images.end()) {
2282        ERROR("Image not found: %s", id.c_str());
2283        return;
2284    }
2285
2286    do {
2287        itr->second->setBackground(state);
2288    } while (doAll && ++itr != _images.end());
2289
2290    _needsRedraw = true;
2291}
2292
2293void Renderer::setImageBacking(const DataSetId& id, bool state)
2294{
2295    ImageHashmap::iterator itr;
2296
2297    bool doAll = false;
2298
2299    if (id.compare("all") == 0) {
2300        itr = _images.begin();
2301        if (itr == _images.end())
2302            return;
2303        doAll = true;
2304    } else {
2305        itr = _images.find(id);
2306    }
2307    if (itr == _images.end()) {
2308        ERROR("Image not found: %s", id.c_str());
2309        return;
2310    }
2311
2312    do {
2313        itr->second->setBacking(state);
2314    } while (doAll && ++itr != _images.end());
2315
2316    _needsRedraw = true;
2317}
2318
2319void Renderer::setImageBorder(const DataSetId& id, bool state)
2320{
2321    ImageHashmap::iterator itr;
2322
2323    bool doAll = false;
2324
2325    if (id.compare("all") == 0) {
2326        itr = _images.begin();
2327        if (itr == _images.end())
2328            return;
2329        doAll = true;
2330    } else {
2331        itr = _images.find(id);
2332    }
2333    if (itr == _images.end()) {
2334        ERROR("Image not found: %s", id.c_str());
2335        return;
2336    }
2337
2338    do {
2339        itr->second->setBorder(state);
2340    } while (doAll && ++itr != _images.end());
2341
2342    _needsRedraw = true;
2343}
2344
2345void Renderer::setImageExtents(const DataSetId& id, int extents[6])
2346{
2347    ImageHashmap::iterator itr;
2348
2349    bool doAll = false;
2350
2351    if (id.compare("all") == 0) {
2352        itr = _images.begin();
2353        if (itr == _images.end())
2354            return;
2355        doAll = true;
2356    } else {
2357        itr = _images.find(id);
2358    }
2359    if (itr == _images.end()) {
2360        ERROR("Image not found: %s", id.c_str());
2361        return;
2362    }
2363
2364    do {
2365        itr->second->setExtents(extents);
2366    } while (doAll && ++itr != _images.end());
2367
2368    _needsRedraw = true;
2369}
2370
2371void Renderer::setImageLevel(const DataSetId& id, double level)
2372{
2373    ImageHashmap::iterator itr;
2374
2375    bool doAll = false;
2376
2377    if (id.compare("all") == 0) {
2378        itr = _images.begin();
2379        if (itr == _images.end())
2380            return;
2381        doAll = true;
2382    } else {
2383        itr = _images.find(id);
2384    }
2385    if (itr == _images.end()) {
2386        ERROR("Image not found: %s", id.c_str());
2387        return;
2388    }
2389
2390    do {
2391        itr->second->setLevel(level);
2392    } while (doAll && ++itr != _images.end());
2393
2394    _needsRedraw = true;
2395}
2396
2397void Renderer::setImageWindow(const DataSetId& id, double window)
2398{
2399    ImageHashmap::iterator itr;
2400
2401    bool doAll = false;
2402
2403    if (id.compare("all") == 0) {
2404        itr = _images.begin();
2405        if (itr == _images.end())
2406            return;
2407        doAll = true;
2408    } else {
2409        itr = _images.find(id);
2410    }
2411    if (itr == _images.end()) {
2412        ERROR("Image not found: %s", id.c_str());
2413        return;
2414    }
2415
2416    do {
2417        itr->second->setWindow(window);
2418    } while (doAll && ++itr != _images.end());
2419
2420    _needsRedraw = true;
2421}
2422
2423void Renderer::setImageZSlice(const DataSetId& id, int z)
2424{
2425    ImageHashmap::iterator itr;
2426
2427    bool doAll = false;
2428
2429    if (id.compare("all") == 0) {
2430        itr = _images.begin();
2431        if (itr == _images.end())
2432            return;
2433        doAll = true;
2434    } else {
2435        itr = _images.find(id);
2436    }
2437    if (itr == _images.end()) {
2438        ERROR("Image not found: %s", id.c_str());
2439        return;
2440    }
2441
2442    do {
2443        itr->second->setZSlice(z);
2444    } while (doAll && ++itr != _images.end());
2445
2446    _needsRedraw = true;
2447}
2448
2449/**
2450 * \brief Create a new Line and associate it with an ID
2451 */
2452bool Renderer::addLine(const DataSetId& id, double pt1[3], double pt2[3])
2453{
2454    Line *gobj;
2455    if ((gobj = getGraphicsObject<Line>(id)) != NULL) {
2456        WARN("Replacing existing %s %s", gobj->getClassName(), id.c_str());
2457        deleteGraphicsObject<Line>(id);
2458    }
2459
2460    gobj = new Line();
2461 
2462    gobj->setDataSet(NULL, this);
2463
2464    if (gobj->getProp() == NULL &&
2465        gobj->getOverlayProp() == NULL) {
2466        delete gobj;
2467        return false;
2468    } else {
2469        if (gobj->getProp())
2470            _renderer->AddViewProp(gobj->getProp());
2471        if (gobj->getOverlayProp())
2472            _renderer->AddViewProp(gobj->getOverlayProp());
2473    }
2474
2475    gobj->setEndPoints(pt1, pt2);
2476
2477    getGraphicsObjectHashmap<Line>()[id] = gobj;
2478
2479    sceneBoundsChanged();
2480    _needsRedraw = true;
2481    return true;
2482}
2483
2484/**
2485 * \brief Create a new Line and associate it with an ID
2486 */
2487bool Renderer::addLine(const DataSetId& id, std::vector<double> points)
2488{
2489    Line *gobj;
2490    if ((gobj = getGraphicsObject<Line>(id)) != NULL) {
2491        WARN("Replacing existing %s %s", gobj->getClassName(), id.c_str());
2492        deleteGraphicsObject<Line>(id);
2493    }
2494
2495    gobj = new Line();
2496 
2497    gobj->setDataSet(NULL, this);
2498
2499    if (gobj->getProp() == NULL &&
2500        gobj->getOverlayProp() == NULL) {
2501        delete gobj;
2502        return false;
2503    } else {
2504        if (gobj->getProp())
2505            _renderer->AddViewProp(gobj->getProp());
2506        if (gobj->getOverlayProp())
2507            _renderer->AddViewProp(gobj->getOverlayProp());
2508    }
2509
2510    gobj->setPoints(points);
2511
2512    getGraphicsObjectHashmap<Line>()[id] = gobj;
2513
2514    sceneBoundsChanged();
2515    _needsRedraw = true;
2516    return true;
2517}
2518
2519/**
2520 * \brief Set atom sphere resolution
2521 */
2522void Renderer::setMoleculeAtomQuality(const DataSetId& id, double quality)
2523{
2524    MoleculeHashmap::iterator itr;
2525
2526    bool doAll = false;
2527
2528    if (id.compare("all") == 0) {
2529        itr = _molecules.begin();
2530        if (itr == _molecules.end())
2531            return;
2532        doAll = true;
2533    } else {
2534        itr = _molecules.find(id);
2535    }
2536    if (itr == _molecules.end()) {
2537        ERROR("Molecule not found: %s", id.c_str());
2538        return;
2539    }
2540
2541    do {
2542        itr->second->setAtomQuality(quality);
2543    } while (doAll && ++itr != _molecules.end());
2544
2545    sceneBoundsChanged();
2546    _needsRedraw = true;
2547}
2548
2549/**
2550 * \brief Set bond cylinder resolution
2551 */
2552void Renderer::setMoleculeBondQuality(const DataSetId& id, double quality)
2553{
2554    MoleculeHashmap::iterator itr;
2555
2556    bool doAll = false;
2557
2558    if (id.compare("all") == 0) {
2559        itr = _molecules.begin();
2560        if (itr == _molecules.end())
2561            return;
2562        doAll = true;
2563    } else {
2564        itr = _molecules.find(id);
2565    }
2566    if (itr == _molecules.end()) {
2567        ERROR("Molecule not found: %s", id.c_str());
2568        return;
2569    }
2570
2571    do {
2572        itr->second->setBondQuality(quality);
2573    } while (doAll && ++itr != _molecules.end());
2574
2575    sceneBoundsChanged();
2576    _needsRedraw = true;
2577}
2578
2579/**
2580 * \brief Set radius scale factor for atoms
2581 */
2582void Renderer::setMoleculeAtomRadiusScale(const DataSetId& id, double scale)
2583{
2584    MoleculeHashmap::iterator itr;
2585
2586    bool doAll = false;
2587
2588    if (id.compare("all") == 0) {
2589        itr = _molecules.begin();
2590        if (itr == _molecules.end())
2591            return;
2592        doAll = true;
2593    } else {
2594        itr = _molecules.find(id);
2595    }
2596    if (itr == _molecules.end()) {
2597        ERROR("Molecule not found: %s", id.c_str());
2598        return;
2599    }
2600
2601    do {
2602        itr->second->setAtomRadiusScale(scale);
2603    } while (doAll && ++itr != _molecules.end());
2604
2605    sceneBoundsChanged();
2606    _needsRedraw = true;
2607}
2608
2609/**
2610 * \brief Set radius standard for scaling atoms
2611 */
2612void Renderer::setMoleculeAtomScaling(const DataSetId& id, Molecule::AtomScaling scaling)
2613{
2614    MoleculeHashmap::iterator itr;
2615
2616    bool doAll = false;
2617
2618    if (id.compare("all") == 0) {
2619        itr = _molecules.begin();
2620        if (itr == _molecules.end())
2621            return;
2622        doAll = true;
2623    } else {
2624        itr = _molecules.find(id);
2625    }
2626    if (itr == _molecules.end()) {
2627        ERROR("Molecule not found: %s", id.c_str());
2628        return;
2629    }
2630
2631    do {
2632        itr->second->setAtomScaling(scaling);
2633    } while (doAll && ++itr != _molecules.end());
2634
2635    sceneBoundsChanged();
2636    _needsRedraw = true;
2637}
2638
2639/**
2640 * \brief Turn on/off rendering of the Molecule atoms for the given DataSet
2641 */
2642void Renderer::setMoleculeAtomVisibility(const DataSetId& id, bool state)
2643{
2644    MoleculeHashmap::iterator itr;
2645
2646    bool doAll = false;
2647
2648    if (id.compare("all") == 0) {
2649        itr = _molecules.begin();
2650        if (itr == _molecules.end())
2651            return;
2652        doAll = true;
2653    } else {
2654        itr = _molecules.find(id);
2655    }
2656    if (itr == _molecules.end()) {
2657        ERROR("Molecule not found: %s", id.c_str());
2658        return;
2659    }
2660
2661    do {
2662        itr->second->setAtomVisibility(state);
2663    } while (doAll && ++itr != _molecules.end());
2664
2665    sceneBoundsChanged();
2666    _needsRedraw = true;
2667}
2668
2669/**
2670 * \brief Set the field used to label atoms for the given DataSet
2671 */
2672void Renderer::setMoleculeAtomLabelField(const DataSetId& id, const char *fieldName)
2673{
2674    MoleculeHashmap::iterator itr;
2675
2676    bool doAll = false;
2677
2678    if (id.compare("all") == 0) {
2679        itr = _molecules.begin();
2680        if (itr == _molecules.end())
2681            return;
2682        doAll = true;
2683    } else {
2684        itr = _molecules.find(id);
2685    }
2686    if (itr == _molecules.end()) {
2687        ERROR("Molecule not found: %s", id.c_str());
2688        return;
2689    }
2690
2691    do {
2692        itr->second->setAtomLabelField(fieldName);
2693    } while (doAll && ++itr != _molecules.end());
2694
2695    _needsRedraw = true;
2696}
2697
2698/**
2699 * \brief Turn on/off rendering of the Molecule atom labels for the given DataSet
2700 */
2701void Renderer::setMoleculeAtomLabelVisibility(const DataSetId& id, bool state)
2702{
2703    MoleculeHashmap::iterator itr;
2704
2705    bool doAll = false;
2706
2707    if (id.compare("all") == 0) {
2708        itr = _molecules.begin();
2709        if (itr == _molecules.end())
2710            return;
2711        doAll = true;
2712    } else {
2713        itr = _molecules.find(id);
2714    }
2715    if (itr == _molecules.end()) {
2716        ERROR("Molecule not found: %s", id.c_str());
2717        return;
2718    }
2719
2720    do {
2721        itr->second->setAtomLabelVisibility(state);
2722    } while (doAll && ++itr != _molecules.end());
2723
2724    sceneBoundsChanged();
2725    _needsRedraw = true;
2726}
2727
2728/**
2729 * \brief Set radius scale factor for atoms
2730 */
2731void Renderer::setMoleculeBondRadiusScale(const DataSetId& id, double scale)
2732{
2733    MoleculeHashmap::iterator itr;
2734
2735    bool doAll = false;
2736
2737    if (id.compare("all") == 0) {
2738        itr = _molecules.begin();
2739        if (itr == _molecules.end())
2740            return;
2741        doAll = true;
2742    } else {
2743        itr = _molecules.find(id);
2744    }
2745    if (itr == _molecules.end()) {
2746        ERROR("Molecule not found: %s", id.c_str());
2747        return;
2748    }
2749
2750    do {
2751        itr->second->setBondRadiusScale(scale);
2752    } while (doAll && ++itr != _molecules.end());
2753
2754    sceneBoundsChanged();
2755    _needsRedraw = true;
2756}
2757
2758/**
2759 * \brief Turn on/off rendering of the Molecule bonds for the given DataSet
2760 */
2761void Renderer::setMoleculeBondVisibility(const DataSetId& id, bool state)
2762{
2763    MoleculeHashmap::iterator itr;
2764
2765    bool doAll = false;
2766
2767    if (id.compare("all") == 0) {
2768        itr = _molecules.begin();
2769        if (itr == _molecules.end())
2770            return;
2771        doAll = true;
2772    } else {
2773        itr = _molecules.find(id);
2774    }
2775    if (itr == _molecules.end()) {
2776        ERROR("Molecule not found: %s", id.c_str());
2777        return;
2778    }
2779
2780    do {
2781        itr->second->setBondVisibility(state);
2782    } while (doAll && ++itr != _molecules.end());
2783
2784    sceneBoundsChanged();
2785    _needsRedraw = true;
2786}
2787
2788/**
2789 * \brief Set render style of the Molecule bonds for the given DataSet
2790 */
2791void Renderer::setMoleculeBondStyle(const DataSetId& id, Molecule::BondStyle style)
2792{
2793    MoleculeHashmap::iterator itr;
2794
2795    bool doAll = false;
2796
2797    if (id.compare("all") == 0) {
2798        itr = _molecules.begin();
2799        if (itr == _molecules.end())
2800            return;
2801        doAll = true;
2802    } else {
2803        itr = _molecules.find(id);
2804    }
2805    if (itr == _molecules.end()) {
2806        ERROR("Molecule not found: %s", id.c_str());
2807        return;
2808    }
2809
2810    do {
2811        itr->second->setBondStyle(style);
2812    } while (doAll && ++itr != _molecules.end());
2813
2814    sceneBoundsChanged();
2815    _needsRedraw = true;
2816}
2817
2818/**
2819 * \brief Set coloring mode of the Molecule bonds for the given DataSet
2820 */
2821void Renderer::setMoleculeBondColorMode(const DataSetId& id, Molecule::BondColorMode mode)
2822{
2823    MoleculeHashmap::iterator itr;
2824
2825    bool doAll = false;
2826
2827    if (id.compare("all") == 0) {
2828        itr = _molecules.begin();
2829        if (itr == _molecules.end())
2830            return;
2831        doAll = true;
2832    } else {
2833        itr = _molecules.find(id);
2834    }
2835    if (itr == _molecules.end()) {
2836        ERROR("Molecule not found: %s", id.c_str());
2837        return;
2838    }
2839
2840    do {
2841        itr->second->setBondColorMode(mode);
2842    } while (doAll && ++itr != _molecules.end());
2843
2844    _needsRedraw = true;
2845}
2846
2847/**
2848 * \brief Set constant color of the Molecule bonds for the given DataSet
2849 */
2850void Renderer::setMoleculeBondColor(const DataSetId& id, float color[3])
2851{
2852    MoleculeHashmap::iterator itr;
2853
2854    bool doAll = false;
2855
2856    if (id.compare("all") == 0) {
2857        itr = _molecules.begin();
2858        if (itr == _molecules.end())
2859            return;
2860        doAll = true;
2861    } else {
2862        itr = _molecules.find(id);
2863    }
2864    if (itr == _molecules.end()) {
2865        ERROR("Molecule not found: %s", id.c_str());
2866        return;
2867    }
2868
2869    do {
2870        itr->second->setBondColor(color);
2871    } while (doAll && ++itr != _molecules.end());
2872
2873    _needsRedraw = true;
2874}
2875
2876/**
2877 * \brief Set the color mode for the specified DataSet
2878 */
2879void Renderer::setMoleculeColorMode(const DataSetId& id,
2880                                    Molecule::ColorMode mode,
2881                                    DataSet::DataAttributeType type,
2882                                    const char *name, double range[2])
2883{
2884    MoleculeHashmap::iterator itr;
2885
2886    bool doAll = false;
2887
2888    if (id.compare("all") == 0) {
2889        itr = _molecules.begin();
2890        if (itr == _molecules.end())
2891            return;
2892        doAll = true;
2893    } else {
2894        itr = _molecules.find(id);
2895    }
2896    if (itr == _molecules.end()) {
2897        ERROR("Molecule not found: %s", id.c_str());
2898        return;
2899    }
2900
2901    do {
2902        itr->second->setColorMode(mode, type, name, range);
2903    } while (doAll && ++itr != _molecules.end());
2904
2905    _needsRedraw = true;
2906}
2907
2908/**
2909 * \brief Set the color mode for the specified DataSet
2910 */
2911void Renderer::setMoleculeColorMode(const DataSetId& id,
2912                                    Molecule::ColorMode mode,
2913                                    const char *name, double range[2])
2914{
2915    MoleculeHashmap::iterator itr;
2916
2917    bool doAll = false;
2918
2919    if (id.compare("all") == 0) {
2920        itr = _molecules.begin();
2921        if (itr == _molecules.end())
2922            return;
2923        doAll = true;
2924    } else {
2925        itr = _molecules.find(id);
2926    }
2927    if (itr == _molecules.end()) {
2928        ERROR("Molecule not found: %s", id.c_str());
2929        return;
2930    }
2931
2932    do {
2933        itr->second->setColorMode(mode, name, range);
2934    } while (doAll && ++itr != _molecules.end());
2935
2936    _needsRedraw = true;
2937}
2938
2939/**
2940 * \brief Create a new n-sided regular Polygon and associate it with an ID
2941 */
2942bool Renderer::addPolygon(const DataSetId& id, int numSides,
2943                          double center[3], double normal[3], double radius)
2944{
2945    Polygon *gobj;
2946    if ((gobj = getGraphicsObject<Polygon>(id)) != NULL) {
2947        WARN("Replacing existing %s %s", gobj->getClassName(), id.c_str());
2948        deleteGraphicsObject<Polygon>(id);
2949    }
2950
2951    gobj = new Polygon();
2952 
2953    gobj->setDataSet(NULL, this);
2954
2955    if (gobj->getProp() == NULL &&
2956        gobj->getOverlayProp() == NULL) {
2957        delete gobj;
2958        return false;
2959    } else {
2960        if (gobj->getProp())
2961            _renderer->AddViewProp(gobj->getProp());
2962        if (gobj->getOverlayProp())
2963            _renderer->AddViewProp(gobj->getOverlayProp());
2964    }
2965
2966    gobj->setNumberOfSides(numSides);
2967    gobj->setCenter(center);
2968    gobj->setNormal(normal);
2969    gobj->setRadius(radius);
2970
2971    getGraphicsObjectHashmap<Polygon>()[id] = gobj;
2972
2973    sceneBoundsChanged();
2974    _needsRedraw = true;
2975    return true;
2976}
2977
2978/**
2979 * \brief Set the  point cloud render style for the specified DataSet
2980 */
2981void Renderer::setPolyDataCloudStyle(const DataSetId& id,
2982                                     PolyData::CloudStyle style)
2983{
2984    PolyDataHashmap::iterator itr;
2985
2986    bool doAll = false;
2987
2988    if (id.compare("all") == 0) {
2989        itr = _polyDatas.begin();
2990        if (itr == _polyDatas.end())
2991            return;
2992        doAll = true;
2993    } else {
2994        itr = _polyDatas.find(id);
2995    }
2996    if (itr == _polyDatas.end()) {
2997        ERROR("PolyData not found: %s", id.c_str());
2998        return;
2999    }
3000
3001    do {
3002        itr->second->setCloudStyle(style);
3003    } while (doAll && ++itr != _polyDatas.end());
3004
3005    _needsRedraw = true;
3006}
3007
3008/**
3009 * \brief Set the color mode for the specified DataSet
3010 */
3011void Renderer::setPolyDataColorMode(const DataSetId& id,
3012                                    PolyData::ColorMode mode,
3013                                    DataSet::DataAttributeType type,
3014                                    const char *name, double range[2])
3015{
3016    PolyDataHashmap::iterator itr;
3017
3018    bool doAll = false;
3019
3020    if (id.compare("all") == 0) {
3021        itr = _polyDatas.begin();
3022        if (itr == _polyDatas.end())
3023            return;
3024        doAll = true;
3025    } else {
3026        itr = _polyDatas.find(id);
3027    }
3028    if (itr == _polyDatas.end()) {
3029        ERROR("PolyData not found: %s", id.c_str());
3030        return;
3031    }
3032
3033    do {
3034        itr->second->setColorMode(mode, type, name, range);
3035    } while (doAll && ++itr != _polyDatas.end());
3036
3037    _needsRedraw = true;
3038}
3039
3040/**
3041 * \brief Set the color mode for the specified DataSet
3042 */
3043void Renderer::setPolyDataColorMode(const DataSetId& id,
3044                                    PolyData::ColorMode mode,
3045                                    const char *name, double range[2])
3046{
3047    PolyDataHashmap::iterator itr;
3048
3049    bool doAll = false;
3050
3051    if (id.compare("all") == 0) {
3052        itr = _polyDatas.begin();
3053        if (itr == _polyDatas.end())
3054            return;
3055        doAll = true;
3056    } else {
3057        itr = _polyDatas.find(id);
3058    }
3059    if (itr == _polyDatas.end()) {
3060        ERROR("PolyData not found: %s", id.c_str());
3061        return;
3062    }
3063
3064    do {
3065        itr->second->setColorMode(mode, name, range);
3066    } while (doAll && ++itr != _polyDatas.end());
3067
3068    _needsRedraw = true;
3069}
3070
3071/**
3072 * \brief Set the  point cloud render style for the specified DataSet
3073 */
3074void Renderer::setPseudoColorCloudStyle(const DataSetId& id,
3075                                        PseudoColor::CloudStyle style)
3076{
3077    PseudoColorHashmap::iterator itr;
3078
3079    bool doAll = false;
3080
3081    if (id.compare("all") == 0) {
3082        itr = _pseudoColors.begin();
3083        if (itr == _pseudoColors.end())
3084            return;
3085        doAll = true;
3086    } else {
3087        itr = _pseudoColors.find(id);
3088    }
3089    if (itr == _pseudoColors.end()) {
3090        ERROR("PseudoColor not found: %s", id.c_str());
3091        return;
3092    }
3093
3094    do {
3095        itr->second->setCloudStyle(style);
3096    } while (doAll && ++itr != _pseudoColors.end());
3097
3098    _needsRedraw = true;
3099}
3100
3101/**
3102 * \brief Set the color mode for the specified DataSet
3103 */
3104void Renderer::setPseudoColorColorMode(const DataSetId& id,
3105                                       PseudoColor::ColorMode mode,
3106                                       DataSet::DataAttributeType type,
3107                                       const char *name, double range[2])
3108{
3109    PseudoColorHashmap::iterator itr;
3110
3111    bool doAll = false;
3112
3113    if (id.compare("all") == 0) {
3114        itr = _pseudoColors.begin();
3115        if (itr == _pseudoColors.end())
3116            return;
3117        doAll = true;
3118    } else {
3119        itr = _pseudoColors.find(id);
3120    }
3121    if (itr == _pseudoColors.end()) {
3122        ERROR("PseudoColor not found: %s", id.c_str());
3123        return;
3124    }
3125
3126    do {
3127        itr->second->setColorMode(mode, type, name, range);
3128    } while (doAll && ++itr != _pseudoColors.end());
3129
3130    _needsRedraw = true;
3131}
3132
3133/**
3134 * \brief Set the color mode for the specified DataSet
3135 */
3136void Renderer::setPseudoColorColorMode(const DataSetId& id,
3137                                       PseudoColor::ColorMode mode,
3138                                       const char *name, double range[2])
3139{
3140    PseudoColorHashmap::iterator itr;
3141
3142    bool doAll = false;
3143
3144    if (id.compare("all") == 0) {
3145        itr = _pseudoColors.begin();
3146        if (itr == _pseudoColors.end())
3147            return;
3148        doAll = true;
3149    } else {
3150        itr = _pseudoColors.find(id);
3151    }
3152    if (itr == _pseudoColors.end()) {
3153        ERROR("PseudoColor not found: %s", id.c_str());
3154        return;
3155    }
3156
3157    do {
3158        itr->second->setColorMode(mode, name, range);
3159    } while (doAll && ++itr != _pseudoColors.end());
3160
3161    _needsRedraw = true;
3162}
3163
3164/**
3165 * \brief Create a new Sphere and associate it with an ID
3166 */
3167bool Renderer::addSphere(const DataSetId& id, double center[3], double radius, bool flipNormals)
3168{
3169    Sphere *gobj;
3170    if ((gobj = getGraphicsObject<Sphere>(id)) != NULL) {
3171        WARN("Replacing existing %s %s", gobj->getClassName(), id.c_str());
3172        deleteGraphicsObject<Sphere>(id);
3173    }
3174
3175    gobj = new Sphere();
3176 
3177    gobj->setDataSet(NULL, this);
3178
3179    if (gobj->getProp() == NULL &&
3180        gobj->getOverlayProp() == NULL) {
3181        delete gobj;
3182        return false;
3183    } else {
3184        if (gobj->getProp())
3185            _renderer->AddViewProp(gobj->getProp());
3186        if (gobj->getOverlayProp())
3187            _renderer->AddViewProp(gobj->getOverlayProp());
3188    }
3189
3190    gobj->setCenter(center);
3191    gobj->setRadius(radius);
3192    if (flipNormals)
3193        gobj->flipNormals(flipNormals);
3194
3195    getGraphicsObjectHashmap<Sphere>()[id] = gobj;
3196
3197    sceneBoundsChanged();
3198    _needsRedraw = true;
3199    return true;
3200}
3201
3202/**
3203 * \brief Create a new Text3D label and associate it with an ID
3204 */
3205bool Renderer::addText3D(const DataSetId& id, const char *string,
3206                         const char *fontFamily, int fontSize,
3207                         bool bold, bool italic, bool shadow)
3208{
3209    Text3D *gobj;
3210    if ((gobj = getGraphicsObject<Text3D>(id)) != NULL) {
3211        WARN("Replacing existing %s %s", gobj->getClassName(), id.c_str());
3212        deleteGraphicsObject<Text3D>(id);
3213    }
3214
3215    gobj = new Text3D();
3216
3217    gobj->setDataSet(NULL, this);
3218
3219    gobj->setText(string);
3220    gobj->setFont(fontFamily);
3221    gobj->setFontSize(fontSize);
3222    gobj->setBold(bold);
3223    gobj->setItalic(italic);
3224    gobj->setShadow(shadow);
3225
3226    if (gobj->getProp() == NULL &&
3227        gobj->getOverlayProp() == NULL) {
3228        delete gobj;
3229        return false;
3230    } else {
3231        if (gobj->getProp())
3232            _renderer->AddViewProp(gobj->getProp());
3233        if (gobj->getOverlayProp())
3234            _renderer->AddViewProp(gobj->getOverlayProp());
3235    }
3236
3237    getGraphicsObjectHashmap<Text3D>()[id] = gobj;
3238
3239    sceneBoundsChanged();
3240    _needsRedraw = true;
3241    return true;
3242}
3243
3244/**
3245 * \brief Set Sphere resolution
3246 */
3247void Renderer::setSphereResolution(const DataSetId& id, int thetaRes, int phiRes)
3248{
3249    SphereHashmap::iterator itr;
3250
3251    bool doAll = false;
3252
3253    if (id.compare("all") == 0) {
3254        itr = _spheres.begin();
3255        if (itr == _spheres.end())
3256            return;
3257        doAll = true;
3258    } else {
3259        itr = _spheres.find(id);
3260    }
3261    if (itr == _spheres.end()) {
3262        ERROR("Sphere not found: %s", id.c_str());
3263        return;
3264    }
3265
3266    do {
3267        itr->second->setThetaResolution(thetaRes);
3268        itr->second->setPhiResolution(phiRes);
3269    } while (doAll && ++itr != _spheres.end());
3270
3271    sceneBoundsChanged();
3272    _needsRedraw = true;
3273}
3274
3275/**
3276 * \brief Set Sphere section
3277 */
3278void Renderer::setSphereSection(const DataSetId& id, double thetaStart, double thetaEnd,
3279                                double phiStart, double phiEnd)
3280{
3281    SphereHashmap::iterator itr;
3282
3283    bool doAll = false;
3284
3285    if (id.compare("all") == 0) {
3286        itr = _spheres.begin();
3287        if (itr == _spheres.end())
3288            return;
3289        doAll = true;
3290    } else {
3291        itr = _spheres.find(id);
3292    }
3293    if (itr == _spheres.end()) {
3294        ERROR("Sphere not found: %s", id.c_str());
3295        return;
3296    }
3297
3298    do {
3299        itr->second->setStartTheta(thetaStart);
3300        itr->second->setEndTheta(thetaEnd);
3301        itr->second->setStartPhi(phiStart);
3302        itr->second->setEndPhi(phiEnd);
3303    } while (doAll && ++itr != _spheres.end());
3304
3305    sceneBoundsChanged();
3306    _needsRedraw = true;
3307}
3308
3309/**
3310 * \brief Set the streamlines seed to points of the streamlines DataSet
3311 */
3312void Renderer::setStreamlinesNumberOfSeedPoints(const DataSetId& id, int numPoints)
3313{
3314    StreamlinesHashmap::iterator itr;
3315
3316    bool doAll = false;
3317
3318    if (id.compare("all") == 0) {
3319        itr = _streamlines.begin();
3320        if (itr == _streamlines.end())
3321            return;
3322        doAll = true;
3323    } else {
3324        itr = _streamlines.find(id);
3325    }
3326    if (itr == _streamlines.end()) {
3327        ERROR("Streamlines not found: %s", id.c_str());
3328        return;
3329    }
3330
3331    do {
3332        itr->second->setNumberOfSeedPoints(numPoints);
3333    } while (doAll && ++itr != _streamlines.end());
3334
3335    sceneBoundsChanged();
3336    _needsRedraw = true;
3337}
3338
3339/**
3340 * \brief Set the streamlines seed point size (may be a no-op)
3341 */
3342void Renderer::setStreamlinesSeedPointSize(const DataSetId& id, float size)
3343{
3344    StreamlinesHashmap::iterator itr;
3345
3346    bool doAll = false;
3347
3348    if (id.compare("all") == 0) {
3349        itr = _streamlines.begin();
3350        if (itr == _streamlines.end())
3351            return;
3352        doAll = true;
3353    } else {
3354        itr = _streamlines.find(id);
3355    }
3356    if (itr == _streamlines.end()) {
3357        ERROR("Streamlines not found: %s", id.c_str());
3358        return;
3359    }
3360
3361    do {
3362        itr->second->setSeedPointSize(size);
3363    } while (doAll && ++itr != _streamlines.end());
3364
3365    _needsRedraw = true;
3366}
3367
3368/**
3369 * \brief Set the streamlines seed to points of the streamlines DataSet
3370 */
3371void Renderer::setStreamlinesSeedToMeshPoints(const DataSetId& id,
3372                                              int maxPoints)
3373{
3374    StreamlinesHashmap::iterator itr;
3375
3376    bool doAll = false;
3377
3378    if (id.compare("all") == 0) {
3379        itr = _streamlines.begin();
3380        if (itr == _streamlines.end())
3381            return;
3382        doAll = true;
3383    } else {
3384        itr = _streamlines.find(id);
3385    }
3386    if (itr == _streamlines.end()) {
3387        ERROR("Streamlines not found: %s", id.c_str());
3388        return;
3389    }
3390
3391    do {
3392        itr->second->setSeedToMeshPoints(maxPoints);
3393    } while (doAll && ++itr != _streamlines.end());
3394
3395    sceneBoundsChanged();
3396    _needsRedraw = true;
3397}
3398
3399/**
3400 * \brief Set the streamlines seed to points distributed randomly inside
3401 * cells of the streamlines DataSet
3402 */
3403void Renderer::setStreamlinesSeedToFilledMesh(const DataSetId& id, int numPoints)
3404{
3405    StreamlinesHashmap::iterator itr;
3406
3407    bool doAll = false;
3408
3409    if (id.compare("all") == 0) {
3410        itr = _streamlines.begin();
3411        if (itr == _streamlines.end())
3412            return;
3413        doAll = true;
3414    } else {
3415        itr = _streamlines.find(id);
3416    }
3417    if (itr == _streamlines.end()) {
3418        ERROR("Streamlines not found: %s", id.c_str());
3419        return;
3420    }
3421
3422    do {
3423        itr->second->setSeedToFilledMesh(numPoints);
3424    } while (doAll && ++itr != _streamlines.end());
3425
3426    sceneBoundsChanged();
3427    _needsRedraw = true;
3428}
3429
3430/**
3431 * \brief Set the streamlines seed to points of a DataSet
3432 *
3433 * \param[in] id DataSet identifier
3434 * \param[in] data Bytes of VTK DataSet file
3435 * \param[in] nbytes Length of data array
3436 * \param[in] maxPoints Maximum number of points to be used as seeds
3437 *
3438 * \return boolean indicating success or failure
3439 */
3440bool Renderer::setStreamlinesSeedToMeshPoints(const DataSetId& id,
3441                                              char *data, size_t nbytes,
3442                                              int maxPoints)
3443{
3444    vtkSmartPointer<vtkDataSetReader> reader = vtkSmartPointer<vtkDataSetReader>::New();
3445    vtkSmartPointer<vtkCharArray> dataSetString = vtkSmartPointer<vtkCharArray>::New();
3446
3447    dataSetString->SetArray(data, nbytes, 1);
3448    reader->SetInputArray(dataSetString);
3449    reader->ReadFromInputStringOn();
3450    reader->Update();
3451
3452    vtkSmartPointer<vtkDataSet> dataSet = reader->GetOutput();
3453    if (dataSet == NULL) {
3454        return false;
3455    }
3456#ifndef USE_VTK6
3457    dataSet->SetPipelineInformation(NULL);
3458#endif
3459    StreamlinesHashmap::iterator itr;
3460
3461    bool doAll = false;
3462
3463    if (id.compare("all") == 0) {
3464        itr = _streamlines.begin();
3465        doAll = true;
3466    } else {
3467        itr = _streamlines.find(id);
3468    }
3469    if (itr == _streamlines.end()) {
3470        ERROR("Streamlines not found: %s", id.c_str());
3471        return false;
3472    }
3473
3474    do {
3475        itr->second->setSeedToMeshPoints(dataSet, maxPoints);
3476    } while (doAll && ++itr != _streamlines.end());
3477
3478    sceneBoundsChanged();
3479    _needsRedraw = true;
3480    return true;
3481}
3482
3483/**
3484 * \brief Set the streamlines seed to points distributed randomly inside
3485 * cells of DataSet
3486 *
3487 * \param[in] id DataSet identifier
3488 * \param[in] data Bytes of VTK DataSet file
3489 * \param[in] nbytes Length of data array
3490 * \param[in] numPoints Number of random seed points to generate
3491 *
3492 * \return boolean indicating success or failure
3493 */
3494bool Renderer::setStreamlinesSeedToFilledMesh(const DataSetId& id,
3495                                              char *data, size_t nbytes,
3496                                              int numPoints)
3497{
3498    vtkSmartPointer<vtkDataSetReader> reader = vtkSmartPointer<vtkDataSetReader>::New();
3499    vtkSmartPointer<vtkCharArray> dataSetString = vtkSmartPointer<vtkCharArray>::New();
3500
3501    dataSetString->SetArray(data, nbytes, 1);
3502    reader->SetInputArray(dataSetString);
3503    reader->ReadFromInputStringOn();
3504    reader->Update();
3505
3506    vtkSmartPointer<vtkDataSet> dataSet = reader->GetOutput();
3507    if (dataSet == NULL) {
3508        return false;
3509    }
3510#ifndef USE_VTK6
3511    dataSet->SetPipelineInformation(NULL);
3512#endif
3513    StreamlinesHashmap::iterator itr;
3514
3515    bool doAll = false;
3516
3517    if (id.compare("all") == 0) {
3518        itr = _streamlines.begin();
3519        doAll = true;
3520    } else {
3521        itr = _streamlines.find(id);
3522    }
3523    if (itr == _streamlines.end()) {
3524        ERROR("Streamlines not found: %s", id.c_str());
3525        return false;
3526    }
3527
3528    do {
3529        itr->second->setSeedToFilledMesh(dataSet, numPoints);
3530    } while (doAll && ++itr != _streamlines.end());
3531
3532    sceneBoundsChanged();
3533    _needsRedraw = true;
3534    return true;
3535}
3536
3537/**
3538 * \brief Set the streamlines seed to points along a line
3539 */
3540void Renderer::setStreamlinesSeedToRake(const DataSetId& id,
3541                                        double start[3], double end[3],
3542                                        int numPoints)
3543{
3544    StreamlinesHashmap::iterator itr;
3545
3546    bool doAll = false;
3547
3548    if (id.compare("all") == 0) {
3549        itr = _streamlines.begin();
3550        if (itr == _streamlines.end())
3551            return;
3552        doAll = true;
3553    } else {
3554        itr = _streamlines.find(id);
3555    }
3556    if (itr == _streamlines.end()) {
3557        ERROR("Streamlines not found: %s", id.c_str());
3558        return;
3559    }
3560
3561    do {
3562        itr->second->setSeedToRake(start, end, numPoints);
3563    } while (doAll && ++itr != _streamlines.end());
3564
3565    sceneBoundsChanged();
3566    _needsRedraw = true;
3567}
3568
3569/**
3570 * \brief Set the streamlines seed to points inside a disk, with optional
3571 * hole
3572 */
3573void Renderer::setStreamlinesSeedToDisk(const DataSetId& id,
3574                                        double center[3], double normal[3],
3575                                        double radius, double innerRadius,
3576                                        int numPoints)
3577{
3578    StreamlinesHashmap::iterator itr;
3579
3580    bool doAll = false;
3581
3582    if (id.compare("all") == 0) {
3583        itr = _streamlines.begin();
3584        if (itr == _streamlines.end())
3585            return;
3586        doAll = true;
3587    } else {
3588        itr = _streamlines.find(id);
3589    }
3590    if (itr == _streamlines.end()) {
3591        ERROR("Streamlines not found: %s", id.c_str());
3592        return;
3593    }
3594
3595    do {
3596        itr->second->setSeedToDisk(center, normal, radius, innerRadius, numPoints);
3597    } while (doAll && ++itr != _streamlines.end());
3598
3599    sceneBoundsChanged();
3600    _needsRedraw = true;
3601}
3602
3603/**
3604 * \brief Set the streamlines seed to vertices of an n-sided polygon
3605 */
3606void Renderer::setStreamlinesSeedToPolygon(const DataSetId& id,
3607                                           double center[3], double normal[3],
3608                                           double angle, double radius,
3609                                           int numSides)
3610{
3611    StreamlinesHashmap::iterator itr;
3612
3613    bool doAll = false;
3614
3615    if (id.compare("all") == 0) {
3616        itr = _streamlines.begin();
3617        if (itr == _streamlines.end())
3618            return;
3619        doAll = true;
3620    } else {
3621        itr = _streamlines.find(id);
3622    }
3623    if (itr == _streamlines.end()) {
3624        ERROR("Streamlines not found: %s", id.c_str());
3625        return;
3626    }
3627
3628    do {
3629        itr->second->setSeedToPolygon(center, normal, angle, radius, numSides);
3630    } while (doAll && ++itr != _streamlines.end());
3631
3632    sceneBoundsChanged();
3633    _needsRedraw = true;
3634}
3635
3636/**
3637 * \brief Set the streamlines seed to vertices of an n-sided polygon
3638 */
3639void Renderer::setStreamlinesSeedToFilledPolygon(const DataSetId& id,
3640                                                 double center[3],
3641                                                 double normal[3],
3642                                                 double angle, double radius,
3643                                                 int numSides, int numPoints)
3644{
3645    StreamlinesHashmap::iterator itr;
3646
3647    bool doAll = false;
3648
3649    if (id.compare("all") == 0) {
3650        itr = _streamlines.begin();
3651        if (itr == _streamlines.end())
3652            return;
3653        doAll = true;
3654    } else {
3655        itr = _streamlines.find(id);
3656    }
3657    if (itr == _streamlines.end()) {
3658        ERROR("Streamlines not found: %s", id.c_str());
3659        return;
3660    }
3661
3662    do {
3663        itr->second->setSeedToFilledPolygon(center, normal, angle,
3664                                            radius, numSides, numPoints);
3665    } while (doAll && ++itr != _streamlines.end());
3666
3667    sceneBoundsChanged();
3668    _needsRedraw = true;
3669}
3670
3671void Renderer::setStreamlinesTerminalSpeed(const DataSetId& id, double speed)
3672{
3673    StreamlinesHashmap::iterator itr;
3674
3675    bool doAll = false;
3676
3677    if (id.compare("all") == 0) {
3678        itr = _streamlines.begin();
3679        if (itr == _streamlines.end())
3680            return;
3681        doAll = true;
3682    } else {
3683        itr = _streamlines.find(id);
3684    }
3685    if (itr == _streamlines.end()) {
3686        ERROR("Streamlines not found: %s", id.c_str());
3687        return;
3688    }
3689
3690    do {
3691        itr->second->setTerminalSpeed(speed);
3692    } while (doAll && ++itr != _streamlines.end());
3693
3694    sceneBoundsChanged();
3695    _needsRedraw = true;
3696}
3697
3698/**
3699 * \brief Set Streamlines rendering to polylines for the specified DataSet
3700 */
3701void Renderer::setStreamlinesTypeToLines(const DataSetId& id)
3702{
3703    StreamlinesHashmap::iterator itr;
3704
3705    bool doAll = false;
3706
3707    if (id.compare("all") == 0) {
3708        itr = _streamlines.begin();
3709        if (itr == _streamlines.end())
3710            return;
3711        doAll = true;
3712    } else {
3713        itr = _streamlines.find(id);
3714    }
3715    if (itr == _streamlines.end()) {
3716        ERROR("Streamlines not found: %s", id.c_str());
3717        return;
3718    }
3719
3720    do {
3721        itr->second->setLineTypeToLines();
3722    } while (doAll && ++itr != _streamlines.end());
3723
3724    sceneBoundsChanged();
3725    _needsRedraw = true;
3726}
3727
3728/**
3729 * \brief Set Streamlines rendering to tubes for the specified DataSet
3730 */
3731void Renderer::setStreamlinesTypeToTubes(const DataSetId& id, int numSides, double radius)
3732{
3733    StreamlinesHashmap::iterator itr;
3734
3735    bool doAll = false;
3736
3737    if (id.compare("all") == 0) {
3738        itr = _streamlines.begin();
3739        if (itr == _streamlines.end())
3740            return;
3741        doAll = true;
3742    } else {
3743        itr = _streamlines.find(id);
3744    }
3745    if (itr == _streamlines.end()) {
3746        ERROR("Streamlines not found: %s", id.c_str());
3747        return;
3748    }
3749
3750    do {
3751        itr->second->setLineTypeToTubes(numSides, radius);
3752    } while (doAll && ++itr != _streamlines.end());
3753
3754    sceneBoundsChanged();
3755    _needsRedraw = true;
3756}
3757
3758/**
3759 * \brief Set Streamlines rendering to ribbons for the specified DataSet
3760 */
3761void Renderer::setStreamlinesTypeToRibbons(const DataSetId& id, double width, double angle)
3762{
3763    StreamlinesHashmap::iterator itr;
3764
3765    bool doAll = false;
3766
3767    if (id.compare("all") == 0) {
3768        itr = _streamlines.begin();
3769        if (itr == _streamlines.end())
3770            return;
3771        doAll = true;
3772    } else {
3773        itr = _streamlines.find(id);
3774    }
3775    if (itr == _streamlines.end()) {
3776        ERROR("Streamlines not found: %s", id.c_str());
3777        return;
3778    }
3779
3780    do {
3781        itr->second->setLineTypeToRibbons(width, angle);
3782    } while (doAll && ++itr != _streamlines.end());
3783
3784    sceneBoundsChanged();
3785    _needsRedraw = true;
3786}
3787
3788/**
3789 * \brief Set Streamlines maximum length for the specified DataSet
3790 */
3791void Renderer::setStreamlinesLength(const DataSetId& id, double length)
3792{
3793    StreamlinesHashmap::iterator itr;
3794
3795    bool doAll = false;
3796
3797    if (id.compare("all") == 0) {
3798        itr = _streamlines.begin();
3799        if (itr == _streamlines.end())
3800            return;
3801        doAll = true;
3802    } else {
3803        itr = _streamlines.find(id);
3804    }
3805    if (itr == _streamlines.end()) {
3806        ERROR("Streamlines not found: %s", id.c_str());
3807        return;
3808    }
3809
3810    do {
3811        itr->second->setMaxPropagation(length);
3812    } while (doAll && ++itr != _streamlines.end());
3813
3814    sceneBoundsChanged();
3815    _needsRedraw = true;
3816}
3817
3818/**
3819 * \brief Turn on/off rendering of the Streamlines seed geometry for the given DataSet
3820 */
3821void Renderer::setStreamlinesSeedVisibility(const DataSetId& id, bool state)
3822{
3823    StreamlinesHashmap::iterator itr;
3824
3825    bool doAll = false;
3826
3827    if (id.compare("all") == 0) {
3828        itr = _streamlines.begin();
3829        if (itr == _streamlines.end())
3830            return;
3831        doAll = true;
3832    } else {
3833        itr = _streamlines.find(id);
3834    }
3835    if (itr == _streamlines.end()) {
3836        ERROR("Streamlines not found: %s", id.c_str());
3837        return;
3838    }
3839
3840    do {
3841        itr->second->setSeedVisibility(state);
3842    } while (doAll && ++itr != _streamlines.end());
3843
3844    sceneBoundsChanged();
3845    _needsRedraw = true;
3846}
3847
3848/**
3849 * \brief Set the color mode for the specified DataSet
3850 */
3851void Renderer::setStreamlinesColorMode(const DataSetId& id,
3852                                       Streamlines::ColorMode mode,
3853                                       DataSet::DataAttributeType type,
3854                                       const char *name, double range[2])
3855{
3856    StreamlinesHashmap::iterator itr;
3857
3858    bool doAll = false;
3859
3860    if (id.compare("all") == 0) {
3861        itr = _streamlines.begin();
3862        if (itr == _streamlines.end())
3863            return;
3864        doAll = true;
3865    } else {
3866        itr = _streamlines.find(id);
3867    }
3868    if (itr == _streamlines.end()) {
3869        ERROR("Streamlines not found: %s", id.c_str());
3870        return;
3871    }
3872
3873    do {
3874        itr->second->setColorMode(mode, type, name, range);
3875    } while (doAll && ++itr != _streamlines.end());
3876
3877    _needsRedraw = true;
3878}
3879
3880/**
3881 * \brief Set the color mode for the specified DataSet
3882 */
3883void Renderer::setStreamlinesColorMode(const DataSetId& id,
3884                                       Streamlines::ColorMode mode,
3885                                       const char *name, double range[2])
3886{
3887    StreamlinesHashmap::iterator itr;
3888
3889    bool doAll = false;
3890
3891    if (id.compare("all") == 0) {
3892        itr = _streamlines.begin();
3893        if (itr == _streamlines.end())
3894            return;
3895        doAll = true;
3896    } else {
3897        itr = _streamlines.find(id);
3898    }
3899    if (itr == _streamlines.end()) {
3900        ERROR("Streamlines not found: %s", id.c_str());
3901        return;
3902    }
3903
3904    do {
3905        itr->second->setColorMode(mode, name, range);
3906    } while (doAll && ++itr != _streamlines.end());
3907
3908    _needsRedraw = true;
3909}
3910
3911/**
3912 * \brief Set the RGB line/edge color for the specified DataSet
3913 */
3914void Renderer::setStreamlinesSeedColor(const DataSetId& id, float color[3])
3915{
3916    StreamlinesHashmap::iterator itr;
3917
3918    bool doAll = false;
3919
3920    if (id.compare("all") == 0) {
3921        itr = _streamlines.begin();
3922        if (itr == _streamlines.end())
3923            return;
3924        doAll = true;
3925    } else {
3926        itr = _streamlines.find(id);
3927    }
3928    if (itr == _streamlines.end()) {
3929        ERROR("Streamlines not found: %s", id.c_str());
3930        return;
3931    }
3932
3933    do {
3934        itr->second->setSeedColor(color);
3935    } while (doAll && ++itr != _streamlines.end());
3936
3937    _needsRedraw = true;
3938}
3939
3940void Renderer::setText3DBold(const DataSetId& id, bool state)
3941{
3942    Text3DHashmap::iterator itr;
3943
3944    bool doAll = false;
3945
3946    if (id.compare("all") == 0) {
3947        itr = _text3Ds.begin();
3948        if (itr == _text3Ds.end())
3949            return;
3950        doAll = true;
3951    } else {
3952        itr = _text3Ds.find(id);
3953    }
3954    if (itr == _text3Ds.end()) {
3955        ERROR("Text3D not found: %s", id.c_str());
3956        return;
3957    }
3958
3959    do {
3960        itr->second->setBold(state);
3961    } while (doAll && ++itr != _text3Ds.end());
3962
3963    sceneBoundsChanged();
3964    _needsRedraw = true;
3965}
3966
3967/**
3968 * \brief Set the font family for the Text3D
3969 */
3970void Renderer::setText3DFont(const DataSetId& id, const char *fontFamily)
3971{
3972    Text3DHashmap::iterator itr;
3973
3974    bool doAll = false;
3975
3976    if (id.compare("all") == 0) {
3977        itr = _text3Ds.begin();
3978        if (itr == _text3Ds.end())
3979            return;
3980        doAll = true;
3981    } else {
3982        itr = _text3Ds.find(id);
3983    }
3984    if (itr == _text3Ds.end()) {
3985        ERROR("Text3D not found: %s", id.c_str());
3986        return;
3987    }
3988
3989    do {
3990        itr->second->setFont(fontFamily);
3991    } while (doAll && ++itr != _text3Ds.end());
3992
3993    sceneBoundsChanged();
3994    _needsRedraw = true;
3995}
3996
3997/**
3998 * \brief Set the font family for the Text3D
3999 */
4000void Renderer::setText3DFontSize(const DataSetId& id, int size)
4001{
4002    Text3DHashmap::iterator itr;
4003
4004    bool doAll = false;
4005
4006    if (id.compare("all") == 0) {
4007        itr = _text3Ds.begin();
4008        if (itr == _text3Ds.end())
4009            return;
4010        doAll = true;
4011    } else {
4012        itr = _text3Ds.find(id);
4013    }
4014    if (itr == _text3Ds.end()) {
4015        ERROR("Text3D not found: %s", id.c_str());
4016        return;
4017    }
4018
4019    do {
4020        itr->second->setFontSize(size);
4021    } while (doAll && ++itr != _text3Ds.end());
4022
4023    sceneBoundsChanged();
4024    _needsRedraw = true;
4025}
4026
4027void Renderer::setText3DFollowCamera(const DataSetId& id, bool state)
4028{
4029    Text3DHashmap::iterator itr;
4030
4031    bool doAll = false;
4032
4033    if (id.compare("all") == 0) {
4034        itr = _text3Ds.begin();
4035        if (itr == _text3Ds.end())
4036            return;
4037        doAll = true;
4038    } else {
4039        itr = _text3Ds.find(id);
4040    }
4041    if (itr == _text3Ds.end()) {
4042        ERROR("Text3D not found: %s", id.c_str());
4043        return;
4044    }
4045
4046    do {
4047        itr->second->setFollowCamera(state, _renderer);
4048    } while (doAll && ++itr != _text3Ds.end());
4049
4050    sceneBoundsChanged();
4051    _needsRedraw = true;
4052}
4053
4054void Renderer::setText3DItalic(const DataSetId& id, bool state)
4055{
4056    Text3DHashmap::iterator itr;
4057
4058    bool doAll = false;
4059
4060    if (id.compare("all") == 0) {
4061        itr = _text3Ds.begin();
4062        if (itr == _text3Ds.end())
4063            return;
4064        doAll = true;
4065    } else {
4066        itr = _text3Ds.find(id);
4067    }
4068    if (itr == _text3Ds.end()) {
4069        ERROR("Text3D not found: %s", id.c_str());
4070        return;
4071    }
4072
4073    do {
4074        itr->second->setItalic(state);
4075    } while (doAll && ++itr != _text3Ds.end());
4076
4077    sceneBoundsChanged();
4078    _needsRedraw = true;
4079}
4080
4081void Renderer::setText3DShadow(const DataSetId& id, bool state)
4082{
4083    Text3DHashmap::iterator itr;
4084
4085    bool doAll = false;
4086
4087    if (id.compare("all") == 0) {
4088        itr = _text3Ds.begin();
4089        if (itr == _text3Ds.end())
4090            return;
4091        doAll = true;
4092    } else {
4093        itr = _text3Ds.find(id);
4094    }
4095    if (itr == _text3Ds.end()) {
4096        ERROR("Text3D not found: %s", id.c_str());
4097        return;
4098    }
4099
4100    do {
4101        itr->second->setShadow(state);
4102    } while (doAll && ++itr != _text3Ds.end());
4103
4104    sceneBoundsChanged();
4105    _needsRedraw = true;
4106}
4107
4108void Renderer::setText3DText(const DataSetId& id, const char *text)
4109{
4110    Text3DHashmap::iterator itr;
4111
4112    bool doAll = false;
4113
4114    if (id.compare("all") == 0) {
4115        itr = _text3Ds.begin();
4116        if (itr == _text3Ds.end())
4117            return;
4118        doAll = true;
4119    } else {
4120        itr = _text3Ds.find(id);
4121    }
4122    if (itr == _text3Ds.end()) {
4123        ERROR("Text3D not found: %s", id.c_str());
4124        return;
4125    }
4126
4127    do {
4128        itr->second->setText(text);
4129    } while (doAll && ++itr != _text3Ds.end());
4130
4131    sceneBoundsChanged();
4132    _needsRedraw = true;
4133}
4134
4135/**
4136 * \brief Set the sample rate for the volume shader
4137 *
4138 * Smaller values will give better rendering at the cost
4139 * of slower rendering
4140 */
4141void Renderer::setVolumeSampleDistance(const DataSetId& id, double distance)
4142{
4143    VolumeHashmap::iterator itr;
4144
4145    bool doAll = false;
4146
4147    if (id.compare("all") == 0) {
4148        itr = _volumes.begin();
4149        if (itr == _volumes.end())
4150            return;
4151        doAll = true;
4152    } else {
4153        itr = _volumes.find(id);
4154    }
4155    if (itr == _volumes.end()) {
4156        ERROR("Volume not found: %s", id.c_str());
4157        return;
4158    }
4159
4160    do {
4161        distance *= itr->second->getAverageSpacing();
4162        itr->second->setSampleDistance((float)distance);
4163    } while (doAll && ++itr != _volumes.end());
4164
4165    _needsRedraw = true;
4166}
4167
4168/**
4169 * \brief Set the point cloud render style for the specified DataSet
4170 */
4171void Renderer::setWarpCloudStyle(const DataSetId& id,
4172                                 Warp::CloudStyle style)
4173{
4174    WarpHashmap::iterator itr;
4175
4176    bool doAll = false;
4177
4178    if (id.compare("all") == 0) {
4179        itr = _warps.begin();
4180        if (itr == _warps.end())
4181            return;
4182        doAll = true;
4183    } else {
4184        itr = _warps.find(id);
4185    }
4186    if (itr == _warps.end()) {
4187        ERROR("Warp not found: %s", id.c_str());
4188        return;
4189    }
4190
4191    do {
4192        itr->second->setCloudStyle(style);
4193    } while (doAll && ++itr != _warps.end());
4194
4195    _needsRedraw = true;
4196}
4197
4198/**
4199 * \brief Set the color mode for the specified DataSet
4200 */
4201void Renderer::setWarpColorMode(const DataSetId& id,
4202                                Warp::ColorMode mode,
4203                                DataSet::DataAttributeType type,
4204                                const char *name, double range[2])
4205{
4206    WarpHashmap::iterator itr;
4207
4208    bool doAll = false;
4209
4210    if (id.compare("all") == 0) {
4211        itr = _warps.begin();
4212        if (itr == _warps.end())
4213            return;
4214        doAll = true;
4215    } else {
4216        itr = _warps.find(id);
4217    }
4218    if (itr == _warps.end()) {
4219        ERROR("Warp not found: %s", id.c_str());
4220        return;
4221    }
4222
4223    do {
4224        itr->second->setColorMode(mode, type, name, range);
4225    } while (doAll && ++itr != _warps.end());
4226
4227    _needsRedraw = true;
4228}
4229
4230/**
4231 * \brief Set the color mode for the specified DataSet
4232 */
4233void Renderer::setWarpColorMode(const DataSetId& id,
4234                                Warp::ColorMode mode,
4235                                const char *name, double range[2])
4236{
4237    WarpHashmap::iterator itr;
4238
4239    bool doAll = false;
4240
4241    if (id.compare("all") == 0) {
4242        itr = _warps.begin();
4243        if (itr == _warps.end())
4244            return;
4245        doAll = true;
4246    } else {
4247        itr = _warps.find(id);
4248    }
4249    if (itr == _warps.end()) {
4250        ERROR("Warp not found: %s", id.c_str());
4251        return;
4252    }
4253
4254    do {
4255        itr->second->setColorMode(mode, name, range);
4256    } while (doAll && ++itr != _warps.end());
4257
4258    _needsRedraw = true;
4259}
4260
4261/**
4262 * \brief Set amount to scale vector magnitudes when warping
4263 * a mesh
4264 */
4265void Renderer::setWarpWarpScale(const DataSetId& id, double scale)
4266{
4267    WarpHashmap::iterator itr;
4268
4269    bool doAll = false;
4270
4271    if (id.compare("all") == 0) {
4272        itr = _warps.begin();
4273        if (itr == _warps.end())
4274            return;
4275        doAll = true;
4276    } else {
4277        itr = _warps.find(id);
4278    }
4279
4280    if (itr == _warps.end()) {
4281        ERROR("Warp not found: %s", id.c_str());
4282        return;
4283    }
4284
4285    do {
4286        itr->second->setWarpScale(scale);
4287     } while (doAll && ++itr != _warps.end());
4288
4289    sceneBoundsChanged();
4290    _needsRedraw = true;
4291}
Note: See TracBrowser for help on using the repository browser.