FreeCAD

Форк
0
/
SoFCColorLegend.cpp 
358 строк · 11.2 Кб
1
/***************************************************************************
2
 *   Copyright (c) 2005 Werner Mayer <wmayer[at]users.sourceforge.net>     *
3
 *                                                                         *
4
 *   This file is part of the FreeCAD CAx development system.              *
5
 *                                                                         *
6
 *   This library is free software; you can redistribute it and/or         *
7
 *   modify it under the terms of the GNU Library General Public           *
8
 *   License as published by the Free Software Foundation; either          *
9
 *   version 2 of the License, or (at your option) any later version.      *
10
 *                                                                         *
11
 *   This library  is distributed in the hope that it will be useful,      *
12
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
13
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
14
 *   GNU Library General Public License for more details.                  *
15
 *                                                                         *
16
 *   You should have received a copy of the GNU Library General Public     *
17
 *   License along with this library; see the file COPYING.LIB. If not,    *
18
 *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
19
 *   Suite 330, Boston, MA  02111-1307, USA                                *
20
 *                                                                         *
21
 ***************************************************************************/
22

23
#include "PreCompiled.h"
24

25
#ifndef _PreComp_
26
# include <sstream>
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>
35
#endif
36

37
#include "SoFCColorLegend.h"
38
#include "ViewProvider.h"
39

40

41
using namespace Gui;
42

43
SO_NODE_SOURCE(SoFCColorLegend)
44

45
/*!
46
  Constructor.
47
*/
48
SoFCColorLegend::SoFCColorLegend() : _bbox(4.0f, -4.0f, 4.5f, 4.0f)
49
{
50
    SO_NODE_CONSTRUCTOR(SoFCColorLegend);
51
    coords = new SoCoordinate3;
52
    coords->ref();
53
    labelGroup = new SoSeparator;
54
    labelGroup->ref();
55

56
    valueGroup = new SoSeparator;
57
    valueGroup->ref();
58

59
    setColorLegend(_currentLegend);
60
    setLegendLabels(_currentLegend, 3);
61
}
62

63
/*!
64
  Destructor.
65
*/
66
SoFCColorLegend::~SoFCColorLegend()
67
{
68
    //delete THIS;
69
    coords->unref();
70
    labelGroup->unref();
71
    valueGroup->unref();
72
}
73

74
// doc from parent
75
void SoFCColorLegend::initClass()
76
{
77
    SO_NODE_INIT_CLASS(SoFCColorLegend,SoFCColorBarBase,"Separator");
78
}
79

80
void SoFCColorLegend::finish()
81
{
82
    atexit_cleanup();
83
}
84

85
const char* SoFCColorLegend::getColorBarName() const
86
{
87
    return QT_TRANSLATE_NOOP("QObject", "Color Legend");
88
}
89

90
namespace {
91
std::vector<SbVec3f> getLabelPositions(int num, const SbBox2f& bbox)
92
{
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;
97

98
    if (num > 1) {
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);
103
        }
104
    }
105

106
    return pos;
107
}
108

109
std::vector<SbVec3f> getValuePositions(int num, const SbBox2f& bbox)
110
{
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;
115

116
    if (num > 2) {
117
        float fStep = (fMaxY-fMinY) / static_cast<float>(num - 2);
118
        float eps = fStep / 4.0f;
119

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);
123
        }
124

125
        SbVec3f v;
126
        v = pos[1];
127
        v[1] -= eps;
128
        pos[1] = v;
129

130
        v = pos[2];
131
        v[1] += eps;
132
        pos[2] = v;
133

134
        v = pos.back();
135
        v[1] += eps;
136
        pos.back() = v;
137
    }
138

139
    return pos;
140
}
141
}
142

143
void SoFCColorLegend::setMarkerLabel(const SoMFString& label)
144
{
145
    coinRemoveAllChildren(labelGroup);
146

147
    int num = label.getNum();
148
    if (num > 1) {
149
        std::vector<SbVec3f> pos = getLabelPositions(num, _bbox);
150

151
        auto trans = new SoTransform;
152
        trans->translation.setValue(pos[0]);
153
        labelGroup->addChild(trans);
154

155
        for (int i=0; i<num; i++) {
156
            auto trans = new SoTransform;
157
            auto color = new SoBaseColor;
158
            auto text2 = new SoText2;
159

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);
166
        }
167
    }
168
}
169

