source: trunk/packages/vizservers/vtkvis/RendererGraphicsObjs.cpp @ 4026

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

add missing param doc

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