source: branches/1.3/packages/vizservers/vtkvis/RendererGraphicsObjs.cpp @ 3877

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

Merge from trunk

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