source: vtkvis/branches/1.7/RendererGraphicsObjs.cpp @ 4604

Last change on this file since 4604 was 4604, checked in by ldelgass, 10 years ago

Merge r4073-4074,4077-4081 from trunk

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