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

Last change on this file since 3978 was 3961, checked in by ldelgass, 11 years ago

Add volume blendmode option for VTK volume renderer. Also, don't change field
active scalar if requested field not found in dataset (previously, active
scalar field would be cleared to NULL if field not found).

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