Base: refactor InventorBuilder and add more unit tests

This commit is contained in:
wmayer
2022-12-02 18:53:47 +01:00
parent f6cf0e7f3d
commit 663a9e665b
3 changed files with 375 additions and 10 deletions

View File

@@ -89,7 +89,7 @@ std::string DrawStyle::patternAsString() const
return str.str();
}
const char* MaterialBinding::bindingAsString() const
const char* BindingElement::bindingAsString() const
{
switch (value) {
case Binding::PerPart:
@@ -178,6 +178,25 @@ void InventorOutput::decreaseIndent()
// -----------------------------------------------------------------------------
void NodeItem::writeField(const char* field, const std::vector<Vector3f>& vec, InventorOutput& out) const
{
if (vec.empty())
return;
if (vec.size() == 1) {
out.write() << field << " " << vec[0].x << " " << vec[0].y << " " << vec[0].z << '\n';
}
else {
out.write() << field << " [\n";
out.increaseIndent();
for (auto it : vec) {
out.write() << it.x << " " << it.y << " " << it.z << '\n';
}
out.decreaseIndent();
out.write() << "]\n";
}
}
void NodeItem::writeField(const char* field, const std::vector<ColorRGB>& rgb, InventorOutput& out) const
{
if (rgb.empty())
@@ -312,6 +331,56 @@ void LineItem::write(InventorOutput& out) const
// -----------------------------------------------------------------------------
ArrowItem::ArrowItem(const Base::Line3f& line, DrawStyle drawStyle, const ColorRGB& rgb)
: line(line)
, drawStyle(drawStyle)
, rgb(rgb)
{
}
void ArrowItem::write(InventorOutput& out) const
{
float length = line.Length();
float coneLength = length / 10.0F;
float coneRadius = coneLength / 2.0F;
float sf1 = length - coneLength;
float sf2 = length - coneLength/2.0F;
Vector3f dir = line.GetDirection();
dir.Normalize();
dir.Scale(sf1, sf1, sf1);
Vector3f pt2s = line.p1 + dir;
dir.Normalize();
dir.Scale(sf2, sf2, sf2);
Vector3f cpt = line.p1 + dir;
Vector3f rot = Vector3f(0.0f, 1.0f, 0.0f) % dir;
rot.Normalize();
float angle = Vector3f(0.0f, 1.0f, 0.0f).GetAngle(dir);
out.write() << "Separator {\n";
out.write() << " Material { diffuseColor " << rgb.red() << " "<< rgb.green() << " "<< rgb.blue() << "}\n";
out.write() << " DrawStyle { lineWidth " << drawStyle.lineWidth << " }\n";
out.write() << " Coordinate3 {\n";
out.write() << " point [ ";
out.write() << line.p1.x << " " << line.p1.y << " " << line.p1.z << ", ";
out.write() << pt2s.x << " " << pt2s.y << " " << pt2s.z;
out.write() << " ]\n";
out.write() << " }\n";
out.write() << " LineSet { }\n";
out.write() << " Transform { \n";
out.write() << " translation "
<< cpt.x << " " << cpt.y << " " << cpt.z << '\n';
out.write() << " rotation "
<< rot.x << " " << rot.y << " " << rot.z << " " << angle << '\n';
out.write() << " }\n";
out.write() << " Cone { bottomRadius " << coneRadius << " height " << coneLength << "} \n";
out.write() << "}\n";
}
// -----------------------------------------------------------------------------
void MaterialItem::setAmbientColor(const std::vector<ColorRGB>& rgb)
{
ambientColor = rgb;
@@ -398,15 +467,15 @@ void MaterialItem::writeTransparency(InventorOutput& out) const
// -----------------------------------------------------------------------------
MaterialBindingItem::MaterialBindingItem(MaterialBinding bind) : bind(bind)
void MaterialBindingItem::setValue(BindingElement::Binding bind)
{
value.value = bind;
}
void MaterialBindingItem::write(InventorOutput& out) const
{
out.write() << "MaterialBinding { value "
<< bind.bindingAsString() << " } \n";
<< value.bindingAsString() << " } \n";
}
// -----------------------------------------------------------------------------
@@ -466,6 +535,95 @@ void PointSetItem::write(InventorOutput& out) const
// -----------------------------------------------------------------------------
void NormalItem::setVector(const std::vector<Base::Vector3f>& vec)
{
vector = vec;
}
void NormalItem::write(InventorOutput& out) const
{
beginNormal(out);
writeField("vector", vector, out);
endNormal(out);
}
void NormalItem::beginNormal(InventorOutput& out) const
{
out.writeLine("Normal {");
out.increaseIndent();
}
void NormalItem::endNormal(InventorOutput& out) const
{
out.decreaseIndent();
out.writeLine("}");
}
// -----------------------------------------------------------------------------
void NormalBindingItem::setValue(BindingElement::Binding bind)
{
value.value = bind;
}
void NormalBindingItem::write(InventorOutput& out) const
{
out.write() << "NormalBinding { value "
<< value.bindingAsString() << " }\n";
}
// -----------------------------------------------------------------------------
void CylinderItem::setRadius(float value)
{
radius = value;
}
void CylinderItem::setHeight(float value)
{
height = value;
}
void CylinderItem::write(InventorOutput& out) const
{
out.write() << "Cylinder {\n";
out.write() << " radius " << radius << "\n";
out.write() << " height " << height << "\n";
out.write() << " parts (SIDES | TOP | BOTTOM)\n";
out.write() << "}\n";
}
// -----------------------------------------------------------------------------
void ConeItem::setBottomRadius(float value)
{
bottomRadius = value;
}
void ConeItem::setHeight(float value)
{
height = value;
}
void ConeItem::write(InventorOutput& out) const
{
out.write() << "Cone { bottomRadius " << bottomRadius << " height " << height << " }\n";
}
// -----------------------------------------------------------------------------
void SphereItem::setRadius(float value)
{
radius = value;
}
void SphereItem::write(InventorOutput& out) const
{
out.write() << "Sphere { radius " << radius << " }\n";
}
// -----------------------------------------------------------------------------
InventorBuilder::InventorBuilder(std::ostream& output)
: result(output)
{
@@ -557,7 +715,7 @@ void InventorBuilder::addColor(const ColorRGB& rgb)
result << rgb.red() << " " << rgb.green() << " " << rgb.blue() << '\n';
}
void InventorBuilder::addMaterialBinding(MaterialBinding bind)
void InventorBuilder::addMaterialBinding(BindingElement bind)
{
result << indent << "MaterialBinding { value "
<< bind.bindingAsString() << " } \n";

View File

@@ -84,7 +84,7 @@ public:
unsigned short linePattern = 0xffff;
};
class BaseExport MaterialBinding
class BaseExport BindingElement
{
public:
enum class Binding {
@@ -192,6 +192,7 @@ public:
virtual void write(InventorOutput& out) const = 0;
protected:
void writeField(const char* field, const std::vector<Vector3f>& vec, InventorOutput& out) const;
void writeField(const char* field, const std::vector<ColorRGB>& rgb, InventorOutput& out) const;
void writeField(const char* field, const std::vector<float>& value, InventorOutput& out) const;
};
@@ -259,6 +260,18 @@ private:
ColorRGB rgb;
};
class BaseExport ArrowItem : public NodeItem
{
public:
explicit ArrowItem(const Base::Line3f& line, DrawStyle drawStyle, const ColorRGB& rgb = ColorRGB{1.0F, 1.0F, 1.0F});
void write(InventorOutput& out) const override;
private:
Base::Line3f line;
DrawStyle drawStyle;
ColorRGB rgb;
};
/*!
* \brief The MaterialItem class supports the SoMaterial node.
*/
@@ -298,11 +311,12 @@ private:
class BaseExport MaterialBindingItem : public NodeItem
{
public:
explicit MaterialBindingItem(MaterialBinding bind);
MaterialBindingItem() = default;
void setValue(BindingElement::Binding bind);
void write(InventorOutput& out) const override;
private:
MaterialBinding bind;
BindingElement value;
};
/*!
@@ -353,6 +367,79 @@ public:
void write(InventorOutput& out) const override;
};
/*!
* \brief The NormalItem class supports the SoNormal node.
*/
class BaseExport NormalItem : public NodeItem
{
public:
explicit NormalItem() = default;
void setVector(const std::vector<Base::Vector3f>& vec);
void write(InventorOutput& out) const override;
private:
void beginNormal(InventorOutput& out) const;
void endNormal(InventorOutput& out) const;
std::vector<Base::Vector3f> vector;
};
/*!
* \brief The MaterialBindingItem class supports the SoMaterialBinding node.
*/
class BaseExport NormalBindingItem : public NodeItem
{
public:
NormalBindingItem() = default;
void setValue(BindingElement::Binding bind);
void write(InventorOutput& out) const override;
private:
BindingElement value;
};
/*!
* \brief The CylinderItem class supports the SoCylinder node.
*/
class BaseExport CylinderItem : public NodeItem
{
public:
void setRadius(float);
void setHeight(float);
void write(InventorOutput& out) const override;
private:
float radius = 2.0F;
float height = 10.0F;
};
/*!
* \brief The ConeItem class supports the SoCone node.
*/
class BaseExport ConeItem : public NodeItem
{
public:
void setBottomRadius(float);
void setHeight(float);
void write(InventorOutput& out) const override;
private:
float bottomRadius = 2.0F;
float height = 10.0F;
};
/*!
* \brief The SphereItem class supports the SoSphere node.
*/
class BaseExport SphereItem : public NodeItem
{
public:
void setRadius(float);
void write(InventorOutput& out) const override;
private:
float radius = 2.0F;
};
/**
* This class does basically the same as Builder3D except that it writes the data
* directly into a given stream without buffering the output data in a string stream.
@@ -423,7 +510,7 @@ public:
* \brief Sets a material binding node.
* \param binding - binding of the material.
*/
void addMaterialBinding(MaterialBinding);
void addMaterialBinding(BindingElement);
/*!
* \brief Sets a draw style node.
*/

View File

@@ -73,7 +73,7 @@ private Q_SLOTS:
{
QFETCH(QString, result);
Base::MaterialBindingItem item{Base::MaterialBinding{}};
Base::MaterialBindingItem item;
builder.addNode(item);
QString string = QString::fromStdString(output.str());
@@ -292,6 +292,29 @@ R"(PolygonOffset {
QCOMPARE(string, result);
}
void test_Normal_data()
{
auto result =
R"(Normal {
vector 1 0 0.5
}
)";
QTest::addColumn<QString>("result");
QTest::newRow("Normal") << result;
}
void test_Normal()
{
QFETCH(QString, result);
Base::NormalItem item;
item.setVector({Base::Vector3f{1,0,0.5}});
builder.addNode(item);
QString string = QString::fromStdString(output.str());
QCOMPARE(string, result);
}
void test_LineItem()
{
Base::Line3f line;
@@ -303,6 +326,19 @@ R"(PolygonOffset {
QVERIFY(node != nullptr);
}
void test_ArrowItem()
{
Base::Line3f line;
line.p2.z = 10;
Base::DrawStyle style;
Base::ArrowItem item{line, style};
builder.addNode(item);
qDebug() << QString::fromStdString(output.str());
SoNode* node = loadBuffer(output.str());
QVERIFY(node != nullptr);
}
void test_PointItem()
{
Base::Vector3f pnt;
@@ -314,6 +350,90 @@ R"(PolygonOffset {
QVERIFY(node != nullptr);
}
void test_NormalBinding_data()
{
auto result = "NormalBinding { value PER_PART }\n";
QTest::addColumn<QString>("result");
QTest::newRow("NormalBinding") << result;
}
void test_NormalBinding()
{
QFETCH(QString, result);
Base::NormalBindingItem item;
item.setValue(Base::BindingElement::Binding::PerPart);
builder.addNode(item);
QString string = QString::fromStdString(output.str());
QCOMPARE(string, result);
}
void test_Cylinder_data()
{
auto result =
R"(Cylinder {
radius 3
height 7
parts (SIDES | TOP | BOTTOM)
}
)";
QTest::addColumn<QString>("result");
QTest::newRow("Cylinder") << result;
}
void test_Cylinder()
{
QFETCH(QString, result);
Base::CylinderItem item;
item.setRadius(3);
item.setHeight(7);
builder.addNode(item);
QString string = QString::fromStdString(output.str());
QCOMPARE(string, result);
}
void test_Cone_data()
{
auto result = "Cone { bottomRadius 2 height 10 }\n";
QTest::addColumn<QString>("result");
QTest::newRow("Cone") << result;
}
void test_Cone()
{
QFETCH(QString, result);
Base::ConeItem item;
item.setBottomRadius(2);
item.setHeight(10);
builder.addNode(item);
QString string = QString::fromStdString(output.str());
QCOMPARE(string, result);
}
void test_Sphere_data()
{
auto result = "Sphere { radius 4 }\n";
QTest::addColumn<QString>("result");
QTest::newRow("Sphere") << result;
}
void test_Sphere()
{
QFETCH(QString, result);
Base::SphereItem item;
item.setRadius(4);
builder.addNode(item);
QString string = QString::fromStdString(output.str());
QCOMPARE(string, result);
}
private:
std::stringstream output;
Base::InventorBuilder builder;