FreeCAD

Форк
0
/
SoFCDB.cpp 
705 строк · 25.8 Кб
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
#ifndef _PreComp_
25
# include <Inventor/SbSphere.h>
26
# include <Inventor/SbString.h>
27
# include <Inventor/SoInteraction.h>
28
# include <Inventor/actions/SoGetBoundingBoxAction.h>
29
# include <Inventor/actions/SoToVRML2Action.h>
30
# include <Inventor/actions/SoWriteAction.h>
31
# include <Inventor/fields/SoMFNode.h>
32
# include <Inventor/fields/SoSFNode.h>
33
# include <Inventor/nodes/SoGroup.h>
34
# include <Inventor/VRMLnodes/SoVRMLGroup.h>
35
# include <Inventor/VRMLnodes/SoVRMLIndexedFaceSet.h>
36
# include <Inventor/VRMLnodes/SoVRMLNormal.h>
37
# include <Inventor/VRMLnodes/SoVRMLParent.h>
38
# include <Inventor/VRMLnodes/SoVRMLShape.h>
39
# include <QDir>
40
# include <QProcess>
41
# include <QTemporaryFile>
42
# include <sstream>
43
#endif
44

45
#include <Base/FileInfo.h>
46
#include <Base/Stream.h>
47
#include <Base/Tools.h>
48
#include <zipios++/gzipoutputstream.h>
49

50
#include "SoFCDB.h"
51
#include "Camera.h"
52
#include "Flag.h"
53
#include "GestureNavigationStyle.h"
54
#include "NavigationStyle.h"
55
#include "SelectionObject.h"
56
#include "SoAxisCrossKit.h"
57
#include "SoFCBackgroundGradient.h"
58
#include "SoFCBoundingBox.h"
59
#include "SoFCColorBar.h"
60
#include "SoFCColorGradient.h"
61
#include "SoFCColorLegend.h"
62
#include "SoFCCSysDragger.h"
63
#include "SoFCInteractiveElement.h"
64
#include "SoFCSelection.h"
65
#include "SoFCSelectionAction.h"
66
#include "SoFCUnifiedSelection.h"
67
#include "SoFCVectorizeSVGAction.h"
68
#include "SoFCVectorizeU3DAction.h"
69
#include "SoMouseWheelEvent.h"
70
#include "SoTextLabel.h"
71
#include "SoDatumLabel.h"
72
#include "Inventor/MarkerBitmaps.h"
73
#include "Inventor/SmSwitchboard.h"
74
#include "Inventor/SoAutoZoomTranslation.h"
75
#include "Inventor/SoDrawingGrid.h"
76
#include "propertyeditor/PropertyItem.h"
77

78

79
using namespace Gui;
80
using namespace Gui::Inventor;
81
using namespace Gui::PropertyEditor;
82

83
static SbBool init_done = false;
84
static SoGroup *storage = nullptr;
85

86
SbBool Gui::SoFCDB::isInitialized()
87
{
88
    return init_done;
89
}
90

