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

Last change on this file since 4952 was 4783, checked in by ldelgass, 9 years ago

Merge some changes from trunk, including 2 new (currently unused) commands for
the image (slice) object

  • Property svn:eol-style set to native
File size: 104.3 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::setImageSlicePlane(const DataSetId& id, double normal[3], double origin[3])
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->setSlicePlane(normal, origin);
2423    } while (doAll && ++itr != _images.end());
2424
2425    _needsRedraw = true;
2426}
2427
2428void Renderer::setImageSliceFollowsCamera(const DataSetId& id, bool state)
2429{
2430    ImageHashmap::iterator itr;
2431
2432    bool doAll = false;
2433
2434    if (id.compare("all") == 0) {
2435        itr = _images.begin();
2436        if (itr == _images.end())
2437            return;
2438        doAll = true;
2439    } else {
2440        itr = _images.find(id);
2441    }
2442    if (itr == _images.end()) {
2443        ERROR("Image not found: %s", id.c_str());
2444        return;
2445    }
2446
2447    do {
2448        itr->second->setSliceFollowsCamera(state);
2449    } while (doAll && ++itr != _images.end());
2450
2451    _needsRedraw = true;
2452}
2453
2454void Renderer::setImageZSlice(const DataSetId& id, int z)
2455{
2456    ImageHashmap::iterator itr;
2457
2458    bool doAll = false;
2459
2460    if (id.compare("all") == 0) {
2461        itr = _images.begin();
2462        if (itr == _images.end())
2463            return;
2464        doAll = true;
2465    } else {
2466        itr = _images.find(id);
2467    }
2468    if (itr == _images.end()) {
2469        ERROR("Image not found: %s", id.c_str());
2470        return;
2471    }
2472
2473    do {
2474        itr->second->setZSlice(z);
2475    } while (doAll && ++itr != _images.end());
2476
2477    _needsRedraw = true;
2478}
2479
2480/**
2481 * \brief Create a new Line and associate it with an ID
2482 */
2483bool Renderer::addLine(const DataSetId& id, double pt1[3], double pt2[3])
2484{
2485    Line *gobj;
2486    if ((gobj = getGraphicsObject<Line>(id)) != NULL) {
2487        WARN("Replacing existing %s %s", gobj->getClassName(), id.c_str());
2488        deleteGraphicsObject<Line>(id);
2489    }
2490
2491    gobj = new Line();
2492 
2493    gobj->setDataSet(NULL, this);
2494
2495    if (gobj->getProp() == NULL &&
2496        gobj->getOverlayProp() == NULL) {
2497        delete gobj;
2498        return false;
2499    } else {
2500        if (gobj->getProp())
2501            _renderer->AddViewProp(gobj->getProp());
2502        if (gobj->getOverlayProp())
2503            _renderer->AddViewProp(gobj->getOverlayProp());
2504    }
2505
2506    gobj->setEndPoints(pt1, pt2);
2507
2508    getGraphicsObjectHashmap<Line>()[id] = gobj;
2509
2510    sceneBoundsChanged();
2511    _needsRedraw = true;
2512    return true;
2513}
2514
2515/**
2516 * \brief Create a new Line and associate it with an ID
2517 */
2518bool Renderer::addLine(const DataSetId& id, std::vector<double> points)
2519{
2520    Line *gobj;
2521    if ((gobj = getGraphicsObject<Line>(id)) != NULL) {
2522        WARN("Replacing existing %s %s", gobj->getClassName(), id.c_str());
2523        deleteGraphicsObject<Line>(id);
2524    }
2525
2526    gobj = new Line();
2527 
2528    gobj->setDataSet(NULL, this);
2529
2530    if (gobj->getProp() == NULL &&
2531        gobj->getOverlayProp() == NULL) {
2532        delete gobj;
2533        return false;
2534    } else {
2535        if (gobj->getProp())
2536            _renderer->AddViewProp(gobj->getProp());
2537        if (gobj->getOverlayProp())
2538            _renderer->AddViewProp(gobj->getOverlayProp());
2539    }
2540
2541    gobj->setPoints(points);
2542
2543    getGraphicsObjectHashmap<Line>()[id] = gobj;
2544
2545    sceneBoundsChanged();
2546    _needsRedraw = true;
2547    return true;
2548}
2549
2550/**
2551 * \brief Set atom sphere resolution
2552 */
2553void Renderer::setMoleculeAtomQuality(const DataSetId& id, double quality)
2554{
2555    MoleculeHashmap::iterator itr;
2556
2557    bool doAll = false;
2558
2559    if (id.compare("all") == 0) {
2560        itr = _molecules.begin();
2561        if (itr == _molecules.end())
2562            return;
2563        doAll = true;
2564    } else {
2565        itr = _molecules.find(id);
2566    }
2567    if (itr == _molecules.end()) {
2568        ERROR("Molecule not found: %s", id.c_str());
2569        return;
2570    }
2571
2572    do {
2573        itr->second->setAtomQuality(quality);
2574    } while (doAll && ++itr != _molecules.end());
2575
2576    sceneBoundsChanged();
2577    _needsRedraw = true;
2578}
2579
2580/**
2581 * \brief Set bond cylinder resolution
2582 */
2583void Renderer::setMoleculeBondQuality(const DataSetId& id, double quality)
2584{
2585    MoleculeHashmap::iterator itr;
2586
2587    bool doAll = false;
2588
2589    if (id.compare("all") == 0) {
2590        itr = _molecules.begin();
2591        if (itr == _molecules.end())
2592            return;
2593        doAll = true;
2594    } else {
2595        itr = _molecules.find(id);
2596    }
2597    if (itr == _molecules.end()) {
2598        ERROR("Molecule not found: %s", id.c_str());
2599        return;
2600    }
2601
2602    do {
2603        itr->second->setBondQuality(quality);
2604    } while (doAll && ++itr != _molecules.end());
2605
2606    sceneBoundsChanged();
2607    _needsRedraw = true;
2608}
2609
2610/**
2611 * \brief Set radius scale factor for atoms
2612 */
2613void Renderer::setMoleculeAtomRadiusScale(const DataSetId& id, double scale)
2614{
2615    MoleculeHashmap::iterator itr;
2616
2617    bool doAll = false;
2618
2619    if (id.compare("all") == 0) {
2620        itr = _molecules.begin();
2621        if (itr == _molecules.end())
2622            return;
2623        doAll = true;
2624    } else {
2625        itr = _molecules.find(id);
2626    }
2627    if (itr == _molecules.end()) {
2628        ERROR("Molecule not found: %s", id.c_str());
2629        return;
2630    }
2631
2632    do {
2633        itr->second->setAtomRadiusScale(scale);
2634    } while (doAll && ++itr != _molecules.end());
2635
2636    sceneBoundsChanged();
2637    _needsRedraw = true;
2638}
2639
2640/**
2641 * \brief Set radius standard for scaling atoms
2642 */
2643void Renderer::setMoleculeAtomScaling(const DataSetId& id, Molecule::AtomScaling scaling)
2644{
2645    MoleculeHashmap::iterator itr;
2646
2647    bool doAll = false;
2648
2649    if (id.compare("all") == 0) {
2650        itr = _molecules.begin();
2651        if (itr == _molecules.end())
2652            return;
2653        doAll = true;
2654    } else {
2655        itr = _molecules.find(id);
2656    }
2657    if (itr == _molecules.end()) {
2658        ERROR("Molecule not found: %s", id.c_str());
2659        return;
2660    }
2661
2662    do {
2663        itr->second->setAtomScaling(scaling);
2664    } while (doAll && ++itr != _molecules.end());
2665
2666    sceneBoundsChanged();
2667    _needsRedraw = true;
2668}
2669
2670/**
2671 * \brief Turn on/off rendering of the Molecule atoms for the given DataSet
2672 */
2673void Renderer::setMoleculeAtomVisibility(const DataSetId& id, bool state)
2674{
2675    MoleculeHashmap::iterator itr;
2676
2677    bool doAll = false;
2678
2679    if (id.compare("all") == 0) {
2680        itr = _molecules.begin();
2681        if (itr == _molecules.end())
2682            return;
2683        doAll = true;
2684    } else {
2685        itr = _molecules.find(id);
2686    }
2687    if (itr == _molecules.end()) {
2688        ERROR("Molecule not found: %s", id.c_str());
2689        return;
2690    }
2691
2692    do {
2693        itr->second->setAtomVisibility(state);
2694    } while (doAll && ++itr != _molecules.end());
2695
2696    sceneBoundsChanged();
2697    _needsRedraw = true;
2698}
2699
2700/**
2701 * \brief Set the field used to label atoms for the given DataSet
2702 */
2703void Renderer::setMoleculeAtomLabelField(const DataSetId& id, const char *fieldName)
2704{
2705    MoleculeHashmap::iterator itr;
2706
2707    bool doAll = false;
2708
2709    if (id.compare("all") == 0) {
2710        itr = _molecules.begin();
2711        if (itr == _molecules.end())
2712            return;
2713        doAll = true;
2714    } else {
2715        itr = _molecules.find(id);
2716    }
2717    if (itr == _molecules.end()) {
2718        ERROR("Molecule not found: %s", id.c_str());
2719        return;
2720    }
2721
2722    do {
2723        itr->second->setAtomLabelField(fieldName);
2724    } while (doAll && ++itr != _molecules.end());
2725
2726    _needsRedraw = true;
2727}
2728
2729/**
2730 * \brief Turn on/off rendering of the Molecule atom labels for the given DataSet
2731 */
2732void Renderer::setMoleculeAtomLabelVisibility(const DataSetId& id, bool state)
2733{
2734    MoleculeHashmap::iterator itr;
2735
2736    bool doAll = false;
2737
2738    if (id.compare("all") == 0) {
2739        itr = _molecules.begin();
2740        if (itr == _molecules.end())
2741            return;
2742        doAll = true;
2743    } else {
2744        itr = _molecules.find(id);
2745    }
2746    if (itr == _molecules.end()) {
2747        ERROR("Molecule not found: %s", id.c_str());
2748        return;
2749    }
2750
2751    do {
2752        itr->second->setAtomLabelVisibility(state);
2753    } while (doAll && ++itr != _molecules.end());
2754
2755    sceneBoundsChanged();
2756    _needsRedraw = true;
2757}
2758
2759/**
2760 * \brief Set radius scale factor for atoms
2761 */
2762void Renderer::setMoleculeBondRadiusScale(const DataSetId& id, double scale)
2763{
2764    MoleculeHashmap::iterator itr;
2765
2766    bool doAll = false;
2767
2768    if (id.compare("all") == 0) {
2769        itr = _molecules.begin();
2770        if (itr == _molecules.end())
2771            return;
2772        doAll = true;
2773    } else {
2774        itr = _molecules.find(id);
2775    }
2776    if (itr == _molecules.end()) {
2777        ERROR("Molecule not found: %s", id.c_str());
2778        return;
2779    }
2780
2781    do {
2782        itr->second->setBondRadiusScale(scale);
2783    } while (doAll && ++itr != _molecules.end());
2784
2785    sceneBoundsChanged();
2786    _needsRedraw = true;
2787}
2788
2789/**
2790 * \brief Turn on/off rendering of the Molecule bonds for the given DataSet
2791 */
2792void Renderer::setMoleculeBondVisibility(const DataSetId& id, bool state)
2793{
2794    MoleculeHashmap::iterator itr;
2795
2796    bool doAll = false;
2797
2798    if (id.compare("all") == 0) {
2799        itr = _molecules.begin();
2800        if (itr == _molecules.end())
2801            return;
2802        doAll = true;
2803    } else {
2804        itr = _molecules.find(id);
2805    }
2806    if (itr == _molecules.end()) {
2807        ERROR("Molecule not found: %s", id.c_str());
2808        return;
2809    }
2810
2811    do {
2812        itr->second->setBondVisibility(state);
2813    } while (doAll && ++itr != _molecules.end());
2814
2815    sceneBoundsChanged();
2816    _needsRedraw = true;
2817}
2818
2819/**
2820 * \brief Set render style of the Molecule bonds for the given DataSet
2821 */
2822void Renderer::setMoleculeBondStyle(const DataSetId& id, Molecule::BondStyle style)
2823{
2824    MoleculeHashmap::iterator itr;
2825
2826    bool doAll = false;
2827
2828    if (id.compare("all") == 0) {
2829        itr = _molecules.begin();
2830        if (itr == _molecules.end())
2831            return;
2832        doAll = true;
2833    } else {
2834        itr = _molecules.find(id);
2835    }
2836    if (itr == _molecules.end()) {
2837        ERROR("Molecule not found: %s", id.c_str());
2838        return;
2839    }
2840
2841    do {
2842        itr->second->setBondStyle(style);
2843    } while (doAll && ++itr != _molecules.end());
2844
2845    sceneBoundsChanged();
2846    _needsRedraw = true;
2847}
2848
2849/**
2850 * \brief Set coloring mode of the Molecule bonds for the given DataSet
2851 */
2852void Renderer::setMoleculeBondColorMode(const DataSetId& id, Molecule::BondColorMode mode)
2853{
2854    MoleculeHashmap::iterator itr;
2855
2856    bool doAll = false;
2857
2858    if (id.compare("all") == 0) {
2859        itr = _molecules.begin();
2860        if (itr == _molecules.end())
2861            return;
2862        doAll = true;
2863    } else {
2864        itr = _molecules.find(id);
2865    }
2866    if (itr == _molecules.end()) {
2867        ERROR("Molecule not found: %s", id.c_str());
2868        return;
2869    }
2870
2871    do {
2872        itr->second->setBondColorMode(mode);
2873    } while (doAll && ++itr != _molecules.end());
2874
2875    _needsRedraw = true;
2876}
2877
2878/**
2879 * \brief Set constant color of the Molecule bonds for the given DataSet
2880 */
2881void Renderer::setMoleculeBondColor(const DataSetId& id, float color[3])
2882{
2883    MoleculeHashmap::iterator itr;
2884
2885    bool doAll = false;
2886
2887    if (id.compare("all") == 0) {
2888        itr = _molecules.begin();
2889        if (itr == _molecules.end())
2890            return;
2891        doAll = true;
2892    } else {
2893        itr = _molecules.find(id);
2894    }
2895    if (itr == _molecules.end()) {
2896        ERROR("Molecule not found: %s", id.c_str());
2897        return;
2898    }
2899
2900    do {
2901        itr->second->setBondColor(color);
2902    } while (doAll && ++itr != _molecules.end());
2903
2904    _needsRedraw = true;
2905}
2906
2907/**
2908 * \brief Set the color mode for the specified DataSet
2909 */
2910void Renderer::setMoleculeColorMode(const DataSetId& id,
2911                                    Molecule::ColorMode mode,
2912                                    DataSet::DataAttributeType type,
2913                                    const char *name, double range[2])
2914{
2915    MoleculeHashmap::iterator itr;
2916
2917    bool doAll = false;
2918
2919    if (id.compare("all") == 0) {
2920        itr = _molecules.begin();
2921        if (itr == _molecules.end())
2922            return;
2923        doAll = true;
2924    } else {
2925        itr = _molecules.find(id);
2926    }
2927    if (itr == _molecules.end()) {
2928        ERROR("Molecule not found: %s", id.c_str());
2929        return;
2930    }
2931
2932    do {
2933        itr->second->setColorMode(mode, type, name, range);
2934    } while (doAll && ++itr != _molecules.end());
2935
2936    _needsRedraw = true;
2937}
2938
2939/**
2940 * \brief Set the color mode for the specified DataSet
2941 */
2942void Renderer::setMoleculeColorMode(const DataSetId& id,
2943                                    Molecule::ColorMode mode,
2944                                    const char *name, double range[2])
2945{
2946    MoleculeHashmap::iterator itr;
2947
2948    bool doAll = false;
2949
2950    if (id.compare("all") == 0) {
2951        itr = _molecules.begin();
2952        if (itr == _molecules.end())
2953            return;
2954        doAll = true;
2955    } else {
2956        itr = _molecules.find(id);
2957    }
2958    if (itr == _molecules.end()) {
2959        ERROR("Molecule not found: %s", id.c_str());
2960        return;
2961    }
2962
2963    do {
2964        itr->second->setColorMode(mode, name, range);
2965    } while (doAll && ++itr != _molecules.end());
2966
2967    _needsRedraw = true;
2968}
2969
2970/**
2971 * \brief Create a new Parallelepiped and associate it with an ID
2972 */
2973bool Renderer::addParallelepiped(const DataSetId& id,
2974                                 double vec1[3], double vec2[3], double vec3[3],
2975                                 bool flipNormals)
2976{
2977    Parallelepiped *gobj;
2978    if ((gobj = getGraphicsObject<Parallelepiped>(id)) != NULL) {
2979        WARN("Replacing existing %s %s", gobj->getClassName(), id.c_str());
2980        deleteGraphicsObject<Parallelepiped>(id);
2981    }
2982
2983    gobj = new Parallelepiped();
2984 
2985    gobj->setDataSet(NULL, this);
2986
2987    if (gobj->getProp() == NULL &&
2988        gobj->getOverlayProp() == NULL) {
2989        delete gobj;
2990        return false;
2991    } else {
2992        if (gobj->getProp())
2993            _renderer->AddViewProp(gobj->getProp());
2994        if (gobj->getOverlayProp())
2995            _renderer->AddViewProp(gobj->getOverlayProp());
2996    }
2997
2998    gobj->setVectors(vec1, vec2, vec3);
2999    if (flipNormals)
3000        gobj->flipNormals(flipNormals);
3001
3002    getGraphicsObjectHashmap<Parallelepiped>()[id] = gobj;
3003
3004    sceneBoundsChanged();
3005    _needsRedraw = true;
3006    return true;
3007}
3008
3009/**
3010 * \brief Create a new n-sided regular Polygon and associate it with an ID
3011 */
3012bool Renderer::addPolygon(const DataSetId& id, int numSides,
3013                          double center[3], double normal[3], double radius)
3014{
3015    Polygon *gobj;
3016    if ((gobj = getGraphicsObject<Polygon>(id)) != NULL) {
3017        WARN("Replacing existing %s %s", gobj->getClassName(), id.c_str());
3018        deleteGraphicsObject<Polygon>(id);
3019    }
3020
3021    gobj = new Polygon();
3022 
3023    gobj->setDataSet(NULL, this);
3024
3025    if (gobj->getProp() == NULL &&
3026        gobj->getOverlayProp() == NULL) {
3027        delete gobj;
3028        return false;
3029    } else {
3030        if (gobj->getProp())
3031            _renderer->AddViewProp(gobj->getProp());
3032        if (gobj->getOverlayProp())
3033            _renderer->AddViewProp(gobj->getOverlayProp());
3034    }
3035
3036    gobj->setNumberOfSides(numSides);
3037    gobj->setCenter(center);
3038    gobj->setNormal(normal);
3039    gobj->setRadius(radius);
3040
3041    getGraphicsObjectHashmap<Polygon>()[id] = gobj;
3042
3043    sceneBoundsChanged();
3044    _needsRedraw = true;
3045    return true;
3046}
3047
3048/**
3049 * \brief Set the  point cloud render style for the specified DataSet
3050 */
3051void Renderer::setPolyDataCloudStyle(const DataSetId& id,
3052                                     PolyData::CloudStyle style)
3053{
3054    PolyDataHashmap::iterator itr;
3055
3056    bool doAll = false;
3057
3058    if (id.compare("all") == 0) {
3059        itr = _polyDatas.begin();
3060        if (itr == _polyDatas.end())
3061            return;
3062        doAll = true;
3063    } else {
3064        itr = _polyDatas.find(id);
3065    }
3066    if (itr == _polyDatas.end()) {
3067        ERROR("PolyData not found: %s", id.c_str());
3068        return;
3069    }
3070
3071    do {
3072        itr->second->setCloudStyle(style);
3073    } while (doAll && ++itr != _polyDatas.end());
3074
3075    _needsRedraw = true;
3076}
3077
3078/**
3079 * \brief Set the color mode for the specified DataSet
3080 */
3081void Renderer::setPolyDataColorMode(const DataSetId& id,
3082                                    PolyData::ColorMode mode,
3083                                    DataSet::DataAttributeType type,
3084                                    const char *name, double range[2])
3085{
3086    PolyDataHashmap::iterator itr;
3087
3088    bool doAll = false;
3089
3090    if (id.compare("all") == 0) {
3091        itr = _polyDatas.begin();
3092        if (itr == _polyDatas.end())
3093            return;
3094        doAll = true;
3095    } else {
3096        itr = _polyDatas.find(id);
3097    }
3098    if (itr == _polyDatas.end()) {
3099        ERROR("PolyData not found: %s", id.c_str());
3100        return;
3101    }
3102
3103    do {
3104        itr->second->setColorMode(mode, type, name, range);
3105    } while (doAll && ++itr != _polyDatas.end());
3106
3107    _needsRedraw = true;
3108}
3109
3110/**
3111 * \brief Set the color mode for the specified DataSet
3112 */
3113void Renderer::setPolyDataColorMode(const DataSetId& id,
3114                                    PolyData::ColorMode mode,
3115                                    const char *name, double range[2])
3116{
3117    PolyDataHashmap::iterator itr;
3118
3119    bool doAll = false;
3120
3121    if (id.compare("all") == 0) {
3122        itr = _polyDatas.begin();
3123        if (itr == _polyDatas.end())
3124            return;
3125        doAll = true;
3126    } else {
3127        itr = _polyDatas.find(id);
3128    }
3129    if (itr == _polyDatas.end()) {
3130        ERROR("PolyData not found: %s", id.c_str());
3131        return;
3132    }
3133
3134    do {
3135        itr->second->setColorMode(mode, name, range);
3136    } while (doAll && ++itr != _polyDatas.end());
3137
3138    _needsRedraw = true;
3139}
3140
3141/**
3142 * \brief Set the  point cloud render style for the specified DataSet
3143 */
3144void Renderer::setPseudoColorCloudStyle(const DataSetId& id,
3145                                        PseudoColor::CloudStyle style)
3146{
3147    PseudoColorHashmap::iterator itr;
3148
3149    bool doAll = false;
3150
3151    if (id.compare("all") == 0) {
3152        itr = _pseudoColors.begin();
3153        if (itr == _pseudoColors.end())
3154            return;
3155        doAll = true;
3156    } else {
3157        itr = _pseudoColors.find(id);
3158    }
3159    if (itr == _pseudoColors.end()) {
3160        ERROR("PseudoColor not found: %s", id.c_str());
3161        return;
3162    }
3163
3164    do {
3165        itr->second->setCloudStyle(style);
3166    } while (doAll && ++itr != _pseudoColors.end());
3167
3168    _needsRedraw = true;
3169}
3170
3171/**
3172 * \brief Set the color mode for the specified DataSet
3173 */
3174void Renderer::setPseudoColorColorMode(const DataSetId& id,
3175                                       PseudoColor::ColorMode mode,
3176                                       DataSet::DataAttributeType type,
3177                                       const char *name, double range[2])
3178{
3179    PseudoColorHashmap::iterator itr;
3180
3181    bool doAll = false;
3182
3183    if (id.compare("all") == 0) {
3184        itr = _pseudoColors.begin();
3185        if (itr == _pseudoColors.end())
3186            return;
3187        doAll = true;
3188    } else {
3189        itr = _pseudoColors.find(id);
3190    }
3191    if (itr == _pseudoColors.end()) {
3192        ERROR("PseudoColor not found: %s", id.c_str());
3193        return;
3194    }
3195
3196    do {
3197        itr->second->setColorMode(mode, type, name, range);
3198    } while (doAll && ++itr != _pseudoColors.end());
3199
3200    _needsRedraw = true;
3201}
3202
3203/**
3204 * \brief Set the color mode for the specified DataSet
3205 */
3206void Renderer::setPseudoColorColorMode(const DataSetId& id,
3207                                       PseudoColor::ColorMode mode,
3208                                       const char *name, double range[2])
3209{
3210    PseudoColorHashmap::iterator itr;
3211
3212    bool doAll = false;
3213
3214    if (id.compare("all") == 0) {
3215        itr = _pseudoColors.begin();
3216        if (itr == _pseudoColors.end())
3217            return;
3218        doAll = true;
3219    } else {
3220        itr = _pseudoColors.find(id);
3221    }
3222    if (itr == _pseudoColors.end()) {
3223        ERROR("PseudoColor not found: %s", id.c_str());
3224        return;
3225    }
3226
3227    do {
3228        itr->second->setColorMode(mode, name, range);
3229    } while (doAll && ++itr != _pseudoColors.end());
3230
3231    _needsRedraw = true;
3232}
3233
3234/**
3235 * \brief Create a new Sphere and associate it with an ID
3236 */
3237bool Renderer::addSphere(const DataSetId& id, double center[3], double radius, bool flipNormals)
3238{
3239    Sphere *gobj;
3240    if ((gobj = getGraphicsObject<Sphere>(id)) != NULL) {
3241        WARN("Replacing existing %s %s", gobj->getClassName(), id.c_str());
3242        deleteGraphicsObject<Sphere>(id);
3243    }
3244
3245    gobj = new Sphere();
3246 
3247    gobj->setDataSet(NULL, this);
3248
3249    if (gobj->getProp() == NULL &&
3250        gobj->getOverlayProp() == NULL) {
3251        delete gobj;
3252        return false;
3253    } else {
3254        if (gobj->getProp())
3255            _renderer->AddViewProp(gobj->getProp());
3256        if (gobj->getOverlayProp())
3257            _renderer->AddViewProp(gobj->getOverlayProp());
3258    }
3259
3260    gobj->setCenter(center);
3261    gobj->setRadius(radius);
3262    if (flipNormals)
3263        gobj->flipNormals(flipNormals);
3264
3265    getGraphicsObjectHashmap<Sphere>()[id] = gobj;
3266
3267    sceneBoundsChanged();
3268    _needsRedraw = true;
3269    return true;
3270}
3271
3272/**
3273 * \brief Create a new Text3D label and associate it with an ID
3274 */
3275bool Renderer::addText3D(const DataSetId& id, const char *string,
3276                         const char *fontFamily, int fontSize,
3277                         bool bold, bool italic, bool shadow)
3278{
3279    Text3D *gobj;
3280    if ((gobj = getGraphicsObject<Text3D>(id)) != NULL) {
3281        WARN("Replacing existing %s %s", gobj->getClassName(), id.c_str());
3282        deleteGraphicsObject<Text3D>(id);
3283    }
3284
3285    gobj = new Text3D();
3286
3287    gobj->setDataSet(NULL, this);
3288
3289    gobj->setText(string);
3290    gobj->setFont(fontFamily);
3291    gobj->setFontSize(fontSize);
3292    gobj->setBold(bold);
3293    gobj->setItalic(italic);
3294    gobj->setShadow(shadow);
3295
3296    if (gobj->getProp() == NULL &&
3297        gobj->getOverlayProp() == NULL) {
3298        delete gobj;
3299        return false;
3300    } else {
3301        if (gobj->getProp())
3302            _renderer->AddViewProp(gobj->getProp());
3303        if (gobj->getOverlayProp())
3304            _renderer->AddViewProp(gobj->getOverlayProp());
3305    }
3306
3307    getGraphicsObjectHashmap<Text3D>()[id] = gobj;
3308
3309    sceneBoundsChanged();
3310    _needsRedraw = true;
3311    return true;
3312}
3313
3314/**
3315 * \brief Set Sphere resolution
3316 */
3317void Renderer::setSphereResolution(const DataSetId& id, int thetaRes, int phiRes)
3318{
3319    SphereHashmap::iterator itr;
3320
3321    bool doAll = false;
3322
3323    if (id.compare("all") == 0) {
3324        itr = _spheres.begin();
3325        if (itr == _spheres.end())
3326            return;
3327        doAll = true;
3328    } else {
3329        itr = _spheres.find(id);
3330    }
3331    if (itr == _spheres.end()) {
3332        ERROR("Sphere not found: %s", id.c_str());
3333        return;
3334    }
3335
3336    do {
3337        itr->second->setThetaResolution(thetaRes);
3338        itr->second->setPhiResolution(phiRes);
3339    } while (doAll && ++itr != _spheres.end());
3340
3341    sceneBoundsChanged();
3342    _needsRedraw = true;
3343}
3344
3345/**
3346 * \brief Set Sphere section
3347 */
3348void Renderer::setSphereSection(const DataSetId& id, double thetaStart, double thetaEnd,
3349                                double phiStart, double phiEnd)
3350{
3351    SphereHashmap::iterator itr;
3352
3353    bool doAll = false;
3354
3355    if (id.compare("all") == 0) {
3356        itr = _spheres.begin();
3357        if (itr == _spheres.end())
3358            return;
3359        doAll = true;
3360    } else {
3361        itr = _spheres.find(id);
3362    }
3363    if (itr == _spheres.end()) {
3364        ERROR("Sphere not found: %s", id.c_str());
3365        return;
3366    }
3367
3368    do {
3369        itr->second->setStartTheta(thetaStart);
3370        itr->second->setEndTheta(thetaEnd);
3371        itr->second->setStartPhi(phiStart);
3372        itr->second->setEndPhi(phiEnd);
3373    } while (doAll && ++itr != _spheres.end());
3374
3375    sceneBoundsChanged();
3376    _needsRedraw = true;
3377}
3378
3379/**
3380 * \brief Set the streamlines seed to points of the streamlines DataSet
3381 */
3382void Renderer::setStreamlinesNumberOfSeedPoints(const DataSetId& id, int numPoints)
3383{
3384    StreamlinesHashmap::iterator itr;
3385
3386    bool doAll = false;
3387
3388    if (id.compare("all") == 0) {
3389        itr = _streamlines.begin();
3390        if (itr == _streamlines.end())
3391            return;
3392        doAll = true;
3393    } else {
3394        itr = _streamlines.find(id);
3395    }
3396    if (itr == _streamlines.end()) {
3397        ERROR("Streamlines not found: %s", id.c_str());
3398        return;
3399    }
3400
3401    do {
3402        itr->second->setNumberOfSeedPoints(numPoints);
3403    } while (doAll && ++itr != _streamlines.end());
3404
3405    sceneBoundsChanged();
3406    _needsRedraw = true;
3407}
3408
3409/**
3410 * \brief Set the streamlines seed point size (may be a no-op)
3411 */
3412void Renderer::setStreamlinesSeedPointSize(const DataSetId& id, float size)
3413{
3414    StreamlinesHashmap::iterator itr;
3415
3416    bool doAll = false;
3417
3418    if (id.compare("all") == 0) {
3419        itr = _streamlines.begin();
3420        if (itr == _streamlines.end())
3421            return;
3422        doAll = true;
3423    } else {
3424        itr = _streamlines.find(id);
3425    }
3426    if (itr == _streamlines.end()) {
3427        ERROR("Streamlines not found: %s", id.c_str());
3428        return;
3429    }
3430
3431    do {
3432        itr->second->setSeedPointSize(size);
3433    } while (doAll && ++itr != _streamlines.end());
3434
3435    _needsRedraw = true;
3436}
3437
3438/**
3439 * \brief Set the streamlines seed to points of the streamlines DataSet
3440 */
3441void Renderer::setStreamlinesSeedToMeshPoints(const DataSetId& id,
3442                                              int maxPoints)
3443{
3444    StreamlinesHashmap::iterator itr;
3445
3446    bool doAll = false;
3447
3448    if (id.compare("all") == 0) {
3449        itr = _streamlines.begin();
3450        if (itr == _streamlines.end())
3451            return;
3452        doAll = true;
3453    } else {
3454        itr = _streamlines.find(id);
3455    }
3456    if (itr == _streamlines.end()) {
3457        ERROR("Streamlines not found: %s", id.c_str());
3458        return;
3459    }
3460
3461    do {
3462        itr->second->setSeedToMeshPoints(maxPoints);
3463    } while (doAll && ++itr != _streamlines.end());
3464
3465    sceneBoundsChanged();
3466    _needsRedraw = true;
3467}
3468
3469/**
3470 * \brief Set the streamlines seed to points distributed randomly inside
3471 * cells of the streamlines DataSet
3472 */
3473void Renderer::setStreamlinesSeedToFilledMesh(const DataSetId& id, int numPoints)
3474{
3475    StreamlinesHashmap::iterator itr;
3476
3477    bool doAll = false;
3478
3479    if (id.compare("all") == 0) {
3480        itr = _streamlines.begin();
3481        if (itr == _streamlines.end())
3482            return;
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;
3490    }
3491
3492    do {
3493        itr->second->setSeedToFilledMesh(numPoints);
3494    } while (doAll && ++itr != _streamlines.end());
3495
3496    sceneBoundsChanged();
3497    _needsRedraw = true;
3498}
3499
3500/**
3501 * \brief Set the streamlines seed to points of a DataSet
3502 *
3503 * \param[in] id DataSet identifier
3504 * \param[in] data Bytes of VTK DataSet file
3505 * \param[in] nbytes Length of data array
3506 * \param[in] maxPoints Maximum number of points to be used as seeds
3507 *
3508 * \return boolean indicating success or failure
3509 */
3510bool Renderer::setStreamlinesSeedToMeshPoints(const DataSetId& id,
3511                                              char *data, size_t nbytes,
3512                                              int maxPoints)
3513{
3514    vtkSmartPointer<vtkDataSetReader> reader = vtkSmartPointer<vtkDataSetReader>::New();
3515    vtkSmartPointer<vtkCharArray> dataSetString = vtkSmartPointer<vtkCharArray>::New();
3516
3517    dataSetString->SetArray(data, nbytes, 1);
3518    reader->SetInputArray(dataSetString);
3519    reader->ReadFromInputStringOn();
3520    reader->Update();
3521
3522    vtkSmartPointer<vtkDataSet> dataSet = reader->GetOutput();
3523    if (dataSet == NULL) {
3524        return false;
3525    }
3526#ifndef USE_VTK6
3527    dataSet->SetPipelineInformation(NULL);
3528#endif
3529    StreamlinesHashmap::iterator itr;
3530
3531    bool doAll = false;
3532
3533    if (id.compare("all") == 0) {
3534        itr = _streamlines.begin();
3535        doAll = true;
3536    } else {
3537        itr = _streamlines.find(id);
3538    }
3539    if (itr == _streamlines.end()) {
3540        ERROR("Streamlines not found: %s", id.c_str());
3541        return false;
3542    }
3543
3544    do {
3545        itr->second->setSeedToMeshPoints(dataSet, maxPoints);
3546    } while (doAll && ++itr != _streamlines.end());
3547
3548    sceneBoundsChanged();
3549    _needsRedraw = true;
3550    return true;
3551}
3552
3553/**
3554 * \brief Set the streamlines seed to points distributed randomly inside
3555 * cells of DataSet
3556 *
3557 * \param[in] id DataSet identifier
3558 * \param[in] data Bytes of VTK DataSet file
3559 * \param[in] nbytes Length of data array
3560 * \param[in] numPoints Number of random seed points to generate
3561 *
3562 * \return boolean indicating success or failure
3563 */
3564bool Renderer::setStreamlinesSeedToFilledMesh(const DataSetId& id,
3565                                              char *data, size_t nbytes,
3566                                              int numPoints)
3567{
3568    vtkSmartPointer<vtkDataSetReader> reader = vtkSmartPointer<vtkDataSetReader>::New();
3569    vtkSmartPointer<vtkCharArray> dataSetString = vtkSmartPointer<vtkCharArray>::New();
3570
3571    dataSetString->SetArray(data, nbytes, 1);
3572    reader->SetInputArray(dataSetString);
3573    reader->ReadFromInputStringOn();
3574    reader->Update();
3575
3576    vtkSmartPointer<vtkDataSet> dataSet = reader->GetOutput();
3577    if (dataSet == NULL) {
3578        return false;
3579    }
3580#ifndef USE_VTK6
3581    dataSet->SetPipelineInformation(NULL);
3582#endif
3583    StreamlinesHashmap::iterator itr;
3584
3585    bool doAll = false;
3586
3587    if (id.compare("all") == 0) {
3588        itr = _streamlines.begin();
3589        doAll = true;
3590    } else {
3591        itr = _streamlines.find(id);
3592    }
3593    if (itr == _streamlines.end()) {
3594        ERROR("Streamlines not found: %s", id.c_str());
3595        return false;
3596    }
3597
3598    do {
3599        itr->second->setSeedToFilledMesh(dataSet, numPoints);
3600    } while (doAll && ++itr != _streamlines.end());
3601
3602    sceneBoundsChanged();
3603    _needsRedraw = true;
3604    return true;
3605}
3606
3607/**
3608 * \brief Set the streamlines seed to points along a line
3609 */
3610void Renderer::setStreamlinesSeedToRake(const DataSetId& id,
3611                                        double start[3], double end[3],
3612                                        int numPoints)
3613{
3614    StreamlinesHashmap::iterator itr;
3615
3616    bool doAll = false;
3617
3618    if (id.compare("all") == 0) {
3619        itr = _streamlines.begin();
3620        if (itr == _streamlines.end())
3621            return;
3622        doAll = true;
3623    } else {
3624        itr = _streamlines.find(id);
3625    }
3626    if (itr == _streamlines.end()) {
3627        ERROR("Streamlines not found: %s", id.c_str());
3628        return;
3629    }
3630
3631    do {
3632        itr->second->setSeedToRake(start, end, numPoints);
3633    } while (doAll && ++itr != _streamlines.end());
3634
3635    sceneBoundsChanged();
3636    _needsRedraw = true;
3637}
3638
3639/**
3640 * \brief Set the streamlines seed to points inside a disk, with optional
3641 * hole
3642 */
3643void Renderer::setStreamlinesSeedToDisk(const DataSetId& id,
3644                                        double center[3], double normal[3],
3645                                        double radius, double innerRadius,
3646                                        int numPoints)
3647{
3648    StreamlinesHashmap::iterator itr;
3649
3650    bool doAll = false;
3651
3652    if (id.compare("all") == 0) {
3653        itr = _streamlines.begin();
3654        if (itr == _streamlines.end())
3655            return;
3656        doAll = true;
3657    } else {
3658        itr = _streamlines.find(id);
3659    }
3660    if (itr == _streamlines.end()) {
3661        ERROR("Streamlines not found: %s", id.c_str());
3662        return;
3663    }
3664
3665    do {
3666        itr->second->setSeedToDisk(center, normal, radius, innerRadius, numPoints);
3667    } while (doAll && ++itr != _streamlines.end());
3668
3669    sceneBoundsChanged();
3670    _needsRedraw = true;
3671}
3672
3673/**
3674 * \brief Set the streamlines seed to vertices of an n-sided polygon
3675 */
3676void Renderer::setStreamlinesSeedToPolygon(const DataSetId& id,
3677                                           double center[3], double normal[3],
3678                                           double angle, double radius,
3679                                           int numSides)
3680{
3681    StreamlinesHashmap::iterator itr;
3682
3683    bool doAll = false;
3684
3685    if (id.compare("all") == 0) {
3686        itr = _streamlines.begin();
3687        if (itr == _streamlines.end())
3688            return;
3689        doAll = true;
3690    } else {
3691        itr = _streamlines.find(id);
3692    }
3693    if (itr == _streamlines.end()) {
3694        ERROR("Streamlines not found: %s", id.c_str());
3695        return;
3696    }
3697
3698    do {
3699        itr->second->setSeedToPolygon(center, normal, angle, radius, numSides);
3700    } while (doAll && ++itr != _streamlines.end());
3701
3702    sceneBoundsChanged();
3703    _needsRedraw = true;
3704}
3705
3706/**
3707 * \brief Set the streamlines seed to vertices of an n-sided polygon
3708 */
3709void Renderer::setStreamlinesSeedToFilledPolygon(const DataSetId& id,
3710                                                 double center[3],
3711                                                 double normal[3],
3712                                                 double angle, double radius,
3713                                                 int numSides, int numPoints)
3714{
3715    StreamlinesHashmap::iterator itr;
3716
3717    bool doAll = false;
3718
3719    if (id.compare("all") == 0) {
3720        itr = _streamlines.begin();
3721        if (itr == _streamlines.end())
3722            return;
3723        doAll = true;
3724    } else {
3725        itr = _streamlines.find(id);
3726    }
3727    if (itr == _streamlines.end()) {
3728        ERROR("Streamlines not found: %s", id.c_str());
3729        return;
3730    }
3731
3732    do {
3733        itr->second->setSeedToFilledPolygon(center, normal, angle,
3734                                            radius, numSides, numPoints);
3735    } while (doAll && ++itr != _streamlines.end());
3736
3737    sceneBoundsChanged();
3738    _needsRedraw = true;
3739}
3740
3741void Renderer::setStreamlinesTerminalSpeed(const DataSetId& id, double speed)
3742{
3743    StreamlinesHashmap::iterator itr;
3744
3745    bool doAll = false;
3746
3747    if (id.compare("all") == 0) {
3748        itr = _streamlines.begin();
3749        if (itr == _streamlines.end())
3750            return;
3751        doAll = true;
3752    } else {
3753        itr = _streamlines.find(id);
3754    }
3755    if (itr == _streamlines.end()) {
3756        ERROR("Streamlines not found: %s", id.c_str());
3757        return;
3758    }
3759
3760    do {
3761        itr->second->setTerminalSpeed(speed);
3762    } while (doAll && ++itr != _streamlines.end());
3763
3764    sceneBoundsChanged();
3765    _needsRedraw = true;
3766}
3767
3768/**
3769 * \brief Set Streamlines rendering to polylines for the specified DataSet
3770 */
3771void Renderer::setStreamlinesTypeToLines(const DataSetId& id)
3772{
3773    StreamlinesHashmap::iterator itr;
3774
3775    bool doAll = false;
3776
3777    if (id.compare("all") == 0) {
3778        itr = _streamlines.begin();
3779        if (itr == _streamlines.end())
3780            return;
3781        doAll = true;
3782    } else {
3783        itr = _streamlines.find(id);
3784    }
3785    if (itr == _streamlines.end()) {
3786        ERROR("Streamlines not found: %s", id.c_str());
3787        return;
3788    }
3789
3790    do {
3791        itr->second->setLineTypeToLines();
3792    } while (doAll && ++itr != _streamlines.end());
3793
3794    sceneBoundsChanged();
3795    _needsRedraw = true;
3796}
3797
3798/**
3799 * \brief Set Streamlines rendering to tubes for the specified DataSet
3800 */
3801void Renderer::setStreamlinesTypeToTubes(const DataSetId& id, int numSides, double radius)
3802{
3803    StreamlinesHashmap::iterator itr;
3804
3805    bool doAll = false;
3806
3807    if (id.compare("all") == 0) {
3808        itr = _streamlines.begin();
3809        if (itr == _streamlines.end())
3810            return;
3811        doAll = true;
3812    } else {
3813        itr = _streamlines.find(id);
3814    }
3815    if (itr == _streamlines.end()) {
3816        ERROR("Streamlines not found: %s", id.c_str());
3817        return;
3818    }
3819
3820    do {
3821        itr->second->setLineTypeToTubes(numSides, radius);
3822    } while (doAll && ++itr != _streamlines.end());
3823
3824    sceneBoundsChanged();
3825    _needsRedraw = true;
3826}
3827
3828/**
3829 * \brief Set Streamlines rendering to ribbons for the specified DataSet
3830 */
3831void Renderer::setStreamlinesTypeToRibbons(const DataSetId& id, double width, double angle)
3832{
3833    StreamlinesHashmap::iterator itr;
3834
3835    bool doAll = false;
3836
3837    if (id.compare("all") == 0) {
3838        itr = _streamlines.begin();
3839        if (itr == _streamlines.end())
3840            return;
3841        doAll = true;
3842    } else {
3843        itr = _streamlines.find(id);
3844    }
3845    if (itr == _streamlines.end()) {
3846        ERROR("Streamlines not found: %s", id.c_str());
3847        return;
3848    }
3849
3850    do {
3851        itr->second->setLineTypeToRibbons(width, angle);
3852    } while (doAll && ++itr != _streamlines.end());
3853
3854    sceneBoundsChanged();
3855    _needsRedraw = true;
3856}
3857
3858/**
3859 * \brief Set Streamlines maximum length for the specified DataSet
3860 */
3861void Renderer::setStreamlinesLength(const DataSetId& id, double length)
3862{
3863    StreamlinesHashmap::iterator itr;
3864
3865    bool doAll = false;
3866
3867    if (id.compare("all") == 0) {
3868        itr = _streamlines.begin();
3869        if (itr == _streamlines.end())
3870            return;
3871        doAll = true;
3872    } else {
3873        itr = _streamlines.find(id);
3874    }
3875    if (itr == _streamlines.end()) {
3876        ERROR("Streamlines not found: %s", id.c_str());
3877        return;
3878    }
3879
3880    do {
3881        itr->second->setMaxPropagation(length);
3882    } while (doAll && ++itr != _streamlines.end());
3883
3884    sceneBoundsChanged();
3885    _needsRedraw = true;
3886}
3887
3888/**
3889 * \brief Turn on/off rendering of the Streamlines seed geometry for the given DataSet
3890 */
3891void Renderer::setStreamlinesSeedVisibility(const DataSetId& id, bool state)
3892{
3893    StreamlinesHashmap::iterator itr;
3894
3895    bool doAll = false;
3896
3897    if (id.compare("all") == 0) {
3898        itr = _streamlines.begin();
3899        if (itr == _streamlines.end())
3900            return;
3901        doAll = true;
3902    } else {
3903        itr = _streamlines.find(id);
3904    }
3905    if (itr == _streamlines.end()) {
3906        ERROR("Streamlines not found: %s", id.c_str());
3907        return;
3908    }
3909
3910    do {
3911        itr->second->setSeedVisibility(state);
3912    } while (doAll && ++itr != _streamlines.end());
3913
3914    sceneBoundsChanged();
3915    _needsRedraw = true;
3916}
3917
3918/**
3919 * \brief Set the color mode for the specified DataSet
3920 */
3921void Renderer::setStreamlinesColorMode(const DataSetId& id,
3922                                       Streamlines::ColorMode mode,
3923                                       DataSet::DataAttributeType type,
3924                                       const char *name, double range[2])
3925{
3926    StreamlinesHashmap::iterator itr;
3927
3928    bool doAll = false;
3929
3930    if (id.compare("all") == 0) {
3931        itr = _streamlines.begin();
3932        if (itr == _streamlines.end())
3933            return;
3934        doAll = true;
3935    } else {
3936        itr = _streamlines.find(id);
3937    }
3938    if (itr == _streamlines.end()) {
3939        ERROR("Streamlines not found: %s", id.c_str());
3940        return;
3941    }
3942
3943    do {
3944        itr->second->setColorMode(mode, type, name, range);
3945    } while (doAll && ++itr != _streamlines.end());
3946
3947    _needsRedraw = true;
3948}
3949
3950/**
3951 * \brief Set the color mode for the specified DataSet
3952 */
3953void Renderer::setStreamlinesColorMode(const DataSetId& id,
3954                                       Streamlines::ColorMode mode,
3955                                       const char *name, double range[2])
3956{
3957    StreamlinesHashmap::iterator itr;
3958
3959    bool doAll = false;
3960
3961    if (id.compare("all") == 0) {
3962        itr = _streamlines.begin();
3963        if (itr == _streamlines.end())
3964            return;
3965        doAll = true;
3966    } else {
3967        itr = _streamlines.find(id);
3968    }
3969    if (itr == _streamlines.end()) {
3970        ERROR("Streamlines not found: %s", id.c_str());
3971        return;
3972    }
3973
3974    do {
3975        itr->second->setColorMode(mode, name, range);
3976    } while (doAll && ++itr != _streamlines.end());
3977
3978    _needsRedraw = true;
3979}
3980
3981/**
3982 * \brief Set the RGB line/edge color for the specified DataSet
3983 */
3984void Renderer::setStreamlinesSeedColor(const DataSetId& id, float color[3])
3985{
3986    StreamlinesHashmap::iterator itr;
3987
3988    bool doAll = false;
3989
3990    if (id.compare("all") == 0) {
3991        itr = _streamlines.begin();
3992        if (itr == _streamlines.end())
3993            return;
3994        doAll = true;
3995    } else {
3996        itr = _streamlines.find(id);
3997    }
3998    if (itr == _streamlines.end()) {
3999        ERROR("Streamlines not found: %s", id.c_str());
4000        return;
4001    }
4002
4003    do {
4004        itr->second->setSeedColor(color);
4005    } while (doAll && ++itr != _streamlines.end());
4006
4007    _needsRedraw = true;
4008}
4009
4010void Renderer::setText3DBold(const DataSetId& id, bool state)
4011{
4012    Text3DHashmap::iterator itr;
4013
4014    bool doAll = false;
4015
4016    if (id.compare("all") == 0) {
4017        itr = _text3Ds.begin();
4018        if (itr == _text3Ds.end())
4019            return;
4020        doAll = true;
4021    } else {
4022        itr = _text3Ds.find(id);
4023    }
4024    if (itr == _text3Ds.end()) {
4025        ERROR("Text3D not found: %s", id.c_str());
4026        return;
4027    }
4028
4029    do {
4030        itr->second->setBold(state);
4031    } while (doAll && ++itr != _text3Ds.end());
4032
4033    sceneBoundsChanged();
4034    _needsRedraw = true;
4035}
4036
4037/**
4038 * \brief Set the font family for the Text3D
4039 */
4040void Renderer::setText3DFont(const DataSetId& id, const char *fontFamily)
4041{
4042    Text3DHashmap::iterator itr;
4043
4044    bool doAll = false;
4045
4046    if (id.compare("all") == 0) {
4047        itr = _text3Ds.begin();
4048        if (itr == _text3Ds.end())
4049            return;
4050        doAll = true;
4051    } else {
4052        itr = _text3Ds.find(id);
4053    }
4054    if (itr == _text3Ds.end()) {
4055        ERROR("Text3D not found: %s", id.c_str());
4056        return;
4057    }
4058
4059    do {
4060        itr->second->setFont(fontFamily);
4061    } while (doAll && ++itr != _text3Ds.end());
4062
4063    sceneBoundsChanged();
4064    _needsRedraw = true;
4065}
4066
4067/**
4068 * \brief Set the font family for the Text3D
4069 */
4070void Renderer::setText3DFontSize(const DataSetId& id, int size)
4071{
4072    Text3DHashmap::iterator itr;
4073
4074    bool doAll = false;
4075
4076    if (id.compare("all") == 0) {
4077        itr = _text3Ds.begin();
4078        if (itr == _text3Ds.end())
4079            return;
4080        doAll = true;
4081    } else {
4082        itr = _text3Ds.find(id);
4083    }
4084    if (itr == _text3Ds.end()) {
4085        ERROR("Text3D not found: %s", id.c_str());
4086        return;
4087    }
4088
4089    do {
4090        itr->second->setFontSize(size);
4091    } while (doAll && ++itr != _text3Ds.end());
4092
4093    sceneBoundsChanged();
4094    _needsRedraw = true;
4095}
4096
4097void Renderer::setText3DFollowCamera(const DataSetId& id, bool state)
4098{
4099    Text3DHashmap::iterator itr;
4100
4101    bool doAll = false;
4102
4103    if (id.compare("all") == 0) {
4104        itr = _text3Ds.begin();
4105        if (itr == _text3Ds.end())
4106            return;
4107        doAll = true;
4108    } else {
4109        itr = _text3Ds.find(id);
4110    }
4111    if (itr == _text3Ds.end()) {
4112        ERROR("Text3D not found: %s", id.c_str());
4113        return;
4114    }
4115
4116    do {
4117        itr->second->setFollowCamera(state, _renderer);
4118    } while (doAll && ++itr != _text3Ds.end());
4119
4120    sceneBoundsChanged();
4121    _needsRedraw = true;
4122}
4123
4124void Renderer::setText3DItalic(const DataSetId& id, bool state)
4125{
4126    Text3DHashmap::iterator itr;
4127
4128    bool doAll = false;
4129
4130    if (id.compare("all") == 0) {
4131        itr = _text3Ds.begin();
4132        if (itr == _text3Ds.end())
4133            return;
4134        doAll = true;
4135    } else {
4136        itr = _text3Ds.find(id);
4137    }
4138    if (itr == _text3Ds.end()) {
4139        ERROR("Text3D not found: %s", id.c_str());
4140        return;
4141    }
4142
4143    do {
4144        itr->second->setItalic(state);
4145    } while (doAll && ++itr != _text3Ds.end());
4146
4147    sceneBoundsChanged();
4148    _needsRedraw = true;
4149}
4150
4151void Renderer::setText3DShadow(const DataSetId& id, bool state)
4152{
4153    Text3DHashmap::iterator itr;
4154
4155    bool doAll = false;
4156
4157    if (id.compare("all") == 0) {
4158        itr = _text3Ds.begin();
4159        if (itr == _text3Ds.end())
4160            return;
4161        doAll = true;
4162    } else {
4163        itr = _text3Ds.find(id);
4164    }
4165    if (itr == _text3Ds.end()) {
4166        ERROR("Text3D not found: %s", id.c_str());
4167        return;
4168    }
4169
4170    do {
4171        itr->second->setShadow(state);
4172    } while (doAll && ++itr != _text3Ds.end());
4173
4174    sceneBoundsChanged();
4175    _needsRedraw = true;
4176}
4177
4178void Renderer::setText3DText(const DataSetId& id, const char *text)
4179{
4180    Text3DHashmap::iterator itr;
4181
4182    bool doAll = false;
4183
4184    if (id.compare("all") == 0) {
4185        itr = _text3Ds.begin();
4186        if (itr == _text3Ds.end())
4187            return;
4188        doAll = true;
4189    } else {
4190        itr = _text3Ds.find(id);
4191    }
4192    if (itr == _text3Ds.end()) {
4193        ERROR("Text3D not found: %s", id.c_str());
4194        return;
4195    }
4196
4197    do {
4198        itr->second->setText(text);
4199    } while (doAll && ++itr != _text3Ds.end());
4200
4201    sceneBoundsChanged();
4202    _needsRedraw = true;
4203}
4204
4205void Renderer::setVolumeBlendMode(const DataSetId& id, Volume::BlendMode mode)
4206{
4207    VolumeHashmap::iterator itr;
4208
4209    bool doAll = false;
4210
4211    if (id.compare("all") == 0) {
4212        itr = _volumes.begin();
4213        if (itr == _volumes.end())
4214            return;
4215        doAll = true;
4216    } else {
4217        itr = _volumes.find(id);
4218    }
4219    if (itr == _volumes.end()) {
4220        ERROR("Volume not found: %s", id.c_str());
4221        return;
4222    }
4223
4224    do {
4225        itr->second->setBlendMode(mode);
4226    } while (doAll && ++itr != _volumes.end());
4227
4228    _needsRedraw = true;
4229}
4230
4231/**
4232 * \brief Set the sample rate for the volume shader
4233 *
4234 * Smaller values will give better rendering at the cost
4235 * of slower rendering
4236 */
4237void Renderer::setVolumeSampleDistance(const DataSetId& id, double distance)
4238{
4239    VolumeHashmap::iterator itr;
4240
4241    bool doAll = false;
4242
4243    if (id.compare("all") == 0) {
4244        itr = _volumes.begin();
4245        if (itr == _volumes.end())
4246            return;
4247        doAll = true;
4248    } else {
4249        itr = _volumes.find(id);
4250    }
4251    if (itr == _volumes.end()) {
4252        ERROR("Volume not found: %s", id.c_str());
4253        return;
4254    }
4255
4256    do {
4257        distance *= itr->second->getAverageSpacing();
4258        itr->second->setSampleDistance((float)distance);
4259    } while (doAll && ++itr != _volumes.end());
4260
4261    _needsRedraw = true;
4262}
4263
4264/**
4265 * \brief Set the point cloud render style for the specified DataSet
4266 */
4267void Renderer::setWarpCloudStyle(const DataSetId& id,
4268                                 Warp::CloudStyle style)
4269{
4270    WarpHashmap::iterator itr;
4271
4272    bool doAll = false;
4273
4274    if (id.compare("all") == 0) {
4275        itr = _warps.begin();
4276        if (itr == _warps.end())
4277            return;
4278        doAll = true;
4279    } else {
4280        itr = _warps.find(id);
4281    }
4282    if (itr == _warps.end()) {
4283        ERROR("Warp not found: %s", id.c_str());
4284        return;
4285    }
4286
4287    do {
4288        itr->second->setCloudStyle(style);
4289    } while (doAll && ++itr != _warps.end());
4290
4291    _needsRedraw = true;
4292}
4293
4294/**
4295 * \brief Set the color mode for the specified DataSet
4296 */
4297void Renderer::setWarpColorMode(const DataSetId& id,
4298                                Warp::ColorMode mode,
4299                                DataSet::DataAttributeType type,
4300                                const char *name, double range[2])
4301{
4302    WarpHashmap::iterator itr;
4303
4304    bool doAll = false;
4305
4306    if (id.compare("all") == 0) {
4307        itr = _warps.begin();
4308        if (itr == _warps.end())
4309            return;
4310        doAll = true;
4311    } else {
4312        itr = _warps.find(id);
4313    }
4314    if (itr == _warps.end()) {
4315        ERROR("Warp not found: %s", id.c_str());
4316        return;
4317    }
4318
4319    do {
4320        itr->second->setColorMode(mode, type, name, range);
4321    } while (doAll && ++itr != _warps.end());
4322
4323    _needsRedraw = true;
4324}
4325
4326/**
4327 * \brief Set the color mode for the specified DataSet
4328 */
4329void Renderer::setWarpColorMode(const DataSetId& id,
4330                                Warp::ColorMode mode,
4331                                const char *name, double range[2])
4332{
4333    WarpHashmap::iterator itr;
4334
4335    bool doAll = false;
4336
4337    if (id.compare("all") == 0) {
4338        itr = _warps.begin();
4339        if (itr == _warps.end())
4340            return;
4341        doAll = true;
4342    } else {
4343        itr = _warps.find(id);
4344    }
4345    if (itr == _warps.end()) {
4346        ERROR("Warp not found: %s", id.c_str());
4347        return;
4348    }
4349
4350    do {
4351        itr->second->setColorMode(mode, name, range);
4352    } while (doAll && ++itr != _warps.end());
4353
4354    _needsRedraw = true;
4355}
4356
4357/**
4358 * \brief Set amount to scale vector magnitudes when warping
4359 * a mesh
4360 */
4361void Renderer::setWarpWarpScale(const DataSetId& id, double scale)
4362{
4363    WarpHashmap::iterator itr;
4364
4365    bool doAll = false;
4366
4367    if (id.compare("all") == 0) {
4368        itr = _warps.begin();
4369        if (itr == _warps.end())
4370            return;
4371        doAll = true;
4372    } else {
4373        itr = _warps.find(id);
4374    }
4375
4376    if (itr == _warps.end()) {
4377        ERROR("Warp not found: %s", id.c_str());
4378        return;
4379    }
4380
4381    do {
4382        itr->second->setWarpScale(scale);
4383     } while (doAll && ++itr != _warps.end());
4384
4385    sceneBoundsChanged();
4386    _needsRedraw = true;
4387}
Note: See TracBrowser for help on using the repository browser.