Skip to content

Commit

Permalink
🦄 refactor: Completed the replacement of the OCC module
Browse files Browse the repository at this point in the history
  • Loading branch information
xiangechen committed Oct 9, 2024
1 parent eebf9b9 commit 845b95b
Show file tree
Hide file tree
Showing 15 changed files with 576 additions and 125 deletions.
6 changes: 6 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@
"windows": {
"program": "${workspaceFolder}/node_modules/jest/bin/jest"
}
},
{
"name": "debug",
"type": "msedge",
"request": "launch",
"url": "http://localhost:8080/"
}
]
}
296 changes: 290 additions & 6 deletions cpp/src/converter.cpp
Original file line number Diff line number Diff line change
@@ -1,33 +1,317 @@
#include <TopoDS_Shape.hxx>
#include "shared.hpp"
#include <BRep_Builder.hxx>
#include <BRepTools.hxx>
#include <emscripten/bind.h>
#include <emscripten/val.h>
#include <BRepTools.hxx>
#include <BRep_Builder.hxx>
#include <IGESCAFControl_Reader.hxx>
#include <Quantity_Color.hxx>
#include <STEPCAFControl_Reader.hxx>
#include <TDataStd_Name.hxx>
#include <TDF_ChildIterator.hxx>
#include <TDF_Label.hxx>
#include <TDocStd_Document.hxx>
#include <TopoDS_Shape.hxx>
#include <XCAFDoc_ColorTool.hxx>
#include <XCAFDoc_DocumentTool.hxx>
#include <XCAFDoc_ShapeTool.hxx>
#include <STEPControl_Writer.hxx>
#include <IGESControl_Writer.hxx>

using namespace emscripten;