91
void Gui::SoFCDB::init()
92
{
93
    SoInteraction                   ::init();
94
    SoGLRenderActionElement         ::initClass();
95
    SoFCInteractiveElement          ::initClass();
96
    SoGLWidgetElement               ::initClass();
97
    SoFCColorBarBase                ::initClass();
98
    SoFCColorBar                    ::initClass();
99
    SoFCColorLegend                 ::initClass();
100
    SoFCColorGradient               ::initClass();
101
    SoFCBackgroundGradient          ::initClass();
102
    SoFCBoundingBox                 ::initClass();
103
    SoFCSelection                   ::initClass();
104
    SoFCUnifiedSelection            ::initClass();
105
    SoFCHighlightAction             ::initClass();
106
    SoFCSelectionAction             ::initClass();
107
    SoFCDocumentAction              ::initClass();
108
    SoGLWidgetNode                  ::initClass();
109
    SoGLVBOActivatedElement         ::initClass();
110
    SoFCEnableSelectionAction       ::initClass();
111
    SoFCEnableHighlightAction       ::initClass();
112
    SoFCSelectionColorAction        ::initClass();
113
    SoFCHighlightColorAction        ::initClass();
114
    SoFCDocumentObjectAction        ::initClass();
115
    SoGLSelectAction                ::initClass();
116
    SoVisibleFaceAction             ::initClass();
117
    SoUpdateVBOAction               ::initClass();
118
    SoBoxSelectionRenderAction      ::initClass();
119
    SoFCVectorizeSVGAction          ::initClass();
120
    SoFCVectorizeU3DAction          ::initClass();
121
    SoHighlightElementAction        ::initClass();
122
    SoSelectionElementAction        ::initClass();
123
    SoVRMLAction                    ::initClass();
124
    SoSkipBoundingGroup             ::initClass();
125
    SoTextLabel                     ::initClass();
126
    SoDatumLabel                    ::initClass();
127
    SoColorBarLabel                 ::initClass();
128
    SoStringLabel                   ::initClass();
129
    SoFrameLabel                    ::initClass();
130
    TranslateManip                  ::initClass();
131
    SoShapeScale                    ::initClass();
132
    SoAxisCrossKit                  ::initClass();
133
    SoRegPoint                      ::initClass();
134
    SoDrawingGrid                   ::initClass();
135
    SoAutoZoomTranslation           ::initClass();
136
    MarkerBitmaps                   ::initClass();
137
    SoFCCSysDragger                 ::initClass();
138
    SmSwitchboard                   ::initClass();
139
    SoFCSeparator                   ::initClass();
140
    SoFCSelectionRoot               ::initClass();
141
    SoFCPathAnnotation              ::initClass();
142
    SoMouseWheelEvent               ::initClass();
143

144
    PropertyItem                    ::init();
145
    PropertySeparatorItem           ::init();
146
    PropertyStringItem              ::init();
147
    PropertyFontItem                ::init();
148
    PropertyIntegerItem             ::init();
149
    PropertyIntegerConstraintItem   ::init();
150
    PropertyFloatItem               ::init();
151
    PropertyUnitItem                ::init();
152
    PropertyFloatConstraintItem     ::init();
153
    PropertyPrecisionItem           ::init();
154
    PropertyUnitConstraintItem      ::init();
155
    PropertyAngleItem               ::init();
156
    PropertyBoolItem                ::init();
157
    PropertyVectorItem              ::init();
158
    PropertyVectorListItem          ::init();
159
    PropertyVectorDistanceItem      ::init();
160
    PropertyPositionItem            ::init();
161
    PropertyDirectionItem           ::init();
162
    PropertyMatrixItem              ::init();
163
    PropertyPlacementItem           ::init();
164
    PropertyRotationItem            ::init();
165
    PropertyEnumItem                ::init();
166
    PropertyStringListItem          ::init();
167
    PropertyFloatListItem           ::init();
168
    PropertyIntegerListItem         ::init();
169
    PropertyColorItem               ::init();
170
    PropertyMaterialItem            ::init();
171
    PropertyMaterialListItem        ::init();
172
    PropertyFileItem                ::init();
173
    PropertyPathItem                ::init();
174
    PropertyTransientFileItem       ::init();
175
    PropertyLinkItem                ::init();
176
    PropertyLinkListItem            ::init();
177

178
    NavigationStyle                 ::init();
179
    UserNavigationStyle             ::init();
180
    InventorNavigationStyle         ::init();
181
    CADNavigationStyle              ::init();
182
    RevitNavigationStyle            ::init();
183
    BlenderNavigationStyle          ::init();
184
    MayaGestureNavigationStyle      ::init();
185
    TouchpadNavigationStyle         ::init();
186
    GestureNavigationStyle          ::init();
187
    OpenCascadeNavigationStyle      ::init();
188
    OpenSCADNavigationStyle         ::init();
189
    TinkerCADNavigationStyle        ::init();
190

191
    GLGraphicsItem                  ::init();
192
    GLFlagWindow                    ::init();
193

194
    SelectionObject                 ::init();
195

196
    qRegisterMetaType<Base::Vector3f>("Base::Vector3f");
197
    qRegisterMetaType<Base::Vector3d>("Base::Vector3d");
198
    qRegisterMetaType<Base::Quantity>("Base::Quantity");
199
    qRegisterMetaType<QList<Base::Quantity> >("Base::QuantityList");
200
    init_done = true;
201

202
    assert(!storage);
203
    storage = new SoGroup();
204
    storage->ref();
205
}
206

