FreeCAD

Форк
0
/
SoBrepEdgeSet.cpp 
466 строк · 16.5 Кб
1
/***************************************************************************
2
 *   Copyright (c) 2011 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
# ifdef FC_OS_WIN32
27
#  include <windows.h>
28
# endif
29
# ifdef FC_OS_MACOSX
30
#  include <OpenGL/gl.h>
31
# else
32
#  include <GL/gl.h>
33
# endif
34
# include <algorithm>
35
# include <cfloat>
36
# include <Inventor/SoPickedPoint.h>
37
# include <Inventor/SoPrimitiveVertex.h>
38
# include <Inventor/actions/SoGetBoundingBoxAction.h>
39
# include <Inventor/actions/SoGLRenderAction.h>
40
# include <Inventor/bundles/SoMaterialBundle.h>
41
# include <Inventor/details/SoLineDetail.h>
42
# include <Inventor/elements/SoCoordinateElement.h>
43
# include <Inventor/elements/SoGLCoordinateElement.h>
44
# include <Inventor/elements/SoLineWidthElement.h>
45
# include <Inventor/errors/SoDebugError.h>
46
# include <Inventor/misc/SoState.h>
47
#endif
48

49
#include <Gui/SoFCUnifiedSelection.h>
50
#include "SoBrepEdgeSet.h"
51

52

53
using namespace PartGui;
54

55
SO_NODE_SOURCE(SoBrepEdgeSet)
56

57
struct SoBrepEdgeSet::SelContext: Gui::SoFCSelectionContext {
58
    std::vector<int32_t> hl, sl;
59
};
60

61
void SoBrepEdgeSet::initClass()
62
{
63
    SO_NODE_INIT_CLASS(SoBrepEdgeSet, SoIndexedLineSet, "IndexedLineSet");
64
}
65

66
SoBrepEdgeSet::SoBrepEdgeSet()
67
    : selContext(std::make_shared<SelContext>())
68
    , selContext2(std::make_shared<SelContext>())
69
{
70
    SO_NODE_CONSTRUCTOR(SoBrepEdgeSet);
71
}
72

73
void SoBrepEdgeSet::GLRender(SoGLRenderAction *action)
74
{
75
    auto state = action->getState();
76
    selCounter.checkRenderCache(state);
77

78
    SelContextPtr ctx2;
79
    SelContextPtr ctx = Gui::SoFCSelectionRoot::getRenderContext<SelContext>(this,selContext,ctx2);
80
    if(ctx2 && ctx2->selectionIndex.empty())
81
        return;
82
    if(selContext2->checkGlobal(ctx)) {
83
        if(selContext2->isSelectAll()) {
84
            selContext2->sl.clear();
85
            selContext2->sl.push_back(-1);
86
        }else if(ctx)
87
            selContext2->sl = ctx->sl;
88
        if(selContext2->highlightIndex==INT_MAX) {
89
            selContext2->hl.clear();
90
            selContext2->hl.push_back(-1);
91
        }else if(ctx)
92
            selContext2->hl = ctx->hl;
93
        ctx = selContext2;
94
    }
95

96
    if(ctx && ctx->highlightIndex==INT_MAX) {
97
        if(ctx->selectionIndex.empty() || ctx->isSelectAll()) {
98
            if(ctx2) {
99
                ctx2->selectionColor = ctx->highlightColor;
100
                renderSelection(action,ctx2);
101
            } else
102
                renderHighlight(action,ctx);
103
        }else{
104
            if(!action->isRenderingDelayedPaths())
105
                renderSelection(action,ctx);
106
            if(ctx2) {
107
                ctx2->selectionColor = ctx->highlightColor;
108
                renderSelection(action,ctx2);
109
            } else
110
                renderHighlight(action,ctx);
111
            if(action->isRenderingDelayedPaths())
112
                renderSelection(action,ctx);
113
        }
114
        return;
115
    }
116

117
    if(!action->isRenderingDelayedPaths())
118
        renderHighlight(action,ctx);
119
    if(ctx && !ctx->selectionIndex.empty()) {
120
        if(ctx->isSelectAll()) {
121
            if(ctx2) {
122
                ctx2->selectionColor = ctx->selectionColor;
123
                renderSelection(action,ctx2);
124
            }else if(ctx->isSelectAll())
125
                renderSelection(action,ctx);
126
            if(action->isRenderingDelayedPaths())
127
                renderHighlight(action,ctx);
128
            return;
129
        }
130
        if(!action->isRenderingDelayedPaths())
131
            renderSelection(action,ctx);
132
    }
133
    if(ctx2 && !ctx2->selectionIndex.empty())
134
        renderSelection(action,ctx2,false);
135
    else
136
        inherited::GLRender(action);
137

138
    // Workaround for #0000433
139
//#if !defined(FC_OS_WIN32)
140
    if(!action->isRenderingDelayedPaths())
141
        renderHighlight(action,ctx);
142
    if(ctx && !ctx->selectionIndex.empty())
143
        renderSelection(action,ctx);
144
    if(action->isRenderingDelayedPaths())
145
        renderHighlight(action,ctx);
146
//#endif
147
}
148

149
void SoBrepEdgeSet::GLRenderBelowPath(SoGLRenderAction * action)
150
{
151
    inherited::GLRenderBelowPath(action);
152
}
153

154
void SoBrepEdgeSet::getBoundingBox(SoGetBoundingBoxAction * action) {
155

156
    SelContextPtr ctx2 = Gui::SoFCSelectionRoot::getSecondaryActionContext<SelContext>(action,this);
157
    if(!ctx2 || (ctx2->sl.size()==1 && ctx2->sl[0]<0)) {
158
        inherited::getBoundingBox(action);
159
        return;
160
    }
161

162
    if(ctx2->sl.empty())
163
        return;
164

165
    auto state = action->getState();
166
    auto coords = SoCoordinateElement::getInstance(state);
167
    const SbVec3f *coords3d = coords->getArrayPtr3();
168

169
    if(!validIndexes(coords,ctx2->sl))
170
        return;
171

172
    SbBox3f bbox;
173

174
    int32_t i;
175
    const int32_t *cindices = &ctx2->sl[0];
176
    const int32_t *end = cindices + ctx2->sl.size();
177
    while (cindices < end) {
178
        bbox.extendBy(coords3d[*cindices++]);
179
        i = (cindices < end) ? *cindices++ : -1;
180
        while (i >= 0) {
181
            bbox.extendBy(coords3d[i]);
182
            i = cindices < end ? *cindices++ : -1;
183
        }
184
    }
185
    if(!bbox.isEmpty())
186
        action->extendBy(bbox);
187
}
188

189
void SoBrepEdgeSet::renderShape(const SoGLCoordinateElement * const coords,
190
                                const int32_t *cindices, int numindices)
191
{
192

193
    const SbVec3f * coords3d = coords->getArrayPtr3();
194

195
    int32_t i;
196
    int previ;
197
    const int32_t *end = cindices + numindices;
198
    while (cindices < end) {
199
        glBegin(GL_LINE_STRIP);
200
        previ = *cindices++;
201
        i = (cindices < end) ? *cindices++ : -1;
202
        while (i >= 0) {
203
            glVertex3fv((const GLfloat*) (coords3d + previ));
204
            glVertex3fv((const GLfloat*) (coords3d + i));
205
            previ = i;
206
            i = cindices < end ? *cindices++ : -1;
207
        }
208
        glEnd();
209
    }
210
}
211

212
void SoBrepEdgeSet::renderHighlight(SoGLRenderAction *action, SelContextPtr ctx)
213
{
214
    if(!ctx || ctx->highlightIndex<0)
215
        return;
216

217
    SoState * state = action->getState();
218
    state->push();
219
  //SoLineWidthElement::set(state, this, 4.0f);
220

221
    SoLazyElement::setEmissive(state, &ctx->highlightColor);
222
    packedColor = ctx->highlightColor.getPackedValue(0.0);
223
    SoLazyElement::setPacked(state, this,1, &packedColor,false);
224

225
    const SoCoordinateElement * coords;
226
    const SbVec3f * normals;
227
    const int32_t * cindices;
228
    int numcindices;
229
    const int32_t * nindices;
230
    const int32_t * tindices;
231
    const int32_t * mindices;
232
    SbBool normalCacheUsed;
233

234
    this->getVertexData(state, coords, normals, cindices, nindices,
235
        tindices, mindices, numcindices, false, normalCacheUsed);
236

237
    SoMaterialBundle mb(action);
238
    mb.sendFirst(); // make sure we have the correct material
239

240
    int num = (int)ctx->hl.size();
241
    if (num > 0) {
242
        if (ctx->hl[0] < 0) {
243
            renderShape(static_cast<const SoGLCoordinateElement*>(coords), cindices, numcindices);
244
        }
245
        else {
246
            const int32_t* id = &(ctx->hl[0]);
247
            if (!validIndexes(coords, ctx->hl)) {
248
                SoDebugError::postWarning("SoBrepEdgeSet::renderHighlight", "highlightIndex out of range");
249
            }
250
            else {
251
                renderShape(static_cast<const SoGLCoordinateElement*>(coords), id, num);
252
            }
253
        }
254
    }
255
    state->pop();
256
}
257

258
void SoBrepEdgeSet::renderSelection(SoGLRenderAction *action, SelContextPtr ctx, bool push)
259
{
260
    SoState * state = action->getState();
261
    if(push){
262
        state->push();
263
        //SoLineWidthElement::set(state, this, 4.0f);
264

265
        SoLazyElement::setEmissive(state, &ctx->selectionColor);
266
        packedColor = ctx->selectionColor.getPackedValue(0.0);
267
        SoLazyElement::setPacked(state, this,1, &packedColor,false);
268
    }
269

270
    const SoCoordinateElement * coords;
271
    const SbVec3f * normals;
272
    const int32_t * cindices;
273
    int numcindices;
274
    const int32_t * nindices;
275
    const int32_t * tindices;
276
    const int32_t * mindices;
277
    SbBool normalCacheUsed;
278

279
    this->getVertexData(state, coords, normals, cindices, nindices,
280
        tindices, mindices, numcindices, false, normalCacheUsed);
281

282
    SoMaterialBundle mb(action);
283
    mb.sendFirst(); // make sure we have the correct material
284

285
    int num = (int)ctx->sl.size();
286
    if (num > 0) {
287
        if (ctx->sl[0] < 0) {
288
            renderShape(static_cast<const SoGLCoordinateElement*>(coords), cindices, numcindices);
289
        }
290
        else {
291
            cindices = &(ctx->sl[0]);
292
            numcindices = (int)ctx->sl.size();
293
            if (!validIndexes(coords, ctx->sl)) {
294
                SoDebugError::postWarning("SoBrepEdgeSet::renderSelection", "selectionIndex out of range");
295
            }
296
            else {
297
                renderShape(static_cast<const SoGLCoordinateElement*>(coords), cindices, numcindices);
298
            }
299
        }
300
    }
301
    if(push) state->pop();
302
}
303

304
bool SoBrepEdgeSet::validIndexes(const SoCoordinateElement* coords, const std::vector<int32_t>& pts) const
305
{
306
    for (int32_t it : pts) {
307
        if (it >= coords->getNum()) {
308
            return false;
309
        }
310
    }
311
    return true;
312
}
313

314
void SoBrepEdgeSet::doAction(SoAction* action)
315
{
316
    if (action->getTypeId() == Gui::SoHighlightElementAction::getClassTypeId()) {
317
        Gui::SoHighlightElementAction* hlaction = static_cast<Gui::SoHighlightElementAction*>(action);
318
        selCounter.checkAction(hlaction);
319
        if (!hlaction->isHighlighted()) {
320
            SelContextPtr ctx = Gui::SoFCSelectionRoot::getActionContext(action,this,selContext,false);
321
            if(ctx) {
322
                ctx->highlightIndex = -1;
323
                ctx->hl.clear();
324
                touch();
325
            }
326
            return;
327
        }
328
        const SoDetail* detail = hlaction->getElement();
329
        if (!detail) {
330
            SelContextPtr ctx = Gui::SoFCSelectionRoot::getActionContext(action,this,selContext);
331
            ctx->highlightColor = hlaction->getColor();
332
            ctx->highlightIndex = INT_MAX;
333
            ctx->hl.clear();
334
            ctx->hl.push_back(-1);
335
            touch();
336
            return;
337
        }
338

339
        if (!detail->isOfType(SoLineDetail::getClassTypeId())) {
340
            SelContextPtr ctx = Gui::SoFCSelectionRoot::getActionContext(action,this,selContext,false);
341
            if(ctx) {
342
                ctx->highlightIndex = -1;
343
                ctx->hl.clear();
344
                touch();
345
            }
346
            return;
347
        }
348

349
        SelContextPtr ctx = Gui::SoFCSelectionRoot::getActionContext(action,this,selContext);
350
        ctx->highlightColor = hlaction->getColor();
351
        int index = static_cast<const SoLineDetail*>(detail)->getLineIndex();
352
        const int32_t* cindices = this->coordIndex.getValues(0);
353
        int numcindices = this->coordIndex.getNum();
354

355
        ctx->hl.clear();
356
        for(int section=0,i=0;i<numcindices;i++) {
357
            if(cindices[i] < 0) {
358
                if(++section > index)
359
                    break;
360
            }else if(section == index)
361
                ctx->hl.push_back(cindices[i]);
362
        }
363
        if(!ctx->hl.empty())
364
            ctx->highlightIndex = index;
365
        else
366
            ctx->highlightIndex = -1;
367
        touch();
368
        return;
369
    }
370
    else if (action->getTypeId() == Gui::SoSelectionElementAction::getClassTypeId()) {
371
        Gui::SoSelectionElementAction* selaction = static_cast<Gui::SoSelectionElementAction*>(action);
372

373
        switch(selaction->getType()) {
374
        case Gui::SoSelectionElementAction::None: {
375
            if(selaction->isSecondary()) {
376
                if(Gui::SoFCSelectionRoot::removeActionContext(action,this))
377
                    touch();
378
            }else {
379
                SelContextPtr ctx = Gui::SoFCSelectionRoot::getActionContext(action,this,selContext,false);
380
                if(ctx) {
381
                    ctx->selectionIndex.clear();
382
                    ctx->sl.clear();
383
                    touch();
384
                }
385
            }
386
            return;
387
        } case Gui::SoSelectionElementAction::All: {
388
            SelContextPtr ctx = Gui::SoFCSelectionRoot::getActionContext(action,this,selContext);
389
            selCounter.checkAction(selaction,ctx);
390
            ctx->selectionColor = selaction->getColor();
391
            ctx->selectionIndex.clear();
392
            ctx->selectionIndex.insert(-1); // all
393
            ctx->sl.clear();
394
            ctx->sl.push_back(-1);
395
            touch();
396
            return;
397
        } case Gui::SoSelectionElementAction::Append:
398
          case Gui::SoSelectionElementAction::Remove: {
399
            const SoDetail* detail = selaction->getElement();
400
            if (!detail || !detail->isOfType(SoLineDetail::getClassTypeId())) {
401
                if(selaction->isSecondary()) {
402
                    // For secondary context, a detail of different type means
403
                    // the user may want to partial render only other type of
404
                    // geometry. So we call below to obtain a action context.
405
                    // If no secondary context exist, it will create an empty
406
                    // one, and an empty secondary context inhibites drawing
407
                    // here.
408
                    auto ctx = Gui::SoFCSelectionRoot::getActionContext(action,this,selContext);
409
                    selCounter.checkAction(selaction,ctx);
410
                    touch();
411
                }
412
                return;
413
            }
414
            int index = static_cast<const SoLineDetail*>(detail)->getLineIndex();
415
            SelContextPtr ctx;
416
            if(selaction->getType() == Gui::SoSelectionElementAction::Append) {
417
                ctx = Gui::SoFCSelectionRoot::getActionContext(action,this,selContext);
418
                selCounter.checkAction(selaction,ctx);
419
                ctx->selectionColor = selaction->getColor();
420
                if(ctx->isSelectAll())
421
                    ctx->selectionIndex.clear();
422
                if(!ctx->selectionIndex.insert(index).second)
423
                    return;
424
            }else{
425
                ctx = Gui::SoFCSelectionRoot::getActionContext(action,this,selContext,false);
426
                if(!ctx || !ctx->removeIndex(index))
427
                    return;
428
            }
429
            ctx->sl.clear();
430
            if(!ctx->selectionIndex.empty()) {
431
                const int32_t* cindices = this->coordIndex.getValues(0);
432
                int numcindices = this->coordIndex.getNum();
433
                auto it = ctx->selectionIndex.begin();
434
                for(int section=0,i=0;i<numcindices;i++) {
435
                    if(section == *it)
436
                        ctx->sl.push_back(cindices[i]);
437
                    if(cindices[i] < 0) {
438
                        if(++section > *it) {
439
                            if(++it == ctx->selectionIndex.end())
440
                                break;
441
                        }
442
                    }
443
                }
444
            }
445
            touch();
446
            break;
447
        } default :
448
            break;
449
        }
450
        return;
451
    }
452

453
    inherited::doAction(action);
454
}
455

456
SoDetail * SoBrepEdgeSet::createLineSegmentDetail(SoRayPickAction * action,
457
                                                  const SoPrimitiveVertex * v1,
458
                                                  const SoPrimitiveVertex * v2,
459
                                                  SoPickedPoint * pp)
460
{
461
    SoDetail* detail = inherited::createLineSegmentDetail(action, v1, v2, pp);
462
    SoLineDetail* line_detail = static_cast<SoLineDetail*>(detail);
463
    int index = line_detail->getLineIndex();
464
    line_detail->setPartIndex(index);
465
    return detail;
466
}
467

468

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

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

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

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