class Converter {
class VectorBuffer : public std::streambuf
{
public:
VectorBuffer(const std::vector<uint8_t> &v)
{
setg((char *)v.data(), (char *)v.data(), (char *)(v.data() + v.size()));
}
};

struct Color
{
double r;
double g;
double b;
double a;
};

EMSCRIPTEN_DECLARE_VAL_TYPE(ShapeNodeArray)

struct ShapeNode
{
std::optional<TopoDS_Shape> shape;
Color color;
std::vector<ShapeNode> children;
std::string name;

ShapeNodeArray getChildren() const
{
return ShapeNodeArray(val::array(children));
}
};

static std::string getLabelNameNoRef(const TDF_Label &label)
{
Handle(TDataStd_Name) nameAttribute = new TDataStd_Name();
if (!label.FindAttribute(nameAttribute->GetID(), nameAttribute))
{
return std::string();
}

Standard_Integer utf8NameLength = nameAttribute->Get().LengthOfCString();
char *nameBuf = new char[utf8NameLength + 1];
nameAttribute->Get().ToUTF8CString(nameBuf);
std::string name(nameBuf, utf8NameLength);
delete[] nameBuf;
return name;
}

static std::string getLabelName(const TDF_Label &label, const Handle(XCAFDoc_ShapeTool) & shapeTool)
{
if (XCAFDoc_ShapeTool::IsReference(label))
{
TDF_Label referredShapeLabel;
shapeTool->GetReferredShape(label, referredShapeLabel);
return getLabelName(referredShapeLabel, shapeTool);
}
return getLabelNameNoRef(label);
}

static std::string getShapeName(const TopoDS_Shape &shape, const Handle(XCAFDoc_ShapeTool) & shapeTool)
{
TDF_Label shapeLabel;
if (!shapeTool->Search(shape, shapeLabel))
{
return std::string();
}
return getLabelName(shapeLabel, shapeTool);
}

static bool getLabelColorNoRef(const TDF_Label &label, const Handle(XCAFDoc_ColorTool) & colorTool, Color &color)
{
static const std::vector<XCAFDoc_ColorType> colorTypes = {
XCAFDoc_ColorSurf,
XCAFDoc_ColorCurv,
XCAFDoc_ColorGen};

Quantity_Color qColor;
for (XCAFDoc_ColorType colorType : colorTypes)
{
if (colorTool->GetColor(label, colorType, qColor))
{
color = {qColor.Red(), qColor.Green(), qColor.Blue(), 1.0};
return true;
}
}

return false;
}

static bool getLabelColor(const TDF_Label &label, const Handle(XCAFDoc_ShapeTool) & shapeTool, const Handle(XCAFDoc_ColorTool) & colorTool, Color &color)
{
if (getLabelColorNoRef(label, colorTool, color))
{
return true;
}

if (XCAFDoc_ShapeTool::IsReference(label))
{
TDF_Label referredShape;
shapeTool->GetReferredShape(label, referredShape);
return getLabelColor(referredShape, shapeTool, colorTool, color);
}

return false;
}

static bool getShapeColor(const TopoDS_Shape &shape, const Handle(XCAFDoc_ShapeTool) & shapeTool, const Handle(XCAFDoc_ColorTool) & colorTool, Color &color)
{
TDF_Label shapeLabel;
if (!shapeTool->Search(shape, shapeLabel))
{
return false;
}
return getLabelColor(shapeLabel, shapeTool, colorTool, color);
}

static ShapeNode initNode(const TDF_Label label, const Handle(XCAFDoc_ShapeTool) shapeTool, const Handle(XCAFDoc_ColorTool) colorTool)
{
Color color;
getLabelColor(label, shapeTool, colorTool, color);

ShapeNode node = {
.shape = std::nullopt,
.color = color,
.children = {},
.name = getLabelName(label, shapeTool),
};

return node;
}

static void addChildNodes(ShapeNode &parent, const TDF_Label &parentLabel, const Handle(XCAFDoc_ShapeTool) & shapeTool, const Handle(XCAFDoc_ColorTool) & colorTool)
{
for (TDF_ChildIterator it(parentLabel); it.More(); it.Next())
{
TDF_Label childLabel = it.Value();
TopoDS_Shape tmpShape;
if (shapeTool->GetShape(childLabel, tmpShape) && shapeTool->IsFree(childLabel))
{
ShapeNode childNode = initNode(childLabel, shapeTool, colorTool);
childNode.shape = tmpShape;
parent.children.push_back(childNode);

addChildNodes(childNode, childLabel, shapeTool, colorTool);
}
}
}

static ShapeNode getNodesFromDocument(Handle(TDocStd_Document) document)
{
TDF_Label mainLabel = document->Main();
Handle(XCAFDoc_ShapeTool) shapeTool = XCAFDoc_DocumentTool::ShapeTool(mainLabel);
Handle(XCAFDoc_ColorTool) colorTool = XCAFDoc_DocumentTool::ColorTool(mainLabel);

TDF_Label shapeLabel = shapeTool->Label();
ShapeNode rootNode = initNode(shapeLabel, shapeTool, colorTool);
TopoDS_Shape tmpShape;
if (shapeTool->GetShape(shapeLabel, tmpShape) && shapeTool->IsFree(shapeLabel))
{
rootNode.shape = tmpShape;
}
addChildNodes(rootNode, shapeLabel, shapeTool, colorTool);

return rootNode;
}

class Converter
{
public:
static std::string convertToBrep(const TopoDS_Shape& input) {
static std::string convertToBrep(const TopoDS_Shape &input)
{
std::ostringstream oss;
BRepTools::Write(input, oss);
return oss.str();
}

static TopoDS_Shape convertFromBrep(const std::string& input) {
static TopoDS_Shape convertFromBrep(const std::string &input)
{
std::istringstream iss(input);
TopoDS_Shape output;
BRep_Builder builder;
BRepTools::Read(output, iss, builder);
return output;
}

static std::optional<ShapeNode> convertFromStep(const Uint8Array &buffer)
{
std::vector<uint8_t> input = convertJSArrayToNumberVector<uint8_t>(buffer);
VectorBuffer vectorBuffer(input);
std::istream iss(&vectorBuffer);

STEPCAFControl_Reader cafReader;
cafReader.SetColorMode(true);
cafReader.SetNameMode(true);
IFSelect_ReturnStatus readStatus = cafReader.ReadStream("stp", iss);

if (readStatus != IFSelect_RetDone)
{
return std::nullopt;
}

Handle(TDocStd_Document) document = new TDocStd_Document("bincaf");
if (!cafReader.Transfer(document))
{
return std::nullopt;
}

return getNodesFromDocument(document);
}

static std::optional<ShapeNode> convertFromIges(const Uint8Array &buffer)
{
std::vector<uint8_t> input = convertJSArrayToNumberVector<uint8_t>(buffer);
std::string dummyFileName = "temp.igs";
std::ofstream dummyFile;
dummyFile.open(dummyFileName, std::ios::binary);
dummyFile.write((char *)input.data(), input.size());
dummyFile.close();

IGESCAFControl_Reader igesCafReader;
igesCafReader.SetColorMode(true);
igesCafReader.SetNameMode(true);
IFSelect_ReturnStatus readStatus = igesCafReader.ReadFile(dummyFileName.c_str());

if (readStatus != IFSelect_RetDone)
{
return std::nullopt;
}

Handle(TDocStd_Document) document = new TDocStd_Document("bincaf");
if (!igesCafReader.Transfer(document))
{
return std::nullopt;
}

return getNodesFromDocument(document);
}

static std::string convertToStep(const ShapeArray &input)
{
auto shapes = vecFromJSArray<TopoDS_Shape>(input);
std::ostringstream oss;
STEPControl_Writer stepWriter;
for (const auto &shape : shapes)
{
stepWriter.Transfer(shape, STEPControl_AsIs);
}
stepWriter.WriteStream(oss);
return oss.str();
}

static std::string convertToIges(const ShapeArray &input)
{
auto shapes = vecFromJSArray<TopoDS_Shape>(input);
std::ostringstream oss;
IGESControl_Writer igesWriter;
for (const auto &shape : shapes)
{
igesWriter.AddShape(shape);
}
igesWriter.ComputeModel();
igesWriter.Write(oss);
return oss.str();
}

};

EMSCRIPTEN_BINDINGS(Converter)
{
register_optional<ShapeNode>();

register_type<ShapeNodeArray>("Array<ShapeNode>");

value_object<Color>("Color")
.field("r", &Color::r)
.field("g", &Color::g)
.field("b", &Color::b)
.field("a", &Color::a);

class_<ShapeNode>("ShapeNode")
.property("shape", &ShapeNode::shape)
.property("color", &ShapeNode::color)
.property("name", &ShapeNode::name)
.function("getChildren", &ShapeNode::getChildren)
;

class_<Converter>("Converter")
.class_function("convertToBrep", &Converter::convertToBrep)
.class_function("convertFromBrep", &Converter::convertFromBrep)
.class_function("convertFromStep", &Converter::convertFromStep)
.class_function("convertFromIges", &Converter::convertFromIges)
.class_function("convertToStep", &Converter::convertToStep)
.class_function("convertToIges", &Converter::convertToIges)

;
}
Loading

0 comments on commit 845b95b

Please sign in to comment.