207
void Gui::SoFCDB::finish()
208
{
209
    // Coin doesn't provide a mechanism to free static members of own data types.
210
    // Hence, we need to define a static method e.g. 'finish()' for all new types
211
    // to invoke the private member function 'atexit_cleanup()'.
212
    SoFCColorBarBase                ::finish();
213
    SoFCColorBar                    ::finish();
214
    SoFCColorLegend                 ::finish();
215
    SoFCColorGradient               ::finish();
216
    SoFCBackgroundGradient          ::finish();
217
    SoFCBoundingBox                 ::finish();
218
    SoFCSelection                   ::finish();
219
    SoFCHighlightAction             ::finish();
220
    SoFCSelectionAction             ::finish();
221
    SoFCDocumentAction              ::finish();
222
    SoFCDocumentObjectAction        ::finish();
223
    SoFCEnableSelectionAction       ::finish();
224
    SoFCEnableHighlightAction       ::finish();
225
    SoFCSelectionColorAction        ::finish();
226
    SoUpdateVBOAction               ::finish();
227
    SoFCHighlightColorAction        ::finish();
228
    SoFCSeparator                   ::finish();
229
    SoFCSelectionRoot               ::finish();
230
    SoFCPathAnnotation              ::finish();
231

232
    storage->unref();
233
    storage = nullptr;
234
}
235

236
// buffer acrobatics for inventor ****************************************************
237

238
namespace {
239
static std::vector<char> static_buffer;
240

241
static void *
242
buffer_realloc(void * /*bufptr*/, std::size_t size)
243
{
244
    static_buffer.resize(size);
245
    return static_buffer.data();
246
}
247
}
248

249
const std::string& Gui::SoFCDB::writeNodesToString(SoNode * root)
250
{
251
    SoOutput out;
252
    static_buffer.resize(1024);
253
    out.setBuffer(static_buffer.data(), static_buffer.size(), buffer_realloc);
254
    if (root && root->getTypeId().isDerivedFrom(SoVRMLParent::getClassTypeId()))
255
        out.setHeaderString("#VRML V2.0 utf8");
256

257
    SoWriteAction wa(&out);
258
    wa.apply(root);
259

260
    static std::string cReturnString;
261
    cReturnString = static_buffer.data();
262
    return cReturnString;
263
}
264

265
SoNode* replaceSwitches(SoNodeList* children, SoGroup* parent)
266
{
267
    if (!children) {
268
        return parent;
269
    }
270

271
    for (int i=0; i<children->getLength(); i++) {
272
        SoNode* node = (*children)[i];
273
        if (node->getTypeId().isDerivedFrom(SoGroup::getClassTypeId())) {
274
            if (node->getTypeId().isDerivedFrom(SoSwitch::getClassTypeId())) {
275
                auto group = static_cast<SoSwitch*>(node);
276
                int which = group->whichChild.getValue();
277
                if (which == SO_SWITCH_NONE)
278
                    continue;
279
                auto newParent = new SoGroup();
280
                SoNodeList c;
281
                if (which >= 0) {
282
                    c.append(group->getChild(which));
283
                }
284
                else {
285
                    // SO_SWITCH_INHERIT or SO_SWITCH_ALL
286
                    for (int i=0; i<group->getNumChildren(); i++)
287
                        c.append(group->getChild(i));
288
                }
289

290
                replaceSwitches(&c, newParent);
291
                parent->addChild(newParent);
292
            }
293
            else {
294
                auto newParent = static_cast<SoGroup*>(node->getTypeId().createInstance());
295
                replaceSwitches(node->getChildren(), newParent);
296
                parent->addChild(newParent);
297
            }
298
        }
299
        else {
300
            parent->addChild(node);
301
        }
302
    }
303

304
    return parent;
305
}
306

