1
/***************************************************************************
2
* Copyright (c) 2011 Jürgen Riegel <juergen.riegel@web.de> *
4
* This file is part of the FreeCAD CAx development system. *
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. *
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. *
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 *
21
***************************************************************************/
24
#include "PreCompiled.h"
33
#include <boost/algorithm/string.hpp>
34
#include <boost/algorithm/string/predicate.hpp>
35
#include <boost/lexical_cast.hpp>
36
#include <boost/tokenizer.hpp>
51
constexpr float valueMinLegal {-1.0F};
52
constexpr float valueMaxLegal {1.0F};
55
: Rgb {1.0F, 1.0F, 1.0F}
58
ColorRGB::ColorRGB(float red, float green, float blue)
59
: Rgb {valueInRange(red), valueInRange(green), valueInRange(blue)}
62
float ColorRGB::valueInRange(float value)
64
return std::clamp(value, valueMinLegal, valueMaxLegal);
67
const char* DrawStyle::styleAsString() const
76
case Style::Invisible:
82
std::string DrawStyle::patternAsString() const
84
std::stringstream str;
85
str << "0x" << std::hex << linePattern;
89
const char* VertexOrdering::toString() const
92
case Ordering::UnknownOrdering:
93
return "UNKNOWN_ORDERING";
94
case Ordering::Clockwise:
96
case Ordering::CounterClockwise:
97
return "COUNTERCLOCKWISE";
99
return "UNKNOWN_ORDERING";
102
const char* ShapeType::toString() const
105
case Type::UnknownShapeType:
106
return "UNKNOWN_SHAPE_TYPE";
110
return "UNKNOWN_SHAPE_TYPE";
113
const char* BindingElement::bindingAsString() const
116
case Binding::PerPart:
118
case Binding::PerPartIndexed:
119
return "PER_PART_INDEXED";
120
case Binding::PerFace:
122
case Binding::PerFaceIndexed:
123
return "PER_FACE_INDEXED";
124
case Binding::PerVertex:
126
case Binding::PerVertexIndexed:
127
return "PER_VERTEX_INDEXED";
133
const char* PolygonOffset::styleAsString() const
146
// -----------------------------------------------------------------------------
148
InventorOutput::InventorOutput(std::ostream& result, Indentation& indent)
153
std::ostream& InventorOutput::stream()
158
std::ostream& InventorOutput::write()
164
std::ostream& InventorOutput::write(const char* str)
166
result << indent << str;
170
std::ostream& InventorOutput::write(const std::string& str)
172
result << indent << str;
176
std::ostream& InventorOutput::writeLine()
178
result << indent << '\n';
182
std::ostream& InventorOutput::writeLine(const char* str)
184
result << indent << str << '\n';
188
std::ostream& InventorOutput::writeLine(const std::string& str)
190
result << indent << str << '\n';
194
void InventorOutput::increaseIndent()
196
indent.increaseIndent();
199
void InventorOutput::decreaseIndent()
201
indent.decreaseIndent();
204
// -----------------------------------------------------------------------------
214
struct field_traits<float>
216
using field_type = float;
217
static std::ostream& write(std::ostream& out, const field_type& item)
225
struct field_traits<Vector3f>
227
using field_type = Vector3f;
228
static std::ostream& write(std::ostream& out, const field_type& item)
230
out << item.x << " " << item.y << " " << item.z;
236
struct field_traits<ColorRGB>
238
using field_type = ColorRGB;
239
static std::ostream& write(std::ostream& out, const field_type& item)
241
out << item.red() << " " << item.green() << " " << item.blue();
247
* Writes a field type to a stream.
248
* @author Werner Mayer
250
class InventorFieldWriter
254
void write(const char* fieldName, const std::vector<T>& fieldData, InventorOutput& out) const;
258
void InventorFieldWriter::write(const char* fieldName,
259
const std::vector<T>& fieldData,
260
InventorOutput& out) const
262
if (fieldData.empty()) {
266
if (fieldData.size() == 1) {
267
out.write() << fieldName << " ";
268
field_traits<T>::write(out.stream(), fieldData[0]) << '\n';
271
out.write() << fieldName << " [\n";
272
out.increaseIndent();
273
for (auto it : fieldData) {
275
field_traits<T>::write(out.stream(), it) << '\n';
277
out.decreaseIndent();
278
out.write() << "]\n";
283
void InventorFieldWriter::write<int>(const char* fieldName,
284
const std::vector<int>& fieldData,
285
InventorOutput& out) const
287
if (fieldData.empty()) {
291
out.write() << fieldName << " [\n";
292
out.increaseIndent();
293
std::size_t last_index {fieldData.size()};
294
std::size_t index {};
295
for (auto it : fieldData) {
296
if (index % 8 == 0) {
299
if (index < last_index) {
300
out.stream() << it << ", ";
303
out.stream() << it << " ] \n";
305
if (++index % 8 == 0) {
306
out.stream() << '\n';
309
out.decreaseIndent();
310
out.write() << "]\n";
314
// -----------------------------------------------------------------------------
316
LabelItem::LabelItem(std::string text)
317
: text(std::move(text))
320
void LabelItem::write(InventorOutput& out) const
322
out.write("Label {\n");
323
out.write() << " label \"" << text << "\"\n";
327
// -----------------------------------------------------------------------------
329
InfoItem::InfoItem(std::string text)
330
: text(std::move(text))
333
void InfoItem::write(InventorOutput& out) const
335
out.write("Info {\n");
336
out.write() << " string \"" << text << "\"\n";
340
// -----------------------------------------------------------------------------
342
BaseColorItem::BaseColorItem(const ColorRGB& rgb)
346
void BaseColorItem::write(InventorOutput& out) const
348
out.write("BaseColor {\n");
349
out.write() << " rgb " << rgb.red() << " " << rgb.green() << " " << rgb.blue() << '\n';
353
// -----------------------------------------------------------------------------
355
PointItem::PointItem(const Base::Vector3f& point, DrawStyle drawStyle, const ColorRGB& rgb)
357
, drawStyle(drawStyle)
361
void PointItem::write(InventorOutput& out) const
363
out.write() << "Separator { \n";
364
out.write() << " Material { \n";
365
out.write() << " diffuseColor " << rgb.red() << " " << rgb.green() << " " << rgb.blue()
367
out.write() << " }\n";
368
out.write() << " MaterialBinding { value PER_PART }\n";
369
out.write() << " DrawStyle { pointSize " << drawStyle.pointSize << "}\n";
370
out.write() << " Coordinate3 {\n";
371
out.write() << " point [ " << point.x << " " << point.y << " " << point.z << "]\n";
372
out.write() << " }\n";
373
out.write() << " PointSet { }\n";
374
out.write() << "}\n";
377
// -----------------------------------------------------------------------------
379
LineItem::LineItem(const Base::Line3f& line, DrawStyle drawStyle, const ColorRGB& rgb)
381
, drawStyle(drawStyle)
385
void LineItem::write(InventorOutput& out) const
387
std::string pattern = drawStyle.patternAsString();
389
out.write(" Separator { \n");
390
out.write() << " Material { diffuseColor " << rgb.red() << " " << rgb.green() << " "
391
<< rgb.blue() << "} \n";
392
out.write() << " DrawStyle { lineWidth " << drawStyle.lineWidth << " linePattern " << pattern
394
out.write() << " Coordinate3 { \n";
395
out.write() << " point [ ";
396
out.write() << line.p1.x << " " << line.p1.y << " " << line.p1.z << ",";
397
out.write() << line.p2.x << " " << line.p2.y << " " << line.p2.z;
398
out.write() << " ] \n";
399
out.write() << " } \n";
400
out.write() << " LineSet { } \n";
401
out.write() << " } \n";
404
// -----------------------------------------------------------------------------
406
MultiLineItem::MultiLineItem(std::vector<Vector3f> points, DrawStyle drawStyle, const ColorRGB& rgb)
407
: points {std::move(points)}
408
, drawStyle {drawStyle}
412
void MultiLineItem::write(InventorOutput& out) const
414
std::string pattern = drawStyle.patternAsString();
416
out.write() << "Separator {\n";
417
out.write() << " Material { diffuseColor " << rgb.red() << " " << rgb.green() << " "
418
<< rgb.blue() << "}\n";
419
out.write() << " DrawStyle { lineWidth " << drawStyle.lineWidth << " linePattern " << pattern
421
out.write() << " Coordinate3 {\n";
423
InventorFieldWriter writer;
424
writer.write<Vector3f>("point", points, out);
426
out.write() << " }\n";
427
out.write() << " LineSet {\n";
428
out.write() << " numVertices [ -1 ]\n";
429
out.write() << " }\n";
430
out.write() << "}\n";
433
// -----------------------------------------------------------------------------
435
ArrowItem::ArrowItem(const Base::Line3f& line, DrawStyle drawStyle, const ColorRGB& rgb)
437
, drawStyle(drawStyle)
441
void ArrowItem::write(InventorOutput& out) const
443
float length = line.Length();
444
float coneLength = length / 10.0F;
445
float coneRadius = coneLength / 2.0F;
446
float sf1 = length - coneLength;
447
float sf2 = length - coneLength / 2.0F;
449
Vector3f dir = line.GetDirection();
451
dir.Scale(sf1, sf1, sf1);
452
Vector3f pt2s = line.p1 + dir;
454
dir.Scale(sf2, sf2, sf2);
455
Vector3f cpt = line.p1 + dir;
457
Vector3f rot = Vector3f(0.0F, 1.0F, 0.0F) % dir;
459
float angle = Vector3f(0.0F, 1.0F, 0.0F).GetAngle(dir);
461
out.write() << "Separator {\n";
462
out.write() << " Material { diffuseColor " << rgb.red() << " " << rgb.green() << " "
463
<< rgb.blue() << "}\n";
464
out.write() << " DrawStyle { lineWidth " << drawStyle.lineWidth << " }\n";
465
out.write() << " Coordinate3 {\n";
466
out.write() << " point [ ";
467
out.write() << line.p1.x << " " << line.p1.y << " " << line.p1.z << ", ";
468
out.write() << pt2s.x << " " << pt2s.y << " " << pt2s.z;
469
out.write() << " ]\n";
470
out.write() << " }\n";
471
out.write() << " LineSet { }\n";
472
out.write() << " Transform { \n";
473
out.write() << " translation " << cpt.x << " " << cpt.y << " " << cpt.z << '\n';
474
out.write() << " rotation " << rot.x << " " << rot.y << " " << rot.z << " " << angle << '\n';
475
out.write() << " }\n";
476
out.write() << " Cone { bottomRadius " << coneRadius << " height " << coneLength << "} \n";
477
out.write() << "}\n";
480
// -----------------------------------------------------------------------------
482
BoundingBoxItem::BoundingBoxItem(const Vector3f& pt1,
488
, drawStyle {drawStyle}
492
void BoundingBoxItem::write(InventorOutput& out) const
494
std::vector<Base::Vector3f> points(8);
495
points[0].Set(pt1.x, pt1.y, pt1.z);
496
points[1].Set(pt1.x, pt1.y, pt2.z);
497
points[2].Set(pt1.x, pt2.y, pt1.z);
498
points[3].Set(pt1.x, pt2.y, pt2.z);
499
points[4].Set(pt2.x, pt1.y, pt1.z);
500
points[5].Set(pt2.x, pt1.y, pt2.z);
501
points[6].Set(pt2.x, pt2.y, pt1.z);
502
points[7].Set(pt2.x, pt2.y, pt2.z);
504
std::vector<int> lineset = {0, 2, 6, 4, 0, -1, 1, 5, 7, 3, 1, -1, 7, 6, 2,
505
3, 7, -1, 3, 2, 0, 1, 3, -1, 5, 1, 0, 4, 5, -1};
507
out.write() << "Separator {\n";
508
out.write() << " Material { diffuseColor " << rgb.red() << " " << rgb.green() << " "
509
<< rgb.blue() << "}\n";
510
out.write() << " DrawStyle { lineWidth " << drawStyle.lineWidth << "}\n";
512
Coordinate3Item coords {points};
513
out.increaseIndent();
515
out.decreaseIndent();
517
IndexedLineSetItem indexed {lineset};
518
out.increaseIndent();
520
out.decreaseIndent();
522
out.write() << "}\n";
525
// -----------------------------------------------------------------------------
527
void MaterialItem::setAmbientColor(const std::vector<ColorRGB>& rgb)
532
void MaterialItem::setDiffuseColor(const std::vector<ColorRGB>& rgb)
537
void MaterialItem::setSpecularColor(const std::vector<ColorRGB>& rgb)
542
void MaterialItem::setEmissiveColor(const std::vector<ColorRGB>& rgb)
547
void MaterialItem::setShininess(const std::vector<float>& value)
552
void MaterialItem::setTransparency(const std::vector<float>& value)
554
transparency = value;
557
void MaterialItem::write(InventorOutput& out) const
560
writeAmbientColor(out);
561
writeDiffuseColor(out);
562
writeSpecularColor(out);
563
writeEmissiveColor(out);
565
writeTransparency(out);
569
void MaterialItem::beginMaterial(InventorOutput& out) const
571
out.writeLine("Material {");
572
out.increaseIndent();
575
void MaterialItem::endMaterial(InventorOutput& out) const
577
out.decreaseIndent();
581
void MaterialItem::writeAmbientColor(InventorOutput& out) const
583
InventorFieldWriter writer;
584
writer.write<ColorRGB>("ambientColor", ambientColor, out);
587
void MaterialItem::writeDiffuseColor(InventorOutput& out) const
589
InventorFieldWriter writer;
590
writer.write<ColorRGB>("diffuseColor", diffuseColor, out);
593
void MaterialItem::writeSpecularColor(InventorOutput& out) const
595
InventorFieldWriter writer;
596
writer.write<ColorRGB>("specularColor", specularColor, out);
599
void MaterialItem::writeEmissiveColor(InventorOutput& out) const
601
InventorFieldWriter writer;
602
writer.write<ColorRGB>("emissiveColor", emissiveColor, out);
605
void MaterialItem::writeShininess(InventorOutput& out) const
607
InventorFieldWriter writer;
608
writer.write<float>("shininess", shininess, out);
611
void MaterialItem::writeTransparency(InventorOutput& out) const
613
InventorFieldWriter writer;
614
writer.write<float>("transparency", transparency, out);
617
// -----------------------------------------------------------------------------
619
MaterialBindingItem::MaterialBindingItem(BindingElement::Binding bind)
624
void MaterialBindingItem::setValue(BindingElement::Binding bind)
629
void MaterialBindingItem::write(InventorOutput& out) const
631
out.write() << "MaterialBinding { value " << value.bindingAsString() << " } \n";
634
// -----------------------------------------------------------------------------
636
DrawStyleItem::DrawStyleItem(DrawStyle value)
640
void DrawStyleItem::setValue(DrawStyle value)
645
void DrawStyleItem::write(InventorOutput& out) const
647
out.write() << "DrawStyle {\n";
648
out.write() << " style " << style.styleAsString() << '\n';
649
out.write() << " pointSize " << style.pointSize << '\n';
650
out.write() << " lineWidth " << style.lineWidth << '\n';
651
out.write() << " linePattern " << style.patternAsString() << '\n';
652
out.write() << "}\n";
655
// -----------------------------------------------------------------------------
657
ShapeHintsItem::ShapeHintsItem(float creaseAngle)
658
: creaseAngle(creaseAngle)
661
void ShapeHintsItem::setVertexOrdering(VertexOrdering::Ordering value)
663
vertexOrdering.ordering = value;
666
void ShapeHintsItem::setShapeType(ShapeType::Type value)
668
shapeType.type = value;
671
void ShapeHintsItem::write(InventorOutput& out) const
673
out.write() << "ShapeHints {\n";
674
out.write() << " creaseAngle " << creaseAngle << '\n';
675
out.write() << " vertexOrdering " << vertexOrdering.toString() << '\n';
676
out.write() << " shapeType " << shapeType.toString() << '\n';
677
out.write() << "}\n";
680
// -----------------------------------------------------------------------------
682
void PolygonOffsetItem::setValue(PolygonOffset value)
687
void PolygonOffsetItem::write(InventorOutput& out) const
689
out.write() << "PolygonOffset {\n";
690
out.write() << " factor " << offset.factor << '\n';
691
out.write() << " units " << offset.units << '\n';
692
out.write() << " styles " << offset.styleAsString() << '\n';
693
out.write() << " on " << (offset.on ? "TRUE" : "FALSE") << '\n';
694
out.write() << "}\n";
697
// -----------------------------------------------------------------------------
699
Coordinate3Item::Coordinate3Item(std::vector<Vector3f> points)
700
: points(std::move(points))
703
void Coordinate3Item::write(InventorOutput& out) const
706
InventorFieldWriter writer;
707
writer.write<Vector3f>("point", points, out);
711
void Coordinate3Item::beginPoint(InventorOutput& out) const
713
out.writeLine("Coordinate3 {");
714
out.increaseIndent();
717
void Coordinate3Item::endPoint(InventorOutput& out) const
719
out.decreaseIndent();
723
// -----------------------------------------------------------------------------
725
void PointSetItem::write(InventorOutput& out) const
727
out.writeLine("PointSet { }");
730
// -----------------------------------------------------------------------------
732
void LineSetItem::write(InventorOutput& out) const
734
out.writeLine("LineSet { }");
737
// -----------------------------------------------------------------------------
739
FaceSetItem::FaceSetItem(std::vector<int> indices)
740
: indices(std::move(indices))
743
void FaceSetItem::write(InventorOutput& out) const
745
out.write() << "FaceSet {\n";
746
out.increaseIndent();
747
InventorFieldWriter writer;
748
writer.write<int>("numVertices", indices, out);
749
out.decreaseIndent();
750
out.write() << "}\n";
753
// -----------------------------------------------------------------------------
755
IndexedLineSetItem::IndexedLineSetItem(std::vector<int> indices)
756
: indices(std::move(indices))
759
void IndexedLineSetItem::write(InventorOutput& out) const
761
out.write() << "IndexedLineSet {\n";
762
out.increaseIndent();
763
InventorFieldWriter writer;
764
writer.write<int>("coordIndex", indices, out);
765
out.decreaseIndent();
766
out.write() << "}\n";
769
// -----------------------------------------------------------------------------
771
IndexedFaceSetItem::IndexedFaceSetItem(std::vector<int> indices)
772
: indices(std::move(indices))
775
void IndexedFaceSetItem::write(InventorOutput& out) const
777
out.write() << "IndexedFaceSet {\n";
778
out.increaseIndent();
779
InventorFieldWriter writer;
780
writer.write<int>("coordIndex", indices, out);
781
out.decreaseIndent();
782
out.write() << "}\n";
785
// -----------------------------------------------------------------------------
787
NormalItem::NormalItem(std::vector<Base::Vector3f> vec)
788
: vector(std::move(vec))
791
void NormalItem::write(InventorOutput& out) const
794
InventorFieldWriter writer;
795
writer.write<Vector3f>("vector", vector, out);
799
void NormalItem::beginNormal(InventorOutput& out) const
801
out.writeLine("Normal {");
802
out.increaseIndent();
805
void NormalItem::endNormal(InventorOutput& out) const
807
out.decreaseIndent();
811
// -----------------------------------------------------------------------------
813
void NormalBindingItem::setValue(BindingElement::Binding bind)
818
void NormalBindingItem::write(InventorOutput& out) const
820
out.write() << "NormalBinding { value " << value.bindingAsString() << " }\n";
823
// -----------------------------------------------------------------------------
825
void CylinderItem::setRadius(float value)
830
void CylinderItem::setHeight(float value)
835
void CylinderItem::write(InventorOutput& out) const
837
out.write() << "Cylinder {\n";
838
out.write() << " radius " << radius << "\n";
839
out.write() << " height " << height << "\n";
840
out.write() << " parts (SIDES | TOP | BOTTOM)\n";
841
out.write() << "}\n";
844
// -----------------------------------------------------------------------------
846
void ConeItem::setBottomRadius(float value)
848
bottomRadius = value;
851
void ConeItem::setHeight(float value)
856
void ConeItem::write(InventorOutput& out) const
858
out.write() << "Cone { bottomRadius " << bottomRadius << " height " << height << " }\n";
861
// -----------------------------------------------------------------------------
863
void SphereItem::setRadius(float value)
868
void SphereItem::write(InventorOutput& out) const
870
out.write() << "Sphere { radius " << radius << " }\n";
873
// -----------------------------------------------------------------------------
875
void NurbsSurfaceItem::setControlPoints(int numU, int numV)
877
numUControlPoints = numU;
878
numVControlPoints = numV;
881
void NurbsSurfaceItem::setKnotVector(const std::vector<float>& uKnots,
882
const std::vector<float>& vKnots)
884
uKnotVector = uKnots;
885
vKnotVector = vKnots;
888
void NurbsSurfaceItem::write(InventorOutput& out) const
890
out.write() << "NurbsSurface {\n";
891
out.write() << " numUControlPoints " << numUControlPoints << '\n';
892
out.write() << " numVControlPoints " << numVControlPoints << '\n';
893
out.increaseIndent();
894
InventorFieldWriter writer;
895
writer.write<float>("uKnotVector", uKnotVector, out);
896
writer.write<float>("vKnotVector", vKnotVector, out);
897
out.decreaseIndent();
898
out.write() << "}\n";
901
// -----------------------------------------------------------------------------
903
Text2Item::Text2Item(std::string string)
904
: string(std::move(string))
907
void Text2Item::write(InventorOutput& out) const
909
out.write() << "Text2 { string \"" << string << "\" "
913
// -----------------------------------------------------------------------------
916
TransformItem::TransformItem(const Base::Placement& placement)
917
: placement(placement)
920
TransformItem::TransformItem(const Matrix4D& transform)
922
placement.fromMatrix(transform);
925
void TransformItem::write(InventorOutput& out) const
927
Base::Vector3d translation = placement.getPosition();
928
Base::Vector3d rotationaxis;
930
placement.getRotation().getValue(rotationaxis, angle);
932
out.write() << "Transform {\n";
933
out.write() << " translation " << translation.x << " " << translation.y << " " << translation.z
935
out.write() << " rotation " << rotationaxis.x << " " << rotationaxis.y << " " << rotationaxis.z
936
<< " " << angle << '\n';
937
out.write() << "}" << '\n';
940
// -----------------------------------------------------------------------------
942
InventorBuilder::InventorBuilder(std::ostream& str)
948
InventorBuilder::~InventorBuilder() = default;
950
void InventorBuilder::addHeader()
952
result << "#Inventor V2.1 ascii \n\n";
955
void InventorBuilder::increaseIndent()
957
indent.increaseIndent();
960
void InventorBuilder::decreaseIndent()
962
indent.decreaseIndent();
965
void InventorBuilder::addNode(const NodeItem& node)
967
InventorOutput out(result, indent);
971
void InventorBuilder::beginSeparator()
973
result << indent << "Separator { \n";
977
void InventorBuilder::endSeparator()
980
result << indent << "}\n";
983
// -----------------------------------------------------------------------------
987
* A more elaborate description of the constructor.
989
Builder3D::Builder3D()
996
* A more elaborate description of the destructor.
998
Builder3D::~Builder3D() = default;
1000
void Builder3D::clear()
1002
// under gcc stringstream::str() returns a copy not a reference
1003
#if defined(_MSC_VER)
1004
result.str().clear();
1010
* Save the resulting inventor 3D representation to the Console().Log() facility.
1011
* In DEBUG mode the Gui (if running) will trigger on that and show the representation in
1012
* the active Viewer/Document. It shows only one representation on time. If you need to
1013
* show more then one representation use saveToFile() instead.
1016
void Builder3D::saveToLog()
1018
ILogger* obs = Base::Console().Get("StatusBar");
1020
obs->SendLog("Builder3D",
1022
Base::LogStyle::Log,
1023
Base::IntendedRecipient::Developer,
1024
Base::ContentType::Untranslatable);
1029
* Save the resulting inventor 3D representation to a file. Ending should be *.iv.
1030
* That enables you to show the result in a Inventor Viewer or in FreeCAD by:
1032
* Gui.document().addAnnotation("Debug","MyFile.iv")
1036
void Builder3D::saveToFile(const char* FileName)
1038
Base::FileInfo fi(FileName);
1039
Base::ofstream file(fi);
1041
throw FileException("Cannot open file");
1044
file << result.str();
1047
void Builder3D::addNode(const NodeItem& item)
1049
builder.addNode(item);
1052
void Builder3D::beginSeparator()
1054
builder.beginSeparator();
1057
void Builder3D::endSeparator()
1059
builder.endSeparator();
1062
// -----------------------------------------------------------------------------
1065
std::vector<T> InventorLoader::readData(const char* fieldName) const
1067
std::vector<T> fieldValues;
1070
// search for 'fieldName' and '['
1072
while (std::getline(inp, str)) {
1073
std::string::size_type point = str.find(fieldName);
1074
std::string::size_type open = str.find('[');
1075
if (point != std::string::npos && open > point) {
1076
str = str.substr(open);
1087
boost::char_separator<char> sep(" ,");
1088
boost::tokenizer<boost::char_separator<char>> tokens(str, sep);
1089
std::vector<std::string> token_results;
1090
token_results.assign(tokens.begin(), tokens.end());
1092
for (const auto& it : token_results) {
1094
T value = boost::lexical_cast<T>(it);
1095
fieldValues.emplace_back(value);
1097
catch (const boost::bad_lexical_cast&) {
1101
// search for ']' to finish the reading
1102
if (str.find(']') != std::string::npos) {
1105
} while (std::getline(inp, str));
1110
std::vector<Vector3f> InventorLoader::convert(const std::vector<float>& data) const
1112
if (data.size() % 3 != 0) {
1113
throw std::string("Reading failed");
1116
std::size_t len = data.size() / 3;
1117
std::vector<Vector3f> points;
1118
points.reserve(len);
1120
for (std::size_t i = 0; i < len; i++) {
1121
float x = data[3 * i];
1122
float y = data[3 * i + 1];
1123
float z = data[3 * i + 2];
1124
points.emplace_back(x, y, z);
1130
std::vector<InventorLoader::Face> InventorLoader::convert(const std::vector<int32_t>& data) const
1132
std::vector<Face> faces;
1133
faces.reserve(data.size());
1134
int32_t coordIndex = 0;
1135
for (const auto it : data) {
1137
faces.emplace_back(coordIndex, coordIndex + 1, coordIndex + 2);
1140
faces.emplace_back(coordIndex, coordIndex + 1, coordIndex + 2);
1141
faces.emplace_back(coordIndex, coordIndex + 2, coordIndex + 3);
1148
std::vector<std::vector<int32_t>> InventorLoader::split(const std::vector<int32_t>& data)
1150
std::vector<std::vector<int32_t>> splitdata;
1151
std::vector<int32_t>::const_iterator begin = data.cbegin();
1152
std::vector<int32_t>::const_iterator it = begin;
1154
while ((it = std::find(begin, data.cend(), -1)) != data.cend()) {
1155
splitdata.emplace_back(begin, it);
1157
std::advance(begin, 1);
1162
std::vector<InventorLoader::Face>
1163
InventorLoader::convert(const std::vector<std::vector<int32_t>>& coordIndex) const
1165
std::vector<Face> faces;
1166
faces.reserve(coordIndex.size());
1167
for (const auto& it : coordIndex) {
1168
if (it.size() == 3) {
1169
faces.emplace_back(it[0], it[1], it[2]);
1171
else if (it.size() == 4) {
1172
faces.emplace_back(it[0], it[1], it[2]);
1173
faces.emplace_back(it[0], it[2], it[3]);
1179
void InventorLoader::readNormals()
1181
auto data = readData<float>("vector");
1182
vector = convert(data);
1185
void InventorLoader::readCoords()
1187
auto data = readData<float>("point");
1188
points = convert(data);
1191
void InventorLoader::readIndexedFaceSet()
1193
auto data = readData<int32_t>("coordIndex");
1194
faces = convert(split(data));
1197
void InventorLoader::readFaceSet()
1199
auto data = readData<int32_t>("numVertices");
1200
faces = convert(data);
1201
isnonindexed = true;
1204
bool InventorLoader::read()
1206
if (!inp || inp.bad()) {
1212
// Verify it's an Inventor 2.1 file
1213
std::getline(inp, line);
1214
if (line.find("#Inventor V2.1 ascii") == std::string::npos) {
1218
while (std::getline(inp, line)) {
1219
// read the normals if they are defined
1220
if (line.find("Normal {") != std::string::npos) {
1223
else if (line.find("Coordinate3 {") != std::string::npos) {
1226
else if (line.find("IndexedFaceSet {") != std::string::npos) {
1227
readIndexedFaceSet();
1230
else if (line.find("FaceSet {") != std::string::npos) {
1238
bool InventorLoader::isValid() const
1240
int32_t value {static_cast<int32_t>(points.size())};
1241
auto inRange = [value](const Face& face) {
1242
if (face.p1 < 0 || face.p1 >= value) {
1245
if (face.p2 < 0 || face.p2 >= value) {
1248
if (face.p3 < 0 || face.p3 >= value) {
1254
return std::all_of(faces.cbegin(), faces.cend(), [&inRange](const Face& face) {
1255
return inRange(face);
1261
BaseExport Vector3f to_vector(std::string str)
1263
std::string_view view = str;
1264
if (!boost::starts_with(view, "(") || !boost::ends_with(str, ")")) {
1265
throw std::runtime_error("string is not a tuple");
1268
view.remove_prefix(1);
1269
view.remove_suffix(1);
1273
boost::char_separator<char> sep(" ,");
1274
boost::tokenizer<boost::char_separator<char>> tokens(str, sep);
1275
std::vector<std::string> token_results;
1276
token_results.assign(tokens.begin(), tokens.end());
1278
if (token_results.size() != 3) {
1279
throw std::runtime_error("not a tuple of three floats");
1283
vec.x = boost::lexical_cast<float>(token_results.at(0));
1284
vec.y = boost::lexical_cast<float>(token_results.at(1));
1285
vec.z = boost::lexical_cast<float>(token_results.at(2));