source: branches/blt4/packages/vizservers/vtkvis/RendererGraphicsObjs.cpp @ 3892

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