307
SoNode* replaceSwitchesInSceneGraph(SoNode* node)
308
{
309
    if (node->getTypeId().isDerivedFrom(SoGroup::getClassTypeId())) {
310
        return replaceSwitches(node->getChildren(), new SoSeparator);
311
    }
312

313
    return node;
314
}
315

316
SoNode* Gui::SoFCDB::replaceSwitches(SoNode* node)
317
{
318
    return replaceSwitchesInSceneGraph(node);
319
}
320

321
void Gui::SoFCDB::writeToVRML(SoNode* node, std::string& buffer)
322
{
323
    SoNode* noSwitches = replaceSwitchesInSceneGraph(node);
324
    noSwitches->ref();
325
    SoVRMLAction vrml2;
326
    vrml2.setOverrideMode(true);
327
    vrml2.apply(noSwitches);
328
    SoToVRML2Action tovrml2;
329
    tovrml2.apply(noSwitches);
330
    SoVRMLGroup* vrmlRoot = tovrml2.getVRML2SceneGraph();
331

332
    vrmlRoot->setInstancePrefix(SbString("o"));
333
    vrmlRoot->ref();
334
    buffer = SoFCDB::writeNodesToString(vrmlRoot);
335
    vrmlRoot->unref(); // release the memory as soon as possible
336

337
    // restore old settings
338
    vrml2.setOverrideMode(false);
339
    vrml2.apply(noSwitches);
340
    noSwitches->unref();
341
}
342

343
bool Gui::SoFCDB::writeToVRML(SoNode* node, const char* filename, bool binary)
344
{
345
    std::string buffer;
346
    writeToVRML(node, buffer);
347

348
    Base::FileInfo fi(filename);
349
    if (binary) {
350
        // We want to write compressed VRML but Coin 2.4.3 doesn't do it even though
351
        // SoOutput::getAvailableCompressionMethods() delivers a string list that
352
        // contains 'GZIP'. setCompression() was called directly after opening the file,
353
        // returned true and no error message appeared but anyway it didn't work.
354
        // Strange is that reading GZIPped VRML files works.
355
        // So, we do the compression on our own.
356
        Base::ofstream str(fi, std::ios::out | std::ios::binary);
357
        zipios::GZIPOutputStream gzip(str);
358

359
        if (gzip) {
360
            gzip << buffer;
361
            gzip.close();
362
            return true;
363
        }
364
    }
365
    else {
366
        Base::ofstream str(fi, std::ios::out);
367

368
        if (str) {
369
            str << buffer;
370
            str.close();
371
            return true;
372
        }
373
    }
374

375
    return false;
376
}
377

378
bool Gui::SoFCDB::writeToX3D(SoNode* node, const char* filename, bool binary)
379
{
380
    std::string buffer;
381
    writeToX3D(node, false, buffer);
382

383
    Base::FileInfo fi(filename);
384
    if (binary) {
385
        Base::ofstream str(fi, std::ios::out | std::ios::binary);
386
        zipios::GZIPOutputStream gzip(str);
387

388
        if (gzip) {
389
            gzip << buffer;
390
            gzip.close();
391
            return true;
392
        }
393
    }
394
    else {
395
        Base::ofstream str(fi, std::ios::out);
396

397
        if (str) {
398
            str << buffer;
399
            str.close();
400
            return true;
401
        }
402
    }
403

404
    return false;
405
}
406

