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

Last change on this file since 4364 was 4090, checked in by ldelgass, 10 years ago

Add commands to manually set cut plane on image slice

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