170
void SoFCColorLegend::setMarkerValue(const SoMFString& value)
171
{
172
    coinRemoveAllChildren(valueGroup);
173

174
    int num = value.getNum();
175
    if (num > 1) {
176
        std::vector<SbVec3f> pos = getValuePositions(num, _bbox);
177

178
        auto trans = new SoTransform;
179
        trans->translation.setValue(pos[0]);
180
        valueGroup->addChild(trans);
181

182
        for (int i=0; i<num; i++) {
183
            auto trans = new SoTransform;
184
            auto color = new SoBaseColor;
185
            auto text2 = new SoText2;
186

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);
193
        }
194
    }
195
}
196

197
void SoFCColorLegend::setViewportSize(const SbVec2s& size)
198
{
199
    float fMinX, fMinY, fMaxX, fMaxY;
200
    float boxWidth = getBounds(size, fMinX, fMinY, fMaxX, fMaxY);
201

202
    // legend bar is shifted to the left by width of the labels to assure that labels are fully visible
203
    _bbox.setBounds(fMinX - boxWidth, fMinY, fMaxX - boxWidth, fMaxY);
204

205
    arrangeLabels(_bbox);
206
    arrangeValues(_bbox);
207
    modifyPoints(_bbox);
208
}
209

210
void SoFCColorLegend::setRange(float fMin, float fMax, int prec)
211
{
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);
217
    }
218

219
    setColorLegend(_currentLegend);
220
    setLegendLabels(_currentLegend, prec);
221
}
222

223
void SoFCColorLegend::setLegendLabels(const App::ColorLegend& legend, int prec)
224
{
225
    float fMin = legend.getMinValue();
226
    float fMax = legend.getMaxValue();
227

228
    std::size_t numFields = legend.hasNumberOfFields();
229

230
    SoMFString labels, values;
231

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);
236

237
    for (std::size_t i=0; i < numFields; i++) {
238
        std::stringstream s;
239
        s << legend.getText(numFields - 1 - i);
240
        labels.set1Value(i, s.str().c_str());
241
    }
242

243
    for (std::size_t i=0; i <= numFields; i++) {
244
        std::stringstream s;
245
        s.precision(prec);
246
        s.setf(flags);
247
        float fValue = legend.getValue(numFields - i);
248
        s << fValue;
249
        values.set1Value(i, s.str().c_str());
250
    }
251

252
    setMarkerLabel(labels);
253
    setMarkerValue(values);
254

255
    setModified();
256
}
257

258
void SoFCColorLegend::modifyPoints(const SbBox2f& box)
259
{
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;
264

265
    // set the vertices spanning the faces for the color legend
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);
275
    }
276
}
277

278
void SoFCColorLegend::arrangeLabels(const SbBox2f& box)
279
{
280
    // search for the labels
281
    int num=0;
282
    for (int i=0; i<labelGroup->getNumChildren(); i++) {
283
        if (labelGroup->getChild(i)->getTypeId() == SoTransform::getClassTypeId())
284
            num++;
285
    }
286

287
    if (num > 2) {
288
        std::vector<SbVec3f> pos = getLabelPositions(num-1, box);
289

290
        int index = 0;
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++]);
294
            }
295
        }
296
    }
297
}
298

299
void SoFCColorLegend::arrangeValues(const SbBox2f& box)
300
{
301
    // search for the labels
302
    int num=0;
303
    for (int i=0; i<valueGroup->getNumChildren(); i++) {
304
        if (valueGroup->getChild(i)->getTypeId() == SoTransform::getClassTypeId())
305
            num++;
306
    }
307

308
    if (num > 3) {
309
        std::vector<SbVec3f> pos = getValuePositions(num-1, box);
310

311
        int index = 0;
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++]);
315
            }
316
        }
317
    }
318
}
319

320
void SoFCColorLegend::setColorLegend(const App::ColorLegend& legend)
321
{
322
    // create top value field
323
    std::size_t numFields = legend.hasNumberOfFields();
324
    int intFields = static_cast<int>(numFields);
325
    coords->point.setNum(4 * intFields);
326
    modifyPoints(_bbox);
327

328
    // for numFields colors we need numFields quads
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);
337
    }
338

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);
344
    }
345

346
    auto matBinding = new SoMaterialBinding;
347
    matBinding->value = SoMaterialBinding::PER_FACE;
348

349
    // first clear the children
350
    if (getNumChildren() > 0)
351
        coinRemoveAllChildren(this);
352
    addChild(labelGroup);
353
    addChild(valueGroup);
354
    addChild(coords);
355
    addChild(mat);
356
    addChild(matBinding);
357
    addChild(faceset);
358
}
359

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.