source: branches/blt4/packages/vizservers/vtkvis/ColorMap.cpp @ 2201

Last change on this file since 2201 was 2201, checked in by gah, 13 years ago
File size: 6.6 KB
Line 
1/* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2/*
3 * Copyright (C) 2011, Purdue Research Foundation
4 *
5 * Author: Leif Delgass <ldelgass@purdue.edu>
6 */
7
8#include <string>
9#include <list>
10#include <cassert>
11#include <vtkLookupTable.h>
12
13#include "ColorMap.h"
14#include "Trace.h"
15
16using namespace Rappture::VtkVis;
17
18ColorMap::ColorMap(const std::string& name) :
19    _name(name),
20    _needsBuild(true),
21    _numTableEntries(256)
22{
23}
24
25ColorMap::~ColorMap()
26{
27}
28
29/**
30 * \brief Return the name/ID of the ColorMap
31 */
32const std::string& ColorMap::getName()
33{
34    return _name;
35}
36
37/**
38 * \brief Build and return the vtkLookupTable from the transfer function
39 */
40vtkLookupTable *ColorMap::getLookupTable()
41{
42    build();
43    assert(_lookupTable != NULL);
44    return _lookupTable;
45}
46
47/**
48 * \brief Insert a new RGB control point into the transfer function
49 */
50void ColorMap::addControlPoint(ControlPoint& cp)
51{
52    _needsBuild = true;
53    // Clamp value to [0,1]
54    if (cp.value < 0.0)
55        cp.value = 0.0;
56    if (cp.value > 1.0)
57        cp.value = 1.0;
58
59    TRACE("New control point: %g  = %g %g %g",
60          cp.value, cp.color[0], cp.color[1], cp.color[2]);
61
62    for (std::list<ControlPoint>::iterator itr = _controlPoints.begin();
63         itr != _controlPoints.end(); ++itr) {
64        if (itr->value == cp.value) {
65            *itr = cp;
66            return;
67        } else if (itr->value > cp.value) {
68            _controlPoints.insert(itr, cp);
69            return;
70        }
71    }
72    // If we reach here, our control point goes at the end
73    _controlPoints.insert(_controlPoints.end(), cp);
74}
75
76/**
77 * \brief Insert a new opacity/alpha control point into the transfer function
78 */
79void ColorMap::addOpacityControlPoint(OpacityControlPoint& cp)
80{
81    _needsBuild = true;
82    // Clamp value to [0,1]
83    if (cp.value < 0.0)
84        cp.value = 0.0;
85    if (cp.value > 1.0)
86        cp.value = 1.0;
87
88    TRACE("New opacity control point: %g  = %g",
89          cp.value, cp.alpha);
90
91    for (std::list<OpacityControlPoint>::iterator itr = _opacityControlPoints.begin();
92         itr != _opacityControlPoints.end(); ++itr) {
93        if (itr->value == cp.value) {
94            *itr = cp;
95            return;
96        } else if (itr->value > cp.value) {
97            _opacityControlPoints.insert(itr, cp);
98            return;
99        }
100    }
101    // If we reach here, our control point goes at the end
102    _opacityControlPoints.insert(_opacityControlPoints.end(), cp);
103}
104
105/**
106 * \brief Set the number of discrete color table entries
107 *
108 * The number of table entries refers to the underlying
109 * vtkLookupTable and is independent of the number of
110 * control points in the transfer function.
111 */
112void ColorMap::setNumberOfTableEntries(int numEntries)
113{
114    if (numEntries != _numTableEntries) {
115        _needsBuild = true;
116        _numTableEntries = numEntries;
117        if (_lookupTable != NULL) {
118            build();
119        }
120    }
121}
122
123/**
124 * \brief Build the lookup table from the control points in the transfer
125 * function
126 */
127void ColorMap::build()
128{
129    if (!_needsBuild)
130        return;
131
132    if (_lookupTable == NULL) {
133        _lookupTable = vtkSmartPointer<vtkLookupTable>::New();
134    }
135
136    _lookupTable->SetNumberOfTableValues(_numTableEntries);
137
138    std::list<ControlPoint>::iterator itr = _controlPoints.begin();
139    std::list<OpacityControlPoint>::iterator oitr = _opacityControlPoints.begin();
140
141    // If first value is > 0, insert a copy at 0 to create
142    // constant range up to first specified cp
143    if (itr->value > 0.0) {
144        ControlPoint cp = *itr;
145        cp.value = 0.0;
146        itr = _controlPoints.insert(itr, cp);
147    }
148    if (oitr->value > 0.0) {
149        OpacityControlPoint ocp = *oitr;
150        ocp.value = 0.0;
151        oitr = _opacityControlPoints.insert(oitr, ocp);
152    }
153
154    std::list<ControlPoint>::iterator itr2 = itr;
155    itr2++;
156    std::list<OpacityControlPoint>::iterator oitr2 = oitr;
157    oitr2++;
158
159    for (int i = 0; i < _numTableEntries; i++) {
160        double value = ((double)i)/(_numTableEntries-1);
161        double color[4];
162        if (itr2 != _controlPoints.end() && value > itr2->value) {
163            itr = itr2;
164            itr2++;
165        }
166        if (oitr2 != _opacityControlPoints.end() && value > oitr2->value) {
167            oitr = oitr2;
168            oitr2++;
169        }
170        if (itr2 == _controlPoints.end()) {
171            TRACE("val: %g Range: %g - 1 Color: %g %g %g", value, itr->value,
172                  itr->color[0], itr->color[1], itr->color[2]);
173            memcpy(color, itr->color, sizeof(double)*3);
174        } else {
175            assert(itr->value < itr2->value);
176            assert(value >= itr->value && value <= itr2->value);
177            lerp(color, *itr, *itr2, value);
178            TRACE("val: %g Range: %g - %g Color: %g %g %g", value, itr->value, itr2->value,
179                  color[0], color[1], color[2]);
180        }
181        if (oitr2 == _opacityControlPoints.end()) {
182            TRACE("val: %g Range: %g - 1 Alpha %g", value, oitr->value,
183                  oitr->alpha);
184            color[3] = oitr->alpha;
185        } else {
186            assert(oitr->value < oitr2->value);
187            assert(value >= oitr->value && value <= oitr2->value);
188            lerp(&color[3], *oitr, *oitr2, value);
189            TRACE("val: %g Range: %g - %g Alpha: %g", value, oitr->value, oitr2->value,
190                  color[3]);
191        }
192        _lookupTable->SetTableValue(i, color);
193    }
194    _needsBuild = false;
195}
196
197void ColorMap::lerp(double *result, const ControlPoint& cp1, const ControlPoint& cp2, double value)
198{
199    double factor = (value - cp1.value) / (cp2.value - cp1.value);
200    for (int i = 0; i < 3; i++) {
201        result[i] = cp1.color[i] * (1.0 - factor) + cp2.color[i] * factor;
202    }
203}
204
205void ColorMap::lerp(double *result, const OpacityControlPoint& cp1, const OpacityControlPoint& cp2, double value)
206{
207    double factor = (value - cp1.value) / (cp2.value - cp1.value);
208    *result = cp1.alpha * (1.0 - factor) + cp2.alpha * factor;
209}
210
211/**
212 * \brief Remove all control points and lookup table
213 */
214void ColorMap::clear()
215{
216    _controlPoints.clear();
217    _opacityControlPoints.clear();
218    _lookupTable = NULL;
219}
220
221/**
222 * \brief Create a default ColorMap with a blue-cyan-green-yellow-red ramp
223 */
224ColorMap * ColorMap::createDefault()
225{
226    ColorMap *colorMap = new ColorMap("default");
227    ControlPoint cp[5];
228    cp[0].value = 0.0;
229    cp[0].color[0] = 0.0;
230    cp[0].color[1] = 0.0;
231    cp[0].color[2] = 1.0;
232    cp[1].value = 0.25;
233    cp[1].color[0] = 0.0;
234    cp[1].color[1] = 1.0;
235    cp[1].color[2] = 1.0;
236    cp[2].value = 0.5;
237    cp[2].color[0] = 0.0;
238    cp[2].color[1] = 1.0;
239    cp[2].color[2] = 0.0;
240    cp[3].value = 0.75;
241    cp[3].color[0] = 1.0;
242    cp[3].color[1] = 1.0;
243    cp[3].color[2] = 0.0;
244    cp[4].value = 1.0;
245    cp[4].color[0] = 1.0;
246    cp[4].color[1] = 0.0;
247    cp[4].color[2] = 0.0;
248    for (int i = 0; i < 5; i++) {
249        colorMap->addControlPoint(cp[i]);
250    }
251    OpacityControlPoint ocp[2];
252    ocp[0].value = 0.0;
253    ocp[0].alpha = 1.0;
254    ocp[1].value = 1.0;
255    ocp[1].alpha = 1.0;
256    colorMap->addOpacityControlPoint(ocp[0]);
257    colorMap->addOpacityControlPoint(ocp[1]);
258    colorMap->build();
259    return colorMap;
260}
Note: See TracBrowser for help on using the repository browser.