407
bool Gui::SoFCDB::writeToX3D(SoNode* node, bool exportViewpoints, std::string& buffer)
408
{
409
    SoNode* noSwitches = replaceSwitchesInSceneGraph(node);
410
    noSwitches->ref();
411
    SoVRMLAction vrml2;
412
    vrml2.setOverrideMode(true);
413
    vrml2.apply(noSwitches);
414
    SoToVRML2Action tovrml2;
415
    tovrml2.apply(noSwitches);
416
    SoVRMLGroup* vrmlRoot = tovrml2.getVRML2SceneGraph();
417

418
    vrmlRoot->setInstancePrefix(SbString("o"));
419
    vrmlRoot->ref();
420

421
    // Search for SoVRMLIndexedFaceSet nodes and set creaseAngle to 0.5
422
    {
423
        SoSearchAction sa;
424
        sa.setType(SoVRMLShape::getClassTypeId());
425
        sa.setInterest(SoSearchAction::ALL);
426
        sa.setSearchingAll(true);
427
        sa.apply(vrmlRoot);
428
        SoPathList& paths = sa.getPaths();
429
        for (int i=0; i<paths.getLength(); i++) {
430
            SoPath* path = paths[i];
431
            auto shape = static_cast<SoVRMLShape*>(path->getTail());
432
            SoNode* geom = shape->geometry.getValue();
433
            if (geom && geom->getTypeId() == SoVRMLIndexedFaceSet::getClassTypeId()) {
434
                SoNode* norm = static_cast<SoVRMLIndexedFaceSet*>(geom)->normal.getValue();
435
                if (norm && norm->getTypeId() == SoVRMLNormal::getClassTypeId()) {
436
                    // if empty then nullify the normal field node
437
                    if (static_cast<SoVRMLNormal*>(norm)->vector.getNum() == 0)
438
                        static_cast<SoVRMLIndexedFaceSet*>(geom)->normal.setValue(nullptr);
439
                }
440
                else {
441
                    static_cast<SoVRMLIndexedFaceSet*>(geom)->creaseAngle.setValue(0.5f);
442
                }
443
            }
444
        }
445
        sa.reset(); // clear the internal cache
446
    }
447

448
    std::stringstream out;
449
    writeX3D(vrmlRoot, exportViewpoints, out);
450
    buffer = out.str();
451

452
    vrmlRoot->unref(); // release the memory as soon as possible
453

454
    // restore old settings
455
    vrml2.setOverrideMode(false);
456
    vrml2.apply(noSwitches);
457
    noSwitches->unref();
458

459
    return true;
460
}
461

462
void Gui::SoFCDB::writeX3DFields(SoNode* node, std::map<SoNode*, std::string>& nodeMap,
463
                                 bool isRoot, int& numDEF, int spaces, std::ostream& out)
464
{
465
    // remove the VRML prefix from the type name
466
    std::string type(node->getTypeId().getName().getString());
467
    type = type.substr(4);
468

469
    out << Base::blanks(spaces) << "<" << type;
470
    if (node->getRefCount() > 1 && !isRoot) {
471
        SbName name = node->getName();
472
        std::stringstream str;
473
        if (name.getLength() == 0)
474
            str << "o" << numDEF++;
475
        else
476
            str << name.getString();
477

478
        nodeMap[node] = str.str();
479
        out << " DEF=\"" << str.str() << "\"";
480
    }
481

482
    const SoFieldData* fielddata = node->getFieldData();
483
    if (fielddata) {
484
        int numFieldNodes = 0;
485

486
        // process non-SoSFNode and non-SoMFNode fields
487
        for (int i=0; i<fielddata->getNumFields(); i++) {
488
            SoField* field = fielddata->getField(node, i);
489
            if (!field->isDefault()) {
490
                if (!field->isOfType(SoSFNode::getClassTypeId()) &&
491
                    !field->isOfType(SoMFNode::getClassTypeId())) {
492
                    SbString value;
493
                    field->get(value);
494
                    QByteArray ba(value.getString(), value.getLength());
495
                    ba.replace('\n', ' ');
496
                    if (field->isOfType(SoMField::getClassTypeId())) {
497
                        ba.replace('[', ' ');
498
                        ba.replace(']', ' ');
499
                        ba = ba.simplified();
500
                    }
501

502
                    out << '\n' << Base::blanks(spaces+2) << fielddata->getFieldName(i).getString() << "=\"" << ba.data() << "\" ";
503
                }
504
                else {
505
                    numFieldNodes++;
506
                }
507
            }
508
        }
509

510
        if (numFieldNodes > 0) {
511
            out << ">\n";
512
        }
513
        else {
514
            out << "/>\n";
515
        }
516

517
        // process SoSFNode or SoMFNode fields
518
        for (int i=0; i<fielddata->getNumFields(); i++) {
519
            SoField* field = fielddata->getField(node, i);
520
            if (!field->isDefault()) {
521
                if (field->isOfType(SoSFNode::getClassTypeId())) {
522
                    auto sfNode = static_cast<SoSFNode*>(field);
523
                    writeX3DChild(sfNode->getValue(), nodeMap, numDEF, spaces+2, out);
524
                }
525
                else if (field->isOfType(SoMFNode::getClassTypeId())) {
526
                    auto mfNode = static_cast<SoMFNode*>(field);
527
                    for (int j=0; j<mfNode->getNum(); j++) {
528
                        writeX3DChild(mfNode->getNode(j), nodeMap, numDEF, spaces+2, out);
529
                    }
530
                }
531
            }
532
        }
533

534
        if (numFieldNodes > 0) {
535
            out << Base::blanks(spaces) << "</" << type << ">\n";
536
        }
537
    }
538
}
539

