OGS
VtkColorLookupTable.cpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: Copyright (c) OpenGeoSys Community (opengeosys.org)
2// SPDX-License-Identifier: BSD-3-Clause
3
5
6#include <vtkObjectFactory.h>
7
8#include <cmath>
9#include <sstream>
10
12#include "BaseLib/Logging.h"
13
15
17
19{
20 for (auto& it : _dict)
21 {
22 delete it.second;
23 }
24}
25
26unsigned char VtkColorLookupTable::linInterpolation(unsigned char a,
27 unsigned char b,
28 double p) const
29{
30 return static_cast<unsigned char>(a * (1 - p) + b * p);
31}
32
33unsigned char VtkColorLookupTable::expInterpolation(unsigned char a,
34 unsigned char b,
35 double gamma,
36 double p) const
37{
38 assert(gamma > 0 && gamma < 4);
39 return static_cast<unsigned char>((b - a) * pow(p, gamma) + a);
40}
41
43{
44 double range[2];
45 this->GetTableRange(range);
46 const double interval = range[1] - range[0];
47 this->SetNumberOfTableValues(static_cast<vtkIdType>(ceil(interval)) + 1);
48 // const vtkIdType nColours = this->GetNumberOfTableValues();
49 if (!_dict.empty())
50 {
51 // make sure that color map starts with the first color in the
52 // dictionary
53 unsigned char startcolor[4] = {0, 0, 0, 0};
54 std::pair<std::size_t, unsigned char*> lastValue(0, startcolor);
55
56 for (auto& it : _dict)
57 {
58 double val = (it.first < range[0])
59 ? range[0]
60 : ((it.first > range[1]) ? range[1] : it.first);
61 auto const nextIndex =
62 static_cast<std::size_t>(std::floor(val - range[0]));
63
64 this->SetTableValueRGBA(nextIndex, it.second);
65
66 if (nextIndex - lastValue.first > 0)
67 {
68 for (std::size_t i = lastValue.first + 1; i < nextIndex; i++)
69 {
70 unsigned char int_rgba[4];
71 double pos =
72 (i - lastValue.first) /
73 (static_cast<double>(nextIndex - lastValue.first));
74
76 {
77 for (std::size_t j = 0; j < 4; j++)
78 {
79 int_rgba[j] = linInterpolation(
80 (lastValue.second)[j], (it.second)[j], pos);
81 }
82 }
84 {
85 for (std::size_t j = 0; j < 4; j++)
86 {
87 int_rgba[j] =
88 expInterpolation((lastValue.second)[j],
89 (it.second)[j], 0.2, pos);
90 }
91 }
92 else
93 { // no interpolation
94 for (std::size_t j = 0; j < 4; j++)
95 {
96 int_rgba[j] = (lastValue.second)[j];
97 }
98 }
99
100 this->SetTableValueRGBA(i, int_rgba);
101 }
102 }
103
104 lastValue.first = nextIndex;
105 lastValue.second = it.second;
106 }
107 }
108 else
109 {
110 vtkLookupTable::Build();
111 }
112}
113
116{
117 std::size_t const n_colors(lut.size());
118 for (std::size_t i = 0; i < n_colors; ++i)
119 {
120 setColor(std::get<0>(lut[i]), std::get<1>(lut[i]));
121 }
123 auto const range(lut.getTableRange());
124 SetTableRange(range.first, range.second);
125 Build();
126}
127
128void VtkColorLookupTable::writeToFile(const std::string& filename)
129{
130 std::stringstream strout;
131 strout << "Writing color table to " << filename << " ... ";
132 std::ofstream out(filename.c_str(), std::ios::out);
133
134 std::size_t nColors = this->GetNumberOfTableValues();
135 for (std::size_t i = 0; i < nColors; i++)
136 {
137 unsigned char rgba[4];
138 this->GetTableValue(i, rgba);
139 out << i << "\t" << rgba[0] << "\t" << rgba[1] << "\t" << rgba[2]
140 << "\n";
141 }
142
143 strout << " done." << std::endl;
144 INFO("{:s}", strout.str());
145 out.close();
146}
147
149 unsigned char rgba[4])
150{
151 double value[4];
152
153 for (unsigned i = 0; i < 4; ++i)
154 {
155 value[i] = rgba[i] / 255.0;
156 }
157 vtkLookupTable::SetTableValue(idx, value);
158}
159
160void VtkColorLookupTable::GetTableValue(vtkIdType idx, unsigned char rgba[4])
161{
162 double value[4];
163 vtkLookupTable::GetTableValue(idx, value);
164
165 for (unsigned i = 0; i < 4; ++i)
166 {
167 rgba[i] = static_cast<unsigned char>(value[i] * 255.0);
168 }
169}
170
172 DataHolderLib::Color const& color)
173{
174 auto* dict_rgba = new unsigned char[4];
175 for (std::size_t i = 0; i < 4; i++)
176 {
177 dict_rgba[i] = color[i];
178 }
179 _dict.insert(std::pair<double, unsigned char*>(pos, dict_rgba));
180}
181
182void VtkColorLookupTable::getColor(vtkIdType index, unsigned char rgba[4]) const
183{
184 index = ((index < this->TableRange[0])
185 ? static_cast<vtkIdType>(this->TableRange[0])
186 : (index >= this->TableRange[1]
187 ? static_cast<vtkIdType>(this->TableRange[1]) - 1
188 : index));
189 index = static_cast<std::size_t>(std::floor(
190 (index - this->TableRange[0]) *
191 (this->NumberOfColors / (this->TableRange[1] - this->TableRange[0]))));
192
193 unsigned char* _rgba;
194 _rgba = this->Table->GetPointer(index * 4);
195 for (std::size_t i = 0; i < 4; i++)
196 {
197 rgba[i] = _rgba[i];
198 }
199}
void INFO(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:28
vtkStandardNewMacro(VtkColorLookupTable)
DataHolderLib::LUTType getInterpolationType() const
std::pair< double, double > getTableRange() const
Calculates and stores a colour lookup table.
~VtkColorLookupTable() override
Destructor.
DataHolderLib::LUTType _type
void setColor(double pos, DataHolderLib::Color const &color)
unsigned char expInterpolation(unsigned char a, unsigned char b, double gamma, double p) const
Interpolates values exponentially. gamma should roughly be in [0,4), for gamma=1 interpolation is lin...
void writeToFile(const std::string &filename)
Exports a color table to a file.
std::map< double, unsigned char * > _dict
void SetTableValueRGBA(vtkIdType idx, unsigned char rgba[4])
Set a value within the LUT.
void Build() override
Builds the colour table based on the previously set parameters. This method should only be called aft...
unsigned char linInterpolation(unsigned char a, unsigned char b, double p) const
Interpolates values linearly.
void GetTableValue(vtkIdType idx, unsigned char rgba[4])
Get a value from the LUT.
VtkColorLookupTable()
Constructor.
void setInterpolationType(DataHolderLib::LUTType type)
Sets the type of interpolation.
void getColor(vtkIdType index, unsigned char rgba[4]) const
void setLookupTable(DataHolderLib::ColorLookupTable const &lut)
Imports settings of OGS lookup table class.
std::array< unsigned char, 4 > Color
Definition Color.h:12