Skip to content

Commit

Permalink
🦄 refactor: Refactored the import of step
Browse files Browse the repository at this point in the history
  • Loading branch information
xiangechen committed Dec 31, 2024
1 parent 6fd9383 commit 2401cf8
Show file tree
Hide file tree
Showing 15 changed files with 270 additions and 134 deletions.
165 changes: 129 additions & 36 deletions cpp/src/converter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <TDF_Label.hxx>
#include <TDocStd_Document.hxx>
#include <TopoDS_Shape.hxx>
#include <TopoDS_Iterator.hxx>
#include <XCAFDoc_ColorTool.hxx>
#include <XCAFDoc_DocumentTool.hxx>
#include <XCAFDoc_ShapeTool.hxx>
Expand All @@ -33,7 +34,7 @@ EMSCRIPTEN_DECLARE_VAL_TYPE(ShapeNodeArray)
struct ShapeNode
{
std::optional<TopoDS_Shape> shape;
std::string color;
std::optional<std::string> color;
std::vector<ShapeNode> children;
std::string name;

Expand All @@ -43,7 +44,7 @@ struct ShapeNode
}
};

static std::string getLabelNameNoRef(const TDF_Label &label)
std::string getLabelNameNoRef(const TDF_Label &label)
{
Handle(TDataStd_Name) nameAttribute = new TDataStd_Name();
if (!label.FindAttribute(nameAttribute->GetID(), nameAttribute))
Expand All @@ -59,7 +60,7 @@ static std::string getLabelNameNoRef(const TDF_Label &label)
return name;
}