540
void Gui::SoFCDB::writeX3DChild(SoNode* node, std::map<SoNode*, std::string>& nodeMap,
541
                                int& numDEF, int spaces, std::ostream& out)
542
{
543
    if (!node)
544
        return;
545

546
    // check if the node is already used
547
    auto mapIt = nodeMap.find(node);
548
    if (mapIt == nodeMap.end()) {
549
        writeX3DFields(node, nodeMap, false, numDEF, spaces, out);
550
    }
551
    else {
552
        // remove the VRML prefix from the type name
553
        std::string sftype(node->getTypeId().getName().getString());
554
        sftype = sftype.substr(4);
555
        out << Base::blanks(spaces) << "<" << sftype << " USE=\"" << mapIt->second << "\" />\n";
556
    }
557
}
558

559
void Gui::SoFCDB::writeX3D(SoVRMLGroup* node, bool exportViewpoints, std::ostream& out)
560
{
561
    out << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
562
    out << "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n";
563
    out << "<X3D profile=\"Immersive\" version=\"3.2\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema-instance\" "
564
           "xsd:noNamespaceSchemaLocation=\"http://www.web3d.org/specifications/x3d-3.2.xsd\" width=\"1280px\"  height=\"1024px\">\n";
565
    out << "  <head>\n"
566
           "    <meta name=\"generator\" content=\"FreeCAD\"/>\n"
567
           "    <meta name=\"author\" content=\"\"/>\n"
568
           "    <meta name=\"company\" content=\"\"/>\n"
569
           "  </head>\n";
570

571
    std::map<SoNode*, std::string> nodeMap;
572
    out << "  <Scene>\n";
573

574
    // compute a sensible view point
575
    SoGetBoundingBoxAction bboxAction(SbViewportRegion(1280, 1024));
576
    bboxAction.apply(node);
577
    SbBox3f bbox = bboxAction.getBoundingBox();
578
    SbSphere bs;
579
    bs.circumscribe(bbox);
580
    const SbVec3f& cnt = bs.getCenter();
581
    float dist = 2.4f * bs.getRadius();
582
    float dist3 = 0.577350f * dist; // sqrt(1/3) * dist
583

584
    if (exportViewpoints) {
585
        auto viewpoint = [&out](const char* text, const SbVec3f& cnt,
586
                                const SbVec3f& pos, const SbRotation& rot) {
587
            SbVec3f axis; float angle;
588
            rot.getValue(axis, angle);
589
            out << "    <Viewpoint id=\"" << text
590
                << "\" centerOfRotation=\"" << cnt[0] << " " << cnt[1] << " " << cnt[2]
591
                << "\" position=\"" << pos[0] << " " << pos[1] << " " << pos[2]
592
                << "\" orientation=\"" << axis[0] << " " << axis[1] << " " << axis[2] << " " << angle
593
                << R"(" description="camera" fieldOfView="0.9">)"
594
                << "</Viewpoint>\n";
595
        };
596

597
        viewpoint("Iso", cnt, SbVec3f(cnt[0] + dist3, cnt[1] - dist3, cnt[2] + dist3), Camera::rotation(Camera::Isometric));
598
        viewpoint("Front", cnt, SbVec3f(cnt[0], cnt[1] - dist, cnt[2]), Camera::rotation(Camera::Front));
599
        viewpoint("Back", cnt, SbVec3f(cnt[0], cnt[1] + dist, cnt[2]), Camera::rotation(Camera::Rear));
600
        viewpoint("Right", cnt, SbVec3f(cnt[0] + dist, cnt[1], cnt[2]), Camera::rotation(Camera::Right));
601
        viewpoint("Left", cnt, SbVec3f(cnt[0] - dist, cnt[1], cnt[2]), Camera::rotation(Camera::Left));
602
        viewpoint("Top", cnt, SbVec3f(cnt[0], cnt[1], cnt[2] + dist), Camera::rotation(Camera::Top));
603
        viewpoint("Bottom", cnt, SbVec3f(cnt[0], cnt[1], cnt[2] - dist), Camera::rotation(Camera::Bottom));
604
    }
