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

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

Add protocol for setting max. number of glyphs

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