static std::string getLabelName(const TDF_Label &label, const Handle(XCAFDoc_ShapeTool) & shapeTool)
std::string getLabelName(const TDF_Label &label, const Handle(XCAFDoc_ShapeTool) & shapeTool)
{
if (XCAFDoc_ShapeTool::IsReference(label))
{
Expand All @@ -70,7 +71,7 @@ static std::string getLabelName(const TDF_Label &label, const Handle(XCAFDoc_Sha
return getLabelNameNoRef(label);
}

static std::string getShapeName(const TopoDS_Shape &shape, const Handle(XCAFDoc_ShapeTool) & shapeTool)
std::string getShapeName(const TopoDS_Shape &shape, const Handle(XCAFDoc_ShapeTool) & shapeTool)
{
TDF_Label shapeLabel;
if (!shapeTool->Search(shape, shapeLabel))
Expand All @@ -80,7 +81,7 @@ static std::string getShapeName(const TopoDS_Shape &shape, const Handle(XCAFDoc_
return getLabelName(shapeLabel, shapeTool);
}

static bool getLabelColorNoRef(const TDF_Label &label, const Handle(XCAFDoc_ColorTool) & colorTool, std::string &color)
bool getLabelColorNoRef(const TDF_Label &label, const Handle(XCAFDoc_ColorTool) & colorTool, std::string &color)
{
static const std::vector<XCAFDoc_ColorType> colorTypes = {
XCAFDoc_ColorSurf,
Expand All @@ -100,7 +101,7 @@ static bool getLabelColorNoRef(const TDF_Label &label, const Handle(XCAFDoc_Colo
return false;
}

static bool getLabelColor(const TDF_Label &label, const Handle(XCAFDoc_ShapeTool) & shapeTool, const Handle(XCAFDoc_ColorTool) & colorTool, std::string &color)
bool getLabelColor(const TDF_Label &label, const Handle(XCAFDoc_ShapeTool) & shapeTool, const Handle(XCAFDoc_ColorTool) & colorTool, std::string &color)
{
if (getLabelColorNoRef(label, colorTool, color))
{
Expand All @@ -117,7 +118,7 @@ static bool getLabelColor(const TDF_Label &label, const Handle(XCAFDoc_ShapeTool
return false;
}

static bool getShapeColor(const TopoDS_Shape &shape, const Handle(XCAFDoc_ShapeTool) & shapeTool, const Handle(XCAFDoc_ColorTool) & colorTool, std::string &color)
bool getShapeColor(const TopoDS_Shape &shape, const Handle(XCAFDoc_ShapeTool) & shapeTool, const Handle(XCAFDoc_ColorTool) & colorTool, std::string &color)
{
TDF_Label shapeLabel;
if (!shapeTool->Search(shape, shapeLabel))
Expand All @@ -127,7 +128,42 @@ static bool getShapeColor(const TopoDS_Shape &shape, const Handle(XCAFDoc_ShapeT
return getLabelColor(shapeLabel, shapeTool, colorTool, color);
}

static ShapeNode initNode(const TDF_Label label, const Handle(XCAFDoc_ShapeTool) shapeTool, const Handle(XCAFDoc_ColorTool) colorTool)
bool isFreeShape(const TDF_Label &label, const Handle(XCAFDoc_ShapeTool) & shapeTool)
{
TopoDS_Shape tmpShape;
return shapeTool->GetShape(label, tmpShape) && shapeTool->IsFree(label);
}

bool isMeshNode(const TDF_Label &label, const Handle(XCAFDoc_ShapeTool) & shapeTool)
{
// if there are no children, it is a mesh node
if (!label.HasChild())
{
return true;
}

// if it has a subshape child, treat it as mesh node
for (TDF_ChildIterator it(label); it.More(); it.Next())
{
if (shapeTool->IsSubShape(it.Value()))
{
return true;
}
}

// if it doesn't have a freeshape child, treat it as a mesh node
for (TDF_ChildIterator it(label); it.More(); it.Next())
{
if (isFreeShape(it.Value(), shapeTool))
{
return false;
}
}

return false;
}

ShapeNode initLabelNode(const TDF_Label label, const Handle(XCAFDoc_ShapeTool) shapeTool, const Handle(XCAFDoc_ColorTool) colorTool)
{
std::string color;
getLabelColor(label, shapeTool, colorTool, color);
Expand All @@ -142,39 +178,100 @@ static ShapeNode initNode(const TDF_Label label, const Handle(XCAFDoc_ShapeTool)
return node;
}

static void addChildNodes(ShapeNode &parent, const TDF_Label &parentLabel, const Handle(XCAFDoc_ShapeTool) & shapeTool, const Handle(XCAFDoc_ColorTool) & colorTool)
ShapeNode initShapeNode(
const TopoDS_Shape &shape,
const Handle(XCAFDoc_ShapeTool) & shapeTool,
const Handle(XCAFDoc_ColorTool) & colorTool)
{
std::string color;
getShapeColor(shape, shapeTool, colorTool, color);
ShapeNode childShapeNode = {
.shape = shape,
.color = color,
.children = {},
.name = getShapeName(shape, shapeTool)};
return childShapeNode;
}

ShapeNode initGroupNode(const TopoDS_Shape &shape, const Handle_XCAFDoc_ShapeTool &shapeTool)
{
ShapeNode groupNode = {
.shape = std::nullopt,
.color = std::nullopt,
.children = {},
.name = getShapeName(shape, shapeTool)};

return groupNode;
}

ShapeNode parseShape(TopoDS_Shape &shape, const Handle_XCAFDoc_ShapeTool &shapeTool, const Handle_XCAFDoc_ColorTool &colorTool)
{
for (TDF_ChildIterator it(parentLabel); it.More(); it.Next())
if (shape.ShapeType() == TopAbs_COMPOUND || shape.ShapeType() == TopAbs_COMPSOLID)
{
TDF_Label childLabel = it.Value();
TopoDS_Shape tmpShape;
if (shapeTool->GetShape(childLabel, tmpShape) && shapeTool->IsFree(childLabel))
auto node = initGroupNode(shape, shapeTool);
TopoDS_Iterator iterator(shape);
while (iterator.More())
{
ShapeNode childNode = initNode(childLabel, shapeTool, colorTool);
childNode.shape = tmpShape;
parent.children.push_back(childNode);
auto subShape = iterator.Value();
node.children.push_back(parseShape(subShape, shapeTool, colorTool));
iterator.Next();
}
return node;
}
return initShapeNode(shape, shapeTool, colorTool);
}

addChildNodes(childNode, childLabel, shapeTool, colorTool);
ShapeNode parseLabelToNode(
const TDF_Label &label,
const Handle(XCAFDoc_ShapeTool) & shapeTool,
const Handle(XCAFDoc_ColorTool) & colorTool)
{
if (isMeshNode(label, shapeTool))
{
auto shape = shapeTool->GetShape(label);
return parseShape(shape, shapeTool, colorTool);
}

auto node = initLabelNode(label, shapeTool, colorTool);
for (TDF_ChildIterator it(label); it.More(); it.Next())
{
auto childLabel = it.Value();
if (isFreeShape(childLabel, shapeTool))
{
auto childNode = parseLabelToNode(childLabel, shapeTool, colorTool);
node.children.push_back(childNode);
}
}
return node;
}

static ShapeNode getNodesFromDocument(Handle(TDocStd_Document) document)
ShapeNode parseRootLabelToNode(
const Handle(XCAFDoc_ShapeTool) & shapeTool,
const Handle(XCAFDoc_ColorTool) & colorTool)
{
TDF_Label mainLabel = document->Main();
Handle(XCAFDoc_ShapeTool) shapeTool = XCAFDoc_DocumentTool::ShapeTool(mainLabel);
Handle(XCAFDoc_ColorTool) colorTool = XCAFDoc_DocumentTool::ColorTool(mainLabel);
auto label = shapeTool->Label();

TDF_Label shapeLabel = shapeTool->Label();
ShapeNode rootNode = initNode(shapeLabel, shapeTool, colorTool);
TopoDS_Shape tmpShape;
if (shapeTool->GetShape(shapeLabel, tmpShape) && shapeTool->IsFree(shapeLabel))
ShapeNode node = initLabelNode(label, shapeTool, colorTool);
for (TDF_ChildIterator it(label); it.More(); it.Next())
{
rootNode.shape = tmpShape;
auto childLabel = it.Value();
if (isFreeShape(childLabel, shapeTool))
{
auto childNode = parseLabelToNode(childLabel, shapeTool, colorTool);
node.children.push_back(childNode);
}
}
addChildNodes(rootNode, shapeLabel, shapeTool, colorTool);

return rootNode;
return node;
}

static ShapeNode parseNodeFromDocument(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);

return parseRootLabelToNode(shapeTool, colorTool);
}

class Converter
Expand Down Expand Up @@ -218,7 +315,7 @@ class Converter
return std::nullopt;
}

return getNodesFromDocument(document);
return parseNodeFromDocument(document);
}

static std::optional<ShapeNode> convertFromIges(const Uint8Array &buffer)
Expand Down Expand Up @@ -246,7 +343,7 @@ class Converter
return std::nullopt;
}

return getNodesFromDocument(document);
return parseNodeFromDocument(document);
}

static std::string convertToStep(const ShapeArray &input)
Expand Down Expand Up @@ -275,7 +372,6 @@ class Converter
igesWriter.Write(oss);
return oss.str();
}

};

EMSCRIPTEN_BINDINGS(Converter)
Expand All @@ -288,16 +384,13 @@ EMSCRIPTEN_BINDINGS(Converter)
.property("shape", &ShapeNode::shape)
.property("color", &ShapeNode::color)
.property("name", &ShapeNode::name)
.function("getChildren", &ShapeNode::getChildren)
;
.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)

;
.class_function("convertToIges", &Converter::convertToIges);
}
1 change: 1 addition & 0 deletions cpp/src/shared.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ EMSCRIPTEN_BINDINGS(Shared) {
register_optional<double>();
register_optional<UV>();
register_optional<PointAndParameter>();
register_optional<std::string>();

value_object<Domain>("Domain")
.field("start", &Domain::start)
Expand Down
15 changes: 5 additions & 10 deletions packages/chili-core/src/dataExchange.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import { IDocument } from "./document";
import { PubSub } from "./foundation";
import { EditableShapeNode, FolderNode, ShapeNode, VisualNode } from "./model";
import { ShapeNode, VisualNode } from "./model";

export interface IDataExchange {
importFormats(): string[];
Expand All @@ -23,21 +23,16 @@ export class DefaultDataExchange implements IDataExchange {
async import(document: IDocument, files: FileList | File[]): Promise<void> {
for (const file of files) {
let content = new Uint8Array(await file.arrayBuffer());
let factory = document.application.shapeFactory.converter.convertFromIGES;
let shape = document.application.shapeFactory.converter.convertFromIGES(document, content);
if (file.name.endsWith(".step") || file.name.endsWith(".stp")) {
factory = document.application.shapeFactory.converter.convertFromSTEP;
shape = document.application.shapeFactory.converter.convertFromSTEP(document, content);
}
let shape = factory(content);
if (!shape.isOk) {
PubSub.default.pub("showToast", "toast.read.error");
return;
}
let shapes = shape.value.map((x, i) => {
return new EditableShapeNode(document, x.name, x.shape);
});
let nodeList = new FolderNode(document, file.name);
document.addNode(nodeList);
nodeList.add(...shapes);
shape.value.name = file.name;
document.addNode(shape.value);
document.visual.update();
}
}
Expand Down
12 changes: 4 additions & 8 deletions packages/chili-core/src/shape/shapeConverter.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,15 @@
// Copyright 2022-2023 the Chili authors. All rights reserved. AGPL-3.0 license.

import { IDocument } from "../document";
import { Result } from "../foundation";
import { FolderNode } from "../model";
import { IShape } from "./shape";

export type ShapeInfo = {
name: string;
shape: IShape;
color: string;
};

export interface IShapeConverter {
convertToIGES(...shapes: IShape[]): Result<string>;
convertFromIGES(iges: Uint8Array): Result<ShapeInfo[]>;
convertFromIGES(document: IDocument, iges: Uint8Array): Result<FolderNode>;
convertToSTEP(...shapes: IShape[]): Result<string>;
convertFromSTEP(step: Uint8Array): Result<ShapeInfo[]>;
convertFromSTEP(document: IDocument, step: Uint8Array): Result<FolderNode>;
convertToBrep(shape: IShape): Result<string>;
convertFromBrep(brep: string): Result<IShape>;
}
3 changes: 3 additions & 0 deletions packages/chili-ui/src/converters/colorConverter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ import { IConverter, Result } from "chili-core";

export class ColorConverter implements IConverter<number> {
convert(value: number): Result<string> {
if (typeof value === "string") {
return Result.ok(value);
}
return Result.ok("#" + value.toString(16).padStart(6, "0"));
}

Expand Down
Loading

0 comments on commit 2401cf8

Please sign in to comment.