source: vtkvis/trunk/RendererGraphicsObjs.cpp @ 6226

Last change on this file since 6226 was 5835, checked in by ldelgass, 9 years ago

Require VTK >= 6.0.0

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