23
#include "PreCompiled.h"
27
# include <QCoreApplication>
28
# include <Inventor/fields/SoMFString.h>
29
# include <Inventor/nodes/SoBaseColor.h>
30
# include <Inventor/nodes/SoCoordinate3.h>
31
# include <Inventor/nodes/SoIndexedFaceSet.h>
32
# include <Inventor/nodes/SoMaterial.h>
33
# include <Inventor/nodes/SoText2.h>
34
# include <Inventor/nodes/SoTransform.h>
37
#include "SoFCColorLegend.h"
38
#include "ViewProvider.h"
43
SO_NODE_SOURCE(SoFCColorLegend)
48
SoFCColorLegend::SoFCColorLegend() : _bbox(4.0f, -4.0f, 4.5f, 4.0f)
50
SO_NODE_CONSTRUCTOR(SoFCColorLegend);
51
coords = new SoCoordinate3;
53
labelGroup = new SoSeparator;
56
valueGroup = new SoSeparator;
59
setColorLegend(_currentLegend);
60
setLegendLabels(_currentLegend, 3);
66
SoFCColorLegend::~SoFCColorLegend()
75
void SoFCColorLegend::initClass()
77
SO_NODE_INIT_CLASS(SoFCColorLegend,SoFCColorBarBase,"Separator");
80
void SoFCColorLegend::finish()
85
const char* SoFCColorLegend::getColorBarName() const
87
return QT_TRANSLATE_NOOP("QObject", "Color Legend");
91
std::vector<SbVec3f> getLabelPositions(int num, const SbBox2f& bbox)
93
std::vector<SbVec3f> pos;
94
float fMinY = bbox.getMin()[1];
95
float fMaxX = bbox.getMax()[0];
96
float fMaxY = bbox.getMax()[1] - 0.5f;
99
float fStep = (fMaxY-fMinY) / static_cast<float>(num - 1);
100
pos.emplace_back(fMaxX + 0.1f, fMaxY + 0.20f + fStep, 0.0f);
101
for (int i=0; i<num; i++) {
102
pos.emplace_back(0.0f, -fStep, 0.0f);
109
std::vector<SbVec3f> getValuePositions(int num, const SbBox2f& bbox)
111
std::vector<SbVec3f> pos;
112
float fMinY = bbox.getMin()[1];
113
float fMaxX = bbox.getMax()[0];
114
float fMaxY = bbox.getMax()[1] - 0.5f;
117
float fStep = (fMaxY-fMinY) / static_cast<float>(num - 2);
118
float eps = fStep / 4.0f;
120
pos.emplace_back(fMaxX + 0.1f, fMaxY + 0.25f + 1.5f * fStep, 0.0f);
121
for (int i=0; i<num; i++) {
122
pos.emplace_back(0.0f, -fStep, 0.0f);
143
void SoFCColorLegend::setMarkerLabel(const SoMFString& label)
145
coinRemoveAllChildren(labelGroup);
147
int num = label.getNum();
149
std::vector<SbVec3f> pos = getLabelPositions(num, _bbox);
151
auto trans = new SoTransform;
152
trans->translation.setValue(pos[0]);
153
labelGroup->addChild(trans);
155
for (int i=0; i<num; i++) {
156
auto trans = new SoTransform;
157
auto color = new SoBaseColor;
158
auto text2 = new SoText2;
160
trans->translation.setValue(pos[i+1]);
161
color->rgb.setValue(0, 0, 0);
162
text2->string.setValue(label[i]);
163
labelGroup->addChild(trans);
164
labelGroup->addChild(color);
165
labelGroup->addChild(text2);
170
void SoFCColorLegend::setMarkerValue(const SoMFString& value)
172
coinRemoveAllChildren(valueGroup);
174
int num = value.getNum();
176
std::vector<SbVec3f> pos = getValuePositions(num, _bbox);
178
auto trans = new SoTransform;
179
trans->translation.setValue(pos[0]);
180
valueGroup->addChild(trans);
182
for (int i=0; i<num; i++) {
183
auto trans = new SoTransform;
184
auto color = new SoBaseColor;
185
auto text2 = new SoText2;
187
trans->translation.setValue(pos[i+1]);
188
color->rgb.setValue(0, 0, 0);
189
text2->string.setValue(value[i]);
190
valueGroup->addChild(trans);
191
valueGroup->addChild(color);
192
valueGroup->addChild(text2);
197
void SoFCColorLegend::setViewportSize(const SbVec2s& size)
199
float fMinX, fMinY, fMaxX, fMaxY;
200
float boxWidth = getBounds(size, fMinX, fMinY, fMaxX, fMaxY);
203
_bbox.setBounds(fMinX - boxWidth, fMinY, fMaxX - boxWidth, fMaxY);
205
arrangeLabels(_bbox);
206
arrangeValues(_bbox);
210
void SoFCColorLegend::setRange(float fMin, float fMax, int prec)
212
std::size_t numFields = _currentLegend.hasNumberOfFields();
213
for (std::size_t i = 0; i <= numFields; i++) {
214
float factor = static_cast<float>(i) / numFields;
215
float value = (1 - factor) * fMin + factor * fMax;
216
_currentLegend.setValue(i, value);
219
setColorLegend(_currentLegend);
220
setLegendLabels(_currentLegend, prec);
223
void SoFCColorLegend::setLegendLabels(const App::ColorLegend& legend, int prec)
225
float fMin = legend.getMinValue();
226
float fMax = legend.getMaxValue();
228
std::size_t numFields = legend.hasNumberOfFields();
230
SoMFString labels, values;
232
float eps = std::pow(10.0f, static_cast<float>(-prec));
233
float value = std::min<float>(fabs(fMin), fabs(fMax));
234
std::ios::fmtflags flags = value < eps ? (std::ios::scientific | std::ios::showpoint | std::ios::showpos)
235
: (std::ios::fixed | std::ios::showpoint | std::ios::showpos);
237
for (std::size_t i=0; i < numFields; i++) {
239
s << legend.getText(numFields - 1 - i);
240
labels.set1Value(i, s.str().c_str());
243
for (std::size_t i=0; i <= numFields; i++) {
247
float fValue = legend.getValue(numFields - i);
249
values.set1Value(i, s.str().c_str());
252
setMarkerLabel(labels);
253
setMarkerValue(values);
258
void SoFCColorLegend::modifyPoints(const SbBox2f& box)
260
float fMinX = box.getMin()[0];
261
float fMinY = box.getMin()[1];
262
float fMaxX = box.getMax()[0];
263
float fMaxY = box.getMax()[1] - 0.5f;
266
int intFields = coords->point.getNum() / 4;
267
for (int i = 0; i < intFields; i++) {
268
float w = static_cast<float>(i) / (intFields - 1);
269
float fPosY1 = w * fMaxY + (1.0f - w) * fMinY;
270
float fPosY2 = fPosY1 + 0.5f;
271
coords->point.set1Value(4 * i, fMinX, fPosY1, 0.0f);
272
coords->point.set1Value(4 * i + 1, fMaxX, fPosY1, 0.0f);
273
coords->point.set1Value(4 * i + 2, fMaxX, fPosY2, 0.0f);
274
coords->point.set1Value(4 * i + 3, fMinX, fPosY2, 0.0f);
278
void SoFCColorLegend::arrangeLabels(const SbBox2f& box)
282
for (int i=0; i<labelGroup->getNumChildren(); i++) {
283
if (labelGroup->getChild(i)->getTypeId() == SoTransform::getClassTypeId())
288
std::vector<SbVec3f> pos = getLabelPositions(num-1, box);
291
for (int j=0; j<labelGroup->getNumChildren(); j++) {
292
if (labelGroup->getChild(j)->getTypeId() == SoTransform::getClassTypeId()) {
293
static_cast<SoTransform*>(labelGroup->getChild(j))->translation.setValue(pos[index++]);
299
void SoFCColorLegend::arrangeValues(const SbBox2f& box)
303
for (int i=0; i<valueGroup->getNumChildren(); i++) {
304
if (valueGroup->getChild(i)->getTypeId() == SoTransform::getClassTypeId())
309
std::vector<SbVec3f> pos = getValuePositions(num-1, box);
312
for (int j=0; j<valueGroup->getNumChildren(); j++) {
313
if (valueGroup->getChild(j)->getTypeId() == SoTransform::getClassTypeId()) {
314
static_cast<SoTransform*>(valueGroup->getChild(j))->translation.setValue(pos[index++]);
320
void SoFCColorLegend::setColorLegend(const App::ColorLegend& legend)
323
std::size_t numFields = legend.hasNumberOfFields();
324
int intFields = static_cast<int>(numFields);
325
coords->point.setNum(4 * intFields);
329
auto faceset = new SoIndexedFaceSet;
330
faceset->coordIndex.setNum(5 * intFields);
331
for (int j = 0; j < intFields; j++) {
332
faceset->coordIndex.set1Value(5*j, 4*j);
333
faceset->coordIndex.set1Value(5*j+1, 4*j+1);
334
faceset->coordIndex.set1Value(5*j+2, 4*j+2);
335
faceset->coordIndex.set1Value(5*j+3, 4*j+3);
336
faceset->coordIndex.set1Value(5*j+4, SO_END_FACE_INDEX);
339
auto mat = new SoMaterial;
340
mat->diffuseColor.setNum(intFields);
341
for (std::size_t k = 0; k < numFields; k++) {
342
App::Color col = legend.getColor(k);
343
mat->diffuseColor.set1Value(k, col.r, col.g, col.b);
346
auto matBinding = new SoMaterialBinding;
347
matBinding->value = SoMaterialBinding::PER_FACE;
350
if (getNumChildren() > 0)
351
coinRemoveAllChildren(this);
352
addChild(labelGroup);
353
addChild(valueGroup);
356
addChild(matBinding);