605

606
    int numDEF = 0;
607
    writeX3DFields(node, nodeMap, true, numDEF, 4, out);
608
    out << "  </Scene>\n";
609
    out << "</X3D>\n";
610
}
611

612
bool Gui::SoFCDB::writeToX3DOM(SoNode* node, std::string& buffer)
613
{
614
    std::string x3d;
615
    if (!writeToX3D(node, true, x3d))
616
        return false;
617

618
    // remove the first two lines from the x3d output as this duplicates
619
    // the xml and doctype header
620
    std::size_t pos = x3d.find('\n');
621
    pos = x3d.find('\n', pos + 1);
622
    x3d = x3d.erase(0, pos + 1);
623

624
    std::stringstream out;
625
    out << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
626
        << "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n";
627
    out << "<html xmlns='http://www.w3.org/1999/xhtml'>\n"
628
        << "  <head>\n"
629
        << "    <script type='text/javascript' src='http://www.x3dom.org/download/x3dom.js'> </script>\n"
630
        << "    <link rel='stylesheet' type='text/css' href='http://www.x3dom.org/download/x3dom.css'></link>\n"
631
        << "  </head>\n";
632

633
    auto onclick = [&out](const char* text) {
634
        out << "  <button onclick=\"document.getElementById('" << text << "').setAttribute('set_bind','true');\">" << text << "</button>\n";
635
    };
636

637
    onclick("Iso");
638
    onclick("Front");
639
    onclick("Back");
640
    onclick("Right");
641
    onclick("Left");
642
    onclick("Top");
643
    onclick("Bottom");
644

645
    out << x3d;
646

647
    out << "</html>\n";
648

649
    buffer = out.str();
650

651
    return true;
652
}
653

654
bool Gui::SoFCDB::writeToFile(SoNode* node, const char* filename, bool binary)
655
{
656
    bool ret = false;
657
    Base::FileInfo fi(filename);
658

659
    // Write VRML V2.0
660
    if (fi.hasExtension({"wrl", "vrml", "wrz"})) {
661
        // If 'wrz' is set then force compression
662
        if (fi.hasExtension("wrz"))
663
            binary = true;
664

665
        ret = SoFCDB::writeToVRML(node, filename, binary);
666
    }
667
    else if (fi.hasExtension({"x3d", "x3dz"})) {
668
        // If 'x3dz' is set then force compression
669
        if (fi.hasExtension("x3dz"))
670
            binary = true;
671

672
        ret = SoFCDB::writeToX3D(node, filename, binary);
673
    }
674
    else if (fi.hasExtension("xhtml")) {
675
        std::string buffer;
676
        if (SoFCDB::writeToX3DOM(node, buffer)) {
677
            Base::ofstream str(Base::FileInfo(filename), std::ios::out);
678

679
            if (str) {
680
                str << buffer;
681
                str.close();
682
                ret = true;
683
            }
684
        }
685
    }
686
    else if (fi.hasExtension("iv")) {
687
        // Write Inventor in ASCII
688
        std::string buffer = SoFCDB::writeNodesToString(node);
689
        Base::ofstream str(Base::FileInfo(filename), std::ios::out);
690

691
        if (str) {
692
            str << buffer;
693
            str.close();
694
            ret = true;
695
        }
696
    }
697

698
    return ret;
699
}
700

701
SoGroup* Gui::SoFCDB::getStorage()
702
{
703
  assert(storage); //call init first.
704
  return storage;
705
}
706

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

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

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

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